From 3697e3ac630994c480e3265e456ee17b4107d843 Mon Sep 17 00:00:00 2001 From: Matthias Wittgen <matthias.michael.wittgen@cern.ch> Date: Wed, 22 Mar 2017 19:49:49 +0100 Subject: [PATCH] Revert "start cleanup - drop gen1 support" This reverts commit fe71c382b43d2d6aed3e0b160e8584f8ffcd8e5e --- rce/Makefile | 9 + rce/Makefile.inc | 64 + rce/Makefile_nonparallel | 40 + rce/fw-hsio/.gitignore | 1 + rce/fw-hsio/Readme.txt | 23 + .../modules/pgp/coregen/pgp_adder_16_16.xco | 66 + .../modules/pgp/coregen/pgp_afifo_20x511.xco | 77 + .../modules/pgp/coregen/pgp_dpram_51x256.xco | 75 + .../modules/pgp/coregen/pgp_fifo_20x512.xco | 77 + .../modules/pgp/coregen/pgp_fifo_21x512.xco | 77 + .../modules/pgp/coregen/pgp_fifo_8x256.xco | 77 + .../modules/pgp/coregen/pgp_fifo_9x256.xco | 77 + rce/fw-hsio/modules/pgp/hdl/PgpAckRx.vhd | 759 + rce/fw-hsio/modules/pgp/hdl/PgpCellRx.vhd | 719 + rce/fw-hsio/modules/pgp/hdl/PgpCellTx.vhd | 702 + rce/fw-hsio/modules/pgp/hdl/PgpClkGen.vhd | 367 + rce/fw-hsio/modules/pgp/hdl/PgpCmdSlave.vhd | 295 + rce/fw-hsio/modules/pgp/hdl/PgpDataBuffer.vhd | 256 + rce/fw-hsio/modules/pgp/hdl/PgpDsBuff.vhd | 150 + rce/fw-hsio/modules/pgp/hdl/PgpFrontEnd.vhd | 890 + rce/fw-hsio/modules/pgp/hdl/PgpMgtWrap.vhd | 1590 ++ rce/fw-hsio/modules/pgp/hdl/PgpPhy.vhd | 835 + rce/fw-hsio/modules/pgp/hdl/PgpPicRemBuff.vhd | 252 + rce/fw-hsio/modules/pgp/hdl/PgpRegSlave.vhd | 803 + rce/fw-hsio/modules/pgp/hdl/PgpRxTrack.vhd | 339 + rce/fw-hsio/modules/pgp/hdl/PgpTop.vhd | 714 + rce/fw-hsio/modules/pgp/hdl/PgpTxSched.vhd | 267 + rce/fw-hsio/modules/pgp/hdl/PgpVersion.vhd | 44 + .../pgp2/coregen/pgp2_v4_afifo_18x1023.xco | 84 + .../pgp2/coregen/pgp2_v4_fifo_69x512.xco | 84 + .../modules/pgp2/coregen/pgp2_v4_icon.xco | 47 + .../modules/pgp2/coregen/pgp2_v4_ila.xco | 130 + .../modules/pgp2/coregen/pgp2_v4_vio.xco | 50 + .../pgp2/coregen/pgp2_v5_afifo_18x1023.xco | 84 + .../pgp2/hdl/applications/Pgp2AppPackage.vhd | 141 + .../pgp2/hdl/applications/Pgp2CmdSlave.vhd | 290 + .../pgp2/hdl/applications/Pgp2DsBuff.vhd | 195 + .../pgp2/hdl/applications/Pgp2RegSlave.vhd | 1104 ++ .../pgp2/hdl/applications/Pgp2UsBuff.vhd | 194 + .../pgp2/hdl/applications/PgpDsBuff.vhd | 150 + .../pgp2/hdl/applications/PgpFrontEnd.vhd | 630 + .../modules/pgp2/hdl/core/Pgp2CorePackage.vhd | 341 + rce/fw-hsio/modules/pgp2/hdl/core/Pgp2Rx.vhd | 201 + .../modules/pgp2/hdl/core/Pgp2RxCell.vhd | 744 + .../modules/pgp2/hdl/core/Pgp2RxPhy.vhd | 715 + rce/fw-hsio/modules/pgp2/hdl/core/Pgp2Tx.vhd | 241 + .../modules/pgp2/hdl/core/Pgp2TxCell.vhd | 655 + .../modules/pgp2/hdl/core/Pgp2TxPhy.vhd | 413 + .../modules/pgp2/hdl/core/Pgp2TxSched.vhd | 257 + .../modules/pgp2/hdl/gtp/Pgp2Gtp16.vhd | 861 + .../modules/pgp2/hdl/gtp/Pgp2Gtp32.vhd | 899 + .../modules/pgp2/hdl/gtp/Pgp2GtpClk.vhd | 226 + .../modules/pgp2/hdl/gtp/Pgp2GtpDual.vhd | 1200 ++ .../modules/pgp2/hdl/gtp/Pgp2GtpPackage.vhd | 399 + .../modules/pgp2/hdl/gtp/Pgp2GtpRxRst.vhd | 205 + .../modules/pgp2/hdl/gtp/Pgp2GtpTxRst.vhd | 179 + .../modules/pgp2/hdl/gtx/Pgp2Gtx16.vhd | 954 + .../modules/pgp2/hdl/gtx/Pgp2Gtx16B.vhd | 953 + .../modules/pgp2/hdl/gtx/Pgp2GtxClk.vhd | 213 + .../modules/pgp2/hdl/gtx/Pgp2GtxDual.vhd | 1294 ++ .../modules/pgp2/hdl/gtx/Pgp2GtxPackage.vhd | 391 + .../modules/pgp2/hdl/gtx/Pgp2GtxRxRst.vhd | 198 + .../modules/pgp2/hdl/gtx/Pgp2GtxTxRst.vhd | 179 + .../modules/pgp2/hdl/mgt/Pgp2Mgt16.vhd | 782 + .../modules/pgp2/hdl/mgt/Pgp2Mgt32.vhd | 1227 ++ .../modules/pgp2/hdl/mgt/Pgp2Mgt64.vhd | 2114 ++ .../modules/pgp2/hdl/mgt/Pgp2MgtClk.vhd | 207 + .../modules/pgp2/hdl/mgt/Pgp2MgtPackage.vhd | 333 + .../modules/pgp2/hdl/mgt/Pgp2MgtRxRst.vhd | 291 + .../modules/pgp2/hdl/mgt/Pgp2MgtTxRst.vhd | 283 + .../modules/pgp2/hdl/mgt/PgpClkGen.vhd | 298 + rce/fw-hsio/modules/pgp2/hdl/rce/Pgp2Rce.vhd | 682 + .../modules/pgp2/hdl/rce/Pgp2RceExport.vhd | 583 + .../modules/pgp2/hdl/rce/Pgp2RceImport.vhd | 457 + .../modules/pgp2/hdl/rce/Pgp2RceLane.vhd | 462 + .../modules/pgp2/hdl/rce/Pgp2RcePackage.vhd | 196 + .../pixelcore/coregen/data24bitfifo4096.xco | 213 + .../pixelcore/coregen/data24bitfifo8192.xco | 213 + .../pixelcore/coregen/datafifo1024.xco | 203 + .../pixelcore/coregen/datafifo131072.xco | 219 + .../pixelcore/coregen/datafifo16384.xco | 219 + .../pixelcore/coregen/datafifo32768.xco | 203 + .../pixelcore/coregen/datafifo4096.xco | 219 + .../pixelcore/coregen/datafifo8192.xco | 203 + .../pixelcore/coregen/dataflagfifo.xco | 217 + .../modules/pixelcore/coregen/eofcounter.xco | 64 + .../pixelcore/coregen/pattern_blk_mem.ngc | 3 + .../pixelcore/coregen/pattern_blk_mem.vhd | 145 + .../pixelcore/coregen/pattern_blk_mem.vho | 74 + .../coregen/pattern_blk_mem.xco-outdated | 78 + .../modules/pixelcore/coregen/triggerfifo.xco | 82 + .../modules/pixelcore/coregen/xil_cores.cgp | 19 + .../pixelcore/hdl/BiphaseMarkEncoder.vhd | 41 + .../pixelcore/hdl/DisplayCharacters.vhd | 126 + .../modules/pixelcore/hdl/DisplayControl.vhd | 260 + .../modules/pixelcore/hdl/HsioPixelCore.vhd | 1826 ++ .../modules/pixelcore/hdl/I2cMaster.vhd | 369 + rce/fw-hsio/modules/pixelcore/hdl/I2cPkg.vhd | 199 + .../modules/pixelcore/hdl/I2cRegMaster.vhd | 261 + .../modules/pixelcore/hdl/OutputEncoder.vhd | 56 + .../modules/pixelcore/hdl/StdRtlPkg.vhd | 1267 ++ .../modules/pixelcore/hdl/adcreadout.vhd | 77 + .../modules/pixelcore/hdl/arraytype.vhd | 12 + .../modules/pixelcore/hdl/clock160.vhd | 113 + .../modules/pixelcore/hdl/clock200.vhd | 102 + .../modules/pixelcore/hdl/coincidence.vhd | 117 + .../modules/pixelcore/hdl/datafifo.vhd | 242 + .../modules/pixelcore/hdl/dataflag.vhd | 90 + .../modules/pixelcore/hdl/dataflagff.vhd | 85 + .../modules/pixelcore/hdl/dataflagnew.vhd | 79 + rce/fw-hsio/modules/pixelcore/hdl/dec.mif | 1024 + .../pixelcore/hdl/decode_8b10b_bram.vhd | 337 + .../pixelcore/hdl/decode_8b10b_disp.vhd | 207 + .../pixelcore/hdl/decode_8b10b_lut.vhd | 197 + .../pixelcore/hdl/decode_8b10b_lut_base.vhd | 801 + .../pixelcore/hdl/decode_8b10b_pkg.vhd | 251 + .../pixelcore/hdl/decode_8b10b_rtl.vhd | 565 + .../pixelcore/hdl/decode_8b10b_top.vhd | 280 + .../pixelcore/hdl/decode_8b10b_wrapper.vhd | 215 + .../pixelcore/hdl/decodefei4record.vhd | 96 + rce/fw-hsio/modules/pixelcore/hdl/deser.vhd | 131 + .../modules/pixelcore/hdl/deser10b.vhd | 64 + rce/fw-hsio/modules/pixelcore/hdl/deser4b.vhd | 64 + .../modules/pixelcore/hdl/encodepgp.vhd | 157 + .../modules/pixelcore/hdl/encodepgp24bit.vhd | 197 + .../modules/pixelcore/hdl/eofcounter.vhd | 113 + .../modules/pixelcore/hdl/eudaqTrigger.vhd | 86 + .../modules/pixelcore/hdl/framealign.vhd | 56 + .../pixelcore/hdl/framealignhitbus.vhd | 51 + .../modules/pixelcore/hdl/hitbuspipeline.vhd | 59 + .../pixelcore/hdl/i2c_master_bit_ctrl.vhd | 727 + .../pixelcore/hdl/i2c_master_byte_ctrl.vhd | 388 + .../modules/pixelcore/hdl/lookaheadfifo.vhd | 136 + .../modules/pixelcore/hdl/multiplexdata.vhd | 250 + .../pixelcore/hdl/multiplexdataopt.vhd | 265 + .../pixelcore/hdl/multiplexdatapgp2.vhd | 252 + .../modules/pixelcore/hdl/phaseshift.vhd | 131 + rce/fw-hsio/modules/pixelcore/hdl/ser.vhd | 96 + rce/fw-hsio/modules/pixelcore/hdl/ser32.vhd | 72 + rce/fw-hsio/modules/pixelcore/hdl/stdlib.vhd | 603 + .../modules/pixelcore/hdl/syncdatac.vhd | 317 + rce/fw-hsio/modules/pixelcore/hdl/tdc.vhd | 215 + .../modules/pixelcore/hdl/tdcreadout.vhd | 176 + rce/fw-hsio/modules/pixelcore/hdl/tempadc.vhd | 93 + .../modules/pixelcore/hdl/triggerlogic.vhd | 290 + .../modules/pixelcore/hdl/triggerpipeline.vhd | 125 + .../modules/pixelcore/hdl/wordswapper.vhd | 134 + rce/fw-hsio/projects/HsioCosmic/Makefile | 12 + rce/fw-hsio/projects/HsioCosmic/Readme.txt | 59 + rce/fw-hsio/projects/HsioCosmic/Version.vhd | 34 + .../HsioCosmic/config/bitgen_options.txt | 5 + .../HsioCosmic/config/map_options.txt | 21 + .../HsioCosmic/config/ngdbuild_options.txt | 5 + .../HsioCosmic/config/par_options.txt | 9 + .../HsioCosmic/config/promgen_options.txt | 7 + .../projects/HsioCosmic/config/sources.txt | 1 + .../HsioCosmic/config/sources_pgp1.txt | 80 + .../HsioCosmic/config/sources_pgp2.txt | 86 + .../HsioCosmic/config/trce_options.txt | 7 + .../HsioCosmic/config/xst_options.txt | 50 + .../projects/HsioCosmic/hdl/HsioCosmic.ucf | 1 + .../HsioCosmic/hdl/HsioCosmic.ucf.2core | 408 + .../HsioCosmic/hdl/HsioCosmic.ucf.4core | 438 + .../hdl/HsioCosmic.ucf.RJ45.oldHSIO | 370 + .../HsioCosmic/hdl/HsioCosmic.ucf.fei3 | 161 + .../HsioCosmic/hdl/HsioCosmic.ucf.full | 412 + .../HsioCosmic/hdl/HsioCosmic.ucf.oldCosmic | 219 + .../projects/HsioCosmic/hdl/HsioCosmic.vhd | 1 + .../HsioCosmic/hdl/HsioCosmic.vhd.2core | 786 + .../HsioCosmic/hdl/HsioCosmic.vhd.4core | 986 + .../HsioCosmic/hdl/HsioCosmic.vhd.fei3 | 770 + .../HsioCosmic/hdl/HsioCosmic.vhd.multicore | 800 + .../HsioCosmic/hdl/HsioCosmic.vhd.oldCosmic | 668 + .../HsioCosmic/hdl/HsioCosmic.vhd.regular | 697 + .../projects/HsioCosmic/images/.gitignore | 2 + rce/fw-hsio/projects/HsioStave0/Makefile | 12 + rce/fw-hsio/projects/HsioStave0/Readme.txt | 59 + rce/fw-hsio/projects/HsioStave0/Version.vhd | 32 + .../HsioStave0/config/bitgen_options.txt | 5 + .../HsioStave0/config/map_options.txt | 21 + .../HsioStave0/config/ngdbuild_options.txt | 5 + .../HsioStave0/config/par_options.txt | 9 + .../HsioStave0/config/promgen_options.txt | 7 + .../projects/HsioStave0/config/sources.txt | 1 + .../HsioStave0/config/sources_pgp1.txt | 73 + .../HsioStave0/config/sources_pgp2.txt | 67 + .../HsioStave0/config/trce_options.txt | 7 + .../HsioStave0/config/xst_options.txt | 50 + .../projects/HsioStave0/hdl/HsioStave0.ucf | 1 + .../hdl/HsioStave0.ucf.dbm_nonrotated | 333 + .../HsioStave0/hdl/HsioStave0.ucf.full | 348 + .../HsioStave0/hdl/HsioStave0.ucf.opto.ibl | 396 + .../hdl/HsioStave0.ucf.opto.nsqp.flipped | 354 + .../HsioStave0/hdl/HsioStave0.ucf.rotated | 368 + .../projects/HsioStave0/hdl/HsioStave0.vhd | 886 + .../projects/HsioStave0/images/.gitignore | 2 + rce/fw-hsio/projects/IBLcableTester/Makefile | 12 + .../projects/IBLcableTester/Readme.txt | 59 + .../projects/IBLcableTester/Version.vhd | 26 + .../IBLcableTester/config/bitgen_options.txt | 5 + .../IBLcableTester/config/map_options.txt | 21 + .../config/ngdbuild_options.txt | 5 + .../IBLcableTester/config/par_options.txt | 9 + .../IBLcableTester/config/promgen_options.txt | 7 + .../IBLcableTester/config/sources.txt | 40 + .../IBLcableTester/config/trce_options.txt | 7 + .../IBLcableTester/config/xst_options.txt | 50 + .../IBLcableTester/coregen/counter30.xco | 64 + ...0_c_counter_binary_v8_0_xst_1.ngc_xst.xrpt | 74 + .../IBLcableTester/coregen/counter30_xmdf.tcl | 68 + .../IBLcableTester/coregen/iblfifo.xco | 217 + ...ifo_fifo_generator_v4_4_xst_1.ngc_xst.xrpt | 101 + .../example_design/iblfifo_top.ucf | 59 + .../example_design/iblfifo_top.vhd | 358 + .../example_design/iblfifo_top.xdc | 57 + .../iblfifo_ste/implement/implement.bat | 88 + .../iblfifo_ste/implement/implement.sh | 87 + .../iblfifo_ste/implement/planAhead_rdn.bat | 55 + .../iblfifo_ste/implement/planAhead_rdn.sh | 55 + .../iblfifo_ste/implement/planAhead_rdn.tcl | 67 + .../coregen/iblfifo_ste/implement/xst.prj | 1 + .../coregen/iblfifo_ste/implement/xst.scr | 13 + .../coregen/iblfifo_upgrade.txt | 129 + .../IBLcableTester/coregen/iblfifo_xmdf.tcl | 115 + .../coregen/pattern_blk_mem.ngc | 3 + .../coregen/pattern_blk_mem.vhd | 145 + .../coregen/pattern_blk_mem.vho | 74 + .../coregen/pattern_blk_mem.xco | 78 + ...lk_mem_blk_mem_gen_v2_8_xst_1.ngc_xst.xrpt | 49 + .../coregen/pattern_blk_mem_flist.txt | 8 + .../coregen/pattern_blk_mem_readme.txt | 39 + .../coregen/pattern_blk_mem_xmdf.tcl | 68 + .../IBLcableTester/coregen/wordcounter.xco | 78 + ...ounter_blk_mem_gen_v2_8_xst_1.ngc_xst.xrpt | 50 + .../coregen/wordcounter_xmdf.tcl | 68 + .../IBLcableTester/hdl/IBLcableTester.ucf | 1 + .../hdl/IBLcableTester.ucf.cable.newHSIO | 460 + .../hdl/IBLcableTester.ucf.cable.oldHSIO | 457 + .../hdl/IBLcableTester.ucf.iblbert | 519 + .../IBLcableTester/hdl/IBLcableTester.vhd | 523 + .../IBLcableTester/hdl/IBLcableTesterCore.vhd | 670 + .../hdl/IBLcableTesterCoreOld.vhd | 622 + .../IBLcableTester/hdl/IBLcableTesterOld.vhd | 518 + .../projects/IBLcableTester/hdl/deser.vhd | 70 + .../projects/IBLcableTester/hdl/deser16.vhd | 67 + .../IBLcableTester/hdl/pattern_cmd.vhd | 575 + .../IBLcableTester/hdl/pattern_mem.vhd | 745 + .../IBLcableTester/hdl/pattern_memOld.vhd | 677 + .../IBLcableTester/hdl/phaseshift.vhd | 104 + .../projects/IBLcableTester/hdl/ser.vhd | 74 + .../IBLcableTester/hdl/serbiphase.vhd | 86 + rce/fw-hsio/system.mk | 262 + rce/make/hw/Makefile.package.template | 20 + rce/make/hw/constituents.mk.template | 29 + rce/make/hw/flags.mk | 44 + rce/make/hw/flags.mk.template | 1 + rce/make/hw/optgen.py | 23 + rce/make/hw/package.mk | 296 + rce/make/hw/prjgen.py | 64 + rce/make/hw/tclgen.py | 48 + rce/make/share/Makefile.project.template | 17 + rce/make/share/packages.mk.template | 2 + rce/make/share/premake.mk | 41 + rce/make/share/project.mk | 39 + rce/make/share/release.mk | 82 + rce/make/share/setup.mk | 49 + rce/make/sw/Makefile.package.template | 20 + rce/make/sw/constituents.mk.template | 39 + rce/make/sw/flags.mk | 236 + rce/make/sw/flags.mk.template | 1 + rce/make/sw/idl.mk | 24 + rce/make/sw/package.mk | 396 + rce/make/sw/python.mk | 41 + rce/make/sw/qt.mk | 10 + rce/make/sw/rootcint.mk | 10 + rce/make/tools/options.py | 47 + rce/make/tools/pkgcreate.py | 50 + rce/make/tools/prjupdate.py | 48 + rce/make/tools/replace.pl | 23 + rce/pixelrce/config/FEI3/IPCModule.cc | 203 + rce/pixelrce/config/FEI3/IPCModule.hh | 27 + rce/pixelrce/config/FEI4/IPCFEI4AModule.cc | 314 + rce/pixelrce/config/FEI4/IPCFEI4AModule.hh | 32 + rce/pixelrce/config/FEI4/IPCFEI4BModule.cc | 331 + rce/pixelrce/config/FEI4/IPCFEI4BModule.hh | 32 + rce/pixelrce/config/IPCConfigIF.cc | 140 + rce/pixelrce/config/IPCConfigIF.hh | 41 + rce/pixelrce/config/IPCModuleFactory.cc | 116 + rce/pixelrce/config/IPCModuleFactory.hh | 32 + rce/pixelrce/config/afp-hptdc/IPCModule.cc | 185 + rce/pixelrce/config/afp-hptdc/IPCModule.hh | 26 + rce/pixelrce/config/hitbus/IPCModule.cc | 74 + rce/pixelrce/config/hitbus/IPCModule.hh | 26 + rce/pixelrce/idl/IPCAFPHPTDCAdapter.idl | 16 + rce/pixelrce/idl/IPCConfigIFAdapter.idl | 42 + rce/pixelrce/idl/IPCFEI3Adapter.idl | 16 + rce/pixelrce/idl/IPCFEI4AAdapter.idl | 20 + rce/pixelrce/idl/IPCFEI4BAdapter.idl | 20 + rce/pixelrce/idl/IPCHitbusAdapter.idl | 16 + rce/pixelrce/idl/IPCScanAdapter.idl | 21 + rce/pixelrce/idl/IPCScanRootAdapter.idl | 23 + rce/pixelrce/scanctrl/IPCRceCallback.cc | 35 + rce/pixelrce/scanctrl/IPCRceCallback.hh | 18 + rce/pixelrce/scanctrl/IPCScan.cc | 99 + rce/pixelrce/scanctrl/IPCScan.hh | 29 + rce/pixelrce/scanctrl/IPCScanRoot.cc | 184 + rce/pixelrce/scanctrl/IPCScanRoot.hh | 31 + rce/pixelrce/server/IPCCalibGui.cc | 54 + rce/pixelrce/server/IPCCallback.hh | 30 + rce/pixelrce/server/IPCController.cc | 851 + rce/pixelrce/server/IPCController.hh | 64 + rce/pixelrce/server/IPCCosmicGui.cc | 62 + rce/pixelrce/server/IPCGuiCallback.cc | 29 + rce/pixelrce/server/IPCGuiCallback.hh | 18 + rce/pixelrce/server/IPCHistoController.cc | 170 + rce/pixelrce/server/IPCHistoController.hh | 30 + rce/pixelrce/server/IPCRceOfflineProducer.cc | 76 + rce/pixelrce/server/IPCRegularCallback.cc | 19 + rce/pixelrce/server/IPCRegularCallback.hh | 13 + rce/pixelrce/server/IPClinux_server_pgp.cc | 104 + rce/pixelrce/server/IPCrebootHSIO.cc | 80 + rce/pixelrce/util/IPCProvider.hh | 53 + rce/pixelrce/util/IPCProvider.i | 58 + rce/projects.mk | 34 + rce/rcecalib/HW/BitStream.hh | 22 + rce/rcecalib/HW/Headers.hh | 107 + rce/rcecalib/HW/Makefile | 20 + rce/rcecalib/HW/RCDImaster.cc | 344 + rce/rcecalib/HW/RCDImaster.hh | 72 + rce/rcecalib/HW/Receiver.hh | 22 + rce/rcecalib/HW/SerialHexdump.cc | 71 + rce/rcecalib/HW/SerialHexdump.hh | 25 + rce/rcecalib/HW/SerialIF.cc | 67 + rce/rcecalib/HW/SerialIF.hh | 45 + rce/rcecalib/HW/SerialPgp.cc | 50 + rce/rcecalib/HW/SerialPgp.hh | 19 + rce/rcecalib/HW/SerialPgpBw.cc | 67 + rce/rcecalib/HW/SerialPgpBw.hh | 25 + rce/rcecalib/HW/SerialPgpFei4.cc | 18 + rce/rcecalib/HW/SerialPgpFei4.hh | 17 + rce/rcecalib/HW/constituents.mk | 34 + rce/rcecalib/Makefile | 17 + rce/rcecalib/analysis/AnalysisFactory.cc | 90 + rce/rcecalib/analysis/AnalysisFactory.hh | 15 + rce/rcecalib/analysis/AnalysisGui.cc | 205 + rce/rcecalib/analysis/AnalysisGui.hh | 44 + rce/rcecalib/analysis/CalibAnalysis.cc | 147 + rce/rcecalib/analysis/CalibAnalysis.hh | 38 + rce/rcecalib/analysis/CfgFileWriter.cc | 13 + rce/rcecalib/analysis/CfgFileWriter.hh | 17 + rce/rcecalib/analysis/CrosstalkAnalysis.cc | 168 + rce/rcecalib/analysis/CrosstalkAnalysis.hh | 24 + rce/rcecalib/analysis/DigitalTestAnalysis.cc | 111 + rce/rcecalib/analysis/DigitalTestAnalysis.hh | 25 + rce/rcecalib/analysis/Fdac_Analysis.cc | 218 + rce/rcecalib/analysis/Fdac_Analysis.hh | 30 + rce/rcecalib/analysis/Fei3CfgFileWriter.cc | 52 + rce/rcecalib/analysis/Fei3CfgFileWriter.hh | 14 + rce/rcecalib/analysis/Fei4CfgFileWriter.cc | 51 + rce/rcecalib/analysis/Fei4CfgFileWriter.hh | 14 + rce/rcecalib/analysis/GdacAnalysis.cc | 199 + rce/rcecalib/analysis/GdacAnalysis.hh | 33 + .../analysis/GdacCoarseFastAnalysis.cc | 127 + .../analysis/GdacCoarseFastAnalysis.hh | 31 + rce/rcecalib/analysis/GdacFastAnalysis.cc | 155 + rce/rcecalib/analysis/GdacFastAnalysis.hh | 31 + rce/rcecalib/analysis/HistoViewerGui.cc | 194 + rce/rcecalib/analysis/HistoViewerGui.hh | 45 + rce/rcecalib/analysis/Iff_Analysis.cc | 169 + rce/rcecalib/analysis/Iff_Analysis.hh | 26 + rce/rcecalib/analysis/Makefile | 21 + rce/rcecalib/analysis/MergeMaskFilesFei4.cc | 50 + .../analysis/ModuleCrosstalkAnalysis.cc | 70 + .../analysis/ModuleCrosstalkAnalysis.hh | 21 + rce/rcecalib/analysis/MultiTrigAnalysis.cc | 263 + rce/rcecalib/analysis/MultiTrigAnalysis.hh | 24 + .../analysis/MultiTrigNoiseAnalysis.cc | 144 + .../analysis/MultiTrigNoiseAnalysis.hh | 24 + rce/rcecalib/analysis/NoiseAnalysis.cc | 85 + rce/rcecalib/analysis/NoiseAnalysis.hh | 25 + rce/rcecalib/analysis/OffsetAnalysis.cc | 132 + rce/rcecalib/analysis/OffsetAnalysis.hh | 23 + rce/rcecalib/analysis/RegisterTestAnalysis.cc | 168 + rce/rcecalib/analysis/RegisterTestAnalysis.hh | 22 + rce/rcecalib/analysis/SerialNumberAnalysis.cc | 53 + rce/rcecalib/analysis/SerialNumberAnalysis.hh | 21 + rce/rcecalib/analysis/StuckPixelAnalysis.cc | 52 + rce/rcecalib/analysis/StuckPixelAnalysis.hh | 25 + rce/rcecalib/analysis/T0Analysis.cc | 311 + rce/rcecalib/analysis/T0Analysis.hh | 23 + rce/rcecalib/analysis/TdacAnalysis.cc | 157 + rce/rcecalib/analysis/TdacAnalysis.hh | 33 + rce/rcecalib/analysis/TdacFastAnalysis.cc | 124 + rce/rcecalib/analysis/TdacFastAnalysis.hh | 33 + rce/rcecalib/analysis/TemperatureAnalysis.cc | 106 + rce/rcecalib/analysis/TemperatureAnalysis.hh | 21 + rce/rcecalib/analysis/ThresholdAnalysis.cc | 191 + rce/rcecalib/analysis/ThresholdAnalysis.hh | 24 + rce/rcecalib/analysis/TimeWalkAnalysis.cc | 237 + rce/rcecalib/analysis/TimeWalkAnalysis.hh | 23 + rce/rcecalib/analysis/TotAnalysis.cc | 169 + rce/rcecalib/analysis/TotAnalysis.hh | 28 + rce/rcecalib/analysis/TotCalibAnalysis.cc | 165 + rce/rcecalib/analysis/TotCalibAnalysis.hh | 23 + rce/rcecalib/analysis/analysisGui_Linkdef.hh | 2 + rce/rcecalib/analysis/constituents.mk | 124 + rce/rcecalib/analysis/histoViewer_Linkdef.hh | 1 + rce/rcecalib/analysis/tdacScanAnalysis.cc | 89 + rce/rcecalib/analysis/tdacScanAnalysis.hh | 22 + rce/rcecalib/config/AbsFormatter.hh | 22 + rce/rcecalib/config/AbsModule.hh | 40 + rce/rcecalib/config/AbsModuleGroup.cc | 22 + rce/rcecalib/config/AbsModuleGroup.hh | 32 + rce/rcecalib/config/AbsTrigger.cc | 9 + rce/rcecalib/config/AbsTrigger.hh | 27 + rce/rcecalib/config/BFU.hh | 157 + rce/rcecalib/config/ConfigIF.cc | 250 + rce/rcecalib/config/ConfigIF.hh | 53 + rce/rcecalib/config/DummyFormatter.cc | 20 + rce/rcecalib/config/DummyFormatter.hh | 13 + rce/rcecalib/config/Endianness.hh | 270 + rce/rcecalib/config/EventFromDspTrigger.cc | 93 + rce/rcecalib/config/EventFromDspTrigger.hh | 28 + rce/rcecalib/config/EventFromFileTrigger.cc | 29 + rce/rcecalib/config/EventFromFileTrigger.hh | 19 + .../config/FEI3/CrosstalkMaskStaging.cc | 42 + .../config/FEI3/CrosstalkMaskStaging.hh | 19 + rce/rcecalib/config/FEI3/FECommands.cc | 63 + rce/rcecalib/config/FEI3/FECommands.hh | 46 + rce/rcecalib/config/FEI3/Frontend.cc | 204 + rce/rcecalib/config/FEI3/Frontend.hh | 42 + rce/rcecalib/config/FEI3/GlobalRegister.cc | 235 + rce/rcecalib/config/FEI3/GlobalRegister.hh | 44 + rce/rcecalib/config/FEI3/IPCModule.cc | 203 + rce/rcecalib/config/FEI3/IPCModule.hh | 27 + rce/rcecalib/config/FEI3/JJFormatter.cc | 774 + rce/rcecalib/config/FEI3/JJFormatter.hh | 14 + rce/rcecalib/config/FEI3/MaskStageFactory.cc | 86 + rce/rcecalib/config/FEI3/MaskStaging.cc | 22 + rce/rcecalib/config/FEI3/Mcc.cc | 92 + rce/rcecalib/config/FEI3/Mcc.hh | 37 + rce/rcecalib/config/FEI3/Module.cc | 172 + rce/rcecalib/config/FEI3/Module.hh | 41 + rce/rcecalib/config/FEI3/ModuleGroup.cc | 88 + rce/rcecalib/config/FEI3/ModuleGroup.hh | 33 + rce/rcecalib/config/FEI3/PixelRegister.cc | 25 + rce/rcecalib/config/FEI3/PixelRegister.hh | 56 + .../config/FEI3/RegularMaskStaging.cc | 34 + .../config/FEI3/RegularMaskStaging.hh | 19 + .../FEI4/AnalogColpr2MaskStagingFei4a.cc | 43 + .../FEI4/AnalogColpr2MaskStagingFei4a.hh | 20 + .../config/FEI4/AnalogColprMaskStaging.cc | 51 + .../config/FEI4/AnalogColprMaskStaging.hh | 23 + rce/rcecalib/config/FEI4/AnalogMaskStaging.cc | 36 + rce/rcecalib/config/FEI4/AnalogMaskStaging.hh | 21 + .../FEI4/AnalogSimpleColprMaskStaging.cc | 38 + .../FEI4/AnalogSimpleColprMaskStaging.hh | 22 + .../config/FEI4/AnalogSingleMaskStaging.cc | 19 + .../config/FEI4/AnalogSingleMaskStaging.hh | 18 + .../config/FEI4/CrosstalkFastMaskStaging.cc | 106 + .../config/FEI4/CrosstalkFastMaskStaging.hh | 19 + .../config/FEI4/CrosstalkMaskStaging.cc | 44 + .../config/FEI4/CrosstalkMaskStaging.hh | 19 + .../config/FEI4/DiffusionMaskStaging.cc | 28 + .../config/FEI4/DiffusionMaskStaging.hh | 19 + .../config/FEI4/DigStepMaskStaging.cc | 29 + .../config/FEI4/DigStepMaskStaging.hh | 19 + .../config/FEI4/DigitalMaskStaging.cc | 28 + .../config/FEI4/DigitalMaskStaging.hh | 17 + rce/rcecalib/config/FEI4/FECommands.cc | 61 + rce/rcecalib/config/FEI4/FECommands.hh | 35 + rce/rcecalib/config/FEI4/FEI4AFormatter.cc | 100 + rce/rcecalib/config/FEI4/FEI4AFormatter.hh | 19 + .../config/FEI4/FEI4AGlobalRegister.cc | 295 + .../config/FEI4/FEI4AGlobalRegister.hh | 31 + rce/rcecalib/config/FEI4/FEI4AModule.cc | 107 + rce/rcecalib/config/FEI4/FEI4AModule.hh | 25 + rce/rcecalib/config/FEI4/FEI4ARecord.hh | 246 + rce/rcecalib/config/FEI4/FEI4BFormatter.cc | 117 + rce/rcecalib/config/FEI4/FEI4BFormatter.hh | 23 + .../config/FEI4/FEI4BGlobalRegister.cc | 300 + .../config/FEI4/FEI4BGlobalRegister.hh | 31 + rce/rcecalib/config/FEI4/FEI4BModule.cc | 104 + rce/rcecalib/config/FEI4/FEI4BModule.hh | 25 + rce/rcecalib/config/FEI4/FEI4BRecord.hh | 246 + .../config/FEI4/FEI4HitorFormatter.cc | 63 + .../config/FEI4/FEI4HitorFormatter.hh | 14 + rce/rcecalib/config/FEI4/FEI4OccFormatter.cc | 82 + rce/rcecalib/config/FEI4/FEI4OccFormatter.hh | 19 + .../config/FEI4/FastAnalogMaskStaging.cc | 37 + .../config/FEI4/FastAnalogMaskStaging.hh | 20 + .../config/FEI4/Fei4RegisterTestTrigger.cc | 97 + .../config/FEI4/Fei4RegisterTestTrigger.hh | 25 + rce/rcecalib/config/FEI4/GlobalRegister.cc | 273 + rce/rcecalib/config/FEI4/GlobalRegister.hh | 61 + rce/rcecalib/config/FEI4/IPCFEI4AModule.cc | 314 + rce/rcecalib/config/FEI4/IPCFEI4AModule.hh | 32 + rce/rcecalib/config/FEI4/IPCFEI4BModule.cc | 331 + rce/rcecalib/config/FEI4/IPCFEI4BModule.hh | 32 + rce/rcecalib/config/FEI4/MaskStageFactory.cc | 149 + rce/rcecalib/config/FEI4/MaskStaging.cc | 27 + rce/rcecalib/config/FEI4/MaskStaging26880.cc | 33 + rce/rcecalib/config/FEI4/MaskStaging26880.hh | 16 + rce/rcecalib/config/FEI4/Module.cc | 332 + rce/rcecalib/config/FEI4/Module.hh | 73 + .../config/FEI4/ModuleCrosstalkMaskStaging.cc | 50 + .../config/FEI4/ModuleCrosstalkMaskStaging.hh | 20 + rce/rcecalib/config/FEI4/ModuleGroup.cc | 210 + rce/rcecalib/config/FEI4/ModuleGroup.hh | 35 + rce/rcecalib/config/FEI4/MonleakTrigger.cc | 77 + rce/rcecalib/config/FEI4/MonleakTrigger.hh | 26 + rce/rcecalib/config/FEI4/NoiseMaskStaging.cc | 54 + rce/rcecalib/config/FEI4/NoiseMaskStaging.hh | 20 + .../config/FEI4/PatternMaskStaging.cc | 23 + .../config/FEI4/PatternMaskStaging.hh | 18 + rce/rcecalib/config/FEI4/PixelRegister.cc | 261 + rce/rcecalib/config/FEI4/PixelRegister.hh | 106 + rce/rcecalib/config/FEI4/RegisterDef.hh | 29 + rce/rcecalib/config/FEI4/SNTrigger.cc | 67 + rce/rcecalib/config/FEI4/SNTrigger.hh | 26 + .../config/FEI4/TemperatureTrigger.cc | 72 + .../config/FEI4/TemperatureTrigger.hh | 26 + rce/rcecalib/config/FEI4/Utils.hh | 14 + rce/rcecalib/config/FormattedRecord.hh | 158 + rce/rcecalib/config/HitorTrigger.cc | 29 + rce/rcecalib/config/HitorTrigger.hh | 22 + rce/rcecalib/config/IPCConfigIF.cc | 140 + rce/rcecalib/config/IPCConfigIF.hh | 41 + rce/rcecalib/config/IPCModuleFactory.cc | 146 + rce/rcecalib/config/IPCModuleFactory.hh | 32 + rce/rcecalib/config/Makefile | 20 + rce/rcecalib/config/MaskStageFactory.hh | 17 + rce/rcecalib/config/MaskStaging.hh | 29 + rce/rcecalib/config/Masks.hh | 12 + rce/rcecalib/config/MeasurementTrigger.cc | 29 + rce/rcecalib/config/MeasurementTrigger.hh | 18 + rce/rcecalib/config/ModuleFactory.hh | 22 + rce/rcecalib/config/ModuleInfo.hh | 32 + rce/rcecalib/config/MultiShotTrigger.cc | 78 + rce/rcecalib/config/MultiShotTrigger.hh | 28 + rce/rcecalib/config/MultiTrigger.cc | 277 + rce/rcecalib/config/MultiTrigger.hh | 36 + rce/rcecalib/config/Trigger.cc | 154 + rce/rcecalib/config/Trigger.hh | 31 + rce/rcecalib/config/TriggerReceiverIF.cc | 15 + rce/rcecalib/config/TriggerReceiverIF.hh | 13 + .../config/afp-hptdc/AFPHPTDCFormatter.cc | 81 + .../config/afp-hptdc/AFPHPTDCFormatter.hh | 16 + .../config/afp-hptdc/AFPHPTDCRecord.hh | 30 + rce/rcecalib/config/afp-hptdc/IPCModule.cc | 184 + rce/rcecalib/config/afp-hptdc/IPCModule.hh | 26 + rce/rcecalib/config/afp-hptdc/Module.cc | 321 + rce/rcecalib/config/afp-hptdc/Module.hh | 64 + rce/rcecalib/config/afp-hptdc/ModuleGroup.cc | 86 + rce/rcecalib/config/afp-hptdc/ModuleGroup.hh | 33 + rce/rcecalib/config/constituents.mk | 90 + rce/rcecalib/config/hitbus/IPCModule.cc | 74 + rce/rcecalib/config/hitbus/IPCModule.hh | 26 + rce/rcecalib/config/hitbus/Module.cc | 129 + rce/rcecalib/config/hitbus/Module.hh | 55 + rce/rcecalib/config/hitbus/ModuleGroup.cc | 81 + rce/rcecalib/config/hitbus/ModuleGroup.hh | 33 + rce/rcecalib/dataproc/AbsDataHandler.hh | 23 + rce/rcecalib/dataproc/AbsDataProc.cc | 47 + rce/rcecalib/dataproc/AbsDataProc.hh | 30 + rce/rcecalib/dataproc/AbsReceiver.hh | 15 + rce/rcecalib/dataproc/BcidDataProc.cc | 155 + rce/rcecalib/dataproc/BcidDataProc.hh | 33 + rce/rcecalib/dataproc/Channeldefs.hh | 7 + rce/rcecalib/dataproc/ClusterProc.cc | 154 + rce/rcecalib/dataproc/ClusterProc.hh | 61 + rce/rcecalib/dataproc/CosmicDataHandler.cc | 59 + rce/rcecalib/dataproc/CosmicDataHandler.hh | 27 + rce/rcecalib/dataproc/CosmicDataProc.cc | 264 + rce/rcecalib/dataproc/CosmicDataProc.hh | 39 + rce/rcecalib/dataproc/CosmicEvent.cc | 302 + rce/rcecalib/dataproc/CosmicEvent.hh | 58 + rce/rcecalib/dataproc/CosmicEventIterator.cc | 177 + rce/rcecalib/dataproc/CosmicEventIterator.hh | 44 + rce/rcecalib/dataproc/CosmicEventReceiver.hh | 17 + rce/rcecalib/dataproc/DataProcFactory.cc | 114 + rce/rcecalib/dataproc/DataProcFactory.hh | 24 + rce/rcecalib/dataproc/DelayScanDataHandler.cc | 15 + rce/rcecalib/dataproc/DelayScanDataHandler.hh | 19 + rce/rcecalib/dataproc/DelayScanDataProc.cc | 43 + rce/rcecalib/dataproc/DelayScanDataProc.hh | 19 + .../dataproc/Fei4RegisterTestDataProc.cc | 145 + .../dataproc/Fei4RegisterTestDataProc.hh | 26 + rce/rcecalib/dataproc/HitorDataProc.cc | 56 + rce/rcecalib/dataproc/HitorDataProc.hh | 21 + rce/rcecalib/dataproc/Makefile | 20 + rce/rcecalib/dataproc/MeasurementDataProc.cc | 74 + rce/rcecalib/dataproc/MeasurementDataProc.hh | 28 + rce/rcecalib/dataproc/MeasurementReceiver.cc | 101 + rce/rcecalib/dataproc/MeasurementReceiver.hh | 24 + .../dataproc/ModuleCrosstalkRawDataHandler.cc | 85 + .../dataproc/ModuleCrosstalkRawDataHandler.hh | 31 + rce/rcecalib/dataproc/MonleakDataProc.cc | 192 + rce/rcecalib/dataproc/MonleakDataProc.hh | 32 + .../dataproc/MultiTrigNoiseDataProc.cc | 219 + .../dataproc/MultiTrigNoiseDataProc.hh | 40 + .../dataproc/MultiTrigOccupancyDataProc.cc | 219 + .../dataproc/MultiTrigOccupancyDataProc.hh | 40 + .../dataproc/NoiseOccupancyDataProc.cc | 94 + .../dataproc/NoiseOccupancyDataProc.hh | 25 + rce/rcecalib/dataproc/OccupancyDataProc.cc | 121 + rce/rcecalib/dataproc/OccupancyDataProc.hh | 29 + rce/rcecalib/dataproc/PgpCosmicNwReceiver.cc | 145 + rce/rcecalib/dataproc/PgpCosmicNwReceiver.hh | 33 + rce/rcecalib/dataproc/PgpCosmicReceiver.cc | 63 + rce/rcecalib/dataproc/PgpCosmicReceiver.hh | 21 + rce/rcecalib/dataproc/PgpReceiver.cc | 54 + rce/rcecalib/dataproc/PgpReceiver.hh | 20 + rce/rcecalib/dataproc/ProducerIF.hh | 18 + .../dataproc/RawFei4OccupancyDataProc.cc | 154 + .../dataproc/RawFei4OccupancyDataProc.hh | 34 + .../dataproc/RegularScanDataHandler.cc | 108 + .../dataproc/RegularScanDataHandler.hh | 31 + .../dataproc/RegularScanRawDataHandler.cc | 91 + .../dataproc/RegularScanRawDataHandler.hh | 29 + rce/rcecalib/dataproc/SNDataProc.cc | 82 + rce/rcecalib/dataproc/SNDataProc.hh | 21 + rce/rcecalib/dataproc/SelftriggerDataProc.cc | 393 + rce/rcecalib/dataproc/SelftriggerDataProc.hh | 70 + rce/rcecalib/dataproc/SimpleDataHandler.hh | 24 + rce/rcecalib/dataproc/SimpleReceiver.cc | 6 + rce/rcecalib/dataproc/SimpleReceiver.hh | 12 + rce/rcecalib/dataproc/TemperatureDataProc.cc | 132 + rce/rcecalib/dataproc/TemperatureDataProc.hh | 29 + rce/rcecalib/dataproc/TotCalibDataProc.cc | 79 + rce/rcecalib/dataproc/TotCalibDataProc.hh | 26 + rce/rcecalib/dataproc/TotDataProc.cc | 162 + rce/rcecalib/dataproc/TotDataProc.hh | 30 + rce/rcecalib/dataproc/constituents.mk | 99 + rce/rcecalib/dataproc/fit/AbsFit.hh | 24 + .../dataproc/fit/CalculateMeanSigma.cc | 73 + rce/rcecalib/dataproc/fit/FitData.cc | 35 + rce/rcecalib/dataproc/fit/FitData.hh | 34 + rce/rcecalib/dataproc/fit/FitFactory.cc | 28 + rce/rcecalib/dataproc/fit/FitFactory.hh | 18 + .../fit/FitScurveLikelihoodFastInt.cc | 822 + .../fit/FitScurveLikelihoodFastInt.hh | 77 + .../dataproc/fit/FitScurveLikelihoodFloat.cc | 461 + .../dataproc/fit/FitScurveLikelihoodFloat.hh | 57 + .../dataproc/fit/FitScurveLikelihoodInt.cc | 543 + .../dataproc/fit/FitScurveLikelihoodInt.hh | 66 + rce/rcecalib/dataproc/fit/binomial_weight.dat | 1001 + .../dataproc/fit/binomial_weight_fastint.dat | 1001 + .../dataproc/fit/binomial_weight_int.dat | 1001 + rce/rcecalib/dataproc/fit/errf_ext.dat | 7001 +++++++ .../dataproc/fit/errf_ext_fastint.dat | 8191 ++++++++ rce/rcecalib/dataproc/fit/errf_ext_int.dat | 7001 +++++++ rce/rcecalib/dataproc/fit/logx.dat | 7001 +++++++ rce/rcecalib/dataproc/fit/logx_ext.dat | 14002 +++++++++++++ .../dataproc/fit/logx_ext_fastint.dat | 16382 ++++++++++++++++ rce/rcecalib/dataproc/fit/logx_ext_int.dat | 14002 +++++++++++++ rce/rcecalib/eudaq/BufferSerializer.cc | 32 + rce/rcecalib/eudaq/BufferSerializer.hh | 33 + rce/rcecalib/eudaq/CommandReceiver.cc | 154 + rce/rcecalib/eudaq/CommandReceiver.hh | 51 + rce/rcecalib/eudaq/Configuration.cc | 153 + rce/rcecalib/eudaq/Configuration.hh | 59 + rce/rcecalib/eudaq/DataSender.cc | 63 + rce/rcecalib/eudaq/DataSender.hh | 27 + rce/rcecalib/eudaq/DataSenderIF.cc | 25 + rce/rcecalib/eudaq/DataSenderIF.hh | 27 + rce/rcecalib/eudaq/DetectorEvent.cc | 45 + rce/rcecalib/eudaq/DetectorEvent.hh | 51 + rce/rcecalib/eudaq/Event.cc | 117 + rce/rcecalib/eudaq/Event.hh | 119 + rce/rcecalib/eudaq/Exception.cc | 48 + rce/rcecalib/eudaq/Exception.hh | 84 + rce/rcecalib/eudaq/FileSerializer.cc | 123 + rce/rcecalib/eudaq/FileSerializer.hh | 52 + rce/rcecalib/eudaq/Makefile | 21 + rce/rcecalib/eudaq/Mutex.cc | 84 + rce/rcecalib/eudaq/Mutex.hh | 42 + rce/rcecalib/eudaq/Producer.cc | 14 + rce/rcecalib/eudaq/Producer.hh | 30 + rce/rcecalib/eudaq/ProducerIF.cc | 15 + rce/rcecalib/eudaq/ProducerIF.hh | 18 + rce/rcecalib/eudaq/RawDataEvent.cc | 60 + rce/rcecalib/eudaq/RawDataEvent.hh | 112 + rce/rcecalib/eudaq/Serializable.hh | 22 + rce/rcecalib/eudaq/Serializer.hh | 262 + rce/rcecalib/eudaq/Status.cc | 63 + rce/rcecalib/eudaq/Status.hh | 51 + rce/rcecalib/eudaq/TLUEvent.cc | 26 + rce/rcecalib/eudaq/TLUEvent.hh | 39 + rce/rcecalib/eudaq/Time.cc | 60 + rce/rcecalib/eudaq/Time.hh | 89 + rce/rcecalib/eudaq/TransportBase.cc | 103 + rce/rcecalib/eudaq/TransportBase.hh | 206 + rce/rcecalib/eudaq/TransportClient.cc | 8 + rce/rcecalib/eudaq/TransportClient.hh | 19 + rce/rcecalib/eudaq/TransportFactory.cc | 86 + rce/rcecalib/eudaq/TransportFactory.hh | 22 + rce/rcecalib/eudaq/TransportNULL.cc | 45 + rce/rcecalib/eudaq/TransportNULL.hh | 45 + rce/rcecalib/eudaq/TransportServer.cc | 12 + rce/rcecalib/eudaq/TransportServer.hh | 22 + rce/rcecalib/eudaq/TransportTCP.cc | 473 + rce/rcecalib/eudaq/TransportTCP.hh | 81 + rce/rcecalib/eudaq/TransportTCP_POSIX.inc | 51 + rce/rcecalib/eudaq/Utils.cc | 135 + rce/rcecalib/eudaq/Utils.hh | 261 + rce/rcecalib/eudaq/constituents.mk | 61 + rce/rcecalib/eudaq/counted_ptr.hh | 113 + rce/rcecalib/eudaq/testread.cc | 245 + rce/rcecalib/eudaq/testreadp.cc | 258 + rce/rcecalib/eudaq/testwrite.cc | 19 + rce/rcecalib/flags.mk | 86 + rce/rcecalib/idl/AFPHPTDCModuleConfig.idl | 120 + rce/rcecalib/idl/Callback.idl | 26 + rce/rcecalib/idl/HitbusModuleConfig.idl | 25 + rce/rcecalib/idl/IPCAFPHPTDCAdapter.idl | 16 + rce/rcecalib/idl/IPCConfigIFAdapter.idl | 42 + rce/rcecalib/idl/IPCFEI3Adapter.idl | 16 + rce/rcecalib/idl/IPCFEI4AAdapter.idl | 20 + rce/rcecalib/idl/IPCFEI4BAdapter.idl | 20 + rce/rcecalib/idl/IPCHitbusAdapter.idl | 16 + rce/rcecalib/idl/IPCScanAdapter.idl | 21 + rce/rcecalib/idl/IPCScanRootAdapter.idl | 23 + rce/rcecalib/idl/Makefile | 21 + rce/rcecalib/idl/PixelFEI4AConfig.idl | 117 + rce/rcecalib/idl/PixelFEI4BConfig.idl | 128 + rce/rcecalib/idl/PixelFEI4GenConfig.idl | 40 + rce/rcecalib/idl/PixelModuleConfig.idl | 216 + rce/rcecalib/idl/ScanOptions.idl | 96 + rce/rcecalib/idl/constituents.mk | 33 + rce/rcecalib/namespace_aliases.hh | 61 + rce/rcecalib/packages.mk | 5 + rce/rcecalib/profiler/Makefile | 21 + rce/rcecalib/profiler/Profiler.cc | 1221 ++ rce/rcecalib/profiler/Profiler.hh | 258 + rce/rcecalib/profiler/README | 64 + rce/rcecalib/profiler/constituents.mk | 13 + rce/rcecalib/projects.mk.template | 34 + rce/rcecalib/scanctrl/AbsScan.hh | 29 + rce/rcecalib/scanctrl/ActionFactory.cc | 90 + rce/rcecalib/scanctrl/ActionFactory.hh | 26 + rce/rcecalib/scanctrl/ChangeBinAction.hh | 19 + rce/rcecalib/scanctrl/CloseFileEoLAction.hh | 19 + .../scanctrl/ConfigureModulesAction.hh | 19 + .../scanctrl/ConfigureModulesNEAction.hh | 19 + rce/rcecalib/scanctrl/CosmicDataSetup.cc | 45 + rce/rcecalib/scanctrl/CosmicDataSetup.hh | 18 + .../CosmicEnableScintillatorTriggerAction.hh | 21 + .../scanctrl/CosmicEnableTDCAction.hh | 20 + .../scanctrl/CosmicSetInputDelayAction.hh | 51 + rce/rcecalib/scanctrl/DelayScanSetup.cc | 43 + rce/rcecalib/scanctrl/DelayScanSetup.hh | 18 + .../scanctrl/DisableAllChannelsAction.hh | 19 + .../scanctrl/DisableAllChannelsEoLAction.hh | 19 + rce/rcecalib/scanctrl/DisableTriggerAction.hh | 19 + .../scanctrl/DisableTriggerEoLAction.hh | 20 + rce/rcecalib/scanctrl/EnableTriggerAction.hh | 20 + rce/rcecalib/scanctrl/EndOfLoopAction.hh | 17 + rce/rcecalib/scanctrl/FitEoLAction.hh | 27 + rce/rcecalib/scanctrl/IPCScan.cc | 99 + rce/rcecalib/scanctrl/IPCScan.hh | 29 + rce/rcecalib/scanctrl/IPCScanRoot.cc | 184 + rce/rcecalib/scanctrl/IPCScanRoot.hh | 29 + rce/rcecalib/scanctrl/IfScanSetup.cc | 63 + rce/rcecalib/scanctrl/IfScanSetup.hh | 18 + rce/rcecalib/scanctrl/IfWaitAction.hh | 22 + rce/rcecalib/scanctrl/LoopAction.hh | 19 + rce/rcecalib/scanctrl/LoopFactory.cc | 38 + rce/rcecalib/scanctrl/LoopFactory.hh | 16 + rce/rcecalib/scanctrl/LoopSetup.hh | 17 + rce/rcecalib/scanctrl/Makefile | 20 + rce/rcecalib/scanctrl/NestedLoop.cc | 81 + rce/rcecalib/scanctrl/NestedLoop.hh | 32 + rce/rcecalib/scanctrl/NoiseScanSetup.cc | 42 + rce/rcecalib/scanctrl/NoiseScanSetup.hh | 18 + rce/rcecalib/scanctrl/PauseAction.hh | 20 + rce/rcecalib/scanctrl/RceCallback.cc | 47 + rce/rcecalib/scanctrl/RceCallback.hh | 24 + rce/rcecalib/scanctrl/RegularCfgScanSetup.cc | 110 + rce/rcecalib/scanctrl/RegularCfgScanSetup.hh | 18 + rce/rcecalib/scanctrl/RegularScanSetup.cc | 106 + rce/rcecalib/scanctrl/RegularScanSetup.hh | 18 + rce/rcecalib/scanctrl/ResetFEEoLAction.hh | 19 + rce/rcecalib/scanctrl/Scan.cc | 242 + rce/rcecalib/scanctrl/Scan.hh | 47 + rce/rcecalib/scanctrl/ScanLoop.cc | 83 + rce/rcecalib/scanctrl/ScanLoop.hh | 48 + rce/rcecalib/scanctrl/ScanRoot.cc | 72 + rce/rcecalib/scanctrl/ScanRoot.hh | 28 + rce/rcecalib/scanctrl/SelftriggerSetup.cc | 37 + rce/rcecalib/scanctrl/SelftriggerSetup.hh | 18 + rce/rcecalib/scanctrl/SendTriggerAction.hh | 19 + rce/rcecalib/scanctrl/SetChannelMaskAction.hh | 18 + rce/rcecalib/scanctrl/SetupMaskStageAction.hh | 52 + rce/rcecalib/scanctrl/SetupParamAction.hh | 45 + rce/rcecalib/scanctrl/SetupTriggerAction.hh | 53 + rce/rcecalib/scanctrl/constituents.mk | 45 + rce/rcecalib/server/.gitignore | 1 + rce/rcecalib/server/AFPHPTDCConfigFile.cc | 566 + rce/rcecalib/server/AFPHPTDCConfigFile.hh | 30 + rce/rcecalib/server/BootLoaderPort.hh | 6 + rce/rcecalib/server/CalibGui.cc | 1856 ++ rce/rcecalib/server/CalibGui.hh | 145 + rce/rcecalib/server/CallbackInfo.cc | 51 + rce/rcecalib/server/CallbackInfo.hh | 20 + rce/rcecalib/server/CmdDecoder.cc | 174 + rce/rcecalib/server/CmdDecoder.hh | 41 + rce/rcecalib/server/ConfigGui.cc | 498 + rce/rcecalib/server/ConfigGui.hh | 93 + rce/rcecalib/server/CosmicDataReceiver.cc | 268 + rce/rcecalib/server/CosmicDataReceiver.hh | 45 + rce/rcecalib/server/CosmicGui.cc | 1373 ++ rce/rcecalib/server/CosmicGui.hh | 108 + rce/rcecalib/server/CosmicMonitoringGui.cc | 97 + rce/rcecalib/server/CosmicMonitoringGui.hh | 28 + .../server/CosmicMonitoringGuiEmbedded.cc | 1297 ++ .../server/CosmicMonitoringGuiEmbedded.hh | 140 + rce/rcecalib/server/CosmicOfflineDataProc.cc | 378 + rce/rcecalib/server/CosmicOfflineDataProc.hh | 57 + rce/rcecalib/server/DataExporter.cc | 117 + rce/rcecalib/server/DataExporter.hh | 23 + rce/rcecalib/server/EthPrimitive.cc | 65 + rce/rcecalib/server/EthPrimitive.hh | 33 + rce/rcecalib/server/FEI4AConfigFile.cc | 737 + rce/rcecalib/server/FEI4AConfigFile.hh | 32 + rce/rcecalib/server/FEI4BConfigFile.cc | 772 + rce/rcecalib/server/FEI4BConfigFile.hh | 32 + rce/rcecalib/server/GlobalConfigGui.cc | 560 + rce/rcecalib/server/GlobalConfigGui.hh | 71 + rce/rcecalib/server/HitbusConfigFile.cc | 146 + rce/rcecalib/server/HitbusConfigFile.hh | 25 + rce/rcecalib/server/IPCCallback.hh | 20 + rce/rcecalib/server/IPCController.cc | 975 + rce/rcecalib/server/IPCController.hh | 70 + rce/rcecalib/server/IPCGuiCallback.cc | 29 + rce/rcecalib/server/IPCGuiCallback.hh | 18 + rce/rcecalib/server/IPCHistoController.cc | 207 + rce/rcecalib/server/IPCHistoController.hh | 30 + rce/rcecalib/server/IPCRegularCallback.cc | 19 + rce/rcecalib/server/IPCRegularCallback.hh | 13 + rce/rcecalib/server/Makefile | 29 + rce/rcecalib/server/Mean.hh | 28 + rce/rcecalib/server/PixScan.cc | 851 + rce/rcecalib/server/PixScan.hh | 216 + rce/rcecalib/server/PrimList.cc | 119 + rce/rcecalib/server/PrimList.hh | 69 + rce/rcecalib/server/PrimListGui.cc | 572 + rce/rcecalib/server/PrimListGui.hh | 83 + rce/rcecalib/server/RceControl.cc | 123 + rce/rcecalib/server/RceControl.hh | 34 + rce/rcecalib/server/RceOfflineProducer.cc | 380 + rce/rcecalib/server/RceOfflineProducer.hh | 38 + rce/rcecalib/server/RceProducer.cc | 217 + rce/rcecalib/server/RceProducer.hh | 29 + rce/rcecalib/server/ScanGui.cc | 276 + rce/rcecalib/server/ScanGui.hh | 57 + rce/rcecalib/server/ScanLog.cc | 316 + rce/rcecalib/server/ScanLog.hh | 51 + rce/rcecalib/server/StandardStream.o | Bin 0 -> 1165544 bytes rce/rcecalib/server/ThrottleStream.o | Bin 0 -> 660216 bytes rce/rcecalib/server/TurboDaqFile.cc | 914 + rce/rcecalib/server/TurboDaqFile.hh | 34 + rce/rcecalib/server/atlasimage.hh | 364 + rce/rcecalib/server/bootloader.cc | 201 + rce/rcecalib/server/bootloader_2.2.cc | 130 + rce/rcecalib/server/calibGui_Linkdef.hh | 5 + rce/rcecalib/server/calibclient.cc | 321 + rce/rcecalib/server/calibserver.cc | 146 + rce/rcecalib/server/calibserver.hh | 12 + rce/rcecalib/server/constituents.mk | 820 + rce/rcecalib/server/cosmicGui_Linkdef.hh | 4 + .../server/cosmicMonitoringGui_Linkdef.hh | 4 + rce/rcecalib/server/delaycalib.cc | 132 + rce/rcecalib/server/dumpRceMod.cc | 46 + rce/rcecalib/server/dumpRceScan.cc | 53 + rce/rcecalib/server/ettcp.c | 922 + rce/rcecalib/server/eudaqserver.cc | 124 + rce/rcecalib/server/eudaqserver.hh | 11 + rce/rcecalib/server/host_bootloader.cc | 81 + .../server/rceOfflineProducer_Linkdef.hh | 2 + rce/rcecalib/server/rebootHSIO.cc | 82 + rce/rcecalib/server/rtems_config.cc | 68 + rce/rcecalib/server/rtems_config_2.2.cc | 127 + rce/rcecalib/server/runeudaqserver.cc | 125 + rce/rcecalib/server/runeudaqservermod.cc | 106 + rce/rcecalib/server/runserver.cc | 127 + rce/rcecalib/server/runservermod.cc | 117 + rce/rcecalib/server/sendBitStream.cc | 604 + rce/rcecalib/server/sendRandomPattern.cc | 60 + rce/rcecalib/server/tdccalib.cc | 209 + rce/rcecalib/server/test_client.cc | 756 + rce/rcecalib/server/test_scan_client.cc | 244 + rce/rcecalib/server/test_server.cc | 113 + rce/rcecalib/util/AbsRceHisto.cc | 24 + rce/rcecalib/util/AbsRceHisto.hh | 31 + rce/rcecalib/util/DataCond.hh | 14 + rce/rcecalib/util/IPCHistoManager.cc | 70 + rce/rcecalib/util/IPCHistoManager.hh | 35 + rce/rcecalib/util/Makefile | 20 + rce/rcecalib/util/RceHisto1d.cc | 181 + rce/rcecalib/util/RceHisto1d.hh | 35 + rce/rcecalib/util/RceHisto2d.cc | 223 + rce/rcecalib/util/RceHisto2d.hh | 38 + rce/rcecalib/util/RceMath.cc | 41 + rce/rcecalib/util/RceMath.hh | 13 + rce/rcecalib/util/RceName.cc | 20 + rce/rcecalib/util/RceName.hh | 14 + rce/rcecalib/util/VerifyErrors.hh | 11 + rce/rcecalib/util/constituents.mk | 28 + rce/rcecalib/util/exceptions.hh | 33 + rce/rcecalib/xmd.ini | 1 + rce/scripts/cmake_script | 3 + rce/scripts/dumpscans | 22 + rce/scripts/findUndefSymbols.pl | 38 + rce/scripts/patch.links | 7 + rce/scripts/rce_dow | 8 + rce/scripts/rce_dow.ex | 18 + rce/scripts/setup-gen3.sh | 38 +- rce/scripts/setup_rce-04-00-00.csh | 148 + rce/scripts/setup_rce-04-00-01.csh | 126 + rce/scripts/setup_rce-04-00-01.sh | 114 + rce/scripts/setup_rce-04-00-01_rceG1.csh | 131 + rce/scripts/setup_rce.csh | 147 + rce/scripts/setup_rce.sh | 183 + 924 files changed, 209794 insertions(+), 20 deletions(-) create mode 100644 rce/Makefile create mode 100644 rce/Makefile.inc create mode 100644 rce/Makefile_nonparallel create mode 100644 rce/fw-hsio/.gitignore create mode 100644 rce/fw-hsio/Readme.txt create mode 100644 rce/fw-hsio/modules/pgp/coregen/pgp_adder_16_16.xco create mode 100644 rce/fw-hsio/modules/pgp/coregen/pgp_afifo_20x511.xco create mode 100644 rce/fw-hsio/modules/pgp/coregen/pgp_dpram_51x256.xco create mode 100644 rce/fw-hsio/modules/pgp/coregen/pgp_fifo_20x512.xco create mode 100644 rce/fw-hsio/modules/pgp/coregen/pgp_fifo_21x512.xco create mode 100644 rce/fw-hsio/modules/pgp/coregen/pgp_fifo_8x256.xco create mode 100644 rce/fw-hsio/modules/pgp/coregen/pgp_fifo_9x256.xco create mode 100644 rce/fw-hsio/modules/pgp/hdl/PgpAckRx.vhd create mode 100755 rce/fw-hsio/modules/pgp/hdl/PgpCellRx.vhd create mode 100644 rce/fw-hsio/modules/pgp/hdl/PgpCellTx.vhd create mode 100755 rce/fw-hsio/modules/pgp/hdl/PgpClkGen.vhd create mode 100644 rce/fw-hsio/modules/pgp/hdl/PgpCmdSlave.vhd create mode 100755 rce/fw-hsio/modules/pgp/hdl/PgpDataBuffer.vhd create mode 100644 rce/fw-hsio/modules/pgp/hdl/PgpDsBuff.vhd create mode 100755 rce/fw-hsio/modules/pgp/hdl/PgpFrontEnd.vhd create mode 100755 rce/fw-hsio/modules/pgp/hdl/PgpMgtWrap.vhd create mode 100755 rce/fw-hsio/modules/pgp/hdl/PgpPhy.vhd create mode 100755 rce/fw-hsio/modules/pgp/hdl/PgpPicRemBuff.vhd create mode 100755 rce/fw-hsio/modules/pgp/hdl/PgpRegSlave.vhd create mode 100755 rce/fw-hsio/modules/pgp/hdl/PgpRxTrack.vhd create mode 100755 rce/fw-hsio/modules/pgp/hdl/PgpTop.vhd create mode 100644 rce/fw-hsio/modules/pgp/hdl/PgpTxSched.vhd create mode 100644 rce/fw-hsio/modules/pgp/hdl/PgpVersion.vhd create mode 100644 rce/fw-hsio/modules/pgp2/coregen/pgp2_v4_afifo_18x1023.xco create mode 100644 rce/fw-hsio/modules/pgp2/coregen/pgp2_v4_fifo_69x512.xco create mode 100644 rce/fw-hsio/modules/pgp2/coregen/pgp2_v4_icon.xco create mode 100644 rce/fw-hsio/modules/pgp2/coregen/pgp2_v4_ila.xco create mode 100644 rce/fw-hsio/modules/pgp2/coregen/pgp2_v4_vio.xco create mode 100644 rce/fw-hsio/modules/pgp2/coregen/pgp2_v5_afifo_18x1023.xco create mode 100755 rce/fw-hsio/modules/pgp2/hdl/applications/Pgp2AppPackage.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/applications/Pgp2CmdSlave.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/applications/Pgp2DsBuff.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/applications/Pgp2RegSlave.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/applications/Pgp2UsBuff.vhd create mode 100644 rce/fw-hsio/modules/pgp2/hdl/applications/PgpDsBuff.vhd create mode 100644 rce/fw-hsio/modules/pgp2/hdl/applications/PgpFrontEnd.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/core/Pgp2CorePackage.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/core/Pgp2Rx.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/core/Pgp2RxCell.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/core/Pgp2RxPhy.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/core/Pgp2Tx.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/core/Pgp2TxCell.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/core/Pgp2TxPhy.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/core/Pgp2TxSched.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2Gtp16.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2Gtp32.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2GtpClk.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2GtpDual.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2GtpPackage.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2GtpRxRst.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2GtpTxRst.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2Gtx16.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2Gtx16B.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2GtxClk.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2GtxDual.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2GtxPackage.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2GtxRxRst.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2GtxTxRst.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2Mgt16.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2Mgt32.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2Mgt64.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2MgtClk.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2MgtPackage.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2MgtRxRst.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2MgtTxRst.vhd create mode 100644 rce/fw-hsio/modules/pgp2/hdl/mgt/PgpClkGen.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/rce/Pgp2Rce.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/rce/Pgp2RceExport.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/rce/Pgp2RceImport.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/rce/Pgp2RceLane.vhd create mode 100755 rce/fw-hsio/modules/pgp2/hdl/rce/Pgp2RcePackage.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/coregen/data24bitfifo4096.xco create mode 100644 rce/fw-hsio/modules/pixelcore/coregen/data24bitfifo8192.xco create mode 100644 rce/fw-hsio/modules/pixelcore/coregen/datafifo1024.xco create mode 100644 rce/fw-hsio/modules/pixelcore/coregen/datafifo131072.xco create mode 100644 rce/fw-hsio/modules/pixelcore/coregen/datafifo16384.xco create mode 100644 rce/fw-hsio/modules/pixelcore/coregen/datafifo32768.xco create mode 100644 rce/fw-hsio/modules/pixelcore/coregen/datafifo4096.xco create mode 100644 rce/fw-hsio/modules/pixelcore/coregen/datafifo8192.xco create mode 100644 rce/fw-hsio/modules/pixelcore/coregen/dataflagfifo.xco create mode 100644 rce/fw-hsio/modules/pixelcore/coregen/eofcounter.xco create mode 100644 rce/fw-hsio/modules/pixelcore/coregen/pattern_blk_mem.ngc create mode 100644 rce/fw-hsio/modules/pixelcore/coregen/pattern_blk_mem.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/coregen/pattern_blk_mem.vho create mode 100644 rce/fw-hsio/modules/pixelcore/coregen/pattern_blk_mem.xco-outdated create mode 100644 rce/fw-hsio/modules/pixelcore/coregen/triggerfifo.xco create mode 100644 rce/fw-hsio/modules/pixelcore/coregen/xil_cores.cgp create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/BiphaseMarkEncoder.vhd create mode 100755 rce/fw-hsio/modules/pixelcore/hdl/DisplayCharacters.vhd create mode 100755 rce/fw-hsio/modules/pixelcore/hdl/DisplayControl.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/HsioPixelCore.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/I2cMaster.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/I2cPkg.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/I2cRegMaster.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/OutputEncoder.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/StdRtlPkg.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/adcreadout.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/arraytype.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/clock160.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/clock200.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/coincidence.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/datafifo.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/dataflag.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/dataflagff.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/dataflagnew.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/dec.mif create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_bram.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_disp.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_lut.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_lut_base.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_pkg.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_rtl.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_top.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_wrapper.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/decodefei4record.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/deser.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/deser10b.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/deser4b.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/encodepgp.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/encodepgp24bit.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/eofcounter.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/eudaqTrigger.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/framealign.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/framealignhitbus.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/hitbuspipeline.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/i2c_master_bit_ctrl.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/i2c_master_byte_ctrl.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/lookaheadfifo.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/multiplexdata.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/multiplexdataopt.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/multiplexdatapgp2.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/phaseshift.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/ser.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/ser32.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/stdlib.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/syncdatac.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/tdc.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/tdcreadout.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/tempadc.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/triggerlogic.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/triggerpipeline.vhd create mode 100644 rce/fw-hsio/modules/pixelcore/hdl/wordswapper.vhd create mode 100644 rce/fw-hsio/projects/HsioCosmic/Makefile create mode 100644 rce/fw-hsio/projects/HsioCosmic/Readme.txt create mode 100644 rce/fw-hsio/projects/HsioCosmic/Version.vhd create mode 100755 rce/fw-hsio/projects/HsioCosmic/config/bitgen_options.txt create mode 100755 rce/fw-hsio/projects/HsioCosmic/config/map_options.txt create mode 100755 rce/fw-hsio/projects/HsioCosmic/config/ngdbuild_options.txt create mode 100755 rce/fw-hsio/projects/HsioCosmic/config/par_options.txt create mode 100755 rce/fw-hsio/projects/HsioCosmic/config/promgen_options.txt create mode 120000 rce/fw-hsio/projects/HsioCosmic/config/sources.txt create mode 100644 rce/fw-hsio/projects/HsioCosmic/config/sources_pgp1.txt create mode 100644 rce/fw-hsio/projects/HsioCosmic/config/sources_pgp2.txt create mode 100755 rce/fw-hsio/projects/HsioCosmic/config/trce_options.txt create mode 100644 rce/fw-hsio/projects/HsioCosmic/config/xst_options.txt create mode 120000 rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf create mode 100644 rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf.2core create mode 100644 rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf.4core create mode 100644 rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf.RJ45.oldHSIO create mode 100644 rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf.fei3 create mode 100644 rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf.full create mode 100644 rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf.oldCosmic create mode 120000 rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd create mode 100755 rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd.2core create mode 100755 rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd.4core create mode 100755 rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd.fei3 create mode 100755 rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd.multicore create mode 100644 rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd.oldCosmic create mode 100755 rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd.regular create mode 100644 rce/fw-hsio/projects/HsioCosmic/images/.gitignore create mode 100644 rce/fw-hsio/projects/HsioStave0/Makefile create mode 100644 rce/fw-hsio/projects/HsioStave0/Readme.txt create mode 100644 rce/fw-hsio/projects/HsioStave0/Version.vhd create mode 100755 rce/fw-hsio/projects/HsioStave0/config/bitgen_options.txt create mode 100755 rce/fw-hsio/projects/HsioStave0/config/map_options.txt create mode 100755 rce/fw-hsio/projects/HsioStave0/config/ngdbuild_options.txt create mode 100755 rce/fw-hsio/projects/HsioStave0/config/par_options.txt create mode 100755 rce/fw-hsio/projects/HsioStave0/config/promgen_options.txt create mode 120000 rce/fw-hsio/projects/HsioStave0/config/sources.txt create mode 100644 rce/fw-hsio/projects/HsioStave0/config/sources_pgp1.txt create mode 100644 rce/fw-hsio/projects/HsioStave0/config/sources_pgp2.txt create mode 100755 rce/fw-hsio/projects/HsioStave0/config/trce_options.txt create mode 100644 rce/fw-hsio/projects/HsioStave0/config/xst_options.txt create mode 120000 rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.ucf create mode 100644 rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.ucf.dbm_nonrotated create mode 100644 rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.ucf.full create mode 100644 rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.ucf.opto.ibl create mode 100644 rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.ucf.opto.nsqp.flipped create mode 100644 rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.ucf.rotated create mode 100755 rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.vhd create mode 100644 rce/fw-hsio/projects/HsioStave0/images/.gitignore create mode 100644 rce/fw-hsio/projects/IBLcableTester/Makefile create mode 100644 rce/fw-hsio/projects/IBLcableTester/Readme.txt create mode 100644 rce/fw-hsio/projects/IBLcableTester/Version.vhd create mode 100755 rce/fw-hsio/projects/IBLcableTester/config/bitgen_options.txt create mode 100755 rce/fw-hsio/projects/IBLcableTester/config/map_options.txt create mode 100755 rce/fw-hsio/projects/IBLcableTester/config/ngdbuild_options.txt create mode 100755 rce/fw-hsio/projects/IBLcableTester/config/par_options.txt create mode 100755 rce/fw-hsio/projects/IBLcableTester/config/promgen_options.txt create mode 100644 rce/fw-hsio/projects/IBLcableTester/config/sources.txt create mode 100755 rce/fw-hsio/projects/IBLcableTester/config/trce_options.txt create mode 100644 rce/fw-hsio/projects/IBLcableTester/config/xst_options.txt create mode 100644 rce/fw-hsio/projects/IBLcableTester/coregen/counter30.xco create mode 100644 rce/fw-hsio/projects/IBLcableTester/coregen/counter30_c_counter_binary_v8_0_xst_1.ngc_xst.xrpt create mode 100644 rce/fw-hsio/projects/IBLcableTester/coregen/counter30_xmdf.tcl create mode 100644 rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo.xco create mode 100644 rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_fifo_generator_v4_4_xst_1.ngc_xst.xrpt create mode 100755 rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/example_design/iblfifo_top.ucf create mode 100755 rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/example_design/iblfifo_top.vhd create mode 100755 rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/example_design/iblfifo_top.xdc create mode 100755 rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/implement.bat create mode 100755 rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/implement.sh create mode 100755 rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/planAhead_rdn.bat create mode 100755 rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/planAhead_rdn.sh create mode 100755 rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/planAhead_rdn.tcl create mode 100755 rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/xst.prj create mode 100755 rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/xst.scr create mode 100644 rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_upgrade.txt create mode 100644 rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_xmdf.tcl create mode 100644 rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem.ngc create mode 100644 rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem.vhd create mode 100644 rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem.vho create mode 100644 rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem.xco create mode 100644 rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem_blk_mem_gen_v2_8_xst_1.ngc_xst.xrpt create mode 100644 rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem_flist.txt create mode 100644 rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem_readme.txt create mode 100644 rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem_xmdf.tcl create mode 100644 rce/fw-hsio/projects/IBLcableTester/coregen/wordcounter.xco create mode 100644 rce/fw-hsio/projects/IBLcableTester/coregen/wordcounter_blk_mem_gen_v2_8_xst_1.ngc_xst.xrpt create mode 100644 rce/fw-hsio/projects/IBLcableTester/coregen/wordcounter_xmdf.tcl create mode 120000 rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTester.ucf create mode 100644 rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTester.ucf.cable.newHSIO create mode 100644 rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTester.ucf.cable.oldHSIO create mode 100644 rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTester.ucf.iblbert create mode 100755 rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTester.vhd create mode 100644 rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTesterCore.vhd create mode 100644 rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTesterCoreOld.vhd create mode 100755 rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTesterOld.vhd create mode 100644 rce/fw-hsio/projects/IBLcableTester/hdl/deser.vhd create mode 100644 rce/fw-hsio/projects/IBLcableTester/hdl/deser16.vhd create mode 100644 rce/fw-hsio/projects/IBLcableTester/hdl/pattern_cmd.vhd create mode 100644 rce/fw-hsio/projects/IBLcableTester/hdl/pattern_mem.vhd create mode 100644 rce/fw-hsio/projects/IBLcableTester/hdl/pattern_memOld.vhd create mode 100644 rce/fw-hsio/projects/IBLcableTester/hdl/phaseshift.vhd create mode 100644 rce/fw-hsio/projects/IBLcableTester/hdl/ser.vhd create mode 100644 rce/fw-hsio/projects/IBLcableTester/hdl/serbiphase.vhd create mode 100644 rce/fw-hsio/system.mk create mode 100644 rce/make/hw/Makefile.package.template create mode 100644 rce/make/hw/constituents.mk.template create mode 100644 rce/make/hw/flags.mk create mode 100644 rce/make/hw/flags.mk.template create mode 100755 rce/make/hw/optgen.py create mode 100644 rce/make/hw/package.mk create mode 100755 rce/make/hw/prjgen.py create mode 100755 rce/make/hw/tclgen.py create mode 100644 rce/make/share/Makefile.project.template create mode 100644 rce/make/share/packages.mk.template create mode 100644 rce/make/share/premake.mk create mode 100644 rce/make/share/project.mk create mode 100644 rce/make/share/release.mk create mode 100644 rce/make/share/setup.mk create mode 100644 rce/make/sw/Makefile.package.template create mode 100644 rce/make/sw/constituents.mk.template create mode 100644 rce/make/sw/flags.mk create mode 100644 rce/make/sw/flags.mk.template create mode 100644 rce/make/sw/idl.mk create mode 100644 rce/make/sw/package.mk create mode 100644 rce/make/sw/python.mk create mode 100644 rce/make/sw/qt.mk create mode 100644 rce/make/sw/rootcint.mk create mode 100644 rce/make/tools/options.py create mode 100755 rce/make/tools/pkgcreate.py create mode 100755 rce/make/tools/prjupdate.py create mode 100755 rce/make/tools/replace.pl create mode 100644 rce/pixelrce/config/FEI3/IPCModule.cc create mode 100644 rce/pixelrce/config/FEI3/IPCModule.hh create mode 100644 rce/pixelrce/config/FEI4/IPCFEI4AModule.cc create mode 100644 rce/pixelrce/config/FEI4/IPCFEI4AModule.hh create mode 100644 rce/pixelrce/config/FEI4/IPCFEI4BModule.cc create mode 100644 rce/pixelrce/config/FEI4/IPCFEI4BModule.hh create mode 100644 rce/pixelrce/config/IPCConfigIF.cc create mode 100644 rce/pixelrce/config/IPCConfigIF.hh create mode 100644 rce/pixelrce/config/IPCModuleFactory.cc create mode 100644 rce/pixelrce/config/IPCModuleFactory.hh create mode 100644 rce/pixelrce/config/afp-hptdc/IPCModule.cc create mode 100644 rce/pixelrce/config/afp-hptdc/IPCModule.hh create mode 100644 rce/pixelrce/config/hitbus/IPCModule.cc create mode 100644 rce/pixelrce/config/hitbus/IPCModule.hh create mode 100644 rce/pixelrce/idl/IPCAFPHPTDCAdapter.idl create mode 100644 rce/pixelrce/idl/IPCConfigIFAdapter.idl create mode 100644 rce/pixelrce/idl/IPCFEI3Adapter.idl create mode 100644 rce/pixelrce/idl/IPCFEI4AAdapter.idl create mode 100644 rce/pixelrce/idl/IPCFEI4BAdapter.idl create mode 100644 rce/pixelrce/idl/IPCHitbusAdapter.idl create mode 100644 rce/pixelrce/idl/IPCScanAdapter.idl create mode 100644 rce/pixelrce/idl/IPCScanRootAdapter.idl create mode 100644 rce/pixelrce/scanctrl/IPCRceCallback.cc create mode 100644 rce/pixelrce/scanctrl/IPCRceCallback.hh create mode 100644 rce/pixelrce/scanctrl/IPCScan.cc create mode 100644 rce/pixelrce/scanctrl/IPCScan.hh create mode 100644 rce/pixelrce/scanctrl/IPCScanRoot.cc create mode 100644 rce/pixelrce/scanctrl/IPCScanRoot.hh create mode 100644 rce/pixelrce/server/IPCCalibGui.cc create mode 100644 rce/pixelrce/server/IPCCallback.hh create mode 100644 rce/pixelrce/server/IPCController.cc create mode 100644 rce/pixelrce/server/IPCController.hh create mode 100644 rce/pixelrce/server/IPCCosmicGui.cc create mode 100644 rce/pixelrce/server/IPCGuiCallback.cc create mode 100644 rce/pixelrce/server/IPCGuiCallback.hh create mode 100644 rce/pixelrce/server/IPCHistoController.cc create mode 100644 rce/pixelrce/server/IPCHistoController.hh create mode 100644 rce/pixelrce/server/IPCRceOfflineProducer.cc create mode 100644 rce/pixelrce/server/IPCRegularCallback.cc create mode 100644 rce/pixelrce/server/IPCRegularCallback.hh create mode 100644 rce/pixelrce/server/IPClinux_server_pgp.cc create mode 100644 rce/pixelrce/server/IPCrebootHSIO.cc create mode 100644 rce/pixelrce/util/IPCProvider.hh create mode 100644 rce/pixelrce/util/IPCProvider.i create mode 100644 rce/projects.mk create mode 100644 rce/rcecalib/HW/BitStream.hh create mode 100644 rce/rcecalib/HW/Headers.hh create mode 100644 rce/rcecalib/HW/Makefile create mode 100644 rce/rcecalib/HW/RCDImaster.cc create mode 100644 rce/rcecalib/HW/RCDImaster.hh create mode 100644 rce/rcecalib/HW/Receiver.hh create mode 100644 rce/rcecalib/HW/SerialHexdump.cc create mode 100644 rce/rcecalib/HW/SerialHexdump.hh create mode 100644 rce/rcecalib/HW/SerialIF.cc create mode 100644 rce/rcecalib/HW/SerialIF.hh create mode 100644 rce/rcecalib/HW/SerialPgp.cc create mode 100644 rce/rcecalib/HW/SerialPgp.hh create mode 100644 rce/rcecalib/HW/SerialPgpBw.cc create mode 100644 rce/rcecalib/HW/SerialPgpBw.hh create mode 100644 rce/rcecalib/HW/SerialPgpFei4.cc create mode 100644 rce/rcecalib/HW/SerialPgpFei4.hh create mode 100644 rce/rcecalib/HW/constituents.mk create mode 100644 rce/rcecalib/Makefile create mode 100644 rce/rcecalib/analysis/AnalysisFactory.cc create mode 100644 rce/rcecalib/analysis/AnalysisFactory.hh create mode 100644 rce/rcecalib/analysis/AnalysisGui.cc create mode 100644 rce/rcecalib/analysis/AnalysisGui.hh create mode 100644 rce/rcecalib/analysis/CalibAnalysis.cc create mode 100644 rce/rcecalib/analysis/CalibAnalysis.hh create mode 100644 rce/rcecalib/analysis/CfgFileWriter.cc create mode 100644 rce/rcecalib/analysis/CfgFileWriter.hh create mode 100644 rce/rcecalib/analysis/CrosstalkAnalysis.cc create mode 100644 rce/rcecalib/analysis/CrosstalkAnalysis.hh create mode 100644 rce/rcecalib/analysis/DigitalTestAnalysis.cc create mode 100644 rce/rcecalib/analysis/DigitalTestAnalysis.hh create mode 100644 rce/rcecalib/analysis/Fdac_Analysis.cc create mode 100644 rce/rcecalib/analysis/Fdac_Analysis.hh create mode 100644 rce/rcecalib/analysis/Fei3CfgFileWriter.cc create mode 100644 rce/rcecalib/analysis/Fei3CfgFileWriter.hh create mode 100644 rce/rcecalib/analysis/Fei4CfgFileWriter.cc create mode 100644 rce/rcecalib/analysis/Fei4CfgFileWriter.hh create mode 100644 rce/rcecalib/analysis/GdacAnalysis.cc create mode 100644 rce/rcecalib/analysis/GdacAnalysis.hh create mode 100644 rce/rcecalib/analysis/GdacCoarseFastAnalysis.cc create mode 100644 rce/rcecalib/analysis/GdacCoarseFastAnalysis.hh create mode 100644 rce/rcecalib/analysis/GdacFastAnalysis.cc create mode 100644 rce/rcecalib/analysis/GdacFastAnalysis.hh create mode 100644 rce/rcecalib/analysis/HistoViewerGui.cc create mode 100644 rce/rcecalib/analysis/HistoViewerGui.hh create mode 100644 rce/rcecalib/analysis/Iff_Analysis.cc create mode 100644 rce/rcecalib/analysis/Iff_Analysis.hh create mode 100644 rce/rcecalib/analysis/Makefile create mode 100644 rce/rcecalib/analysis/MergeMaskFilesFei4.cc create mode 100644 rce/rcecalib/analysis/ModuleCrosstalkAnalysis.cc create mode 100644 rce/rcecalib/analysis/ModuleCrosstalkAnalysis.hh create mode 100644 rce/rcecalib/analysis/MultiTrigAnalysis.cc create mode 100644 rce/rcecalib/analysis/MultiTrigAnalysis.hh create mode 100644 rce/rcecalib/analysis/MultiTrigNoiseAnalysis.cc create mode 100644 rce/rcecalib/analysis/MultiTrigNoiseAnalysis.hh create mode 100644 rce/rcecalib/analysis/NoiseAnalysis.cc create mode 100644 rce/rcecalib/analysis/NoiseAnalysis.hh create mode 100644 rce/rcecalib/analysis/OffsetAnalysis.cc create mode 100644 rce/rcecalib/analysis/OffsetAnalysis.hh create mode 100644 rce/rcecalib/analysis/RegisterTestAnalysis.cc create mode 100644 rce/rcecalib/analysis/RegisterTestAnalysis.hh create mode 100644 rce/rcecalib/analysis/SerialNumberAnalysis.cc create mode 100644 rce/rcecalib/analysis/SerialNumberAnalysis.hh create mode 100644 rce/rcecalib/analysis/StuckPixelAnalysis.cc create mode 100644 rce/rcecalib/analysis/StuckPixelAnalysis.hh create mode 100644 rce/rcecalib/analysis/T0Analysis.cc create mode 100644 rce/rcecalib/analysis/T0Analysis.hh create mode 100644 rce/rcecalib/analysis/TdacAnalysis.cc create mode 100644 rce/rcecalib/analysis/TdacAnalysis.hh create mode 100644 rce/rcecalib/analysis/TdacFastAnalysis.cc create mode 100644 rce/rcecalib/analysis/TdacFastAnalysis.hh create mode 100644 rce/rcecalib/analysis/TemperatureAnalysis.cc create mode 100644 rce/rcecalib/analysis/TemperatureAnalysis.hh create mode 100644 rce/rcecalib/analysis/ThresholdAnalysis.cc create mode 100644 rce/rcecalib/analysis/ThresholdAnalysis.hh create mode 100644 rce/rcecalib/analysis/TimeWalkAnalysis.cc create mode 100644 rce/rcecalib/analysis/TimeWalkAnalysis.hh create mode 100644 rce/rcecalib/analysis/TotAnalysis.cc create mode 100644 rce/rcecalib/analysis/TotAnalysis.hh create mode 100644 rce/rcecalib/analysis/TotCalibAnalysis.cc create mode 100644 rce/rcecalib/analysis/TotCalibAnalysis.hh create mode 100644 rce/rcecalib/analysis/analysisGui_Linkdef.hh create mode 100644 rce/rcecalib/analysis/constituents.mk create mode 100644 rce/rcecalib/analysis/histoViewer_Linkdef.hh create mode 100644 rce/rcecalib/analysis/tdacScanAnalysis.cc create mode 100644 rce/rcecalib/analysis/tdacScanAnalysis.hh create mode 100644 rce/rcecalib/config/AbsFormatter.hh create mode 100644 rce/rcecalib/config/AbsModule.hh create mode 100644 rce/rcecalib/config/AbsModuleGroup.cc create mode 100644 rce/rcecalib/config/AbsModuleGroup.hh create mode 100644 rce/rcecalib/config/AbsTrigger.cc create mode 100644 rce/rcecalib/config/AbsTrigger.hh create mode 100644 rce/rcecalib/config/BFU.hh create mode 100644 rce/rcecalib/config/ConfigIF.cc create mode 100644 rce/rcecalib/config/ConfigIF.hh create mode 100644 rce/rcecalib/config/DummyFormatter.cc create mode 100644 rce/rcecalib/config/DummyFormatter.hh create mode 100644 rce/rcecalib/config/Endianness.hh create mode 100644 rce/rcecalib/config/EventFromDspTrigger.cc create mode 100644 rce/rcecalib/config/EventFromDspTrigger.hh create mode 100644 rce/rcecalib/config/EventFromFileTrigger.cc create mode 100644 rce/rcecalib/config/EventFromFileTrigger.hh create mode 100644 rce/rcecalib/config/FEI3/CrosstalkMaskStaging.cc create mode 100644 rce/rcecalib/config/FEI3/CrosstalkMaskStaging.hh create mode 100644 rce/rcecalib/config/FEI3/FECommands.cc create mode 100644 rce/rcecalib/config/FEI3/FECommands.hh create mode 100644 rce/rcecalib/config/FEI3/Frontend.cc create mode 100644 rce/rcecalib/config/FEI3/Frontend.hh create mode 100644 rce/rcecalib/config/FEI3/GlobalRegister.cc create mode 100644 rce/rcecalib/config/FEI3/GlobalRegister.hh create mode 100644 rce/rcecalib/config/FEI3/IPCModule.cc create mode 100644 rce/rcecalib/config/FEI3/IPCModule.hh create mode 100644 rce/rcecalib/config/FEI3/JJFormatter.cc create mode 100644 rce/rcecalib/config/FEI3/JJFormatter.hh create mode 100644 rce/rcecalib/config/FEI3/MaskStageFactory.cc create mode 100644 rce/rcecalib/config/FEI3/MaskStaging.cc create mode 100644 rce/rcecalib/config/FEI3/Mcc.cc create mode 100644 rce/rcecalib/config/FEI3/Mcc.hh create mode 100644 rce/rcecalib/config/FEI3/Module.cc create mode 100644 rce/rcecalib/config/FEI3/Module.hh create mode 100644 rce/rcecalib/config/FEI3/ModuleGroup.cc create mode 100644 rce/rcecalib/config/FEI3/ModuleGroup.hh create mode 100644 rce/rcecalib/config/FEI3/PixelRegister.cc create mode 100644 rce/rcecalib/config/FEI3/PixelRegister.hh create mode 100644 rce/rcecalib/config/FEI3/RegularMaskStaging.cc create mode 100644 rce/rcecalib/config/FEI3/RegularMaskStaging.hh create mode 100644 rce/rcecalib/config/FEI4/AnalogColpr2MaskStagingFei4a.cc create mode 100644 rce/rcecalib/config/FEI4/AnalogColpr2MaskStagingFei4a.hh create mode 100644 rce/rcecalib/config/FEI4/AnalogColprMaskStaging.cc create mode 100644 rce/rcecalib/config/FEI4/AnalogColprMaskStaging.hh create mode 100644 rce/rcecalib/config/FEI4/AnalogMaskStaging.cc create mode 100644 rce/rcecalib/config/FEI4/AnalogMaskStaging.hh create mode 100644 rce/rcecalib/config/FEI4/AnalogSimpleColprMaskStaging.cc create mode 100644 rce/rcecalib/config/FEI4/AnalogSimpleColprMaskStaging.hh create mode 100644 rce/rcecalib/config/FEI4/AnalogSingleMaskStaging.cc create mode 100644 rce/rcecalib/config/FEI4/AnalogSingleMaskStaging.hh create mode 100644 rce/rcecalib/config/FEI4/CrosstalkFastMaskStaging.cc create mode 100644 rce/rcecalib/config/FEI4/CrosstalkFastMaskStaging.hh create mode 100644 rce/rcecalib/config/FEI4/CrosstalkMaskStaging.cc create mode 100644 rce/rcecalib/config/FEI4/CrosstalkMaskStaging.hh create mode 100644 rce/rcecalib/config/FEI4/DiffusionMaskStaging.cc create mode 100644 rce/rcecalib/config/FEI4/DiffusionMaskStaging.hh create mode 100644 rce/rcecalib/config/FEI4/DigStepMaskStaging.cc create mode 100644 rce/rcecalib/config/FEI4/DigStepMaskStaging.hh create mode 100644 rce/rcecalib/config/FEI4/DigitalMaskStaging.cc create mode 100644 rce/rcecalib/config/FEI4/DigitalMaskStaging.hh create mode 100644 rce/rcecalib/config/FEI4/FECommands.cc create mode 100644 rce/rcecalib/config/FEI4/FECommands.hh create mode 100644 rce/rcecalib/config/FEI4/FEI4AFormatter.cc create mode 100644 rce/rcecalib/config/FEI4/FEI4AFormatter.hh create mode 100644 rce/rcecalib/config/FEI4/FEI4AGlobalRegister.cc create mode 100644 rce/rcecalib/config/FEI4/FEI4AGlobalRegister.hh create mode 100644 rce/rcecalib/config/FEI4/FEI4AModule.cc create mode 100644 rce/rcecalib/config/FEI4/FEI4AModule.hh create mode 100644 rce/rcecalib/config/FEI4/FEI4ARecord.hh create mode 100644 rce/rcecalib/config/FEI4/FEI4BFormatter.cc create mode 100644 rce/rcecalib/config/FEI4/FEI4BFormatter.hh create mode 100644 rce/rcecalib/config/FEI4/FEI4BGlobalRegister.cc create mode 100644 rce/rcecalib/config/FEI4/FEI4BGlobalRegister.hh create mode 100644 rce/rcecalib/config/FEI4/FEI4BModule.cc create mode 100644 rce/rcecalib/config/FEI4/FEI4BModule.hh create mode 100644 rce/rcecalib/config/FEI4/FEI4BRecord.hh create mode 100644 rce/rcecalib/config/FEI4/FEI4HitorFormatter.cc create mode 100644 rce/rcecalib/config/FEI4/FEI4HitorFormatter.hh create mode 100644 rce/rcecalib/config/FEI4/FEI4OccFormatter.cc create mode 100644 rce/rcecalib/config/FEI4/FEI4OccFormatter.hh create mode 100644 rce/rcecalib/config/FEI4/FastAnalogMaskStaging.cc create mode 100644 rce/rcecalib/config/FEI4/FastAnalogMaskStaging.hh create mode 100644 rce/rcecalib/config/FEI4/Fei4RegisterTestTrigger.cc create mode 100644 rce/rcecalib/config/FEI4/Fei4RegisterTestTrigger.hh create mode 100644 rce/rcecalib/config/FEI4/GlobalRegister.cc create mode 100644 rce/rcecalib/config/FEI4/GlobalRegister.hh create mode 100644 rce/rcecalib/config/FEI4/IPCFEI4AModule.cc create mode 100644 rce/rcecalib/config/FEI4/IPCFEI4AModule.hh create mode 100644 rce/rcecalib/config/FEI4/IPCFEI4BModule.cc create mode 100644 rce/rcecalib/config/FEI4/IPCFEI4BModule.hh create mode 100644 rce/rcecalib/config/FEI4/MaskStageFactory.cc create mode 100644 rce/rcecalib/config/FEI4/MaskStaging.cc create mode 100644 rce/rcecalib/config/FEI4/MaskStaging26880.cc create mode 100644 rce/rcecalib/config/FEI4/MaskStaging26880.hh create mode 100644 rce/rcecalib/config/FEI4/Module.cc create mode 100644 rce/rcecalib/config/FEI4/Module.hh create mode 100644 rce/rcecalib/config/FEI4/ModuleCrosstalkMaskStaging.cc create mode 100644 rce/rcecalib/config/FEI4/ModuleCrosstalkMaskStaging.hh create mode 100644 rce/rcecalib/config/FEI4/ModuleGroup.cc create mode 100644 rce/rcecalib/config/FEI4/ModuleGroup.hh create mode 100644 rce/rcecalib/config/FEI4/MonleakTrigger.cc create mode 100644 rce/rcecalib/config/FEI4/MonleakTrigger.hh create mode 100644 rce/rcecalib/config/FEI4/NoiseMaskStaging.cc create mode 100644 rce/rcecalib/config/FEI4/NoiseMaskStaging.hh create mode 100644 rce/rcecalib/config/FEI4/PatternMaskStaging.cc create mode 100644 rce/rcecalib/config/FEI4/PatternMaskStaging.hh create mode 100644 rce/rcecalib/config/FEI4/PixelRegister.cc create mode 100644 rce/rcecalib/config/FEI4/PixelRegister.hh create mode 100644 rce/rcecalib/config/FEI4/RegisterDef.hh create mode 100644 rce/rcecalib/config/FEI4/SNTrigger.cc create mode 100644 rce/rcecalib/config/FEI4/SNTrigger.hh create mode 100644 rce/rcecalib/config/FEI4/TemperatureTrigger.cc create mode 100644 rce/rcecalib/config/FEI4/TemperatureTrigger.hh create mode 100644 rce/rcecalib/config/FEI4/Utils.hh create mode 100644 rce/rcecalib/config/FormattedRecord.hh create mode 100644 rce/rcecalib/config/HitorTrigger.cc create mode 100644 rce/rcecalib/config/HitorTrigger.hh create mode 100644 rce/rcecalib/config/IPCConfigIF.cc create mode 100644 rce/rcecalib/config/IPCConfigIF.hh create mode 100644 rce/rcecalib/config/IPCModuleFactory.cc create mode 100644 rce/rcecalib/config/IPCModuleFactory.hh create mode 100644 rce/rcecalib/config/Makefile create mode 100644 rce/rcecalib/config/MaskStageFactory.hh create mode 100644 rce/rcecalib/config/MaskStaging.hh create mode 100644 rce/rcecalib/config/Masks.hh create mode 100644 rce/rcecalib/config/MeasurementTrigger.cc create mode 100644 rce/rcecalib/config/MeasurementTrigger.hh create mode 100644 rce/rcecalib/config/ModuleFactory.hh create mode 100644 rce/rcecalib/config/ModuleInfo.hh create mode 100644 rce/rcecalib/config/MultiShotTrigger.cc create mode 100644 rce/rcecalib/config/MultiShotTrigger.hh create mode 100644 rce/rcecalib/config/MultiTrigger.cc create mode 100644 rce/rcecalib/config/MultiTrigger.hh create mode 100644 rce/rcecalib/config/Trigger.cc create mode 100644 rce/rcecalib/config/Trigger.hh create mode 100644 rce/rcecalib/config/TriggerReceiverIF.cc create mode 100644 rce/rcecalib/config/TriggerReceiverIF.hh create mode 100644 rce/rcecalib/config/afp-hptdc/AFPHPTDCFormatter.cc create mode 100644 rce/rcecalib/config/afp-hptdc/AFPHPTDCFormatter.hh create mode 100644 rce/rcecalib/config/afp-hptdc/AFPHPTDCRecord.hh create mode 100644 rce/rcecalib/config/afp-hptdc/IPCModule.cc create mode 100644 rce/rcecalib/config/afp-hptdc/IPCModule.hh create mode 100644 rce/rcecalib/config/afp-hptdc/Module.cc create mode 100644 rce/rcecalib/config/afp-hptdc/Module.hh create mode 100644 rce/rcecalib/config/afp-hptdc/ModuleGroup.cc create mode 100644 rce/rcecalib/config/afp-hptdc/ModuleGroup.hh create mode 100644 rce/rcecalib/config/constituents.mk create mode 100644 rce/rcecalib/config/hitbus/IPCModule.cc create mode 100644 rce/rcecalib/config/hitbus/IPCModule.hh create mode 100644 rce/rcecalib/config/hitbus/Module.cc create mode 100644 rce/rcecalib/config/hitbus/Module.hh create mode 100644 rce/rcecalib/config/hitbus/ModuleGroup.cc create mode 100644 rce/rcecalib/config/hitbus/ModuleGroup.hh create mode 100644 rce/rcecalib/dataproc/AbsDataHandler.hh create mode 100644 rce/rcecalib/dataproc/AbsDataProc.cc create mode 100644 rce/rcecalib/dataproc/AbsDataProc.hh create mode 100644 rce/rcecalib/dataproc/AbsReceiver.hh create mode 100644 rce/rcecalib/dataproc/BcidDataProc.cc create mode 100644 rce/rcecalib/dataproc/BcidDataProc.hh create mode 100644 rce/rcecalib/dataproc/Channeldefs.hh create mode 100644 rce/rcecalib/dataproc/ClusterProc.cc create mode 100644 rce/rcecalib/dataproc/ClusterProc.hh create mode 100644 rce/rcecalib/dataproc/CosmicDataHandler.cc create mode 100644 rce/rcecalib/dataproc/CosmicDataHandler.hh create mode 100644 rce/rcecalib/dataproc/CosmicDataProc.cc create mode 100644 rce/rcecalib/dataproc/CosmicDataProc.hh create mode 100644 rce/rcecalib/dataproc/CosmicEvent.cc create mode 100644 rce/rcecalib/dataproc/CosmicEvent.hh create mode 100644 rce/rcecalib/dataproc/CosmicEventIterator.cc create mode 100644 rce/rcecalib/dataproc/CosmicEventIterator.hh create mode 100644 rce/rcecalib/dataproc/CosmicEventReceiver.hh create mode 100644 rce/rcecalib/dataproc/DataProcFactory.cc create mode 100644 rce/rcecalib/dataproc/DataProcFactory.hh create mode 100644 rce/rcecalib/dataproc/DelayScanDataHandler.cc create mode 100644 rce/rcecalib/dataproc/DelayScanDataHandler.hh create mode 100644 rce/rcecalib/dataproc/DelayScanDataProc.cc create mode 100644 rce/rcecalib/dataproc/DelayScanDataProc.hh create mode 100644 rce/rcecalib/dataproc/Fei4RegisterTestDataProc.cc create mode 100644 rce/rcecalib/dataproc/Fei4RegisterTestDataProc.hh create mode 100644 rce/rcecalib/dataproc/HitorDataProc.cc create mode 100644 rce/rcecalib/dataproc/HitorDataProc.hh create mode 100644 rce/rcecalib/dataproc/Makefile create mode 100644 rce/rcecalib/dataproc/MeasurementDataProc.cc create mode 100644 rce/rcecalib/dataproc/MeasurementDataProc.hh create mode 100644 rce/rcecalib/dataproc/MeasurementReceiver.cc create mode 100644 rce/rcecalib/dataproc/MeasurementReceiver.hh create mode 100644 rce/rcecalib/dataproc/ModuleCrosstalkRawDataHandler.cc create mode 100644 rce/rcecalib/dataproc/ModuleCrosstalkRawDataHandler.hh create mode 100644 rce/rcecalib/dataproc/MonleakDataProc.cc create mode 100644 rce/rcecalib/dataproc/MonleakDataProc.hh create mode 100644 rce/rcecalib/dataproc/MultiTrigNoiseDataProc.cc create mode 100644 rce/rcecalib/dataproc/MultiTrigNoiseDataProc.hh create mode 100644 rce/rcecalib/dataproc/MultiTrigOccupancyDataProc.cc create mode 100644 rce/rcecalib/dataproc/MultiTrigOccupancyDataProc.hh create mode 100644 rce/rcecalib/dataproc/NoiseOccupancyDataProc.cc create mode 100644 rce/rcecalib/dataproc/NoiseOccupancyDataProc.hh create mode 100644 rce/rcecalib/dataproc/OccupancyDataProc.cc create mode 100644 rce/rcecalib/dataproc/OccupancyDataProc.hh create mode 100644 rce/rcecalib/dataproc/PgpCosmicNwReceiver.cc create mode 100644 rce/rcecalib/dataproc/PgpCosmicNwReceiver.hh create mode 100644 rce/rcecalib/dataproc/PgpCosmicReceiver.cc create mode 100644 rce/rcecalib/dataproc/PgpCosmicReceiver.hh create mode 100644 rce/rcecalib/dataproc/PgpReceiver.cc create mode 100644 rce/rcecalib/dataproc/PgpReceiver.hh create mode 100644 rce/rcecalib/dataproc/ProducerIF.hh create mode 100644 rce/rcecalib/dataproc/RawFei4OccupancyDataProc.cc create mode 100644 rce/rcecalib/dataproc/RawFei4OccupancyDataProc.hh create mode 100644 rce/rcecalib/dataproc/RegularScanDataHandler.cc create mode 100644 rce/rcecalib/dataproc/RegularScanDataHandler.hh create mode 100644 rce/rcecalib/dataproc/RegularScanRawDataHandler.cc create mode 100644 rce/rcecalib/dataproc/RegularScanRawDataHandler.hh create mode 100644 rce/rcecalib/dataproc/SNDataProc.cc create mode 100644 rce/rcecalib/dataproc/SNDataProc.hh create mode 100644 rce/rcecalib/dataproc/SelftriggerDataProc.cc create mode 100644 rce/rcecalib/dataproc/SelftriggerDataProc.hh create mode 100644 rce/rcecalib/dataproc/SimpleDataHandler.hh create mode 100644 rce/rcecalib/dataproc/SimpleReceiver.cc create mode 100644 rce/rcecalib/dataproc/SimpleReceiver.hh create mode 100644 rce/rcecalib/dataproc/TemperatureDataProc.cc create mode 100644 rce/rcecalib/dataproc/TemperatureDataProc.hh create mode 100644 rce/rcecalib/dataproc/TotCalibDataProc.cc create mode 100644 rce/rcecalib/dataproc/TotCalibDataProc.hh create mode 100644 rce/rcecalib/dataproc/TotDataProc.cc create mode 100644 rce/rcecalib/dataproc/TotDataProc.hh create mode 100644 rce/rcecalib/dataproc/constituents.mk create mode 100644 rce/rcecalib/dataproc/fit/AbsFit.hh create mode 100644 rce/rcecalib/dataproc/fit/CalculateMeanSigma.cc create mode 100644 rce/rcecalib/dataproc/fit/FitData.cc create mode 100644 rce/rcecalib/dataproc/fit/FitData.hh create mode 100644 rce/rcecalib/dataproc/fit/FitFactory.cc create mode 100644 rce/rcecalib/dataproc/fit/FitFactory.hh create mode 100644 rce/rcecalib/dataproc/fit/FitScurveLikelihoodFastInt.cc create mode 100644 rce/rcecalib/dataproc/fit/FitScurveLikelihoodFastInt.hh create mode 100644 rce/rcecalib/dataproc/fit/FitScurveLikelihoodFloat.cc create mode 100644 rce/rcecalib/dataproc/fit/FitScurveLikelihoodFloat.hh create mode 100644 rce/rcecalib/dataproc/fit/FitScurveLikelihoodInt.cc create mode 100644 rce/rcecalib/dataproc/fit/FitScurveLikelihoodInt.hh create mode 100644 rce/rcecalib/dataproc/fit/binomial_weight.dat create mode 100644 rce/rcecalib/dataproc/fit/binomial_weight_fastint.dat create mode 100644 rce/rcecalib/dataproc/fit/binomial_weight_int.dat create mode 100644 rce/rcecalib/dataproc/fit/errf_ext.dat create mode 100644 rce/rcecalib/dataproc/fit/errf_ext_fastint.dat create mode 100644 rce/rcecalib/dataproc/fit/errf_ext_int.dat create mode 100644 rce/rcecalib/dataproc/fit/logx.dat create mode 100644 rce/rcecalib/dataproc/fit/logx_ext.dat create mode 100644 rce/rcecalib/dataproc/fit/logx_ext_fastint.dat create mode 100644 rce/rcecalib/dataproc/fit/logx_ext_int.dat create mode 100644 rce/rcecalib/eudaq/BufferSerializer.cc create mode 100644 rce/rcecalib/eudaq/BufferSerializer.hh create mode 100644 rce/rcecalib/eudaq/CommandReceiver.cc create mode 100644 rce/rcecalib/eudaq/CommandReceiver.hh create mode 100644 rce/rcecalib/eudaq/Configuration.cc create mode 100644 rce/rcecalib/eudaq/Configuration.hh create mode 100644 rce/rcecalib/eudaq/DataSender.cc create mode 100644 rce/rcecalib/eudaq/DataSender.hh create mode 100644 rce/rcecalib/eudaq/DataSenderIF.cc create mode 100644 rce/rcecalib/eudaq/DataSenderIF.hh create mode 100644 rce/rcecalib/eudaq/DetectorEvent.cc create mode 100644 rce/rcecalib/eudaq/DetectorEvent.hh create mode 100644 rce/rcecalib/eudaq/Event.cc create mode 100644 rce/rcecalib/eudaq/Event.hh create mode 100644 rce/rcecalib/eudaq/Exception.cc create mode 100644 rce/rcecalib/eudaq/Exception.hh create mode 100644 rce/rcecalib/eudaq/FileSerializer.cc create mode 100644 rce/rcecalib/eudaq/FileSerializer.hh create mode 100644 rce/rcecalib/eudaq/Makefile create mode 100644 rce/rcecalib/eudaq/Mutex.cc create mode 100644 rce/rcecalib/eudaq/Mutex.hh create mode 100644 rce/rcecalib/eudaq/Producer.cc create mode 100644 rce/rcecalib/eudaq/Producer.hh create mode 100644 rce/rcecalib/eudaq/ProducerIF.cc create mode 100644 rce/rcecalib/eudaq/ProducerIF.hh create mode 100644 rce/rcecalib/eudaq/RawDataEvent.cc create mode 100644 rce/rcecalib/eudaq/RawDataEvent.hh create mode 100644 rce/rcecalib/eudaq/Serializable.hh create mode 100644 rce/rcecalib/eudaq/Serializer.hh create mode 100644 rce/rcecalib/eudaq/Status.cc create mode 100644 rce/rcecalib/eudaq/Status.hh create mode 100644 rce/rcecalib/eudaq/TLUEvent.cc create mode 100644 rce/rcecalib/eudaq/TLUEvent.hh create mode 100644 rce/rcecalib/eudaq/Time.cc create mode 100644 rce/rcecalib/eudaq/Time.hh create mode 100644 rce/rcecalib/eudaq/TransportBase.cc create mode 100644 rce/rcecalib/eudaq/TransportBase.hh create mode 100644 rce/rcecalib/eudaq/TransportClient.cc create mode 100644 rce/rcecalib/eudaq/TransportClient.hh create mode 100644 rce/rcecalib/eudaq/TransportFactory.cc create mode 100644 rce/rcecalib/eudaq/TransportFactory.hh create mode 100644 rce/rcecalib/eudaq/TransportNULL.cc create mode 100644 rce/rcecalib/eudaq/TransportNULL.hh create mode 100644 rce/rcecalib/eudaq/TransportServer.cc create mode 100644 rce/rcecalib/eudaq/TransportServer.hh create mode 100644 rce/rcecalib/eudaq/TransportTCP.cc create mode 100644 rce/rcecalib/eudaq/TransportTCP.hh create mode 100644 rce/rcecalib/eudaq/TransportTCP_POSIX.inc create mode 100644 rce/rcecalib/eudaq/Utils.cc create mode 100644 rce/rcecalib/eudaq/Utils.hh create mode 100644 rce/rcecalib/eudaq/constituents.mk create mode 100644 rce/rcecalib/eudaq/counted_ptr.hh create mode 100644 rce/rcecalib/eudaq/testread.cc create mode 100644 rce/rcecalib/eudaq/testreadp.cc create mode 100644 rce/rcecalib/eudaq/testwrite.cc create mode 100644 rce/rcecalib/flags.mk create mode 100644 rce/rcecalib/idl/AFPHPTDCModuleConfig.idl create mode 100644 rce/rcecalib/idl/Callback.idl create mode 100644 rce/rcecalib/idl/HitbusModuleConfig.idl create mode 100644 rce/rcecalib/idl/IPCAFPHPTDCAdapter.idl create mode 100644 rce/rcecalib/idl/IPCConfigIFAdapter.idl create mode 100644 rce/rcecalib/idl/IPCFEI3Adapter.idl create mode 100644 rce/rcecalib/idl/IPCFEI4AAdapter.idl create mode 100644 rce/rcecalib/idl/IPCFEI4BAdapter.idl create mode 100644 rce/rcecalib/idl/IPCHitbusAdapter.idl create mode 100644 rce/rcecalib/idl/IPCScanAdapter.idl create mode 100644 rce/rcecalib/idl/IPCScanRootAdapter.idl create mode 100644 rce/rcecalib/idl/Makefile create mode 100644 rce/rcecalib/idl/PixelFEI4AConfig.idl create mode 100644 rce/rcecalib/idl/PixelFEI4BConfig.idl create mode 100644 rce/rcecalib/idl/PixelFEI4GenConfig.idl create mode 100644 rce/rcecalib/idl/PixelModuleConfig.idl create mode 100644 rce/rcecalib/idl/ScanOptions.idl create mode 100644 rce/rcecalib/idl/constituents.mk create mode 100644 rce/rcecalib/namespace_aliases.hh create mode 100644 rce/rcecalib/packages.mk create mode 100644 rce/rcecalib/profiler/Makefile create mode 100644 rce/rcecalib/profiler/Profiler.cc create mode 100644 rce/rcecalib/profiler/Profiler.hh create mode 100644 rce/rcecalib/profiler/README create mode 100644 rce/rcecalib/profiler/constituents.mk create mode 100644 rce/rcecalib/projects.mk.template create mode 100644 rce/rcecalib/scanctrl/AbsScan.hh create mode 100644 rce/rcecalib/scanctrl/ActionFactory.cc create mode 100644 rce/rcecalib/scanctrl/ActionFactory.hh create mode 100644 rce/rcecalib/scanctrl/ChangeBinAction.hh create mode 100644 rce/rcecalib/scanctrl/CloseFileEoLAction.hh create mode 100644 rce/rcecalib/scanctrl/ConfigureModulesAction.hh create mode 100644 rce/rcecalib/scanctrl/ConfigureModulesNEAction.hh create mode 100644 rce/rcecalib/scanctrl/CosmicDataSetup.cc create mode 100644 rce/rcecalib/scanctrl/CosmicDataSetup.hh create mode 100644 rce/rcecalib/scanctrl/CosmicEnableScintillatorTriggerAction.hh create mode 100644 rce/rcecalib/scanctrl/CosmicEnableTDCAction.hh create mode 100644 rce/rcecalib/scanctrl/CosmicSetInputDelayAction.hh create mode 100644 rce/rcecalib/scanctrl/DelayScanSetup.cc create mode 100644 rce/rcecalib/scanctrl/DelayScanSetup.hh create mode 100644 rce/rcecalib/scanctrl/DisableAllChannelsAction.hh create mode 100644 rce/rcecalib/scanctrl/DisableAllChannelsEoLAction.hh create mode 100644 rce/rcecalib/scanctrl/DisableTriggerAction.hh create mode 100644 rce/rcecalib/scanctrl/DisableTriggerEoLAction.hh create mode 100644 rce/rcecalib/scanctrl/EnableTriggerAction.hh create mode 100644 rce/rcecalib/scanctrl/EndOfLoopAction.hh create mode 100644 rce/rcecalib/scanctrl/FitEoLAction.hh create mode 100644 rce/rcecalib/scanctrl/IPCScan.cc create mode 100644 rce/rcecalib/scanctrl/IPCScan.hh create mode 100644 rce/rcecalib/scanctrl/IPCScanRoot.cc create mode 100644 rce/rcecalib/scanctrl/IPCScanRoot.hh create mode 100644 rce/rcecalib/scanctrl/IfScanSetup.cc create mode 100644 rce/rcecalib/scanctrl/IfScanSetup.hh create mode 100644 rce/rcecalib/scanctrl/IfWaitAction.hh create mode 100644 rce/rcecalib/scanctrl/LoopAction.hh create mode 100644 rce/rcecalib/scanctrl/LoopFactory.cc create mode 100644 rce/rcecalib/scanctrl/LoopFactory.hh create mode 100644 rce/rcecalib/scanctrl/LoopSetup.hh create mode 100644 rce/rcecalib/scanctrl/Makefile create mode 100644 rce/rcecalib/scanctrl/NestedLoop.cc create mode 100644 rce/rcecalib/scanctrl/NestedLoop.hh create mode 100644 rce/rcecalib/scanctrl/NoiseScanSetup.cc create mode 100644 rce/rcecalib/scanctrl/NoiseScanSetup.hh create mode 100644 rce/rcecalib/scanctrl/PauseAction.hh create mode 100644 rce/rcecalib/scanctrl/RceCallback.cc create mode 100644 rce/rcecalib/scanctrl/RceCallback.hh create mode 100644 rce/rcecalib/scanctrl/RegularCfgScanSetup.cc create mode 100644 rce/rcecalib/scanctrl/RegularCfgScanSetup.hh create mode 100644 rce/rcecalib/scanctrl/RegularScanSetup.cc create mode 100644 rce/rcecalib/scanctrl/RegularScanSetup.hh create mode 100644 rce/rcecalib/scanctrl/ResetFEEoLAction.hh create mode 100644 rce/rcecalib/scanctrl/Scan.cc create mode 100644 rce/rcecalib/scanctrl/Scan.hh create mode 100644 rce/rcecalib/scanctrl/ScanLoop.cc create mode 100644 rce/rcecalib/scanctrl/ScanLoop.hh create mode 100644 rce/rcecalib/scanctrl/ScanRoot.cc create mode 100644 rce/rcecalib/scanctrl/ScanRoot.hh create mode 100644 rce/rcecalib/scanctrl/SelftriggerSetup.cc create mode 100644 rce/rcecalib/scanctrl/SelftriggerSetup.hh create mode 100644 rce/rcecalib/scanctrl/SendTriggerAction.hh create mode 100644 rce/rcecalib/scanctrl/SetChannelMaskAction.hh create mode 100644 rce/rcecalib/scanctrl/SetupMaskStageAction.hh create mode 100644 rce/rcecalib/scanctrl/SetupParamAction.hh create mode 100644 rce/rcecalib/scanctrl/SetupTriggerAction.hh create mode 100644 rce/rcecalib/scanctrl/constituents.mk create mode 100644 rce/rcecalib/server/.gitignore create mode 100644 rce/rcecalib/server/AFPHPTDCConfigFile.cc create mode 100644 rce/rcecalib/server/AFPHPTDCConfigFile.hh create mode 100644 rce/rcecalib/server/BootLoaderPort.hh create mode 100644 rce/rcecalib/server/CalibGui.cc create mode 100644 rce/rcecalib/server/CalibGui.hh create mode 100644 rce/rcecalib/server/CallbackInfo.cc create mode 100644 rce/rcecalib/server/CallbackInfo.hh create mode 100644 rce/rcecalib/server/CmdDecoder.cc create mode 100644 rce/rcecalib/server/CmdDecoder.hh create mode 100644 rce/rcecalib/server/ConfigGui.cc create mode 100644 rce/rcecalib/server/ConfigGui.hh create mode 100644 rce/rcecalib/server/CosmicDataReceiver.cc create mode 100644 rce/rcecalib/server/CosmicDataReceiver.hh create mode 100644 rce/rcecalib/server/CosmicGui.cc create mode 100644 rce/rcecalib/server/CosmicGui.hh create mode 100644 rce/rcecalib/server/CosmicMonitoringGui.cc create mode 100644 rce/rcecalib/server/CosmicMonitoringGui.hh create mode 100644 rce/rcecalib/server/CosmicMonitoringGuiEmbedded.cc create mode 100644 rce/rcecalib/server/CosmicMonitoringGuiEmbedded.hh create mode 100644 rce/rcecalib/server/CosmicOfflineDataProc.cc create mode 100644 rce/rcecalib/server/CosmicOfflineDataProc.hh create mode 100644 rce/rcecalib/server/DataExporter.cc create mode 100644 rce/rcecalib/server/DataExporter.hh create mode 100644 rce/rcecalib/server/EthPrimitive.cc create mode 100644 rce/rcecalib/server/EthPrimitive.hh create mode 100644 rce/rcecalib/server/FEI4AConfigFile.cc create mode 100644 rce/rcecalib/server/FEI4AConfigFile.hh create mode 100644 rce/rcecalib/server/FEI4BConfigFile.cc create mode 100644 rce/rcecalib/server/FEI4BConfigFile.hh create mode 100644 rce/rcecalib/server/GlobalConfigGui.cc create mode 100644 rce/rcecalib/server/GlobalConfigGui.hh create mode 100644 rce/rcecalib/server/HitbusConfigFile.cc create mode 100644 rce/rcecalib/server/HitbusConfigFile.hh create mode 100644 rce/rcecalib/server/IPCCallback.hh create mode 100644 rce/rcecalib/server/IPCController.cc create mode 100644 rce/rcecalib/server/IPCController.hh create mode 100644 rce/rcecalib/server/IPCGuiCallback.cc create mode 100644 rce/rcecalib/server/IPCGuiCallback.hh create mode 100644 rce/rcecalib/server/IPCHistoController.cc create mode 100644 rce/rcecalib/server/IPCHistoController.hh create mode 100644 rce/rcecalib/server/IPCRegularCallback.cc create mode 100644 rce/rcecalib/server/IPCRegularCallback.hh create mode 100644 rce/rcecalib/server/Makefile create mode 100644 rce/rcecalib/server/Mean.hh create mode 100644 rce/rcecalib/server/PixScan.cc create mode 100644 rce/rcecalib/server/PixScan.hh create mode 100644 rce/rcecalib/server/PrimList.cc create mode 100644 rce/rcecalib/server/PrimList.hh create mode 100644 rce/rcecalib/server/PrimListGui.cc create mode 100644 rce/rcecalib/server/PrimListGui.hh create mode 100644 rce/rcecalib/server/RceControl.cc create mode 100644 rce/rcecalib/server/RceControl.hh create mode 100644 rce/rcecalib/server/RceOfflineProducer.cc create mode 100644 rce/rcecalib/server/RceOfflineProducer.hh create mode 100644 rce/rcecalib/server/RceProducer.cc create mode 100644 rce/rcecalib/server/RceProducer.hh create mode 100644 rce/rcecalib/server/ScanGui.cc create mode 100644 rce/rcecalib/server/ScanGui.hh create mode 100644 rce/rcecalib/server/ScanLog.cc create mode 100644 rce/rcecalib/server/ScanLog.hh create mode 100644 rce/rcecalib/server/StandardStream.o create mode 100644 rce/rcecalib/server/ThrottleStream.o create mode 100644 rce/rcecalib/server/TurboDaqFile.cc create mode 100644 rce/rcecalib/server/TurboDaqFile.hh create mode 100644 rce/rcecalib/server/atlasimage.hh create mode 100644 rce/rcecalib/server/bootloader.cc create mode 100644 rce/rcecalib/server/bootloader_2.2.cc create mode 100644 rce/rcecalib/server/calibGui_Linkdef.hh create mode 100644 rce/rcecalib/server/calibclient.cc create mode 100644 rce/rcecalib/server/calibserver.cc create mode 100644 rce/rcecalib/server/calibserver.hh create mode 100644 rce/rcecalib/server/constituents.mk create mode 100644 rce/rcecalib/server/cosmicGui_Linkdef.hh create mode 100644 rce/rcecalib/server/cosmicMonitoringGui_Linkdef.hh create mode 100644 rce/rcecalib/server/delaycalib.cc create mode 100644 rce/rcecalib/server/dumpRceMod.cc create mode 100644 rce/rcecalib/server/dumpRceScan.cc create mode 100644 rce/rcecalib/server/ettcp.c create mode 100644 rce/rcecalib/server/eudaqserver.cc create mode 100644 rce/rcecalib/server/eudaqserver.hh create mode 100644 rce/rcecalib/server/host_bootloader.cc create mode 100644 rce/rcecalib/server/rceOfflineProducer_Linkdef.hh create mode 100644 rce/rcecalib/server/rebootHSIO.cc create mode 100644 rce/rcecalib/server/rtems_config.cc create mode 100644 rce/rcecalib/server/rtems_config_2.2.cc create mode 100644 rce/rcecalib/server/runeudaqserver.cc create mode 100644 rce/rcecalib/server/runeudaqservermod.cc create mode 100644 rce/rcecalib/server/runserver.cc create mode 100644 rce/rcecalib/server/runservermod.cc create mode 100644 rce/rcecalib/server/sendBitStream.cc create mode 100644 rce/rcecalib/server/sendRandomPattern.cc create mode 100644 rce/rcecalib/server/tdccalib.cc create mode 100644 rce/rcecalib/server/test_client.cc create mode 100644 rce/rcecalib/server/test_scan_client.cc create mode 100644 rce/rcecalib/server/test_server.cc create mode 100644 rce/rcecalib/util/AbsRceHisto.cc create mode 100644 rce/rcecalib/util/AbsRceHisto.hh create mode 100644 rce/rcecalib/util/DataCond.hh create mode 100644 rce/rcecalib/util/IPCHistoManager.cc create mode 100644 rce/rcecalib/util/IPCHistoManager.hh create mode 100644 rce/rcecalib/util/Makefile create mode 100644 rce/rcecalib/util/RceHisto1d.cc create mode 100644 rce/rcecalib/util/RceHisto1d.hh create mode 100644 rce/rcecalib/util/RceHisto2d.cc create mode 100644 rce/rcecalib/util/RceHisto2d.hh create mode 100644 rce/rcecalib/util/RceMath.cc create mode 100644 rce/rcecalib/util/RceMath.hh create mode 100644 rce/rcecalib/util/RceName.cc create mode 100644 rce/rcecalib/util/RceName.hh create mode 100644 rce/rcecalib/util/VerifyErrors.hh create mode 100644 rce/rcecalib/util/constituents.mk create mode 100644 rce/rcecalib/util/exceptions.hh create mode 100755 rce/rcecalib/xmd.ini create mode 100755 rce/scripts/cmake_script create mode 100755 rce/scripts/dumpscans create mode 100755 rce/scripts/findUndefSymbols.pl create mode 100755 rce/scripts/patch.links create mode 100755 rce/scripts/rce_dow create mode 100644 rce/scripts/rce_dow.ex create mode 100644 rce/scripts/setup_rce-04-00-00.csh create mode 100644 rce/scripts/setup_rce-04-00-01.csh create mode 100644 rce/scripts/setup_rce-04-00-01.sh create mode 100644 rce/scripts/setup_rce-04-00-01_rceG1.csh create mode 100644 rce/scripts/setup_rce.csh create mode 100644 rce/scripts/setup_rce.sh diff --git a/rce/Makefile b/rce/Makefile new file mode 100644 index 00000000..3f5e59c4 --- /dev/null +++ b/rce/Makefile @@ -0,0 +1,9 @@ + +include Makefile.inc +default: .server .gpib +clean: + rm -rf $(RELEASE_DIR)/build + + + + diff --git a/rce/Makefile.inc b/rce/Makefile.inc new file mode 100644 index 00000000..b6044202 --- /dev/null +++ b/rce/Makefile.inc @@ -0,0 +1,64 @@ +# Checks +# ------ +# Check release location variables +# number of parallel make jobs +ifneq ($(JOBS),) +JOBS:=16 +endif + +ifeq ($(RELEASE_DIR),) +export RELEASE_DIR := $(PWD) +endif + +export RCE_CORE := /daq/slc5/opt/rcecore/$(RCE_CORE_VERSION) +# Includes +# -------- + +ifeq ($(RCE_CORE_VERSION),2.2) +.coredep: + mkdir -p $(RELEASE_DIR)/build + ln -sfn $(RCE_CORE)/build/configuration $(RELEASE_DIR)/build + ln -sfn $(RCE_CORE)/build/oldPpi $(RELEASE_DIR)/build + ln -sfn $(RCE_CORE)/build/platform $(RELEASE_DIR)/build + ln -sfn $(RCE_CORE)/build/service $(RELEASE_DIR)/build + ln -sfn $(RCE_CORE)/build/tool $(RELEASE_DIR)/build +else +.coredep: + mkdir -p $(RELEASE_DIR)/build + ln -sfn $(RCE_CORE)/build/rce $(RELEASE_DIR)/build + ln -sfn $(RCE_CORE)/build/rceusr $(RELEASE_DIR)/build + ln -sfn $(RCE_CORE)/build/rceapp $(RELEASE_DIR)/build +endif + + + +.softlinks: .coredep + ln -sfn $(RTEMS) $(RELEASE_DIR)/build/rtems + ln -sfn $(ROOTSYS) $(RELEASE_DIR)/build + +.idl: + +$(MAKE) -j$(JOBS) -C $(RELEASE_DIR)/rcecalib/idl $(RCE_ARCH) $(HOST_ARCH) + + + +.HW: .softlinks .idl + +$(MAKE) -j$(JOBS) -C $(RELEASE_DIR)/rcecalib/HW $(RCE_ARCH) $(HOST_ARCH) +.eudaq: + +$(MAKE) -j$(JOBS) -C $(RELEASE_DIR)/rcecalib/eudaq $(RCE_ARCH) $(HOST_ARCH) +.dataproc: + +$(MAKE) -j$(JOBS) -C $(RELEASE_DIR)/rcecalib/dataproc $(RCE_ARCH) $(HOST_ARCH) +.profiler: + +$(MAKE) -j$(JOBS) -C $(RELEASE_DIR)/rcecalib/profiler $(RCE_ARCH) $(HOST_ARCH) +.scanctrl: + +$(MAKE) -j$(JOBS) -C $(RELEASE_DIR)/rcecalib/scanctrl $(RCE_ARCH) $(HOST_ARCH) +.analysis: + +$(MAKE) -j$(JOBS) -C $(RELEASE_DIR)/rcecalib/analysis $(RCE_ARCH) $(HOST_ARCH) +.config: + +$(MAKE) -j$(JOBS) -C $(RELEASE_DIR)/rcecalib/config $(RCE_ARCH) $(HOST_ARCH) +.util: + +$(MAKE) -j$(JOBS) -C $(RELEASE_DIR)/rcecalib/util $(RCE_ARCH) $(HOST_ARCH) +.server: .HW .eudaq .dataproc .profiler .scanctrl .analysis .config .util + +$(MAKE) -j$(JOBS) -C $(RELEASE_DIR)/rcecalib/server $(RCE_ARCH) $(HOST_ARCH) +.gpib: .server + +$(MAKE) -j$(JOBS) -C rcedcs/gpib $(HOST_ARCH) +# +$(MAKE) -j$(JOBS) $(RELEASE_DIR)/rcedcs/labjack $(HOST_ARCH) diff --git a/rce/Makefile_nonparallel b/rce/Makefile_nonparallel new file mode 100644 index 00000000..dd8ec9b9 --- /dev/null +++ b/rce/Makefile_nonparallel @@ -0,0 +1,40 @@ +# Top level makefile +# ------------------ +%.mk:; + + +# Checks +# ------ +# Check release location variables +ifeq ($(RELEASE_DIR),) +export RELEASE_DIR := $(PWD) +endif + + + +export RCE_CORE := /daq/slc5/opt/rcecore/$(RCE_CORE_VERSION) + +all: + $(MAKE) $(RCE_ARCH) $(HOST_ARCH) +clean: + $(MAKE) $(RCE_ARCH).clean $(HOST_ARCH).clean + + + +# Includes +# -------- +include make/share/setup.mk +include projects.mk +include make/share/release.mk + + + +#doxygen target +doxygen: + cd doxygen; doxygen Doxyfile + +.PHONY: doxygen + + + + diff --git a/rce/fw-hsio/.gitignore b/rce/fw-hsio/.gitignore new file mode 100644 index 00000000..567609b1 --- /dev/null +++ b/rce/fw-hsio/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/rce/fw-hsio/Readme.txt b/rce/fw-hsio/Readme.txt new file mode 100644 index 00000000..dbc0d2af --- /dev/null +++ b/rce/fw-hsio/Readme.txt @@ -0,0 +1,23 @@ +This is the COB DPM top level directory. + +The modules directory contains the generic modules +that are used in multiple DPM projects. + +The projects directory contains the specific design +files for each DPM project. + +The top level generic makefile 'system.mk' is contained +in this directory. + +In order to build a project go to the project's directory +and type gmake. See the Readme.txt file in the project +directory for more information. + +A local build directory must be created in order to compile designs. +The build directory can either be a local directory or a link to +a directory located on a scratch disk: + +mkdir build +or +ln -s /u1/build build + diff --git a/rce/fw-hsio/modules/pgp/coregen/pgp_adder_16_16.xco b/rce/fw-hsio/modules/pgp/coregen/pgp_adder_16_16.xco new file mode 100644 index 00000000..31dc5fd5 --- /dev/null +++ b/rce/fw-hsio/modules/pgp/coregen/pgp_adder_16_16.xco @@ -0,0 +1,66 @@ +############################################################## +# +# Xilinx Core Generator version IP3_J.9 +# Date: Tue Oct 30 22:57:30 2007 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# BEGIN Project Options +SET addpads = False +SET asysymbol = False +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = False +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = False +SET foundationsym = False +SET implementationfiletype = Ngc +SET package = ff1152 +SET removerpms = False +SET simulationfiles = Behavioral +SET speedgrade = -10 +SET verilogsim = False +SET vhdlsim = True +# END Project Options +# BEGIN Select +SELECT Adder_Subtracter family Xilinx,_Inc. 7.0 +# END Select +# BEGIN Parameters +CSET async_init_value=0 +CSET asynchronous_settings=none +CSET bypass=false +CSET bypass_sense=active_high +CSET carry_borrow_input=false +CSET carry_borrow_output=false +CSET ce_override_for_bypass=true +CSET ce_overrides=sync_controls_override_ce +CSET clock_enable=false +CSET component_name=pgp_adder_16_16 +CSET create_rpm=true +CSET latency=0 +CSET operation=add +CSET output_options=non_registered +CSET output_width=16 +CSET overflow_output=false +CSET port_a_sign=unsigned +CSET port_a_width=16 +CSET port_b_constant=false +CSET port_b_constant_value=0 +CSET port_b_sign=unsigned +CSET port_b_width=16 +CSET set_clear_priority=clear_overrides_set +CSET sync_init_value=0 +CSET synchronous_settings=none +# END Parameters +GENERATE +# CRC: 9fee80ef + diff --git a/rce/fw-hsio/modules/pgp/coregen/pgp_afifo_20x511.xco b/rce/fw-hsio/modules/pgp/coregen/pgp_afifo_20x511.xco new file mode 100644 index 00000000..10983cac --- /dev/null +++ b/rce/fw-hsio/modules/pgp/coregen/pgp_afifo_20x511.xco @@ -0,0 +1,77 @@ +############################################################## +# +# Xilinx Core Generator version IP3_J.9 +# Date: Tue Oct 30 23:01:31 2007 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# BEGIN Project Options +SET addpads = False +SET asysymbol = False +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = False +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = False +SET foundationsym = False +SET implementationfiletype = Ngc +SET package = ff1152 +SET removerpms = False +SET simulationfiles = Behavioral +SET speedgrade = -10 +SET verilogsim = False +SET vhdlsim = True +# END Project Options +# BEGIN Select +SELECT Fifo_Generator family Xilinx,_Inc. 3.3 +# END Select +# BEGIN Parameters +CSET almost_empty_flag=false +CSET almost_full_flag=false +CSET component_name=pgp_afifo_20x511 +CSET data_count=false +CSET data_count_width=9 +CSET dout_reset_value=0 +CSET empty_threshold_assert_value=2 +CSET empty_threshold_negate_value=3 +CSET enable_ecc=false +CSET fifo_implementation=Independent_Clocks_Block_RAM +CSET full_threshold_assert_value=510 +CSET full_threshold_negate_value=509 +CSET input_data_width=20 +CSET input_depth=512 +CSET output_data_width=20 +CSET output_depth=512 +CSET overflow_flag=false +CSET overflow_sense=Active_High +CSET performance_options=Standard_FIFO +CSET programmable_empty_type=No_Programmable_Empty_Threshold +CSET programmable_full_type=No_Programmable_Full_Threshold +CSET read_clock_frequency=100 +CSET read_data_count=false +CSET read_data_count_width=9 +CSET reset_pin=true +CSET reset_type=Asynchronous_Reset +CSET underflow_flag=false +CSET underflow_sense=Active_High +CSET use_extra_logic=false +CSET valid_flag=false +CSET valid_sense=Active_High +CSET write_acknowledge_flag=false +CSET write_acknowledge_sense=Active_High +CSET write_clock_frequency=100 +CSET write_data_count=true +CSET write_data_count_width=9 +# END Parameters +GENERATE +# CRC: ace9941 + diff --git a/rce/fw-hsio/modules/pgp/coregen/pgp_dpram_51x256.xco b/rce/fw-hsio/modules/pgp/coregen/pgp_dpram_51x256.xco new file mode 100644 index 00000000..9f170a6c --- /dev/null +++ b/rce/fw-hsio/modules/pgp/coregen/pgp_dpram_51x256.xco @@ -0,0 +1,75 @@ +############################################################## +# +# Xilinx Core Generator version IP3_J.9 +# Date: Tue Oct 30 23:04:53 2007 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# BEGIN Project Options +SET addpads = False +SET asysymbol = False +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = False +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = False +SET foundationsym = False +SET implementationfiletype = Ngc +SET package = ff1152 +SET removerpms = False +SET simulationfiles = Behavioral +SET speedgrade = -10 +SET verilogsim = False +SET vhdlsim = True +# END Project Options +# BEGIN Select +SELECT Dual_Port_Block_Memory family Xilinx,_Inc. 6.3 +# END Select +# BEGIN Parameters +CSET component_name=pgp_dpram_51x256 +CSET configuration_port_a=Write_Only +CSET configuration_port_b=Read_And_Write +CSET depth_a=256 +CSET depth_b=256 +CSET disable_warning_messages=true +CSET global_init_value=0 +CSET load_init_file=false +CSET port_a_active_clock_edge=Rising_Edge_Triggered +CSET port_a_additional_output_pipe_stages=0 +CSET port_a_enable_pin=false +CSET port_a_enable_pin_polarity=Active_High +CSET port_a_handshaking_pins=false +CSET port_a_init_pin=false +CSET port_a_init_value=0 +CSET port_a_initialization_pin_polarity=Active_High +CSET port_a_register_inputs=false +CSET port_a_write_enable_polarity=Active_High +CSET port_b_active_clock_edge=Rising_Edge_Triggered +CSET port_b_additional_output_pipe_stages=0 +CSET port_b_enable_pin=false +CSET port_b_enable_pin_polarity=Active_High +CSET port_b_handshaking_pins=false +CSET port_b_init_pin=false +CSET port_b_init_value=0 +CSET port_b_initialization_pin_polarity=Active_High +CSET port_b_register_inputs=false +CSET port_b_write_enable_polarity=Active_High +CSET primitive_selection=Optimize_For_Area +CSET select_primitive=32kx1 +CSET width_a=51 +CSET width_b=51 +CSET write_mode_port_a=Read_After_Write +CSET write_mode_port_b=Read_After_Write +# END Parameters +GENERATE +# CRC: 3d2f768 + diff --git a/rce/fw-hsio/modules/pgp/coregen/pgp_fifo_20x512.xco b/rce/fw-hsio/modules/pgp/coregen/pgp_fifo_20x512.xco new file mode 100644 index 00000000..532c8358 --- /dev/null +++ b/rce/fw-hsio/modules/pgp/coregen/pgp_fifo_20x512.xco @@ -0,0 +1,77 @@ +############################################################## +# +# Xilinx Core Generator version IP3_J.9 +# Date: Tue Nov 27 21:31:02 2007 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# BEGIN Project Options +SET addpads = False +SET asysymbol = False +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = False +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = False +SET foundationsym = False +SET implementationfiletype = Ngc +SET package = ff1152 +SET removerpms = False +SET simulationfiles = Behavioral +SET speedgrade = -10 +SET verilogsim = False +SET vhdlsim = True +# END Project Options +# BEGIN Select +SELECT Fifo_Generator family Xilinx,_Inc. 3.3 +# END Select +# BEGIN Parameters +CSET almost_empty_flag=false +CSET almost_full_flag=false +CSET component_name=pgp_fifo_20x512 +CSET data_count=true +CSET data_count_width=9 +CSET dout_reset_value=0 +CSET empty_threshold_assert_value=2 +CSET empty_threshold_negate_value=3 +CSET enable_ecc=false +CSET fifo_implementation=Common_Clock_Block_RAM +CSET full_threshold_assert_value=510 +CSET full_threshold_negate_value=509 +CSET input_data_width=20 +CSET input_depth=512 +CSET output_data_width=20 +CSET output_depth=512 +CSET overflow_flag=false +CSET overflow_sense=Active_High +CSET performance_options=Standard_FIFO +CSET programmable_empty_type=No_Programmable_Empty_Threshold +CSET programmable_full_type=No_Programmable_Full_Threshold +CSET read_clock_frequency=100 +CSET read_data_count=false +CSET read_data_count_width=9 +CSET reset_pin=true +CSET reset_type=Asynchronous_Reset +CSET underflow_flag=false +CSET underflow_sense=Active_High +CSET use_extra_logic=false +CSET valid_flag=false +CSET valid_sense=Active_High +CSET write_acknowledge_flag=false +CSET write_acknowledge_sense=Active_High +CSET write_clock_frequency=100 +CSET write_data_count=false +CSET write_data_count_width=9 +# END Parameters +GENERATE +# CRC: ff734927 + diff --git a/rce/fw-hsio/modules/pgp/coregen/pgp_fifo_21x512.xco b/rce/fw-hsio/modules/pgp/coregen/pgp_fifo_21x512.xco new file mode 100644 index 00000000..e796c930 --- /dev/null +++ b/rce/fw-hsio/modules/pgp/coregen/pgp_fifo_21x512.xco @@ -0,0 +1,77 @@ +############################################################## +# +# Xilinx Core Generator version IP3_J.9 +# Date: Tue Nov 20 21:00:35 2007 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# BEGIN Project Options +SET addpads = False +SET asysymbol = False +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = False +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = False +SET foundationsym = False +SET implementationfiletype = Ngc +SET package = ff1152 +SET removerpms = False +SET simulationfiles = Behavioral +SET speedgrade = -10 +SET verilogsim = False +SET vhdlsim = True +# END Project Options +# BEGIN Select +SELECT Fifo_Generator family Xilinx,_Inc. 3.3 +# END Select +# BEGIN Parameters +CSET almost_empty_flag=false +CSET almost_full_flag=false +CSET component_name=pgp_fifo_21x512 +CSET data_count=true +CSET data_count_width=9 +CSET dout_reset_value=0 +CSET empty_threshold_assert_value=2 +CSET empty_threshold_negate_value=3 +CSET enable_ecc=false +CSET fifo_implementation=Common_Clock_Block_RAM +CSET full_threshold_assert_value=510 +CSET full_threshold_negate_value=509 +CSET input_data_width=21 +CSET input_depth=512 +CSET output_data_width=21 +CSET output_depth=512 +CSET overflow_flag=false +CSET overflow_sense=Active_High +CSET performance_options=Standard_FIFO +CSET programmable_empty_type=No_Programmable_Empty_Threshold +CSET programmable_full_type=No_Programmable_Full_Threshold +CSET read_clock_frequency=100 +CSET read_data_count=false +CSET read_data_count_width=9 +CSET reset_pin=true +CSET reset_type=Asynchronous_Reset +CSET underflow_flag=false +CSET underflow_sense=Active_High +CSET use_extra_logic=false +CSET valid_flag=false +CSET valid_sense=Active_High +CSET write_acknowledge_flag=false +CSET write_acknowledge_sense=Active_High +CSET write_clock_frequency=100 +CSET write_data_count=false +CSET write_data_count_width=9 +# END Parameters +GENERATE +# CRC: fc18e96b + diff --git a/rce/fw-hsio/modules/pgp/coregen/pgp_fifo_8x256.xco b/rce/fw-hsio/modules/pgp/coregen/pgp_fifo_8x256.xco new file mode 100644 index 00000000..63ac4e4c --- /dev/null +++ b/rce/fw-hsio/modules/pgp/coregen/pgp_fifo_8x256.xco @@ -0,0 +1,77 @@ +############################################################## +# +# Xilinx Core Generator version IP3_J.9 +# Date: Tue Oct 30 23:11:26 2007 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# BEGIN Project Options +SET addpads = False +SET asysymbol = False +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = False +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = False +SET foundationsym = False +SET implementationfiletype = Ngc +SET package = ff1152 +SET removerpms = False +SET simulationfiles = Behavioral +SET speedgrade = -10 +SET verilogsim = False +SET vhdlsim = True +# END Project Options +# BEGIN Select +SELECT Fifo_Generator family Xilinx,_Inc. 3.3 +# END Select +# BEGIN Parameters +CSET almost_empty_flag=false +CSET almost_full_flag=false +CSET component_name=pgp_fifo_8x256 +CSET data_count=false +CSET data_count_width=8 +CSET dout_reset_value=0 +CSET empty_threshold_assert_value=2 +CSET empty_threshold_negate_value=3 +CSET enable_ecc=false +CSET fifo_implementation=Common_Clock_Block_RAM +CSET full_threshold_assert_value=254 +CSET full_threshold_negate_value=253 +CSET input_data_width=8 +CSET input_depth=256 +CSET output_data_width=8 +CSET output_depth=256 +CSET overflow_flag=false +CSET overflow_sense=Active_High +CSET performance_options=Standard_FIFO +CSET programmable_empty_type=No_Programmable_Empty_Threshold +CSET programmable_full_type=No_Programmable_Full_Threshold +CSET read_clock_frequency=100 +CSET read_data_count=false +CSET read_data_count_width=8 +CSET reset_pin=true +CSET reset_type=Asynchronous_Reset +CSET underflow_flag=false +CSET underflow_sense=Active_High +CSET use_extra_logic=false +CSET valid_flag=false +CSET valid_sense=Active_High +CSET write_acknowledge_flag=false +CSET write_acknowledge_sense=Active_High +CSET write_clock_frequency=100 +CSET write_data_count=false +CSET write_data_count_width=8 +# END Parameters +GENERATE +# CRC: 6c912950 + diff --git a/rce/fw-hsio/modules/pgp/coregen/pgp_fifo_9x256.xco b/rce/fw-hsio/modules/pgp/coregen/pgp_fifo_9x256.xco new file mode 100644 index 00000000..b22d04ec --- /dev/null +++ b/rce/fw-hsio/modules/pgp/coregen/pgp_fifo_9x256.xco @@ -0,0 +1,77 @@ +############################################################## +# +# Xilinx Core Generator version IP3_J.9 +# Date: Tue Oct 30 23:13:10 2007 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# BEGIN Project Options +SET addpads = False +SET asysymbol = False +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = False +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = False +SET foundationsym = False +SET implementationfiletype = Ngc +SET package = ff1152 +SET removerpms = False +SET simulationfiles = Behavioral +SET speedgrade = -10 +SET verilogsim = False +SET vhdlsim = True +# END Project Options +# BEGIN Select +SELECT Fifo_Generator family Xilinx,_Inc. 3.3 +# END Select +# BEGIN Parameters +CSET almost_empty_flag=false +CSET almost_full_flag=false +CSET component_name=pgp_fifo_9x256 +CSET data_count=false +CSET data_count_width=8 +CSET dout_reset_value=0 +CSET empty_threshold_assert_value=2 +CSET empty_threshold_negate_value=3 +CSET enable_ecc=false +CSET fifo_implementation=Common_Clock_Block_RAM +CSET full_threshold_assert_value=254 +CSET full_threshold_negate_value=253 +CSET input_data_width=9 +CSET input_depth=256 +CSET output_data_width=9 +CSET output_depth=256 +CSET overflow_flag=false +CSET overflow_sense=Active_High +CSET performance_options=Standard_FIFO +CSET programmable_empty_type=No_Programmable_Empty_Threshold +CSET programmable_full_type=No_Programmable_Full_Threshold +CSET read_clock_frequency=100 +CSET read_data_count=false +CSET read_data_count_width=8 +CSET reset_pin=true +CSET reset_type=Asynchronous_Reset +CSET underflow_flag=false +CSET underflow_sense=Active_High +CSET use_extra_logic=false +CSET valid_flag=false +CSET valid_sense=Active_High +CSET write_acknowledge_flag=false +CSET write_acknowledge_sense=Active_High +CSET write_clock_frequency=100 +CSET write_data_count=false +CSET write_data_count_width=8 +# END Parameters +GENERATE +# CRC: 6aa03d9 + diff --git a/rce/fw-hsio/modules/pgp/hdl/PgpAckRx.vhd b/rce/fw-hsio/modules/pgp/hdl/PgpAckRx.vhd new file mode 100644 index 00000000..61fb19a8 --- /dev/null +++ b/rce/fw-hsio/modules/pgp/hdl/PgpAckRx.vhd @@ -0,0 +1,759 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, ACK/NACK Receive & Timer Logic +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : PgpAckRx.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 10/24/2006 +------------------------------------------------------------------------------- +-- Description: +-- ACK/NACK receive module for the Pretty Good Protocol core. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 10/24/2006: created. +-- 06/15/2007: Added register state before ACK FIFO. Needed for timing. +-- 07/25/2007: Changed cell CRC error to cell receive error. +-- 09/21/2007: Ack timeout converted to generic. +-- 09/29/2007: Changed name of coregen blocks +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE work.ALL; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity PgpAckRx is + generic ( + AckTimeout : natural := 8 -- Ack/Nack Not Received Timeout, 8.192uS Steps + ); + port ( + + -- System clock, reset & control + pgpClk : in std_logic; -- Master clock + pgpReset : in std_logic; -- Synchronous reset input + + -- PIB Interface + pibLinkReady : in std_logic; -- PIB Link Ready + + -- Error Indication + seqFifoEmpty : out std_logic; -- Sequence number fifo is empty + nackCountInc : out std_logic; -- Nack received count increment + + -- Cell Receiver Interface + cellRxDone : in std_logic; -- Cell reception done + cellRxCellError : in std_logic; -- Cell receieve error + cellRxSeq : in std_logic_vector(7 downto 0); -- Cell receieve sequence + cellRxAck : in std_logic; -- Cell receieve ACK + cellRxNAck : in std_logic; -- Cell receieve NACK + + -- Transmit Schedular Interface + cidReady : out std_logic; -- CID Engine is ready + cidTimerStart : in std_logic; -- CID timer start + cellTxDataVc : in std_logic_vector(1 downto 0); -- Cell transmit virtual channel + cidSave : in std_logic; -- CID value store signal + + -- Cell Transmit logic + cellTxSOF : in std_logic; -- Cell contained SOF + cellTxDataSeq : out std_logic_vector(7 downto 0); -- Transmit sequence number + + -- User logic interface + vc0FrameTxCid : in std_logic_vector(31 downto 0); -- User frame data, context ID + vc0FrameTxAckCid : out std_logic_vector(31 downto 0); -- PGP ACK/NACK context ID + vc0FrameTxAckEn : out std_logic; -- PGP ACK/NACK enable + vc0FrameTxAck : out std_logic; -- PGP ACK/NACK + vc1FrameTxCid : in std_logic_vector(31 downto 0); -- User frame data, context ID + vc1FrameTxAckCid : out std_logic_vector(31 downto 0); -- PGP ACK/NACK context ID + vc1FrameTxAckEn : out std_logic; -- PGP ACK/NACK enable + vc1FrameTxAck : out std_logic; -- PGP ACK/NACK + vc2FrameTxCid : in std_logic_vector(31 downto 0); -- User frame data, context ID + vc2FrameTxAckCid : out std_logic_vector(31 downto 0); -- PGP ACK/NACK context ID + vc2FrameTxAckEn : out std_logic; -- PGP ACK/NACK enable + vc2FrameTxAck : out std_logic; -- PGP ACK/NACK + vc3FrameTxCid : in std_logic_vector(31 downto 0); -- User frame data, context ID + vc3FrameTxAckCid : out std_logic_vector(31 downto 0); -- PGP ACK/NACK context ID + vc3FrameTxAckEn : out std_logic; -- PGP ACK/NACK enable + vc3FrameTxAck : out std_logic -- PGP ACK/NACK + ); + +end PgpAckRx; + + +-- Define architecture +architecture PgpAckRx of PgpAckRx is + + -- Active context ID memory + component pgp_dpram_51x256 port ( + addra: IN std_logic_VECTOR(7 downto 0); + addrb: IN std_logic_VECTOR(7 downto 0); + clka: IN std_logic; + clkb: IN std_logic; + dina: IN std_logic_VECTOR(50 downto 0); + dinb: IN std_logic_VECTOR(50 downto 0); + doutb: OUT std_logic_VECTOR(50 downto 0); + wea: IN std_logic; + web: IN std_logic + ); end component; + + -- Seq number FIFO + component pgp_fifo_8x256 port ( + clk: IN std_logic; + rst: IN std_logic; + din: IN std_logic_VECTOR(7 downto 0); + wr_en: IN std_logic; + rd_en: IN std_logic; + dout: OUT std_logic_VECTOR(7 downto 0); + full: OUT std_logic; + empty: OUT std_logic + ); end component; + + -- Adder 16+16=16 + component pgp_adder_16_16 + port ( + A : IN std_logic_VECTOR(15 downto 0); + B : IN std_logic_VECTOR(15 downto 0); + S : OUT std_logic_VECTOR(15 downto 0) + ); + end component; + + + -- Local Signals + signal seqNumber : std_logic_vector(7 downto 0); + signal seqNumberInc : std_logic; + signal seqAddrSel : std_logic; + signal seqFifoDin : std_logic_vector(7 downto 0); + signal seqFifoWr : std_logic; + signal seqFifoRd : std_logic; + signal seqFifoRst : std_logic; + signal seqFifoDout : std_logic_vector(7 downto 0); + signal seqFifoDoutVal : std_logic; + signal seqFifoFull : std_logic; + signal intSeqFifoEmpty : std_logic; + signal intCidReady : std_logic; + signal startSeqNum : std_logic_vector(7 downto 0); + signal cidMemAddrA : std_logic_vector(7 downto 0); + signal cidMemAddrB : std_logic_vector(7 downto 0); + signal cidMemDinA : std_logic_vector(50 downto 0); + signal cidMemWrA : std_logic; + signal cidMemWrAReq : std_logic; + signal cidMemWrANext : std_logic; + signal cidMemWrB : std_logic; + signal cidMemRdB : std_logic; + signal cidMemDoutB : std_logic_vector(50 downto 0); + signal intFrameTxAckCid : std_logic_vector(31 downto 0); + signal intFrameTxAckEn : std_logic_vector(3 downto 0); + signal intFrameTxAck : std_logic; + signal nxtFrameTxAckEn : std_logic_vector(3 downto 0); + signal nxtFrameTxAck : std_logic; + signal seqRxFlag : std_logic; + signal dlyRxFlag : std_logic; + signal seqRxFlagClr : std_logic; + signal locCellRxSeq : std_logic_vector(7 downto 0); + signal locCellRxAck : std_logic; + signal ackTimer : std_logic_vector(15 downto 0); + signal ackTimerSum : std_logic_vector(15 downto 0); + signal ackTimerInc : std_logic; + signal muxVcSeq : std_logic_vector(7 downto 0); + signal intVc0Seq : std_logic_vector(7 downto 0); + signal intVc1Seq : std_logic_vector(7 downto 0); + signal intVc2Seq : std_logic_vector(7 downto 0); + signal intVc3Seq : std_logic_vector(7 downto 0); + signal muxFrameTxCid : std_logic_vector(31 downto 0); + signal cidSaveData : std_logic_vector(31 downto 0); + signal regFifoDin : std_logic_vector(7 downto 0); + signal regFifoWr : std_logic; + signal intTimeout : std_logic_vector(15 downto 0); + + -- Context state machine + signal seqState : std_logic_vector(7 downto 0); + signal nxtState : std_logic_vector(7 downto 0); + constant ST_INIT : std_logic_vector(7 downto 0) := "00000001"; + constant ST_WAIT : std_logic_vector(7 downto 0) := "00000010"; + constant ST_FILL : std_logic_vector(7 downto 0) := "00000100"; + constant ST_TIME_RD : std_logic_vector(7 downto 0) := "00001000"; + constant ST_TIME_CHK : std_logic_vector(7 downto 0) := "00010000"; + constant ST_ACK_RD : std_logic_vector(7 downto 0) := "00100000"; + constant ST_ACK_RET : std_logic_vector(7 downto 0) := "01000000"; + constant ST_CID_START : std_logic_vector(7 downto 0) := "10000000"; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + + -- Black Box Attributes + attribute syn_black_box : boolean; + attribute syn_noprune : boolean; + attribute syn_black_box of pgp_dpram_51x256 : component is TRUE; + attribute syn_noprune of pgp_dpram_51x256 : component is TRUE; + attribute syn_black_box of pgp_fifo_8x256 : component is TRUE; + attribute syn_noprune of pgp_fifo_8x256 : component is TRUE; + attribute syn_black_box of pgp_adder_16_16 : component is TRUE; + attribute syn_noprune of pgp_adder_16_16 : component is TRUE; + +begin + + -- Convert Ack Timeout Value + intTimeout <= conv_std_logic_vector(AckTimeout,16); + + -- Sequence number FIFO is empty + seqFifoEmpty <= intSeqFifoEmpty; + cellTxDataSeq <= seqFifoDout; + + -- Nack counter increment + nackCountInc <= '0' when intFrameTxAckEn = "0000" else (not intFrameTxAck); + + -- CID FIFO is ready + cidReady <= seqFifoDoutVal; + + -- Context ID, VC 0 + vc0FrameTxAckCid <= intFrameTxAckCid; + vc0FrameTxAckEn <= intFrameTxAckEn(0); + vc0FrameTxAck <= intFrameTxAck; + + -- Context ID, VC 1 + vc1FrameTxAckCid <= intFrameTxAckCid; + vc1FrameTxAckEn <= intFrameTxAckEn(1); + vc1FrameTxAck <= intFrameTxAck; + + -- Context ID, VC 2 + vc2FrameTxAckCid <= intFrameTxAckCid; + vc2FrameTxAckEn <= intFrameTxAckEn(2); + vc2FrameTxAck <= intFrameTxAck; + + -- Context ID, VC 3 + vc3FrameTxAckCid <= intFrameTxAckCid; + vc3FrameTxAckEn <= intFrameTxAckEn(3); + vc3FrameTxAck <= intFrameTxAck; + + + -- Interface for sechedular to read available seq number values + -- from the seq number FIFO. Also provide interface for the + -- schedular to start the timer for a previously allocated sequence number. + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + seqFifoDoutVal <= '0' after tpd; + seqFifoRd <= '0' after tpd; + startSeqNum <= (others=>'0') after tpd; + cidMemDinA <= (others=>'0') after tpd; + cidMemWrA <= '0' after tpd; + cidMemWrAReq <= '0' after tpd; + intVc0Seq <= (others=>'0') after tpd; + intVc1Seq <= (others=>'0') after tpd; + intVc2Seq <= (others=>'0') after tpd; + intVc3Seq <= (others=>'0') after tpd; + cidSaveData <= (others=>'0') after tpd; + + elsif rising_edge(pgpClk) then + + -- Reset data out on link down + if intCidReady = '0' then + seqFifoDoutVal <= '0' after tpd; + seqFifoRd <= '0' after tpd; + + -- We just read from FIFO + elsif seqFifoRd = '1' then + seqFifoRd <= '0' after tpd; + seqFifoDoutVal <= '1' after tpd; + + -- Scheduler just read seq number + elsif cellTxSOF = '1' then + + -- Clear valid flag, read next sequence number + seqFifoDoutVal <= '0' after tpd; + seqFifoRd <= not intSeqFifoEmpty after tpd; + + -- Store sequence number associted with VC + case cellTxDataVc is + when "00" => intVc0Seq <= seqFifoDout after tpd; + when "01" => intVc1Seq <= seqFifoDout after tpd; + when "10" => intVc2Seq <= seqFifoDout after tpd; + when "11" => intVc3Seq <= seqFifoDout after tpd; + when others => + end case; + + -- Load next value if none is waiting + elsif seqFifoDoutVal = '0' then + seqFifoRd <= not intSeqFifoEmpty after tpd; + end if; + + -- Schedular is passing CID value at the start of a cell. Store the + -- data for now just in case this cell contains an EOF. + if cidSave = '1' then + cidSaveData <= muxFrameTxCid after tpd; + end if; + + -- Memory write occured, clear request + if cidMemWrA = '1' then + cidMemWrAReq <= '0' after tpd; + + -- Schedular has indicated that the timer should start for the + -- current VC. + elsif cidTimerStart = '1' then + startSeqNum <= muxVcSeq after tpd; + cidMemDinA(50) <= '1' after tpd; + cidMemDinA(49 downto 48) <= cellTxDataVc after tpd; + cidMemDinA(47 downto 32) <= ackTimerSum after tpd; + cidMemDinA(31 downto 0) <= cidSaveData after tpd; + cidMemWrAReq <= '1' after tpd; + end if; + + -- Drive write to memory when it is safe, one clock after timer read + cidMemWrA <= cidMemWrAReq and cidMemWrANext after tpd; + + end if; + end process; + + + -- Mux for vc related data + process (cellTxDataVc, intVc0Seq, intVc1Seq, intVc2Seq, intVc3Seq, + vc0FrameTxCid, vc1FrameTxCid, vc2FrameTxCid, vc3FrameTxCid ) begin + case cellTxDataVc is + when "00" => muxVcSeq <= intVc0Seq; muxFrameTxCid <= vc0FrameTxCid; + when "01" => muxVcSeq <= intVc1Seq; muxFrameTxCid <= vc1FrameTxCid; + when "10" => muxVcSeq <= intVc2Seq; muxFrameTxCid <= vc2FrameTxCid; + when "11" => muxVcSeq <= intVc3Seq; muxFrameTxCid <= vc3FrameTxCid; + when others => muxVcSeq <= (others=>'0'); muxFrameTxCid <= (others=>'0'); + end case; + end process; + + + -- Sequence number input state machine. This engine pre-fills the + -- sequence number FIFO when the link goes active, adds received + -- sequence numbers back into the FIFO, removes recieved sequence numbers + -- from the active context memory. This engine will also handle + -- timeouts for the currently active contexts. The timeout values for each + -- of the 256 memory locations are serviced once every 4 clocks. This results + -- in every timer processed every 1024 clocks or 8.192uS. + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + seqState <= ST_INIT after tpd; + seqRxFlag <= '0' after tpd; + dlyRxFlag <= '0' after tpd; + locCellRxSeq <= (others=>'0') after tpd; + locCellRxAck <= '0' after tpd; + seqNumber <= (others=>'0') after tpd; + ackTimer <= (others=>'0') after tpd; + intFrameTxAckCid <= (others=>'0') after tpd; + intFrameTxAck <= '0' after tpd; + intFrameTxAckEn <= "0000" after tpd; + + elsif rising_edge(pgpClk) then + + -- Force back to INIT state when link goes down + if pibLinkReady = '0' then + seqState <= ST_INIT after tpd; + + -- State transition + else + seqState <= nxtState after tpd; + end if; + + -- Clear sequence address value + if pibLinkReady = '0' then + seqNumber <= (others=>'0') after tpd; + + -- Increment address value + elsif seqNumberInc = '1' then + seqNumber <= seqNumber + 1 after tpd; + end if; + + -- Register ack/nack data passed from frame receiver. Mark + -- a flag to indicate pending request. Clear when state machine + -- processes. + if cellRxDone = '1' and cellRxCellError = '0' then + locCellRxSeq <= cellRxSeq after tpd; + locCellRxAck <= cellRxAck after tpd; + seqRxFlag <= cellRxAck or cellRxNack after tpd; + elsif seqRxFlagClr = '1' then + seqRxFlag <= '0' after tpd; + end if; + + -- Delayed copy of receive flag. This is needed to ensure we look at + -- the non delayed flag only once in the state machine. + dlyRxFlag <= seqRxFlag after tpd; + + -- Reset Ack timer + if pibLinkReady = '0' then + ackTimer <= (others=>'0') after tpd; + + -- Increment Ack timer value + elsif ackTimerInc = '1' then + ackTimer <= ackTimer + 1 after tpd; + end if; + + -- Drive outgoing CID ack/nack signals + intFrameTxAckCid <= cidMemDoutB(31 downto 0) after tpd; + intFrameTxAck <= nxtFrameTxAck after tpd; + intFrameTxAckEn <= nxtFrameTxAckEn after tpd; + + end if; + end process; + + + -- State transition control. The following signals are driven in each state: + -- intCidReady : Indicates to schedular that memory init is complete + -- seqFifoWr : Controls writes into the available seq number FIFO + -- cidMemWrB : Controls writes to context memory + -- cidMemRdB : Controls reads from context memory + -- seqAddrSel : Chooses between seq num counter (value=0) and returned seq number + -- seqNumberInc : Increment the seq number counter + -- seqRxFlagClr : Clear the flag indicating a seq number has been passed + -- nxtFrameTxAck : Next outgoing frame ack signal + -- nxtFrameTxAckEn : Next outgoing frame ack signal enable + -- ackTimerInc : Ack timer increment + -- nxtState : Defines which state to proceed to + process ( seqState, seqNumber, cidMemDoutB, ackTimer, + seqFifoFull, seqRxFlag, dlyRxFlag, locCellRxAck ) begin + case seqState is + + -- INIT conect memory and sequence FIFO + when ST_INIT => + + -- Not ready + intCidReady <= '0'; + + -- Fifo is being reset, no mem reads or writes + seqFifoWr <= '0'; + cidMemWrB <= '0'; + cidMemRdB <= '0'; + + -- Seq nubmer is being cleared. Clear any pending receive flags + seqAddrSel <= '0'; + seqNumberInc <= '0'; + ackTimerInc <= '0'; + seqRxFlagClr <= '1'; + + -- No ACK/NACK output + nxtFrameTxAck <= '0'; + nxtFrameTxAckEn <= "0000"; + + -- CID Memory write enable + cidMemWrANext <= '0'; + + -- Start fill of data + nxtState <= ST_WAIT; + + -- Wait for FIFO to be ready following reset + when ST_WAIT => + + -- Not ready + intCidReady <= '0'; + + -- No mem reads or writes + seqFifoWr <= '0'; + cidMemWrB <= '0'; + cidMemRdB <= '0'; + + -- Seq nubmer is being cleared. Clear any pending receive flags + seqAddrSel <= '0'; + seqNumberInc <= '0'; + ackTimerInc <= '0'; + seqRxFlagClr <= '0'; + + -- No ACK/NACK output + nxtFrameTxAck <= '0'; + nxtFrameTxAckEn <= "0000"; + + -- CID Memory write enable + cidMemWrANext <= '0'; + + -- Start fill of data when FIFO full flag de-asserts + if seqFifoFull = '0' then + nxtState <= ST_FILL; + else + nxtState <= seqState; + end if; + + -- Fill sequence FIFO and clear each context memory location + when ST_FILL => + + -- Not ready + intCidReady <= '0'; + + -- Store current count value into sequence number FIFO, clear context mem location + seqFifoWr <= '1'; + cidMemWrB <= '1'; + cidMemRdB <= '0'; + seqAddrSel <= '0'; + seqRxFlagClr <= '0'; + seqNumberInc <= '1'; + ackTimerInc <= '0'; + + -- No ACK/NACK output + nxtFrameTxAck <= '0'; + nxtFrameTxAckEn <= "0000"; + + -- CID Memory write enable + cidMemWrANext <= '0'; + + -- Stop after writing 256 bytes + if seqNumber = 255 then + nxtState <= ST_TIME_RD; + else + nxtState <= seqState; + end if; + + -- Read currnt timer value from current location + when ST_TIME_RD => + + -- Block is ready + intCidReady <= '1'; + + -- Read from current context memory location + seqAddrSel <= '0'; + seqFifoWr <= '0'; + cidMemWrB <= '0'; + cidMemRdB <= '1'; + + -- Don't Increment sequence number + seqNumberInc <= '0'; + ackTimerInc <= '0'; + seqRxFlagClr <= '0'; + + -- No ACK/NACK output + nxtFrameTxAck <= '0'; + nxtFrameTxAckEn <= "0000"; + + -- CID Memory write enable + cidMemWrANext <= '0'; + + -- Go to check state + nxtState <= ST_TIME_CHK; + + -- Check for expired timer in current location + when ST_TIME_CHK => + + -- Block is ready + intCidReady <= '1'; + + -- No memory read + seqAddrSel <= '0'; + cidMemRdB <= '0'; + + -- Increment sequence number + seqNumberInc <= '1'; + seqRxFlagClr <= '0'; + + -- Increment timer if we just read from seq address 255 + if seqNumber = 255 then + ackTimerInc <= '1'; + else + ackTimerInc <= '0'; + end if; + + -- Entry is active and timer expire value matches + if cidMemDoutB(50) = '1' and cidMemDoutB(47 downto 32) = ackTimer(15 downto 0) then + + -- Drive nack output + nxtFrameTxAck <= '0'; + + -- Select dest for ack enable + case cidMemDoutB(49 downto 48) is + when "00" => nxtFrameTxAckEn <= "0001"; + when "01" => nxtFrameTxAckEn <= "0010"; + when "10" => nxtFrameTxAckEn <= "0100"; + when "11" => nxtFrameTxAckEn <= "1000"; + when others => nxtFrameTxAckEn <= "0000"; + end case; + + -- Return seq number to FIFO, Clear context memory + seqFifoWr <= '1'; + cidMemWrB <= '1'; + + -- No Timeout + else + + -- No NACK/ACK + nxtFrameTxAck <= '0'; + nxtFrameTxAckEn <= "0000"; + seqFifoWr <= '0'; + cidMemWrB <= '0'; + end if; + + -- CID Memory write enable + cidMemWrANext <= '0'; + + -- Go to Ack received state + nxtState <= ST_ACK_RD; + + -- Read from context memory if pending ack is ready + when ST_ACK_RD => + + -- Block is ready + intCidReady <= '1'; + + -- Read from current context memory location if ack is pending + seqAddrSel <= '1'; + seqFifoWr <= '0'; + cidMemWrB <= '0'; + cidMemRdB <= seqRxFlag; + + -- Don't Increment sequence number + seqNumberInc <= '0'; + ackTimerInc <= '0'; + seqRxFlagClr <= '0'; + + -- No ACK/NACK output + nxtFrameTxAck <= '0'; + nxtFrameTxAckEn <= "0000"; + + -- CID Memory write enable + cidMemWrANext <= '0'; + + -- Go to check return state + nxtState <= ST_ACK_RET; + + -- Return ack/nack to user if context memory location is active, clear + -- context memory location + when ST_ACK_RET => + + -- Block is ready + intCidReady <= '1'; + + -- No memory read, select return ack value as address + seqAddrSel <= '1'; + cidMemRdB <= '0'; + + -- No timer increments + seqNumberInc <= '0'; + ackTimerInc <= '0'; + + -- Clear rx flag if valid on previous clock + seqRxFlagClr <= dlyRxFlag; + + -- Entry is active and rx flag was valid on previous clock + if dlyRxFlag = '1' and cidMemDoutB(50) = '1' then + + -- Drive ack output + nxtFrameTxAck <= locCellRxAck; + + -- Select dest + case cidMemDoutB(49 downto 48) is + when "00" => nxtFrameTxAckEn <= "0001"; + when "01" => nxtFrameTxAckEn <= "0010"; + when "10" => nxtFrameTxAckEn <= "0100"; + when "11" => nxtFrameTxAckEn <= "1000"; + when others => nxtFrameTxAckEn <= "0000"; + end case; + + -- Return seq number to FIFO, Clear context memory + seqFifoWr <= '1'; + cidMemWrB <= '1'; + + -- Not Active + else + + -- No NACK/ACK + nxtFrameTxAck <= '0'; + nxtFrameTxAckEn <= "0000"; + seqFifoWr <= '0'; + cidMemWrB <= '0'; + end if; + + -- CID Memory write enable + cidMemWrANext <= '0'; + + -- Go to Ack received state + nxtState <= ST_CID_START; + + + -- Timeslot for CID entry creation in memory through port A + when ST_CID_START => + + -- Block is ready + intCidReady <= '1'; + + -- No memory read or timer increments + seqAddrSel <= '0'; + cidMemRdB <= '0'; + seqNumberInc <= '0'; + ackTimerInc <= '0'; + seqRxFlagClr <= '0'; + + -- No NACK/ACK + nxtFrameTxAck <= '0'; + nxtFrameTxAckEn <= "0000"; + seqFifoWr <= '0'; + cidMemWrB <= '0'; + + -- CID Memory write enable + cidMemWrANext <= '1'; + + -- Go to Ack received state + nxtState <= ST_TIME_RD; + + + -- Just in case + when others => + intCidReady <= '0'; + seqAddrSel <= '0'; + cidMemRdB <= '0'; + cidMemWrANext <= '0'; + seqNumberInc <= '0'; + ackTimerInc <= '0'; + seqRxFlagClr <= '0'; + nxtFrameTxAck <= '0'; + nxtFrameTxAckEn <= "0000"; + seqFifoWr <= '0'; + cidMemWrB <= '0'; + nxtState <= ST_INIT; + end case; + end process; + + + + -- Determine which address to use for FIFO input and context memory + -- port B. Chooses between running counter and returned sequence value. + -- Reset the FIFO when the link is not ready + seqFifoDin <= seqNumber when seqAddrSel = '0' else locCellRxSeq; + seqFifoRst <= not pibLinkReady; + + + -- Pipeline writes to FIFO, needed for timing purposes + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + regFifoDin <= (others=>'0') after tpd; + regFifoWr <= '0' after tpd; + elsif rising_edge(pgpClk) then + regFifoDin <= seqFifoDin after tpd; + regFifoWr <= seqFifoWr after tpd; + end if; + end process; + + + -- Sequence number FIFO + U_SeqNumFifo : pgp_fifo_8x256 port map ( + clk => pgpClk, rst => seqFifoRst, + din => regFifoDin, wr_en => regFifoWr, + rd_en => seqFifoRd, dout => seqFifoDout, + full => seqFifoFull, empty => intSeqFifoEmpty + ); + + + -- Keep addresses from lining up, addresses can never match in Xilinx DPRAM + cidMemAddrA <= startSeqNum when cidMemWrA = '1' else not seqFifoDin; + cidMemAddrB <= seqFifoDin when cidMemWrA = '0' else not startSeqNum; + + + -- Active context ID memory + -- Bits 31-0 = cidValue, bits 47-32 = cidTimer, bits 49-48 = VC num, bit 50 is en + -- Writes to port B will always be zero + U_CidMemory : pgp_dpram_51x256 port map ( + clka => pgpClk, clkb => pgpClk, + addra => cidMemAddrA, addrb => cidMemAddrB, + dina => cidMemDinA, dinb => (others=>'0'), + wea => cidMemWrA, web => cidMemWrB, + doutb => cidMemDoutB + ); + + + -- Adder to calculate timeout value for newly created context timers + U_TimerSum : pgp_adder_16_16 port map ( + A => ackTimer, + B => intTimeout, + S => ackTimerSum + ); + +end PgpAckRx; + diff --git a/rce/fw-hsio/modules/pgp/hdl/PgpCellRx.vhd b/rce/fw-hsio/modules/pgp/hdl/PgpCellRx.vhd new file mode 100755 index 00000000..595a0c52 --- /dev/null +++ b/rce/fw-hsio/modules/pgp/hdl/PgpCellRx.vhd @@ -0,0 +1,719 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, Cell Receive Interface +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : PgpCellRx.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 10/24/2006 +------------------------------------------------------------------------------- +-- Description: +-- Cell Receive interface module for the Pretty Good Protocol core. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 10/24/2006: created. +-- 04/18/2007: Added support to track the number of cells in a frame to detect +-- dropped cells. +-- 04/19/2007: Set initial states of buffer status bits to bad +-- 07/19/2007: Removed support to track the number of cells in a frame to detect +-- dropped cells. +-- 07/25/2007: Added support to terminate in progress frames on missed cell. Also +-- added ability to detect missing cells. +-- 09/18/2007: Data is only output for a VC if the VC is currently in frame. +-- Abort flag from rx tracker will end a cell if SOF is received +-- for a VC that is already in frame. SOF of new frame is blocked. +-- 09/18/2007: Added forceCellSize signal to make sure all outgoing cells are +-- 512 bytes unless they are the last in a frame. Frame will be +-- ended with error if this occurs. +-- 09/19/2007: Changed force cell size signal to PIC mode signal +-- Add feature where the following cell after an errored cell will +-- be dropped as well. This ensures the PIC interface code has +-- enough clocks to abort all VCs. +-- 09/20/2007: Added fix so SOF is only aserted for received VC during certain +-- abort situations. SOF can only be asserted in a way that does not +-- violate the SOF-EOF ordering to external logic. +-- 09/21/2007: Converted PIC mode to generic. +-- 10/17/2007: CrcNotZero signal is now registered. +-- 10/24/2007: Fixed error where SOF was not clearing after first word. +-- 11/06/2007: Added cellRxShort flag to indicate to tracking logic that EOFE +-- was generated due to short cell. +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE work.ALL; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity PgpCellRx is + generic ( + PicMode : integer := 0 -- PIC Interface Mode, 1=PIC, 0=Normal + ); + port ( + + -- System clock, reset & control + pgpClk : in std_logic; -- Master clock + pgpReset : in std_logic; -- Synchronous reset input + pibLinkReady : in std_logic; -- PIB Link Ready + + -- Receive Tracking Block + cellRxSOF : out std_logic; -- Cell contained SOF + cellRxDataVc : out std_logic_vector(1 downto 0); -- Cell virtual channel + cellRxEOF : out std_logic; -- Cell contained EOF + cellRxEOFE : out std_logic; -- Cell contained EOFE + cellRxEmpty : out std_logic; -- Cell was empty + cellVcInFrame : in std_logic_vector(3 downto 0); -- Cell VC in frame status + cellVcAbort : in std_logic; -- Cell abort flag for current VC + cellRxStart : out std_logic; -- Cell reception start + cellRxDone : out std_logic; -- Cell reception done + cellRxCellError : out std_logic; -- Cell receieve CRC error + cellRxShort : out std_logic; -- Cell receieve is short (PIC Mode) + cellRxSeq : out std_logic_vector(7 downto 0); -- Cell receieve sequence + cellRxAck : out std_logic; -- Cell receieve ACK + cellRxNAck : out std_logic; -- Cell receieve NACK + + -- Frame Receive Interface, VC 0 + vc0FrameRxValid : out std_logic; -- PGP frame data is valid + vc0FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc0FrameRxWidth : out std_logic; -- PGP frame data width + vc0FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc0FrameRxEOFE : out std_logic; -- PGP frame data error + vc0FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc0RemBuffAFull : out std_logic; -- Remote buffer almost full + vc0RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 1 + vc1FrameRxValid : out std_logic; -- PGP frame data is valid + vc1FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc1FrameRxWidth : out std_logic; -- PGP frame data width + vc1FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc1FrameRxEOFE : out std_logic; -- PGP frame data error + vc1FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc1RemBuffAFull : out std_logic; -- Remote buffer almost full + vc1RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 2 + vc2FrameRxValid : out std_logic; -- PGP frame data is valid + vc2FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc2FrameRxWidth : out std_logic; -- PGP frame data width + vc2FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc2FrameRxEOFE : out std_logic; -- PGP frame data error + vc2FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc2RemBuffAFull : out std_logic; -- Remote buffer almost full + vc2RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 3 + vc3FrameRxValid : out std_logic; -- PGP frame data is valid + vc3FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc3FrameRxWidth : out std_logic; -- PGP frame data width + vc3FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc3FrameRxEOFE : out std_logic; -- PGP frame data error + vc3FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc3RemBuffAFull : out std_logic; -- Remote buffer almost full + vc3RemBuffFull : out std_logic; -- Remote buffer full + + -- Receive CRC Interface + crcRxIn : out std_logic_vector(15 downto 0); -- Receive data for CRC + crcRxInit : out std_logic; -- Receive CRC value init + crcRxValid : out std_logic; -- Receive data for CRC is valid + crcRxWidth : out std_logic; -- Receive data for CRC width + crcRxOut : in std_logic_vector(31 downto 0); -- Receive calculated CRC value + + -- Cell Receive Interface + pibRxSOC : in std_logic; -- Cell data start of cell + pibRxWidth : in std_logic; -- Cell data width + pibRxEOC : in std_logic; -- Cell data end of cell + pibRxEOF : in std_logic; -- Cell data end of frame + pibRxEOFE : in std_logic; -- Cell data end of frame error + pibRxData : in std_logic_vector(15 downto 0) -- Cell data data + ); + +end PgpCellRx; + + +-- Define architecture +architecture PgpCellRx of PgpCellRx is + + -- Local Signals + signal dly0SOC : std_logic; + signal dly0Width : std_logic; + signal dly0EOC : std_logic; + signal dly0EOF : std_logic; + signal dly0EOFE : std_logic; + signal dly0Data : std_logic_vector(15 downto 0); + signal dly1SOC : std_logic; + signal dly1Width : std_logic; + signal dly1EOC : std_logic; + signal dly1EOF : std_logic; + signal dly1EOFE : std_logic; + signal dly1Data : std_logic_vector(15 downto 0); + signal dly2SOC : std_logic; + signal dly2Width : std_logic; + signal dly2EOC : std_logic; + signal dly2EOF : std_logic; + signal dly2EOFE : std_logic; + signal dly2Data : std_logic_vector(15 downto 0); + signal dly3SOC : std_logic; + signal dly3Width : std_logic; + signal dly3EOC : std_logic; + signal dly3EOF : std_logic; + signal dly3EOFE : std_logic; + signal dly3Data : std_logic_vector(15 downto 0); + signal dly4SOC : std_logic; + signal dly4EOC : std_logic; + signal dly4Data : std_logic_vector(15 downto 0); + signal dly5SOC : std_logic; + signal dly5Data : std_logic_vector(15 downto 0); + signal dly6SOC : std_logic; + signal dly7SOC : std_logic; + signal inCellCrc : std_logic; + signal crcNotZero : std_logic; + signal intCellRxSOF : std_logic; + signal intCellRxEmpty : std_logic; + signal intCellRxDataVc : std_logic_vector(1 downto 0); + signal intBuffAFull : std_logic_vector(3 downto 0); + signal intBuffFull : std_logic_vector(3 downto 0); + signal intFrameRxValid : std_logic_vector(3 downto 0); + signal muxFrameRxValid : std_logic_vector(3 downto 0); + signal muxFrameRxSOF : std_logic_vector(3 downto 0); + signal intFrameRxSOF : std_logic_vector(3 downto 0); + signal intFrameRxWidth : std_logic; + signal intFrameRxEOF : std_logic; + signal intFrameRxEOFE : std_logic; + signal intFrameRxData : std_logic_vector(15 downto 0); + signal interCellCount : std_logic_vector(4 downto 0); + signal expSerial : std_logic_vector(1 downto 0); + signal cellSerial : std_logic_vector(1 downto 0); + signal inCellRx : std_logic; + signal linkReadyDly : std_logic; + signal intRxCellError : std_logic; + signal firstCellRx : std_logic; + signal cellRxSize : std_logic_vector(7 downto 0); + signal dropNextCell : std_logic; + signal intMode : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Convert Pic Mode Generic + intMode <= '0' when PicMode = 0 else '1'; + + -- Interface to CRC calculator + crcRxInit <= pibRxSOC; + crcRxValid <= pibRxSOC or inCellCrc; + crcRxWidth <= pibRxWidth and not pibRxSOC; + --crcNotZero <= '0' when crcRxOut = 0 else '1'; + + -- Crc data may be switched + crcRxIn(7 downto 0) <= pibRxData(7 downto 0) when pibRxSOC='0' else pibRxData(15 downto 8); + crcRxIn(15 downto 8) <= pibRxData(15 downto 8) when pibRxSOC='0' else pibRxData(7 downto 0); + + -- Outputs to tracking blocks + cellRxStart <= dly6SOC; + cellRxEOF <= intFrameRxEOF; + cellRxEOFE <= intFrameRxEOFE; + cellRxEmpty <= intCellRxEmpty; + cellRxDataVc <= intCellRxDataVc; + cellRxSOF <= intCellRxSOF; + cellRxCellError <= intRxCellError; + + -- Frame Receive Interface, VC 0 + vc0FrameRxValid <= intFrameRxValid(0); + vc0FrameRxSOF <= intFrameRxSOF(0); + vc0FrameRxWidth <= intFrameRxWidth; + vc0FrameRxEOF <= intFrameRxEOF; + vc0FrameRxEOFE <= intFrameRxEOFE; + vc0FrameRxData <= intFrameRxData; + + -- Frame Receive Interface, VC 1 + vc1FrameRxValid <= intFrameRxValid(1); + vc1FrameRxSOF <= intFrameRxSOF(1); + vc1FrameRxWidth <= intFrameRxWidth; + vc1FrameRxEOF <= intFrameRxEOF; + vc1FrameRxEOFE <= intFrameRxEOFE; + vc1FrameRxData <= intFrameRxData; + + -- Frame Receive Interface, VC 2 + vc2FrameRxValid <= intFrameRxValid(2); + vc2FrameRxSOF <= intFrameRxSOF(2); + vc2FrameRxWidth <= intFrameRxWidth; + vc2FrameRxEOF <= intFrameRxEOF; + vc2FrameRxEOFE <= intFrameRxEOFE; + vc2FrameRxData <= intFrameRxData; + + -- Frame Receive Interface, VC 3 + vc3FrameRxValid <= intFrameRxValid(3); + vc3FrameRxSOF <= intFrameRxSOF(3); + vc3FrameRxWidth <= intFrameRxWidth; + vc3FrameRxEOF <= intFrameRxEOF; + vc3FrameRxEOFE <= intFrameRxEOFE; + vc3FrameRxData <= intFrameRxData; + + + -- Delay stages to line up data with CRC calculation + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + dly0SOC <= '0' after tpd; + dly0Width <= '0' after tpd; + dly0EOC <= '0' after tpd; + dly0EOF <= '0' after tpd; + dly0EOFE <= '0' after tpd; + dly0Data <= (others=>'0') after tpd; + dly1SOC <= '0' after tpd; + dly1Width <= '0' after tpd; + dly1EOC <= '0' after tpd; + dly1EOF <= '0' after tpd; + dly1EOFE <= '0' after tpd; + dly1Data <= (others=>'0') after tpd; + dly2SOC <= '0' after tpd; + dly2Width <= '0' after tpd; + dly2EOC <= '0' after tpd; + dly2EOF <= '0' after tpd; + dly2EOFE <= '0' after tpd; + dly2Data <= (others=>'0') after tpd; + dly3SOC <= '0' after tpd; + dly3Width <= '0' after tpd; + dly3EOC <= '0' after tpd; + dly3EOF <= '0' after tpd; + dly3EOFE <= '0' after tpd; + dly3Data <= (others=>'0') after tpd; + dly4SOC <= '0' after tpd; + dly4EOC <= '0' after tpd; + dly4Data <= (others=>'0') after tpd; + dly5SOC <= '0' after tpd; + dly5Data <= (others=>'0') after tpd; + dly6SOC <= '0' after tpd; + dly7SOC <= '0' after tpd; + inCellCrc <= '0' after tpd; + elsif rising_edge(pgpClk) then + + -- CRC Enable + if pibRxSOC = '1' then + inCellCrc <= '1' after tpd; + elsif pibRxEOC = '1' then + inCellCrc <= '0' after tpd; + end if; + + -- Delay stage 0 + dly0SOC <= pibRxSOC after tpd; + dly0Width <= pibRxWidth after tpd; + dly0EOC <= pibRxEOC after tpd; + dly0EOF <= pibRxEOF after tpd; + dly0EOFE <= pibRxEOFE after tpd; + dly0Data <= pibRxData after tpd; + + -- Delay stage 1 + dly1SOC <= dly0SOC after tpd; + dly1Width <= dly0Width after tpd; + dly1EOC <= dly0EOC after tpd; + dly1EOF <= dly0EOF after tpd; + dly1EOFE <= dly0EOFE after tpd; + dly1Data <= dly0Data after tpd; + + -- Delay stage 2 + dly2SOC <= dly1SOC after tpd; + dly2Width <= dly1Width after tpd; + dly2EOC <= dly1EOC after tpd; + dly2EOF <= dly1EOF after tpd; + dly2EOFE <= dly1EOFE after tpd; + dly2Data <= dly1Data after tpd; + + -- Delay stage 3 + dly3SOC <= dly2SOC after tpd; + dly3Width <= dly2Width after tpd; + dly3EOC <= dly2EOC after tpd; + dly3EOF <= dly2EOF after tpd; + dly3EOFE <= dly2EOFE after tpd; + dly3Data <= dly2Data after tpd; + + -- Delay stage 4 + dly4SOC <= dly3SOC after tpd; + dly4EOC <= dly3EOC after tpd; + dly4Data <= dly3Data after tpd; + + -- Delay stage 5 + dly5SOC <= dly4SOC after tpd; + dly5Data <= dly4Data after tpd; + + -- Delay stage 6 & 7, extra for SOC to drop header + dly6SOC <= dly5SOC after tpd; + dly7SOC <= dly6SOC after tpd; + end if; + end process; + + + -- MUX in frame status bits for transmit. + -- Valid is asserted if current VC is active or the abort flag + -- has been asserted. + process ( intCellRxDataVc, cellVcInFrame, cellVcAbort ) begin + case intCellRxDataVc is + when "00" => + muxFrameRxValid(0) <= cellVcInFrame(0) or cellVcAbort; + muxFrameRxValid(1) <= '0'; + muxFrameRxValid(2) <= '0'; + muxFrameRxValid(3) <= '0'; + when "01" => + muxFrameRxValid(0) <= '0'; + muxFrameRxValid(1) <= cellVcInFrame(1) or cellVcAbort; + muxFrameRxValid(2) <= '0'; + muxFrameRxValid(3) <= '0'; + when "10" => + muxFrameRxValid(0) <= '0'; + muxFrameRxValid(1) <= '0'; + muxFrameRxValid(2) <= cellVcInFrame(2) or cellVcAbort; + muxFrameRxValid(3) <= '0'; + when "11" => + muxFrameRxValid(0) <= '0'; + muxFrameRxValid(1) <= '0'; + muxFrameRxValid(2) <= '0'; + muxFrameRxValid(3) <= cellVcInFrame(3) or cellVcAbort; + when others => muxFrameRxValid <= "0000"; + end case; + end process; + + + -- MUX SOF status bits for transmit. + -- SOF is asserted if this is an SOF cell, the current VC is active + -- and the abort flag has not been asserted. + process ( intCellRxDataVc, cellVcInFrame, cellVcAbort, intCellRxSOF ) begin + case intCellRxDataVc is + when "00" => + muxFrameRxSOF(0) <= cellVcInFrame(0) and intCellRxSOF and not cellVcAbort; + muxFrameRxSOF(1) <= '0'; + muxFrameRxSOF(2) <= '0'; + muxFrameRxSOF(3) <= '0'; + when "01" => + muxFrameRxSOF(0) <= '0'; + muxFrameRxSOF(1) <= cellVcInFrame(1) and intCellRxSOF and not cellVcAbort; + muxFrameRxSOF(2) <= '0'; + muxFrameRxSOF(3) <= '0'; + when "10" => + muxFrameRxSOF(0) <= '0'; + muxFrameRxSOF(1) <= '0'; + muxFrameRxSOF(2) <= cellVcInFrame(2) and intCellRxSOF and not cellVcAbort; + muxFrameRxSOF(3) <= '0'; + when "11" => + muxFrameRxSOF(0) <= '0'; + muxFrameRxSOF(1) <= '0'; + muxFrameRxSOF(2) <= '0'; + muxFrameRxSOF(3) <= cellVcInFrame(3) and intCellRxSOF and not cellVcAbort; + when others => muxFrameRxSOF <= "0000"; + end case; + end process; + + + -- Receive cell tracking + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + intCellRxSOF <= '0' after tpd; + intCellRxDataVc <= "00" after tpd; + intCellRxEmpty <= '0' after tpd; + cellRxSeq <= (others=>'0') after tpd; + cellRxAck <= '0' after tpd; + cellRxNAck <= '0' after tpd; + intBuffAFull <= (others=>'0') after tpd; + intBuffFull <= (others=>'0') after tpd; + cellSerial <= "00" after tpd; + intFrameRxValid <= "0000" after tpd; + intFrameRxSOF <= "0000" after tpd; + intFrameRxEOF <= '0' after tpd; + intFrameRxEOFE <= '0' after tpd; + intFrameRxWidth <= '0' after tpd; + intFrameRxData <= (others=>'0') after tpd; + cellRxDone <= '0' after tpd; + intRxCellError <= '0' after tpd; + interCellCount <= (others=>'0') after tpd; + expSerial <= "00" after tpd; + inCellRx <= '0' after tpd; + linkReadyDly <= '0' after tpd; + firstCellRx <= '0' after tpd; + cellRxSize <= (others=>'0') after tpd; + dropNextCell <= '0' after tpd; + crcNotZero <= '0' after tpd; + cellRxShort <= '0' after tpd; + elsif rising_edge(pgpClk) then + + -- CRC Error + if crcRxOut = 0 then + crcNotZero <= '0' after tpd; + else + crcNotZero <= '1' after tpd; + end if; + + -- Delayed copy of link ready + linkReadyDly <= pibLinkready after tpd; + + -- Register header data when enough data has been received + if dly5SOC = '1' then + + -- Frame type, + -- Force empty flag if cell is marked to be dropped + case dly5Data(15 downto 14) is + when "00" => -- IDLE + intCellRxSOF <= '0' after tpd; + intCellRxEmpty <= '1' after tpd; + cellRxAck <= dly5Data(13) after tpd; + cellRxNAck <= dly5Data(12) after tpd; + when "01" => -- Payload + intCellRxSOF <= '0' after tpd; + intCellRxEmpty <= dropNextCell after tpd; + cellRxAck <= dly5Data(13) after tpd; + cellRxNAck <= dly5Data(12) after tpd; + when "10" => -- Reserved + intCellRxSOF <= '0' after tpd; + intCellRxEmpty <= '1' after tpd; + cellRxAck <= '0' after tpd; + cellRxNAck <= '0' after tpd; + when "11" => -- SOF + intCellRxSOF <= '1' after tpd; + intCellRxEmpty <= dropNextCell after tpd; + cellRxAck <= '0' after tpd; + cellRxNAck <= '0' after tpd; + when others => + intCellRxSOF <= '0' after tpd; + intCellRxEmpty <= '0' after tpd; + cellRxAck <= '0' after tpd; + cellRxNAck <= '0' after tpd; + end case; + + -- Cell Flags + intCellRxDataVc <= dly5Data(11 downto 10) after tpd; + cellSerial <= dly5Data(9 downto 8) after tpd; + cellRxSeq <= dly4Data(7 downto 0) after tpd; + + -- VC Flags + intBuffFull <= dly4Data(15 downto 12) after tpd; + intBuffAFull <= dly4Data(11 downto 8) after tpd; + end if; + + -- Inter cell counter, don't start count until first cell is received. + if pibLinkReady = '0' then + interCellCount <= (others=>'0') after tpd; + firstCellRx <= '0' after tpd; + elsif inCellRx = '1' then + interCellCount <= (others=>'0') after tpd; + firstCellRx <= '1' after tpd; + elsif interCellCount /= 27 and firstCellRx = '1' then + interCellCount <= interCellCount + 1 after tpd; + end if; + + -- Count size of each cell received + if inCellRx = '1' then + cellRxSize <= cellRxSize + 1 after tpd; + else + cellRxSize <= (others=>'0') after tpd; + end if; + + -- Link is down. + if pibLinkReady = '0' then + + -- Reset expected serial + expSerial <= "00" after tpd; + inCellRx <= '0' after tpd; + dropNextCell <= '0' after tpd; + intFrameRxSOF <= "0000" after tpd; + + -- Link just went down. Send EOFE to all active VCs + if linkReadyDly = '1' then + intFrameRxValid <= cellVcInFrame after tpd; + intFrameRxEOF <= '1' after tpd; + intFrameRxEOFE <= '1' after tpd; + else + intFrameRxValid <= "0000" after tpd; + intFrameRxEOF <= '0' after tpd; + intFrameRxEOFE <= '0' after tpd; + end if; + + -- Special case for 1 or 2 byte cells. SOC in delay 7 pos and + -- EOC in delay 3 pos. + elsif dly7SOC = '1' and dly3EOC = '1' then + + -- Mark in frame + inCellRx <= '1' after tpd; + + -- Receive is done + cellRxDone <= '1' after tpd; + + -- Look for large gap between cells or cell number mismatch + -- Mark all inFrame VCs as active and output error + -- Set drop next cell flag if in pic mode + -- Mark SOF for current VC if SOF Cell + if interCellCount = 27 or expSerial /= cellSerial then + intFrameRxValid <= cellVcInFrame after tpd; + intFrameRxEOF <= '1' after tpd; + intFrameRxEOFE <= '1' after tpd; + intRxCellError <= '1' after tpd; + expSerial <= cellSerial after tpd; + dropNextCell <= intMode after tpd; + intFrameRxSOF <= muxFrameRxSOF after tpd; + + -- CRC Error, Mark all in frame VCs as active output EOF with error + -- Set drop next cell flag if in pic mode + -- Mark SOF for current VC if SOF Cell + -- even if VC is in error, rx track will generate correct SOF + -- which won't confuse external logic + elsif crcNotZero = '1' then + intFrameRxValid <= cellVcInFrame after tpd; + intFrameRxEOF <= '1' after tpd; + intFrameRxEOFE <= '1' after tpd; + intRxCellError <= '1' after tpd; + dropNextCell <= intMode after tpd; + intFrameRxSOF <= muxFrameRxSOF after tpd; + + -- Non-Errored Frame Reception, + else + + -- Choose active VC if cell is not empty. + if intCellRxEmpty = '0' then + intFrameRxValid <= muxFrameRxValid after tpd; + intFrameRxSOF <= muxFrameRxSOF after tpd; + end if; + + -- Clear drop next cell flag + dropNextCell <= '0'; + + -- Cell size enforecement. If cell is not an EOF and force cell + -- size is asserted then end frame in error + if intMode = '1' and dly3EOF = '0' and intCellRxEmpty = '0' then + intFrameRxEOF <= '1' after tpd; + intFrameRxEOFE <= '1' after tpd; + cellRxShort <= '1' after tpd; + + -- Set EOF and EOFE, force EOF and EOFE if abort is asserted + else + intFrameRxEOF <= dly3EOF or cellVcAbort after tpd; + intFrameRxEOFE <= dly3EOFE or cellVcAbort after tpd; + end if; + end if; + + -- Start of data movement when SOC is in delay 7 position. + elsif dly7SOC = '1' then + + -- Mark in frame + inCellRx <= '1' after tpd; + + -- Look for large gap between cells or cell number mismatch + -- Mark cell as in error and do not output to any VCs + -- Mark SOF for current VC if SOF Cell + if interCellCount = 27 or expSerial /= cellSerial then + intFrameRxValid <= "0000" after tpd; + intRxCellError <= '1' after tpd; + expSerial <= cellSerial after tpd; + intFrameRxSOF <= muxFrameRxSOF after tpd; + + -- Normal cell reception, Choose active VC + else + + -- Choose active VC if cell is not empty + if intCellRxEmpty = '0' then + intFrameRxValid <= muxFrameRxValid after tpd; + intFrameRxSOF <= muxFrameRxSOF after tpd; + end if; + + -- Clear drop next cell flag + dropNextCell <= '0'; + end if; + + -- EOC arrives in delay position 3 when cell is done + elsif dly3EOC = '1' then + + -- Receive is done + cellRxDone <= '1' after tpd; + intFrameRxSOF <= "0000" after tpd; + + -- End of frame forced by error, all active VCs get EOFE + -- Set drop next cell flag if in pic mode + if crcNotZero = '1' or intRxCellError = '1' then + intFrameRxValid <= cellVcInFrame after tpd; + intFrameRxEOF <= '1' after tpd; + intFrameRxEOFE <= '1' after tpd; + intRxCellError <= '1' after tpd; + dropNextCell <= intMode after tpd; + + -- Cell size enforecement. If cell is not full, EOF is not asserted + -- and force cell size is asserted then end frame in error + elsif intMode = '1' and dly3EOF = '0' and + cellRxSize /= 254 and intCellRxEmpty = '0' then + intFrameRxEOF <= '1' after tpd; + intFrameRxEOFE <= '1' after tpd; + cellRxShort <= '1' after tpd; + + -- Normal End of frame detected + -- Set EOF and EOFE, force EOF and EOFE if abort is asserted + else + intFrameRxEOF <= dly3EOF or cellVcAbort after tpd; + intFrameRxEOFE <= dly3EOFE or cellVcAbort after tpd; + end if; + + -- Detect End Of Frame, clear flags + elsif dly4EOC = '1' then + + -- Increment expected serial number for next cell + expSerial <= expSerial + 1 after tpd; + + -- Clear EOF, Done, error and valid signals + inCellRx <= '0' after tpd; + intFrameRxSOF <= "0000" after tpd; + intFrameRxEOF <= '0' after tpd; + intFrameRxEOFE <= '0' after tpd; + cellRxDone <= '0' after tpd; + intRxCellError <= '0' after tpd; + intFrameRxValid <= "0000" after tpd; + cellRxShort <= '0' after tpd; + + -- Clear SOF after first byte + else + intFrameRxSOF <= "0000" after tpd; + end if; + + -- Data output, width follows delay 4 + intFrameRxWidth <= dly3Width after tpd; + intFrameRxData <= dly5Data after tpd; + + end if; + end process; + + + -- Update buffer status on successfull cell reception + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + vc0RemBuffAFull <= '1' after tpd; + vc0RemBuffFull <= '1' after tpd; + vc1RemBuffAFull <= '1' after tpd; + vc1RemBuffFull <= '1' after tpd; + vc2RemBuffAFull <= '1' after tpd; + vc2RemBuffFull <= '1' after tpd; + vc3RemBuffAFull <= '1' after tpd; + vc3RemBuffFull <= '1' after tpd; + elsif rising_edge(pgpClk) then + + -- Link is not ready, force buffer states to bad + if pibLinkReady = '0' then + vc0RemBuffAFull <= '1' after tpd; + vc0RemBuffFull <= '1' after tpd; + vc1RemBuffAFull <= '1' after tpd; + vc1RemBuffFull <= '1' after tpd; + vc2RemBuffAFull <= '1' after tpd; + vc2RemBuffFull <= '1' after tpd; + vc3RemBuffAFull <= '1' after tpd; + vc3RemBuffFull <= '1' after tpd; + + -- Update buffer status if there was no CRC error + elsif dly3EOC = '1' and crcNotZero = '0' then + vc0RemBuffAFull <= intBuffAFull(0) after tpd; + vc0RemBuffFull <= intBuffFull(0) after tpd; + vc1RemBuffAFull <= intBuffAFull(1) after tpd; + vc1RemBuffFull <= intBuffFull(1) after tpd; + vc2RemBuffAFull <= intBuffAFull(2) after tpd; + vc2RemBuffFull <= intBuffFull(2) after tpd; + vc3RemBuffAFull <= intBuffAFull(3) after tpd; + vc3RemBuffFull <= intBuffFull(3) after tpd; + end if; + end if; + end process; + +end PgpCellRx; + diff --git a/rce/fw-hsio/modules/pgp/hdl/PgpCellTx.vhd b/rce/fw-hsio/modules/pgp/hdl/PgpCellTx.vhd new file mode 100644 index 00000000..2752a4b9 --- /dev/null +++ b/rce/fw-hsio/modules/pgp/hdl/PgpCellTx.vhd @@ -0,0 +1,702 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, Cell Transmit Interface +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : PgpCellTx.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 10/24/2006 +------------------------------------------------------------------------------- +-- Description: +-- Cell Transmit interface module for the Pretty Good Protocol core. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 10/24/2006: created. +-- 04/16/2007: Modified to a more pipelined design alloing back to back cell +-- tranmission as well as fixing some bugs related to short frames +-- 04/18/2007: Added support to track the number of cells in a frame to detect +-- dropped cells. +-- 06/19/2007: Moved rand data logic into this block. +-- 07/19/2007: Removed support to track the number of cells in a frame. Added +-- cell sequence number. +-- 09/18/2007: Added logic to force error if width='0' without EOF +-- 09/21/2007: Removed payload imput +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE work.ALL; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity PgpCellTx is port ( + + -- System clock, reset & control + pgpClk : in std_logic; -- Master clock + pgpReset : in std_logic; -- Synchronous reset input + + -- PIB Interface + pibLinkReady : in std_logic; -- PIB Link Ready + + -- Transmit Scheduler Interface + cellTxDataSeq : in std_logic_vector(7 downto 0); -- Transmit sequence number + cellTxSOF : out std_logic; -- Cell contained SOF + cellTxEOF : out std_logic; -- Cell contained EOF + cellTxIdle : in std_logic; -- Force IDLE transmit + cellTxReq : in std_logic; -- Cell transmit request + cellTxInp : out std_logic; -- Cell transmit in progress + cellTxDataVc : in std_logic_vector(1 downto 0); -- Cell transmit virtual channel + + -- ACK/NACK Transmit Logic + cellTxNAck : in std_logic; -- Cell transmit NACK request + cellTxAck : in std_logic; -- Cell transmit ACK request + cellTxAckSeq : in std_logic_vector(7 downto 0); -- Cell transmit ACK sequence + cellTxAcked : out std_logic; -- Cell transmit ACK was sent + + -- Frame Transmit Interface, VC 0 + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc0FrameTxReady : out std_logic; -- PGP is ready + vc0FrameTxSOF : in std_logic; -- User frame data start of frame + vc0FrameTxWidth : in std_logic; -- User frame data width + vc0FrameTxEOF : in std_logic; -- User frame data end of frame + vc0FrameTxEOFE : in std_logic; -- User frame data error + vc0FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc0LocBuffAFull : in std_logic; -- Remote buffer almost full + vc0LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 1 + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxReady : out std_logic; -- PGP is ready + vc1FrameTxSOF : in std_logic; -- User frame data start of frame + vc1FrameTxWidth : in std_logic; -- User frame data width + vc1FrameTxEOF : in std_logic; -- User frame data end of frame + vc1FrameTxEOFE : in std_logic; -- User frame data error + vc1FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc1LocBuffAFull : in std_logic; -- Remote buffer almost full + vc1LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 2 + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxReady : out std_logic; -- PGP is ready + vc2FrameTxSOF : in std_logic; -- User frame data start of frame + vc2FrameTxWidth : in std_logic; -- User frame data width + vc2FrameTxEOF : in std_logic; -- User frame data end of frame + vc2FrameTxEOFE : in std_logic; -- User frame data error + vc2FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc2LocBuffAFull : in std_logic; -- Remote buffer almost full + vc2LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 3 + vc3FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxReady : out std_logic; -- PGP is ready + vc3FrameTxSOF : in std_logic; -- User frame data start of frame + vc3FrameTxWidth : in std_logic; -- User frame data width + vc3FrameTxEOF : in std_logic; -- User frame data end of frame + vc3FrameTxEOFE : in std_logic; -- User frame data error + vc3FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc3LocBuffAFull : in std_logic; -- Remote buffer almost full + vc3LocBuffFull : in std_logic; -- Remote buffer full + + -- PHY Interface + pibTxSOC : out std_logic; -- Cell data start of cell + pibTxWidth : out std_logic; -- Cell data width + pibTxEOC : out std_logic; -- Cell data end of cell + pibTxEOF : out std_logic; -- Cell data end of frame + pibTxEOFE : out std_logic; -- Cell data end of frame error + pibTxData : out std_logic_vector(15 downto 0); -- Cell data data + + -- Transmit CRC Interface + crcTxIn : out std_logic_vector(15 downto 0); -- Transmit data for CRC + crcTxInit : out std_logic; -- Transmit CRC value init + crcTxValid : out std_logic; -- Transmit data for CRC is valid + crcTxWidth : out std_logic; -- Transmit data for CRC width + crcTxOut : in std_logic_vector(31 downto 0) -- Transmit calculated CRC value + ); + +end PgpCellTx; + + +-- Define architecture +architecture PgpCellTx of PgpCellTx is + + -- Local Signals + signal muxFrameTxValid : std_logic; + signal muxFrameTxSOF : std_logic; + signal muxFrameTxWidth : std_logic; + signal muxFrameTxEOF : std_logic; + signal muxFrameTxEOFE : std_logic; + signal muxFrameTxData : std_logic_vector(15 downto 0); + signal dlyFrameTxData : std_logic_vector(15 downto 0); + signal dlyFrameTxEOF : std_logic; + signal dlyFrameTxEOFE : std_logic; + signal dlyFrameTxWidth : std_logic; + signal selSOC : std_logic; + signal selValid : std_logic; + signal selWidth : std_logic; + signal selEOF : std_logic; + signal selEOFE : std_logic; + signal selCrcMask : std_logic_vector(3 downto 0); + signal selData : std_logic_vector(15 downto 0); + signal frameReadyOut : std_logic; + signal payloadCount : std_logic_vector(8 downto 0); + signal dly1TxSOC : std_logic; + signal dly1TxEOF : std_logic; + signal dly1TxEOFE : std_logic; + signal dly1CrcMask : std_logic_vector(3 downto 0); + signal dly1TxData : std_logic_vector(15 downto 0); + signal dly2TxSOC : std_logic; + signal dly2TxEOF : std_logic; + signal dly2TxEOFE : std_logic; + signal dly2CrcMask : std_logic_vector(3 downto 0); + signal dly2TxData : std_logic_vector(15 downto 0); + signal dly3TxSOC : std_logic; + signal dly3TxEOF : std_logic; + signal dly3TxEOFE : std_logic; + signal dly3CrcMask : std_logic_vector(3 downto 0); + signal dly3TxData : std_logic_vector(15 downto 0); + signal dly4TxSOC : std_logic; + signal dly4TxEOF : std_logic; + signal dly4TxEOFE : std_logic; + signal dly4CrcMask : std_logic_vector(3 downto 0); + signal dly4TxData : std_logic_vector(15 downto 0); + signal nextAcked : std_logic; + signal randData : std_logic_vector(15 downto 0); + signal cellSerial : std_logic_vector(1 downto 0); + + -- Transmit states + signal txState : std_logic_vector(2 downto 0); + constant ST_IDLE : std_logic_vector(2 downto 0) := "000"; + constant ST_HEAD0 : std_logic_vector(2 downto 0) := "001"; + constant ST_HEAD1 : std_logic_vector(2 downto 0) := "010"; + constant ST_PAYLD : std_logic_vector(2 downto 0) := "011"; + constant ST_CRC01 : std_logic_vector(2 downto 0) := "100"; + constant ST_CRC23 : std_logic_vector(2 downto 0) := "101"; + constant ST_CRC12 : std_logic_vector(2 downto 0) := "110"; + constant ST_CRC3 : std_logic_vector(2 downto 0) := "111"; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Interface to CRC calculator + crcTxInit <= selSOC; + crcTxValid <= selValid; + crcTxWidth <= selWidth; + + -- Crc data may be switched + crcTxIn(7 downto 0) <= selData(7 downto 0) when selSOC = '0' else selData(15 downto 8); + crcTxIn(15 downto 8) <= selData(15 downto 8) when selSOC = '0' else selData(7 downto 0); + + + -- Mux incoming data depending on squence number, drive outgoing ready + process ( cellTxDataVc, vc0FrameTxValid, vc0FrameTxSOF, vc0FrameTxWidth, + vc0FrameTxEOF, vc0FrameTxEOFE, vc0FrameTxData, vc1FrameTxValid, + vc1FrameTxSOF, vc1FrameTxWidth, vc1FrameTxEOF, vc1FrameTxEOFE, + vc1FrameTxData, vc2FrameTxValid, vc2FrameTxSOF, vc2FrameTxWidth, + vc2FrameTxEOF, vc2FrameTxEOFE, vc2FrameTxData, vc3FrameTxValid, + vc3FrameTxSOF, vc3FrameTxWidth, vc3FrameTxEOF, vc3FrameTxEOFE, + vc3FrameTxData, frameReadyOut, cellTxIdle, randData ) begin + + -- Use random data when not transmitting a frame or when + -- transmitting the payload of an IDLE cell + if cellTxIdle = '1' then + muxFrameTxValid <= '1'; + muxFrameTxSOF <= '0'; + muxFrameTxWidth <= '1'; + muxFrameTxEOF <= '0'; + muxFrameTxEOFE <= '0'; + muxFrameTxData <= randData; + vc0FrameTxReady <= '0'; + vc1FrameTxReady <= '0'; + vc2FrameTxReady <= '0'; + vc3FrameTxReady <= '0'; + + -- Choose virtual channel when not transmitting IDLE cell and when + -- scheduler wants a frame transmitted. + else case cellTxDataVc is + when "00" => + muxFrameTxValid <= vc0FrameTxValid; + muxFrameTxSOF <= vc0FrameTxSOF; + muxFrameTxWidth <= vc0FrameTxWidth; + muxFrameTxEOF <= vc0FrameTxEOF; + muxFrameTxEOFE <= vc0FrameTxEOFE; + muxFrameTxData <= vc0FrameTxData; + vc0FrameTxReady <= frameReadyOut; + vc1FrameTxReady <= '0'; + vc2FrameTxReady <= '0'; + vc3FrameTxReady <= '0'; + when "01" => + muxFrameTxValid <= vc1FrameTxValid; + muxFrameTxSOF <= vc1FrameTxSOF; + muxFrameTxWidth <= vc1FrameTxWidth; + muxFrameTxEOF <= vc1FrameTxEOF; + muxFrameTxEOFE <= vc1FrameTxEOFE; + muxFrameTxData <= vc1FrameTxData; + vc0FrameTxReady <= '0'; + vc1FrameTxReady <= frameReadyOut; + vc2FrameTxReady <= '0'; + vc3FrameTxReady <= '0'; + when "10" => + muxFrameTxValid <= vc2FrameTxValid; + muxFrameTxSOF <= vc2FrameTxSOF; + muxFrameTxWidth <= vc2FrameTxWidth; + muxFrameTxEOF <= vc2FrameTxEOF; + muxFrameTxEOFE <= vc2FrameTxEOFE; + muxFrameTxData <= vc2FrameTxData; + vc0FrameTxReady <= '0'; + vc1FrameTxReady <= '0'; + vc2FrameTxReady <= frameReadyOut; + vc3FrameTxReady <= '0'; + when "11" => + muxFrameTxValid <= vc3FrameTxValid; + muxFrameTxSOF <= vc3FrameTxSOF; + muxFrameTxWidth <= vc3FrameTxWidth; + muxFrameTxEOF <= vc3FrameTxEOF; + muxFrameTxEOFE <= vc3FrameTxEOFE; + muxFrameTxData <= vc3FrameTxData; + vc0FrameTxReady <= '0'; + vc1FrameTxReady <= '0'; + vc2FrameTxReady <= '0'; + vc3FrameTxReady <= frameReadyOut; + when others => + muxFrameTxValid <= '0'; + muxFrameTxSOF <= '0'; + muxFrameTxWidth <= '0'; + muxFrameTxEOF <= '0'; + muxFrameTxEOFE <= '0'; + muxFrameTxData <= (others=>'0'); + vc0FrameTxReady <= '0'; + vc1FrameTxReady <= '0'; + vc2FrameTxReady <= '0'; + vc3FrameTxReady <= '0'; + end case; + end if; + end process; + + + -- Payload counter used to limit payload size of frames + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + payloadCount <= (others=>'0') after tpd; + elsif rising_edge(pgpClk) then + if txState = ST_PAYLD then + payloadCount <= payloadCount + 1 after tpd; + else + payloadCount <= (others=>'0') after tpd; + end if; + end if; + end process; + + + -- Simple state machine to control transmission of data frames + -- Control input state of delay chain + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + dlyFrameTxData <= (others=>'0') after tpd; + dlyFrameTxEOF <= '0' after tpd; + dlyFrameTxEOFE <= '0' after tpd; + dlyFrameTxWidth <= '0' after tpd; + cellTxSOF <= '0' after tpd; + cellTxEOF <= '0' after tpd; + cellTxInp <= '0' after tpd; + cellTxAcked <= '0' after tpd; + nextAcked <= '0' after tpd; + frameReadyOut <= '0' after tpd; + selSOC <= '0' after tpd; + selValid <= '0' after tpd; + selWidth <= '0' after tpd; + selEOF <= '0' after tpd; + selEOFE <= '0' after tpd; + selCrcMask <= "0000" after tpd; + selData <= (others=>'0') after tpd; + txState <= ST_IDLE after tpd; + cellSerial <= "00" after tpd; + + elsif rising_edge(pgpClk) then + + -- Muxed data delay stage + dlyFrameTxData <= muxFrameTxData after tpd; + dlyFrameTxEOF <= muxFrameTxEOF after tpd; + dlyFrameTxEOFE <= muxFrameTxEOFE after tpd; + dlyFrameTxWidth <= muxFrameTxWidth after tpd; + + -- Delayed version of acked + cellTxAcked <= nextAcked; + + -- Link is not ready + if pibLinkReady = '0' then + cellTxSOF <= '0' after tpd; + cellTxEOF <= '0' after tpd; + nextAcked <= '0' after tpd; + selValid <= '0' after tpd; + selWidth <= '0' after tpd; + selSOC <= '0' after tpd; + selEOF <= '0' after tpd; + selEOFE <= '0' after tpd; + selCrcMask <= "0000" after tpd; + selData <= (others=>'0') after tpd; + frameReadyOut <= '0' after tpd; + cellTxInp <= '0' after tpd; + cellSerial <= "00" after tpd; + txState <= ST_IDLE after tpd; + + -- Transmit state engine + else case txState is + + -- IDLE, waiting for frame, no data on sel + when ST_IDLE => + + -- Clear Flags + cellTxEOF <= '0' after tpd; + nextAcked <= '0' after tpd; + frameReadyOut <= '0' after tpd; + + -- No Data + selValid <= '0' after tpd; + selWidth <= '0' after tpd; + selEOF <= '0' after tpd; + selEOFE <= '0' after tpd; + selCrcMask <= "0000" after tpd; + selData <= randData after tpd; + + -- Wait for transmit control from scheduler + if cellTxReq = '1' then + + -- Set in frame mode + txState <= ST_HEAD0 after tpd; + cellTxInp <= '1' after tpd; + + -- Assert SOF, payload flags as early as possible + cellTxSOF <= not cellTxIdle and muxFrameTxSOF after tpd; + else + cellTxInp <= '0' after tpd; + cellTxSOF <= '0' after tpd; + end if; + + -- Header 0, data is SOC placeholder and header byte 0 + when ST_HEAD0 => + + -- Assert ready + selSOC <= '1' after tpd; + cellTxSOF <= '0' after tpd; + + -- Assert flags to external blocks, some fields depend on frame type + -- IDLE cell + if cellTxIdle = '1' then + frameReadyOut <= '0' after tpd; + nextAcked <= cellTxAck or cellTxNack after tpd; + selData(15 downto 14) <= "00" after tpd; -- Cell Type + selData(13) <= cellTxAck after tpd; -- Ack Bit + selData(12) <= cellTxNAck after tpd; -- Nack Bit + selData(11 downto 10) <= "00" after tpd; -- VC + + -- SOF Frame + elsif muxFrameTxSOF = '1' then + frameReadyOut <= '1' after tpd; + nextAcked <= '0' after tpd; + selData(15 downto 14) <= "11" after tpd; -- Cell Type + selData(13) <= '0' after tpd; -- Ack Bit + selData(12) <= '0' after tpd; -- Nack Bit + selData(11 downto 10) <= cellTxDataVc after tpd; -- VC + + -- Payload + else + frameReadyOut <= '1' after tpd; + nextAcked <= cellTxAck or cellTxNack after tpd; + selData(15 downto 14) <= "01" after tpd; -- Cell Type + selData(13) <= cellTxAck after tpd; -- Ack Bit + selData(12) <= cellTxNAck after tpd; -- Nack Bit + selData(11 downto 10) <= cellTxDataVc after tpd; -- VC + end if; + + -- Delay pipeline input + selValid <= '1' after tpd; + selWidth <= '0' after tpd; + selData(9 downto 8) <= cellSerial after tpd; -- Cell serial number + + -- Increment serial number + cellSerial <= cellSerial + 1 after tpd; + + -- Go to header 1 state + txState <= ST_HEAD1 after tpd; + + -- Header 1, data is header bytes 1 & 2 + when ST_HEAD1 => + + -- Clear flags + selSOC <= '0' after tpd; + cellTxSOF <= '0' after tpd; + nextAcked <= '0' after tpd; + + -- Delay pipeline input + selWidth <= '1' after tpd; + selData(15) <= vc3LocBuffFull after tpd; + selData(14) <= vc2LocBuffFull after tpd; + selData(13) <= vc1LocBuffFull after tpd; + selData(12) <= vc0LocBuffFull after tpd; + selData(11) <= vc3LocBuffAFull after tpd; + selData(10) <= vc2LocBuffAFull after tpd; + selData(9) <= vc1LocBuffAFull after tpd; + selData(8) <= vc0LocBuffAFull after tpd; + + -- Lower byte depends on frame type + if nextAcked = '1' then + selData(7 downto 0) <= cellTxAckSeq after tpd; -- Ack/Nack seq num + else + selData(7 downto 0) <= cellTxDataSeq after tpd; -- Data frame seq num + end if; + + -- EOF is passed at input + if muxFrameTxEOF = '1' then + frameReadyOut <= '0' after tpd; + end if; + + -- Process payload data + txState <= ST_PAYLD after tpd; + + -- Payload data + when ST_PAYLD => + + -- Delay pipeline input + selValid <= '1' after tpd; + + -- EOF + if dlyFrameTxEOF = '1' then + + -- Store error flag for later + selEOF <= '1' after tpd; + selEOFE <= dlyFrameTxEOFE after tpd; + + -- Width = 0, overwrite upper byte with CRC byte 0 + if dlyFrameTxWidth = '0' then + selData <= dlyFrameTxData after tpd; + txState <= ST_CRC12 after tpd; + selCrcMask <= "0001" after tpd; + selWidth <= '0' after tpd; + + -- Width = 1 + else + selData <= dlyFrameTxData after tpd; + txState <= ST_CRC01 after tpd; + selCrcMask <= "0000" after tpd; + selWidth <= '1' after tpd; + end if; + + -- Ready de-asserted by user or valid de-asserted by local logic + elsif frameReadyOut = '0' or muxFrameTxValid = '0' then + selData <= dlyFrameTxData after tpd; + txState <= ST_CRC01 after tpd; + selCrcMask <= "0000" after tpd; + selWidth <= '1' after tpd; + + -- Normal data. Pass width flag to CRC generator. This will ensure an + -- error occurs if user de-asserts width flag without EOF. + else + selData <= dlyFrameTxData after tpd; + selCrcMask <= "0000" after tpd; + selWidth <= dlyFrameTxWidth after tpd; + end if; + + -- EOF is passed at input or user has de-asserted valid + if muxFrameTxValid = '0' or muxFrameTxEOF = '1' then + frameReadyOut <= '0' after tpd; + + -- Payload size exceeded or idle size has been reached + elsif payloadCount = 254 or (payloadCount = 4 and cellTxIdle = '1') then + frameReadyOut <= '0' after tpd; + end if; + + -- CRC bytes 01, even alignment + when ST_CRC01 => + selWidth <= '1' after tpd; + selValid <= '0' after tpd; + selCrcMask <= "0011" after tpd; + txState <= ST_CRC23 after tpd; + + -- CRC bytes 23, even alignment + when ST_CRC23 => + selWidth <= '1' after tpd; + selValid <= '0' after tpd; + selCrcMask <= "1100" after tpd; + cellTxEOF <= selEOF after tpd; + txState <= ST_IDLE after tpd; + + -- CRC bytes 12, odd alignment + when ST_CRC12 => + selWidth <= '1' after tpd; + selValid <= '0' after tpd; + selCrcMask <= "0110" after tpd; + txState <= ST_CRC3 after tpd; + + -- CRC byte 3, odd alignment + when ST_CRC3 => + selWidth <= '0' after tpd; + selValid <= '0' after tpd; + selCrcMask <= "1000" after tpd; + cellTxEOF <= selEOF after tpd; + txState <= ST_IDLE after tpd; + + -- Just in case + when others => txState <= ST_IDLE after tpd; + end case; + end if; + end if; + end process; + + + -- The rest of the delay chain. A delay is required in order to compensate + -- for the latency of the CRC generator. + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + dly1TxSOC <= '0' after tpd; + dly1TxEOF <= '0' after tpd; + dly1TxEOFE <= '0' after tpd; + dly1CrcMask <= "0000" after tpd; + dly1TxData <= (others=>'0') after tpd; + dly2TxSOC <= '0' after tpd; + dly2TxEOF <= '0' after tpd; + dly2TxEOFE <= '0' after tpd; + dly2CrcMask <= "0000" after tpd; + dly2TxData <= (others=>'0') after tpd; + dly3TxSOC <= '0' after tpd; + dly3TxEOF <= '0' after tpd; + dly3TxEOFE <= '0' after tpd; + dly3CrcMask <= "0000" after tpd; + dly3TxData <= (others=>'0') after tpd; + dly4TxSOC <= '0' after tpd; + dly4TxEOF <= '0' after tpd; + dly4TxEOFE <= '0' after tpd; + dly4CrcMask <= "0000" after tpd; + dly4TxData <= (others=>'0') after tpd; + elsif rising_edge(pgpClk) then + + -- Delay stage 1 + dly1TxSOC <= selSOC after tpd; + dly1TxEOF <= selEOF after tpd; + dly1TxEOFE <= selEOFE after tpd; + dly1CrcMask <= selCrcMask after tpd; + dly1TxData <= selData after tpd; + + -- Delay stage 2 + dly2TxSOC <= dly1TxSOC after tpd; + dly2TxEOF <= dly1TxEOF after tpd; + dly2TxEOFE <= dly1TxEOFE after tpd; + dly2CrcMask <= dly1CrcMask after tpd; + dly2TxData <= dly1TxData after tpd; + + -- Delay stage 3 + dly3TxSOC <= dly2TxSOC after tpd; + dly3TxEOF <= dly2TxEOF after tpd; + dly3TxEOFE <= dly2TxEOFE after tpd; + dly3CrcMask <= dly2CrcMask after tpd; + dly3TxData <= dly2TxData after tpd; + + -- Delay stage 3 + dly4TxSOC <= dly3TxSOC after tpd; + dly4TxEOF <= dly3TxEOF after tpd; + dly4TxEOFE <= dly3TxEOFE after tpd; + dly4CrcMask <= dly3CrcMask after tpd; + dly4TxData <= dly3TxData after tpd; + end if; + end process; + + + -- Output stage, either real data or insert CRC values + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + pibTxSOC <= '0' after tpd; + pibTxWidth <= '0' after tpd; + pibTxEOC <= '0' after tpd; + pibTxEOF <= '0' after tpd; + pibTxEOFE <= '0' after tpd; + pibTxData <= (others=>'0') after tpd; + + elsif rising_edge(pgpClk) then + + -- Data depends on state of shifted CRC mask + case dly4CrcMask is + + -- Normal data + when "0000" => + pibTxSOC <= dly4TxSOC after tpd; + pibTxWidth <= '1' after tpd; + pibTxEOC <= '0' after tpd; + pibTxEOF <= '0' after tpd; + pibTxEOFE <= '0' after tpd; + pibTxData <= dly4TxData after tpd; + + -- Partial CRC in upper byte + when "0001" => + pibTxSOC <= '0' after tpd; + pibTxWidth <= '1' after tpd; + pibTxEOC <= '0' after tpd; + pibTxEOF <= '0' after tpd; + pibTxEOFE <= '0' after tpd; + pibTxData(7 downto 0) <= dly4TxData(7 downto 0) after tpd; + pibTxData(15 downto 8) <= crcTxOut(31 downto 24) after tpd; + + -- Shifted CRC + when "0110" => + pibTxSOC <= '0' after tpd; + pibTxWidth <= '1' after tpd; + pibTxEOC <= '0' after tpd; + pibTxEOF <= '0' after tpd; + pibTxEOFE <= '0' after tpd; + pibTxData(7 downto 0) <= crcTxOut(23 downto 16) after tpd; + pibTxData(15 downto 8) <= crcTxOut(15 downto 8) after tpd; + + -- Partial CRC in lower byte, end of cell + when "1000" => + pibTxSOC <= '0' after tpd; + pibTxWidth <= '0' after tpd; + pibTxEOC <= '1' after tpd; + pibTxEOF <= dly4TxEOF after tpd; + pibTxEOFE <= dly4TxEOFE after tpd; + pibTxData(7 downto 0) <= crcTxOut(7 downto 0) after tpd; + pibTxData(15 downto 8) <= (others=>'0') after tpd; + + -- Full CRC + when "0011" => + pibTxSOC <= '0' after tpd; + pibTxWidth <= '1' after tpd; + pibTxEOC <= '0' after tpd; + pibTxEOF <= '0' after tpd; + pibTxEOFE <= '0' after tpd; + pibTxData(7 downto 0) <= crcTxOut(31 downto 24) after tpd; + pibTxData(15 downto 8) <= crcTxOut(23 downto 16) after tpd; + + -- Full CRC, end of cell + when "1100" => + pibTxSOC <= '0' after tpd; + pibTxWidth <= '1' after tpd; + pibTxEOC <= '1' after tpd; + pibTxEOF <= dly4TxEOF after tpd; + pibTxEOFE <= dly4TxEOFE after tpd; + pibTxData(7 downto 0) <= crcTxOut(15 downto 8) after tpd; + pibTxData(15 downto 8) <= crcTxOut(7 downto 0) after tpd; + + when others => + pibTxSOC <= '0' after tpd; + pibTxWidth <= '1' after tpd; + pibTxEOC <= '0' after tpd; + pibTxEOF <= '0' after tpd; + pibTxEOFE <= '0' after tpd; + pibTxData <= dly4TxData after tpd; + end case; + end if; + end process; + + + -- Random data generator + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + randData <= (others =>'0') after tpd; + elsif rising_edge(pgpClk) then + randData <= randData + 1 after tpd; + end if; + end process; + +end PgpCellTx; + diff --git a/rce/fw-hsio/modules/pgp/hdl/PgpClkGen.vhd b/rce/fw-hsio/modules/pgp/hdl/PgpClkGen.vhd new file mode 100755 index 00000000..5a7082f7 --- /dev/null +++ b/rce/fw-hsio/modules/pgp/hdl/PgpClkGen.vhd @@ -0,0 +1,367 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol Applications, Clock Source Module +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : PgpClkGen.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 06/09/2007 +------------------------------------------------------------------------------- +-- Description: +-- PGP Clock Module. Contians GT11 clock module and DCM to support PGP. +-- Used to generate 152.65Mhz reference clock for MGT and global buffer clock +-- for PGP core at the same frequency. Will also generate an optional 125Mhz +-- global clock and reset for external logic use. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 06/09/2007: created. +-- 09/19/2007: Added power on reset input and local reset inputs, added 125Mhz +-- clock outputs. +-- 09/21/2007: Added generic to choose reference clock drive +-- 10/08/2007: Fixed inversion error on DCM reset. +-- 10/19/2007: Clocks are now fed back into block for use to clean up +-- synplicity clock contraints. +-- 11/06/2007: Changed DLL frequency mode to high. +-- 11/08/2007: Changed GT11 clock inputs from open to '0' to fix simulation. +-- 11/08/2007: Added simulation libraries +-- 01/25/2008: Added generics to support adjusting user clock settings. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; +-- synopsys translate_off +Library UNISIM; +-- synopsys translate_on + +entity PgpClkGen is + generic ( + RefClkEn1 : string := "ENABLE"; -- ENABLE or DISABLE + RefClkEn2 : string := "DISABLE"; -- ENABLE or DISABLE + DcmClkSrc : string := "RefClk1"; -- RefClk1 or RefClk2 + UserFxDiv : integer := 5; -- DCM FX Output Divide + UserFxMult : integer := 4 -- DCM FX Output Divide, 4/5 * 156.25 = 125Mhz + ); + port ( + + -- Reference Clock Pad Inputs + pgpRefClkInP : in std_logic; + pgpRefClkInN : in std_logic; + + -- Power On Reset Input + ponResetL : in std_logic; + + -- Locally Generated Reset + locReset : in std_logic; + + -- Reference Clock To PGP MGT + -- Use one, See RefClkEn1 & RefClkEn2 Generics + pgpRefClk1 : out std_logic; + pgpRefClk2 : out std_logic; + + -- Global Clock & Reset For PGP Logic, 156.25Mhz + pgpClk : out std_logic; + pgpClk90 : out std_logic; + pgpReset : out std_logic; + + clk320 : out std_logic; + -- Global Clock & Reset For User Logic, 125Mhz + userClk : out std_logic; + userReset : out std_logic; + + -- Inputs clocks for reset generation connect + -- to pgpClk and userClk + pgpClkIn : in std_logic; + userClkIn : in std_logic; + + -- Output unbuffered clocks + pgpClkUnbuf : out std_logic; + pgpClk90Unbuf : out std_logic; + locClkUnbuf : out std_logic + ); + +end PgpClkGen; + + +-- Define architecture +architecture PgpClkGen of PgpClkGen is + + -- Xilinx GTLL Clock Module + component GT11CLK + generic ( + REFCLKSEL : string := "MGTCLK"; + SYNCLK1OUTEN : string := "ENABLE"; + SYNCLK2OUTEN : string := "DISABLE" + ); + port ( + SYNCLK1OUT : out std_ulogic; + SYNCLK2OUT : out std_ulogic; + MGTCLKN : in std_ulogic; + MGTCLKP : in std_ulogic; + REFCLK : in std_ulogic; + RXBCLK : in std_ulogic; + SYNCLK1IN : in std_ulogic; + SYNCLK2IN : in std_ulogic + ); + end component; + + -- Xilinx DCM + component DCM + generic ( + CLKDV_DIVIDE : real := 2.0; + CLKFX_DIVIDE : integer := 1; + CLKFX_MULTIPLY : integer := 4; + CLKIN_PERIOD : real := 10.0; + CLKIN_DIVIDE_BY_2 : boolean := false; + CLKOUT_PHASE_SHIFT : string := "NONE"; + CLK_FEEDBACK : string := "1X"; + DESKEW_ADJUST : string := "SYSTEM_SYNCHRONOUS"; + DFS_FREQUENCY_MODE : string := "LOW"; + DLL_FREQUENCY_MODE : string := "LOW"; + DSS_MODE : string := "NONE"; + DUTY_CYCLE_CORRECTION : boolean := true; + FACTORY_JF : bit_vector := X"C080"; + PHASE_SHIFT : integer := 0; + STARTUP_WAIT : boolean := false + ); + port ( + CLK0 : out std_ulogic := '0'; + CLK180 : out std_ulogic := '0'; + CLK270 : out std_ulogic := '0'; + CLK2X : out std_ulogic := '0'; + CLK2X180 : out std_ulogic := '0'; + CLK90 : out std_ulogic := '0'; + CLKDV : out std_ulogic := '0'; + CLKFX : out std_ulogic := '0'; + CLKFX180 : out std_ulogic := '0'; + LOCKED : out std_ulogic := '0'; + PSDONE : out std_ulogic := '0'; + STATUS : out std_logic_vector(7 downto 0) := "00000000"; + CLKFB : in std_ulogic := '0'; + CLKIN : in std_ulogic := '0'; + DSSEN : in std_ulogic := '0'; + PSCLK : in std_ulogic := '0'; + PSEN : in std_ulogic := '0'; + PSINCDEC : in std_ulogic := '0'; + RST : in std_ulogic := '0' + ); + end component; + + -- Xilinx global clock buffer component + component BUFGMUX + port ( + O : out std_logic; + I0 : in std_logic; + I1 : in std_logic; + S : in std_logic + ); + end component; + + + -- For simulation + -- synopsys translate_off + for all : BUFGMUX use entity UNISIM.BUFGMUX (bufgmux_v); + for all : DCM use entity UNISIM.DCM (dcm_v); + for all : GT11CLK use entity UNISIM.GT11CLK (gt11clk_v); + -- synopsys translate_on + + -- Local Signals + signal ponReset : std_logic; + signal intRefClk1 : std_logic; + signal intRefClk2 : std_logic; + signal tmpPgpClk : std_logic; + signal tmpPgpClk90 : std_logic; + signal intPgpClk : std_logic; + signal intPgpClk90 : std_logic; + signal intPgpRst : std_logic; + signal tmpLocClk : std_logic; + signal tmp320Clk : std_logic; + signal int320Clk : std_logic; + signal intUsrClk : std_logic; + signal intUsrRst : std_logic; + signal syncPgpRstIn : std_logic_vector(2 downto 0); + signal pgpRstCnt : std_logic_vector(3 downto 0); + signal syncLocRstIn : std_logic_vector(2 downto 0); + signal locRstCnt : std_logic_vector(3 downto 0); + signal dcmRefClk : std_logic; + signal dcmLock : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + + -- Black Box Attributes + attribute syn_black_box : boolean; + attribute syn_noprune : boolean; + attribute syn_black_box of GT11CLK : component is TRUE; + attribute syn_noprune of GT11CLK : component is TRUE; + attribute syn_black_box of DCM : component is TRUE; + attribute syn_noprune of DCM : component is TRUE; + attribute syn_black_box of BUFGMUX : component is TRUE; + attribute syn_noprune of BUFGMUX : component is TRUE; + +begin + + -- Output Generated Clock And Reset Signals + pgpRefClk1 <= intRefClk1; + pgpRefClk2 <= intRefClk2; + pgpClk <= intPgpClk; + pgpClk90 <= intPgpClk90; + clk320 <= int320Clk; + pgpReset <= intPgpRst; + userClk <= intUsrClk; + userReset <= intUsrRst; + + -- Output unbuffered clocks + pgpClkUnbuf <= tmpPgpClk; + pgpClk90Unbuf <= tmpPgpClk90; + locClkUnbuf <= tmpLocClk; + + -- Invert power on reset + ponReset <= not ponResetL; + + + -- MGT Clock Module + U_PgpClkGT11: GT11CLK generic map ( + SYNCLK1OUTEN => RefClkEn1, + SYNCLK2OUTEN => RefClkEn2, + REFCLKSEL => "MGTCLK" + ) port map ( + MGTCLKN => pgpRefClkInN, + MGTCLKP => pgpRefClkInP, + REFCLK => '0', + RXBCLK => '0', + SYNCLK1IN => '0', + SYNCLK2IN => '0', + SYNCLK1OUT => intRefClk1, + SYNCLK2OUT => intRefClk2 + ); + + + -- REF Clock 1 Is Selected As DCM Source + U_DCM_REF1: if DcmClkSrc = "RefClk1" generate + dcmRefClk <= intRefClk1; + end generate; + + -- REF Clock 2 Is Selected As DCM Source + U_DCM_REF2: if DcmClkSrc = "RefClk2" generate + dcmRefClk <= intRefClk2; + end generate; + + + -- DCM For PGP Clock & User Clock + U_PgpDcm: DCM + generic map ( + DFS_FREQUENCY_MODE => "LOW", DLL_FREQUENCY_MODE => "HIGH", + DUTY_CYCLE_CORRECTION => FALSE, CLKIN_DIVIDE_BY_2 => FALSE, + CLK_FEEDBACK => "1X", CLKOUT_PHASE_SHIFT => "NONE", + STARTUP_WAIT => false, PHASE_SHIFT => 0, + CLKFX_MULTIPLY => UserFxMult, CLKFX_DIVIDE => UserFxDiv, + CLKDV_DIVIDE => 4.0, CLKIN_PERIOD => 6.4, + DSS_MODE => "NONE", FACTORY_JF => X"C080", + DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS" + ) + port map ( + CLKIN => dcmRefClk, CLKFB => intPgpClk, + CLK0 => tmpPgpClk, CLK90 => tmpPgpClk90, + CLK180 => open, CLK270 => open, + CLK2X => tmp320Clk, CLK2X180 => open, + CLKDV => tmpLocClk, CLKFX => open, + CLKFX180 => open, LOCKED => dcmLock, + PSDONE => open, STATUS => open, + DSSEN => '0', PSCLK => '0', + PSEN => '0', PSINCDEC => '0', + RST => ponReset + ); + + + -- Global Buffer For PGP Clock + U_PgpClkBuff: BUFGMUX port map ( + O => intPgpClk, + I0 => tmpPgpClk, + I1 => '0', + S => '0' + ); + U_PgpClkBuff90: BUFGMUX port map ( + O => intPgpClk90, + I0 => tmpPgpClk90, + I1 => '0', + S => '0' + ); + + + -- Global Buffer For 125Mhz Clock + U_LocClkBuff: BUFGMUX port map ( + O => intUsrClk, + I0 => tmpLocClk, + I1 => '0', + S => '0' + ); + + U_320ClkBuff: BUFGMUX port map ( + O => int320Clk, + I0 => tmp320Clk, + I1 => '0', + S => '0' + ); + + + -- PGP Clock Synced Reset + process ( pgpClkIn ) begin + if rising_edge(pgpClkIn) then + + -- Sync local reset, lock and power on reset to local clock + -- Negative asserted signal + syncPgpRstIn(0) <= dcmLock and ponResetL and not locReset after tpd; + syncPgpRstIn(1) <= syncPgpRstIn(0) after tpd; + syncPgpRstIn(2) <= syncPgpRstIn(1) after tpd; + + -- Reset counter on reset + if syncPgpRstIn(2) = '0' then + pgpRstCnt <= (others=>'0') after tpd; + intPgpRst <= '1' after tpd; + + -- Count Up To Max Value + elsif pgpRstCnt = "1111" then + intPgpRst <= '0' after tpd; + + -- Increment counter + else + intPgpRst <= '1' after tpd; + pgpRstCnt <= pgpRstCnt + 1 after tpd; + end if; + end if; + end process; + + + -- Local 125Mhz Clock Synced Reset + process ( userClkIn ) begin + if rising_edge(userClkIn) then + + -- Sync local reset, lock and power on reset to local clock + -- Negative asserted signal + syncLocRstIn(0) <= dcmLock and ponResetL and not locReset after tpd; + syncLocRstIn(1) <= syncLocRstIn(0) after tpd; + syncLocRstIn(2) <= syncLocRstIn(1) after tpd; + + -- Reset counter on reset + if syncLocRstIn(2) = '0' then + locRstCnt <= (others=>'0') after tpd; + intUsrRst <= '1' after tpd; + + -- Count Up To Max Value + elsif locRstCnt = "1111" then + intUsrRst <= '0' after tpd; + + -- Increment counter + else + intUsrRst <= '1' after tpd; + locRstCnt <= locRstCnt + 1 after tpd; + end if; + end if; + end process; + +end PgpClkGen; + diff --git a/rce/fw-hsio/modules/pgp/hdl/PgpCmdSlave.vhd b/rce/fw-hsio/modules/pgp/hdl/PgpCmdSlave.vhd new file mode 100644 index 00000000..054385f5 --- /dev/null +++ b/rce/fw-hsio/modules/pgp/hdl/PgpCmdSlave.vhd @@ -0,0 +1,295 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol Applications, Command Slave Block +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : PgpCmdSlave.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 09/22/2007 +------------------------------------------------------------------------------- +-- Description: +-- Slave block for Command protocol over the PGP. +-- Packet is 16 bytes. The 16 bit values passed over the PGP will be: +-- Word 0 Data[1:0] = VC +-- Word 0 Data[7:2] = Dest_ID +-- Word 0 Data[15:8] = TID[7:0] +-- Word 1 Data[15:0] = TID[23:8] +-- Word 2 Data[7:0] = OpCode[7:0] +-- Word 2 Data[15:8] = Don't Care +-- Word 3 Data[15:0] = Don't Care +-- Word 4 = Don't Care +-- Word 5 = Don't Care +-- Word 6 = Don't Care +-- Word 7 = Don't Care +------------------------------------------------------------------------------- +-- Copyright (c) 2007 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 09/22/2007: created. +-- 10/10/2007: Converted context value to 32-bits. +-- 10/29/2007: Changed name of coregen blocks +-- 11/20/2007: Added check to ensure overflow will put EOFE into buffer. +-- 11/27/2007: Modified to allow the option of sync or async FIFO +-- 11/30/2007: Fixed error with back to back frames and mis-connected data lines. +-- 01/25/2008: Adjusted for new frame format. +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE work.ALL; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity PgpCmdSlave is + generic ( + DestId : natural := 0; -- Destination ID Value To Match + DestMask : natural := 0; -- Destination ID Mask For Match + AsyncFIFO : string := "TRUE" -- Use Async FIFOs, TRUE or FALSE + ); + port ( + + -- PGP Clock And Reset + pgpClk : in std_logic; -- PGP Clock + pgpReset : in std_logic; -- Synchronous PGP Reset + + -- Local clock and reset + locClk : in std_logic; -- Local Clock + locReset : in std_logic; -- Synchronous Local Reset + + -- PGP Signals, Virtual Channel Rx Only + vcFrameRxValid : in std_logic; -- Data is valid + vcFrameRxSOF : in std_logic; -- Data is SOF + vcFrameRxWidth : in std_logic; -- Data is 16-bits + vcFrameRxEOF : in std_logic; -- Data is EOF + vcFrameRxEOFE : in std_logic; -- Data is EOF with Error + vcFrameRxData : in std_logic_vector(15 downto 0); -- Data + vcLocBuffAFull : out std_logic; -- Local buffer almost full + vcLocBuffFull : out std_logic; -- Local buffer full + + -- Local command signals + cmdEn : out std_logic; -- Command Enable + cmdOpCode : out std_logic_vector(7 downto 0); -- Command OpCode + cmdCtxOut : out std_logic_vector(23 downto 0) -- Command Context + ); + +end PgpCmdSlave; + + +-- Define architecture +architecture PgpCmdSlave of PgpCmdSlave is + + -- Async FIFO + component pgp_afifo_20x511 port ( + din: IN std_logic_VECTOR(19 downto 0); + rd_clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_clk: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(19 downto 0); + empty: OUT std_logic; + full: OUT std_logic; + wr_data_count: OUT std_logic_VECTOR(8 downto 0)); + end component; + + -- Sync FIFO + component pgp_fifo_20x512 port ( + din: IN std_logic_VECTOR(19 downto 0); + clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(19 downto 0); + empty: OUT std_logic; + full: OUT std_logic; + data_count: OUT std_logic_VECTOR(8 downto 0)); + end component; + + -- Local Signals + signal intDestId : std_logic_vector(5 downto 0); + signal selDestId : std_logic_vector(5 downto 0); + signal selDestMask : std_logic_vector(5 downto 0); + signal intCmdEn : std_logic; + signal intCmdOpCode : std_logic_vector(7 downto 0); + signal intCmdCtxOut : std_logic_vector(23 downto 0); + signal fifoDin : std_logic_vector(19 downto 0); + signal fifoDout : std_logic_vector(19 downto 0); + signal fifoRd : std_logic; + signal fifoRdDly : std_logic; + signal fifoCount : std_logic_vector(8 downto 0); + signal fifoEmpty : std_logic; + signal locSOF : std_logic; + signal locWidth : std_logic; + signal locEOF : std_logic; + signal locEOFE : std_logic; + signal locData : std_logic_vector(15 downto 0); + signal intCnt : std_logic_vector(2 downto 0); + signal intCntEn : std_logic; + signal fifoErr : std_logic; + signal fifoFull : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + + -- Black Box Attributes + attribute syn_black_box : boolean; + attribute syn_noprune : boolean; + attribute syn_black_box of pgp_afifo_20x511 : component is TRUE; + attribute syn_noprune of pgp_afifo_20x511 : component is TRUE; + attribute syn_black_box of pgp_fifo_20x512 : component is TRUE; + attribute syn_noprune of pgp_fifo_20x512 : component is TRUE; + +begin + + -- Output signal + cmdEn <= intCmdEn; + cmdOpCode <= intCmdOpCode; + cmdCtxOut <= intCmdCtxOut; + + -- Convert destnation ID and Mask + selDestId <= conv_std_logic_vector(DestId,6); + selDestMask <= conv_std_logic_vector(DestMask,6); + + -- Data going into FIFO + fifoDin(19) <= vcFrameRxSOF; + fifoDin(18) <= vcFrameRxWidth; + fifoDin(17) <= vcFrameRxEOF or fifoErr; + fifoDin(16) <= vcFrameRxEOFE or fifoErr; + fifoDin(15 downto 0) <= vcFrameRxData; + + -- Async FIFO + U_GenAFifo: if AsyncFIFO = "TRUE" generate + U_CmdAFifo: pgp_afifo_20x511 port map ( + din => fifoDin, + rd_clk => locClk, + rd_en => fifoRd, + rst => pgpReset, + wr_clk => pgpClk, + wr_en => vcFrameRxValid, + dout => fifoDout, + empty => fifoEmpty, + full => fifoFull, + wr_data_count => fifoCount + ); + end generate; + + -- Sync FIFO + U_GenFifo: if AsyncFIFO = "FALSE" generate + U_CmdFifo: pgp_fifo_20x512 port map ( + din => fifoDin, + clk => pgpClk, + rd_en => fifoRd, + rst => pgpReset, + wr_en => vcFrameRxValid, + dout => fifoDout, + empty => fifoEmpty, + full => fifoFull, + data_count => fifoCount + ); + end generate; + + + -- Data coming out of FIFO + locSOF <= fifoDout(19); + locWidth <= fifoDout(18); + locEOF <= fifoDout(17); + locEOFE <= fifoDout(16); + locData <= fifoDout(15 downto 0); + + -- FIFO Read Control + fifoRd <= not fifoEmpty; + + + -- Generate flow control + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + vcLocBuffAFull <= '0' after tpd; + vcLocBuffFull <= '0' after tpd; + fifoErr <= '0' after tpd; + elsif rising_edge(pgpClk) then + + -- Generate full error + if fifoCount >= 508 or fifoFull = '1' then + fifoErr <= '1' after tpd; + else + fifoErr <= '0' after tpd; + end if; + + -- Almost full at half capacity + vcLocBuffAFull <= fifoCount(8); + + -- Full at 3/4 capacity + vcLocBuffFull <= fifoCount(8) and fifoCount(7); + end if; + end process; + + + -- Receive Data Processor + process ( locClk, locReset ) begin + if locReset = '1' then + intCmdEn <= '0' after tpd; + intCmdOpCode <= (others=>'0') after tpd; + intCmdCtxOut <= (others=>'0') after tpd; + intDestId <= (others=>'0') after tpd; + fifoRdDly <= '0' after tpd; + intCnt <= (others=>'0') after tpd; + intCntEn <= '0' after tpd; + elsif rising_edge(locClk) then + + -- Generate delayed read + fifoRdDly <= fifoRd after tpd; + + -- Only process when data has been read + if fifoRdDly = '1' then + + -- Receive Data Counter + -- Reset on SOF or EOF, Start counter on SOF + if locSOF = '1' or locEOF = '1' then + intCnt <= (others=>'0') after tpd; + intCntEn <= not locEOF after tpd; + elsif intCntEn = '1' and intCnt /= "110" then + intCnt <= intCnt + 1 after tpd; + end if; + + -- SOF Received + if locSOF = '1' then + intCmdCtxOut(7 downto 0) <= locData(15 downto 8) after tpd; + intDestId <= locData(7 downto 2) after tpd; + intCmdEn <= '0' after tpd; + + -- Rest of Frame + else case intCnt is + + -- Word 1 + when "000" => + intCmdCtxOut(23 downto 8) <= locData after tpd; + intCmdEn <= '0' after tpd; + + -- Word 2 + when "001" => + intCmdOpCode <= locData(7 downto 0) after tpd; + intCmdEn <= '0' after tpd; + + -- Word 7, Last word + when "110" => + + -- No error and destination ID matches + if locEOF = '1' and locEOFE = '0' and + ( intDestId and selDestMask ) = selDestId then + intCmdEn <= '1' after tpd; + else + intCmdEn <= '0' after tpd; + end if; + + -- Do nothing for others + when others => + intCmdEn <= '0' after tpd; + end case; + end if; + else + intCmdEn <= '0' after tpd; + end if; + end if; + end process; + +end PgpCmdSlave; + diff --git a/rce/fw-hsio/modules/pgp/hdl/PgpDataBuffer.vhd b/rce/fw-hsio/modules/pgp/hdl/PgpDataBuffer.vhd new file mode 100755 index 00000000..777f7be3 --- /dev/null +++ b/rce/fw-hsio/modules/pgp/hdl/PgpDataBuffer.vhd @@ -0,0 +1,256 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol Applications, Data Buffer +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : PgpDataBuffer.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 10/04/2007 +------------------------------------------------------------------------------- +-- Description: +-- Data buffer for front end data sent up to RCE +------------------------------------------------------------------------------- +-- Copyright (c) 2007 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 09/24/2007: created. +-- 11/06/2007: Changed flow control reaction to ensure their are no short cells. +-- 11/07/2007: Changed reaction to full flag due to change in pic interface. +-- 11/09/2007: Moved PGP Fifo to common block. +-- 03/06/2008: Removed width signal. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity PgpDataBuffer is port ( + + -- PGP Clock & Reset Signals + pgpClk : in std_logic; + pgpReset : in std_logic; + + -- Local clock and reset + locClk : in std_logic; + locReset : in std_logic; + + -- Local data transfer signals + frameTxEnable : in std_logic; + frameTxSOF : in std_logic; + frameTxEOF : in std_logic; + frameTxEOFE : in std_logic; + frameTxData : in std_logic_vector(15 downto 0); + frameTxAFull : out std_logic; + + -- PGP Virtual Channels Signals + vcFrameTxValid : out std_logic; + vcFrameTxReady : in std_logic; + vcFrameTxSOF : out std_logic; + vcFrameTxWidth : out std_logic; + vcFrameTxEOF : out std_logic; + vcFrameTxEOFE : out std_logic; + vcFrameTxData : out std_logic_vector(15 downto 0); + vcFrameTxCid : out std_logic_vector(31 downto 0); + vcFrameTxAckCid : in std_logic_vector(31 downto 0); + vcFrameTxAckEn : in std_logic; + vcFrameTxAck : in std_logic; + vcRemBuffAFull : in std_logic; + vcRemBuffFull : in std_logic; + + -- Overflow occured flag + dataOverFlow : out std_logic + ); +end PgpDataBuffer; + + +-- Define architecture +architecture PgpDataBuffer of PgpDataBuffer is + + -- Async Fifo + component pgp_afifo_20x511 port ( + din: IN std_logic_VECTOR(19 downto 0); + rd_clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_clk: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(19 downto 0); + empty: OUT std_logic; + full: OUT std_logic; + wr_data_count: OUT std_logic_VECTOR(8 downto 0)); + end component; + + -- PGP Pic Buffer Block + component PgpPicRemBuff is + port ( + pgpClk : in std_logic; + pgpReset : in std_logic; + vcFrameTxValid : out std_logic; + vcFrameTxReady : in std_logic; + vcFrameTxSOF : out std_logic; + vcFrameTxWidth : out std_logic; + vcFrameTxEOF : out std_logic; + vcFrameTxEOFE : out std_logic; + vcFrameTxData : out std_logic_vector(15 downto 0); + vcFrameTxCid : out std_logic_vector(31 downto 0); + vcFrameTxAckCid : in std_logic_vector(31 downto 0); + vcFrameTxAckEn : in std_logic; + vcFrameTxAck : in std_logic; + vcRemBuffAFull : in std_logic; + vcRemBuffFull : in std_logic; + txFifoRd : out std_logic; + txFifoEmpty : in std_logic; + txFifoData : in std_logic_vector(15 downto 0); + txFifoSOF : in std_logic; + txFifoEOF : in std_logic; + txFifoEOFE : in std_logic + ); + end component; + + -- Local Signals + signal asyncDin : std_logic_vector(19 downto 0); + signal asyncDout : std_logic_vector(19 downto 0); + signal asyncRd : std_logic; + signal asyncCount : std_logic_vector(8 downto 0); + signal asyncEmpty : std_logic; + signal asyncFull : std_logic; + signal asyncOflowRstDly0 : std_logic; + signal asyncOflowRstDly1 : std_logic; + signal asyncOflow : std_logic; + signal asyncOflowDly0 : std_logic; + signal asyncOflowDly1 : std_logic; + signal asyncOflowRst : std_logic; + signal intOverFlow : std_logic; + signal fifoerr : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + + -- Black Box Attributes + attribute syn_black_box : boolean; + attribute syn_noprune : boolean; + attribute syn_black_box of pgp_afifo_20x511 : component is TRUE; + attribute syn_noprune of pgp_afifo_20x511 : component is TRUE; + +begin + + -- Drive overflow flag + dataOverFlow <= intOverFlow; + + -- Detect overflows on write + process ( locClk, locReset ) begin + if locReset = '1' then + asyncOflowRstDly0 <= '0' after tpd; + asyncOflowRstDly1 <= '0' after tpd; + asyncOflow <= '0' after tpd; + elsif rising_edge(locClk) then + + -- Double sync overflow clear + asyncOflowRstDly0 <= asyncOflowRst after tpd; + asyncOflowRstDly1 <= asyncOflowRstDly0 after tpd; + + -- Overflow write clear + if asyncOflowRstDly1 = '1' then + asyncOflow <= '0' after tpd; + + -- Overflow write + elsif asyncFull = '1' and frameTxEnable = '1' then + asyncOflow <= '1' after tpd; + end if; + end if; + end process; + + + -- PGP Clock Version Of Overflow + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + asyncOflowDly0 <= '0' after tpd; + asyncOflowDly1 <= '0' after tpd; + asyncOflowRst <= '0' after tpd; + intOverFlow <= '0' after tpd; + elsif rising_edge(pgpClk) then + + -- Sync overflow signal + asyncOflowDly0 <= asyncOflow after tpd; + asyncOflowDly1 <= asyncOflowDly0 after tpd; + + -- Generate overflow reset + asyncOflowRst <= asyncOflowDly1 after tpd; + + -- Generate overflow signal + intOverFlow <= asyncOflowDly1 and not intOverFlow after tpd; + + end if; + end process; + + + -- Write data into FIFO + asyncDin(19) <= frameTxEOFE or fifoErr; + asyncDin(18) <= frameTxEOF or fifoErr; + asyncDin(17) <= '1'; -- Width + asyncDin(16) <= frameTxSOF; + asyncDin(15 downto 0) <= frameTxData; + + -- Generate fifo error signal + process ( locClk, locReset ) begin + if locReset = '1' then + fifoErr <= '0' after tpd; + frameTxAFull <= '0' after tpd; + elsif rising_edge(locClk) then + + -- Generate full error + if asyncCount >= 508 or asyncFull = '1' then + fifoErr <= '1' after tpd; + else + fifoErr <= '0' after tpd; + end if; + + -- Almost full at 3/4 capacity + frameTxAFull <= asyncFull or (asyncCount(8) and asyncCount(7)); + + end if; + end process; + + -- Async FIFO + U_AsyncFifo: pgp_afifo_20x511 port map ( + din => asyncDin, + rd_clk => pgpClk, + rd_en => asyncRd, + rst => pgpReset, + wr_clk => locClk, + wr_en => frameTxEnable, + dout => asyncDout, + empty => asyncEmpty, + full => asyncFull, + wr_data_count => asyncCount + ); + + + -- PGP Pic Buffer Block + U_PgpBuffer: PgpPicRemBuff port map ( + pgpClk => pgpClk, + pgpReset => pgpReset, + vcFrameTxValid => vcFrameTxValid, + vcFrameTxReady => vcFrameTxReady, + vcFrameTxSOF => vcFrameTxSOF, + vcFrameTxWidth => vcFrameTxWidth, + vcFrameTxEOF => vcFrameTxEOF, + vcFrameTxEOFE => vcFrameTxEOFE, + vcFrameTxData => vcFrameTxData, + vcFrameTxCid => vcFrameTxCid, + vcFrameTxAckCid => vcFrameTxAckCid, + vcFrameTxAckEn => vcFrameTxAckEn, + vcFrameTxAck => vcFrameTxAck, + vcRemBuffAFull => vcRemBuffAFull, + vcRemBuffFull => vcRemBuffFull, + txFifoRd => asyncRd, + txFifoEmpty => asyncEmpty, + txFifoData => asyncDout(15 downto 0), + txFifoSOF => asyncDout(16), + txFifoEOF => asyncDout(18), + txFifoEOFE => asyncDout(19) + ); + +end PgpDataBuffer; + diff --git a/rce/fw-hsio/modules/pgp/hdl/PgpDsBuff.vhd b/rce/fw-hsio/modules/pgp/hdl/PgpDsBuff.vhd new file mode 100644 index 00000000..e5d350e0 --- /dev/null +++ b/rce/fw-hsio/modules/pgp/hdl/PgpDsBuff.vhd @@ -0,0 +1,150 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol Applications, Downstream Data Buffer +-- Project : Reconfigurable Cluster Element +------------------------------------------------------------------------------- +-- File : PgpDsBuff.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 01/11/2010 +------------------------------------------------------------------------------- +-- Description: +-- VHDL source file for buffer block for downstream data. +------------------------------------------------------------------------------- +-- Copyright (c) 2010 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 01/11/2010: created. +------------------------------------------------------------------------------- +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity PgpDsBuff is port ( + + -- Clock and reset + pgpClk : in std_logic; + pgpReset : in std_logic; + locClk : in std_logic; + locReset : in std_logic; + + -- PGP Receive Signals + vcFrameRxValid : in std_logic; + vcFrameRxSOF : in std_logic; + vcFrameRxWidth : in std_logic; + vcFrameRxEOF : in std_logic; + vcFrameRxEOFE : in std_logic; + vcFrameRxData : in std_logic_vector(15 downto 0); + vcLocBuffAFull : out std_logic; + vcLocBuffFull : out std_logic; + + -- Local data transfer signals + frameRxValid : out std_logic; + frameRxReady : in std_logic; + frameRxSOF : out std_logic; + frameRxEOF : out std_logic; + frameRxEOFE : out std_logic; + frameRxData : out std_logic_vector(15 downto 0) + ); +end PgpDsBuff; + + +-- Define architecture +architecture PgpDsBuff of PgpDsBuff is + + -- Async Fifo + component pgp_afifo_20x511 port ( + din: IN std_logic_VECTOR(19 downto 0); + rd_clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_clk: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(19 downto 0); + empty: OUT std_logic; + full: OUT std_logic; + wr_data_count: OUT std_logic_VECTOR(8 downto 0)); + end component; + + -- Local Signals + signal rxFifoDin : std_logic_vector(19 downto 0); + signal rxFifoDout : std_logic_vector(19 downto 0); + signal rxFifoRd : std_logic; + signal rxFifoValid : std_logic; + signal rxFifoCount : std_logic_vector(8 downto 0); + signal rxFifoEmpty : std_logic; + signal rxFifoFull : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + + -- Black Box Attributes + attribute syn_black_box : boolean; + attribute syn_noprune : boolean; + attribute syn_black_box of pgp_afifo_20x511 : component is TRUE; + attribute syn_noprune of pgp_afifo_20x511 : component is TRUE; + +begin + + -- Data going into Rx FIFO + rxFifoDin(19) <= '0'; + rxFifoDin(18) <= vcFrameRxSOF; + rxFifoDin(17) <= vcFrameRxEOF; + rxFifoDin(16) <= vcFrameRxEOFE; + rxFifoDin(15 downto 0) <= vcFrameRxData; + + -- Generate flow control + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + vcLocBuffAFull <= '0' after tpd; + vcLocBuffFull <= '0' after tpd; + elsif rising_edge(pgpClk) then + + -- Almost full at quarter capacity + --vcLocBuffAFull <= rxFifoCount(8); + vcLocBuffAFull <= rxFifoCount(8) or rxFifoCount(7); + + -- Full at half capacity + vcLocBuffFull <= rxFifoFull or rxFifoCount(8); + end if; + end process; + + -- Async FIFO + U_RegRxAFifo: pgp_afifo_20x511 port map ( + din => rxFifoDin, + rd_clk => locClk, + rd_en => rxFifoRd, + rst => pgpReset, + wr_clk => pgpClk, + wr_en => vcFrameRxValid, + dout => rxFifoDout, + empty => rxFifoEmpty, + full => rxFifoFull, + wr_data_count => rxFifoCount + ); + + -- Data valid + process ( locClk, locReset ) begin + if locReset = '1' then + rxFifoValid <= '0' after tpd; + elsif rising_edge(locClk) then + if rxFifoRd = '1' then + rxFifoValid <= '1' after tpd; + elsif frameRxReady = '1' then + rxFifoValid <= '0' after tpd; + end if; + end if; + end process; + + -- Control reads + rxFifoRd <= (not rxFifoEmpty) and ((not rxFifoValid) or frameRxReady); + + -- Outgoing signals + frameRxValid <= rxFifoValid; + frameRxSOF <= rxFifoDout(18); + frameRxEOF <= rxFifoDout(17); + frameRxEOFE <= rxFifoDout(16); + frameRxData <= rxFifoDout(15 downto 0); + +end PgpDsBuff; + diff --git a/rce/fw-hsio/modules/pgp/hdl/PgpFrontEnd.vhd b/rce/fw-hsio/modules/pgp/hdl/PgpFrontEnd.vhd new file mode 100755 index 00000000..3f6e9ca0 --- /dev/null +++ b/rce/fw-hsio/modules/pgp/hdl/PgpFrontEnd.vhd @@ -0,0 +1,890 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol Applications, Front End Wrapper +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : PgpFrontEnd.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 09/24/2007 +------------------------------------------------------------------------------- +-- Description: +-- Wrapper for front end logic connection to the RCE. +------------------------------------------------------------------------------- +-- Copyright (c) 2007 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 09/24/2007: created. +-- 03/06/2008: Removed width signal. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use work.Version.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity PgpFrontEnd is + generic ( + MgtMode : string := "A"; -- Default Location + RefClkSel : string := "REFCLK1" -- Reference Clock To Use "REFCLK1" or "REFCLK2" + ); + port ( + + -- Reference Clock, PGP Clock & Reset Signals + -- Use one ref clock, tie other to 0, see RefClkSel above + pgpRefClk1 : in std_logic; + pgpRefClk2 : in std_logic; + mgtRxRecClk : out std_logic; + pgpClk : in std_logic; + pgpReset : in std_logic; + + -- Display Digits + pgpDispA : out std_logic_vector(7 downto 0); + pgpDispB : out std_logic_vector(7 downto 0); + + -- Reset output + resetOut : out std_logic; + + -- Local clock and reset + locClk : in std_logic; + locReset : in std_logic; + + -- Local command signal + cmdEn : out std_logic; + cmdOpCode : out std_logic_vector(7 downto 0); + cmdCtxOut : out std_logic_vector(23 downto 0); + + -- Local register control signals + regReq : out std_logic; + regOp : out std_logic; + regInp : out std_logic; + regAck : in std_logic; + regFail : in std_logic; + regAddr : out std_logic_vector(23 downto 0); + regDataOut : out std_logic_vector(31 downto 0); + regDataIn : in std_logic_vector(31 downto 0); + + -- Local data transfer signals + frameTxEnable : in std_logic; + frameTxSOF : in std_logic; + frameTxEOF : in std_logic; + frameTxEOFE : in std_logic; + frameTxData : in std_logic_vector(15 downto 0); + frameTxAFull : out std_logic; + frameRxValid : out std_logic; + frameRxReady : in std_logic; + frameRxSOF : out std_logic; + frameRxEOF : out std_logic; + frameRxEOFE : out std_logic; + frameRxData : out std_logic_vector(15 downto 0); + valid : out std_logic; + eof : out std_logic; + sof : out std_logic; + + -- MGT Serial Pins + mgtRxN : in std_logic; + mgtRxP : in std_logic; + mgtTxN : out std_logic; + mgtTxP : out std_logic; + + -- MGT Signals For Simulation, + -- Drive mgtCombusIn to 0's, Leave mgtCombusOut open for real use + mgtCombusIn : in std_logic_vector(15 downto 0); + mgtCombusOut : out std_logic_vector(15 downto 0) + ); +end PgpFrontEnd; + + +-- Define architecture +architecture PgpFrontEnd of PgpFrontEnd is + + -- PGP Block + component PgpMgtWrap + generic ( + MgtMode : string := "A"; -- Default Location + AckTimeout : natural := 8; -- Ack/Nack Not Received Timeout, 8.192uS Steps + PicMode : natural := 0; -- PIC Interface Mode, 1=PIC, 0=Normal + RefClkSel : string := "REFCLK1"; -- Reference Clock To Use "REFCLK1" or "REFCLK2" + CScopeEnPhy : string := "DISABLE" -- Insert ChipScope, Enable or Disable + ); + port ( + pgpClk : in std_logic; -- 125Mhz master clock + pgpReset : in std_logic; -- Synchronous reset input + pibReLink : in std_logic; -- Re-Link control signal + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc0FrameTxReady : out std_logic; -- PGP is ready + vc0FrameTxSOF : in std_logic; -- User frame data start of frame + vc0FrameTxWidth : in std_logic; -- User frame data width + vc0FrameTxEOF : in std_logic; -- User frame data end of frame + vc0FrameTxEOFE : in std_logic; -- User frame data error + vc0FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc0FrameTxCid : in std_logic_vector(31 downto 0); -- User frame data, context ID + vc0FrameTxAckCid : out std_logic_vector(31 downto 0); -- PGP ACK/NACK context ID + vc0FrameTxAckEn : out std_logic; -- PGP ACK/NACK enable + vc0FrameTxAck : out std_logic; -- PGP ACK/NACK + vc0RemBuffAFull : out std_logic; -- Remote buffer almost full + vc0RemBuffFull : out std_logic; -- Remote buffer full + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxReady : out std_logic; -- PGP is ready + vc1FrameTxSOF : in std_logic; -- User frame data start of frame + vc1FrameTxWidth : in std_logic; -- User frame data width + vc1FrameTxEOF : in std_logic; -- User frame data end of frame + vc1FrameTxEOFE : in std_logic; -- User frame data error + vc1FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc1FrameTxCid : in std_logic_vector(31 downto 0); -- User frame data, context ID + vc1FrameTxAckCid : out std_logic_vector(31 downto 0); -- PGP ACK/NACK context ID + vc1FrameTxAckEn : out std_logic; -- PGP ACK/NACK enable + vc1FrameTxAck : out std_logic; -- PGP ACK/NACK + vc1RemBuffAFull : out std_logic; -- Remote buffer almost full + vc1RemBuffFull : out std_logic; -- Remote buffer full + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxReady : out std_logic; -- PGP is ready + vc2FrameTxSOF : in std_logic; -- User frame data start of frame + vc2FrameTxWidth : in std_logic; -- User frame data width + vc2FrameTxEOF : in std_logic; -- User frame data end of frame + vc2FrameTxEOFE : in std_logic; -- User frame data error + vc2FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc2FrameTxCid : in std_logic_vector(31 downto 0); -- User frame data, context ID + vc2FrameTxAckCid : out std_logic_vector(31 downto 0); -- PGP ACK/NACK context ID + vc2FrameTxAckEn : out std_logic; -- PGP ACK/NACK enable + vc2FrameTxAck : out std_logic; -- PGP ACK/NACK + vc2RemBuffAFull : out std_logic; -- Remote buffer almost full + vc2RemBuffFull : out std_logic; -- Remote buffer full + vc3FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxReady : out std_logic; -- PGP is ready + vc3FrameTxSOF : in std_logic; -- User frame data start of frame + vc3FrameTxWidth : in std_logic; -- User frame data width + vc3FrameTxEOF : in std_logic; -- User frame data end of frame + vc3FrameTxEOFE : in std_logic; -- User frame data error + vc3FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc3FrameTxCid : in std_logic_vector(31 downto 0); -- User frame data, context ID + vc3FrameTxAckCid : out std_logic_vector(31 downto 0); -- PGP ACK/NACK context ID + vc3FrameTxAckEn : out std_logic; -- PGP ACK/NACK enable + vc3FrameTxAck : out std_logic; -- PGP ACK/NACK + vc3RemBuffAFull : out std_logic; -- Remote buffer almost full + vc3RemBuffFull : out std_logic; -- Remote buffer full + vc0FrameRxValid : out std_logic; -- PGP frame data is valid + vc0FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc0FrameRxWidth : out std_logic; -- PGP frame data width + vc0FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc0FrameRxEOFE : out std_logic; -- PGP frame data error + vc0FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc0LocBuffAFull : in std_logic; -- Local buffer almost full + vc0LocBuffFull : in std_logic; -- Local buffer full + vc1FrameRxValid : out std_logic; -- PGP frame data is valid + vc1FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc1FrameRxWidth : out std_logic; -- PGP frame data width + vc1FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc1FrameRxEOFE : out std_logic; -- PGP frame data error + vc1FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc1LocBuffAFull : in std_logic; -- Local buffer almost full + vc1LocBuffFull : in std_logic; -- Local buffer full + vc2FrameRxValid : out std_logic; -- PGP frame data is valid + vc2FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc2FrameRxWidth : out std_logic; -- PGP frame data width + vc2FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc2FrameRxEOFE : out std_logic; -- PGP frame data error + vc2FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc2LocBuffAFull : in std_logic; -- Local buffer almost full + vc2LocBuffFull : in std_logic; -- Local buffer full + vc3FrameRxValid : out std_logic; -- PGP frame data is valid + vc3FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc3FrameRxWidth : out std_logic; -- PGP frame data width + vc3FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc3FrameRxEOFE : out std_logic; -- PGP frame data error + vc3FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc3LocBuffAFull : in std_logic; -- Local buffer almost full + vc3LocBuffFull : in std_logic; -- Local buffer full + localVersion : out std_logic_vector(7 downto 0); -- Local version ID + remoteVersion : out std_logic_vector(7 downto 0); -- Remote version ID + pibFail : out std_logic; -- PIB fail indication + pibState : out std_logic_vector(2 downto 0); -- PIB State + pibLock : out std_logic_vector(1 downto 0); -- PIB Lock Bits, 0=Rx, 1=Tx + pibLinkReady : out std_logic; -- PIB link is ready + pgpSeqError : out std_logic; -- PGP Sequence Logic Error Occured + countLinkDown : out std_logic; -- Link down count increment + countLinkError : out std_logic; -- Link error count increment + countNack : out std_logic; -- NACK count increment + countCellError : out std_logic; -- Receive Cell error count increment + mgtDAddr : in std_logic_vector( 7 downto 0); -- MGT Configuration Address + mgtDClk : in std_logic; -- MGT Configuration Clock + mgtDEn : in std_logic; -- MGT Configuration Data Enable + mgtDI : in std_logic_vector(15 downto 0); -- MGT Configuration Data In + mgtDO : out std_logic_vector(15 downto 0); -- MGT Configuration Data Out + mgtDRdy : out std_logic; -- MGT Configuration Ready + mgtDWe : in std_logic; -- MGT Configuration Write Enable + mgtLoopback : in std_logic; -- MGT Serial Loopback Control + mgtInverted : out std_logic; -- MGT Received Data Is Inverted + mgtRefClk1 : in std_logic; -- MGT Reference Clock In 1 + mgtRefClk2 : in std_logic; -- MGT Reference Clock In 2 + mgtRxRecClk : out std_logic; -- MGT Rx Recovered Clock + mgtRxN : in std_logic; -- MGT Serial Receive Negative + mgtRxP : in std_logic; -- MGT Serial Receive Positive + mgtTxN : out std_logic; -- MGT Serial Transmit Negative + mgtTxP : out std_logic; -- MGT Serial Transmit Positive + mgtCombusIn : in std_logic_vector(15 downto 0); + mgtCombusOut : out std_logic_vector(15 downto 0) + ); + end component; + + -- Command Block + component PgpCmdSlave + generic ( + DestId : natural := 0; -- Destination ID Value To Match + DestMask : natural := 0; -- Destination ID Mask For Match + AsyncFIFO : string := "TRUE" -- Use Async FIFOs, TRUE or FALSE + ); + port ( + pgpClk : in std_logic; -- PGP Clock + pgpReset : in std_logic; -- Synchronous PGP Reset + locClk : in std_logic; -- Local Clock + locReset : in std_logic; -- Synchronous Local Reset + vcFrameRxValid : in std_logic; -- Data is valid + vcFrameRxSOF : in std_logic; -- Data is SOF + vcFrameRxWidth : in std_logic; -- Data is 16-bits + vcFrameRxEOF : in std_logic; -- Data is EOF + vcFrameRxEOFE : in std_logic; -- Data is EOF with Error + vcFrameRxData : in std_logic_vector(15 downto 0); -- Data + vcLocBuffAFull : out std_logic; -- Local buffer almost full + vcLocBuffFull : out std_logic; -- Local buffer full + cmdEn : out std_logic; -- Command Enable + cmdOpCode : out std_logic_vector(7 downto 0); -- Command OpCode + cmdCtxOut : out std_logic_vector(23 downto 0) -- Command Context + ); + end component; + + -- Register access block + component PgpRegSlave + generic ( + AsyncFIFO : string := "TRUE" -- Use Async FIFOs, TRUE or FALSE + ); + port ( + pgpClk : in std_logic; -- PGP Clock + pgpReset : in std_logic; -- Synchronous PGP Reset + locClk : in std_logic; -- Local Clock + locReset : in std_logic; -- Synchronous Local Reset + vcFrameRxValid : in std_logic; -- Data is valid + vcFrameRxSOF : in std_logic; -- Data is SOF + vcFrameRxWidth : in std_logic; -- Data is 16-bits + vcFrameRxEOF : in std_logic; -- Data is EOF + vcFrameRxEOFE : in std_logic; -- Data is EOF with Error + vcFrameRxData : in std_logic_vector(15 downto 0); -- Data + vcLocBuffAFull : out std_logic; -- Local buffer almost full + vcLocBuffFull : out std_logic; -- Local buffer full + vcFrameTxValid : out std_logic; -- User frame data is valid + vcFrameTxReady : in std_logic; -- PGP is ready + vcFrameTxSOF : out std_logic; -- User frame data start of frame + vcFrameTxWidth : out std_logic; -- User frame data width + vcFrameTxEOF : out std_logic; -- User frame data end of frame + vcFrameTxEOFE : out std_logic; -- User frame data error + vcFrameTxData : out std_logic_vector(15 downto 0); -- User frame data + vcFrameTxCid : out std_logic_vector(31 downto 0); -- User frame data, context ID + vcFrameTxAckCid : in std_logic_vector(31 downto 0); -- PGP ACK/NACK context ID + vcFrameTxAckEn : in std_logic; -- PGP ACK/NACK enable + vcFrameTxAck : in std_logic; -- PGP ACK/NACK + vcRemBuffAFull : in std_logic; -- Remote buffer almost full + vcRemBuffFull : in std_logic; -- Remote buffer full + regInp : out std_logic; -- Register Access In Progress Flag + regReq : out std_logic; -- Register Access Request + regOp : out std_logic; -- Register OpCode, 0=Read, 1=Write + regAck : in std_logic; -- Register Access Acknowledge + regFail : in std_logic; -- Register Access Fail + regAddr : out std_logic_vector(23 downto 0); -- Register Address + regDataOut : out std_logic_vector(31 downto 0); -- Register Data Out + regDataIn : in std_logic_vector(31 downto 0) -- Register Data In + ); + end component; + + -- Data buffer + component PgpDataBuffer + port ( + pgpClk : in std_logic; + pgpReset : in std_logic; + locClk : in std_logic; + locReset : in std_logic; + frameTxEnable : in std_logic; + frameTxSOF : in std_logic; + frameTxEOF : in std_logic; + frameTxEOFE : in std_logic; + frameTxData : in std_logic_vector(15 downto 0); + frameTxAFull : out std_logic; + vcFrameTxValid : out std_logic; + vcFrameTxReady : in std_logic; + vcFrameTxSOF : out std_logic; + vcFrameTxWidth : out std_logic; + vcFrameTxEOF : out std_logic; + vcFrameTxEOFE : out std_logic; + vcFrameTxData : out std_logic_vector(15 downto 0); + vcFrameTxCid : out std_logic_vector(31 downto 0); + vcFrameTxAckCid : in std_logic_vector(31 downto 0); + vcFrameTxAckEn : in std_logic; + vcFrameTxAck : in std_logic; + vcRemBuffAFull : in std_logic; + vcRemBuffFull : in std_logic; + dataOverFlow : out std_logic + ); + end component; + + -- Downstream buffer + component PgpDsBuff + port ( + pgpClk : in std_logic; + pgpReset : in std_logic; + locClk : in std_logic; + locReset : in std_logic; + vcFrameRxValid : in std_logic; + vcFrameRxSOF : in std_logic; + vcFrameRxWidth : in std_logic; + vcFrameRxEOF : in std_logic; + vcFrameRxEOFE : in std_logic; + vcFrameRxData : in std_logic_vector(15 downto 0); + vcLocBuffAFull : out std_logic; + vcLocBuffFull : out std_logic; + frameRxValid : out std_logic; + frameRxReady : in std_logic; + frameRxSOF : out std_logic; + frameRxEOF : out std_logic; + frameRxEOFE : out std_logic; + frameRxData : out std_logic_vector(15 downto 0) + ); + end component; + + -- Local Signals + signal pibReLink : std_logic; + signal vc0FrameTxValid : std_logic; + signal vc0FrameTxReady : std_logic; + signal vc0FrameTxSOF : std_logic; + signal vc0FrameTxWidth : std_logic; + signal vc0FrameTxEOF : std_logic; + signal vc0FrameTxEOFE : std_logic; + signal vc0FrameTxData : std_logic_vector(15 downto 0); + signal vc0FrameTxCid : std_logic_vector(31 downto 0); + signal vc0FrameTxAckCid : std_logic_vector(31 downto 0); + signal vc0FrameTxAckEn : std_logic; + signal vc0FrameTxAck : std_logic; + signal vc0RemBuffAFull : std_logic; + signal vc0RemBuffFull : std_logic; + signal vc1FrameTxValid : std_logic; + signal vc1FrameTxReady : std_logic; + signal vc1FrameTxSOF : std_logic; + signal vc1FrameTxWidth : std_logic; + signal vc1FrameTxEOF : std_logic; + signal vc1FrameTxEOFE : std_logic; + signal vc1FrameTxData : std_logic_vector(15 downto 0); + signal vc1FrameTxCid : std_logic_vector(31 downto 0); + signal vc1FrameTxAckCid : std_logic_vector(31 downto 0); + signal vc1FrameTxAckEn : std_logic; + signal vc1FrameTxAck : std_logic; + signal vc1RemBuffAFull : std_logic; + signal vc1RemBuffFull : std_logic; + signal vc2FrameTxValid : std_logic; + signal vc2FrameTxReady : std_logic; + signal vc2FrameTxSOF : std_logic; + signal vc2FrameTxWidth : std_logic; + signal vc2FrameTxEOF : std_logic; + signal vc2FrameTxEOFE : std_logic; + signal vc2FrameTxData : std_logic_vector(15 downto 0); + signal vc2FrameTxCid : std_logic_vector(31 downto 0); + signal vc2FrameTxAckCid : std_logic_vector(31 downto 0); + signal vc2FrameTxAckEn : std_logic; + signal vc2FrameTxAck : std_logic; + signal vc2RemBuffAFull : std_logic; + signal vc2RemBuffFull : std_logic; + signal vc3FrameTxValid : std_logic; + signal vc3FrameTxReady : std_logic; + signal vc3FrameTxSOF : std_logic; + signal vc3FrameTxWidth : std_logic; + signal vc3FrameTxEOF : std_logic; + signal vc3FrameTxEOFE : std_logic; + signal vc3FrameTxData : std_logic_vector(15 downto 0); + signal vc3FrameTxCid : std_logic_vector(31 downto 0); + signal vc3FrameTxAckCid : std_logic_vector(31 downto 0); + signal vc3FrameTxAckEn : std_logic; + signal vc3FrameTxAck : std_logic; + signal vc3RemBuffAFull : std_logic; + signal vc3RemBuffFull : std_logic; + signal vc0FrameRxValid : std_logic; + signal vc0FrameRxSOF : std_logic; + signal vc0FrameRxWidth : std_logic; + signal vc0FrameRxEOF : std_logic; + signal vc0FrameRxEOFE : std_logic; + signal vc0FrameRxData : std_logic_vector(15 downto 0); + signal vc0LocBuffAFull : std_logic; + signal vc0LocBuffFull : std_logic; + signal vc1FrameRxValid : std_logic; + signal vc1FrameRxSOF : std_logic; + signal vc1FrameRxWidth : std_logic; + signal vc1FrameRxEOF : std_logic; + signal vc1FrameRxEOFE : std_logic; + signal vc1FrameRxData : std_logic_vector(15 downto 0); + signal vc1LocBuffAFull : std_logic; + signal vc1LocBuffFull : std_logic; + signal vc2FrameRxValid : std_logic; + signal vc2FrameRxSOF : std_logic; + signal vc2FrameRxWidth : std_logic; + signal vc2FrameRxEOF : std_logic; + signal vc2FrameRxEOFE : std_logic; + signal vc2FrameRxData : std_logic_vector(15 downto 0); + signal vc2LocBuffAFull : std_logic; + signal vc2LocBuffFull : std_logic; + signal vc3FrameRxValid : std_logic; + signal vc3FrameRxSOF : std_logic; + signal vc3FrameRxWidth : std_logic; + signal vc3FrameRxEOF : std_logic; + signal vc3FrameRxEOFE : std_logic; + signal vc3FrameRxData : std_logic_vector(15 downto 0); + signal vc3LocBuffAFull : std_logic; + signal vc3LocBuffFull : std_logic; + signal pibState : std_logic_vector(2 downto 0); + signal pibLock : std_logic_vector(1 downto 0); + signal countLinkDown : std_logic; + signal countLinkError : std_logic; + signal countNack : std_logic; + signal countCellError : std_logic; + signal mgtInverted : std_logic; + signal cntLinkError : std_logic_vector(3 downto 0); + signal cntNack : std_logic_vector(3 downto 0); + signal cntCellError : std_logic_vector(3 downto 0); + signal cntLinkDown : std_logic_vector(3 downto 0); + signal cntOverFlow : std_logic_vector(3 downto 0); + signal pllLock : std_logic; + signal pllLockDly : std_logic; + signal cntPllLock : std_logic_vector(3 downto 0); + signal pgpSeqError : std_logic; + signal intRegReq : std_logic; + signal intRegOp : std_logic; + signal intRegAck : std_logic; + signal intRegFail : std_logic; + signal intRegAddr : std_logic_vector(23 downto 0); + signal intRegDataOut : std_logic_vector(31 downto 0); + signal intRegDataIn : std_logic_vector(31 downto 0); + signal intCmdEn : std_logic; + signal intCmdOpCode : std_logic_vector(7 downto 0); + signal intCmdCtxOut : std_logic_vector(23 downto 0); + signal scratchPad : std_logic_vector(31 downto 0); + signal countReset : std_logic; + signal dataOverFlow : std_logic; + signal intCmdAFull : std_logic; + signal intCmdFull : std_logic; + signal extCmdAFull : std_logic; + signal extCmdFull : std_logic; + signal pibError : std_logic; + signal txCount : std_logic_vector(31 downto 0); + signal pibLinkReady : std_logic; + signal pibFail : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Display values + pgpDispB <= x"0" & txCount(3 downto 0); + pgpDispA <= x"10" when pllLock = '0' else -- Display 'P' + x"0F" when pibFail = '1' else -- Display 'F' + x"11" when pibLinkReady = '0' else -- Display 'N' + x"0E" when pibError = '1' else -- Display 'E' + x"12"; -- Display 'L' + + -- Detect error status + pibError <= '1' when (cntLinkError & cntCellError & cntNack) /= 0 else pgpSeqError; + + -- Transaction Counter + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + txCount <= (others=>'0') after tpd; + elsif rising_edge(pgpClk) then + if pibLinkReady = '0' then + txCount <= (others=>'0') after tpd; + else + if (vc0FrameTxReady = '1' and vc0FrameTxEOF = '1') or + (vc1FrameTxReady = '1' and vc1FrameTxEOF = '1') or + (vc2FrameTxReady = '1' and vc2FrameTxEOF = '1') or + (vc3FrameTxReady = '1' and vc3FrameTxEOF = '1') then + txCount <= txCount + 1 after tpd; + end if; + end if; + end if; + end process; + + + -- Register read and write + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + intRegDataIn <= (others=>'0') after tpd; + intRegAck <= '0' after tpd; + intRegFail <= '0' after tpd; + scratchPad <= (others=>'0') after tpd; + elsif rising_edge(pgpClk) then + + -- Register request is pending + if intRegReq = '1' then + + -- Drive ack + intRegAck <= '1' after tpd; + + -- Read + if intRegOp = '0' then + + -- Which register + case intRegAddr is + + when x"000000" => + intRegDataIn <= FpgaVersion after tpd; + intRegFail <= '0' after tpd; + + when x"000001" => + intRegDataIn <= scratchPad after tpd; + intRegFail <= '0' after tpd; + + when x"000002" => + intRegDataIn(31) <= '0' after tpd; + intRegDataIn(30) <= '0' after tpd; + intRegDataIn(29) <= mgtInverted after tpd; + intRegDataIn(28) <= pgpSeqError after tpd; + intRegDataIn(27 downto 24) <= cntOverFlow after tpd; + intRegDataIn(23 downto 20) <= cntPllLock after tpd; + intRegDataIn(19 downto 16) <= cntLinkDown after tpd; + intRegDataIn(15 downto 12) <= cntLinkError after tpd; + intRegDataIn(11 downto 8) <= cntNack after tpd; + intRegDataIn( 7 downto 4) <= cntCellError after tpd; + intRegDataIn( 3 downto 0) <= "0000" after tpd; + intRegFail <= '0' after tpd; + + when x"000003" => + intRegDataIn <= txCount after tpd; + intRegFail <= '0' after tpd; + + when others => + intRegFail <= '1' after tpd; + intRegDataIn <= (others=>'0') after tpd; + end case; + + -- Write + else + + -- Scratchpad write + if intRegAddr = x"000001" then + intRegFail <= '0' after tpd; + scratchPad <= intRegDataOut after tpd; + else + intRegFail <= '1' after tpd; + end if; + end if; + + -- No Request + else + intRegAck <= '0' after tpd; + intRegFail <= '0' after tpd; + intRegDataIn <= (others=>'0') after tpd; + end if; + end if; + end process; + + + -- Internal command receiver + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + countReset <= '0' after tpd; + pibReLink <= '0' after tpd; + resetOut <= '0' after tpd; + elsif rising_edge(pgpClk) then + + -- Internal command received + if intCmdEn = '1' then + + -- Reset + if intCmdOpCode = "00000000" then + resetOut <= '1' after tpd; + countReset <= '0' after tpd; + pibReLink <= '0' after tpd; + + -- Count Reset + elsif intCmdOpCode = "00000001" then + countReset <= '1' after tpd; + pibReLink <= '0' after tpd; + + -- PGP Relink + elsif intCmdOpCode = "00000010" then + countReset <= '0' after tpd; + pibReLink <= '1' after tpd; + + else + countReset <= '0' after tpd; + pibReLink <= '0' after tpd; + end if; + else + countReset <= '0' after tpd; + pibReLink <= '0' after tpd; + end if; + end if; + end process; + + + -- Error Counters + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + cntLinkError <= (others=>'0') after tpd; + cntNack <= (others=>'0') after tpd; + cntCellError <= (others=>'0') after tpd; + cntLinkDown <= (others=>'0') after tpd; + cntPllLock <= (others=>'0') after tpd; + cntOverFlow <= (others=>'0') after tpd; + pllLock <= '0' after tpd; + pllLockDly <= '0' after tpd; + elsif rising_edge(pgpClk) then + + -- Link Error Counter, 8-bits + if countReset = '1' or pibLinkReady = '0' then + cntLinkError <= (others=>'0') after tpd; + elsif countLinkError = '1' and cntLinkError /= x"F" then + cntLinkError <= cntLinkError + 1 after tpd; + end if; + + -- Nack Counter, 8-bits + if countReset = '1' or pibLinkReady = '0' then + cntNack <= (others=>'0') after tpd; + elsif countNack = '1' and cntNack /= x"F" then + cntNack <= cntNack + 1 after tpd; + end if; + + -- Cell Error Counter, 8-bits + if countReset = '1' or pibLinkReady = '0' then + cntCellError <= (others=>'0') after tpd; + elsif countCellError = '1' and cntCellError /= x"F" then + cntCellError <= cntCellError + 1 after tpd; + end if; + + -- Link Down Counter, 8-bits + if countReset = '1' then + cntLinkDown <= (others=>'0') after tpd; + elsif countLinkDown = '1' and cntLinkDown /= x"F" then + cntLinkDown <= cntLinkDown + 1 after tpd; + end if; + + -- PLL Unlock Counter + if countReset = '1' or pibLinkReady = '0' then + cntPllLock <= (others=>'0') after tpd; + elsif pllLock = '0' and pllLockDly = '1' and cntPllLock /= x"F" then + cntPllLock <= cntPllLock + 1 after tpd; + end if; + + -- PLL Lock Edge Detection + pllLock <= pibLock(1) and pibLock(0) after tpd; + pllLockDly <= pllLock after tpd; + + -- Data overflow counter + if countReset = '1' then + cntOverFlow <= (others=>'0') after tpd; + elsif dataOverFlow = '1'and cntOverFlow /= x"F" then + cntOverFlow <= cntOverFlow + 1 after tpd; + end if; + + end if; + end process; + + + -- PGP Wrap + U_PgpMgtWrap: PgpMgtWrap + generic map ( MgtMode => MgtMode, AckTimeout => 8, + PicMode => 0, RefClkSel => RefClkSel, + CScopeEnPhy => "DISABLE" ) port map ( + pgpClk => pgpClk, + pgpReset => pgpReset, + pibReLink => pibReLink, + vc0FrameTxValid => vc0FrameTxValid, vc0FrameTxReady => vc0FrameTxReady, + vc0FrameTxSOF => vc0FrameTxSOF, vc0FrameTxWidth => vc0FrameTxWidth, + vc0FrameTxEOF => vc0FrameTxEOF, vc0FrameTxEOFE => vc0FrameTxEOFE, + vc0FrameTxData => vc0FrameTxData, vc0FrameTxCid => vc0FrameTxCid, + vc0FrameTxAckCid => vc0FrameTxAckCid, vc0FrameTxAckEn => vc0FrameTxAckEn, + vc0FrameTxAck => vc0FrameTxAck, vc0RemBuffAFull => vc0RemBuffAFull, + vc0RemBuffFull => vc0RemBuffFull, vc1FrameTxValid => vc1FrameTxValid, + vc1FrameTxReady => vc1FrameTxReady, vc1FrameTxSOF => vc1FrameTxSOF, + vc1FrameTxWidth => vc1FrameTxWidth, vc1FrameTxEOF => vc1FrameTxEOF, + vc1FrameTxEOFE => vc1FrameTxEOFE, vc1FrameTxData => vc1FrameTxData, + vc1FrameTxCid => vc1FrameTxCid, vc1FrameTxAckCid => vc1FrameTxAckCid, + vc1FrameTxAckEn => vc1FrameTxAckEn, vc1FrameTxAck => vc1FrameTxAck, + vc1RemBuffAFull => vc1RemBuffAFull, vc1RemBuffFull => vc1RemBuffFull, + vc2FrameTxValid => vc2FrameTxValid, vc2FrameTxReady => vc2FrameTxReady, + vc2FrameTxSOF => vc2FrameTxSOF, vc2FrameTxWidth => vc2FrameTxWidth, + vc2FrameTxEOF => vc2FrameTxEOF, vc2FrameTxEOFE => vc2FrameTxEOFE, + vc2FrameTxData => vc2FrameTxData, vc2FrameTxCid => vc2FrameTxCid, + vc2FrameTxAckCid => vc2FrameTxAckCid, vc2FrameTxAckEn => vc2FrameTxAckEn, + vc2FrameTxAck => vc2FrameTxAck, vc2RemBuffAFull => vc2RemBuffAFull, + vc2RemBuffFull => vc2RemBuffFull, vc3FrameTxValid => vc3FrameTxValid, + vc3FrameTxReady => vc3FrameTxReady, vc3FrameTxSOF => vc3FrameTxSOF, + vc3FrameTxWidth => vc3FrameTxWidth, vc3FrameTxEOF => vc3FrameTxEOF, + vc3FrameTxEOFE => vc3FrameTxEOFE, vc3FrameTxData => vc3FrameTxData, + vc3FrameTxCid => vc3FrameTxCid, vc3FrameTxAckCid => vc3FrameTxAckCid, + vc3FrameTxAckEn => vc3FrameTxAckEn, vc3FrameTxAck => vc3FrameTxAck, + vc3RemBuffAFull => vc3RemBuffAFull, vc3RemBuffFull => vc3RemBuffFull, + vc0FrameRxValid => vc0FrameRxValid, vc0FrameRxSOF => vc0FrameRxSOF, + vc0FrameRxWidth => vc0FrameRxWidth, vc0FrameRxEOF => vc0FrameRxEOF, + vc0FrameRxEOFE => vc0FrameRxEOFE, vc0FrameRxData => vc0FrameRxData, + vc0LocBuffAFull => vc0LocBuffAFull, vc0LocBuffFull => vc0LocBuffFull, + vc1FrameRxValid => vc1FrameRxValid, vc1FrameRxSOF => vc1FrameRxSOF, + vc1FrameRxWidth => vc1FrameRxWidth, vc1FrameRxEOF => vc1FrameRxEOF, + vc1FrameRxEOFE => vc1FrameRxEOFE, vc1FrameRxData => vc1FrameRxData, + vc1LocBuffAFull => vc1LocBuffAFull, vc1LocBuffFull => vc1LocBuffFull, + vc2FrameRxValid => vc2FrameRxValid, vc2FrameRxSOF => vc2FrameRxSOF, + vc2FrameRxWidth => vc2FrameRxWidth, vc2FrameRxEOF => vc2FrameRxEOF, + vc2FrameRxEOFE => vc2FrameRxEOFE, vc2FrameRxData => vc2FrameRxData, + vc2LocBuffAFull => vc2LocBuffAFull, vc2LocBuffFull => vc2LocBuffFull, + vc3FrameRxValid => vc3FrameRxValid, vc3FrameRxSOF => vc3FrameRxSOF, + vc3FrameRxWidth => vc3FrameRxWidth, vc3FrameRxEOF => vc3FrameRxEOF, + vc3FrameRxEOFE => vc3FrameRxEOFE, vc3FrameRxData => vc3FrameRxData, + vc3LocBuffAFull => vc3LocBuffAFull, vc3LocBuffFull => vc3LocBuffFull, + localVersion => open, remoteVersion => open, + pibFail => pibFail, pibState => pibState, + pibLinkReady => pibLinkReady, pgpSeqError => pgpSeqError, + countLinkDown => countLinkDown, countLinkError => countLinkError, + countNack => countNack, countCellError => countCellError, + mgtDAddr => (others=>'0'), mgtDClk => '0', + mgtDEn => '0', mgtDI => (others=>'0'), + mgtDO => open, mgtDRdy => open, + mgtDWe => '0', mgtLoopback => '0', + mgtInverted => mgtInverted, mgtRefClk1 => pgpRefClk1, + mgtRefClk2 => pgpRefClk2, mgtRxN => mgtRxN, + mgtRxP => mgtRxP, mgtTxN => mgtTxN, + mgtTxP => mgtTxP, mgtCombusIn => mgtCombusIn, + mgtCombusOut => mgtCombusOut, pibLock => pibLock, + mgtRxRecClk => mgtRxRecClk + ); + + + -- VC0, External command processor + U_ExtCmd: PgpCmdSlave + generic map ( + DestId => 0, + DestMask => 1, + AsyncFIFO => "TRUE" + ) port map ( + pgpClk => pgpClk, pgpReset => pgpReset, + locClk => locClk, locReset => locReset, + vcFrameRxValid => vc0FrameRxValid, vcFrameRxSOF => vc0FrameRxSOF, + vcFrameRxWidth => vc0FrameRxWidth, vcFrameRxEOF => vc0FrameRxEOF, + vcFrameRxEOFE => vc0FrameRxEOFE, vcFrameRxData => vc0FrameRxData, + vcLocBuffAFull => extCmdAFull, vcLocBuffFull => extCmdFull, + cmdEn => cmdEn, cmdOpCode => cmdOpCode, + cmdCtxOut => cmdCtxOut + ); + + + -- VC0, Internal command processor + U_IntCmd: PgpCmdSlave + generic map ( + DestId => 1, + DestMask => 1, + AsyncFIFO => "FALSE" + ) port map ( + pgpClk => pgpClk, pgpReset => pgpReset, + locClk => pgpClk, locReset => pgpReset, + vcFrameRxValid => vc0FrameRxValid, vcFrameRxSOF => vc0FrameRxSOF, + vcFrameRxWidth => vc0FrameRxWidth, vcFrameRxEOF => vc0FrameRxEOF, + vcFrameRxEOFE => vc0FrameRxEOFE, vcFrameRxData => vc0FrameRxData, + vcLocBuffAFull => intCmdAFull, vcLocBuffFull => intCmdFull, + cmdEn => intCmdEn, cmdOpCode => intCmdOpCode, + cmdCtxOut => intCmdCtxOut + ); + + -- Generate flow control + vc0LocBuffAFull <= extCmdAFull or intCmdAFull; + vc0LocBuffFull <= extCmdFull or intCmdFull; + + + -- Return data, VC0 + U_DataBuff: PgpDataBuffer port map ( + pgpClk => pgpClk, pgpReset => pgpReset, + locClk => locClk, locReset => locReset, + frameTxEnable => frameTxEnable, frameTxSOF => frameTxSOF, + frameTxEOF => frameTxEOF, frameTxEOFE => frameTxEOFE, + frameTxData => frameTxData, frameTxAFull => frameTxAFull, + vcFrameTxValid => vc0FrameTxValid, + vcFrameTxReady => vc0FrameTxReady, vcFrameTxSOF => vc0FrameTxSOF, + vcFrameTxWidth => vc0FrameTxWidth, vcFrameTxEOF => vc0FrameTxEOF, + vcFrameTxEOFE => vc0FrameTxEOFE, vcFrameTxData => vc0FrameTxData, + vcFrameTxCid => vc0FrameTxCid, vcFrameTxAckCid => vc0FrameTxAckCid, + vcFrameTxAckEn => vc0FrameTxAckEn, vcFrameTxAck => vc0FrameTxAck, + vcRemBuffAFull => vc0RemBuffAFull, vcRemBuffFull => vc0RemBuffFull, + dataOverFlow => dataOverFlow + ); + + valid<=vc0FrameTxValid; + eof<=vc0FrameTxEOF; + sof<=vc0FrameTxSOF; + + -- VC1, External register access control + U_ExtReg: PgpRegSlave generic map ( AsyncFIFO => "TRUE" ) port map ( + pgpClk => pgpClk, pgpReset => pgpReset, + locClk => locClk, locReset => locReset, + vcFrameRxValid => vc1FrameRxValid, vcFrameRxSOF => vc1FrameRxSOF, + vcFrameRxWidth => vc1FrameRxWidth, vcFrameRxEOF => vc1FrameRxEOF, + vcFrameRxEOFE => vc1FrameRxEOFE, vcFrameRxData => vc1FrameRxData, + vcLocBuffAFull => vc1LocBuffAFull, vcLocBuffFull => vc1LocBuffFull, + vcFrameTxValid => vc1FrameTxValid, vcFrameTxReady => vc1FrameTxReady, + vcFrameTxSOF => vc1FrameTxSOF, vcFrameTxWidth => vc1FrameTxWidth, + vcFrameTxEOF => vc1FrameTxEOF, vcFrameTxEOFE => vc1FrameTxEOFE, + vcFrameTxData => vc1FrameTxData, vcFrameTxCid => vc1FrameTxCid, + vcFrameTxAckCid => vc1FrameTxAckCid, vcFrameTxAckEn => vc1FrameTxAckEn, + vcFrameTxAck => vc1FrameTxAck, vcRemBuffAFull => vc1RemBuffAFull, + vcRemBuffFull => vc1RemBuffFull, regReq => regReq, + regOp => regOp, regAck => regAck, + regFail => regFail, regAddr => regAddr, + regDataOut => regDataOut, regDataIn => regDataIn, + regInp => regInp + ); + + + -- VC2, Internal register access control + U_IntReg: PgpRegSlave generic map ( AsyncFIFO => "FALSE" ) port map ( + pgpClk => pgpClk, pgpReset => pgpReset, + locClk => pgpClk, locReset => pgpReset, + vcFrameRxValid => vc2FrameRxValid, vcFrameRxSOF => vc2FrameRxSOF, + vcFrameRxWidth => vc2FrameRxWidth, vcFrameRxEOF => vc2FrameRxEOF, + vcFrameRxEOFE => vc2FrameRxEOFE, vcFrameRxData => vc2FrameRxData, + vcLocBuffAFull => vc2LocBuffAFull, vcLocBuffFull => vc2LocBuffFull, + vcFrameTxValid => vc2FrameTxValid, vcFrameTxReady => vc2FrameTxReady, + vcFrameTxSOF => vc2FrameTxSOF, vcFrameTxWidth => vc2FrameTxWidth, + vcFrameTxEOF => vc2FrameTxEOF, vcFrameTxEOFE => vc2FrameTxEOFE, + vcFrameTxData => vc2FrameTxData, vcFrameTxCid => vc2FrameTxCid, + vcFrameTxAckCid => vc2FrameTxAckCid, vcFrameTxAckEn => vc2FrameTxAckEn, + vcFrameTxAck => vc2FrameTxAck, vcRemBuffAFull => vc2RemBuffAFull, + vcRemBuffFull => vc2RemBuffFull, regReq => intRegReq, + regOp => intRegOp, regAck => intRegAck, + regFail => intRegFail, regAddr => intRegAddr, + regDataOut => intRegDataOut, regDataIn => intRegDataIn + ); + + -- VC3, Downstream data + U_DsBuff: PgpDsBuff port map ( + pgpClk => pgpClk, + pgpReset => pgpReset, + locClk => locClk, + locReset => locReset, + vcFrameRxValid => vc3FrameRxValid, + vcFrameRxSOF => vc3FrameRxSOF, + vcFrameRxWidth => vc3FrameRxWidth, + vcFrameRxEOF => vc3FrameRxEOF, + vcFrameRxEOFE => vc3FrameRxEOFE, + vcFrameRxData => vc3FrameRxData, + vcLocBuffAFull => vc3LocBuffAFull, + vcLocBuffFull => vc3LocBuffFull, + frameRxValid => frameRxValid, + frameRxReady => frameRxReady, + frameRxSOF => frameRxSOF, + frameRxEOF => frameRxEOF, + frameRxEOFE => frameRxEOFE, + frameRxData => frameRxData + ); + + -- VC3 transmit is unused + vc3FrameTxValid <= '0'; + vc3FrameTxEOFE <= '0'; + vc3FrameTxEOF <= '0'; + vc3FrameTxWidth <= '0'; + vc3FrameTxSOF <= '0'; + vc3FrameTxData <= (others=>'0'); + vc3FrameTxCid <= (others=>'0'); + +end PgpFrontEnd; + diff --git a/rce/fw-hsio/modules/pgp/hdl/PgpMgtWrap.vhd b/rce/fw-hsio/modules/pgp/hdl/PgpMgtWrap.vhd new file mode 100755 index 00000000..63a2db48 --- /dev/null +++ b/rce/fw-hsio/modules/pgp/hdl/PgpMgtWrap.vhd @@ -0,0 +1,1590 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, MGT Wrapper +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : PgpMgtWrap.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 03/15/2007 +------------------------------------------------------------------------------- +-- Description: +-- VHDL source file containing the PGP, MGT and CRC blocks. +-- This module also contains the logic to control the reset of the MGT. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 03/15/2007: created. +-- 06/01/2007: Included MGT block instead of using xilinx wrapper. +-- 06/08/2007: CRC blocks now held in reset when link is down. +-- 06/08/2007: Added Lock Bits +-- 08/25/2007: Changed error count signals. +-- 09/18/2007: Added force cell size signal +-- 09/19/2007: Changed force cell size signal to PIC mode signal +-- 09/21/2007: Ack timeout & Pic Mode converted to generics, +-- Added Generic for reference clock selection and ref clock 2 in +-- 01/25/2008: Added MGT Recovered Clock Output +-- 11/05/2008: Added reset state machine logic. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; +-- synopsys translate_off +library UNISIM; +use UNISIM.VCOMPONENTS.ALL; +-- synopsys translate_on + + +entity PgpMgtWrap is + generic ( + MgtMode : string := "A"; -- Default Location + AckTimeout : natural := 8; -- Ack/Nack Not Received Timeout, 8.192uS Steps + PicMode : natural := 1; -- PIC Interface Mode, 1=PIC, 0=Normal + RefClkSel : string := "REFCLK1"; -- Reference Clock To Use "REFCLK1" or "REFCLK2" + CScopeEnPhy : string := "DISABLE" -- Insert ChipScope, Enable or Disable + ); + port ( + + -- System clock, reset & control + pgpClk : in std_logic; -- 125Mhz master clock + pgpReset : in std_logic; -- Synchronous reset input + pibReLink : in std_logic; -- Re-Link control signal + + -- Frame Transmit Interface, VC 0 + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc0FrameTxReady : out std_logic; -- PGP is ready + vc0FrameTxSOF : in std_logic; -- User frame data start of frame + vc0FrameTxWidth : in std_logic; -- User frame data width + vc0FrameTxEOF : in std_logic; -- User frame data end of frame + vc0FrameTxEOFE : in std_logic; -- User frame data error + vc0FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc0FrameTxCid : in std_logic_vector(31 downto 0); -- User frame data, context ID + vc0FrameTxAckCid : out std_logic_vector(31 downto 0); -- PGP ACK/NACK context ID + vc0FrameTxAckEn : out std_logic; -- PGP ACK/NACK enable + vc0FrameTxAck : out std_logic; -- PGP ACK/NACK + vc0RemBuffAFull : out std_logic; -- Remote buffer almost full + vc0RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 1 + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxReady : out std_logic; -- PGP is ready + vc1FrameTxSOF : in std_logic; -- User frame data start of frame + vc1FrameTxWidth : in std_logic; -- User frame data width + vc1FrameTxEOF : in std_logic; -- User frame data end of frame + vc1FrameTxEOFE : in std_logic; -- User frame data error + vc1FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc1FrameTxCid : in std_logic_vector(31 downto 0); -- User frame data, context ID + vc1FrameTxAckCid : out std_logic_vector(31 downto 0); -- PGP ACK/NACK context ID + vc1FrameTxAckEn : out std_logic; -- PGP ACK/NACK enable + vc1FrameTxAck : out std_logic; -- PGP ACK/NACK + vc1RemBuffAFull : out std_logic; -- Remote buffer almost full + vc1RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 2 + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxReady : out std_logic; -- PGP is ready + vc2FrameTxSOF : in std_logic; -- User frame data start of frame + vc2FrameTxWidth : in std_logic; -- User frame data width + vc2FrameTxEOF : in std_logic; -- User frame data end of frame + vc2FrameTxEOFE : in std_logic; -- User frame data error + vc2FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc2FrameTxCid : in std_logic_vector(31 downto 0); -- User frame data, context ID + vc2FrameTxAckCid : out std_logic_vector(31 downto 0); -- PGP ACK/NACK context ID + vc2FrameTxAckEn : out std_logic; -- PGP ACK/NACK enable + vc2FrameTxAck : out std_logic; -- PGP ACK/NACK + vc2RemBuffAFull : out std_logic; -- Remote buffer almost full + vc2RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 3 + vc3FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxReady : out std_logic; -- PGP is ready + vc3FrameTxSOF : in std_logic; -- User frame data start of frame + vc3FrameTxWidth : in std_logic; -- User frame data width + vc3FrameTxEOF : in std_logic; -- User frame data end of frame + vc3FrameTxEOFE : in std_logic; -- User frame data error + vc3FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc3FrameTxCid : in std_logic_vector(31 downto 0); -- User frame data, context ID + vc3FrameTxAckCid : out std_logic_vector(31 downto 0); -- PGP ACK/NACK context ID + vc3FrameTxAckEn : out std_logic; -- PGP ACK/NACK enable + vc3FrameTxAck : out std_logic; -- PGP ACK/NACK + vc3RemBuffAFull : out std_logic; -- Remote buffer almost full + vc3RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 0 + vc0FrameRxValid : out std_logic; -- PGP frame data is valid + vc0FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc0FrameRxWidth : out std_logic; -- PGP frame data width + vc0FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc0FrameRxEOFE : out std_logic; -- PGP frame data error + vc0FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc0LocBuffAFull : in std_logic; -- Local buffer almost full + vc0LocBuffFull : in std_logic; -- Local buffer full + + -- Frame Receive Interface, VC 1 + vc1FrameRxValid : out std_logic; -- PGP frame data is valid + vc1FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc1FrameRxWidth : out std_logic; -- PGP frame data width + vc1FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc1FrameRxEOFE : out std_logic; -- PGP frame data error + vc1FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc1LocBuffAFull : in std_logic; -- Local buffer almost full + vc1LocBuffFull : in std_logic; -- Local buffer full + + -- Frame Receive Interface, VC 2 + vc2FrameRxValid : out std_logic; -- PGP frame data is valid + vc2FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc2FrameRxWidth : out std_logic; -- PGP frame data width + vc2FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc2FrameRxEOFE : out std_logic; -- PGP frame data error + vc2FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc2LocBuffAFull : in std_logic; -- Local buffer almost full + vc2LocBuffFull : in std_logic; -- Local buffer full + + -- Frame Receive Interface, VC 3 + vc3FrameRxValid : out std_logic; -- PGP frame data is valid + vc3FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc3FrameRxWidth : out std_logic; -- PGP frame data width + vc3FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc3FrameRxEOFE : out std_logic; -- PGP frame data error + vc3FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc3LocBuffAFull : in std_logic; -- Local buffer almost full + vc3LocBuffFull : in std_logic; -- Local buffer full + + -- Event Counters & Status Signals + localVersion : out std_logic_vector(7 downto 0); -- Local version ID + remoteVersion : out std_logic_vector(7 downto 0); -- Remote version ID + pibFail : out std_logic; -- PIB fail indication + pibState : out std_logic_vector(2 downto 0); -- PIB State + pibLock : out std_logic_vector(1 downto 0); -- PIB Lock Bits, 0=Rx, 1=Tx + pibLinkReady : out std_logic; -- PIB link is ready + pgpSeqError : out std_logic; -- PGP Sequence Logic Error Occured + countLinkDown : out std_logic; -- Link down count increment + countLinkError : out std_logic; -- Disparity/Decode err count + countNack : out std_logic; -- NACK count increment + countCellError : out std_logic; -- Receive cell error count + + -- MGT Configuration Port + mgtDAddr : in std_logic_vector( 7 downto 0); -- MGT Configuration Address + mgtDClk : in std_logic; -- MGT Configuration Clock + mgtDEn : in std_logic; -- MGT Configuration Data Enable + mgtDI : in std_logic_vector(15 downto 0); -- MGT Configuration Data In + mgtDO : out std_logic_vector(15 downto 0); -- MGT Configuration Data Out + mgtDRdy : out std_logic; -- MGT Configuration Ready + mgtDWe : in std_logic; -- MGT Configuration Write Enable + + -- MGT Status & Control Signals + mgtLoopback : in std_logic; -- MGT Serial Loopback Control + mgtInverted : out std_logic; -- MGT Received Data Is Inverted + + -- MGT Signals, Drive Ref Clock Which Matches RefClkSel Generic Above + mgtRefClk1 : in std_logic; -- MGT Reference Clock In 1 + mgtRefClk2 : in std_logic; -- MGT Reference Clock In 2 + mgtRxRecClk : out std_logic; -- MGT Rx Recovered Clock + mgtRxN : in std_logic; -- MGT Serial Receive Negative + mgtRxP : in std_logic; -- MGT Serial Receive Positive + mgtTxN : out std_logic; -- MGT Serial Transmit Negative + mgtTxP : out std_logic; -- MGT Serial Transmit Positive + + -- MGT Signals For Simulation, + -- Drive mgtCombusIn to 0's, Leave mgtCombusOut open for real use + mgtCombusIn : in std_logic_vector(15 downto 0); + mgtCombusOut : out std_logic_vector(15 downto 0) + ); + +end PgpMgtWrap; + + +-- Define architecture +architecture PgpMgtWrap of PgpMgtWrap is + + -- PGP Core + component PgpTop + generic ( + AckTimeout : natural := 8; -- Ack/Nack Not Received Timeout, 8.192uS Steps + PicMode : natural := 0 -- PIC Interface Mode, 1=PIC, 0=Normal + ); + port ( + pgpClk : in std_logic; + pgpReset : in std_logic; + pibReLink : in std_logic; + vc0FrameTxValid : in std_logic; + vc0FrameTxReady : out std_logic; + vc0FrameTxSOF : in std_logic; + vc0FrameTxWidth : in std_logic; + vc0FrameTxEOF : in std_logic; + vc0FrameTxEOFE : in std_logic; + vc0FrameTxData : in std_logic_vector(15 downto 0); + vc0FrameTxCid : in std_logic_vector(31 downto 0); + vc0FrameTxAckCid : out std_logic_vector(31 downto 0); + vc0FrameTxAckEn : out std_logic; + vc0FrameTxAck : out std_logic; + vc0RemBuffAFull : out std_logic; + vc0RemBuffFull : out std_logic; + vc1FrameTxValid : in std_logic; + vc1FrameTxReady : out std_logic; + vc1FrameTxSOF : in std_logic; + vc1FrameTxWidth : in std_logic; + vc1FrameTxEOF : in std_logic; + vc1FrameTxEOFE : in std_logic; + vc1FrameTxData : in std_logic_vector(15 downto 0); + vc1FrameTxCid : in std_logic_vector(31 downto 0); + vc1FrameTxAckCid : out std_logic_vector(31 downto 0); + vc1FrameTxAckEn : out std_logic; + vc1FrameTxAck : out std_logic; + vc1RemBuffAFull : out std_logic; + vc1RemBuffFull : out std_logic; + vc2FrameTxValid : in std_logic; + vc2FrameTxReady : out std_logic; + vc2FrameTxSOF : in std_logic; + vc2FrameTxWidth : in std_logic; + vc2FrameTxEOF : in std_logic; + vc2FrameTxEOFE : in std_logic; + vc2FrameTxData : in std_logic_vector(15 downto 0); + vc2FrameTxCid : in std_logic_vector(31 downto 0); + vc2FrameTxAckCid : out std_logic_vector(31 downto 0); + vc2FrameTxAckEn : out std_logic; + vc2FrameTxAck : out std_logic; + vc2RemBuffAFull : out std_logic; + vc2RemBuffFull : out std_logic; + vc3FrameTxValid : in std_logic; + vc3FrameTxReady : out std_logic; + vc3FrameTxSOF : in std_logic; + vc3FrameTxWidth : in std_logic; + vc3FrameTxEOF : in std_logic; + vc3FrameTxEOFE : in std_logic; + vc3FrameTxData : in std_logic_vector(15 downto 0); + vc3FrameTxCid : in std_logic_vector(31 downto 0); + vc3FrameTxAckCid : out std_logic_vector(31 downto 0); + vc3FrameTxAckEn : out std_logic; + vc3FrameTxAck : out std_logic; + vc3RemBuffAFull : out std_logic; + vc3RemBuffFull : out std_logic; + vc0FrameRxValid : out std_logic; + vc0FrameRxSOF : out std_logic; + vc0FrameRxWidth : out std_logic; + vc0FrameRxEOF : out std_logic; + vc0FrameRxEOFE : out std_logic; + vc0FrameRxData : out std_logic_vector(15 downto 0); + vc0LocBuffAFull : in std_logic; + vc0LocBuffFull : in std_logic; + vc1FrameRxValid : out std_logic; + vc1FrameRxSOF : out std_logic; + vc1FrameRxWidth : out std_logic; + vc1FrameRxEOF : out std_logic; + vc1FrameRxEOFE : out std_logic; + vc1FrameRxData : out std_logic_vector(15 downto 0); + vc1LocBuffAFull : in std_logic; + vc1LocBuffFull : in std_logic; + vc2FrameRxValid : out std_logic; + vc2FrameRxSOF : out std_logic; + vc2FrameRxWidth : out std_logic; + vc2FrameRxEOF : out std_logic; + vc2FrameRxEOFE : out std_logic; + vc2FrameRxData : out std_logic_vector(15 downto 0); + vc2LocBuffAFull : in std_logic; + vc2LocBuffFull : in std_logic; + vc3FrameRxValid : out std_logic; + vc3FrameRxSOF : out std_logic; + vc3FrameRxWidth : out std_logic; + vc3FrameRxEOF : out std_logic; + vc3FrameRxEOFE : out std_logic; + vc3FrameRxData : out std_logic_vector(15 downto 0); + vc3LocBuffAFull : in std_logic; + vc3LocBuffFull : in std_logic; + crcTxIn : out std_logic_vector(15 downto 0); + crcTxInit : out std_logic; + crcTxValid : out std_logic; + crcTxWidth : out std_logic; + crcTxOut : in std_logic_vector(31 downto 0); + crcRxIn : out std_logic_vector(15 downto 0); + crcRxInit : out std_logic; + crcRxValid : out std_logic; + crcRxWidth : out std_logic; + crcRxOut : in std_logic_vector(31 downto 0); + phyRxPolarity : out std_logic; + phyRxData : in std_logic_vector(15 downto 0); + phyRxDataK : in std_logic_vector(1 downto 0); + phyTxData : out std_logic_vector(15 downto 0); + phyTxDataK : out std_logic_vector(1 downto 0); + phyLinkError : in std_logic; + phyInitDone : in std_logic; + localVersion : out std_logic_vector(7 downto 0); + remoteVersion : out std_logic_vector(7 downto 0); + pibFail : out std_logic; + pibState : out std_logic_vector(2 downto 0); + pibLinkReady : out std_logic; + pgpSeqError : out std_logic; + countLinkError : out std_logic; + countLinkDown : out std_logic; + countNack : out std_logic; + countCellError : out std_logic + ); + end component; + + + -- MGT Block + component + GT11 generic ( + ALIGN_COMMA_WORD : integer := 1; + BANDGAPSEL : boolean := FALSE; + BIASRESSEL : boolean := TRUE; + CCCB_ARBITRATOR_DISABLE : boolean := FALSE; + CHAN_BOND_LIMIT : integer := 16; + CHAN_BOND_MODE : string := "NONE"; + CHAN_BOND_ONE_SHOT : boolean := FALSE; + CHAN_BOND_SEQ_1_1 : bit_vector := "00000000000"; + CHAN_BOND_SEQ_1_2 : bit_vector := "00000000000"; + CHAN_BOND_SEQ_1_3 : bit_vector := "00000000000"; + CHAN_BOND_SEQ_1_4 : bit_vector := "00000000000"; + CHAN_BOND_SEQ_1_MASK : bit_vector := "0000"; + CHAN_BOND_SEQ_2_1 : bit_vector := "00000000000"; + CHAN_BOND_SEQ_2_2 : bit_vector := "00000000000"; + CHAN_BOND_SEQ_2_3 : bit_vector := "00000000000"; + CHAN_BOND_SEQ_2_4 : bit_vector := "00000000000"; + CHAN_BOND_SEQ_2_MASK : bit_vector := "0000"; + CHAN_BOND_SEQ_2_USE : boolean := FALSE; + CHAN_BOND_SEQ_LEN : integer := 1; + CLK_COR_8B10B_DE : boolean := FALSE; + CLK_COR_MAX_LAT : integer := 48; + CLK_COR_MIN_LAT : integer := 36; + CLK_COR_SEQ_1_1 : bit_vector := "00000000000"; + CLK_COR_SEQ_1_2 : bit_vector := "00000000000"; + CLK_COR_SEQ_1_3 : bit_vector := "00000000000"; + CLK_COR_SEQ_1_4 : bit_vector := "00000000000"; + CLK_COR_SEQ_1_MASK : bit_vector := "0000"; + CLK_COR_SEQ_2_1 : bit_vector := "00000000000"; + CLK_COR_SEQ_2_2 : bit_vector := "00000000000"; + CLK_COR_SEQ_2_3 : bit_vector := "00000000000"; + CLK_COR_SEQ_2_4 : bit_vector := "00000000000"; + CLK_COR_SEQ_2_MASK : bit_vector := "0000"; + CLK_COR_SEQ_2_USE : boolean := FALSE; + CLK_COR_SEQ_DROP : boolean := FALSE; + CLK_COR_SEQ_LEN : integer := 1; + CLK_CORRECT_USE : boolean := TRUE; + COMMA_10B_MASK : bit_vector := x"3FF"; + COMMA32 : boolean := FALSE; + CYCLE_LIMIT_SEL : bit_vector := "00"; + DCDR_FILTER : bit_vector := "010"; + DEC_MCOMMA_DETECT : boolean := TRUE; + DEC_PCOMMA_DETECT : boolean := TRUE; + DEC_VALID_COMMA_ONLY : boolean := TRUE; + DIGRX_FWDCLK : bit_vector := "00"; + DIGRX_SYNC_MODE : boolean := FALSE; + ENABLE_DCDR : boolean := FALSE; + FDET_HYS_CAL : bit_vector := "110"; + FDET_HYS_SEL : bit_vector := "110"; + FDET_LCK_CAL : bit_vector := "101"; + FDET_LCK_SEL : bit_vector := "101"; + GT11_MODE : string := "DONT_CARE"; + IREFBIASMODE : bit_vector := "11"; + LOOPCAL_WAIT : bit_vector := "00"; + MCOMMA_32B_VALUE : bit_vector := x"000000F6"; + MCOMMA_DETECT : boolean := TRUE; + OPPOSITE_SELECT : boolean := FALSE; + PCOMMA_32B_VALUE : bit_vector := x"F6F62828"; + PCOMMA_DETECT : boolean := TRUE; + PCS_BIT_SLIP : boolean := FALSE; + PMA_BIT_SLIP : boolean := FALSE; + PMACLKENABLE : boolean := TRUE; + PMACOREPWRENABLE : boolean := TRUE; + PMAIREFTRIM : bit_vector := "0111"; + PMAVBGCTRL : bit_vector := "00000"; + PMAVREFTRIM : bit_vector := "0111"; + POWER_ENABLE : boolean := TRUE; + REPEATER : boolean := FALSE; + RX_BUFFER_USE : boolean := TRUE; + RX_CLOCK_DIVIDER : bit_vector := "00"; + RXACTST : boolean := FALSE; + RXAFEEQ : bit_vector := "000000000"; + RXAFEPD : boolean := FALSE; + RXAFETST : boolean := FALSE; + RXAPD : boolean := FALSE; + RXASYNCDIVIDE : bit_vector := "11"; + RXBY_32 : boolean := TRUE; + RXCDRLOS : bit_vector := "000000"; + RXCLK0_FORCE_PMACLK : boolean := FALSE; + RXCLKMODE : bit_vector := "000010"; + RXCMADJ : bit_vector := "10"; + RXCPSEL : boolean := TRUE; + RXCPTST : boolean := FALSE; + RXCRCCLOCKDOUBLE : boolean := FALSE; + RXCRCENABLE : boolean := FALSE; + RXCRCINITVAL : bit_vector := x"00000000"; + RXCRCINVERTGEN : boolean := FALSE; + RXCRCSAMECLOCK : boolean := FALSE; + RXCTRL1 : bit_vector := x"200"; + RXCYCLE_LIMIT_SEL : bit_vector := "00"; + RXDATA_SEL : bit_vector := "00"; + RXDCCOUPLE : boolean := FALSE; + RXDIGRESET : boolean := FALSE; + RXDIGRX : boolean := FALSE; + RXEQ : bit_vector := x"4000000000000000"; + RXFDCAL_CLOCK_DIVIDE : string := "NONE"; + RXFDET_HYS_CAL : bit_vector := "110"; + RXFDET_HYS_SEL : bit_vector := "110"; + RXFDET_LCK_CAL : bit_vector := "101"; + RXFDET_LCK_SEL : bit_vector := "101"; + RXFECONTROL1 : bit_vector := "00"; + RXFECONTROL2 : bit_vector := "000"; + RXFETUNE : bit_vector := "01"; + RXLB : boolean := FALSE; + RXLKADJ : bit_vector := "00000"; + RXLKAPD : boolean := FALSE; + RXLOOPCAL_WAIT : bit_vector := "00"; + RXLOOPFILT : bit_vector := "0111"; + RXOUTDIV2SEL : integer := 1; + RXPD : boolean := FALSE; + RXPDDTST : boolean := FALSE; + RXPLLNDIVSEL : integer := 8; + RXPMACLKSEL : string := "REFCLK1"; + RXRCPADJ : bit_vector := "011"; + RXRCPPD : boolean := FALSE; + RXRECCLK1_USE_SYNC : boolean := FALSE; + RXRIBADJ : bit_vector := "11"; + RXRPDPD : boolean := FALSE; + RXRSDPD : boolean := FALSE; + RXSLOWDOWN_CAL : bit_vector := "00"; + RXUSRDIVISOR : integer := 1; + RXVCO_CTRL_ENABLE : boolean := TRUE; + RXVCODAC_INIT : bit_vector := "1010000000"; + SAMPLE_8X : boolean := FALSE; + SH_CNT_MAX : integer := 64; + SH_INVALID_CNT_MAX : integer := 16; + SLOWDOWN_CAL : bit_vector := "00"; + TX_BUFFER_USE : boolean := TRUE; + TX_CLOCK_DIVIDER : bit_vector := "00"; + TXABPMACLKSEL : string := "REFCLK1"; + TXAPD : boolean := FALSE; + TXAREFBIASSEL : boolean := FALSE; + TXASYNCDIVIDE : bit_vector := "11"; + TXCLK0_FORCE_PMACLK : boolean := FALSE; + TXCLKMODE : bit_vector := "1001"; + TXCPSEL : boolean := TRUE; + TXCRCCLOCKDOUBLE : boolean := FALSE; + TXCRCENABLE : boolean := FALSE; + TXCRCINITVAL : bit_vector := x"00000000"; + TXCRCINVERTGEN : boolean := FALSE; + TXCRCSAMECLOCK : boolean := FALSE; + TXCTRL1 : bit_vector := x"200"; + TXDAT_PRDRV_DAC : bit_vector := "111"; + TXDAT_TAP_DAC : bit_vector := "10110"; + TXDATA_SEL : bit_vector := "00"; + TXDIGPD : boolean := FALSE; + TXFDCAL_CLOCK_DIVIDE : string := "NONE"; + TXHIGHSIGNALEN : boolean := TRUE; + TXLOOPFILT : bit_vector := "0111"; + TXLVLSHFTPD : boolean := FALSE; + TXOUTCLK1_USE_SYNC : boolean := FALSE; + TXOUTDIV2SEL : integer := 1; + TXPD : boolean := FALSE; + TXPHASESEL : boolean := FALSE; + TXPLLNDIVSEL : integer := 8; + TXPOST_PRDRV_DAC : bit_vector := "111"; + TXPOST_TAP_DAC : bit_vector := "01110"; + TXPOST_TAP_PD : boolean := TRUE; + TXPRE_PRDRV_DAC : bit_vector := "111"; + TXPRE_TAP_DAC : bit_vector := "00000"; + TXPRE_TAP_PD : boolean := TRUE; + TXSLEWRATE : boolean := FALSE; + TXTERMTRIM : bit_vector := "1100"; + VCO_CTRL_ENABLE : boolean := TRUE; + VCODAC_INIT : bit_vector := "1010000000"; + VREFBIASMODE : bit_vector := "11" + ); + port ( + CHBONDI : in std_logic_vector (4 downto 0); + ENCHANSYNC : in std_logic; + ENMCOMMAALIGN : in std_logic; + ENPCOMMAALIGN : in std_logic; + LOOPBACK : in std_logic_vector (1 downto 0); + POWERDOWN : in std_logic; + RXBLOCKSYNC64B66BUSE : in std_logic; + RXCOMMADETUSE : in std_logic; + RXDATAWIDTH : in std_logic_vector (1 downto 0); + RXDEC64B66BUSE : in std_logic; + RXDEC8B10BUSE : in std_logic; + RXDESCRAM64B66BUSE : in std_logic; + RXIGNOREBTF : in std_logic; + RXINTDATAWIDTH : in std_logic_vector (1 downto 0); + RXPOLARITY : in std_logic; + RXRESET : in std_logic; + RXSLIDE : in std_logic; + RXUSRCLK : in std_logic; + RXUSRCLK2 : in std_logic; + TXBYPASS8B10B : in std_logic_vector (7 downto 0); + TXCHARDISPMODE : in std_logic_vector (7 downto 0); + TXCHARDISPVAL : in std_logic_vector (7 downto 0); + TXCHARISK : in std_logic_vector (7 downto 0); + TXDATA : in std_logic_vector (63 downto 0); + TXDATAWIDTH : in std_logic_vector (1 downto 0); + TXENC64B66BUSE : in std_logic; + TXENC8B10BUSE : in std_logic; + TXGEARBOX64B66BUSE : in std_logic; + TXINHIBIT : in std_logic; + TXINTDATAWIDTH : in std_logic_vector (1 downto 0); + TXPOLARITY : in std_logic; + TXRESET : in std_logic; + TXSCRAM64B66BUSE : in std_logic; + TXUSRCLK : in std_logic; + TXUSRCLK2 : in std_logic; + RXCLKSTABLE : in std_logic; + RXPMARESET : in std_logic; + TXCLKSTABLE : in std_logic; + TXPMARESET : in std_logic; + RXCRCIN : in std_logic_vector (63 downto 0); + RXCRCDATAWIDTH : in std_logic_vector (2 downto 0); + RXCRCDATAVALID : in std_logic; + RXCRCINIT : in std_logic; + RXCRCRESET : in std_logic; + RXCRCPD : in std_logic; + RXCRCCLK : in std_logic; + RXCRCINTCLK : in std_logic; + TXCRCIN : in std_logic_vector (63 downto 0); + TXCRCDATAWIDTH : in std_logic_vector (2 downto 0); + TXCRCDATAVALID : in std_logic; + TXCRCINIT : in std_logic; + TXCRCRESET : in std_logic; + TXCRCPD : in std_logic; + TXCRCCLK : in std_logic; + TXCRCINTCLK : in std_logic; + TXSYNC : in std_logic; + RXSYNC : in std_logic; + TXENOOB : in std_logic; + DCLK : in std_logic; + DADDR : in std_logic_vector (7 downto 0); + DEN : in std_logic; + DWE : in std_logic; + DI : in std_logic_vector (15 downto 0); + RX1P : in std_logic; + RX1N : in std_logic; + GREFCLK : in std_logic; + REFCLK1 : in std_logic; + REFCLK2 : in std_logic; + CHBONDO : out std_logic_vector (4 downto 0); + RXSTATUS : out std_logic_vector (5 downto 0); + RXCHARISCOMMA : out std_logic_vector (7 downto 0); + RXCHARISK : out std_logic_vector (7 downto 0); + RXCOMMADET : out std_logic; + RXDATA : out std_logic_vector (63 downto 0); + RXDISPERR : out std_logic_vector (7 downto 0); + RXLOSSOFSYNC : out std_logic_vector (1 downto 0); + RXNOTINTABLE : out std_logic_vector (7 downto 0); + RXREALIGN : out std_logic; + RXRUNDISP : out std_logic_vector (7 downto 0); + RXBUFERR : out std_logic; + TXBUFERR : out std_logic; + TXKERR : out std_logic_vector (7 downto 0); + TXRUNDISP : out std_logic_vector (7 downto 0); + RXRECCLK1 : out std_logic; + RXRECCLK2 : out std_logic; + TXOUTCLK1 : out std_logic; + TXOUTCLK2 : out std_logic; + RXLOCK : out std_logic; + TXLOCK : out std_logic; + RXCYCLELIMIT : out std_logic; + TXCYCLELIMIT : out std_logic; + RXCALFAIL : out std_logic; + TXCALFAIL : out std_logic; + RXCRCOUT : out std_logic_vector (31 downto 0); + TXCRCOUT : out std_logic_vector (31 downto 0); + RXSIGDET : out std_logic; + DRDY : out std_logic; + DO : out std_logic_vector (15 downto 0); + RXMCLK : out std_logic; + TX1P : out std_logic; + TX1N : out std_logic; + TXPCSHCLKOUT : out std_logic; + RXPCSHCLKOUT : out std_logic; + COMBUSIN : in std_logic_vector (15 downto 0); + COMBUSOUT : out std_logic_vector (15 downto 0) + ); + end component; + + + -- Local Signals + signal crcTxIn : std_logic_vector(15 downto 0); + signal crcTxInMgt : std_logic_vector(63 downto 0); + signal crcTxInit : std_logic; + signal crcTxValid : std_logic; + signal crcTxWidth : std_logic; + signal crcTxWidthMgt : std_logic_vector(2 downto 0); + signal crcTxOut : std_logic_vector(31 downto 0); + signal crcRxIn : std_logic_vector(15 downto 0); + signal crcRxInMgt : std_logic_vector(63 downto 0); + signal crcRxInit : std_logic; + signal crcRxValid : std_logic; + signal crcRxWidth : std_logic; + signal crcRxWidthMgt : std_logic_vector(2 downto 0); + signal crcRxOut : std_logic_vector(31 downto 0); + signal phyRxPolarity : std_logic; + signal phyRxData : std_logic_vector(15 downto 0); + signal phyRxDataK : std_logic_vector(1 downto 0); + signal phyTxData : std_logic_vector(15 downto 0); + signal phyTxDataK : std_logic_vector(1 downto 0); + signal mgtRxPmaReset : std_logic; + signal mgtTxPmaReset : std_logic; + signal mgtRxReset : std_logic; + signal mgtTxReset : std_logic; + signal mgtRxBuffError : std_logic; + signal mgtTxBuffError : std_logic; + signal mgtRxDispErr : std_logic_vector(1 downto 0); + signal mgtRxDecErr : std_logic_vector(1 downto 0); + signal mgtRxLock : std_logic; + signal mgtTxLock : std_logic; + signal crcRxReset : std_logic; + signal crcTxReset : std_logic; + signal txPcsResetCnt : std_logic_vector(3 downto 0); + signal txPcsResetCntRst : std_logic; + signal txPcsResetCntEn : std_logic; + signal txStateCnt : std_logic_vector(5 downto 0); + signal txStateCntRst : std_logic; + signal rxPcsResetCnt : std_logic_vector(3 downto 0); + signal rxPcsResetCntRst : std_logic; + signal rxPcsResetCntEn : std_logic; + signal rxStateCnt : std_logic_vector(13 downto 0); + signal rxStateCntRst : std_logic; + signal intRxPmaReset : std_logic; + signal intTxPmaReset : std_logic; + signal intRxReset : std_logic; + signal intTxReset : std_logic; + signal txClockReady : std_logic; + signal rxClockReady : std_logic; + signal intLinkReady : std_logic; + signal phyLinkError : std_logic; + signal phyInitDone : std_logic; + + -- RX Reset State Machine + constant RX_SYSTEM_RESET : std_logic_vector(2 downto 0) := "000"; + constant RX_PMA_RESET : std_logic_vector(2 downto 0) := "001"; + constant RX_WAIT_LOCK : std_logic_vector(2 downto 0) := "010"; + constant RX_PCS_RESET : std_logic_vector(2 downto 0) := "011"; + constant RX_WAIT_PCS : std_logic_vector(2 downto 0) := "100"; + constant RX_ALMOST_READY : std_logic_vector(2 downto 0) := "101"; + constant RX_READY : std_logic_vector(2 downto 0) := "110"; + signal curRxState : std_logic_vector(2 downto 0); + signal nxtRxState : std_logic_vector(2 downto 0); + + -- TX Reset State Machine + constant TX_SYSTEM_RESET : std_logic_vector(2 downto 0) := "000"; + constant TX_PMA_RESET : std_logic_vector(2 downto 0) := "001"; + constant TX_WAIT_LOCK : std_logic_vector(2 downto 0) := "010"; + constant TX_PCS_RESET : std_logic_vector(2 downto 0) := "011"; + constant TX_WAIT_PCS : std_logic_vector(2 downto 0) := "100"; + constant TX_ALMOST_READY : std_logic_vector(2 downto 0) := "101"; + constant TX_READY : std_logic_vector(2 downto 0) := "110"; + signal curTxState : std_logic_vector(2 downto 0); + signal nxtTxState : std_logic_vector(2 downto 0); + + -- Black Box Attributes + attribute syn_black_box : boolean; + attribute syn_noprune : boolean; + attribute syn_black_box of GT11 : component is TRUE; + attribute syn_noprune of GT11 : component is TRUE; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Pgp + U_PgpTop: PgpTop + generic map (AckTimeout => AckTimeout, + PicMode => PicMode ) port map ( + pgpClk => pgpClk, + pgpReset => pgpReset, + pibReLink => pibReLink, + vc0FrameTxValid => vc0FrameTxValid, vc0FrameTxReady => vc0FrameTxReady, + vc0FrameTxSOF => vc0FrameTxSOF, vc0FrameTxWidth => vc0FrameTxWidth, + vc0FrameTxEOF => vc0FrameTxEOF, vc0FrameTxEOFE => vc0FrameTxEOFE, + vc0FrameTxData => vc0FrameTxData, vc0FrameTxCid => vc0FrameTxCid, + vc0FrameTxAckCid => vc0FrameTxAckCid, vc0FrameTxAckEn => vc0FrameTxAckEn, + vc0FrameTxAck => vc0FrameTxAck, vc0RemBuffAFull => vc0RemBuffAFull, + vc0RemBuffFull => vc0RemBuffFull, vc1FrameTxValid => vc1FrameTxValid, + vc1FrameTxReady => vc1FrameTxReady, vc1FrameTxSOF => vc1FrameTxSOF, + vc1FrameTxWidth => vc1FrameTxWidth, vc1FrameTxEOF => vc1FrameTxEOF, + vc1FrameTxEOFE => vc1FrameTxEOFE, vc1FrameTxData => vc1FrameTxData, + vc1FrameTxCid => vc1FrameTxCid, vc1FrameTxAckCid => vc1FrameTxAckCid, + vc1FrameTxAckEn => vc1FrameTxAckEn, vc1FrameTxAck => vc1FrameTxAck, + vc1RemBuffAFull => vc1RemBuffAFull, vc1RemBuffFull => vc1RemBuffFull, + vc2FrameTxValid => vc2FrameTxValid, vc2FrameTxReady => vc2FrameTxReady, + vc2FrameTxSOF => vc2FrameTxSOF, vc2FrameTxWidth => vc2FrameTxWidth, + vc2FrameTxEOF => vc2FrameTxEOF, vc2FrameTxEOFE => vc2FrameTxEOFE, + vc2FrameTxData => vc2FrameTxData, vc2FrameTxCid => vc2FrameTxCid, + vc2FrameTxAckCid => vc2FrameTxAckCid, vc2FrameTxAckEn => vc2FrameTxAckEn, + vc2FrameTxAck => vc2FrameTxAck, vc2RemBuffAFull => vc2RemBuffAFull, + vc2RemBuffFull => vc2RemBuffFull, vc3FrameTxValid => vc3FrameTxValid, + vc3FrameTxReady => vc3FrameTxReady, vc3FrameTxSOF => vc3FrameTxSOF, + vc3FrameTxWidth => vc3FrameTxWidth, vc3FrameTxEOF => vc3FrameTxEOF, + vc3FrameTxEOFE => vc3FrameTxEOFE, vc3FrameTxData => vc3FrameTxData, + vc3FrameTxCid => vc3FrameTxCid, vc3FrameTxAckCid => vc3FrameTxAckCid, + vc3FrameTxAckEn => vc3FrameTxAckEn, vc3FrameTxAck => vc3FrameTxAck, + vc3RemBuffAFull => vc3RemBuffAFull, vc3RemBuffFull => vc3RemBuffFull, + vc0FrameRxValid => vc0FrameRxValid, vc0FrameRxSOF => vc0FrameRxSOF, + vc0FrameRxWidth => vc0FrameRxWidth, vc0FrameRxEOF => vc0FrameRxEOF, + vc0FrameRxEOFE => vc0FrameRxEOFE, vc0FrameRxData => vc0FrameRxData, + vc0LocBuffAFull => vc0LocBuffAFull, vc0LocBuffFull => vc0LocBuffFull, + vc1FrameRxValid => vc1FrameRxValid, vc1FrameRxSOF => vc1FrameRxSOF, + vc1FrameRxWidth => vc1FrameRxWidth, vc1FrameRxEOF => vc1FrameRxEOF, + vc1FrameRxEOFE => vc1FrameRxEOFE, vc1FrameRxData => vc1FrameRxData, + vc1LocBuffAFull => vc1LocBuffAFull, vc1LocBuffFull => vc1LocBuffFull, + vc2FrameRxValid => vc2FrameRxValid, vc2FrameRxSOF => vc2FrameRxSOF, + vc2FrameRxWidth => vc2FrameRxWidth, vc2FrameRxEOF => vc2FrameRxEOF, + vc2FrameRxEOFE => vc2FrameRxEOFE, vc2FrameRxData => vc2FrameRxData, + vc2LocBuffAFull => vc2LocBuffAFull, vc2LocBuffFull => vc2LocBuffFull, + vc3FrameRxValid => vc3FrameRxValid, vc3FrameRxSOF => vc3FrameRxSOF, + vc3FrameRxWidth => vc3FrameRxWidth, vc3FrameRxEOF => vc3FrameRxEOF, + vc3FrameRxEOFE => vc3FrameRxEOFE, vc3FrameRxData => vc3FrameRxData, + vc3LocBuffAFull => vc3LocBuffAFull, vc3LocBuffFull => vc3LocBuffFull, + crcTxIn => crcTxIn, crcTxInit => crcTxInit, + crcTxValid => crcTxValid, crcTxWidth => crcTxWidth, + crcTxOut => crcTxOut, crcRxIn => crcRxIn, + crcRxInit => crcRxInit, crcRxValid => crcRxValid, + crcRxWidth => crcRxWidth, crcRxOut => crcRxOut, + phyRxPolarity => phyRxPolarity, phyRxData => phyRxData, + phyRxDataK => phyRxDataK, phyTxData => phyTxData, + phyTxDataK => phyTxDataK, phyLinkError => phyLinkError, + phyInitDone => phyInitDone, localVersion => localVersion, + remoteVersion => remoteVersion, pibFail => pibFail, + pibState => pibState, pibLinkReady => intLinkReady, + pgpSeqError => pgpSeqError, countLinkDown => countLinkDown, + countLinkError => countLinkError, countNack => countNack, + countCellError => countCellError + ); + + + -- Lock & Polarity Signals + mgtInverted <= phyRxPolarity; + pibLinkReady <= intLinkReady; + + -- Adapt CRC data width flag + crcTxWidthMgt(2 downto 1) <= "00"; + crcTxWidthMgt(0) <= crcTxWidth; + crcRxWidthMgt(2 downto 1) <= "00"; + crcRxWidthMgt(0) <= crcRxWidth; + crcRxReset <= mgtRxReset; + crcTxReset <= mgtTxReset; + + -- Pass CRC data in on proper bits + crcTxInMgt(63 downto 56) <= crcTxIn(7 downto 0); + crcTxInMgt(55 downto 48) <= crcTxIn(15 downto 8); + crcTxInMgt(47 downto 0) <= (others=>'0'); + crcRxInMgt(63 downto 56) <= crcRxIn(7 downto 0); + crcRxInMgt(55 downto 48) <= crcRxIn(15 downto 8); + crcRxInMgt(47 downto 0) <= (others=>'0'); + + + --------------------------- GT11 Instantiations --------------------------- + U_MGT : GT11 + generic map + ( + + ---------- RocketIO MGT 64B66B Block Sync State Machine Attributes --------- + + SH_CNT_MAX => 64, + SH_INVALID_CNT_MAX => 16, + + ----------------------- RocketIO MGT Alignment Atrributes ------------------ + + ALIGN_COMMA_WORD => 2, + COMMA_10B_MASK => x"3ff", + COMMA32 => FALSE, + DEC_MCOMMA_DETECT => FALSE, + DEC_PCOMMA_DETECT => FALSE, + DEC_VALID_COMMA_ONLY => FALSE, + MCOMMA_32B_VALUE => x"00000283", + MCOMMA_DETECT => TRUE, + PCOMMA_32B_VALUE => x"0000017c", + PCOMMA_DETECT => TRUE, + PCS_BIT_SLIP => FALSE, + + ---- RocketIO MGT Atrributes Common to Clk Correction & Channel Bonding ---- + + CCCB_ARBITRATOR_DISABLE => FALSE, + CLK_COR_8B10B_DE => TRUE, + + ------------------- RocketIO MGT Channel Bonding Atrributes ---------------- + + CHAN_BOND_LIMIT => 16, + CHAN_BOND_MODE => "NONE", + CHAN_BOND_ONE_SHOT => FALSE, + CHAN_BOND_SEQ_1_1 => "00000000000", + CHAN_BOND_SEQ_1_2 => "00000000000", + CHAN_BOND_SEQ_1_3 => "00000000000", + CHAN_BOND_SEQ_1_4 => "00000000000", + CHAN_BOND_SEQ_1_MASK => "1110", + CHAN_BOND_SEQ_2_1 => "00000000000", + CHAN_BOND_SEQ_2_2 => "00000000000", + CHAN_BOND_SEQ_2_3 => "00000000000", + CHAN_BOND_SEQ_2_4 => "00000000000", + CHAN_BOND_SEQ_2_MASK => "1111", + CHAN_BOND_SEQ_2_USE => FALSE, + CHAN_BOND_SEQ_LEN => 1, + + ------------------ RocketIO MGT Clock Correction Atrributes ---------------- + + CLK_COR_MAX_LAT => 48, + CLK_COR_MIN_LAT => 36, + CLK_COR_SEQ_1_1 => "00110111100", + CLK_COR_SEQ_1_2 => "00100011100", + CLK_COR_SEQ_1_3 => "00100011100", + CLK_COR_SEQ_1_4 => "00100011100", + CLK_COR_SEQ_1_MASK => "0000", + CLK_COR_SEQ_2_1 => "00000000000", + CLK_COR_SEQ_2_2 => "00000000000", + CLK_COR_SEQ_2_3 => "00000000000", + CLK_COR_SEQ_2_4 => "00000000000", + CLK_COR_SEQ_2_MASK => "1111", + CLK_COR_SEQ_2_USE => FALSE, + CLK_COR_SEQ_DROP => FALSE, + CLK_COR_SEQ_LEN => 4, + CLK_CORRECT_USE => TRUE, + + ---------------------- RocketIO MGT Clocking Atrributes -------------------- + + RX_CLOCK_DIVIDER => "01", + RXASYNCDIVIDE => "01", + RXCLK0_FORCE_PMACLK => TRUE, + RXCLKMODE => "000011", + RXOUTDIV2SEL => 2, + RXPLLNDIVSEL => 20, -- 8=1.25, 16=2.5, 20=3.125 + RXPMACLKSEL => RefClkSel, + RXRECCLK1_USE_SYNC => FALSE, + RXUSRDIVISOR => 1, + TX_CLOCK_DIVIDER => "01", + TXABPMACLKSEL => RefClkSel, + TXASYNCDIVIDE => "01", + TXCLK0_FORCE_PMACLK => TRUE, + TXCLKMODE => "0100", + TXOUTCLK1_USE_SYNC => FALSE, + TXOUTDIV2SEL => 2, + TXPHASESEL => FALSE, + TXPLLNDIVSEL => 20, -- 8=1.25, 16=2.5, 20=3.125 + + -------------------------- RocketIO MGT CRC Atrributes --------------------- + + RXCRCCLOCKDOUBLE => FALSE, + RXCRCENABLE => TRUE, + RXCRCINITVAL => x"FFFFFFFF", + RXCRCINVERTGEN => TRUE, + RXCRCSAMECLOCK => TRUE, + TXCRCCLOCKDOUBLE => FALSE, + TXCRCENABLE => TRUE, + TXCRCINITVAL => x"FFFFFFFF", + TXCRCINVERTGEN => TRUE, + TXCRCSAMECLOCK => TRUE, + + --------------------- RocketIO MGT Data Path Atrributes -------------------- + + RXDATA_SEL => "00", + TXDATA_SEL => "00", + + ---------------- RocketIO MGT Digital Receiver Attributes ------------------ + + DIGRX_FWDCLK => "01", + DIGRX_SYNC_MODE => FALSE, + ENABLE_DCDR => FALSE, + RXBY_32 => FALSE, + RXDIGRESET => FALSE, + RXDIGRX => FALSE, + SAMPLE_8X => FALSE, + + ----------------- Rocket IO MGT Miscellaneous Attributes ------------------ + + GT11_MODE => MgtMode, + OPPOSITE_SELECT => FALSE, + PMA_BIT_SLIP => FALSE, + REPEATER => FALSE, + RX_BUFFER_USE => TRUE, + RXCDRLOS => "000000", + RXDCCOUPLE => TRUE, + RXFDCAL_CLOCK_DIVIDE => "NONE", + TX_BUFFER_USE => TRUE, + TXFDCAL_CLOCK_DIVIDE => "NONE", + TXSLEWRATE => FALSE, + + ----------------- Rocket IO MGT Preemphasis and Equalization -------------- + + RXAFEEQ => "000000000", + RXEQ => x"4000FF0303030101", + TXDAT_PRDRV_DAC => "111", + TXDAT_TAP_DAC => "11011", -- = TXPOST_TAP_DAC * 4 + TXHIGHSIGNALEN => TRUE, + TXPOST_PRDRV_DAC => "111", + TXPOST_TAP_DAC => "00010", + TXPOST_TAP_PD => FALSE, + TXPRE_PRDRV_DAC => "111", + TXPRE_TAP_DAC => "00001", -- = TXPOST_TAP_DAC / 2 + TXPRE_TAP_PD => TRUE, + + ----------------------- Restricted RocketIO MGT Attributes ------------------- + + ---Note : THE FOLLOWING ATTRIBUTES ARE RESTRICTED. PLEASE DO NOT EDIT. + + ----------------------------- Restricted: Biasing ------------------------- + + BANDGAPSEL => FALSE, + BIASRESSEL => FALSE, + IREFBIASMODE => "11", + PMAIREFTRIM => "0111", + PMAVREFTRIM => "0111", + TXAREFBIASSEL => TRUE, + TXTERMTRIM => "1100", + VREFBIASMODE => "11", + + ---------------- Restricted: Frequency Detector and Calibration ----------- + + CYCLE_LIMIT_SEL => "00", + FDET_HYS_CAL => "010", + FDET_HYS_SEL => "001", + FDET_LCK_CAL => "101", + FDET_LCK_SEL => "111", + LOOPCAL_WAIT => "00", + RXCYCLE_LIMIT_SEL => "00", + RXFDET_HYS_CAL => "010", + RXFDET_HYS_SEL => "001", + RXFDET_LCK_CAL => "101", + RXFDET_LCK_SEL => "100", + RXLOOPCAL_WAIT => "00", + RXSLOWDOWN_CAL => "00", + SLOWDOWN_CAL => "00", + + --------------------------- Restricted: PLL Settings --------------------- + + PMACLKENABLE => TRUE, + PMACOREPWRENABLE => TRUE, + PMAVBGCTRL => "00000", + RXACTST => TRUE, + RXAFETST => TRUE, + RXCMADJ => "10", + RXCPSEL => TRUE, + RXCPTST => FALSE, + RXCTRL1 => x"200", + RXFECONTROL1 => "10", + RXFECONTROL2 => "111", + RXFETUNE => "00", + RXLKADJ => "00000", + RXLOOPFILT => "1111", + RXPDDTST => FALSE, + RXRCPADJ => "011", + RXRIBADJ => "11", + RXVCO_CTRL_ENABLE => TRUE, + RXVCODAC_INIT => "0000101001", + TXCPSEL => TRUE, + TXCTRL1 => x"200", + TXLOOPFILT => "0101", + VCO_CTRL_ENABLE => TRUE, + VCODAC_INIT => "0000101001", + + --------------------------- Restricted: Powerdowns ------------------------ + + POWER_ENABLE => TRUE, + RXAFEPD => FALSE, + RXAPD => FALSE, + RXLKAPD => FALSE, + RXPD => FALSE, + RXRCPPD => FALSE, + RXRPDPD => FALSE, + RXRSDPD => FALSE, + TXAPD => FALSE, + TXDIGPD => FALSE, + TXLVLSHFTPD => FALSE, + TXPD => FALSE + + ) + port map + ( + ------------------------------- CRC Ports ------------------------------ + + RXCRCCLK => pgpClk, + RXCRCDATAVALID => crcRxValid, + RXCRCDATAWIDTH => crcRxWidthMgt, + RXCRCIN => crcRxInMgt, + RXCRCINIT => crcRxInit, + RXCRCINTCLK => pgpClk, + RXCRCOUT => crcRxOut, + RXCRCPD => '0', + RXCRCRESET => crcRxReset, + + TXCRCCLK => pgpClk, + TXCRCDATAVALID => crcTxValid, + TXCRCDATAWIDTH => crcTxWidthMgt, + TXCRCIN => crcTxInMgt, + TXCRCINIT => crcTxInit, + TXCRCINTCLK => pgpClk, + TXCRCOUT => crcTxOut, + TXCRCPD => '0', + TXCRCRESET => crcTxReset, + + ---------------------------- Calibration Ports ------------------------ + + RXCALFAIL => open, + RXCYCLELIMIT => open, + TXCALFAIL => open, + TXCYCLELIMIT => open, + + ------------------------------ Serial Ports ---------------------------- + + RX1N => mgtRxN, + RX1P => mgtRxP, + TX1N => mgtTxN, + TX1P => mgtTxP, + + ------------------------------- PLL Lock ------------------------------- + + RXLOCK => mgtRxLock, + TXLOCK => mgtTxLock, + + -------------------------------- Resets ------------------------------- + + RXPMARESET => mgtRxPmaReset, + RXRESET => mgtRxReset, + TXPMARESET => mgtTxPmaReset, + TXRESET => mgtTxReset, + + ---------------------------- Synchronization --------------------------- + + RXSYNC => '0', + TXSYNC => '0', + + ---------------------------- Out of Band Signalling ------------------- + + RXSIGDET => open, + TXENOOB => '0', + + -------------------------------- Status -------------------------------- + + RXBUFERR => mgtRxBuffError, + RXCLKSTABLE => '1', + RXSTATUS => open, + TXBUFERR => mgtTxBuffError, + TXCLKSTABLE => '1', + + ---------------------------- Polarity Control Ports -------------------- + + RXPOLARITY => phyRxPolarity, + TXINHIBIT => '0', + TXPOLARITY => '0', + + ------------------------------- Channel Bonding Ports ------------------ + + CHBONDI => (others=>'0'), + CHBONDO => open, + ENCHANSYNC => '0', + + ---------------------------- 64B66B Blocks Use Ports ------------------- + + RXBLOCKSYNC64B66BUSE => '0', + RXDEC64B66BUSE => '0', + RXDESCRAM64B66BUSE => '0', + RXIGNOREBTF => '0', + TXENC64B66BUSE => '0', + TXGEARBOX64B66BUSE => '0', + TXSCRAM64B66BUSE => '0', + + ---------------------------- 8B10B Blocks Use Ports -------------------- + + RXDEC8B10BUSE => '1', + TXBYPASS8B10B(7 downto 2) => "000000", + TXBYPASS8B10B(1 downto 0) => "00", + TXENC8B10BUSE => '1', + + ------------------------------ Transmit Control Ports ------------------ + + TXCHARDISPMODE(7 downto 0) => x"00", + TXCHARDISPVAL(7 downto 0) => x"00", + TXCHARISK(7 downto 2) => "000000", + TXCHARISK(1 downto 0) => phyTxDataK, + TXKERR(7 downto 0) => open, + TXRUNDISP(7 downto 0) => open, + + ------------------------------ Receive Control Ports ------------------- + + RXCHARISCOMMA => open, + RXCHARISK(7 downto 2) => open, + RXCHARISK(1 downto 0) => phyRxDataK, + RXDISPERR(7 downto 2) => open, + RXDISPERR(1 downto 0) => mgtRxDispErr, + RXNOTINTABLE(7 downto 2) => open, + RXNOTINTABLE(1 downto 0) => mgtRxDecErr, + RXRUNDISP(7 downto 0) => open, + + ------------------------------- Serdes Alignment ----------------------- + + ENMCOMMAALIGN => '1', + ENPCOMMAALIGN => '1', + RXCOMMADET => open, + RXCOMMADETUSE => '1', + RXLOSSOFSYNC => open, + RXREALIGN => open, + RXSLIDE => '0', + + ----------- Data Width Settings - Internal and fabric interface -------- + + RXDATAWIDTH => "01", + RXINTDATAWIDTH => "11", + TXDATAWIDTH => "01", + TXINTDATAWIDTH => "11", + + ------------------------------- Data Ports ----------------------------- + + RXDATA(63 downto 16) => open, + RXDATA(15 downto 0) => phyRxData, + TXDATA(63 downto 16) => x"000000000000", + TXDATA(15 downto 0) => phyTxData, + + ------------------------------- User Clocks ----------------------------- + + RXMCLK => open, + RXPCSHCLKOUT => open, + RXRECCLK1 => mgtRxRecClk, + RXRECCLK2 => open, + RXUSRCLK => '0', + RXUSRCLK2 => pgpClk, + TXOUTCLK1 => open, + TXOUTCLK2 => open, + TXPCSHCLKOUT => open, + TXUSRCLK => '0', + TXUSRCLK2 => pgpClk, + + ---------------------------- Reference Clocks -------------------------- + + GREFCLK => '0', + REFCLK1 => mgtRefClk1, + REFCLK2 => mgtRefClk2, + + ---------------------------- Powerdown and Loopback Ports -------------- + + LOOPBACK(1) => mgtLoopback, + LOOPBACK(0) => mgtLoopback, + POWERDOWN => '0', + + ------------------- Dynamic Reconfiguration Port (DRP) ------------------ + + DADDR => mgtDAddr, + DCLK => mgtDClk, + DEN => mgtDEn, + DI => mgtDI, + DO => mgtDO, + DRDY => mgtDRdy, + DWE => mgtDWe, + + --------------------- MGT Tile Communication Ports ------------------ + + COMBUSIN => mgtCombusIn, + COMBUSOUT => mgtCombusOut + ); + + + -- TX & RX State Machine Synchronous Logic + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + curTxState <= TX_SYSTEM_RESET after tpd; + curRxState <= RX_SYSTEM_RESET after tpd; + txPcsResetCnt <= (others=>'0') after tpd; + txStateCnt <= (others=>'0') after tpd; + rxPcsResetCnt <= (others=>'0') after tpd; + rxStateCnt <= (others=>'0') after tpd; + mgtRxPmaReset <= '1' after tpd; + mgtTxPmaReset <= '1' after tpd; + mgtRxReset <= '0' after tpd; + mgtTxReset <= '0' after tpd; + phyLinkError <= '0' after tpd; + pibLock <= (others=>'0') after tpd; + phyInitDone <= '0' after tpd; + elsif rising_edge(pgpClk) then + + -- Drive PIB Lock + pibLock(0) <= rxClockReady after tpd; + pibLock(1) <= txClockReady after tpd; + + -- Phy Init Is Done + phyInitDone <= rxClockReady and txClockReady after tpd; + + -- Error signals, only drive during normal operation + if mgtRxDecErr /= "00" or mgtRxDispErr /= "00" then + phyLinkError <= intLinkReady after tpd; + else + phyLinkError <= '0' after tpd; + end if; + + -- Pass on reset signals + mgtRxPmaReset <= intRxPmaReset after tpd; + mgtTxPmaReset <= intTxPmaReset after tpd; + mgtRxReset <= intRxReset after tpd; + mgtTxReset <= intTxReset after tpd; + + -- Update state + if pibReLink = '1' then + curTxState <= TX_WAIT_LOCK after tpd; + curRxState <= RX_WAIT_LOCK after tpd; + else + curTxState <= nxtTxState after tpd; + curRxState <= nxtRxState after tpd; + end if; + + -- Tx State Counter + if txStateCntRst = '1' or pibReLink = '1' then + txStateCnt <= (others=>'0') after tpd; + else + txStateCnt <= txStateCnt + 1 after tpd; + end if; + + -- TX Loop Counter + if txPcsResetCntRst = '1' or pibReLink = '1' then + txPcsResetCnt <= (others=>'0') after tpd; + elsif txPcsResetCntEn = '1' then + txPcsResetCnt <= txPcsResetCnt + 1 after tpd; + end if; + + -- Rx State Counter + if rxStateCntRst = '1' or pibReLink = '1' then + rxStateCnt <= (others=>'0') after tpd; + else + rxStateCnt <= rxStateCnt + 1 after tpd; + end if; + + -- RX Loop Counter + if rxPcsResetCntRst = '1' or pibReLink = '1' then + rxPcsResetCnt <= (others=>'0') after tpd; + elsif rxPcsResetCntEn = '1' then + rxPcsResetCnt <= rxPcsResetCnt + 1 after tpd; + end if; + end if; + end process; + + + -- Async TX State Logic + process ( curTxState, txStateCnt, mgtTxLock, mgtTxBuffError, txPcsResetCnt ) begin + case curTxState is + + -- System Reset State + when TX_SYSTEM_RESET => + txPcsResetCntRst <= '1'; + txPcsResetCntEn <= '0'; + txStateCntRst <= '1'; + intTxPmaReset <= '0'; + intTxReset <= '0'; + txClockReady <= '0'; + nxtTxState <= TX_PMA_RESET; + + -- PMA Reset State + when TX_PMA_RESET => + txPcsResetCntRst <= '0'; + txPcsResetCntEn <= '0'; + intTxPmaReset <= '1'; + intTxReset <= '0'; + txClockReady <= '0'; + + -- Wait for three clocks + if txStateCnt = 3 then + nxtTxState <= TX_WAIT_LOCK; + txStateCntRst <= '1'; + else + nxtTxState <= curTxState; + txStateCntRst <= '0'; + end if; + + -- Wait for TX Lock + when TX_WAIT_LOCK => + txPcsResetCntRst <= '0'; + txPcsResetCntEn <= '0'; + intTxPmaReset <= '0'; + intTxReset <= '0'; + txStateCntRst <= '1'; + txClockReady <= '0'; + + -- Wait for three clocks + if mgtTxLock = '1' then + nxtTxState <= TX_PCS_RESET; + else + nxtTxState <= curTxState; + end if; + + -- Assert PCS Reset + when TX_PCS_RESET => + txPcsResetCntRst <= '0'; + txPcsResetCntEn <= '0'; + intTxPmaReset <= '0'; + intTxReset <= '1'; + txClockReady <= '0'; + + -- Loss of Lock + if mgtTxLock = '0' then + nxtTxState <= TX_WAIT_LOCK; + txStateCntRst <= '1'; + + -- Wait for three clocks + elsif txStateCnt = 3 then + nxtTxState <= TX_WAIT_PCS; + txStateCntRst <= '1'; + else + nxtTxState <= curTxState; + txStateCntRst <= '0'; + end if; + + -- Wait 5 clocks after PCS reset + when TX_WAIT_PCS => + txPcsResetCntRst <= '0'; + txPcsResetCntEn <= '0'; + intTxPmaReset <= '0'; + intTxReset <= '0'; + txClockReady <= '0'; + + -- Loss of Lock + if mgtTxLock = '0' then + nxtTxState <= TX_WAIT_LOCK; + txStateCntRst <= '1'; + + -- Wait for three clocks + elsif txStateCnt = 5 then + nxtTxState <= TX_ALMOST_READY; + txStateCntRst <= '1'; + else + nxtTxState <= curTxState; + txStateCntRst <= '0'; + end if; + + -- Almost Ready State + when TX_ALMOST_READY => + intTxPmaReset <= '0'; + intTxReset <= '0'; + txClockReady <= '0'; + + -- Loss of Lock + if mgtTxLock = '0' then + nxtTxState <= TX_WAIT_LOCK; + txStateCntRst <= '1'; + txPcsResetCntEn <= '0'; + txPcsResetCntRst <= '0'; + + -- TX Buffer Error + elsif mgtTxBuffError = '1' then + txStateCntRst <= '1'; + txPcsResetCntEn <= '1'; + + -- 16 Cycles have occured, reset PLL + if txPcsResetCnt = 15 then + nxtTxState <= TX_PMA_RESET; + txPcsResetCntRst <= '1'; + + -- Go back to PCS Reset + else + nxtTxState <= TX_PCS_RESET; + txPcsResetCntRst <= '0'; + end if; + + -- Wait for 64 clocks + elsif txStateCnt = 63 then + nxtTxState <= TX_READY; + txStateCntRst <= '1'; + txPcsResetCntEn <= '0'; + txPcsResetCntRst <= '0'; + else + nxtTxState <= curTxState; + txStateCntRst <= '0'; + txPcsResetCntEn <= '0'; + txPcsResetCntRst <= '0'; + end if; + + -- Ready State + when TX_READY => + txPcsResetCntRst <= '1'; + txPcsResetCntEn <= '0'; + intTxPmaReset <= '0'; + intTxReset <= '0'; + txStateCntRst <= '1'; + txClockReady <= '1'; + + -- Loss of Lock + if mgtTxLock = '0' then + nxtTxState <= TX_WAIT_LOCK; + + -- Buffer error has occured + elsif mgtTxBuffError = '1' then + nxtTxState <= TX_PCS_RESET; + else + nxtTxState <= curTxState; + end if; + + -- Just in case + when others => + txPcsResetCntRst <= '0'; + txPcsResetCntEn <= '0'; + intTxPmaReset <= '0'; + intTxReset <= '0'; + txStateCntRst <= '0'; + txClockReady <= '0'; + nxtTxState <= TX_SYSTEM_RESET; + end case; + end process; + + + -- Async RX State Logic + process ( curRxState, rxStateCnt, mgtRxLock, mgtRxBuffError, rxPcsResetCnt ) begin + case curRxState is + + -- System Reset State + when RX_SYSTEM_RESET => + rxPcsResetCntRst <= '1'; + rxPcsResetCntEn <= '0'; + rxStateCntRst <= '1'; + intRxPmaReset <= '0'; + intRxReset <= '0'; + rxClockReady <= '0'; + nxtRxState <= RX_PMA_RESET; + + -- PMA Reset State + when RX_PMA_RESET => + rxPcsResetCntRst <= '0'; + rxPcsResetCntEn <= '0'; + intRxPmaReset <= '1'; + intRxReset <= '0'; + rxClockReady <= '0'; + + -- Wait for three clocks + if rxStateCnt = 3 then + nxtRxState <= RX_WAIT_LOCK; + rxStateCntRst <= '1'; + else + nxtRxState <= curRxState; + rxStateCntRst <= '0'; + end if; + + -- Wait for RX Lock + when RX_WAIT_LOCK => + rxPcsResetCntRst <= '0'; + rxPcsResetCntEn <= '0'; + intRxPmaReset <= '0'; + intRxReset <= '0'; + rxStateCntRst <= not mgtRxLock; + rxClockReady <= '0'; + + -- Wait for rx to be locked for 16K clock cycles + if rxStateCnt = "11111111111111" then + nxtRxState <= RX_PCS_RESET; + else + nxtRxState <= curRxState; + end if; + + -- Assert PCS Reset + when RX_PCS_RESET => + rxPcsResetCntRst <= '0'; + rxPcsResetCntEn <= '0'; + intRxPmaReset <= '0'; + intRxReset <= '1'; + rxClockReady <= '0'; + + -- Loss of Lock + if mgtRxLock = '0' then + nxtRxState <= RX_WAIT_LOCK; + rxStateCntRst <= '1'; + + -- Wait for three clocks + elsif rxStateCnt = 3 then + nxtRxState <= RX_WAIT_PCS; + rxStateCntRst <= '1'; + else + nxtRxState <= curRxState; + rxStateCntRst <= '0'; + end if; + + -- Wait 5 clocks after PCS reset + when RX_WAIT_PCS => + rxPcsResetCntRst <= '0'; + rxPcsResetCntEn <= '0'; + intRxPmaReset <= '0'; + intRxReset <= '0'; + rxClockReady <= '0'; + + -- Loss of Lock + if mgtRxLock = '0' then + nxtRxState <= RX_WAIT_LOCK; + rxStateCntRst <= '1'; + + -- Wait for five clocks + elsif rxStateCnt = 5 then + nxtRxState <= RX_ALMOST_READY; + rxStateCntRst <= '1'; + else + nxtRxState <= curRxState; + rxStateCntRst <= '0'; + end if; + + -- Almost Ready State + when RX_ALMOST_READY => + intRxPmaReset <= '0'; + intRxReset <= '0'; + rxClockReady <= '0'; + + -- Loss of Lock + if mgtRxLock = '0' then + nxtRxState <= RX_WAIT_LOCK; + rxStateCntRst <= '1'; + rxPcsResetCntEn <= '0'; + rxPcsResetCntRst <= '0'; + + -- RX Buffer Error + elsif mgtRxBuffError = '1' then + rxStateCntRst <= '1'; + rxPcsResetCntEn <= '1'; + + -- 16 Cycles have occured, reset PLL + if rxPcsResetCnt = 15 then + nxtRxState <= RX_PMA_RESET; + rxPcsResetCntRst <= '1'; + + -- Go back to PCS Reset + else + nxtRxState <= RX_PCS_RESET; + rxPcsResetCntRst <= '0'; + end if; + + -- Wait for 64 clocks + elsif rxStateCnt = 63 then + nxtRxState <= RX_READY; + rxStateCntRst <= '1'; + rxPcsResetCntEn <= '0'; + rxPcsResetCntRst <= '0'; + else + nxtRxState <= curRxState; + rxStateCntRst <= '0'; + rxPcsResetCntEn <= '0'; + rxPcsResetCntRst <= '0'; + end if; + + -- Ready State + when RX_READY => + rxPcsResetCntRst <= '1'; + rxPcsResetCntEn <= '0'; + intRxPmaReset <= '0'; + intRxReset <= '0'; + rxStateCntRst <= '1'; + rxClockReady <= '1'; + + -- Loss of Lock + if mgtRxLock = '0' then + nxtRxState <= RX_WAIT_LOCK; + + -- Buffer error has occured + elsif mgtRxBuffError = '1' then + nxtRxState <= RX_PCS_RESET; + else + nxtRxState <= curRxState; + end if; + + -- Just in case + when others => + rxPcsResetCntRst <= '0'; + rxPcsResetCntEn <= '0'; + intRxPmaReset <= '0'; + intRxReset <= '0'; + rxStateCntRst <= '0'; + rxClockReady <= '0'; + nxtRxState <= RX_SYSTEM_RESET; + end case; + end process; + +end PgpMgtWrap; + diff --git a/rce/fw-hsio/modules/pgp/hdl/PgpPhy.vhd b/rce/fw-hsio/modules/pgp/hdl/PgpPhy.vhd new file mode 100755 index 00000000..2af50f18 --- /dev/null +++ b/rce/fw-hsio/modules/pgp/hdl/PgpPhy.vhd @@ -0,0 +1,835 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, Physical Interface Module +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : PgpPhy.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 10/24/2006 +------------------------------------------------------------------------------- +-- Description: +-- Physical interface module for the Pretty Good Protocol core. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 10/24/2006: created. +-- 01/17/2006: First simulation complete. +-- 04/16/2006: Modified to support cell transmission with a blank spot for the +-- SOC charactor already included in the cell. +-- 05/30/2007: Modified link init sequence so that rx and tx are reset +-- seperately. Changed state counters for pattern detection. +-- Fixed version and link train error, extended init timeout. +-- 06/08/2007: Added counter on rx and tx lock to ensure that we only proceed +-- with init after rx and tx lock are stable. +-- 06/11/2007: Changed init sequence so that txPmaReset and rxPmaReset are not +-- longer asserted during the init sequence. These resets mess with +-- the PLL and should only be asserted at startup. It appears as if +-- the RX PLL can re-lock when the signal returns without a PMA +-- reset. Also the state machine will allow the init sequence to +-- continue to loop until a link is found. The link will only go to +-- fail if the versions mismatch. TX or RX unlock will cause the +-- link to re-start. +-- 06/13/2007: Cleanup of PMA reset control. Wait for RX lock is now much +-- longer than before per the Xilinx datasheet. +-- 06/15/2007: Removed shifting on receive data. MGT will always align comma +-- to an even byte. +-- 06/19/2007: One skip is now transmitted after a cell. The rest is junk data. +-- 06/19/2007: Removed reset of lock counters in ST_RESET state. +-- 08/24/2007: Changed clock init state machine. +-- 08/25/2007: Combined decode and disparity error +-- 04/30/2008: Added Chipscope For Debugging +-- 11/05/2008: Removed chipscope. Removed rx/tx pll and reset logic. +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE work.ALL; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity PgpPhy is port ( + + -- System clock, reset & control + pgpClk : in std_logic; -- Master clock + pgpReset : in std_logic; -- Synchronous reset input + pibReLink : in std_logic; -- Re-Link control signal + + -- Status signals + localVersion : in std_logic_vector(7 downto 0); -- Local version ID + remoteVersion : out std_logic_vector(7 downto 0); -- Remote version ID + pibFail : out std_logic; -- PIB fail indication + pibLinkReady : out std_logic; -- PIB link is ready + pibState : out std_logic_vector(2 downto 0); -- PIB State + + -- Cell Transmit Interface + pibTxSOC : in std_logic; -- Cell data start of cell + pibTxWidth : in std_logic; -- Cell data width + pibTxEOC : in std_logic; -- Cell data end of cell + pibTxEOF : in std_logic; -- Cell data end of frame + pibTxEOFE : in std_logic; -- Cell data end of frame error + pibTxData : in std_logic_vector(15 downto 0); -- Cell data data + + -- Cell Receive Interface + pibRxSOC : out std_logic; -- Cell data start of cell + pibRxWidth : out std_logic; -- Cell data width + pibRxEOC : out std_logic; -- Cell data end of cell + pibRxEOF : out std_logic; -- Cell data end of frame + pibRxEOFE : out std_logic; -- Cell data end of frame error + pibRxData : out std_logic_vector(15 downto 0); -- Cell data data + + -- Physical Interface Signals + phyRxPolarity : out std_logic; -- PHY receive signal polarity + phyRxData : in std_logic_vector(15 downto 0); -- PHY receive data + phyRxDataK : in std_logic_vector(1 downto 0); -- PHY receive data is K character + phyTxData : out std_logic_vector(15 downto 0); -- PHY transmit data + phyTxDataK : out std_logic_vector(1 downto 0); -- PHY transmit data is K character + phyInitDone : in std_logic -- PHY init is done +); + +end PgpPhy; + + +-- Define architecture +architecture PgpPhy of PgpPhy is + + -- Local Signals + signal nxtPibFail : std_logic; + signal nxtPibLinkReady : std_logic; + signal stateCnt : std_logic_vector(15 downto 0); + signal stateCntRst : std_logic; + signal stateCntEn : std_logic; + signal pattCnt : std_logic_vector(7 downto 0); + signal pattCntRst : std_logic; + signal pattCntEn : std_logic; + signal txIdleEn : std_logic; + signal txTrainEn : std_logic; + signal txVerEn : std_logic; + signal txSkipEn : std_logic; + signal txDataEn : std_logic; + signal rxDataEn : std_logic; + signal rxDetectIdle : std_logic; + signal rxDetectTrain : std_logic; + signal rxDetectInvert : std_logic; + signal rxDetectVer : std_logic; + signal rxDetectVerErr : std_logic; + signal nxtRxPolarity : std_logic; + signal dly0RxData : std_logic_vector(15 downto 0); + signal dly0RxDataK : std_logic_vector(1 downto 0); + signal dly1RxData : std_logic_vector(15 downto 0); + signal dly1RxDataK : std_logic_vector(1 downto 0); + signal sofDetect : std_logic; + signal intPhyRxPolarity : std_logic; + signal txDlyEOC : std_logic; + signal txDlyEOF : std_logic; + signal txDlyEOFE : std_logic; + + -- Physical Link State + constant ST_LOCK : std_logic_vector(2 downto 0) := "001"; + constant ST_IDLE : std_logic_vector(2 downto 0) := "010"; + constant ST_TRAIN : std_logic_vector(2 downto 0) := "011"; + constant ST_VER : std_logic_vector(2 downto 0) := "100"; + constant ST_EN : std_logic_vector(2 downto 0) := "101"; + constant ST_SKP : std_logic_vector(2 downto 0) := "110"; + constant ST_FAIL : std_logic_vector(2 downto 0) := "111"; + signal curState : std_logic_vector(2 downto 0); + signal nxtState : std_logic_vector(2 downto 0); + + -- Debug states + signal nxtDebug : std_logic_vector(2 downto 0); + signal curDebug : std_logic_vector(2 downto 0); + + -- Constant 8-bit values for RX & Tx + constant K_COM : std_logic_vector(7 downto 0) := "10111100"; -- K28.5 + constant K_IDL : std_logic_vector(7 downto 0) := "01111100"; -- K28.3 + constant K_LTS : std_logic_vector(7 downto 0) := "00111100"; -- K28.1 + constant D_102 : std_logic_vector(7 downto 0) := "01001010"; -- D10.2 + constant D_215 : std_logic_vector(7 downto 0) := "10110101"; -- D21.5 + constant K_SKP : std_logic_vector(7 downto 0) := "00011100"; -- K28.0 + constant K_VTS : std_logic_vector(7 downto 0) := "11110111"; -- K23.7 + constant K_SOC : std_logic_vector(7 downto 0) := "11111011"; -- K27.7 + constant K_EOF : std_logic_vector(7 downto 0) := "11111101"; -- K29.7 + constant K_EOFE : std_logic_vector(7 downto 0) := "11111110"; -- K30.7 + constant K_EOC : std_logic_vector(7 downto 0) := "01011100"; -- K28.2 + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Outputs + phyRxPolarity <= intPhyRxPolarity; + + + -- State transition sync logic. + -- In state counter for timeouts + -- Rx pattern counter + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + curState <= ST_LOCK after tpd; + curDebug <= ST_LOCK after tpd; + stateCnt <= (others=>'0') after tpd; + pattCnt <= (others=>'0') after tpd; + intPhyRxPolarity <= '0' after tpd; + pibFail <= '0' after tpd; + pibLinkReady <= '0' after tpd; + elsif rising_edge(pgpClk) then + + -- Status signals + pibFail <= nxtPibFail after tpd; + pibLinkReady <= nxtPibLinkReady after tpd; + + -- Re-Link detected or either of the clocks have lost lock + if pibReLink = '1' or phyInitDone = '0' then + curState <= ST_LOCK after tpd; + else + curState <= nxtState after tpd; + end if; + + -- Link inversion + intPhyRxPolarity <= nxtRxPolarity after tpd; + + -- In state counter + if stateCntRst = '1' then + stateCnt <= (others=>'0') after tpd; + elsif stateCntEn = '1' then + stateCnt <= stateCnt + 1 after tpd; + end if; + + -- Pattern receive counter + if pattCntRst = '1' then + pattCnt <= (others=>'0') after tpd; + elsif pattCntEn = '1' then + pattCnt <= pattCnt + 1 after tpd; + end if; + + -- Drive state debug output + curDebug <= nxtDebug; + end if; + end process; + + -- Output debug state + pibState <= curDebug; + + -- Link control state machine + process ( curState, stateCnt, rxDetectIdle, pattCnt, intPhyRxPolarity, rxDetectTrain, + rxDetectVer, rxDetectVerErr, rxDetectInvert, pibTxEOC, pibTxWidth, txDlyEOC, + curDebug ) begin + case curState is + + -- Wait for lock state + when ST_LOCK => + nxtPibLinkReady <= '0'; + nxtPibFail <= '0'; + pattCntRst <= '1'; + pattCntEn <= '0'; + stateCntRst <= '1'; + stateCntEn <= '0'; + txIdleEn <= '0'; + txTrainEn <= '0'; + txVerEn <= '0'; + txSkipEn <= '0'; + txDataEn <= '0'; + rxDataEn <= '0'; + nxtRxPolarity <= '0'; + nxtDebug <= ST_LOCK; + nxtState <= ST_IDLE; + + -- Transmit IDLE + when ST_IDLE => + + -- Idle is transmitting + nxtPibLinkReady <= '0'; + nxtPibFail <= '0'; + txTrainEn <= '0'; + txVerEn <= '0'; + txDataEn <= '0'; + rxDataEn <= '0'; + nxtRxPolarity <= '0'; + nxtDebug <= ST_IDLE; + + -- Transmit IDLE normally, + -- add two skip patterns every 512 clocks + if stateCnt(8 downto 2) = 0 then + txIdleEn <= '0'; + txSkipEn <= '1'; + else + txIdleEn <= '1'; + txSkipEn <= '0'; + end if; + + -- Free run state counter + stateCntEn <= '1'; + + -- Pattern counter counts IDLE sequence reception + -- Stop counting once we receive enough patterns + pattCntEn <= rxDetectIdle and not pattCnt(7); + + -- Move to next state when 128 IDLE sequences detected and we have + -- been in the state long enough to transmit 256 IDLE sequences (512 clocks) + if pattCnt(7) = '1' and stateCnt > 511 then + stateCntRst <= '1'; + pattCntRst <= '1'; + nxtState <= ST_TRAIN; + + -- Check for timeout while waiting for IDLE + elsif stateCnt = x"FFFF" then + stateCntRst <= '1'; + pattCntRst <= '1'; + nxtState <= ST_LOCK; + + -- Keep counting + else + stateCntRst <= '0'; + pattCntRst <= '0'; + nxtState <= curState; + end if; + + -- Transmit training sequence + when ST_TRAIN => + + -- Training sequence is transmitting + nxtPibLinkReady <= '0'; + nxtPibFail <= '0'; + txIdleEn <= '0'; + txVerEn <= '0'; + txDataEn <= '0'; + rxDataEn <= '0'; + nxtDebug <= ST_TRAIN; + + -- Transmit training normally, + -- add two skip patterns every 512 clocks + if stateCnt(8 downto 2) = 0 then + txTrainEn <= '0'; + txSkipEn <= '1'; + else + txTrainEn <= '1'; + txSkipEn <= '0'; + end if; + + -- Free run state counter + stateCntEn <= '1'; + + -- Detect link inversion, allow single polarity flip due to latency + -- in the rocket IO data path. + if rxDetectTrain = '1' and rxDetectInvert = '1' and intPhyRxPolarity = '0' then + nxtRxPolarity <= '1'; + else + nxtRxPolarity <= intPhyRxPolarity; + end if; + + -- Pattern counter counts training sequence reception + -- Stop counting once we receive enough patterns + pattCntEn <= rxDetectTrain and (not rxDetectInvert) and (not pattCnt(7)); + + -- Move to next state when 128 training sequences detected and we have + -- been in the state long enough to transmit 256 training sequences (512 clocks) + if pattCnt(7) = '1' and stateCnt > 511 then + stateCntRst <= '1'; + pattCntRst <= '1'; + nxtState <= ST_VER; + + -- Check for timeout while waiting for training sequences + elsif stateCnt = x"FFFF" then + stateCntRst <= '1'; + pattCntRst <= '1'; + nxtState <= ST_LOCK; + + -- Keep counting + else + stateCntRst <= '0'; + pattCntRst <= '0'; + nxtState <= curState; + end if; + + -- Transmit Version sequence + when ST_VER => + + -- Version is transmitting + nxtPibLinkReady <= '0'; + nxtPibFail <= '0'; + txIdleEn <= '0'; + txTrainEn <= '0'; + txDataEn <= '0'; + rxDataEn <= '0'; + nxtDebug <= ST_VER; + + -- Transmit version normally, + -- add two skip patterns every 512 clocks + if stateCnt(8 downto 2) = 0 then + txVerEn <= '0'; + txSkipEn <= '1'; + else + txVerEn <= '1'; + txSkipEn <= '0'; + end if; + + -- Free run state counter + stateCntEn <= '1'; + nxtRxPolarity <= intPhyRxPolarity; + + -- Pattern counter counts version sequence reception + -- Stop counting once we receive enough patterns + pattCntEn <= rxDetectVer and not pattCnt(2); + + -- Move to next state when 4 version sequences detected and we have + -- been in the state long enough to transmit 8 version sequences (16 clocks) + if pattCnt(2) = '1' and stateCnt > 15 then + + -- Reset counters for next state + stateCntRst <= '1'; + pattCntRst <= '1'; + + -- Detect version mismatch + if rxDetectVerErr = '1' and rxDetectVer = '1' then + nxtState <= ST_FAIL; + else + nxtState <= ST_EN; + end if; + + -- Check for timeout while waiting for version sequences + elsif stateCnt = x"FFFF" then + stateCntRst <= '1'; + pattCntRst <= '1'; + nxtState <= ST_LOCK; + + -- Keep counting + else + stateCntRst <= '0'; + pattCntRst <= '0'; + nxtState <= curState; + end if; + + -- Normal operation + when ST_EN => + + -- Normal data is transmitting + nxtPibLinkReady <= '1'; + nxtPibFail <= '0'; + txIdleEn <= '0'; + txTrainEn <= '0'; + txVerEn <= '0'; + txSkipEn <= '0'; + txDataEn <= '1'; + rxDataEn <= '1'; + nxtRxPolarity <= intPhyRxPolarity; + nxtDebug <= ST_EN; + + -- Pattern count is not used + pattCntEn <= '0'; + pattCntRst <= '1'; + + -- State Counter Is In Reset + stateCntEn <= '0'; + stateCntRst <= '1'; + + -- IDLE is detected + if rxDetectIdle = '1' then + nxtState <= ST_LOCK; + + -- We just transmitted a CELL, transmit Skip immediatly following + elsif (pibTxEOC = '1' and pibTxWidth = '0') or txDlyEOC = '1' then + nxtState <= ST_SKP; + + -- Stay in enable mode + else + nxtState <= curState; + end if; + + -- Transmit SKP sequence + when ST_SKP => + + -- SKP data is transmitting + nxtPibLinkReady <= '1'; + nxtPibFail <= '0'; + txIdleEn <= '0'; + txTrainEn <= '0'; + txVerEn <= '0'; + txSkipEn <= '1'; + txDataEn <= '0'; + rxDataEn <= '1'; + nxtRxPolarity <= intPhyRxPolarity; + nxtDebug <= ST_SKP; + + -- Reset pattern count + pattCntEn <= '0'; + pattCntRst <= '1'; + + -- We are done when we have transmitted 1 SKIP sequence (2 clocks). + if stateCnt(0) = '1' then + nxtstate <= ST_EN; + stateCntEn <= '0'; + stateCntRst <= '1'; + else + nxtstate <= curState; + stateCntEn <= '1'; + stateCntRst <= '0'; + end if; + + -- Link init failed + when ST_FAIL => + + -- IDLE is transmitting + nxtPibLinkReady <= '0'; + nxtPibFail <= '1'; + txIdleEn <= '1'; + txTrainEn <= '0'; + txVerEn <= '0'; + txSkipEn <= '0'; + txDataEn <= '0'; + rxDataEn <= '0'; + nxtRxPolarity <= '0'; + pattCntEn <= '0'; + stateCntEn <= '1'; + stateCntRst <= '0'; + pattCntRst <= '1'; + nxtState <= curState; + nxtDebug <= curDebug; + + -- Default state + when others => + nxtPibLinkReady <= '0'; + nxtPibFail <= '0'; + txIdleEn <= '0'; + txTrainEn <= '0'; + txVerEn <= '0'; + txSkipEn <= '0'; + txDataEn <= '0'; + rxDataEn <= '0'; + nxtRxPolarity <= '0'; + pattCntEn <= '0'; + stateCntEn <= '0'; + stateCntRst <= '0'; + pattCntRst <= '0'; + nxtState <= ST_LOCK; + nxtDebug <= ST_LOCK; + end case; + end process; + + + -- Receive data from external Serdes + -- Re-Align and detect ordered set + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + dly0RxData <= (others=>'0') after tpd; + dly0RxDataK <= (others=>'0') after tpd; + dly1RxData <= (others=>'0') after tpd; + dly1RxDataK <= (others=>'0') after tpd; + rxDetectIdle <= '0' after tpd; + rxDetectTrain <= '0' after tpd; + rxDetectInvert <= '0' after tpd; + rxDetectVer <= '0' after tpd; + rxDetectVerErr <= '0' after tpd; + remoteVersion <= (others=>'0') after tpd; + elsif rising_edge(pgpClk) then + + -- First and second stages take data right from IO pads + dly0RxData <= phyRxData after tpd; + dly0RxDataK <= phyRxDataK after tpd; + dly1RxData <= dly0RxData after tpd; + dly1RxDataK <= dly0RxDataK after tpd; + + -- Detect IDLE sequence + if dly0RxDataK(0) = '1' and dly0RxData(7 downto 0) = K_COM and + dly0RxDataK(1) = '1' and dly0RxData(15 downto 8) = K_IDL and + dly1RxDataK(0) = '1' and dly1RxData(7 downto 0) = K_IDL and + dly1RxDataK(1) = '1' and dly1RxData(15 downto 8) = K_IDL then + rxDetectIdle <= '1' after tpd; + else + rxDetectIdle <= '0' after tpd; + end if; + + -- Detect training sequence + if dly0RxDataK(0) = '1' and dly0RxData(7 downto 0) = K_COM and + dly0RxDataK(1) = '1' and dly0RxData(15 downto 8) = K_LTS and + dly1RxDataK(0) = '0' and + dly1RxDataK(1) = '1' and dly1RxData(15 downto 8) = K_LTS then + + -- Non-Inverted training data + if dly1RxData(7 downto 0) = D_102 then + rxDetectTrain <= '1' after tpd; + rxDetectInvert <= '0' after tpd; + + -- Inverted training data + elsif dly1RxData(7 downto 0) = D_215 then + rxDetectTrain <= '1' after tpd; + rxDetectInvert <= '1' after tpd; + + -- Bad data + else + rxDetectTrain <= '0' after tpd; + rxDetectInvert <= '0' after tpd; + end if; + else + rxDetectTrain <= '0' after tpd; + rxDetectInvert <= '0' after tpd; + end if; + + -- Detect Version Sequence + if dly0RxDataK(0) = '1' and dly0RxData(7 downto 0) = K_COM and + dly0RxDataK(1) = '1' and dly0RxData(15 downto 8) = K_VTS and + dly1RxDataK(0) = '0' and + dly1RxDataK(1) = '1' and dly1RxData(15 downto 8) = K_VTS then + + -- Version sequence detected + rxDetectVer <= '1' after tpd; + + -- Only store remote version when we are transmitting version + if txVerEn = '0' then + remoteVersion <= dly1RxData(7 downto 0) after tpd; + end if; + + -- Version matches + if dly1RxData(7 downto 0) = localVersion then + rxDetectVerErr <= '0' after tpd; + + -- Version mismatch + else + rxDetectVerErr <= '1' after tpd; + end if; + else + rxDetectVer <= '0' after tpd; + end if; + end if; + end process; + + + -- Receive data from external Serdes + -- Re-Align and detect SOC,EOF,EOC,EOFE + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + pibRxSOC <= '0' after tpd; + pibRxWidth <= '0' after tpd; + pibRxEOC <= '0' after tpd; + pibRxEOF <= '0' after tpd; + pibRxEOFE <= '0' after tpd; + pibRxData <= (others=>'0') after tpd; + sofDetect <= '0' after tpd; + elsif rising_edge(pgpClk) then + + -- Receiver is enabled + if rxDataEn = '1' then + + -- Detect SOC + if dly0RxDataK(0) = '1' and dly0RxData(7 downto 0) = K_SOC then + sofDetect <= '1' after tpd; + else + sofDetect <= '0' after tpd; + end if; + + -- Store data to outgoing pads + pibRxData(15 downto 8) <= dly1RxData(15 downto 8) after tpd; + pibRxData(7 downto 0) <= dly1RxData(7 downto 0) after tpd; + + -- SOC Flags + pibRxSOC <= sofDetect after tpd; + + -- Detect EOF flag, low byte + if (dly0RxDataK(0) = '1' and dly0RxData(7 downto 0) = K_EOF ) then + pibRxEOF <= '1' after tpd; + pibRxEOFE <= '0' after tpd; + pibRxEOC <= '1' after tpd; + pibRxWidth <= '1' after tpd; + + -- Detect EOF flag, high byte + elsif (dly1RxDataK(1) = '1' and dly1RxData(15 downto 8) = K_EOF ) then + pibRxEOF <= '1' after tpd; + pibRxEOFE <= '0' after tpd; + pibRxEOC <= '1' after tpd; + pibRxWidth <= '0' after tpd; + + -- Detect EOFE flag, low byte + elsif (dly0RxDataK(0) = '1' and dly0RxData(7 downto 0) = K_EOFE ) then + pibRxEOF <= '1' after tpd; + pibRxEOFE <= '1' after tpd; + pibRxEOC <= '1' after tpd; + pibRxWidth <= '1' after tpd; + + -- Detect EOFE flag, high byte + elsif (dly1RxDataK(1) = '1' and dly1RxData(15 downto 8) = K_EOFE ) then + pibRxEOF <= '1' after tpd; + pibRxEOFE <= '1' after tpd; + pibRxEOC <= '1' after tpd; + pibRxWidth <= '0' after tpd; + + -- Detect EOC flag, low byte + elsif (dly0RxDataK(0) = '1' and dly0RxData(7 downto 0) = K_EOC ) then + pibRxEOF <= '0' after tpd; + pibRxEOFE <= '0' after tpd; + pibRxEOC <= '1' after tpd; + pibRxWidth <= '1' after tpd; + + -- Detect EOC flag, high byte + elsif (dly1RxDataK(1) = '1' and dly1RxData(15 downto 8) = K_EOC ) then + pibRxEOF <= '0' after tpd; + pibRxEOFE <= '0' after tpd; + pibRxEOC <= '1' after tpd; + pibRxWidth <= '0' after tpd; + + -- Normal data + else + pibRxEOF <= '0' after tpd; + pibRxEOFE <= '0' after tpd; + pibRxEOC <= '0' after tpd; + pibRxWidth <= '1' after tpd; + end if; + end if; + end if; + end process; + + + -- Transmit data to external serdes. Data frame cell tx logic will + -- contain data with the first byte in bits 7-0. An SOC charactor + -- must be added to the front of the frame. An EOF charactor will be + -- added to the end. + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + phyTxData <= (others=>'0') after tpd; + phyTxDataK <= (others=>'0') after tpd; + txDlyEOC <= '0' after tpd; + txDlyEOF <= '0' after tpd; + txDlyEOFE <= '0' after tpd; + + elsif rising_edge(pgpClk) then + + -- Transmit IDLE + if txIdleEn = '1' then + if stateCnt(0) = '0' then + phyTxDataK <= "11" after tpd; + phyTxData(7 downto 0) <= K_COM after tpd; + phyTxData(15 downto 8) <= K_IDL after tpd; + else + phyTxDataK <= "11" after tpd; + phyTxData(7 downto 0) <= K_IDL after tpd; + phyTxData(15 downto 8) <= K_IDL after tpd; + end if; + + -- Unused signals + txDlyEOC <= '0' after tpd; + txDlyEOF <= '0' after tpd; + txDlyEOFE <= '0' after tpd; + + -- Transmit training sequence + elsif txTrainEn = '1' then + if stateCnt(0) = '0' then + phyTxDataK <= "11" after tpd; + phyTxData(7 downto 0) <= K_COM after tpd; + phyTxData(15 downto 8) <= K_LTS after tpd; + else + phyTxDataK <= "10" after tpd; + phyTxData(7 downto 0) <= D_102 after tpd; + phyTxData(15 downto 8) <= K_LTS after tpd; + end if; + + -- Unused signals + txDlyEOC <= '0' after tpd; + txDlyEOF <= '0' after tpd; + txDlyEOFE <= '0' after tpd; + + -- Transmit local version + elsif txVerEn = '1' then + if stateCnt(0) = '0' then + phyTxDataK <= "11" after tpd; + phyTxData(7 downto 0) <= K_COM after tpd; + phyTxData(15 downto 8) <= K_VTS after tpd; + else + phyTxDataK <= "10" after tpd; + phyTxData(7 downto 0) <= localVersion after tpd; + phyTxData(15 downto 8) <= K_VTS after tpd; + end if; + + -- Unused signals + txDlyEOC <= '0' after tpd; + txDlyEOF <= '0' after tpd; + txDlyEOFE <= '0' after tpd; + + -- Transmit skip sequence + elsif txSkipEn = '1' then + if stateCnt(0) = '0' then + phyTxDataK <= "11" after tpd; + phyTxData(7 downto 0) <= K_COM after tpd; + phyTxData(15 downto 8) <= K_SKP after tpd; + else + phyTxDataK <= "11" after tpd; + phyTxData(7 downto 0) <= K_SKP after tpd; + phyTxData(15 downto 8) <= K_SKP after tpd; + end if; + + -- Unused signals + txDlyEOC <= '0' after tpd; + txDlyEOF <= '0' after tpd; + txDlyEOFE <= '0' after tpd; + + -- Transmitter is enabled + elsif txDataEn = '1' then + + -- SOC Generation + if pibTxSOC = '1' then + phyTxData(15 downto 8) <= pibTxData(15 downto 8) after tpd; + phyTxData(7 downto 0) <= K_SOC after tpd; + phyTxDataK <= "01" after tpd; + txDlyEOC <= '0' after tpd; + txDlyEOF <= '0' after tpd; + txDlyEOFE <= '0' after tpd; + + -- End of cell requested + elsif pibTxEOC = '1' then + + -- Width = '0', overwrite upper byte with EOF, we are done + if pibTxWidth = '0' then + phyTxData(7 downto 0) <= pibTxData(7 downto 0) after tpd; + phyTxDataK <= "10" after tpd; + txDlyEOC <= '0' after tpd; + txDlyEOF <= '0' after tpd; + txDlyEOFE <= '0' after tpd; + + -- Which EOC charactor to send + if pibTxEOFE = '1' then + phyTxData(15 downto 8) <= K_EOFE after tpd; + elsif pibTxEOF = '1' then + phyTxData(15 downto 8) <= K_EOF after tpd; + else + phyTxData(15 downto 8) <= K_EOC after tpd; + end if; + + -- Width = '1', need to add an extra byte + else + phyTxData <= pibTxData after tpd; + phyTxDataK <= "00" after tpd; + txDlyEOC <= '1' after tpd; + txDlyEOF <= pibTxEOF after tpd; + txDlyEOFE <= pibTxEOFE after tpd; + end if; + + -- Delayed EOC + elsif txDlyEOC = '1' then + + -- Pass unused through + phyTxData(15 downto 8) <= pibTxData(15 downto 8) after tpd; + phyTxDataK <= "01" after tpd; + txDlyEOC <= '0' after tpd; + txDlyEOF <= '0' after tpd; + txDlyEOFE <= '0' after tpd; + + -- Which EOC charactor to send + if txDlyEOFE = '1' then + phyTxData(7 downto 0) <= K_EOFE after tpd; + elsif txDlyEOF = '1' then + phyTxData(7 downto 0) <= K_EOF after tpd; + else + phyTxData(7 downto 0) <= K_EOC after tpd; + end if; + + -- Normal data + else + phyTxData <= pibTxData after tpd; + phyTxDataK <= "00" after tpd; + txDlyEOC <= '0' after tpd; + txDlyEOF <= '0' after tpd; + txDlyEOFE <= '0' after tpd; + end if; + end if; + end if; + end process; + +end PgpPhy; + diff --git a/rce/fw-hsio/modules/pgp/hdl/PgpPicRemBuff.vhd b/rce/fw-hsio/modules/pgp/hdl/PgpPicRemBuff.vhd new file mode 100755 index 00000000..a106eee6 --- /dev/null +++ b/rce/fw-hsio/modules/pgp/hdl/PgpPicRemBuff.vhd @@ -0,0 +1,252 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol Applications, Remote Buffer For PIC +-- Project : Reconfigurable Cluster Element +------------------------------------------------------------------------------- +-- File : PgpPicRemBuff.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 11/09/2007 +------------------------------------------------------------------------------- +-- Description: +-- VHDL source file for block on the remote end of the PGP link which feeds +-- the PGP with frame data that will be receoved by the PIC Import block. +-- The PIC Import block does not support short cells. This logic will ensure +-- that only full cells are transfered over the PGP link. +-- This block is fed from a fifo which is filled by the user logic. +-- Flow control +-- When the PIC asserts FULL data transfer will stop immediatly. When almost +-- full is asserted the current cell will be complete the the interface will +-- pause at the next boundary. +------------------------------------------------------------------------------- +-- Copyright (c) 2007 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 11/09/2007: created. +-- 11/16/2007: Fixed corner case where flow control asserts just as pre-read +-- data is read from the fifo. +-- 11/27/2007: Moved CID generator into chipscope block for size reasons. +-- 11/29/2007: Changed cell boundary detection to improve timing. +-- 12/11/2007: Removed chipscope; +-- 03/06/2008: Removed 8-bit support. +------------------------------------------------------------------------------- +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity PgpPicRemBuff is port ( + + -- Clock and reset + pgpClk : in std_logic; -- 125Mhz master clock + pgpReset : in std_logic; -- Synchronous reset input + + -- Interface To PGP + vcFrameTxValid : out std_logic; -- User frame data is valid + vcFrameTxReady : in std_logic; -- PGP is ready + vcFrameTxSOF : out std_logic; -- User frame data start of frame + vcFrameTxWidth : out std_logic; -- User frame data width + vcFrameTxEOF : out std_logic; -- User frame data end of frame + vcFrameTxEOFE : out std_logic; -- User frame data error + vcFrameTxData : out std_logic_vector(15 downto 0); -- User frame data + vcFrameTxCid : out std_logic_vector(31 downto 0); -- User frame data, context ID + vcFrameTxAckCid : in std_logic_vector(31 downto 0); -- PGP ACK/NACK context ID + vcFrameTxAckEn : in std_logic; -- PGP ACK/NACK enable + vcFrameTxAck : in std_logic; -- PGP ACK/NACK + vcRemBuffAFull : in std_logic; -- Remote buffer almost full + vcRemBuffFull : in std_logic; -- Remote buffer full + + -- Interface to feeding FIFO + txFifoRd : out std_logic; -- TX Fifo Read Strobe + txFifoEmpty : in std_logic; -- TX Fifo Empty + txFifoData : in std_logic_vector(15 downto 0); -- TX Data + txFifoSOF : in std_logic; -- TX Fifo Start Of Frame + txFifoEOF : in std_logic; -- TX Fifo End Of Frame + txFifoEOFE : in std_logic -- TX Fifo End Of Frame, Error + ); +end PgpPicRemBuff; + + +-- Define architecture +architecture PgpPicRemBuff of PgpPicRemBuff is + + -- Output Fifo + component pgp_fifo_21x512 port ( + clk: IN std_logic; + din: IN std_logic_VECTOR(20 downto 0); + rd_en: IN std_logic; + rst: IN std_logic; + wr_en: IN std_logic; + data_count: OUT std_logic_VECTOR(8 downto 0); + dout: OUT std_logic_VECTOR(20 downto 0); + empty: OUT std_logic; + full: OUT std_logic); + end component; + + -- Local Signals + signal intFifoRdDly : std_logic; + signal syncWr : std_logic; + signal syncDin : std_logic_vector(20 downto 0); + signal wrCount : std_logic_vector(7 downto 0); + signal syncRdDly : std_logic; + signal cellCount : std_logic_vector(2 downto 0); + signal syncValid : std_logic; + signal syncDout : std_logic_vector(20 downto 0); + signal syncRd : std_logic; + signal syncEmpty : std_logic; + signal syncCount : std_logic_vector(8 downto 0); + signal intFifoRd : std_logic; + signal intCid : std_logic_vector(31 downto 0); + signal syncAFull : std_logic; + signal syncSOC : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + + -- Black Box Attributes + attribute syn_black_box : boolean; + attribute syn_noprune : boolean; + attribute syn_black_box of pgp_fifo_21x512 : component is TRUE; + attribute syn_noprune of pgp_fifo_21x512 : component is TRUE; + +begin + + -- Pass read to FIFO + txFifoRd <= intFifoRd; + + -- Read when FIFO has data and sync FIFO has room + intFifoRd <= (not txFifoEmpty) and (not syncAFull); + + -- Track data movement + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + intFifoRdDly <= '0' after tpd; + syncWr <= '0' after tpd; + syncDin(19 downto 0) <= (others=>'0') after tpd; + wrCount <= (others=>'0') after tpd; + syncRdDly <= '0' after tpd; + cellCount <= "000" after tpd; + syncValid <= '0' after tpd; + syncSOC <= '0' after tpd; + syncAFull <= '0' after tpd; + elsif rising_edge(pgpClk) then + + -- Generate sync fifo almost full signal + if syncCount > 500 or cellCount(2) = '1' then + syncAFull <= '1' after tpd; + else + syncAFull <= '0' after tpd; + end if; + + -- Delayed copy of fifo read + intFifoRdDly <= intFifoRd after tpd; + + -- Add pipeline stage to write data for timing + syncWr <= intFifoRdDly after tpd; + syncDin(19) <= txFifoEOFE after tpd; + syncDin(18) <= txFifoEOF after tpd; + syncDin(17) <= '1' after tpd; + syncDin(16) <= txFifoSOF after tpd; + syncDin(15 downto 0) <= txFifoData after tpd; + + -- Cell Write Counter + if syncDin(18) = '1' then + wrCount <= (others=>'0') after tpd; + elsif syncWr = '1' then + wrCount <= wrCount + 1 after tpd; + end if; + + -- Delayed copy of sync FIFO reads + syncRdDly <= syncRd after tpd; + + -- Track number of cells in the sync fifo + -- Read cell marker, no write + if syncRdDly = '1' and syncDout(20) = '1' and + (syncWr = '0' or syncDin(20) = '0') then + cellCount <= cellCount - 1 after tpd; + + -- Write cell marker, no read + elsif syncWr = '1' and syncDin(20) = '1' and + (syncRdDly = '0' or syncDout(20) = '0') then + cellCount <= cellCount + 1 after tpd; + + -- FIFO is empty + elsif syncEmpty = '1' then + cellCount <= "000" after tpd; + end if; + + -- De-assert valid when PGP accepts and no read occurs + if vcFrameTxReady = '1' and syncRd = '0' then + syncValid <= '0' after tpd; + syncSOC <= '0' after tpd; + + -- Read is occuring with or without ready + elsif syncRd = '1' then + + -- Last value was EOC or no cells in FIFO, De-Assert valid for at least one cycle + -- Mark current output as start of cell + if syncDout(20) = '1' or cellCount = 0 then + syncValid <= '0' after tpd; + syncSOC <= '1' after tpd; + else + syncValid <= '1' after tpd; + syncSOC <= '0' after tpd; + end if; + + -- SOC is on FIFO output, assert valid only when at least one cell is + -- present in the FIFO and remote buffers are ready + elsif syncSOC = '1' then + if cellCount /= 0 and syncEmpty = '0' and vcRemBuffAFull = '0' + and vcRemBuffFull = '0' then + syncValid <= '1' after tpd; + end if; + end if; + end if; + end process; + + + -- Set end of cell flag + syncDin(20) <= '1' when syncDin(18) = '1' or wrCount = 255 else '0'; + + + -- Control reads from FIFO + process (vcRemBuffFull, vcFrameTxReady, syncValid, syncSOC, syncEmpty ) begin + + -- Data is moving + if vcFrameTxReady = '1' and syncValid = '1' then + syncRd <= (not syncEmpty) and (not vcRemBuffFull); + + -- Pre-read required + elsif syncValid = '0' and syncSOC = '0' then + syncRd <= (not syncEmpty) and (not vcRemBuffFull); + + -- No Read + else + syncRd <= '0'; + end if; + end process; + + + -- Sync FIFO + U_SyncFifo: pgp_fifo_21x512 port map ( + clk => pgpClk, + din => syncDin, + rd_en => syncRd, + rst => pgpReset, + wr_en => syncWr, + data_count => syncCount, + dout => syncDout, + empty => syncEmpty, + full => open + ); + + -- Outgoing data + vcFrameTxValid <= syncValid; + vcFrameTxEOFE <= syncDout(19); + vcFrameTxEOF <= syncDout(18); + vcFrameTxWidth <= '1'; + vcFrameTxSOF <= syncDout(16); + vcFrameTxData <= syncDout(15 downto 0); + vcFrameTxCid <= (others=>'0'); + +end PgpPicRemBuff; + diff --git a/rce/fw-hsio/modules/pgp/hdl/PgpRegSlave.vhd b/rce/fw-hsio/modules/pgp/hdl/PgpRegSlave.vhd new file mode 100755 index 00000000..e3d7db33 --- /dev/null +++ b/rce/fw-hsio/modules/pgp/hdl/PgpRegSlave.vhd @@ -0,0 +1,803 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol Applications, Register Slave Block +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : PgpRegSlave.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 09/22/2007 +------------------------------------------------------------------------------- +-- Description: +-- Slave block for Register protocol over the PGP. +-- Packet is 16 bytes. The 16 bit values passed over the PGP will be: +-- Word 0 Data[1:0] = VC +-- Word 0 Data[7:2] = Dest_ID +-- Word 0 Data[15:8] = TID[7:0] +-- Word 1 Data[15:0] = TID[23:8] +-- Word 2 Data[15:0] = Address[15:0] +-- Word 3 Data[15:14] = OpCode, 0x0=Read, 0x1=Write, 0x2=Set, 0x3=Clear +-- Word 3 Data[13:8] = Don't Care +-- Word 3 Data[7:0] = Address[23:16] +-- Word 4 Data[15:0] = WriteData[15:0] +-- Word 5 Data[15:0] = WriteData[31:16] +-- Word 6 = Don't Care +-- Word 7 Data[15:2] = Don't Care +-- Word 7 Data[1] = Timeout Flag (response data) +-- Word 7 Data[0] = Fail Flag (response data) +------------------------------------------------------------------------------- +-- Copyright (c) 2007 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 09/22/2007: created. +-- 10/10/2007: Added 32-bit CID value to frame. +-- 10/29/2007: Changed name of coregen blocks +-- 11/06/2007: Changed flow control reaction to ensure their are no short cells. +-- 11/06/2007: Added wait for ACK and re-transmission on NACK reception. +-- 11/07/2007: Changed reaction to full flag due to change in pic interface. +-- 11/20/2007: Added check to ensure overflow will put EOFE into buffer. +-- 11/27/2007: Modified to allow the option of sync or async FIFOs +-- Removed re-transmission of nack reception. +-- 11/30/2007: Fixed error with back to back frames and mis-connected data lines. +-- Made frame size 20bytes for received data. Testing Only. +-- 11/30/2007: Removed FIFO in TX direction. +-- 12/12/2007: Added wait for ack de-assertion for set and clear commands. +-- Previous version would see ack from pervious command due to +-- pipeline of register data. +-- 12/14/2007: Adjusted frame length back to 16 bytes. +-- 01/25/2008: Adjusted for new frame format. +-- 02/08/2008: More frame format changes. Added in progress flag. +-- 02/05/2008: Changed timeout to 12-bits. +-- 07/22/2008: Changed timeout to 16-bits. +-- 01/14/2009: Changed timeout to 24-bits. +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE work.ALL; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity PgpRegSlave is + generic ( + AsyncFIFO : string := "TRUE" -- Use Async FIFOs, TRUE or FALSE + ); + port ( + + -- PGP Clock And Reset + pgpClk : in std_logic; -- PGP Clock + pgpReset : in std_logic; -- Synchronous PGP Reset + + -- Local clock and reset + locClk : in std_logic; -- Local Clock + locReset : in std_logic; -- Synchronous Local Reset + + -- PGP Receive Signals + vcFrameRxValid : in std_logic; -- Data is valid + vcFrameRxSOF : in std_logic; -- Data is SOF + vcFrameRxWidth : in std_logic; -- Data is 16-bits + vcFrameRxEOF : in std_logic; -- Data is EOF + vcFrameRxEOFE : in std_logic; -- Data is EOF with Error + vcFrameRxData : in std_logic_vector(15 downto 0); -- Data + vcLocBuffAFull : out std_logic; -- Local buffer almost full + vcLocBuffFull : out std_logic; -- Local buffer full + + -- PGP Transmit Signals + vcFrameTxValid : out std_logic; -- User frame data is valid + vcFrameTxReady : in std_logic; -- PGP is ready + vcFrameTxSOF : out std_logic; -- User frame data start of frame + vcFrameTxWidth : out std_logic; -- User frame data width + vcFrameTxEOF : out std_logic; -- User frame data end of frame + vcFrameTxEOFE : out std_logic; -- User frame data error + vcFrameTxData : out std_logic_vector(15 downto 0); -- User frame data + vcFrameTxCid : out std_logic_vector(31 downto 0); -- User frame data, context ID + vcFrameTxAckCid : in std_logic_vector(31 downto 0); -- PGP ACK/NACK context ID + vcFrameTxAckEn : in std_logic; -- PGP ACK/NACK enable + vcFrameTxAck : in std_logic; -- PGP ACK/NACK + vcRemBuffAFull : in std_logic; -- Remote buffer almost full + vcRemBuffFull : in std_logic; -- Remote buffer full + + -- Local register control signals + regInp : out std_logic; -- Register Access In Progress Flag + regReq : out std_logic; -- Register Access Request + regOp : out std_logic; -- Register OpCode, 0=Read, 1=Write + regAck : in std_logic; -- Register Access Acknowledge + regFail : in std_logic; -- Register Access Fail + regAddr : out std_logic_vector(23 downto 0); -- Register Address + regDataOut : out std_logic_vector(31 downto 0); -- Register Data Out + regDataIn : in std_logic_vector(31 downto 0) -- Register Data In + ); + +end PgpRegSlave; + + +-- Define architecture +architecture PgpRegSlave of PgpRegSlave is + + -- Async FIFO + component pgp_afifo_20x511 port ( + din: IN std_logic_VECTOR(19 downto 0); + rd_clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_clk: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(19 downto 0); + empty: OUT std_logic; + full: OUT std_logic; + wr_data_count: OUT std_logic_VECTOR(8 downto 0)); + end component; + + -- Sync FIFO + component pgp_fifo_20x512 port ( + din: IN std_logic_VECTOR(19 downto 0); + clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(19 downto 0); + empty: OUT std_logic; + full: OUT std_logic; + data_count: OUT std_logic_VECTOR(8 downto 0)); + end component; + + -- Local Signals + signal rxFifoDin : std_logic_vector(19 downto 0); + signal rxFifoDout : std_logic_vector(19 downto 0); + signal rxFifoRd : std_logic; + signal rxFifoRdDly : std_logic; + signal rxFifoCount : std_logic_vector(8 downto 0); + signal rxFifoEmpty : std_logic; + signal locRxSOF : std_logic; + signal locRxWidth : std_logic; + signal locRxEOF : std_logic; + signal locRxEOFE : std_logic; + signal locRxData : std_logic_vector(15 downto 0); + signal intRxCnt : std_logic_vector(2 downto 0); + signal intRxCntEn : std_logic; + signal intOpCode : std_logic_vector(1 downto 0); + signal intVc : std_logic_vector(1 downto 0); + signal intDest : std_logic_vector(5 downto 0); + signal intAddress : std_logic_vector(23 downto 0); + signal intTid : std_logic_vector(23 downto 0); + signal intWrData : std_logic_vector(31 downto 0); + signal rxFifoRdEn : std_logic; + signal intRegStart : std_logic; + signal intInp : std_logic; + signal intReq : std_logic; + signal intOp : std_logic; + signal intData : std_logic_vector(31 downto 0); + signal intReqCnt : std_logic_vector(23 downto 0); + signal intFail : std_logic; + signal intTout : std_logic; + signal respCnt : std_logic_vector(2 downto 0); + signal nxtInp : std_logic; + signal nxtReq : std_logic; + signal nxtOp : std_logic; + signal nxtdata : std_logic_vector(31 downto 0); + signal nxtFail : std_logic; + signal nxtTout : std_logic; + signal fifoErr : std_logic; + signal fifoFull : std_logic; + signal respReq : std_logic; + signal respReqDly : std_logic_vector(1 downto 0); + signal respAck : std_logic; + signal respAckDly : std_logic_vector(1 downto 0); + signal respValid : std_logic; + + -- Register access states + signal curState : std_logic_vector(2 downto 0); + signal nxtState : std_logic_vector(2 downto 0); + constant ST_IDLE : std_logic_vector(2 downto 0) := "001"; + constant ST_WRITE : std_logic_vector(2 downto 0) := "010"; + constant ST_READ : std_logic_vector(2 downto 0) := "011"; + constant ST_SET : std_logic_vector(2 downto 0) := "100"; + constant ST_CLEAR : std_logic_vector(2 downto 0) := "101"; + constant ST_RESP : std_logic_vector(2 downto 0) := "110"; + constant ST_DONE : std_logic_vector(2 downto 0) := "111"; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + + -- Black Box Attributes + attribute syn_black_box : boolean; + attribute syn_noprune : boolean; + attribute syn_black_box of pgp_afifo_20x511 : component is TRUE; + attribute syn_noprune of pgp_afifo_20x511 : component is TRUE; + attribute syn_black_box of pgp_fifo_20x512 : component is TRUE; + attribute syn_noprune of pgp_fifo_20x512 : component is TRUE; + +begin + + -- Data going into Rx FIFO + rxFifoDin(19) <= vcFrameRxSOF; + rxFifoDin(18) <= vcFrameRxWidth; + rxFifoDin(17) <= vcFrameRxEOF or fifoErr; + rxFifoDin(16) <= vcFrameRxEOFE or fifoErr; + rxFifoDin(15 downto 0) <= vcFrameRxData; + + -- Async Receive FIFO + U_GenRxAFifo: if AsyncFIFO = "TRUE" generate + U_RegRxAFifo: pgp_afifo_20x511 port map ( + din => rxFifoDin, + rd_clk => locClk, + rd_en => rxFifoRd, + rst => pgpReset, + wr_clk => pgpClk, + wr_en => vcFrameRxValid, + dout => rxFifoDout, + empty => rxFifoEmpty, + full => fifoFull, + wr_data_count => rxFifoCount + ); + end generate; + + -- Sync Receive FIFO + U_GenRxFifo: if AsyncFIFO = "FALSE" generate + U_RegRxFifo: pgp_fifo_20x512 port map ( + din => rxFifoDin, + clk => pgpClk, + rd_en => rxFifoRd, + rst => pgpReset, + wr_en => vcFrameRxValid, + dout => rxFifoDout, + empty => rxFifoEmpty, + full => fifoFull, + data_count => rxFifoCount + ); + end generate; + + -- Data coming out of Rx FIFO + locRxSOF <= rxFifoDout(19); + locRxWidth <= rxFifoDout(18); + locRxEOF <= rxFifoDout(17); + locRxEOFE <= rxFifoDout(16); + locRxData <= rxFifoDout(15 downto 0); + + -- Generate fifo read, Don't read after EOF is just read + rxFifoRd <= (not rxFifoEmpty) and rxFifoRdEn and ((not rxFifoRdDly) or (not locRxEOF)); + + -- Generate flow control + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + vcLocBuffAFull <= '0' after tpd; + vcLocBuffFull <= '0' after tpd; + fifoErr <= '0' after tpd; + elsif rising_edge(pgpClk) then + + -- Generate full error + if rxFifoCount >= 508 or fifoFull = '1' then + fifoErr <= '1' after tpd; + else + fifoErr <= '0' after tpd; + end if; + + -- Almost full at half capacity + vcLocBuffAFull <= rxFifoCount(8); + + -- Full at 3/4 capacity + vcLocBuffFull <= rxFifoCount(8) and rxFifoCount(7); + end if; + end process; + + + -- Receive Data Processor + process ( locClk, locReset ) begin + if locReset = '1' then + intOpCode <= "00" after tpd; + intAddress <= (others=>'0') after tpd; + intWrData <= (others=>'0') after tpd; + intRegStart <= '0' after tpd; + intTid <= (others=>'0') after tpd; + rxFifoRdDly <= '0' after tpd; + intRxCnt <= (others=>'0') after tpd; + intRxCntEn <= '0' after tpd; + intDest <= (others=>'0') after tpd; + intVc <= (others=>'0') after tpd; + elsif rising_edge(locClk) then + + -- Generate delayed read + rxFifoRdDly <= rxFifoRd after tpd; + + -- Only process when data has been read + if rxFifoRdDly = '1' then + + -- Receive Data Counter + -- Reset on SOF or EOF, Start counter on SOF + if locRxSOF = '1' or locRxEOF = '1' then + intRxCnt <= (others=>'0') after tpd; + intRxCntEn <= not locRxEOF after tpd; + elsif intRxCntEn = '1' and intRxCnt /= "111" then + intRxCnt <= intRxCnt + 1 after tpd; + end if; + + -- SOF Received + if locRxSOF = '1' then + intTid(7 downto 0) <= locRxData(15 downto 8) after tpd; + intDest <= locRxData(7 downto 2) after tpd; + intVc <= locRxData(1 downto 0) after tpd; + intRegStart <= '0' after tpd; + + -- Rest of Frame + else case intRxCnt is + + -- Word 1 + when "000" => + intTid(23 downto 8) <= locRxData after tpd; + intRegStart <= '0' after tpd; + + -- Word 2 + when "001" => + intAddress(15 downto 0) <= locRxData after tpd; + intRegStart <= '0' after tpd; + + -- Word 3 + when "010" => + intOpCode <= locRxData(15 downto 14) after tpd; + intAddress(23 downto 16) <= locRxData(7 downto 0) after tpd; + intRegStart <= '0' after tpd; + + -- Word 4 + when "011" => + intWrData(15 downto 0) <= locRxData after tpd; + intRegStart <= '0' after tpd; + + -- Word 5 + when "100" => + intWrData(31 downto 16) <= locRxData after tpd; + intRegStart <= '0' after tpd; + + -- Word 7, Last word + when "110" => + + -- No error and internal flags match + if locRxEOF = '1' and locRxEOFE = '0' and locRxWidth = '1' then + intRegStart <= '1' after tpd; + else + intRegStart <= '0' after tpd; + end if; + + -- Do nothing for others + when others => + intRegStart <= '0' after tpd; + end case; + end if; + else + intRegStart <= '0' after tpd; + end if; + end if; + end process; + + + -- Drive address bus + regAddr <= intAddress; + regDataOut <= intData; + regInp <= intInp; + regReq <= intReq; + regOp <= intOp; + + + -- Register State Machine, Sync Logic + process ( locClk, locReset ) begin + if locReset = '1' then + intInp <= '0' after tpd; + intReq <= '0' after tpd; + intOp <= '0' after tpd; + intData <= (others=>'0') after tpd; + intReqCnt <= (others=>'0') after tpd; + intFail <= '0' after tpd; + intTout <= '0' after tpd; + respAckDly <= (others=>'0') after tpd; + curState <= ST_IDLE after tpd; + elsif rising_edge(locClk) then + + -- Sync Response Ack Lines + respAckDly(0) <= respAck; + respAckDly(1) <= respAckDly(0); + + -- State transition + curState <= nxtState after tpd; + + -- Opcode and write data + intInp <= nxtInp after tpd; + intReq <= nxtReq after tpd; + intOp <= nxtOp after tpd; + + -- Data Storage + intData <= nxtData after tpd; + + -- Timeout & fail flags + intFail <= nxtFail after tpd; + intTout <= nxtTout after tpd; + + -- Timeout counter + if intReq <= '0' then + intReqCnt <= (others=>'0') after tpd; + elsif intReqCnt /= x"FFFFFF" then + intReqCnt <= intReqCnt + 1 after tpd; + end if; + end if; + end process; + + + -- Register state engine + process ( curState, intWrData, intRegStart, intOpCode, intData, + regAck, regFail, regDataIn, intReqCnt, intFail, intTout, respAckDly ) begin + + -- States + case curState is + + -- IDLE, Wait for enable from read logic + when ST_IDLE => + + -- No Response Request + respReq <= '0'; + + -- No timeout or fail + nxtFail <= '0'; + nxtTout <= '0'; + + -- No external commands + nxtInp <= '0'; + nxtReq <= '0'; + nxtOp <= '0'; + + -- Register data + nxtdata <= intWrData; + + -- Start + if intRegStart = '1' then + + -- Write Command + if intOpCode = "01" then + nxtState <= ST_WRITE; + + -- Read, Set Bit, Clear Bit + else + nxtState <= ST_READ; + end if; + rxFifoRdEn <= '0'; + else + nxtState <= curState; + rxFifoRdEn <= '1'; + end if; + + -- Write State + when ST_WRITE => + + -- No Response Request + respReq <= '0'; + + -- Assert write to external interface + nxtInp <= '1'; + nxtReq <= '1'; + nxtOp <= '1'; + + -- Disable FIFO Rd + rxFifoRdEn <= '0'; + + -- Keep data + nxtdata <= intData; + + -- Ack is passed + if regAck = '1' then + + -- Generate response + nxtState <= ST_RESP; + + -- Store fail flag, no timeout + nxtFail <= regFail; + nxtTout <= '0'; + + -- Timeout + elsif intReqCnt = x"FFFFFF" then + + -- Generate response + nxtState <= ST_RESP; + + -- No Fail, set timeout + nxtFail <= '0'; + nxtTout <= '1'; + + -- Keep waiting + else + nxtState <= curState; + nxtFail <= '0'; + nxtTout <= '0'; + end if; + + -- Read State + when ST_READ => + + -- No Response Request + respReq <= '0'; + + -- Assert read to external interface + nxtInp <= '1'; + nxtReq <= '1'; + nxtOp <= '0'; + + -- Disable FIFO Rd + rxFifoRdEn <= '0'; + + -- Take read data + nxtdata <= regDataIn; + + -- Ack is passed + if regAck = '1' then + + -- Fail + if regFail = '1' then + + -- Store fail flag, no timeout, send response + nxtFail <= regFail; + nxtTout <= '0'; + nxtState <= ST_RESP; + + -- Normal termination + else + + -- No fail or timeout + nxtFail <= '0'; + nxtTout <= '0'; + + -- Set bit command + if intOpCode = "10" then + nxtState <= ST_SET; + + -- Clear bit command + elsif intOpCode = "11" then + nxtState <= ST_CLEAR; + + -- Read command + else + nxtState <= ST_RESP; + end if; + end if; + + -- Timeout + elsif intReqCnt = x"FFFFFF" then + + -- Generate response + nxtState <= ST_RESP; + + -- No Fail, set timeout + nxtFail <= '0'; + nxtTout <= '1'; + + -- Keep waiting + else + nxtState <= curState; + nxtFail <= '0'; + nxtTout <= '0'; + end if; + + -- Set Bit Command + when ST_SET => + + -- No Response Request + respReq <= '0'; + + -- No external commands + nxtInp <= '1'; + nxtReq <= '0'; + nxtOp <= '0'; + + -- Disable FIFO Rd + rxFifoRdEn <= '0'; + + -- Set bits + nxtdata <= intData or intWrData; + + -- No errors + nxtFail <= '0'; + nxtTout <= '0'; + + -- Go to write state + -- Wait for ack from previous command to clear + if regAck = '0' then + nxtState <= ST_WRITE; + else + nxtState <= curState; + end if; + + -- Clear Bit Command + when ST_CLEAR => + + -- No Response Request + respReq <= '0'; + + -- No external commands + nxtInp <= '1'; + nxtReq <= '0'; + nxtOp <= '0'; + + -- Disable FIFO Rd + rxFifoRdEn <= '0'; + + -- Clear bits + nxtdata <= intData and (not intWrData); + + -- No errors + nxtFail <= '0'; + nxtTout <= '0'; + + -- Go to write state + -- Wait for ack from previous command to clear + if regAck = '0' then + nxtState <= ST_WRITE; + else + nxtState <= curState; + end if; + + -- Response + when ST_RESP => + + -- Response Request + respReq <= '1'; + + -- No external commands + nxtInp <= '0'; + nxtReq <= '0'; + nxtOp <= '0'; + + -- Disable FIFO Rd + rxFifoRdEn <= '0'; + + -- Keep Data + nxtdata <= intData; + + -- Keep errors + nxtFail <= intFail; + nxtTout <= intTout; + + -- Wait For Response Engine To Response + if respAckDly(1) = '1' then + nxtState <= ST_DONE; + else + nxtState <= curState; + end if; + + -- Done + when ST_DONE => + + -- Response Request + respReq <= '0'; + + -- No external commands + nxtInp <= '0'; + nxtReq <= '0'; + nxtOp <= '0'; + + -- Disable FIFO Rd + rxFifoRdEn <= '0'; + + -- Keep Data + nxtdata <= intData; + + -- Keep errors + nxtFail <= intFail; + nxtTout <= intTout; + + -- Wait For Response Engine To Respond + if respAckDly(1) = '0' then + nxtState <= ST_IDLE; + else + nxtState <= curState; + end if; + + when others => + respReq <= '0'; + nxtReq <= '0'; + nxtInp <= '0'; + nxtOp <= '0'; + rxFifoRdEn <= '0'; + nxtdata <= (others=>'0'); + nxtFail <= '0'; + nxtTout <= '0'; + nxtState <= ST_IDLE; + end case; + end process; + + + -- Response Data Engine. Runs on PGP clock not local clock. + -- Handshake lines are double synced before being acted upon. + -- Timing constraints must ensure that data moving between + -- clocks is less than the period of the faster clock. + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + respReqDly <= (others=>'0') after tpd; + respAck <= '0' after tpd; + respCnt <= (others=>'0') after tpd; + respValid <= '0' after tpd; + vcFrameTxSOF <= '0' after tpd; + vcFrameTxEOF <= '0' after tpd; + vcFrameTxData <= (others=>'0') after tpd; + elsif rising_edge(pgpClk) then + + -- Sync Response Req Lines + respReqDly(0) <= respReq after tpd; + respReqDly(1) <= respReqDly(0) after tpd; + + -- Response Counter + if respReqDly(1) = '0' then + respCnt <= (others=>'0') after tpd; + elsif respValid = '1' and vcFrameTxReady = '1' then + respCnt <= respCnt + 1 after tpd; + end if; + + -- Request is not asserted + if respReqDly(1) = '0' then + respValid <= '0' after tpd; + respAck <= '0' after tpd; + + -- Request is assert, valid is not assert, ack is not asserted, + -- wait for PGP to be ready. Assert grant and valid + elsif respValid = '0' and respAck = '0' and vcRemBuffAFull = '0' then + respValid <= '1' after tpd; + respAck <= '0' after tpd; + + -- Data movement on last value. Assert ack, de-assert valid + elsif vcFrameTxReady = '1' and respCnt = "111" then + respValid <= '0' after tpd; + respAck <= '1' after tpd; + end if; + + -- Initial Data + if respReqDly(1) = '0' then + vcFrameTxSOF <= '1' after tpd; + vcFrameTxEOF <= '0' after tpd; + vcFrameTxData(15 downto 8) <= intTid(7 downto 0) after tpd; + vcFrameTxData(7 downto 2) <= intDest after tpd; + vcFrameTxData(1 downto 0) <= intVc after tpd; + + -- Data Movement + elsif respValid = '1' and vcFrameTxReady = '1' then + case respCnt is + when "000" => + vcFrameTxSOF <= '0' after tpd; + vcFrameTxEOF <= '0' after tpd; + vcFrameTxData <= intTid(23 downto 8) after tpd; + when "001" => + vcFrameTxSOF <= '0' after tpd; + vcFrameTxEOF <= '0' after tpd; + vcFrameTxData <= intAddress(15 downto 0) after tpd; + when "010" => + vcFrameTxSOF <= '0' after tpd; + vcFrameTxEOF <= '0' after tpd; + vcFrameTxData(15 downto 14) <= intOpCode after tpd; + vcFrameTxData(13 downto 8) <= (others=>'0') after tpd; + vcFrameTxData(7 downto 0) <= intAddress(23 downto 16) after tpd; + when "011" => + vcFrameTxSOF <= '0' after tpd; + vcFrameTxEOF <= '0' after tpd; + vcFrameTxData <= intData(15 downto 0) after tpd; + when "100" => + vcFrameTxSOF <= '0' after tpd; + vcFrameTxEOF <= '0' after tpd; + vcFrameTxData <= intData(31 downto 16) after tpd; + when "101" => + vcFrameTxSOF <= '0' after tpd; + vcFrameTxEOF <= '0' after tpd; + vcFrameTxData <= (others=>'0') after tpd; + when "110" => + vcFrameTxSOF <= '0' after tpd; + vcFrameTxEOF <= '1' after tpd; + vcFrameTxData(15 downto 2) <= (others=>'0') after tpd; + vcFrameTxData(1) <= intTout after tpd; + vcFrameTxData(0) <= intFail after tpd; + when others => + vcFrameTxSOF <= '0' after tpd; + vcFrameTxEOF <= '0' after tpd; + vcFrameTxData <= (others=>'0') after tpd; + end case; + end if; + end if; + end process; + + -- Output to PGP + vcFrameTxValid <= respValid; + vcFrameTxEOFE <= '0'; + vcFrameTxCid <= (others=>'0'); + vcFrameTxWidth <= '1'; + +end PgpRegSlave; + diff --git a/rce/fw-hsio/modules/pgp/hdl/PgpRxTrack.vhd b/rce/fw-hsio/modules/pgp/hdl/PgpRxTrack.vhd new file mode 100755 index 00000000..507325d8 --- /dev/null +++ b/rce/fw-hsio/modules/pgp/hdl/PgpRxTrack.vhd @@ -0,0 +1,339 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, Receive Tracking Block +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : PgpRxTrack.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 10/24/2006 +------------------------------------------------------------------------------- +-- Description: +-- Receive Tracking logic module for the Pretty Good Protocol core. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 10/24/2006: created. +-- 04/18/2007: Added support to track the number of cells in a frame to detect +-- dropped cells. +-- 06/19/2007: Included PgpAckTx block to reduce file count. +-- 07/25/2007: In frame status of all VCs is now output. Cell CRC error changed +-- to cell rx error. +-- 09/18/2007: Changed code go generate abort flag if SOF is received while +-- the VC is in the in-frame state. This will cause the current VC +-- to receive EOF/EOFE combination. +-- 09/29/2007: Changed name of coregen blocks +-- 11/06/2007: Added cellRxShort flag to indicate to tracking logic that EOFE +-- was generated due to short cell. +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE work.ALL; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity PgpRxTrack is port ( + + -- System clock, reset & control + pgpClk : in std_logic; -- Master clock + pgpReset : in std_logic; -- Synchronous reset input + + -- PIB Interface + pibLinkReady : in std_logic; -- PIB Link Ready + + -- Error Indication + ackFifoFull : out std_logic; -- ACK FIFO is full + + -- Cell Receiver Block + cellRxSOF : in std_logic; -- Cell contained SOF + cellRxDataVc : in std_logic_vector(1 downto 0); -- Cell virtual channel + cellRxEOF : in std_logic; -- Cell contained EOF + cellRxEOFE : in std_logic; -- Cell contained EOFE + cellRxEmpty : in std_logic; -- Cell was empty + cellRxStart : in std_logic; -- Cell reception start + cellRxDone : in std_logic; -- Cell reception done + cellRxShort : in std_logic; -- Cell receieve is short (PIC Mode) + cellRxCellError : in std_logic; -- Cell receieve error + cellRxSeq : in std_logic_vector(7 downto 0); -- Cell receieve sequence + cellVcInFrame : out std_logic_vector(3 downto 0); -- Cell VC in frame status + cellVcAbort : out std_logic; -- Cell abort flag for current VC + + -- Cell Transmit Logic & schedular + cellTxNAck : out std_logic; -- Cell transmit NACK request + cellTxAck : out std_logic; -- Cell transmit ACK request + cellTxAckSeq : out std_logic_vector(7 downto 0); -- Cell transmit ACK sequence + cellTxAcked : in std_logic; -- Cell transmit ACK was sent + cellTxAckReq : out std_logic -- Cell transmit ACK request + ); + +end PgpRxTrack; + + +-- Define architecture +architecture PgpRxTrack of PgpRxTrack is + + -- ACK/NACK FIFO, 9 * 256 + component pgp_fifo_9x256 port ( + clk: IN std_logic; + rst: IN std_logic; + din: IN std_logic_VECTOR(8 downto 0); + wr_en: IN std_logic; + rd_en: IN std_logic; + dout: OUT std_logic_VECTOR(8 downto 0); + full: OUT std_logic; + empty: OUT std_logic + ); end component; + + -- Local Signals + signal vc0InFrame : std_logic; + signal vc0SeqNum : std_logic_vector(7 downto 0); + signal vc1InFrame : std_logic; + signal vc1SeqNum : std_logic_vector(7 downto 0); + signal vc2InFrame : std_logic; + signal vc2SeqNum : std_logic_vector(7 downto 0); + signal vc3InFrame : std_logic; + signal vc3SeqNum : std_logic_vector(7 downto 0); + signal muxInFrame : std_logic; + signal muxSeqNum : std_logic_vector(7 downto 0); + signal ackTxFifoDin : std_logic_vector(8 downto 0); + signal ackTxFifoDout : std_logic_vector(8 downto 0); + signal ackTxFifoWr : std_logic; + signal ackTxFifoRd : std_logic; + signal ackTxFifoRdDly : std_logic; + signal ackTxFifoFull : std_logic; + signal ackTxFifoEmpty : std_logic; + signal ackTxFifoRst : std_logic; + signal intCellTxAckReq : std_logic; + signal frameRxSeq : std_logic_vector(7 downto 0); + signal frameRxAck : std_logic; + signal frameRxNAck : std_logic; + signal intAbort : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + + -- Black Box Attributes + attribute syn_black_box : boolean; + attribute syn_noprune : boolean; + attribute syn_black_box of pgp_fifo_9x256 : component is TRUE; + attribute syn_noprune of pgp_fifo_9x256 : component is TRUE; + +begin + + -- VC In frame status output + cellVcInFrame(0) <= vc0InFrame; + cellVcInFrame(1) <= vc1InFrame; + cellVcInFrame(2) <= vc2InFrame; + cellVcInFrame(3) <= vc3InFrame; + cellVcAbort <= intAbort; + + + -- Mux current VC values + process ( cellRxDataVc, vc0InFrame, vc0SeqNum, vc1InFrame, vc1SeqNum, + vc2InFrame, vc2SeqNum, vc3InFrame, vc3SeqNum ) begin + case cellRxDataVc is + when "00" => + muxInFrame <= vc0InFrame; + muxSeqNum <= vc0SeqNum; + when "01" => + muxInFrame <= vc1InFrame; + muxSeqNum <= vc1SeqNum; + when "10" => + muxInFrame <= vc2InFrame; + muxSeqNum <= vc2SeqNum; + when "11" => + muxInFrame <= vc3InFrame; + muxSeqNum <= vc3SeqNum; + when others => + muxInFrame <= '0'; + muxSeqNum <= (others=>'0'); + end case; + end process; + + + -- Drive current status back to cell receive engine + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + frameRxSeq <= (others=>'0') after tpd; + frameRxAck <= '0' after tpd; + frameRxNAck <= '0' after tpd; + vc0InFrame <= '0' after tpd; + vc0SeqNum <= (others=>'0') after tpd; + vc1InFrame <= '0' after tpd; + vc1SeqNum <= (others=>'0') after tpd; + vc2InFrame <= '0' after tpd; + vc2SeqNum <= (others=>'0') after tpd; + vc3InFrame <= '0' after tpd; + vc3SeqNum <= (others=>'0') after tpd; + intAbort <= '0' after tpd; + elsif rising_edge(pgpClk) then + + -- Link is down, reset status of all VCs + if pibLinkReady = '0' then + vc0InFrame <= '0' after tpd; + vc0SeqNum <= (others=>'0') after tpd; + vc1InFrame <= '0' after tpd; + vc1SeqNum <= (others=>'0') after tpd; + vc2InFrame <= '0' after tpd; + vc2SeqNum <= (others=>'0') after tpd; + vc3InFrame <= '0' after tpd; + vc3SeqNum <= (others=>'0') after tpd; + intAbort <= '0' after tpd; + frameRxAck <= '0' after tpd; + frameRxNAck <= '0' after tpd; + + -- Start of cell, + elsif cellRxStart = '1' then + + -- Detect missing EOF this occurs when + -- we get SOF when we are already in frame + -- Generate NACK for previous sequence number + -- Generate abort signal + if muxInFrame = '1' and cellRxSOF = '1' then + frameRxSeq <= muxSeqNum after tpd; + frameRxAck <= '0' after tpd; + frameRxNAck <= '1' after tpd; + intAbort <= '1' after tpd; + else + frameRxSeq <= (others=>'0') after tpd; + frameRxAck <= '0' after tpd; + frameRxNAck <= '0' after tpd; + intAbort <= '0' after tpd; + end if; + + -- Cell contains start of frame and is not empty + if cellRxSOF = '1' and cellRxEmpty = '0' then + + -- Mark current VC as in frame if in frame flag is not already set. + -- If flag is already set then an error occured and we should to to + -- out of frame state + case cellRxDataVc is + when "00" => + vc0InFrame <= '1' after tpd; + vc0SeqNum <= cellRxSeq after tpd; + when "01" => + vc1InFrame <= '1' after tpd; + vc1SeqNum <= cellRxSeq after tpd; + when "10" => + vc2InFrame <= '1' after tpd; + vc2SeqNum <= cellRxSeq after tpd; + when "11" => + vc3InFrame <= '1' after tpd; + vc3SeqNum <= cellRxSeq after tpd; + when others => + end case; + end if; + + -- End of cell + elsif cellRxDone = '1' then + + -- Clear abort + intAbort <= '0' after tpd; + + -- Cell is in error, mark all VCs as not in frame + if cellRxCellError = '1' then + vc0InFrame <= '0' after tpd; + vc1InFrame <= '0' after tpd; + vc2InFrame <= '0' after tpd; + vc3InFrame <= '0' after tpd; + + -- EOF is received + elsif cellRxEOF = '1' and cellRxEmpty = '0' then + + -- Drive ack/nack only if cell was not short. + -- This is to avoid sending back a nack to the + -- remote end before it is expected. + if cellRxShort = '0' then + + -- Drive ACK/NACK update for one clock. This will handle + -- A NACK for current cell. If others cells are errored + -- out their nack will be handled by the timeout. + frameRxSeq <= muxSeqNum after tpd; + frameRxAck <= not cellRxEOFE after tpd; + frameRxNAck <= cellRxEOFE after tpd; + else + frameRxAck <= '0' after tpd; + frameRxNAck <= '0' after tpd; + end if; + + -- Clear in frame status for current vc + case cellRxDataVc is + when "00" => vc0InFrame <= '0' after tpd; + when "01" => vc1InFrame <= '0' after tpd; + when "10" => vc2InFrame <= '0' after tpd; + when "11" => vc3InFrame <= '0' after tpd; + when others => + end case; + + -- Non EOF frame + else + + -- Clear ACK/NACK drive + frameRxAck <= '0' after tpd; + frameRxNAck <= '0' after tpd; + end if; + + -- Clear Ack/NACK drive + else + frameRxAck <= '0' after tpd; + frameRxNAck <= '0' after tpd; + end if; + end if; + end process; + + + -- Connect external signals + ackFifoFull <= ackTxFifoFull; + cellTxAckReq <= intCellTxAckReq; + + -- Control reads from FIFO + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + cellTxNAck <= '0' after tpd; + cellTxAck <= '0' after tpd; + cellTxAckSeq <= (others=>'0') after tpd; + intCellTxAckReq <= '0' after tpd; + ackTxFifoRdDly <= '0' after tpd; + elsif rising_edge(pgpClk) then + + -- Delayed copy of FIFO read + ackTxFifoRdDly <= ackTxFifoRd after tpd; + + -- Link has gone down or cell transmitter has acked + if pibLinkReady = '0' or cellTxAcked = '1' then + cellTxNAck <= '0' after tpd; + cellTxAck <= '0' after tpd; + cellTxAckSeq <= (others=>'0') after tpd; + intCellTxAckReq <= '0' after tpd; + + -- New value has been read + elsif ackTxFifoRdDly = '1' then + cellTxNAck <= not ackTxFifoDout(8) after tpd; + cellTxAck <= ackTxFifoDout(8) after tpd; + cellTxAckSeq <= ackTxFifoDout(7 downto 0) after tpd; + intCellTxAckReq <= '1' after tpd; + end if; + end if; + end process; + + -- Generate read signal + ackTxFifoRd <= not intCellTxAckReq and not ackTxFifoEmpty and not ackTxFifoRdDly; + + -- Generate FIFO reset + ackTxFifoRst <= pgpReset or not pibLinkReady; + + -- Control write signals + ackTxFifoWr <= frameRxAck or frameRxNAck; + ackTxFifoDin(8) <= frameRxAck; + ackTxFifoDin(7 downto 0) <= frameRxSeq; + + -- Sequence number FIFO + U_AckTxFifo : pgp_fifo_9x256 port map ( + clk => pgpClk, rst => ackTxFifoRst, + din => ackTxFifoDin, wr_en => ackTxFifoWr, + rd_en => ackTxFifoRd, dout => ackTxFifoDout, + full => ackTxFifoFull, empty => ackTxFifoEmpty + ); + +end PgpRxTrack; + diff --git a/rce/fw-hsio/modules/pgp/hdl/PgpTop.vhd b/rce/fw-hsio/modules/pgp/hdl/PgpTop.vhd new file mode 100755 index 00000000..f92d154a --- /dev/null +++ b/rce/fw-hsio/modules/pgp/hdl/PgpTop.vhd @@ -0,0 +1,714 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, Top Level Module +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : PgpTop.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 10/24/2006 +------------------------------------------------------------------------------- +-- Description: +-- Top level VHDL source file for Pretty Good Protocol core. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 10/24/2006: created. +-- 04/18/2007: Added support to track the number of cells in a frame to detect +-- dropped cells. +-- 04/19/2007: Added link ready flag to cell receiver +-- 05/30/2007: Added lock bits and inverted flag outputs. +-- 05/31/2007: Removed lock bits +-- 06/08/2007: Added lock bits +-- 06/19/2007: Removed PgpRandData, PpgAckTx, PgpErrorCount blocks +-- 07/19/2007: Removed cellTxCount +-- 08/25/2007: Changed error count signals. +-- 09/18/2007: Added forceCellSize signal to make sure all outgoing cells are +-- 512 bytes unless they are the last in a frame. +-- 09/19/2007: Changed force cell size signal to PIC mode signal +-- 09/21/2007: Ack timeout & Pic Mode converted to generics. +-- 09/21/2007: Removed payload imput +-- 11/06/2007: Added cellRxShort flag to indicate to tracking logic that EOFE +-- was generated due to short cell. +-- 11/05/2008: Removed chipscope. Removed rx/tx pll and reset logic. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use work.PgpVersion.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity PgpTop is + generic ( + AckTimeout : natural := 8; -- Ack/Nack Not Received Timeout, 8.192uS Steps + PicMode : natural := 0 -- PIC Interface Mode, 1=PIC, 0=Normal + ); + port ( + + -- System clock, reset & control + pgpClk : in std_logic; -- Master clock + pgpReset : in std_logic; -- Synchronous reset input + pibReLink : in std_logic; -- Re-Link control signal + + -- Frame Transmit Interface, VC 0 + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc0FrameTxReady : out std_logic; -- PGP is ready + vc0FrameTxSOF : in std_logic; -- User frame data start of frame + vc0FrameTxWidth : in std_logic; -- User frame data width + vc0FrameTxEOF : in std_logic; -- User frame data end of frame + vc0FrameTxEOFE : in std_logic; -- User frame data end of frame error + vc0FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc0FrameTxCid : in std_logic_vector(31 downto 0); -- User frame data, context ID + vc0FrameTxAckCid : out std_logic_vector(31 downto 0); -- PGP ACK/NACK context ID + vc0FrameTxAckEn : out std_logic; -- PGP ACK/NACK enable + vc0FrameTxAck : out std_logic; -- PGP ACK/NACK + vc0RemBuffAFull : out std_logic; -- Remote buffer almost full + vc0RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 1 + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxReady : out std_logic; -- PGP is ready + vc1FrameTxSOF : in std_logic; -- User frame data start of frame + vc1FrameTxWidth : in std_logic; -- User frame data width + vc1FrameTxEOF : in std_logic; -- User frame data end of frame + vc1FrameTxEOFE : in std_logic; -- User frame data end of frame error + vc1FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc1FrameTxCid : in std_logic_vector(31 downto 0); -- User frame data, context ID + vc1FrameTxAckCid : out std_logic_vector(31 downto 0); -- PGP ACK/NACK context ID + vc1FrameTxAckEn : out std_logic; -- PGP ACK/NACK enable + vc1FrameTxAck : out std_logic; -- PGP ACK/NACK + vc1RemBuffAFull : out std_logic; -- Remote buffer almost full + vc1RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 2 + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxReady : out std_logic; -- PGP is ready + vc2FrameTxSOF : in std_logic; -- User frame data start of frame + vc2FrameTxWidth : in std_logic; -- User frame data width + vc2FrameTxEOF : in std_logic; -- User frame data end of frame + vc2FrameTxEOFE : in std_logic; -- User frame data end of frame error + vc2FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc2FrameTxCid : in std_logic_vector(31 downto 0); -- User frame data, context ID + vc2FrameTxAckCid : out std_logic_vector(31 downto 0); -- PGP ACK/NACK context ID + vc2FrameTxAckEn : out std_logic; -- PGP ACK/NACK enable + vc2FrameTxAck : out std_logic; -- PGP ACK/NACK + vc2RemBuffAFull : out std_logic; -- Remote buffer almost full + vc2RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 3 + vc3FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxReady : out std_logic; -- PGP is ready + vc3FrameTxSOF : in std_logic; -- User frame data start of frame + vc3FrameTxWidth : in std_logic; -- User frame data width + vc3FrameTxEOF : in std_logic; -- User frame data end of frame + vc3FrameTxEOFE : in std_logic; -- User frame data end of frame error + vc3FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc3FrameTxCid : in std_logic_vector(31 downto 0); -- User frame data, context ID + vc3FrameTxAckCid : out std_logic_vector(31 downto 0); -- PGP ACK/NACK context ID + vc3FrameTxAckEn : out std_logic; -- PGP ACK/NACK enable + vc3FrameTxAck : out std_logic; -- PGP ACK/NACK + vc3RemBuffAFull : out std_logic; -- Remote buffer almost full + vc3RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 0 + vc0FrameRxValid : out std_logic; -- PGP frame data is valid + vc0FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc0FrameRxWidth : out std_logic; -- PGP frame data width + vc0FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc0FrameRxEOFE : out std_logic; -- PGP frame data end of frame error + vc0FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc0LocBuffAFull : in std_logic; -- Local buffer almost full + vc0LocBuffFull : in std_logic; -- Local buffer full + + -- Frame Receive Interface, VC 1 + vc1FrameRxValid : out std_logic; -- PGP frame data is valid + vc1FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc1FrameRxWidth : out std_logic; -- PGP frame data width + vc1FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc1FrameRxEOFE : out std_logic; -- PGP frame data end of frame error + vc1FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc1LocBuffAFull : in std_logic; -- Local buffer almost full + vc1LocBuffFull : in std_logic; -- Local buffer full + + -- Frame Receive Interface, VC 2 + vc2FrameRxValid : out std_logic; -- PGP frame data is valid + vc2FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc2FrameRxWidth : out std_logic; -- PGP frame data width + vc2FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc2FrameRxEOFE : out std_logic; -- PGP frame data end of frame error + vc2FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc2LocBuffAFull : in std_logic; -- Local buffer almost full + vc2LocBuffFull : in std_logic; -- Local buffer full + + -- Frame Receive Interface, VC 3 + vc3FrameRxValid : out std_logic; -- PGP frame data is valid + vc3FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc3FrameRxWidth : out std_logic; -- PGP frame data width + vc3FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc3FrameRxEOFE : out std_logic; -- PGP frame data end of frame error + vc3FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc3LocBuffAFull : in std_logic; -- Local buffer almost full + vc3LocBuffFull : in std_logic; -- Local buffer full + + -- Transmit CRC Interface + crcTxIn : out std_logic_vector(15 downto 0); -- Transmit data for CRC + crcTxInit : out std_logic; -- Transmit CRC value init + crcTxValid : out std_logic; -- Transmit data for CRC is valid + crcTxWidth : out std_logic; -- Transmit data for CRC width + crcTxOut : in std_logic_vector(31 downto 0); -- Transmit calculated CRC value + + -- Receive CRC Interface + crcRxIn : out std_logic_vector(15 downto 0); -- Receive data for CRC + crcRxInit : out std_logic; -- Receive CRC value init + crcRxValid : out std_logic; -- Receive data for CRC is valid + crcRxWidth : out std_logic; -- Receive data for CRC width + crcRxOut : in std_logic_vector(31 downto 0); -- Receive calculated CRC value + + -- Physical Interface Signals + phyRxPolarity : out std_logic; -- PHY receive signal polarity + phyRxData : in std_logic_vector(15 downto 0); -- PHY receive data + phyRxDataK : in std_logic_vector(1 downto 0); -- PHY receive data is K character + phyTxData : out std_logic_vector(15 downto 0); -- PHY transmit data + phyTxDataK : out std_logic_vector(1 downto 0); -- PHY transmit data is K character + phyLinkError : in std_logic; -- PHY 8B10B or disparity error + phyInitDone : in std_logic; -- PHY init is done + + -- Event Counters & Status Signals + localVersion : out std_logic_vector(7 downto 0); -- Local version ID + remoteVersion : out std_logic_vector(7 downto 0); -- Remote version ID + pibFail : out std_logic; -- PIB fail indication + pibState : out std_logic_vector(2 downto 0); -- PIB State + pibLinkReady : out std_logic; -- PIB link is ready + pgpSeqError : out std_logic; -- PGP Sequence Logic Error Occured + countLinkDown : out std_logic; -- Link down count increment + countLinkError : out std_logic; -- Disparity/Decode error count + countNack : out std_logic; -- NACK count increment + countCellError : out std_logic -- Receive Cell error count + ); + +end PgpTop; + + +-- Define architecture +architecture PgpTop of PgpTop is + + -- ACK/NACK Receiver Logic + component PgpAckRx + generic ( + AckTimeout : natural := 8 -- Ack/Nack Not Received Timeout, 8.192uS Steps + ); + port ( + pgpClk : in std_logic; -- Master clock + pgpReset : in std_logic; -- Synchronous reset input + pibLinkReady : in std_logic; -- PIB Link Ready + seqFifoEmpty : out std_logic; -- Sequence number fifo is empty + nackCountInc : out std_logic; -- Nack received count increment + cellRxDone : in std_logic; -- Cell reception done + cellRxCellError : in std_logic; -- Cell receieve error + cellRxSeq : in std_logic_vector(7 downto 0); -- Cell receieve sequence + cellRxAck : in std_logic; -- Cell receieve ACK + cellRxNAck : in std_logic; -- Cell receieve NACK + cidReady : out std_logic; -- CID Engine is ready + cidTimerStart : in std_logic; -- CID timer start + cellTxDataVc : in std_logic_vector(1 downto 0); -- Cell transmit virtual channel + cidSave : in std_logic; -- CID value store signal + cellTxSOF : in std_logic; -- Cell contained SOF + cellTxDataSeq : out std_logic_vector(7 downto 0); -- Transmit sequence number + vc0FrameTxCid : in std_logic_vector(31 downto 0); -- User frame data, context ID + vc0FrameTxAckCid : out std_logic_vector(31 downto 0); -- PGP ACK/NACK context ID + vc0FrameTxAckEn : out std_logic; -- PGP ACK/NACK enable + vc0FrameTxAck : out std_logic; -- PGP ACK/NACK + vc1FrameTxCid : in std_logic_vector(31 downto 0); -- User frame data, context ID + vc1FrameTxAckCid : out std_logic_vector(31 downto 0); -- PGP ACK/NACK context ID + vc1FrameTxAckEn : out std_logic; -- PGP ACK/NACK enable + vc1FrameTxAck : out std_logic; -- PGP ACK/NACK + vc2FrameTxCid : in std_logic_vector(31 downto 0); -- User frame data, context ID + vc2FrameTxAckCid : out std_logic_vector(31 downto 0); -- PGP ACK/NACK context ID + vc2FrameTxAckEn : out std_logic; -- PGP ACK/NACK enable + vc2FrameTxAck : out std_logic; -- PGP ACK/NACK + vc3FrameTxCid : in std_logic_vector(31 downto 0); -- User frame data, context ID + vc3FrameTxAckCid : out std_logic_vector(31 downto 0); -- PGP ACK/NACK context ID + vc3FrameTxAckEn : out std_logic; -- PGP ACK/NACK enable + vc3FrameTxAck : out std_logic -- PGP ACK/NACK + ); + end component; + + + -- Cell Receiver Logic + component PgpCellRx + generic ( + PicMode : natural := 0 -- PIC Interface Mode, 1=PIC, 0=Normal + ); + port ( + pgpClk : in std_logic; -- Master clock + pgpReset : in std_logic; -- Synchronous reset input + pibLinkReady : in std_logic; -- PIB Link Ready + cellRxSOF : out std_logic; -- Cell contained SOF + cellRxDataVc : out std_logic_vector(1 downto 0); -- Cell virtual channel + cellRxEOF : out std_logic; -- Cell contained EOF + cellRxEOFE : out std_logic; -- Cell contained EOFE + cellRxEmpty : out std_logic; -- Cell was empty + cellVcInFrame : in std_logic_vector(3 downto 0); -- Cell VC in frame status + cellVcAbort : in std_logic; -- Cell abort flag for current VC + cellRxDone : out std_logic; -- Cell reception done + cellRxShort : out std_logic; -- Cell receieve is short (PIC Mode) + cellRxStart : out std_logic; -- Cell reception start + cellRxCellError : out std_logic; -- Cell receieve CRC error + cellRxSeq : out std_logic_vector(7 downto 0); -- Cell receieve sequence + cellRxAck : out std_logic; -- Cell receieve ACK + cellRxNAck : out std_logic; -- Cell receieve NACK + vc0FrameRxValid : out std_logic; -- PGP frame data is valid + vc0FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc0FrameRxWidth : out std_logic; -- PGP frame data width + vc0FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc0FrameRxEOFE : out std_logic; -- PGP frame data error + vc0FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc0RemBuffAFull : out std_logic; -- Remote buffer almost full + vc0RemBuffFull : out std_logic; -- Remote buffer full + vc1FrameRxValid : out std_logic; -- PGP frame data is valid + vc1FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc1FrameRxWidth : out std_logic; -- PGP frame data width + vc1FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc1FrameRxEOFE : out std_logic; -- PGP frame data error + vc1FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc1RemBuffAFull : out std_logic; -- Remote buffer almost full + vc1RemBuffFull : out std_logic; -- Remote buffer full + vc2FrameRxValid : out std_logic; -- PGP frame data is valid + vc2FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc2FrameRxWidth : out std_logic; -- PGP frame data width + vc2FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc2FrameRxEOFE : out std_logic; -- PGP frame data error + vc2FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc2RemBuffAFull : out std_logic; -- Remote buffer almost full + vc2RemBuffFull : out std_logic; -- Remote buffer full + vc3FrameRxValid : out std_logic; -- PGP frame data is valid + vc3FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc3FrameRxWidth : out std_logic; -- PGP frame data width + vc3FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc3FrameRxEOFE : out std_logic; -- PGP frame data error + vc3FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc3RemBuffAFull : out std_logic; -- Remote buffer almost full + vc3RemBuffFull : out std_logic; -- Remote buffer full + crcRxIn : out std_logic_vector(15 downto 0); -- Receive data for CRC + crcRxInit : out std_logic; -- Receive CRC value init + crcRxValid : out std_logic; -- Receive data for CRC is valid + crcRxWidth : out std_logic; -- Receive data for CRC width + crcRxOut : in std_logic_vector(31 downto 0); -- Receive calculated CRC value + pibRxSOC : in std_logic; -- Cell data start of cell + pibRxWidth : in std_logic; -- Cell data width + pibRxEOC : in std_logic; -- Cell data end of cell + pibRxEOF : in std_logic; -- Cell data end of frame + pibRxEOFE : in std_logic; -- Cell data end of frame error + pibRxData : in std_logic_vector(15 downto 0) -- Cell data data + ); + end component; + + -- Cell Transmit Logic + component PgpCellTx + port ( + pgpClk : in std_logic; -- Master clock + pgpReset : in std_logic; -- Synchronous reset input + pibLinkReady : in std_logic; -- PIB Link Ready + cellTxDataSeq : in std_logic_vector(7 downto 0); -- Transmit sequence number + cellTxSOF : out std_logic; -- Cell contained SOF + cellTxEOF : out std_logic; -- Cell contained EOF + cellTxIdle : in std_logic; -- Force IDLE transmit + cellTxReq : in std_logic; -- Cell transmit request + cellTxInp : out std_logic; -- Cell transmit in progress + cellTxDataVc : in std_logic_vector(1 downto 0); -- Cell transmit virtual channel + cellTxNAck : in std_logic; -- Cell transmit NACK request + cellTxAck : in std_logic; -- Cell transmit ACK request + cellTxAckSeq : in std_logic_vector(7 downto 0); -- Cell transmit ACK sequence + cellTxAcked : out std_logic; -- Cell transmit ACK was sent + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc0FrameTxReady : out std_logic; -- PGP is ready + vc0FrameTxSOF : in std_logic; -- User frame data start of frame + vc0FrameTxWidth : in std_logic; -- User frame data width + vc0FrameTxEOF : in std_logic; -- User frame data end of frame + vc0FrameTxEOFE : in std_logic; -- User frame data error + vc0FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc0LocBuffAFull : in std_logic; -- Local buffer almost full + vc0LocBuffFull : in std_logic; -- Local buffer full + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxReady : out std_logic; -- PGP is ready + vc1FrameTxSOF : in std_logic; -- User frame data start of frame + vc1FrameTxWidth : in std_logic; -- User frame data width + vc1FrameTxEOF : in std_logic; -- User frame data end of frame + vc1FrameTxEOFE : in std_logic; -- User frame data error + vc1FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc1LocBuffAFull : in std_logic; -- Local buffer almost full + vc1LocBuffFull : in std_logic; -- Local buffer full + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxReady : out std_logic; -- PGP is ready + vc2FrameTxSOF : in std_logic; -- User frame data start of frame + vc2FrameTxWidth : in std_logic; -- User frame data width + vc2FrameTxEOF : in std_logic; -- User frame data end of frame + vc2FrameTxEOFE : in std_logic; -- User frame data error + vc2FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc2LocBuffAFull : in std_logic; -- Local buffer almost full + vc2LocBuffFull : in std_logic; -- Local buffer full + vc3FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxReady : out std_logic; -- PGP is ready + vc3FrameTxSOF : in std_logic; -- User frame data start of frame + vc3FrameTxWidth : in std_logic; -- User frame data width + vc3FrameTxEOF : in std_logic; -- User frame data end of frame + vc3FrameTxEOFE : in std_logic; -- User frame data error + vc3FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc3LocBuffAFull : in std_logic; -- Local buffer almost full + vc3LocBuffFull : in std_logic; -- Local buffer full + pibTxSOC : out std_logic; -- Cell data start of cell + pibTxWidth : out std_logic; -- Cell data width + pibTxEOC : out std_logic; -- Cell data end of cell + pibTxEOF : out std_logic; -- Cell data end of frame + pibTxEOFE : out std_logic; -- Cell data end of frame error + pibTxData : out std_logic_vector(15 downto 0); -- Cell data data + crcTxIn : out std_logic_vector(15 downto 0); -- Transmit data for CRC + crcTxInit : out std_logic; -- Transmit CRC value init + crcTxValid : out std_logic; -- Transmit data for CRC is valid + crcTxWidth : out std_logic; -- Transmit data for CRC width + crcTxOut : in std_logic_vector(31 downto 0) -- Transmit calculated CRC value + ); + end component; + + + -- Physical Interface Block + component PgpPhy + port ( + pgpClk : in std_logic; -- Master clock + pgpReset : in std_logic; -- Synchronous reset input + pibReLink : in std_logic; -- Re-Link control signal + localVersion : in std_logic_vector(7 downto 0); -- Local version ID + remoteVersion : out std_logic_vector(7 downto 0); -- Remote version ID + pibFail : out std_logic; -- PIB fail indication + pibLinkReady : out std_logic; -- PIB link is ready + pibState : out std_logic_vector(2 downto 0); -- PIB State + pibTxSOC : in std_logic; -- Cell data start of cell + pibTxWidth : in std_logic; -- Cell data width + pibTxEOC : in std_logic; -- Cell data end of cell + pibTxEOF : in std_logic; -- Cell data end of frame + pibTxEOFE : in std_logic; -- Cell data end of frame error + pibTxData : in std_logic_vector(15 downto 0); -- Cell data data + pibRxSOC : out std_logic; -- Cell data start of cell + pibRxWidth : out std_logic; -- Cell data width + pibRxEOC : out std_logic; -- Cell data end of cell + pibRxEOF : out std_logic; -- Cell data end of frame + pibRxEOFE : out std_logic; -- Cell data end of frame error + pibRxData : out std_logic_vector(15 downto 0); -- Cell data data + phyRxPolarity : out std_logic; -- PHY receive signal polarity + phyRxData : in std_logic_vector(15 downto 0); -- PHY receive data + phyRxDataK : in std_logic_vector(1 downto 0); -- PHY receive data is K char + phyTxData : out std_logic_vector(15 downto 0); -- PHY transmit data + phyTxDataK : out std_logic_vector(1 downto 0); -- PHY transmit data is K char + phyInitDone : in std_logic -- PHY init is done + ); + end component; + + -- Receiver Tracking Logic + component PgpRxTrack + port ( + pgpClk : in std_logic; -- Master clock + pgpReset : in std_logic; -- Synchronous reset input + pibLinkReady : in std_logic; -- PIB Link Ready + ackFifoFull : out std_logic; -- ACK FIFO is full + cellRxSOF : in std_logic; -- Cell contained SOF + cellRxDataVc : in std_logic_vector(1 downto 0); -- Cell virtual channel + cellRxEOF : in std_logic; -- Cell contained EOF + cellRxEOFE : in std_logic; -- Cell contained EOFE + cellRxEmpty : in std_logic; -- Cell was empty + cellRxDone : in std_logic; -- Cell reception done + cellRxShort : in std_logic; -- Cell receieve is short (PIC Mode) + cellRxStart : in std_logic; -- Cell reception start + cellRxCellError : in std_logic; -- Cell receieve error + cellRxSeq : in std_logic_vector(7 downto 0); -- Cell receieve sequence + cellVcInFrame : out std_logic_vector(3 downto 0); -- Cell VC in frame status + cellVcAbort : out std_logic; -- Cell abort flag for current VC + cellTxNAck : out std_logic; -- Cell transmit NACK request + cellTxAck : out std_logic; -- Cell transmit ACK request + cellTxAckSeq : out std_logic_vector(7 downto 0); -- Cell transmit ACK sequence + cellTxAcked : in std_logic; -- Cell transmit ACK was sent + cellTxAckReq : out std_logic -- Cell transmit ACK request + ); + end component; + + -- Transmit Schedular + component PgpTxSched + port ( + pgpClk : in std_logic; -- Master clock + pgpReset : in std_logic; -- Synchronous reset input + pibLinkReady : in std_logic; -- PIB Link Ready + cidReady : in std_logic; -- CID Engine is ready + cidTimerStart : out std_logic; -- CID timer start + cidSave : out std_logic; -- CID value store signal + cellTxAckReq : in std_logic; -- Cell ACK/NACK transmit request + cellTxSOF : in std_logic; -- Cell contained SOF + cellTxEOF : in std_logic; -- Cell contained EOF + cellTxIdle : out std_logic; -- Force IDLE transmit + cellTxReq : out std_logic; -- Cell transmit request + cellTxInp : in std_logic; -- Cell transmit in progress + cellTxDataVc : out std_logic_vector(1 downto 0); -- Cell transmit virtual channel + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxValid : in std_logic -- User frame data is valid + ); + end component; + + + -- Local Signals + signal intLinkReady : std_logic; -- PIB Link Ready + signal seqFifoEmpty : std_logic; -- Sequence number fifo is empty + signal nackCountInc : std_logic; -- Nack received count increment + signal cellRxDone : std_logic; -- Cell reception done + signal cellRxShort : std_logic; -- Cell receieve is short (PIC Mode) + signal cellRxStart : std_logic; -- Cell reception start + signal cellRxCellError : std_logic; -- Cell receieve CRC error + signal cellVcInFrame : std_logic_vector(3 downto 0); -- Cell VC in frame status + signal cellVcAbort : std_logic; -- Cell VC abort control + signal cellRxSeq : std_logic_vector(7 downto 0); -- Cell receieve sequence + signal cellRxAck : std_logic; -- Cell receieve ACK + signal cellRxNAck : std_logic; -- Cell receieve NACK + signal cidTimerStart : std_logic; -- CID timer start + signal cidReady : std_logic; -- Sequence FIFO ready + signal cidSave : std_logic; -- CID save for later + signal ackFifoFull : std_logic; -- ACK FIFO is full + signal cellTxNAck : std_logic; -- Cell transmit NACK request + signal cellTxAck : std_logic; -- Cell transmit ACK request + signal cellTxAckSeq : std_logic_vector(7 downto 0); -- Cell transmit ACK sequence + signal cellTxAcked : std_logic; -- Cell transmit ACK was sent + signal cellTxAckReq : std_logic; -- Cell transmit ACK request + signal cellRxSOF : std_logic; -- Cell contained SOF + signal cellRxDataVc : std_logic_vector(1 downto 0); -- Cell virtual channel + signal cellRxEOF : std_logic; -- Cell contained EOF + signal cellRxEOFE : std_logic; -- Cell contained EOFE + signal cellRxEmpty : std_logic; -- Cell was empty + signal pibRxSOC : std_logic; -- Cell data start of cell + signal pibRxWidth : std_logic; -- Cell data width + signal pibRxEOC : std_logic; -- Cell data end of cell + signal pibRxEOF : std_logic; -- Cell data end of frame + signal pibRxEOFE : std_logic; -- Cell data end of frame error + signal pibRxData : std_logic_vector(15 downto 0); -- Cell data data + signal cellTxDataSeq : std_logic_vector(7 downto 0); -- Transmit sequence number + signal cellTxSOF : std_logic; -- Cell contained SOF + signal cellTxEOF : std_logic; -- Cell contained EOF + signal cellTxIdle : std_logic; -- Force IDLE transmit + signal cellTxReq : std_logic; -- Cell transmit request + signal cellTxInp : std_logic; -- Cell transmit in progress + signal cellTxDataVc : std_logic_vector(1 downto 0); -- Cell transmit virtual channel + signal pibTxSOC : std_logic; -- Cell data start of cell + signal pibTxWidth : std_logic; -- Cell data width + signal pibTxEOC : std_logic; -- Cell data end of cell + signal pibTxEOF : std_logic; -- Cell data end of frame + signal pibTxEOFE : std_logic; -- Cell data end of frame error + signal pibTxData : std_logic_vector(15 downto 0); -- Cell data data + signal intVersion : std_logic_vector(7 downto 0); -- Local version ID + signal phyLinkErrorDly : std_logic; -- Delayed copy of PIB link error + signal nackCountIncDly : std_logic; -- Delayed copy of nack counter + signal cellRxCellErrorDly : std_logic; -- Delayed copy of error + signal linkDownBlock : std_logic_vector(7 downto 0); -- Delayed copy of link ready signal + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + + -- Set version value + intVersion <= work.pgpVersion.PgpVersion; + + -- Version & Link Failure + localVersion <= intVersion; + pibLinkReady <= intLinkReady; + + + -- ACK/NACK Receive Logic + U_PgpAckRx: PgpAckRx generic map ( AckTimeout => AckTimeout ) port map ( + pgpClk => pgpClk, pgpReset => pgpReset, + pibLinkReady => intLinkReady, seqFifoEmpty => seqFifoEmpty, + nackCountInc => nackCountInc, cellRxDone => cellRxDone, + cellRxCellError => cellRxCellError, cellRxSeq => cellRxSeq, + cellRxAck => cellRxAck, cellRxNAck => cellRxNAck, + cidReady => cidReady, cellTxDataSeq => cellTxDataSeq, + cellTxSOF => cellTxSOF, cidTimerStart => cidTimerStart, + cellTxDataVc => cellTxDataVc, cidSave => cidSave, + vc0FrameTxCid => vc0FrameTxCid, vc1FrameTxCid => vc1FrameTxCid, + vc2FrameTxCid => vc2FrameTxCid, vc3FrameTxCid => vc3FrameTxCid, + vc0FrameTxAckCid => vc0FrameTxAckCid, vc0FrameTxAckEn => vc0FrameTxAckEn, + vc0FrameTxAck => vc0FrameTxAck, vc1FrameTxAckCid => vc1FrameTxAckCid, + vc1FrameTxAckEn => vc1FrameTxAckEn, vc1FrameTxAck => vc1FrameTxAck, + vc2FrameTxAckCid => vc2FrameTxAckCid, vc2FrameTxAckEn => vc2FrameTxAckEn, + vc2FrameTxAck => vc2FrameTxAck, vc3FrameTxAckCid => vc3FrameTxAckCid, + vc3FrameTxAckEn => vc3FrameTxAckEn, vc3FrameTxAck => vc3FrameTxAck + ); + + -- Cell Receiver Logic + U_PgpCellRx: PgpCellRx generic map ( PicMode => PicMode ) port map ( + pgpClk => pgpClk, pgpReset => pgpReset, + cellRxSOF => cellRxSOF, cellRxDataVc => cellRxDataVc, + cellRxEOF => cellRxEOF, cellRxEOFE => cellRxEOFE, + cellRxEmpty => cellRxEmpty, cellVcInFrame => cellVcInFrame, + cellRxDone => cellRxDone, cellRxCellError => cellRxCellError, + cellRxSeq => cellRxSeq, cellRxAck => cellRxAck, + cellRxNAck => cellRxNAck, vc0FrameRxValid => vc0FrameRxValid, + vc0FrameRxSOF => vc0FrameRxSOF, vc0FrameRxWidth => vc0FrameRxWidth, + vc0FrameRxEOF => vc0FrameRxEOF, vc0FrameRxEOFE => vc0FrameRxEOFE, + vc0FrameRxData => vc0FrameRxData, vc0RemBuffAFull => vc0RemBuffAFull, + vc0RemBuffFull => vc0RemBuffFull, vc1FrameRxValid => vc1FrameRxValid, + vc1FrameRxSOF => vc1FrameRxSOF, vc1FrameRxWidth => vc1FrameRxWidth, + vc1FrameRxEOF => vc1FrameRxEOF, vc1FrameRxEOFE => vc1FrameRxEOFE, + vc1FrameRxData => vc1FrameRxData, vc1RemBuffAFull => vc1RemBuffAFull, + vc1RemBuffFull => vc1RemBuffFull, vc2FrameRxValid => vc2FrameRxValid, + vc2FrameRxSOF => vc2FrameRxSOF, vc2FrameRxWidth => vc2FrameRxWidth, + vc2FrameRxEOF => vc2FrameRxEOF, vc2FrameRxEOFE => vc2FrameRxEOFE, + vc2FrameRxData => vc2FrameRxData, vc2RemBuffAFull => vc2RemBuffAFull, + vc2RemBuffFull => vc2RemBuffFull, vc3FrameRxValid => vc3FrameRxValid, + vc3FrameRxSOF => vc3FrameRxSOF, vc3FrameRxWidth => vc3FrameRxWidth, + vc3FrameRxEOF => vc3FrameRxEOF, vc3FrameRxEOFE => vc3FrameRxEOFE, + vc3FrameRxData => vc3FrameRxData, vc3RemBuffAFull => vc3RemBuffAFull, + vc3RemBuffFull => vc3RemBuffFull, crcRxIn => crcRxIn, + crcRxInit => crcRxInit, crcRxValid => crcRxValid, + crcRxWidth => crcRxWidth, crcRxOut => crcRxOut, + pibRxSOC => pibRxSOC, pibRxWidth => pibRxWidth, + pibRxEOC => pibRxEOC, pibRxEOF => pibRxEOF, + pibRxEOFE => pibRxEOFE, pibRxData => pibRxData, + cellRxStart => cellRxStart, pibLinkReady => intLinkReady, + cellVcAbort => cellVcAbort, cellRxShort => cellRxShort + ); + + -- Cell Transmitter Logic + U_PgpCellTx: PgpCellTx port map ( + pgpClk => pgpClk, pgpReset => pgpReset, + cellTxDataSeq => cellTxDataSeq, cellTxSOF => cellTxSOF, + cellTxEOF => cellTxEOF, cellTxIdle => cellTxIdle, + cellTxReq => cellTxReq, cellTxInp => cellTxInp, + cellTxDataVc => cellTxDataVc, cellTxNAck => cellTxNAck, + cellTxAck => cellTxAck, cellTxAckSeq => cellTxAckSeq, + cellTxAcked => cellTxAcked, vc0FrameTxValid => vc0FrameTxValid, + vc0FrameTxReady => vc0FrameTxReady, vc0FrameTxSOF => vc0FrameTxSOF, + vc0FrameTxWidth => vc0FrameTxWidth, vc0FrameTxEOF => vc0FrameTxEOF, + vc0FrameTxEOFE => vc0FrameTxEOFE, vc0FrameTxData => vc0FrameTxData, + vc0LocBuffAFull => vc0LocBuffAFull, vc0LocBuffFull => vc0LocBuffFull, + vc1FrameTxValid => vc1FrameTxValid, vc1FrameTxReady => vc1FrameTxReady, + vc1FrameTxSOF => vc1FrameTxSOF, vc1FrameTxWidth => vc1FrameTxWidth, + vc1FrameTxEOF => vc1FrameTxEOF, vc1FrameTxEOFE => vc1FrameTxEOFE, + vc1FrameTxData => vc1FrameTxData, vc1LocBuffAFull => vc1LocBuffAFull, + vc1LocBuffFull => vc1LocBuffFull, vc2FrameTxValid => vc2FrameTxValid, + vc2FrameTxReady => vc2FrameTxReady, vc2FrameTxSOF => vc2FrameTxSOF, + vc2FrameTxWidth => vc2FrameTxWidth, vc2FrameTxEOF => vc2FrameTxEOF, + vc2FrameTxEOFE => vc2FrameTxEOFE, vc2FrameTxData => vc2FrameTxData, + vc2LocBuffAFull => vc2LocBuffAFull, vc2LocBuffFull => vc2LocBuffFull, + vc3FrameTxValid => vc3FrameTxValid, vc3FrameTxReady => vc3FrameTxReady, + vc3FrameTxSOF => vc3FrameTxSOF, vc3FrameTxWidth => vc3FrameTxWidth, + vc3FrameTxEOF => vc3FrameTxEOF, vc3FrameTxEOFE => vc3FrameTxEOFE, + vc3FrameTxData => vc3FrameTxData, vc3LocBuffAFull => vc3LocBuffAFull, + vc3LocBuffFull => vc3LocBuffFull, pibTxSOC => pibTxSOC, + pibTxWidth => pibTxWidth, pibTxEOC => pibTxEOC, + pibTxEOF => pibTxEOF, pibTxEOFE => pibTxEOFE, + pibTxData => pibTxData, crcTxIn => crcTxIn, + crcTxInit => crcTxInit, crcTxValid => crcTxValid, + crcTxWidth => crcTxWidth, crcTxOut => crcTxOut, + pibLinkReady => intLinkReady + ); + + -- Physical Interface Block + U_PgpPhy: PgpPhy port map ( + pgpClk => pgpClk, pgpReset => pgpReset, + pibReLink => pibReLink, localVersion => intVersion, + remoteVersion => remoteVersion, pibFail => pibFail, + pibLinkReady => intLinkReady, pibState => pibState, + pibTxSOC => pibTxSOC, pibTxWidth => pibTxWidth, + pibTxEOC => pibTxEOC, pibTxEOF => pibTxEOF, + pibTxEOFE => pibTxEOFE, pibTxData => pibTxData, + pibRxSOC => pibRxSOC, pibRxWidth => pibRxWidth, + pibRxEOC => pibRxEOC, pibRxEOF => pibRxEOF, + pibRxEOFE => pibRxEOFE, pibRxData => pibRxData, + phyRxPolarity => phyRxPolarity, phyRxData => phyRxData, + phyRxDataK => phyRxDataK, phyTxData => phyTxData, + phyTxDataK => phyTxDataK, phyInitDone => phyInitDone + ); + + -- Receiver Tracking Logic + U_PgpRxTrack: PgpRxTrack port map ( + pgpClk => pgpClk, pgpReset => pgpReset, + pibLinkReady => intLinkReady, ackFifoFull => ackFifoFull, + cellRxSOF => cellRxSOF, cellRxDataVc => cellRxDataVc, + cellRxEOF => cellRxEOF, cellRxEOFE => cellRxEOFE, + cellRxEmpty => cellRxEmpty, cellRxStart => cellRxStart, + cellRxDone => cellRxDone, cellRxCellError => cellRxCellError, + cellRxSeq => cellRxSeq, cellVcInFrame => cellVcInFrame, + cellTxNAck => cellTxNAck, cellTxAck => cellTxAck, + cellTxAckSeq => cellTxAckSeq, cellTxAcked => cellTxAcked, + cellTxAckReq => cellTxAckReq, cellVcAbort => cellVcAbort, + cellRxShort => cellRxShort + ); + + -- Transmit Schedular Logic + U_PgpTxSched: PgpTxSched port map ( + pgpClk => pgpClk, pgpReset => pgpReset, + pibLinkReady => intLinkReady, cidReady => cidReady, + cidTimerStart => cidTimerStart, cidSave => cidSave, + cellTxAckReq => cellTxAckReq, cellTxSOF => cellTxSOF, + cellTxEOF => cellTxEOF, cellTxIdle => cellTxIdle, + cellTxReq => cellTxReq, cellTxInp => cellTxInp, + cellTxDataVc => cellTxDataVc, vc0FrameTxValid => vc0FrameTxValid, + vc1FrameTxValid => vc1FrameTxValid, vc2FrameTxValid => vc2FrameTxValid, + vc3FrameTxValid => vc3FrameTxValid + ); + + + -- Generate error count pulses + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + phyLinkErrorDly <= '0' after tpd; + nackCountIncDly <= '0' after tpd; + cellRxCellErrorDly <= '0' after tpd; + countLinkDown <= '0' after tpd; + countLinkError <= '0' after tpd; + countNack <= '0' after tpd; + countCellError <= '0' after tpd; + pgpSeqError <= '0' after tpd; + linkDownBlock <= (others=>'0') after tpd; + + elsif rising_edge(pgpClk) then + + -- Delay chain to block counts when link is down + if intLinkReady = '0' then + linkDownBlock <= (others=>'0') after tpd; + else + linkDownBlock(7 downto 1) <= linkDownBlock(6 downto 0) after tpd; + linkDownBlock(0) <= '1' after tpd; + end if; + + -- Detect error in sequence logic. Latch until re-link + if linkDownBlock(7) = '0' then + pgpSeqError <= '0' after tpd; + elsif ackFifoFull = '1' or seqFifoEmpty = '1' then + pgpSeqError <= '1' after tpd; + end if; + + -- Delayed copy of signals + phyLinkErrorDly <= phyLinkError after tpd; + nackCountIncDly <= nackCountInc after tpd; + cellRxCellErrorDly <= cellRxCellError after tpd; + + -- Only count when link has been up and is stable + if linkDownBlock(7) = '1' then + + -- Edge detect + countLinkError <= not phyLinkErrorDly and phyLinkError after tpd; + countNack <= not nackCountIncDly and nackCountInc after tpd; + countCellError <= not cellRxCellErrorDly and cellRxCellError after tpd; + else + countLinkError <= '0' after tpd; + countNack <= '0' after tpd; + countCellError <= '0' after tpd; + end if; + + -- Link down counter + countLinkDown <= (not intLinkReady) and linkDownBlock(0) after tpd; + + end if; + end process; + +end PgpTop; + diff --git a/rce/fw-hsio/modules/pgp/hdl/PgpTxSched.vhd b/rce/fw-hsio/modules/pgp/hdl/PgpTxSched.vhd new file mode 100644 index 00000000..40299456 --- /dev/null +++ b/rce/fw-hsio/modules/pgp/hdl/PgpTxSched.vhd @@ -0,0 +1,267 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, Transmit Schedular +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : PgpTxSched.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 10/24/2006 +------------------------------------------------------------------------------- +-- Description: +-- Transmit schedular module for the Pretty Good Protocol core. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 10/24/2006: created. +-- 04/18/2007: Added support to track the number of cells in a frame to detect +-- dropped cells. +-- 06/19/2007: Added two clocks of delay after a cell. This ensures the +-- received cell is always fully processed even if a skip is +-- dropped. +-- 07/19/2007: Removed support to track the number of cells in a frame to detect +-- dropped cells. +-- 09/21/2007: Removed payload imput +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE work.ALL; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity PgpTxSched is port ( + + -- System clock, reset & control + pgpClk : in std_logic; -- Master clock + pgpReset : in std_logic; -- Synchronous reset input + + -- PIB Interface + pibLinkReady : in std_logic; -- PIB Link Ready + + -- ACK/NACK Receiver Logic + cidReady : in std_logic; -- CID Engine is ready + cidTimerStart : out std_logic; -- CID timer start + cidSave : out std_logic; -- CID value store signal + + -- ACK/NACK Transmit Logic + cellTxAckReq : in std_logic; -- Cell ACK/NACK transmit request + + -- Cell Transmit Logic + cellTxSOF : in std_logic; -- Cell contained SOF + cellTxEOF : in std_logic; -- Cell contained EOF + cellTxIdle : out std_logic; -- Force IDLE transmit + cellTxReq : out std_logic; -- Cell transmit request + cellTxInp : in std_logic; -- Cell transmit in progress + cellTxDataVc : out std_logic_vector(1 downto 0); -- Cell transmit virtual channel + + -- User logic interface + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxValid : in std_logic -- User frame data is valid + ); + +end PgpTxSched; + + +-- Define architecture +architecture PgpTxSched of PgpTxSched is + + -- Local Signals + signal arbTxVc : std_logic_vector(1 downto 0); + signal nxtTxVc : std_logic_vector(1 downto 0); + signal arbTxIdle : std_logic; + signal nxtTxValid : std_logic; + signal nxtInFrame : std_logic; + signal arbEn : std_logic; + signal arbEnDly : std_logic; + signal vcInFrame : std_logic_vector(3 downto 0); + + -- Schedular state + constant ST_ARB : std_logic_vector(1 downto 0) := "01"; + constant ST_REQ : std_logic_vector(1 downto 0) := "10"; + constant ST_INP : std_logic_vector(1 downto 0) := "11"; + constant ST_DLY : std_logic_vector(1 downto 0) := "00"; + signal curState : std_logic_vector(1 downto 0); + signal nxtState : std_logic_vector(1 downto 0); + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Outgoing signals + cellTxReq <= arbEnDly; + cellTxDataVc <= arbTxVc; + cellTxIdle <= arbTxIdle; + cidSave <= arbEnDly; + + -- Drive timer start if we think frame is being transmitted and + -- EOF or SOF is transmitted. + cidTimerStart <= vcInFrame(conv_integer(arbTxVc)) and (cellTxSOF or cellTxEOF); + + + -- State transition logic + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + curState <= ST_ARB after tpd; + arbTxVc <= "00" after tpd; + arbTxIdle <= '0' after tpd; + arbEnDly <= '0' after tpd; + elsif rising_edge(pgpClk) then + + -- Force state to select state when link goes down + if pibLinkReady = '0' then + curState <= ST_ARB after tpd; + else + curState <= nxtState after tpd; + end if; + + -- Delayed version of arb enable + arbEnDly <= arbEn after tpd; + + -- Only select new source if arbitration is enabled + if arbEn = '1' then + + -- No one is requesting or ack/nack tx is required and + -- selected source is not already in frame + -- Transmit idle frame, keep same last VC for next arb + if nxtTxValid = '0' or ( cellTxAckReq = '1' and nxtInFrame = '0' ) then + arbTxIdle <= '1' after tpd; + + -- Choose next vc source + else + arbTxVc <= nxtTxVc after tpd; + arbTxIdle <= '0' after tpd; + end if; + end if; + end if; + end process; + + + -- Scheduler state machine + process ( curState, cidReady, cellTxInp, pibLinkReady ) begin + case curState is + + -- IDLE, wait for ack receiver to be ready + when ST_ARB => + + -- Continue when ack transmitter is ready + if cidReady = '1' and pibLinkReady = '1' then + nxtState <= ST_REQ; + arbEn <= '1'; + else + nxtState <= curState; + arbEn <= '0'; + end if; + + -- REQ, assert request + when ST_REQ => + + -- No arb, transmit already requested + arbEn <= '0'; + + -- Move to in progress state + nxtState <= ST_INP; + + -- Cell transmission in progress, wait for it to be done + when ST_INP => + + -- No arb, no tx + arbEn <= '0'; + + -- Wait for in progress to be done + if cellTxInp = '0' then + nxtState <= ST_DLY; + arbEn <= '0'; + else + nxtState <= curState; + arbEn <= '0'; + end if; + + -- Delay one clock + when ST_DLY => + + -- No arb, transmit already requested + arbEn <= '0'; + + -- Move to arb state + nxtState <= ST_ARB; + + -- Just in case + when others => + arbEn <= '0'; + nxtState <= ST_ARB; + end case; + end process; + + + -- Select in frame status of arb winner + nxtInFrame <= vcInFrame(conv_integer(nxtTxVc)); + + -- Arbitrate for the next VC value based upon current VC value + -- and status of valid inputs + process ( arbTxVc, vc0FrameTxValid, vc1FrameTxValid, + vc2FrameTxValid, vc3FrameTxValid ) begin + case arbTxVc is + when "00" => + if vc1FrameTxValid = '1' then nxtTxVc <= "01"; nxtTxValid <= '1'; + elsif vc2FrameTxValid = '1' then nxtTxVc <= "10"; nxtTxValid <= '1'; + elsif vc3FrameTxValid = '1' then nxtTxVc <= "11"; nxtTxValid <= '1'; + elsif vc0FrameTxValid = '1' then nxtTxVc <= "00"; nxtTxValid <= '1'; + else nxtTxVc <= arbTxVc; nxtTxValid <= '0'; end if; + when "01" => + if vc2FrameTxValid = '1' then nxtTxVc <= "10"; nxtTxValid <= '1'; + elsif vc3FrameTxValid = '1' then nxtTxVc <= "11"; nxtTxValid <= '1'; + elsif vc0FrameTxValid = '1' then nxtTxVc <= "00"; nxtTxValid <= '1'; + elsif vc1FrameTxValid = '1' then nxtTxVc <= "01"; nxtTxValid <= '1'; + else nxtTxVc <= arbTxVc; nxtTxValid <= '0'; end if; + when "10" => + if vc3FrameTxValid = '1' then nxtTxVc <= "11"; nxtTxValid <= '1'; + elsif vc0FrameTxValid = '1' then nxtTxVc <= "00"; nxtTxValid <= '1'; + elsif vc1FrameTxValid = '1' then nxtTxVc <= "01"; nxtTxValid <= '1'; + elsif vc2FrameTxValid = '1' then nxtTxVc <= "10"; nxtTxValid <= '1'; + else nxtTxVc <= arbTxVc; nxtTxValid <= '0'; end if; + when "11" => + if vc0FrameTxValid = '1' then nxtTxVc <= "00"; nxtTxValid <= '1'; + elsif vc1FrameTxValid = '1' then nxtTxVc <= "01"; nxtTxValid <= '1'; + elsif vc2FrameTxValid = '1' then nxtTxVc <= "10"; nxtTxValid <= '1'; + elsif vc3FrameTxValid = '1' then nxtTxVc <= "11"; nxtTxValid <= '1'; + else nxtTxVc <= arbTxVc; nxtTxValid <= '0'; end if; + when others => + nxtTxVc <= "00"; nxtTxValid <= '0'; + end case; + end process; + + + -- Lock in the status of the last cell transmitted + -- Also track the current frame status of each VC + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + vcInFrame <= "0000" after tpd; + elsif rising_edge(pgpClk) then + + -- Link is down, reset status + if pibLinkReady = '0' then + vcInFrame <= "0000" after tpd; + else + + -- Cell transmission is in progress + if cellTxInp = '1' then + + -- Update state of VC, track if VC is currently in frame or not + -- SOF transmitted + if cellTxSOF = '1' then + vcInFrame(conv_integer(arbTxVc)) <= '1' after tpd; + + -- EOF transmitted + elsif cellTxEOF = '1' then + vcInFrame(conv_integer(arbTxVc)) <= '0' after tpd; + end if; + end if; + end if; + end if; + end process; + +end PgpTxSched; + diff --git a/rce/fw-hsio/modules/pgp/hdl/PgpVersion.vhd b/rce/fw-hsio/modules/pgp/hdl/PgpVersion.vhd new file mode 100644 index 00000000..eaef0e25 --- /dev/null +++ b/rce/fw-hsio/modules/pgp/hdl/PgpVersion.vhd @@ -0,0 +1,44 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, Version Constant +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : PgpVersion.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 10/24/2006 +------------------------------------------------------------------------------- +-- Description: +-- Version Constant module for the Pretty Good Protocol core. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 10/24/2006: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; + +package PgpVersion is + + constant PgpVersion : std_logic_vector(7 downto 0) := "11001110"; + +end PgpVersion; + +------------------------------------------------------------------------------- +-- Revision History: +-- 10/24/2006 (0x00): Initial Version +-- 03/22/2006 (0xC8): Changed to non-zero version value +-- 06/08/2007 (0xC9): Changed CRC Reset and RX/TX PLL Lock Tracking +-- 06/11/2007 (0xCA): Clock now generated externally. Reverted back to original +-- initialization sequence. +-- 06/14/2007 (0xCB): Fixed link state init to follow Xilinx spec. Fixed +-- generation of error increment signals. +-- 08/27/2007 (0xCC): Link init now matches xilinx exactly. Changed cell structure +-- to close all open error cases. +-- 09/18/2007 (0xCD): Added enforcement of cell size on receive for PIC interface. +-- Also added frame abort if SOF is received while in frame. +-- 09/19/2007 (0xCE): Changed force frame signal to PIC mode signal. Added next +-- cell drop after error cell in order to give time to abort +-- the each active VC to the PIC +------------------------------------------------------------------------------- + diff --git a/rce/fw-hsio/modules/pgp2/coregen/pgp2_v4_afifo_18x1023.xco b/rce/fw-hsio/modules/pgp2/coregen/pgp2_v4_afifo_18x1023.xco new file mode 100644 index 00000000..43a49068 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/coregen/pgp2_v4_afifo_18x1023.xco @@ -0,0 +1,84 @@ +############################################################## +# +# Xilinx Core Generator version 11.4 +# Date: Mon May 24 18:29:00 2010 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# BEGIN Project Options +SET addpads = False +SET asysymbol = True +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = False +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = False +SET foundationsym = False +SET implementationfiletype = Ngc +SET package = ff672 +SET removerpms = False +SET simulationfiles = Behavioral +SET speedgrade = -12 +SET verilogsim = False +SET vhdlsim = True +# END Project Options +# BEGIN Select +SELECT Fifo_Generator family Xilinx,_Inc. 5.3 +# END Select +# BEGIN Parameters +CSET almost_empty_flag=false +CSET almost_full_flag=false +CSET component_name=pgp2_v4_afifo_18x1023 +CSET data_count=false +CSET data_count_width=10 +CSET disable_timing_violations=false +CSET dout_reset_value=0 +CSET empty_threshold_assert_value=2 +CSET empty_threshold_negate_value=3 +CSET enable_ecc=false +CSET enable_int_clk=false +CSET enable_reset_synchronization=true +CSET fifo_implementation=Independent_Clocks_Block_RAM +CSET full_flags_reset_value=1 +CSET full_threshold_assert_value=1021 +CSET full_threshold_negate_value=1020 +CSET inject_dbit_error=false +CSET inject_sbit_error=false +CSET input_data_width=18 +CSET input_depth=1024 +CSET output_data_width=18 +CSET output_depth=1024 +CSET overflow_flag=false +CSET overflow_sense=Active_High +CSET performance_options=Standard_FIFO +CSET programmable_empty_type=No_Programmable_Empty_Threshold +CSET programmable_full_type=No_Programmable_Full_Threshold +CSET read_clock_frequency=1 +CSET read_data_count=false +CSET read_data_count_width=10 +CSET reset_pin=true +CSET reset_type=Asynchronous_Reset +CSET underflow_flag=false +CSET underflow_sense=Active_High +CSET use_dout_reset=true +CSET use_embedded_registers=false +CSET use_extra_logic=false +CSET valid_flag=false +CSET valid_sense=Active_High +CSET write_acknowledge_flag=false +CSET write_acknowledge_sense=Active_High +CSET write_clock_frequency=1 +CSET write_data_count=true +CSET write_data_count_width=10 +# END Parameters +GENERATE +# CRC: dc9f4847 diff --git a/rce/fw-hsio/modules/pgp2/coregen/pgp2_v4_fifo_69x512.xco b/rce/fw-hsio/modules/pgp2/coregen/pgp2_v4_fifo_69x512.xco new file mode 100644 index 00000000..c49206eb --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/coregen/pgp2_v4_fifo_69x512.xco @@ -0,0 +1,84 @@ +############################################################## +# +# Xilinx Core Generator version 11.3 +# Date: Fri Jan 15 08:14:17 2010 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# BEGIN Project Options +SET addpads = False +SET asysymbol = True +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = False +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = False +SET foundationsym = False +SET implementationfiletype = Ngc +SET package = ff672 +SET removerpms = False +SET simulationfiles = Behavioral +SET speedgrade = -12 +SET verilogsim = False +SET vhdlsim = True +# END Project Options +# BEGIN Select +SELECT Fifo_Generator family Xilinx,_Inc. 5.3 +# END Select +# BEGIN Parameters +CSET almost_empty_flag=false +CSET almost_full_flag=false +CSET component_name=pgp2_v4_fifo_69x512 +CSET data_count=true +CSET data_count_width=9 +CSET disable_timing_violations=false +CSET dout_reset_value=0 +CSET empty_threshold_assert_value=2 +CSET empty_threshold_negate_value=3 +CSET enable_ecc=false +CSET enable_int_clk=false +CSET enable_reset_synchronization=true +CSET fifo_implementation=Common_Clock_Block_RAM +CSET full_flags_reset_value=1 +CSET full_threshold_assert_value=510 +CSET full_threshold_negate_value=509 +CSET inject_dbit_error=false +CSET inject_sbit_error=false +CSET input_data_width=69 +CSET input_depth=512 +CSET output_data_width=69 +CSET output_depth=512 +CSET overflow_flag=false +CSET overflow_sense=Active_High +CSET performance_options=Standard_FIFO +CSET programmable_empty_type=No_Programmable_Empty_Threshold +CSET programmable_full_type=No_Programmable_Full_Threshold +CSET read_clock_frequency=1 +CSET read_data_count=false +CSET read_data_count_width=9 +CSET reset_pin=true +CSET reset_type=Asynchronous_Reset +CSET underflow_flag=false +CSET underflow_sense=Active_High +CSET use_dout_reset=true +CSET use_embedded_registers=false +CSET use_extra_logic=false +CSET valid_flag=false +CSET valid_sense=Active_High +CSET write_acknowledge_flag=false +CSET write_acknowledge_sense=Active_High +CSET write_clock_frequency=1 +CSET write_data_count=false +CSET write_data_count_width=9 +# END Parameters +GENERATE +# CRC: 9d8b647a diff --git a/rce/fw-hsio/modules/pgp2/coregen/pgp2_v4_icon.xco b/rce/fw-hsio/modules/pgp2/coregen/pgp2_v4_icon.xco new file mode 100644 index 00000000..063d1026 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/coregen/pgp2_v4_icon.xco @@ -0,0 +1,47 @@ +############################################################## +# +# Xilinx Core Generator version 11.4 +# Date: Thu Jun 3 17:09:25 2010 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# BEGIN Project Options +SET addpads = False +SET asysymbol = True +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = False +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = False +SET foundationsym = False +SET implementationfiletype = Ngc +SET package = ff672 +SET removerpms = False +SET simulationfiles = Structural +SET speedgrade = -12 +SET verilogsim = False +SET vhdlsim = True +# END Project Options +# BEGIN Select +SELECT ICON_(ChipScope_Pro_-_Integrated_Controller) family Xilinx,_Inc. 1.04.a +# END Select +# BEGIN Parameters +CSET component_name=pgp2_v4_icon +CSET enable_jtag_bufg=true +CSET number_control_ports=2 +CSET use_ext_bscan=false +CSET use_softbscan=false +CSET use_unused_bscan=false +CSET user_scan_chain=USER1 +# END Parameters +GENERATE +# CRC: af7581bc diff --git a/rce/fw-hsio/modules/pgp2/coregen/pgp2_v4_ila.xco b/rce/fw-hsio/modules/pgp2/coregen/pgp2_v4_ila.xco new file mode 100644 index 00000000..459f7cf4 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/coregen/pgp2_v4_ila.xco @@ -0,0 +1,130 @@ +############################################################## +# +# Xilinx Core Generator version 11.4 +# Date: Thu Jun 3 17:13:17 2010 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# BEGIN Project Options +SET addpads = False +SET asysymbol = True +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = False +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = False +SET foundationsym = False +SET implementationfiletype = Ngc +SET package = ff672 +SET removerpms = False +SET simulationfiles = Structural +SET speedgrade = -12 +SET verilogsim = False +SET vhdlsim = True +# END Project Options +# BEGIN Select +SELECT ILA_(ChipScope_Pro_-_Integrated_Logic_Analyzer) family Xilinx,_Inc. 1.03.a +# END Select +# BEGIN Parameters +CSET component_name=pgp2_v4_ila +CSET counter_width_1=Disabled +CSET counter_width_10=Disabled +CSET counter_width_11=Disabled +CSET counter_width_12=Disabled +CSET counter_width_13=Disabled +CSET counter_width_14=Disabled +CSET counter_width_15=Disabled +CSET counter_width_16=Disabled +CSET counter_width_2=Disabled +CSET counter_width_3=Disabled +CSET counter_width_4=Disabled +CSET counter_width_5=Disabled +CSET counter_width_6=Disabled +CSET counter_width_7=Disabled +CSET counter_width_8=Disabled +CSET counter_width_9=Disabled +CSET data_port_width=64 +CSET data_same_as_trigger=false +CSET enable_storage_qualification=true +CSET enable_trigger_output_port=false +CSET exclude_from_data_storage_1=true +CSET exclude_from_data_storage_10=true +CSET exclude_from_data_storage_11=true +CSET exclude_from_data_storage_12=true +CSET exclude_from_data_storage_13=true +CSET exclude_from_data_storage_14=true +CSET exclude_from_data_storage_15=true +CSET exclude_from_data_storage_16=true +CSET exclude_from_data_storage_2=true +CSET exclude_from_data_storage_3=true +CSET exclude_from_data_storage_4=true +CSET exclude_from_data_storage_5=true +CSET exclude_from_data_storage_6=true +CSET exclude_from_data_storage_7=true +CSET exclude_from_data_storage_8=true +CSET exclude_from_data_storage_9=true +CSET match_type_1=basic +CSET match_type_10=basic +CSET match_type_11=basic +CSET match_type_12=basic +CSET match_type_13=basic +CSET match_type_14=basic +CSET match_type_15=basic +CSET match_type_16=basic +CSET match_type_2=basic +CSET match_type_3=basic +CSET match_type_4=basic +CSET match_type_5=basic +CSET match_type_6=basic +CSET match_type_7=basic +CSET match_type_8=basic +CSET match_type_9=basic +CSET match_units_1=1 +CSET match_units_10=1 +CSET match_units_11=1 +CSET match_units_12=1 +CSET match_units_13=1 +CSET match_units_14=1 +CSET match_units_15=1 +CSET match_units_16=1 +CSET match_units_2=1 +CSET match_units_3=1 +CSET match_units_4=1 +CSET match_units_5=1 +CSET match_units_6=1 +CSET match_units_7=1 +CSET match_units_8=1 +CSET match_units_9=1 +CSET max_sequence_levels=1 +CSET number_of_trigger_ports=1 +CSET sample_data_depth=2048 +CSET sample_on=Rising +CSET trigger_port_width_1=8 +CSET trigger_port_width_10=8 +CSET trigger_port_width_11=8 +CSET trigger_port_width_12=8 +CSET trigger_port_width_13=8 +CSET trigger_port_width_14=8 +CSET trigger_port_width_15=8 +CSET trigger_port_width_16=8 +CSET trigger_port_width_2=8 +CSET trigger_port_width_3=8 +CSET trigger_port_width_4=8 +CSET trigger_port_width_5=8 +CSET trigger_port_width_6=8 +CSET trigger_port_width_7=8 +CSET trigger_port_width_8=8 +CSET trigger_port_width_9=8 +CSET use_rpms=true +# END Parameters +GENERATE +# CRC: a5b91e94 diff --git a/rce/fw-hsio/modules/pgp2/coregen/pgp2_v4_vio.xco b/rce/fw-hsio/modules/pgp2/coregen/pgp2_v4_vio.xco new file mode 100644 index 00000000..7d83f0cc --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/coregen/pgp2_v4_vio.xco @@ -0,0 +1,50 @@ +############################################################## +# +# Xilinx Core Generator version 11.4 +# Date: Thu Jun 3 17:14:49 2010 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# BEGIN Project Options +SET addpads = False +SET asysymbol = True +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = False +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = False +SET foundationsym = False +SET implementationfiletype = Ngc +SET package = ff672 +SET removerpms = False +SET simulationfiles = Structural +SET speedgrade = -12 +SET verilogsim = False +SET vhdlsim = True +# END Project Options +# BEGIN Select +SELECT VIO_(ChipScope_Pro_-_Virtual_Input/Output) family Xilinx,_Inc. 1.03.a +# END Select +# BEGIN Parameters +CSET asynchronous_input_port_width=8 +CSET asynchronous_output_port_width=8 +CSET component_name=pgp2_v4_vio +CSET enable_asynchronous_input_port=false +CSET enable_asynchronous_output_port=false +CSET enable_synchronous_input_port=true +CSET enable_synchronous_output_port=true +CSET invert_clock_input=false +CSET synchronous_input_port_width=16 +CSET synchronous_output_port_width=16 +# END Parameters +GENERATE +# CRC: 41fb01be diff --git a/rce/fw-hsio/modules/pgp2/coregen/pgp2_v5_afifo_18x1023.xco b/rce/fw-hsio/modules/pgp2/coregen/pgp2_v5_afifo_18x1023.xco new file mode 100644 index 00000000..4dbd8c61 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/coregen/pgp2_v5_afifo_18x1023.xco @@ -0,0 +1,84 @@ +############################################################## +# +# Xilinx Core Generator version 11.4 +# Date: Mon May 24 18:33:50 2010 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# BEGIN Project Options +SET addpads = False +SET asysymbol = True +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = False +SET designentry = VHDL +SET device = xc5vfx30t +SET devicefamily = virtex5 +SET flowvendor = Other +SET formalverification = False +SET foundationsym = False +SET implementationfiletype = Ngc +SET package = ff665 +SET removerpms = False +SET simulationfiles = Behavioral +SET speedgrade = -2 +SET verilogsim = False +SET vhdlsim = True +# END Project Options +# BEGIN Select +SELECT Fifo_Generator family Xilinx,_Inc. 5.3 +# END Select +# BEGIN Parameters +CSET almost_empty_flag=false +CSET almost_full_flag=false +CSET component_name=pgp2_v5_afifo_18x1023 +CSET data_count=false +CSET data_count_width=10 +CSET disable_timing_violations=false +CSET dout_reset_value=0 +CSET empty_threshold_assert_value=2 +CSET empty_threshold_negate_value=3 +CSET enable_ecc=false +CSET enable_int_clk=false +CSET enable_reset_synchronization=true +CSET fifo_implementation=Independent_Clocks_Block_RAM +CSET full_flags_reset_value=1 +CSET full_threshold_assert_value=1021 +CSET full_threshold_negate_value=1020 +CSET inject_dbit_error=false +CSET inject_sbit_error=false +CSET input_data_width=18 +CSET input_depth=1024 +CSET output_data_width=18 +CSET output_depth=1024 +CSET overflow_flag=false +CSET overflow_sense=Active_High +CSET performance_options=Standard_FIFO +CSET programmable_empty_type=No_Programmable_Empty_Threshold +CSET programmable_full_type=No_Programmable_Full_Threshold +CSET read_clock_frequency=1 +CSET read_data_count=false +CSET read_data_count_width=10 +CSET reset_pin=true +CSET reset_type=Asynchronous_Reset +CSET underflow_flag=false +CSET underflow_sense=Active_High +CSET use_dout_reset=true +CSET use_embedded_registers=false +CSET use_extra_logic=false +CSET valid_flag=false +CSET valid_sense=Active_High +CSET write_acknowledge_flag=false +CSET write_acknowledge_sense=Active_High +CSET write_clock_frequency=1 +CSET write_data_count=true +CSET write_data_count_width=10 +# END Parameters +GENERATE +# CRC: 46d643bc diff --git a/rce/fw-hsio/modules/pgp2/hdl/applications/Pgp2AppPackage.vhd b/rce/fw-hsio/modules/pgp2/hdl/applications/Pgp2AppPackage.vhd new file mode 100755 index 00000000..bcc3e5f2 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/applications/Pgp2AppPackage.vhd @@ -0,0 +1,141 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, Applications Package +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2AppPackage.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 11/23/2009 +------------------------------------------------------------------------------- +-- Description: +-- Application Components package. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 11/23/2009: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; + +package Pgp2AppPackage is + + -- Register Slave + component Pgp2RegSlave + generic ( + FifoType : string := "V5" -- V5 = Virtex 5, V4 = Virtex 4 + ); + port ( + pgpRxClk : in std_logic; -- PGP Clock + pgpRxReset : in std_logic; -- Synchronous PGP Reset + pgpTxClk : in std_logic; -- PGP Clock + pgpTxReset : in std_logic; -- Synchronous PGP Reset + locClk : in std_logic; -- Local Clock + locReset : in std_logic; -- Synchronous Local Reset + vcFrameRxValid : in std_logic; -- Data is valid + vcFrameRxSOF : in std_logic; -- Data is SOF + vcFrameRxEOF : in std_logic; -- Data is EOF + vcFrameRxEOFE : in std_logic; -- Data is EOF with Error + vcFrameRxData : in std_logic_vector(15 downto 0); -- Data + vcLocBuffAFull : out std_logic; -- Local buffer almost full + vcLocBuffFull : out std_logic; -- Local buffer full + vcFrameTxValid : out std_logic; -- User frame data is valid + vcFrameTxReady : in std_logic; -- PGP is ready + vcFrameTxSOF : out std_logic; -- User frame data start of frame + vcFrameTxEOF : out std_logic; -- User frame data end of frame + vcFrameTxEOFE : out std_logic; -- User frame data error + vcFrameTxData : out std_logic_vector(15 downto 0); -- User frame data + vcRemBuffAFull : in std_logic; -- Remote buffer almost full + vcRemBuffFull : in std_logic; -- Remote buffer full + regInp : out std_logic; -- Register Access In Progress Flag + regReq : out std_logic; -- Register Access Request + regOp : out std_logic; -- Register OpCode, 0=Read, 1=Write + regAck : in std_logic; -- Register Access Acknowledge + regFail : in std_logic; -- Register Access Fail + regAddr : out std_logic_vector(23 downto 0); -- Register Address + regDataOut : out std_logic_vector(31 downto 0); -- Register Data Out + regDataIn : in std_logic_vector(31 downto 0) -- Register Data In + ); + end component; + + -- Register Slave + component Pgp2CmdSlave + generic ( + DestId : natural := 0; -- Destination ID Value To Match + DestMask : natural := 0; -- Destination ID Mask For Match + FifoType : string := "V5" -- V5 = Virtex 5, V4 = Virtex 4 + ); + port ( + pgpRxClk : in std_logic; -- PGP Clock + pgpRxReset : in std_logic; -- Synchronous PGP Reset + locClk : in std_logic; -- Local Clock + locReset : in std_logic; -- Synchronous Local Reset + vcFrameRxValid : in std_logic; -- Data is valid + vcFrameRxSOF : in std_logic; -- Data is SOF + vcFrameRxEOF : in std_logic; -- Data is EOF + vcFrameRxEOFE : in std_logic; -- Data is EOF with Error + vcFrameRxData : in std_logic_vector(15 downto 0); -- Data + vcLocBuffAFull : out std_logic; -- Local buffer almost full + vcLocBuffFull : out std_logic; -- Local buffer full + cmdEn : out std_logic; -- Command Enable + cmdOpCode : out std_logic_vector(7 downto 0); -- Command OpCode + cmdCtxOut : out std_logic_vector(23 downto 0) -- Command Context + ); + end component; + + -- Downstream Buffer + component Pgp2DsBuff + generic ( + FifoType : string := "V5" -- V5 = Virtex 5, V4 = Virtex 4 + ); + port ( + pgpClk : in std_logic; + pgpReset : in std_logic; + locClk : in std_logic; + locReset : in std_logic; + vcFrameRxValid : in std_logic; + vcFrameRxSOF : in std_logic; + vcFrameRxEOF : in std_logic; + vcFrameRxEOFE : in std_logic; + vcFrameRxData : in std_logic_vector(15 downto 0); + vcLocBuffAFull : out std_logic; + vcLocBuffFull : out std_logic; + frameRxValid : out std_logic; + frameRxReady : in std_logic; + frameRxSOF : out std_logic; + frameRxEOF : out std_logic; + frameRxEOFE : out std_logic; + frameRxData : out std_logic_vector(15 downto 0) + ); + end component; + + + -- Upstream Buffer + component Pgp2UsBuff + generic ( + FifoType : string := "V5" -- V5 = Virtex 5, V4 = Virtex 4 + ); + port ( + pgpClk : in std_logic; + pgpReset : in std_logic; + locClk : in std_logic; + locReset : in std_logic; + frameTxValid : in std_logic; + frameTxSOF : in std_logic; + frameTxEOF : in std_logic; + frameTxEOFE : in std_logic; + frameTxData : in std_logic_vector(15 downto 0); + frameTxAFull : out std_logic; + vcFrameTxValid : out std_logic; + vcFrameTxReady : in std_logic; + vcFrameTxSOF : out std_logic; + vcFrameTxEOF : out std_logic; + vcFrameTxEOFE : out std_logic; + vcFrameTxData : out std_logic_vector(15 downto 0); + vcRemBuffAFull : in std_logic; + vcRemBuffFull : in std_logic + ); + end component; + +end Pgp2AppPackage; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/applications/Pgp2CmdSlave.vhd b/rce/fw-hsio/modules/pgp2/hdl/applications/Pgp2CmdSlave.vhd new file mode 100755 index 00000000..812a97c7 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/applications/Pgp2CmdSlave.vhd @@ -0,0 +1,290 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, Command Slave Block +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2CmdSlave.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 11/20/2009 +------------------------------------------------------------------------------- +-- Description: +-- Slave block for Command protocol over the PGP. +-- Packet is 16 bytes. The 16 bit values passed over the PGP will be: +-- Word 0 Data[1:0] = VC +-- Word 0 Data[7:2] = Dest_ID +-- Word 0 Data[15:8] = TID[7:0] +-- Word 1 Data[15:0] = TID[23:8] +-- Word 2 Data[7:0] = OpCode[7:0] +-- Word 2 Data[15:8] = Don't Care +-- Word 3 Data[15:0] = Don't Care +-- Word 4 = Don't Care +-- Word 5 = Don't Care +-- Word 6 = Don't Care +-- Word 7 = Don't Care +------------------------------------------------------------------------------- +-- Copyright (c) 2007 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 11/20/2009: created. +-- 05/24/2010: Modified FIFO +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE work.ALL; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity Pgp2CmdSlave is + generic ( + DestId : natural := 0; -- Destination ID Value To Match + DestMask : natural := 0; -- Destination ID Mask For Match + FifoType : string := "V5" -- V5 = Virtex 5, V4 = Virtex 4 + ); + port ( + + -- PGP Rx Clock And Reset + pgpRxClk : in std_logic; -- PGP Clock + pgpRxReset : in std_logic; -- Synchronous PGP Reset + + -- Local clock and reset + locClk : in std_logic; -- Local Clock + locReset : in std_logic; -- Synchronous Local Reset + + -- PGP Signals, Virtual Channel Rx Only + vcFrameRxValid : in std_logic; -- Data is valid + vcFrameRxSOF : in std_logic; -- Data is SOF + vcFrameRxEOF : in std_logic; -- Data is EOF + vcFrameRxEOFE : in std_logic; -- Data is EOF with Error + vcFrameRxData : in std_logic_vector(15 downto 0); -- Data + vcLocBuffAFull : out std_logic; -- Local buffer almost full + vcLocBuffFull : out std_logic; -- Local buffer full + + -- Local command signals + cmdEn : out std_logic; -- Command Enable + cmdOpCode : out std_logic_vector(7 downto 0); -- Command OpCode + cmdCtxOut : out std_logic_vector(23 downto 0) -- Command Context + ); + +end Pgp2CmdSlave; + + +-- Define architecture +architecture Pgp2CmdSlave of Pgp2CmdSlave is + + -- V4 Async FIFO + component pgp2_v4_afifo_18x1023 port ( + din: IN std_logic_VECTOR(17 downto 0); + rd_clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_clk: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(17 downto 0); + empty: OUT std_logic; + full: OUT std_logic; + wr_data_count: OUT std_logic_VECTOR(9 downto 0)); + end component; + + -- V5 Async FIFO + component pgp2_v5_afifo_18x1023 port ( + din: IN std_logic_VECTOR(17 downto 0); + rd_clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_clk: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(17 downto 0); + empty: OUT std_logic; + full: OUT std_logic; + wr_data_count: OUT std_logic_VECTOR(9 downto 0)); + end component; + + -- Local Signals + signal intDestId : std_logic_vector(5 downto 0); + signal selDestId : std_logic_vector(5 downto 0); + signal selDestMask : std_logic_vector(5 downto 0); + signal intCmdEn : std_logic; + signal intCmdOpCode : std_logic_vector(7 downto 0); + signal intCmdCtxOut : std_logic_vector(23 downto 0); + signal fifoDin : std_logic_vector(17 downto 0); + signal fifoDout : std_logic_vector(17 downto 0); + signal fifoRd : std_logic; + signal fifoRdDly : std_logic; + signal fifoCount : std_logic_vector(9 downto 0); + signal fifoEmpty : std_logic; + signal locSOF : std_logic; + signal locEOF : std_logic; + signal locEOFE : std_logic; + signal locData : std_logic_vector(15 downto 0); + signal intCnt : std_logic_vector(2 downto 0); + signal intCntEn : std_logic; + signal fifoErr : std_logic; + signal fifoFull : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + + -- Black Box Attributes + attribute syn_black_box : boolean; + attribute syn_noprune : boolean; + attribute syn_black_box of pgp2_v4_afifo_18x1023 : component is TRUE; + attribute syn_noprune of pgp2_v4_afifo_18x1023 : component is TRUE; + attribute syn_black_box of pgp2_v5_afifo_18x1023 : component is TRUE; + attribute syn_noprune of pgp2_v5_afifo_18x1023 : component is TRUE; + + +begin + + -- Output signal + cmdEn <= intCmdEn; + cmdOpCode <= intCmdOpCode; + cmdCtxOut <= intCmdCtxOut; + + -- Convert destnation ID and Mask + selDestId <= conv_std_logic_vector(DestId,6); + selDestMask <= conv_std_logic_vector(DestMask,6); + + -- Data going into Rx FIFO + fifoDin(17 downto 16) <= "11" when vcFrameRxEOFE = '1' or fifoErr = '1' else + "10" when vcFrameRxEOF = '1' else + "01" when vcFrameRxSOF = '1' else + "00"; + fifoDin(15 downto 0) <= vcFrameRxData; + + -- V4 FIFO + U_GenV4Fifo: if FifoType = "V4" generate + U_CmdV4Fifo: pgp2_v4_afifo_18x1023 port map ( + din => fifoDin, + rd_clk => locClk, + rd_en => fifoRd, + rst => pgpRxReset, + wr_clk => pgpRxClk, + wr_en => vcFrameRxValid, + dout => fifoDout, + empty => fifoEmpty, + full => fifoFull, + wr_data_count => fifoCount + ); + end generate; + + -- V5 FIFO + U_GenV5Fifo: if FifoType = "V5" generate + U_CmdV5Fifo: pgp2_v5_afifo_18x1023 port map ( + din => fifoDin, + rd_clk => locClk, + rd_en => fifoRd, + rst => pgpRxReset, + wr_clk => pgpRxClk, + wr_en => vcFrameRxValid, + dout => fifoDout, + empty => fifoEmpty, + full => fifoFull, + wr_data_count => fifoCount + ); + end generate; + + + -- Data coming out of Rx FIFO + locSOF <= '1' when fifoDout(17 downto 16) = "01" else '0'; + locEOF <= fifoDout(17); + locEOFE <= '1' when fifoDout(17 downto 16) = "11" else '0'; + locData <= fifoDout(15 downto 0); + + -- FIFO Read Control + fifoRd <= not fifoEmpty; + + + -- Generate flow control + process ( pgpRxClk, pgpRxReset ) begin + if pgpRxReset = '1' then + vcLocBuffAFull <= '0' after tpd; + vcLocBuffFull <= '0' after tpd; + fifoErr <= '0' after tpd; + elsif rising_edge(pgpRxClk) then + + -- Generate full error + if fifoCount >= 1020 or fifoFull = '1' then + fifoErr <= '1' after tpd; + else + fifoErr <= '0' after tpd; + end if; + + -- Almost full at 1/4 capacity + vcLocBuffAFull <= fifoFull or fifoCount(9) or fifoCount(8); + + -- Full at 1/2 capacity + vcLocBuffFull <= fifoFull or fifoCount(9); + end if; + end process; + + + -- Receive Data Processor + process ( locClk, locReset ) begin + if locReset = '1' then + intCmdEn <= '0' after tpd; + intCmdOpCode <= (others=>'0') after tpd; + intCmdCtxOut <= (others=>'0') after tpd; + intDestId <= (others=>'0') after tpd; + fifoRdDly <= '0' after tpd; + intCnt <= (others=>'0') after tpd; + intCntEn <= '0' after tpd; + elsif rising_edge(locClk) then + + -- Generate delayed read + fifoRdDly <= fifoRd after tpd; + + -- Only process when data has been read + if fifoRdDly = '1' then + + -- Receive Data Counter + -- Reset on SOF or EOF, Start counter on SOF + if locSOF = '1' or locEOF = '1' then + intCnt <= (others=>'0') after tpd; + intCntEn <= not locEOF after tpd; + elsif intCntEn = '1' and intCnt /= "110" then + intCnt <= intCnt + 1 after tpd; + end if; + + -- SOF Received + if locSOF = '1' then + intCmdCtxOut(7 downto 0) <= locData(15 downto 8) after tpd; + intDestId <= locData(7 downto 2) after tpd; + intCmdEn <= '0' after tpd; + + -- Rest of Frame + else case intCnt is + + -- Word 1 + when "000" => + intCmdCtxOut(23 downto 8) <= locData after tpd; + intCmdEn <= '0' after tpd; + + -- Word 2 + when "001" => + intCmdOpCode <= locData(7 downto 0) after tpd; + intCmdEn <= '0' after tpd; + + -- Word 7, Last word + when "110" => + + -- No error and destination ID matches + if locEOF = '1' and locEOFE = '0' and + ( intDestId and selDestMask ) = selDestId then + intCmdEn <= '1' after tpd; + else + intCmdEn <= '0' after tpd; + end if; + + -- Do nothing for others + when others => + intCmdEn <= '0' after tpd; + end case; + end if; + else + intCmdEn <= '0' after tpd; + end if; + end if; + end process; + +end Pgp2CmdSlave; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/applications/Pgp2DsBuff.vhd b/rce/fw-hsio/modules/pgp2/hdl/applications/Pgp2DsBuff.vhd new file mode 100755 index 00000000..f9206683 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/applications/Pgp2DsBuff.vhd @@ -0,0 +1,195 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol Applications, Downstream Data Buffer +-- Project : Reconfigurable Cluster Element +------------------------------------------------------------------------------- +-- File : Pgp2DsBuff.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 01/11/2010 +------------------------------------------------------------------------------- +-- Description: +-- VHDL source file for buffer block for downstream data. +------------------------------------------------------------------------------- +-- Copyright (c) 2010 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 01/11/2010: created. +------------------------------------------------------------------------------- +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity Pgp2DsBuff is + generic ( + FifoType : string := "V5" -- V5 = Virtex 5, V4 = Virtex 4 + ); + port ( + + -- Clock and reset + pgpClk : in std_logic; + pgpReset : in std_logic; + locClk : in std_logic; + locReset : in std_logic; + + -- PGP Receive Signals + vcFrameRxValid : in std_logic; + vcFrameRxSOF : in std_logic; + vcFrameRxEOF : in std_logic; + vcFrameRxEOFE : in std_logic; + vcFrameRxData : in std_logic_vector(15 downto 0); + vcLocBuffAFull : out std_logic; + vcLocBuffFull : out std_logic; + + -- Local data transfer signals + frameRxValid : out std_logic; + frameRxReady : in std_logic; + frameRxSOF : out std_logic; + frameRxEOF : out std_logic; + frameRxEOFE : out std_logic; + frameRxData : out std_logic_vector(15 downto 0) + ); +end Pgp2DsBuff; + + +-- Define architecture +architecture Pgp2DsBuff of Pgp2DsBuff is + + -- V4 Async FIFO + component pgp2_v4_afifo_18x1023 port ( + din: IN std_logic_VECTOR(17 downto 0); + rd_clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_clk: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(17 downto 0); + empty: OUT std_logic; + full: OUT std_logic; + wr_data_count: OUT std_logic_VECTOR(9 downto 0)); + end component; + + -- V5 Async FIFO + component pgp2_v5_afifo_18x1023 port ( + din: IN std_logic_VECTOR(17 downto 0); + rd_clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_clk: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(17 downto 0); + empty: OUT std_logic; + full: OUT std_logic; + wr_data_count: OUT std_logic_VECTOR(9 downto 0)); + end component; + + -- Local Signals + signal rxFifoDin : std_logic_vector(17 downto 0); + signal rxFifoDout : std_logic_vector(17 downto 0); + signal rxFifoRd : std_logic; + signal rxFifoValid : std_logic; + signal rxFifoCount : std_logic_vector(9 downto 0); + signal rxFifoEmpty : std_logic; + signal rxFifoFull : std_logic; + signal fifoErr : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + + -- Black Box Attributes + attribute syn_black_box : boolean; + attribute syn_noprune : boolean; + attribute syn_black_box of pgp2_v4_afifo_18x1023 : component is TRUE; + attribute syn_noprune of pgp2_v4_afifo_18x1023 : component is TRUE; + attribute syn_black_box of pgp2_v5_afifo_18x1023 : component is TRUE; + attribute syn_noprune of pgp2_v5_afifo_18x1023 : component is TRUE; + +begin + + -- Data going into Rx FIFO + rxFifoDin(17 downto 16) <= "11" when vcFrameRxEOFE = '1' or fifoErr = '1' else + "10" when vcFrameRxEOF = '1' else + "01" when vcFrameRxSOF = '1' else + "00"; + rxFifoDin(15 downto 0) <= vcFrameRxData; + + -- Generate flow control + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + vcLocBuffAFull <= '0' after tpd; + vcLocBuffFull <= '0' after tpd; + fifoErr <= '0' after tpd; + elsif rising_edge(pgpClk) then + + -- Generate full error + if rxFifoCount >= 1020 or rxFifoFull = '1' then + fifoErr <= '1' after tpd; + else + fifoErr <= '0' after tpd; + end if; + + -- Almost full at 1/4 capacity + vcLocBuffAFull <= rxFifoFull or rxFifoCount(9) or rxFifoCount(8); + + -- Full at 1/2 capacity + vcLocBuffFull <= rxFifoFull or rxFifoCount(9); + end if; + end process; + + -- V4 Receive FIFO + U_GenRxV4Fifo: if FifoType = "V4" generate + U_RegRxV4Fifo: pgp2_v4_afifo_18x1023 port map ( + din => rxFifoDin, + rd_clk => locClk, + rd_en => rxFifoRd, + rst => pgpReset, + wr_clk => pgpClk, + wr_en => vcFrameRxValid, + dout => rxFifoDout, + empty => rxFifoEmpty, + full => rxFifoFull, + wr_data_count => rxFifoCount + ); + end generate; + + -- V5 Receive FIFO + U_GenRxV5Fifo: if FifoType = "V5" generate + U_RegRxV5Fifo: pgp2_v5_afifo_18x1023 port map ( + din => rxFifoDin, + rd_clk => locClk, + rd_en => rxFifoRd, + rst => pgpReset, + wr_clk => pgpClk, + wr_en => vcFrameRxValid, + dout => rxFifoDout, + empty => rxFifoEmpty, + full => rxFifoFull, + wr_data_count => rxFifoCount + ); + end generate; + + -- Data valid + process ( locClk, locReset ) begin + if locReset = '1' then + rxFifoValid <= '0' after tpd; + elsif rising_edge(locClk) then + if rxFifoRd = '1' then + rxFifoValid <= '1' after tpd; + elsif frameRxReady = '1' then + rxFifoValid <= '0' after tpd; + end if; + end if; + end process; + + -- Control reads + rxFifoRd <= (not rxFifoEmpty) and ((not rxFifoValid) or frameRxReady); + + -- Outgoing signals + frameRxValid <= rxFifoValid; + frameRxSOF <= '1' when rxFifoDout(17 downto 16) = "01" else '0'; + frameRxEOF <= rxFifoDout(17); + frameRxEOFE <= '1' when rxFifoDout(17 downto 16) = "11" else '0'; + frameRxData <= rxFifoDout(15 downto 0); + +end Pgp2DsBuff; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/applications/Pgp2RegSlave.vhd b/rce/fw-hsio/modules/pgp2/hdl/applications/Pgp2RegSlave.vhd new file mode 100755 index 00000000..e07acd7e --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/applications/Pgp2RegSlave.vhd @@ -0,0 +1,1104 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, Register Slave Block +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2RegSlave.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 11/20/2009 +------------------------------------------------------------------------------- +-- Description: +-- Slave block for Register protocol over the PGP2. +-- Packet is 16 bytes. The 16 bit values passed over the PGP will be: +-- Word 0 Data[1:0] = VC +-- Word 0 Data[7:2] = Dest_ID +-- Word 0 Data[15:8] = TID[7:0] +-- Word 1 Data[15:0] = TID[23:8] +-- Word 2 Data[15:0] = Address[15:0] +-- Word 3 Data[15:14] = OpCode, 0x0=Read, 0x1=Write, 0x2=Set, 0x3=Clear +-- Word 3 Data[13:8] = Don't Care +-- Word 3 Data[7:0] = Address[23:16] +-- Word 4 Data[15:0] = WriteData0[15:0] or ReadCount[8:0] +-- Word 5 Data[15:0] = WriteData0[31:16] +-- Word N-3 Data[15:0] = WriteData[15:0] +-- Word N-2 Data[15:0] = WriteData[31:16] +-- Word N-1 = Don't Care +-- Word N Data[15:2] = Don't Care +-- Word N Data[1] = Timeout Flag (response data) +-- Word N Data[0] = Fail Flag (response data) +------------------------------------------------------------------------------- +-- Copyright (c) 2007 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 11/20/2009: created. +-- 05/24/2010: Modified FIFO +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE work.ALL; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity Pgp2RegSlave is + generic ( + FifoType : string := "V5" -- V5 = Virtex 5, V4 = Virtex 4 + ); + port ( + + -- PGP Rx Clock And Reset + pgpRxClk : in std_logic; -- PGP Clock + pgpRxReset : in std_logic; -- Synchronous PGP Reset + + -- PGP Tx Clock And Reset + pgpTxClk : in std_logic; -- PGP Clock + pgpTxReset : in std_logic; -- Synchronous PGP Reset + + -- Local clock and reset + locClk : in std_logic; -- Local Clock + locReset : in std_logic; -- Synchronous Local Reset + + -- PGP Receive Signals + vcFrameRxValid : in std_logic; -- Data is valid + vcFrameRxSOF : in std_logic; -- Data is SOF + vcFrameRxEOF : in std_logic; -- Data is EOF + vcFrameRxEOFE : in std_logic; -- Data is EOF with Error + vcFrameRxData : in std_logic_vector(15 downto 0); -- Data + vcLocBuffAFull : out std_logic; -- Local buffer almost full + vcLocBuffFull : out std_logic; -- Local buffer full + + -- PGP Transmit Signals + vcFrameTxValid : out std_logic; -- User frame data is valid + vcFrameTxReady : in std_logic; -- PGP is ready + vcFrameTxSOF : out std_logic; -- User frame data start of frame + vcFrameTxEOF : out std_logic; -- User frame data end of frame + vcFrameTxEOFE : out std_logic; -- User frame data error + vcFrameTxData : out std_logic_vector(15 downto 0); -- User frame data + vcRemBuffAFull : in std_logic; -- Remote buffer almost full + vcRemBuffFull : in std_logic; -- Remote buffer full + + -- Local register control signals + regInp : out std_logic; -- Register Access In Progress Flag + regReq : out std_logic; -- Register Access Request + regOp : out std_logic; -- Register OpCode, 0=Read, 1=Write + regAck : in std_logic; -- Register Access Acknowledge + regFail : in std_logic; -- Register Access Fail + regAddr : out std_logic_vector(23 downto 0); -- Register Address + regDataOut : out std_logic_vector(31 downto 0); -- Register Data Out + regDataIn : in std_logic_vector(31 downto 0) -- Register Data In + ); + +end Pgp2RegSlave; + + +-- Define architecture +architecture Pgp2RegSlave of Pgp2RegSlave is + + -- V4 Async FIFO + component pgp2_v4_afifo_18x1023 port ( + din: IN std_logic_VECTOR(17 downto 0); + rd_clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_clk: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(17 downto 0); + empty: OUT std_logic; + full: OUT std_logic; + wr_data_count: OUT std_logic_VECTOR(9 downto 0)); + end component; + + -- V5 Async FIFO + component pgp2_v5_afifo_18x1023 port ( + din: IN std_logic_VECTOR(17 downto 0); + rd_clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_clk: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(17 downto 0); + empty: OUT std_logic; + full: OUT std_logic; + wr_data_count: OUT std_logic_VECTOR(9 downto 0)); + end component; + + -- Local Signals + signal rxFifoDin : std_logic_vector(17 downto 0); + signal rxFifoDout : std_logic_vector(17 downto 0); + signal rxFifoRd : std_logic; + signal rxFifoCount : std_logic_vector(9 downto 0); + signal rxFifoEmpty : std_logic; + signal rxFifoErr : std_logic; + signal rxFifoFull : std_logic; + signal locRxSOF : std_logic; + signal locRxEOF : std_logic; + signal locRxEOFE : std_logic; + signal locRxData : std_logic_vector(15 downto 0); + signal intAddress : std_logic_vector(23 downto 0); + signal intData : std_logic_vector(31 downto 0); + signal nxtData : std_logic_vector(31 downto 0); + signal intInp : std_logic; + signal nxtInp : std_logic; + signal intReq : std_logic; + signal nxtReq : std_logic; + signal intOp : std_logic; + signal nxtOp : std_logic; + signal intFail : std_logic; + signal nxtFail : std_logic; + signal intTout : std_logic; + signal nxtTout : std_logic; + signal intEOFE : std_logic; + signal nxtEOFE : std_logic; + signal intReqCnt : std_logic_vector(23 downto 0); + signal regStart : std_logic; + signal regDone : std_logic; + signal intWrData : std_logic_vector(31 downto 0); + signal intOpCode : std_logic_vector(1 downto 0); + signal locTxWr : std_logic; + signal nxtTxWr : std_logic; + signal countEn : std_logic; + signal intCount : std_logic_vector(9 downto 0); + signal locTxSOF : std_logic; + signal nxtTxSOF : std_logic; + signal locTxEOF : std_logic; + signal nxtTxEOF : std_logic; + signal locTxEOFE : std_logic; + signal nxtTxEOFE : std_logic; + signal locTxData : std_logic_vector(15 downto 0); + signal nxtTxData : std_logic_vector(15 downto 0); + signal txFifoValid : std_logic; + signal txFifoRd : std_logic; + signal txFifoWr : std_logic; + signal txFifoDout : std_logic_vector(17 downto 0); + signal txFifoDin : std_logic_vector(17 downto 0); + signal txFifoFull : std_logic; + signal txFifoEmpty : std_logic; + signal txFifoAFull : std_logic; + signal txFifoCount : std_logic_vector(9 downto 0); + + -- Master state machine states + signal curState : std_logic_vector(3 downto 0); + signal nxtState : std_logic_vector(3 downto 0); + constant ST_IDLE : std_logic_vector(3 downto 0) := "0001"; + constant ST_HEAD_A : std_logic_vector(3 downto 0) := "0010"; + constant ST_HEAD_B : std_logic_vector(3 downto 0) := "0011"; + constant ST_HEAD_C : std_logic_vector(3 downto 0) := "0100"; + constant ST_HEAD_D : std_logic_vector(3 downto 0) := "0101"; + constant ST_READ : std_logic_vector(3 downto 0) := "0110"; + constant ST_WRITE_A : std_logic_vector(3 downto 0) := "0111"; + constant ST_WRITE_B : std_logic_vector(3 downto 0) := "1000"; + constant ST_REQ : std_logic_vector(3 downto 0) := "1001"; + constant ST_NEXT : std_logic_vector(3 downto 0) := "1010"; + constant ST_DUMP : std_logic_vector(3 downto 0) := "1011"; + constant ST_DONE_A : std_logic_vector(3 downto 0) := "1100"; + constant ST_DONE_B : std_logic_vector(3 downto 0) := "1101"; + + -- Register access states + signal curRegState : std_logic_vector(2 downto 0); + signal nxtRegState : std_logic_vector(2 downto 0); + constant ST_REG_IDLE : std_logic_vector(2 downto 0) := "001"; + constant ST_REG_WRITE : std_logic_vector(2 downto 0) := "010"; + constant ST_REG_READ : std_logic_vector(2 downto 0) := "011"; + constant ST_REG_SET : std_logic_vector(2 downto 0) := "100"; + constant ST_REG_CLEAR : std_logic_vector(2 downto 0) := "101"; + constant ST_REG_WAIT : std_logic_vector(2 downto 0) := "110"; + constant ST_REG_DONE : std_logic_vector(2 downto 0) := "111"; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + + -- Black Box Attributes + attribute syn_black_box : boolean; + attribute syn_noprune : boolean; + attribute syn_black_box of pgp2_v4_afifo_18x1023 : component is TRUE; + attribute syn_noprune of pgp2_v4_afifo_18x1023 : component is TRUE; + attribute syn_black_box of pgp2_v5_afifo_18x1023 : component is TRUE; + attribute syn_noprune of pgp2_v5_afifo_18x1023 : component is TRUE; + +begin + + ------------------------------------- + -- Inbound FIFO + ------------------------------------- + + -- Data going into Rx FIFO + rxFifoDin(17 downto 16) <= "11" when vcFrameRxEOFE = '1' or rxFifoErr = '1' else + "10" when vcFrameRxEOF = '1' else + "01" when vcFrameRxSOF = '1' else + "00"; + rxFifoDin(15 downto 0) <= vcFrameRxData; + + -- V4 Receive FIFO + U_GenRxV4Fifo: if FifoType = "V4" generate + U_RegRxV4Fifo: pgp2_v4_afifo_18x1023 port map ( + din => rxFifoDin, + rd_clk => locClk, + rd_en => rxFifoRd, + rst => pgpRxReset, + wr_clk => pgpRxClk, + wr_en => vcFrameRxValid, + dout => rxFifoDout, + empty => rxFifoEmpty, + full => rxFifoFull, + wr_data_count => rxFifoCount + ); + end generate; + + -- V5 Receive FIFO + U_GenRxV5Fifo: if FifoType = "V5" generate + U_RegRxV5Fifo: pgp2_v5_afifo_18x1023 port map ( + din => rxFifoDin, + rd_clk => locClk, + rd_en => rxFifoRd, + rst => pgpRxReset, + wr_clk => pgpRxClk, + wr_en => vcFrameRxValid, + dout => rxFifoDout, + empty => rxFifoEmpty, + full => rxFifoFull, + wr_data_count => rxFifoCount + ); + end generate; + + -- Data coming out of Rx FIFO + locRxSOF <= '1' when rxFifoDout(17 downto 16) = "01" else '0'; + locRxEOF <= rxFifoDout(17); + locRxEOFE <= '1' when rxFifoDout(17 downto 16) = "11" else '0'; + locRxData <= rxFifoDout(15 downto 0); + + -- Generate flow control + process ( pgpRxClk, pgpRxReset ) begin + if pgpRxReset = '1' then + vcLocBuffAFull <= '0' after tpd; + vcLocBuffFull <= '0' after tpd; + rxFifoErr <= '0' after tpd; + elsif rising_edge(pgpRxClk) then + + -- Generate full error + if rxFifoCount >= 1020 or rxFifoFull = '1' then + rxFifoErr <= '1' after tpd; + else + rxFifoErr <= '0' after tpd; + end if; + + -- Almost full at 1/4 capacity + vcLocBuffAFull <= rxFifoFull or rxFifoCount(9) or rxFifoCount(8); + + -- Full at 1/2 capacity + vcLocBuffFull <= rxFifoFull or rxFifoCount(9); + end if; + end process; + + + ------------------------------------- + -- Master State Machine + ------------------------------------- + + -- Master State Machine, Sync Logic + process ( locClk, locReset ) begin + if locReset = '1' then + intCount <= (others=>'0') after tpd; + intAddress <= (others=>'0') after tpd; + intOpCode <= (others=>'0') after tpd; + intWrData <= (others=>'0') after tpd; + locTxWr <= '0' after tpd; + locTxSOF <= '0' after tpd; + locTxEOF <= '0' after tpd; + locTxEOFE <= '0' after tpd; + locTxData <= (others=>'0') after tpd; + intEOFE <= '0' after tpd; + curState <= ST_IDLE after tpd; + elsif rising_edge(locClk) then + + -- Length Counter + if curState = ST_READ then + intCount <= locRxData(9 downto 0) after tpd; + elsif countEn = '1' then + intCount <= intCount -1 after tpd; + end if; + + -- Address counter + if curState = ST_HEAD_C then + intAddress(15 downto 0) <= locRxData after tpd; + elsif curState = ST_HEAD_D then + intAddress(23 downto 16) <= locRxData(7 downto 0) after tpd; + elsif countEn = '1' then + intAddress <= intAddress + 1 after tpd; + end if; + + -- Store opcode + if curState = ST_HEAD_D then + intOpCode <= locRxData(15 downto 14) after tpd; + end if; + + -- Write data + if curState = ST_WRITE_A then + intWrData(15 downto 0) <= locRxData after tpd; + elsif curState = ST_WRITE_B then + intWrData(31 downto 16) <= locRxData after tpd; + end if; + + -- EOFE tracker + intEOFE <= nxtEOFE after tpd; + + -- Outbound data + locTxWr <= nxtTxWr after tpd; + locTxSOF <= nxtTxSOF after tpd; + locTxEOF <= nxtTxEOF after tpd; + locTxEOFE <= nxtTxEOFE after tpd; + locTxData <= nxtTxData after tpd; + + -- State transition + curState <= nxtState after tpd; + + end if; + end process; + + + -- Master state engine + process ( curState, rxFifoEmpty, locRxData, locRxSOF, locRxEOF, intEOFE, txFifoAFull, + locRxEOFE, intData, regDone, intTout, intFail, intOpCode, intCount ) begin + + -- States + case curState is + + -- IDLE, Wait for data + when ST_IDLE => + regStart <= '0'; + nxtEOFE <= '0'; + nxtTxWr <= '0'; + nxtTxSOF <= '0'; + nxtTxEOF <= '0'; + nxtTxEOFE <= '0'; + nxtTxData <= (others=>'0'); + countEn <= '0'; + + -- Data is ready + if rxFifoEmpty = '0' and txFifoAFull = '0' then + rxFifoRd <= '1'; + nxtState <= ST_HEAD_A; + else + rxFifoRd <= '0'; + nxtState <= curState; + end if; + + -- Read Header A + when ST_HEAD_A => + regStart <= '0'; + nxtEOFE <= '0'; + nxtTxSOF <= '1'; + nxtTxEOF <= '0'; + nxtTxEOFE <= '0'; + nxtTxData <= locRxData; + countEn <= '0'; + + -- Bad alignment + if locRxSOF = '0' or locRxEOF = '1' then + nxtTxWr <= '0'; + rxFifoRd <= '0'; + nxtState <= ST_IDLE; + + -- Data is ready + elsif rxFifoEmpty = '0' then + nxtTxWr <= '1'; + rxFifoRd <= '1'; + nxtState <= ST_HEAD_B; + else + nxtTxWr <= '0'; + rxFifoRd <= '0'; + nxtState <= curState; + end if; + + -- Read Header B + when ST_HEAD_B => + regStart <= '0'; + nxtTxSOF <= '0'; + nxtTxEOF <= '0'; + nxtTxEOFE <= '0'; + nxtTxData <= locRxData; + countEn <= '0'; + + -- Alignment Error + if locRxSOF = '1' or locRxEOF = '1' then + nxtEOFE <= '1'; + nxtTxWr <= '0'; + rxFifoRd <= '0'; + nxtState <= ST_DUMP; + + -- Data is ready + elsif rxFifoEmpty = '0' then + nxtEOFE <= '0'; + nxtTxWr <= '1'; + rxFifoRd <= '1'; + nxtState <= ST_HEAD_C; + else + nxtEOFE <= '0'; + nxtTxWr <= '0'; + rxFifoRd <= '0'; + nxtState <= curState; + end if; + + -- Read Header C + when ST_HEAD_C => + regStart <= '0'; + nxtTxSOF <= '0'; + nxtTxEOF <= '0'; + nxtTxEOFE <= '0'; + nxtTxData <= locRxData; + countEn <= '0'; + + -- Alignment Error + if locRxSOF = '1' or locRxEOF = '1' then + nxtEOFE <= '1'; + nxtTxWr <= '0'; + rxFifoRd <= '0'; + nxtState <= ST_DUMP; + + -- Data is ready + elsif rxFifoEmpty = '0' then + nxtEOFE <= '0'; + nxtTxWr <= '1'; + rxFifoRd <= '1'; + nxtState <= ST_HEAD_D; + else + nxtEOFE <= '0'; + nxtTxWr <= '0'; + rxFifoRd <= '0'; + nxtState <= curState; + end if; + + -- Read Header D + when ST_HEAD_D => + regStart <= '0'; + nxtTxSOF <= '0'; + nxtTxEOF <= '0'; + nxtTxEOFE <= '0'; + nxtTxData <= locRxData; + countEn <= '0'; + + -- Alignment Error + if locRxSOF = '1' or locRxEOF = '1' then + nxtEOFE <= '1'; + nxtTxWr <= '0'; + rxFifoRd <= '0'; + nxtState <= ST_DUMP; + + -- Data is ready + elsif rxFifoEmpty = '0' then + nxtEOFE <= '0'; + nxtTxWr <= '1'; + rxFifoRd <= '1'; + + -- Read + if locRxData(15 downto 14) = "00" then + nxtState <= ST_READ; + else + nxtState <= ST_WRITE_A; + end if; + else + nxtEOFE <= '0'; + nxtTxWr <= '0'; + rxFifoRd <= '0'; + nxtState <= curState; + end if; + + -- Read command, frame word 0 + when ST_READ => + regStart <= '0'; + nxtTxWr <= '0'; + nxtTxSOF <= '0'; + nxtTxEOF <= '0'; + nxtTxEOFE <= '0'; + nxtTxData <= (others=>'0'); + countEn <= '0'; + rxFifoRd <= '0'; + + -- Alignment Error + if locRxSOF = '1' or locRxEOF = '1' then + nxtEOFE <= '1'; + nxtState <= ST_DUMP; + + -- Data is ready + elsif rxFifoEmpty = '0' then + nxtEOFE <= '0'; + nxtState <= ST_REQ; + else + nxtEOFE <= '0'; + nxtState <= curState; + end if; + + -- Low Write Data + when ST_WRITE_A => + regStart <= '0'; + nxtTxWr <= '0'; + nxtTxSOF <= '0'; + nxtTxEOF <= '0'; + nxtTxEOFE <= '0'; + nxtTxData <= (others=>'0'); + countEn <= '0'; + + -- Alignment Error + if locRxSOF = '1' or locRxEOF = '1' then + nxtEOFE <= '1'; + rxFifoRd <= '0'; + nxtState <= ST_DUMP; + + -- Data is ready + elsif rxFifoEmpty = '0' then + nxtEOFE <= '0'; + rxFifoRd <= '1'; + nxtState <= ST_WRITE_B; + else + nxtEOFE <= '0'; + rxFifoRd <= '0'; + nxtState <= curState; + end if; + + -- High Write Data + when ST_WRITE_B => + regStart <= '0'; + nxtTxWr <= '0'; + nxtTxSOF <= '0'; + nxtTxEOF <= '0'; + nxtTxEOFE <= '0'; + nxtTxData <= (others=>'0'); + countEn <= '0'; + rxFifoRd <= '0'; + + -- Alignment Error + if locRxSOF = '1' then + nxtEOFE <= '1'; + nxtState <= ST_DUMP; + + -- EOF + elsif locRxEOF = '1' then + nxtEOFE <= locRxEOFE; + nxtState <= ST_DONE_A; + + -- Request write cycle + else + nxtEOFE <= '0'; + nxtState <= ST_REQ; + end if; + + -- Transaction Request + when ST_REQ => + regStart <= '1'; + nxtEOFE <= '0'; + nxtTxSOF <= '0'; + nxtTxEOF <= '0'; + nxtTxEOFE <= '0'; + nxtTxData <= intData(15 downto 0); + rxFifoRd <= '0'; + countEn <= '0'; + + -- Machine is done, write lower bits of return data + if regDone = '1' then + nxtTxWr <= '1'; + nxtState <= ST_NEXT; + else + nxtTxWr <= '0'; + nxtState <= curState; + end if; + + -- Determine next command, write upper bits of return data + when ST_NEXT => + regStart <= '0'; + nxtEOFE <= '0'; + nxtTxSOF <= '0'; + nxtTxEOF <= '0'; + nxtTxEOFE <= '0'; + nxtTxData <= intData(31 downto 16); + + -- An error occured + if intTout = '1' or intFail = '1' then + rxFifoRd <= '0'; + nxtTxWr <= '1'; + countEn <= '0'; + nxtState <= ST_DUMP; + + -- Read command + elsif intOpCode = "00" then + rxFifoRd <= '0'; + + -- Read is done + if intCount = 0 then + nxtTxWr <= '1'; + countEn <= '0'; + nxtState <= ST_DUMP; + + -- Room in transmit FIFO + elsif txFifoAFull = '0' then + nxtTxWr <= '1'; + countEn <= '1'; + nxtState <= ST_REQ; + else + nxtTxWr <= '0'; + countEn <= '0'; + nxtState <= curState; + end if; + + -- Other command, data is ready + elsif rxFifoEmpty = '0' and txFifoAFull = '0' then + rxFifoRd <= '1'; + nxtTxWr <= '1'; + countEn <= '1'; + nxtState <= ST_WRITE_A; + else + rxFifoRd <= '0'; + nxtTxWr <= '0'; + countEn <= '0'; + nxtState <= curState; + end if; + + -- Dump receive data + when ST_DUMP => + regStart <= '0'; + nxtTxSOF <= '0'; + nxtTxEOF <= '0'; + nxtTxEOFE <= '0'; + nxtTxData <= (others=>'0'); + nxtTxWr <= '0'; + countEn <= '0'; + + -- Data is done + if locRxEOF = '1' then + nxtEOFE <= intEOFE or locRxEOFE; + rxFifoRd <= '0'; + nxtState <= ST_DONE_A; + else + nxtEOFE <= intEOFE; + rxFifoRd <= not rxFifoEmpty; + nxtState <= curState; + end if; + + -- Done word 0 + when ST_DONE_A => + regStart <= '0'; + nxtEOFE <= intEOFE; + nxtTxSOF <= '0'; + nxtTxEOF <= '0'; + nxtTxEOFE <= '0'; + nxtTxData <= (others=>'0'); + nxtTxWr <= '1'; + rxFifoRd <= '0'; + countEn <= '0'; + nxtState <= ST_DONE_B; + + -- Done word 1 + when ST_DONE_B => + regStart <= '0'; + nxtEOFE <= intEOFE; + nxtTxSOF <= '0'; + nxtTxEOF <= '1'; + nxtTxEOFE <= intEOFE; + nxtTxData(15 downto 2) <= (others=>'0'); + nxtTxData(1) <= intTout; + nxtTxData(0) <= intFail; + nxtTxWr <= '1'; + rxFifoRd <= '0'; + countEn <= '0'; + nxtState <= ST_IDLE; + + -- default + when others => + regStart <= '0'; + nxtEOFE <= '0'; + nxtTxSOF <= '0'; + nxtTxEOF <= '0'; + nxtTxEOFE <= '0'; + nxtTxData <= (others=>'0'); + nxtTxWr <= '0'; + rxFifoRd <= '0'; + countEn <= '0'; + nxtState <= ST_IDLE; + + end case; + end process; + + + ------------------------------------- + -- Outbound FIFO + ------------------------------------- + + -- Data going into tx fifo + process ( locClk, locReset ) begin + if locReset = '1' then + txFifoWr <= '0' after tpd; + txFifoDin <= (others=>'0') after tpd; + txFifoAFull <= '0' after tpd; + elsif rising_edge(locClk) then + + -- Write control + txFifoWr <= locTxWr after tpd; + + -- Write Data + if locTxEOFE = '1' then + txFifoDin(17 downto 16) <= "11" after tpd; + elsif locTxEOF = '1' then + txFifoDin(17 downto 16) <= "10" after tpd; + elsif locTxSOF = '1' then + txFifoDin(17 downto 16) <= "01" after tpd; + else + txFifoDin(17 downto 16) <= "00" after tpd; + end if; + txFifoDin(15 downto 0) <= locTxData; + + -- Almost full + if txFifoCount > 1000 or txFifoFull = '1' then + txFifoAFull <= '1' after tpd; + else + txFifoAFull <= '0' after tpd; + end if; + end if; + end process; + + + -- V4 Transmit FIFO + U_GenTxV4Fifo: if FifoType = "V4" generate + U_RegTxV4Fifo: pgp2_v4_afifo_18x1023 port map ( + din => txFifoDin, + rd_clk => pgpTxClk, + rd_en => txFifoRd, + rst => pgpTxReset, + wr_clk => locClk, + wr_en => txFifoWr, + dout => txFifoDout, + empty => txFifoEmpty, + full => txFifoFull, + wr_data_count => txFifoCount + ); + end generate; + + -- V5 Transmit FIFO + U_GenTxV5Fifo: if FifoType = "V5" generate + U_RegTxV5Fifo: pgp2_v5_afifo_18x1023 port map ( + din => txFifoDin, + rd_clk => pgpTxClk, + rd_en => txFifoRd, + rst => pgpTxReset, + wr_clk => locClk, + wr_en => txFifoWr, + dout => txFifoDout, + empty => txFifoEmpty, + full => txFifoFull, + wr_data_count => txFifoCount + ); + end generate; + + -- Data valid + process ( pgpTxClk, pgpTxReset ) begin + if pgpTxReset = '1' then + txFifoValid <= '0' after tpd; + elsif rising_edge(pgpTxClk) then + if txFifoRd = '1' then + txFifoValid <= '1' after tpd; + elsif vcFrameTxReady = '1' then + txFifoValid <= '0' after tpd; + end if; + end if; + end process; + + -- Control reads + txFifoRd <= (not txFifoEmpty) and (not vcRemBuffAFull) and (not vcRemBuffFull) and + ((not txFifoValid) or vcframeTxReady); + + -- Outgoing signals + vcFrameTxValid <= txFifoValid; + vcFrameTxSOF <= '1' when txFifoDout(17 downto 16) = "01" else '0'; + vcFrameTxEOF <= txFifoDout(17); + vcFrameTxEOFE <= '1' when txFifoDout(17 downto 16) = "11" else '0'; + vcFrameTxData <= txFifoDout(15 downto 0); + + + ------------------------------------- + -- Register Access Control + ------------------------------------- + + -- Drive address bus + regAddr <= intAddress; + regDataOut <= intData; + regInp <= intInp; + regReq <= intReq; + regOp <= intOp; + + + -- Register State Machine, Sync Logic + process ( locClk, locReset ) begin + if locReset = '1' then + intInp <= '0' after tpd; + intReq <= '0' after tpd; + intOp <= '0' after tpd; + intData <= (others=>'0') after tpd; + intReqCnt <= (others=>'0') after tpd; + intFail <= '0' after tpd; + intTout <= '0' after tpd; + curRegState <= ST_REG_IDLE after tpd; + elsif rising_edge(locClk) then + + -- State transition + curRegState <= nxtRegState after tpd; + + -- Opcode and write data + intInp <= nxtInp after tpd; + intReq <= nxtReq after tpd; + intOp <= nxtOp after tpd; + + -- Data Storage + intData <= nxtData after tpd; + + -- Timeout & fail flags + intFail <= nxtFail after tpd; + intTout <= nxtTout after tpd; + + -- Timeout counter + if intReq <= '0' then + intReqCnt <= (others=>'0') after tpd; + elsif intReqCnt /= x"FFFFFF" then + intReqCnt <= intReqCnt + 1 after tpd; + end if; + end if; + end process; + + + -- Register state engine + process ( curRegState, intWrData, regStart, intOpCode, intData, + regFail, regAck, regDataIn, intReqCnt, intFail, intTout ) begin + + -- States + case curRegState is + + -- IDLE, Wait for enable from read logic + when ST_REG_IDLE => + regDone <= '0'; + nxtInp <= '0'; + nxtReq <= '0'; + nxtOp <= '0'; + + -- Register data + nxtdata <= intWrData; + + -- Start + if regStart = '1' then + nxtFail <= '0'; + nxtTout <= '0'; + + -- Write Command + if intOpCode = "01" then + nxtRegState <= ST_REG_WRITE; + + -- Read, Set Bit, Clear Bit + else + nxtRegState <= ST_REG_READ; + end if; + else + nxtFail <= intFail; + nxtTout <= intTout; + nxtRegState <= curRegState; + end if; + + -- Write State + when ST_REG_WRITE => + regDone <= '0'; + nxtInp <= '1'; + nxtReq <= '1'; + nxtOp <= '1'; + nxtdata <= intData; + + -- Ack is passed + if regAck = '1' then + + -- Done + nxtRegState <= ST_REG_WAIT; + + -- Store fail flag, no timeout + nxtFail <= regFail; + nxtTout <= '0'; + + -- Timeout + elsif intReqCnt = x"FFFFFF" then + + -- Done + nxtRegState <= ST_REG_WAIT; + + -- No Fail, set timeout + nxtFail <= '0'; + nxtTout <= '1'; + + -- Keep waiting + else + nxtRegState <= curRegState; + nxtFail <= '0'; + nxtTout <= '0'; + end if; + + -- Read State + when ST_REG_READ => + regDone <= '0'; + nxtInp <= '1'; + nxtReq <= '1'; + nxtOp <= '0'; + + -- Take read data + nxtdata <= regDataIn; + + -- Ack is passed + if regAck = '1' then + + -- Fail + if regFail = '1' then + + -- Store fail flag, no timeout, done + nxtFail <= regFail; + nxtTout <= '0'; + nxtRegState <= ST_REG_WAIT; + + -- Normal termination + else + + -- No fail or timeout + nxtFail <= '0'; + nxtTout <= '0'; + + -- Set bit command + if intOpCode = "10" then + nxtRegState <= ST_REG_SET; + + -- Clear bit command + elsif intOpCode = "11" then + nxtRegState <= ST_REG_CLEAR; + + -- Read command + else + nxtRegState <= ST_REG_WAIT; + end if; + end if; + + -- Timeout + elsif intReqCnt = x"FFFFFF" then + + -- done + nxtRegState <= ST_REG_WAIT; + + -- No Fail, set timeout + nxtFail <= '0'; + nxtTout <= '1'; + + -- Keep waiting + else + nxtRegState <= curRegState; + nxtFail <= '0'; + nxtTout <= '0'; + end if; + + -- Set Bit Command + when ST_REG_SET => + regDone <= '0'; + nxtInp <= '1'; + nxtReq <= '0'; + nxtOp <= '0'; + + -- Set bits + nxtdata <= intData or intWrData; + + -- No errors + nxtFail <= '0'; + nxtTout <= '0'; + + -- Go to write state + -- Wait for ack from previous command to clear + if regAck = '0' then + nxtRegState <= ST_REG_WRITE; + else + nxtRegState <= curRegState; + end if; + + -- Clear Bit Command + when ST_REG_CLEAR => + regDone <= '0'; + nxtInp <= '1'; + nxtReq <= '0'; + nxtOp <= '0'; + + -- Clear bits + nxtdata <= intData and (not intWrData); + + -- No errors + nxtFail <= '0'; + nxtTout <= '0'; + + -- Go to write state + -- Wait for ack from previous command to clear + if regAck = '0' then + nxtRegState <= ST_REG_WRITE; + else + nxtRegState <= curRegState; + end if; + + -- Done + when ST_REG_WAIT => + regDone <= '0'; + nxtInp <= '0'; + nxtReq <= '0'; + nxtOp <= '0'; + nxtdata <= intData; + nxtFail <= intFail; + nxtTout <= intTout; + + -- Wait for ack to clear + if regAck = '0' then + nxtRegState <= ST_REG_DONE; + else + nxtRegState <= curRegState; + end if; + + -- Done + when ST_REG_DONE => + regDone <= '1'; + nxtInp <= '0'; + nxtReq <= '0'; + nxtOp <= '0'; + nxtdata <= intData; + nxtFail <= intFail; + nxtTout <= intTout; + nxtRegState <= ST_REG_IDLE; + + when others => + regDone <= '0'; + nxtReq <= '0'; + nxtInp <= '0'; + nxtOp <= '0'; + nxtdata <= (others=>'0'); + nxtFail <= '0'; + nxtTout <= '0'; + nxtRegState <= ST_REG_IDLE; + end case; + end process; + + --debug(63 downto 59) <= (others=>'0'); + --debug(58) <= countEn; + --debug(57) <= intInp; + --debug(56) <= intReq; + --debug(55) <= intOp; + --debug(54) <= intFail; + --debug(53) <= intTout; + --debug(52) <= intEOFE; + --debug(51) <= regStart; + --debug(50) <= regDone; + --debug(49 downto 48) <= intOpCode; + --debug(47 downto 44) <= curState; + --debug(43 downto 41) <= curRegState; + --debug(40) <= '0'; + --debug(39 downto 24) <= locTxData; + --debug(23 downto 8) <= locRxData; + --debug(7) <= locTxSOF; + --debug(6) <= locTxEOF; + --debug(5) <= locTxEOFE; + --debug(4) <= locRxSOF; + --debug(3) <= locRxEOF; + --debug(2) <= locRxEOFE; + --debug(1) <= locTxWr; + --debug(0) <= rxFifoRd; + + +end Pgp2RegSlave; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/applications/Pgp2UsBuff.vhd b/rce/fw-hsio/modules/pgp2/hdl/applications/Pgp2UsBuff.vhd new file mode 100755 index 00000000..7ea6aaf1 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/applications/Pgp2UsBuff.vhd @@ -0,0 +1,194 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol Applications, Upstream Data Buffer +-- Project : Reconfigurable Cluster Element +------------------------------------------------------------------------------- +-- File : Pgp2UsBuff.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 01/11/2010 +------------------------------------------------------------------------------- +-- Description: +-- VHDL source file for buffer block for upstream data. +------------------------------------------------------------------------------- +-- Copyright (c) 2010 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 01/11/2010: created. +------------------------------------------------------------------------------- +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity Pgp2UsBuff is + generic ( + FifoType : string := "V5" -- V5 = Virtex 5, V4 = Virtex 4 + ); + port ( + + -- Clock and reset + pgpClk : in std_logic; + pgpReset : in std_logic; + locClk : in std_logic; + locReset : in std_logic; + + -- Local data transfer signals + frameTxValid : in std_logic; + frameTxSOF : in std_logic; + frameTxEOF : in std_logic; + frameTxEOFE : in std_logic; + frameTxData : in std_logic_vector(15 downto 0); + frameTxAFull : out std_logic; + + -- PGP Transmit Signals + vcFrameTxValid : out std_logic; + vcFrameTxReady : in std_logic; + vcFrameTxSOF : out std_logic; + vcFrameTxEOF : out std_logic; + vcFrameTxEOFE : out std_logic; + vcFrameTxData : out std_logic_vector(15 downto 0); + vcRemBuffAFull : in std_logic; + vcRemBuffFull : in std_logic + ); +end Pgp2UsBuff; + + +-- Define architecture +architecture Pgp2UsBuff of Pgp2UsBuff is + + -- V4 Async FIFO + component pgp2_v4_afifo_18x1023 port ( + din: IN std_logic_VECTOR(17 downto 0); + rd_clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_clk: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(17 downto 0); + empty: OUT std_logic; + full: OUT std_logic; + wr_data_count: OUT std_logic_VECTOR(9 downto 0)); + end component; + + -- V5 Async FIFO + component pgp2_v5_afifo_18x1023 port ( + din: IN std_logic_VECTOR(17 downto 0); + rd_clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_clk: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(17 downto 0); + empty: OUT std_logic; + full: OUT std_logic; + wr_data_count: OUT std_logic_VECTOR(9 downto 0)); + end component; + + -- Local Signals + signal txFifoDin : std_logic_vector(17 downto 0); + signal txFifoDout : std_logic_vector(17 downto 0); + signal txFifoRd : std_logic; + signal txFifoCount : std_logic_vector(9 downto 0); + signal txFifoEmpty : std_logic; + signal txFifoFull : std_logic; + signal txFifoValid : std_logic; + signal fifoErr : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + + -- Black Box Attributes + attribute syn_black_box : boolean; + attribute syn_noprune : boolean; + attribute syn_black_box of pgp2_v4_afifo_18x1023 : component is TRUE; + attribute syn_noprune of pgp2_v4_afifo_18x1023 : component is TRUE; + attribute syn_black_box of pgp2_v5_afifo_18x1023 : component is TRUE; + attribute syn_noprune of pgp2_v5_afifo_18x1023 : component is TRUE; + +begin + + -- Data going into Tx FIFO + txFifoDin(17 downto 16) <= "11" when frameTxEOFE = '1' or fifoErr = '1' else + "10" when frameTxEOF = '1' else + "01" when frameTxSOF = '1' else + "00"; + txFifoDin(15 downto 0) <= frameTxData; + + -- Generate fifo error signal + process ( locClk, locReset ) begin + if locReset = '1' then + fifoErr <= '0' after tpd; + frameTxAFull <= '0' after tpd; + elsif rising_edge(locClk) then + + -- Generate full error + if txFifoCount >= 1020 or txFifoFull = '1' then + fifoErr <= '1' after tpd; + else + fifoErr <= '0' after tpd; + end if; + + -- Almost full at 1/2 capacity + frameTxAFull <= txFifoFull or txFifoCount(9); + + end if; + end process; + + -- V4 Receive FIFO + U_GenRxV4Fifo: if FifoType = "V4" generate + U_RegRxV4Fifo: pgp2_v4_afifo_18x1023 port map ( + din => txFifoDin, + rd_clk => pgpClk, + rd_en => txFifoRd, + rst => pgpReset, + wr_clk => locClk, + wr_en => frameTxValid, + dout => txFifoDout, + empty => txFifoEmpty, + full => txFifoFull, + wr_data_count => txFifoCount + ); + end generate; + + -- V5 Receive FIFO + U_GenRxV5Fifo: if FifoType = "V5" generate + U_RegRxV5Fifo: pgp2_v5_afifo_18x1023 port map ( + din => txFifoDin, + rd_clk => pgpClk, + rd_en => txFifoRd, + rst => pgpReset, + wr_clk => locClk, + wr_en => frameTxValid, + dout => txFifoDout, + empty => txFifoEmpty, + full => txFifoFull, + wr_data_count => txFifoCount + ); + end generate; + + -- Data valid + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + txFifoValid <= '0' after tpd; + elsif rising_edge(pgpClk) then + if txFifoRd = '1' then + txFifoValid <= '1' after tpd; + elsif vcFrameTxReady = '1' then + txFifoValid <= '0' after tpd; + end if; + end if; + end process; + + -- Control reads + txFifoRd <= (not txFifoEmpty) and (not vcRemBuffAFull) and (not vcRemBuffFull) and + ((not txFifoValid) or vcframeTxReady); + + -- Outgoing signals + vcFrameTxValid <= txFifoValid; + vcFrameTxSOF <= '1' when txFifoDout(17 downto 16) = "01" else '0'; + vcFrameTxEOF <= txFifoDout(17); + vcFrameTxEOFE <= '1' when txFifoDout(17 downto 16) = "11" else '0'; + vcFrameTxData <= txFifoDout(15 downto 0); + +end Pgp2UsBuff; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/applications/PgpDsBuff.vhd b/rce/fw-hsio/modules/pgp2/hdl/applications/PgpDsBuff.vhd new file mode 100644 index 00000000..e5d350e0 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/applications/PgpDsBuff.vhd @@ -0,0 +1,150 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol Applications, Downstream Data Buffer +-- Project : Reconfigurable Cluster Element +------------------------------------------------------------------------------- +-- File : PgpDsBuff.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 01/11/2010 +------------------------------------------------------------------------------- +-- Description: +-- VHDL source file for buffer block for downstream data. +------------------------------------------------------------------------------- +-- Copyright (c) 2010 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 01/11/2010: created. +------------------------------------------------------------------------------- +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity PgpDsBuff is port ( + + -- Clock and reset + pgpClk : in std_logic; + pgpReset : in std_logic; + locClk : in std_logic; + locReset : in std_logic; + + -- PGP Receive Signals + vcFrameRxValid : in std_logic; + vcFrameRxSOF : in std_logic; + vcFrameRxWidth : in std_logic; + vcFrameRxEOF : in std_logic; + vcFrameRxEOFE : in std_logic; + vcFrameRxData : in std_logic_vector(15 downto 0); + vcLocBuffAFull : out std_logic; + vcLocBuffFull : out std_logic; + + -- Local data transfer signals + frameRxValid : out std_logic; + frameRxReady : in std_logic; + frameRxSOF : out std_logic; + frameRxEOF : out std_logic; + frameRxEOFE : out std_logic; + frameRxData : out std_logic_vector(15 downto 0) + ); +end PgpDsBuff; + + +-- Define architecture +architecture PgpDsBuff of PgpDsBuff is + + -- Async Fifo + component pgp_afifo_20x511 port ( + din: IN std_logic_VECTOR(19 downto 0); + rd_clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_clk: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(19 downto 0); + empty: OUT std_logic; + full: OUT std_logic; + wr_data_count: OUT std_logic_VECTOR(8 downto 0)); + end component; + + -- Local Signals + signal rxFifoDin : std_logic_vector(19 downto 0); + signal rxFifoDout : std_logic_vector(19 downto 0); + signal rxFifoRd : std_logic; + signal rxFifoValid : std_logic; + signal rxFifoCount : std_logic_vector(8 downto 0); + signal rxFifoEmpty : std_logic; + signal rxFifoFull : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + + -- Black Box Attributes + attribute syn_black_box : boolean; + attribute syn_noprune : boolean; + attribute syn_black_box of pgp_afifo_20x511 : component is TRUE; + attribute syn_noprune of pgp_afifo_20x511 : component is TRUE; + +begin + + -- Data going into Rx FIFO + rxFifoDin(19) <= '0'; + rxFifoDin(18) <= vcFrameRxSOF; + rxFifoDin(17) <= vcFrameRxEOF; + rxFifoDin(16) <= vcFrameRxEOFE; + rxFifoDin(15 downto 0) <= vcFrameRxData; + + -- Generate flow control + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + vcLocBuffAFull <= '0' after tpd; + vcLocBuffFull <= '0' after tpd; + elsif rising_edge(pgpClk) then + + -- Almost full at quarter capacity + --vcLocBuffAFull <= rxFifoCount(8); + vcLocBuffAFull <= rxFifoCount(8) or rxFifoCount(7); + + -- Full at half capacity + vcLocBuffFull <= rxFifoFull or rxFifoCount(8); + end if; + end process; + + -- Async FIFO + U_RegRxAFifo: pgp_afifo_20x511 port map ( + din => rxFifoDin, + rd_clk => locClk, + rd_en => rxFifoRd, + rst => pgpReset, + wr_clk => pgpClk, + wr_en => vcFrameRxValid, + dout => rxFifoDout, + empty => rxFifoEmpty, + full => rxFifoFull, + wr_data_count => rxFifoCount + ); + + -- Data valid + process ( locClk, locReset ) begin + if locReset = '1' then + rxFifoValid <= '0' after tpd; + elsif rising_edge(locClk) then + if rxFifoRd = '1' then + rxFifoValid <= '1' after tpd; + elsif frameRxReady = '1' then + rxFifoValid <= '0' after tpd; + end if; + end if; + end process; + + -- Control reads + rxFifoRd <= (not rxFifoEmpty) and ((not rxFifoValid) or frameRxReady); + + -- Outgoing signals + frameRxValid <= rxFifoValid; + frameRxSOF <= rxFifoDout(18); + frameRxEOF <= rxFifoDout(17); + frameRxEOFE <= rxFifoDout(16); + frameRxData <= rxFifoDout(15 downto 0); + +end PgpDsBuff; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/applications/PgpFrontEnd.vhd b/rce/fw-hsio/modules/pgp2/hdl/applications/PgpFrontEnd.vhd new file mode 100644 index 00000000..2cf08527 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/applications/PgpFrontEnd.vhd @@ -0,0 +1,630 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol Applications, Front End Wrapper +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : PgpFrontEnd.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 09/24/2007 +------------------------------------------------------------------------------- +-- Description: +-- Wrapper for front end logic connection to the RCE. +------------------------------------------------------------------------------- +-- Copyright (c) 2007 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 09/24/2007: created. +-- 03/06/2008: Removed width signal. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use work.Version.all; +use work.Pgp2MgtPackage.all; +use work.Pgp2AppPackage.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity PgpFrontEnd is + generic ( + MgtMode : string := "A"; -- Default Location + RefClkSel : string := "REFCLK1" -- Reference Clock To Use "REFCLK1" or "REFCLK2" + ); + port ( + + -- Reference Clock, PGP Clock & Reset Signals + -- Use one ref clock, tie other to 0, see RefClkSel above + pgpRefClk1 : in std_logic; + pgpRefClk2 : in std_logic; + mgtRxRecClk : out std_logic; + pgpClk : in std_logic; + pgpReset : in std_logic; + + -- Display Digits + pgpDispA : out std_logic_vector(7 downto 0); + pgpDispB : out std_logic_vector(7 downto 0); + + -- Reset output + resetOut : out std_logic; + + -- Local clock and reset + locClk : in std_logic; + locReset : in std_logic; + + -- Local command signal + cmdEn : out std_logic; + cmdOpCode : out std_logic_vector(7 downto 0); + cmdCtxOut : out std_logic_vector(23 downto 0); + + -- Local register control signals + regReq : out std_logic; + regOp : out std_logic; + regInp : out std_logic; + regAck : in std_logic; + regFail : in std_logic; + regAddr : out std_logic_vector(23 downto 0); + regDataOut : out std_logic_vector(31 downto 0); + regDataIn : in std_logic_vector(31 downto 0); + + -- Local data transfer signals + frameTxEnable : in std_logic; + frameTxSOF : in std_logic; + frameTxEOF : in std_logic; + frameTxEOFE : in std_logic; + frameTxData : in std_logic_vector(15 downto 0); + frameTxAFull : out std_logic; + frameRxValid : out std_logic; + frameRxReady : in std_logic; + frameRxSOF : out std_logic; + frameRxEOF : out std_logic; + frameRxEOFE : out std_logic; + frameRxData : out std_logic_vector(15 downto 0); + valid : out std_logic; + eof : out std_logic; + sof : out std_logic; + + -- MGT Serial Pins + mgtRxN : in std_logic; + mgtRxP : in std_logic; + mgtTxN : out std_logic; + mgtTxP : out std_logic; + + -- MGT Signals For Simulation, + -- Drive mgtCombusIn to 0's, Leave mgtCombusOut open for real use + mgtCombusIn : in std_logic_vector(15 downto 0); + mgtCombusOut : out std_logic_vector(15 downto 0) + ); +end PgpFrontEnd; + + +-- Define architecture +architecture PgpFrontEnd of PgpFrontEnd is + + -- Downstream buffer + component PgpDsBuff + port ( + pgpClk : in std_logic; + pgpReset : in std_logic; + locClk : in std_logic; + locReset : in std_logic; + vcFrameRxValid : in std_logic; + vcFrameRxSOF : in std_logic; + vcFrameRxWidth : in std_logic; + vcFrameRxEOF : in std_logic; + vcFrameRxEOFE : in std_logic; + vcFrameRxData : in std_logic_vector(15 downto 0); + vcLocBuffAFull : out std_logic; + vcLocBuffFull : out std_logic; + frameRxValid : out std_logic; + frameRxReady : in std_logic; + frameRxSOF : out std_logic; + frameRxEOF : out std_logic; + frameRxEOFE : out std_logic; + frameRxData : out std_logic_vector(15 downto 0) + ); + end component; + + -- Local Signals + signal pibReLink : std_logic; + signal vc0FrameTxValid : std_logic; + signal vc0FrameTxReady : std_logic; + signal vc0FrameTxSOF : std_logic; + signal vc0FrameTxEOF : std_logic; + signal vc0FrameTxEOFE : std_logic; + signal vc0FrameTxData : std_logic_vector(15 downto 0); + signal vc0RemBuffAFull : std_logic; + signal vc0RemBuffFull : std_logic; + signal vc1FrameTxValid : std_logic; + signal vc1FrameTxReady : std_logic; + signal vc1FrameTxSOF : std_logic; + signal vc1FrameTxEOF : std_logic; + signal vc1FrameTxEOFE : std_logic; + signal vc1FrameTxData : std_logic_vector(15 downto 0); + signal vc1RemBuffAFull : std_logic; + signal vc1RemBuffFull : std_logic; + signal vc2FrameTxValid : std_logic; + signal vc2FrameTxReady : std_logic; + signal vc2FrameTxSOF : std_logic; + signal vc2FrameTxEOF : std_logic; + signal vc2FrameTxEOFE : std_logic; + signal vc2FrameTxData : std_logic_vector(15 downto 0); + signal vc2RemBuffAFull : std_logic; + signal vc2RemBuffFull : std_logic; + signal vc3FrameTxValid : std_logic; + signal vc3FrameTxReady : std_logic; + signal vc3FrameTxSOF : std_logic; + signal vc3FrameTxEOF : std_logic; + signal vc3FrameTxEOFE : std_logic; + signal vc3FrameTxData : std_logic_vector(15 downto 0); + signal vc3RemBuffAFull : std_logic; + signal vc3RemBuffFull : std_logic; + signal vc0FrameRxValid : std_logic; + signal vcFrameRxSOF : std_logic; + signal vcFrameRxEOF : std_logic; + signal vcFrameRxEOFE : std_logic; + signal vcFrameRxData : std_logic_vector(15 downto 0); + signal vc0LocBuffAFull : std_logic; + signal vc0LocBuffFull : std_logic; + signal vc1FrameRxValid : std_logic; + signal vc1LocBuffAFull : std_logic; + signal vc1LocBuffFull : std_logic; + signal vc2FrameRxValid : std_logic; + signal vc2LocBuffAFull : std_logic; + signal vc2LocBuffFull : std_logic; + signal vc3FrameRxValid : std_logic; + signal vc3LocBuffAFull : std_logic; + signal vc3LocBuffFull : std_logic; + signal pibLock : std_logic_vector(1 downto 0); + signal countLinkDown : std_logic; + signal countLinkError : std_logic; + signal countCellError : std_logic; + signal cntLinkError : std_logic_vector(3 downto 0); + signal cntCellError : std_logic_vector(3 downto 0); + signal cntLinkDown : std_logic_vector(3 downto 0); + signal cntOverFlow : std_logic_vector(3 downto 0); + signal pllLock : std_logic; + signal pllLockDly : std_logic; + signal cntPllLock : std_logic_vector(3 downto 0); + signal intRegReq : std_logic; + signal intRegOp : std_logic; + signal intRegAck : std_logic; + signal intRegFail : std_logic; + signal intRegAddr : std_logic_vector(23 downto 0); + signal intRegDataOut : std_logic_vector(31 downto 0); + signal intRegDataIn : std_logic_vector(31 downto 0); + signal intCmdEn : std_logic; + signal intCmdOpCode : std_logic_vector(7 downto 0); + signal intCmdCtxOut : std_logic_vector(23 downto 0); + signal scratchPad : std_logic_vector(31 downto 0); + signal countReset : std_logic; + signal dataOverFlow : std_logic; + signal intCmdAFull : std_logic; + signal intCmdFull : std_logic; + signal extCmdAFull : std_logic; + signal extCmdFull : std_logic; + signal pibError : std_logic; + signal txCount : std_logic_vector(31 downto 0); + signal pibLinkReady : std_logic; + signal iframeTxAFull : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Display values + pgpDispB <= x"0" & txCount(3 downto 0); + pgpDispA <= x"10" when pllLock = '0' else -- Display 'P' + x"11" when pibLinkReady = '0' else -- Display 'N' + x"0E" when pibError = '1' else -- Display 'E' + x"12"; -- Display 'L' + + -- Detect error status + pibError <= '1' when (cntLinkError & cntCellError) /= 0 else '0'; + + -- Transaction Counter + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + txCount <= (others=>'0') after tpd; + elsif rising_edge(pgpClk) then + if pibLinkReady = '0' then + txCount <= (others=>'0') after tpd; + else + if (vc0FrameTxReady = '1' and vc0FrameTxEOF = '1') or + (vc1FrameTxReady = '1' and vc1FrameTxEOF = '1') or + (vc2FrameTxReady = '1' and vc2FrameTxEOF = '1') or + (vc3FrameTxReady = '1' and vc3FrameTxEOF = '1') then + txCount <= txCount + 1 after tpd; + end if; + end if; + end if; + end process; + + + -- Register read and write + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + intRegDataIn <= (others=>'0') after tpd; + intRegAck <= '0' after tpd; + intRegFail <= '0' after tpd; + scratchPad <= (others=>'0') after tpd; + elsif rising_edge(pgpClk) then + + -- Register request is pending + if intRegReq = '1' then + + -- Drive ack + intRegAck <= '1' after tpd; + + -- Read + if intRegOp = '0' then + + -- Which register + case intRegAddr is + + when x"000000" => + intRegDataIn <= FpgaVersion after tpd; + intRegFail <= '0' after tpd; + + when x"000001" => + intRegDataIn <= scratchPad after tpd; + intRegFail <= '0' after tpd; + + when x"000002" => + intRegDataIn(31) <= '0' after tpd; + intRegDataIn(30) <= '0' after tpd; + intRegDataIn(29) <= '0' after tpd; + intRegDataIn(28) <= '0' after tpd; + intRegDataIn(27 downto 24) <= cntOverFlow after tpd; + intRegDataIn(23 downto 20) <= cntPllLock after tpd; + intRegDataIn(19 downto 16) <= cntLinkDown after tpd; + intRegDataIn(15 downto 12) <= cntLinkError after tpd; + intRegDataIn(11 downto 8) <= (others=>'0') after tpd; + intRegDataIn( 7 downto 4) <= cntCellError after tpd; + intRegDataIn( 3 downto 0) <= "0000" after tpd; + intRegFail <= '0' after tpd; + + when x"000003" => + intRegDataIn <= txCount after tpd; + intRegFail <= '0' after tpd; + + when others => + intRegFail <= '1' after tpd; + intRegDataIn <= (others=>'0') after tpd; + end case; + + -- Write + else + + -- Scratchpad write + if intRegAddr = x"000001" then + intRegFail <= '0' after tpd; + scratchPad <= intRegDataOut after tpd; + else + intRegFail <= '1' after tpd; + end if; + end if; + + -- No Request + else + intRegAck <= '0' after tpd; + intRegFail <= '0' after tpd; + intRegDataIn <= (others=>'0') after tpd; + end if; + end if; + end process; + + + -- Internal command receiver + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + countReset <= '0' after tpd; + pibReLink <= '0' after tpd; + resetOut <= '0' after tpd; + elsif rising_edge(pgpClk) then + + -- Internal command received + if intCmdEn = '1' then + + -- Reset + if intCmdOpCode = "00000000" then + resetOut <= '1' after tpd; + countReset <= '0' after tpd; + pibReLink <= '0' after tpd; + + -- Count Reset + elsif intCmdOpCode = "00000001" then + countReset <= '1' after tpd; + pibReLink <= '0' after tpd; + + -- PGP Relink + elsif intCmdOpCode = "00000010" then + countReset <= '0' after tpd; + pibReLink <= '1' after tpd; + + else + countReset <= '0' after tpd; + pibReLink <= '0' after tpd; + end if; + else + countReset <= '0' after tpd; + pibReLink <= '0' after tpd; + end if; + end if; + end process; + + + -- Error Counters + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + cntLinkError <= (others=>'0') after tpd; + cntCellError <= (others=>'0') after tpd; + cntLinkDown <= (others=>'0') after tpd; + cntPllLock <= (others=>'0') after tpd; + cntOverFlow <= (others=>'0') after tpd; + pllLock <= '0' after tpd; + pllLockDly <= '0' after tpd; + elsif rising_edge(pgpClk) then + + -- Link Error Counter, 8-bits + if countReset = '1' or pibLinkReady = '0' then + cntLinkError <= (others=>'0') after tpd; + elsif countLinkError = '1' and cntLinkError /= x"F" then + cntLinkError <= cntLinkError + 1 after tpd; + end if; + + -- Cell Error Counter, 8-bits + if countReset = '1' or pibLinkReady = '0' then + cntCellError <= (others=>'0') after tpd; + elsif countCellError = '1' and cntCellError /= x"F" then + cntCellError <= cntCellError + 1 after tpd; + end if; + + -- Link Down Counter, 8-bits + if countReset = '1' then + cntLinkDown <= (others=>'0') after tpd; + elsif countLinkDown = '1' and cntLinkDown /= x"F" then + cntLinkDown <= cntLinkDown + 1 after tpd; + end if; + + -- PLL Unlock Counter + if countReset = '1' or pibLinkReady = '0' then + cntPllLock <= (others=>'0') after tpd; + elsif pllLock = '0' and pllLockDly = '1' and cntPllLock /= x"F" then + cntPllLock <= cntPllLock + 1 after tpd; + end if; + + -- PLL Lock Edge Detection + pllLock <= pibLock(1) and pibLock(0) after tpd; + pllLockDly <= pllLock after tpd; + + -- Data overflow counter + if countReset = '1' then + cntOverFlow <= (others=>'0') after tpd; + elsif dataOverFlow = '1'and cntOverFlow /= x"F" then + cntOverFlow <= cntOverFlow + 1 after tpd; + end if; + + end if; + end process; + + -- PGP Wrap + U_Pgp2Mgt16: Pgp2Mgt16 + generic map ( + EnShortCells => 1, + VcInterleave => 0, + MgtMode => MgtMode, + RefClkSel => RefClkSel + ) + port map ( + pgpClk => pgpClk, + pgpReset => pgpReset, + pgpFlush => '0', + pllTxRst => '0', + pllRxRst => pibReLink, + pllRxReady => pibLock(0), + pllTxReady => pibLock(1), + pgpRemData => open, + pgpLocData => (others=>'0'), + pgpTxOpCodeEn => '0', + pgpTxOpCode => (others=>'0'), + pgpRxOpCodeEn => open, + pgpRxOpCode => open, + pgpLocLinkReady => pibLinkReady, + pgpRemLinkReady => open, + pgpRxCellError => countCellError, + pgpRxLinkDown => countLinkDown, + pgpRxLinkError => countLinkError, + vc0FrameTxValid => vc0FrameTxValid, + vc0FrameTxReady => vc0FrameTxReady, + vc0FrameTxSOF => vc0FrameTxSOF, + vc0FrameTxEOF => vc0FrameTxEOF, + vc0FrameTxEOFE => vc0FrameTxEOFE, + vc0FrameTxData => vc0FrameTxData, + vc0LocBuffAFull => vc0LocBuffAFull, + vc0LocBuffFull => vc0LocBuffFull, + vc1FrameTxValid => vc1FrameTxValid, + vc1FrameTxReady => vc1FrameTxReady, + vc1FrameTxSOF => vc1FrameTxSOF, + vc1FrameTxEOF => vc1FrameTxEOF, + vc1FrameTxEOFE => vc1FrameTxEOFE, + vc1FrameTxData => vc1FrameTxData, + vc1LocBuffAFull => vc1LocBuffAFull, + vc1LocBuffFull => vc1LocBuffFull, + vc2FrameTxValid => vc2FrameTxValid, + vc2FrameTxReady => vc2FrameTxReady, + vc2FrameTxSOF => vc2FrameTxSOF, + vc2FrameTxEOF => vc2FrameTxEOF, + vc2FrameTxEOFE => vc2FrameTxEOFE, + vc2FrameTxData => vc2FrameTxData, + vc2LocBuffAFull => vc2LocBuffAFull, + vc2LocBuffFull => vc2LocBuffFull, + vc3FrameTxValid => vc3FrameTxValid, + vc3FrameTxReady => vc3FrameTxReady, + vc3FrameTxSOF => vc3FrameTxSOF, + vc3FrameTxEOF => vc3FrameTxEOF, + vc3FrameTxEOFE => vc3FrameTxEOFE, + vc3FrameTxData => vc3FrameTxData, + vc3LocBuffAFull => vc3LocBuffAFull, + vc3LocBuffFull => vc3LocBuffFull, + vcFrameRxSOF => vcFrameRxSOF, + vcFrameRxEOF => vcFrameRxEOF, + vcFrameRxEOFE => vcFrameRxEOFE, + vcFrameRxData => vcFrameRxData, + vc0FrameRxValid => vc0FrameRxValid, + vc0RemBuffAFull => vc0RemBuffAFull, + vc0RemBuffFull => vc0RemBuffFull, + vc1FrameRxValid => vc1FrameRxValid, + vc1RemBuffAFull => vc1RemBuffAFull, + vc1RemBuffFull => vc1RemBuffFull, + vc2FrameRxValid => vc2FrameRxValid, + vc2RemBuffAFull => vc2RemBuffAFull, + vc2RemBuffFull => vc2RemBuffFull, + vc3FrameRxValid => vc3FrameRxValid, + vc3RemBuffAFull => vc3RemBuffAFull, + vc3RemBuffFull => vc3RemBuffFull, + mgtLoopback => '0', + mgtRefClk1 => pgpRefClk1, + mgtRefClk2 => pgpRefClk2, + mgtRxRecClk => mgtRxRecClk, + mgtRxN => mgtRxN, + mgtRxP => mgtRxP, + mgtTxN => mgtTxN, + mgtTxP => mgtTxP, + mgtCombusIn => mgtCombusIn, + mgtCombusOut => mgtCombusOut, + debug => open + ); + + -- Lane 0, VC0, External command processor + U_ExtCmd: Pgp2CmdSlave + generic map ( + DestId => 0, + DestMask => 1, + FifoType => "V4" + ) port map ( + pgpRxClk => pgpClk, pgpRxReset => pgpReset, + locClk => locClk, locReset => locReset, + vcFrameRxValid => vc0FrameRxValid, vcFrameRxSOF => vcFrameRxSOF, + vcFrameRxEOF => vcFrameRxEOF, vcFrameRxEOFE => vcFrameRxEOFE, + vcFrameRxData => vcFrameRxData, vcLocBuffAFull => extCmdAFull, + vcLocBuffFull => extCmdFull, cmdEn => cmdEn, + cmdOpCode => cmdOpCode, cmdCtxOut => cmdCtxOut + ); + + -- Lane 0, VC0, Internal command processor + U_IntCmd: Pgp2CmdSlave + generic map ( + DestId => 1, + DestMask => 1, + FifoType => "V4" + ) port map ( + pgpRxClk => pgpClk, pgpRxReset => pgpReset, + locClk => pgpClk, locReset => pgpReset, + vcFrameRxValid => vc0FrameRxValid, vcFrameRxSOF => vcFrameRxSOF, + vcFrameRxEOF => vcFrameRxEOF, vcFrameRxEOFE => vcFrameRxEOFE, + vcFrameRxData => vcFrameRxData, vcLocBuffAFull => intCmdAFull, + vcLocBuffFull => intCmdFull, cmdEn => intCmdEn, + cmdOpCode => intCmdOpCode, cmdCtxOut => intCmdCtxOut + ); + + -- Generate flow control + vc0LocBuffAFull <= extCmdAFull or intCmdAFull; + vc0LocBuffFull <= extCmdFull or intCmdFull; + + -- Return data, Lane 0, VC0 + U_DataBuff0: Pgp2UsBuff generic map ( FifoType => "V4" ) port map ( + pgpClk => pgpClk, + pgpReset => pgpReset, + locClk => locClk, + locReset => locReset, + frameTxValid => frameTxEnable, + frameTxSOF => frameTxSOF, + frameTxEOF => frameTxEOF, + frameTxEOFE => frameTxEOFE, + frameTxData => frameTxData, + frameTxAFull => iframeTxAFull, + vcFrameTxValid => vc0FrameTxValid, + vcFrameTxReady => vc0FrameTxReady, + vcFrameTxSOF => vc0FrameTxSOF, + vcFrameTxEOF => vc0FrameTxEOF, + vcFrameTxEOFE => vc0FrameTxEOFE, + vcFrameTxData => vc0FrameTxData, + vcRemBuffAFull => vc0RemBuffAFull, + vcRemBuffFull => vc0RemBuffFull + ); + dataOverFlow <= frameTxEnable and iframeTxAFull; + frameTxAFull <= iframeTxAFull; + + valid <= vc0FrameTxValid; + eof <= vc0FrameTxEOF; + sof <= vc0FrameTxSOF; + + -- Lane 0, VC1, External register access control + U_ExtReg: Pgp2RegSlave generic map ( FifoType => "V4" ) port map ( + pgpRxClk => pgpClk, pgpRxReset => pgpReset, + pgpTxClk => pgpClk, pgpTxReset => pgpReset, + locClk => locClk, locReset => locReset, + vcFrameRxValid => vc1FrameRxValid, vcFrameRxSOF => vcFrameRxSOF, + vcFrameRxEOF => vcFrameRxEOF, vcFrameRxEOFE => vcFrameRxEOFE, + vcFrameRxData => vcFrameRxData, vcLocBuffAFull => vc1LocBuffAFull, + vcLocBuffFull => vc1LocBuffFull, vcFrameTxValid => vc1FrameTxValid, + vcFrameTxReady => vc1FrameTxReady, vcFrameTxSOF => vc1FrameTxSOF, + vcFrameTxEOF => vc1FrameTxEOF, vcFrameTxEOFE => vc1FrameTxEOFE, + vcFrameTxData => vc1FrameTxData, vcRemBuffAFull => vc1RemBuffAFull, + vcRemBuffFull => vc1RemBuffFull, regInp => regInp, + regReq => regReq, regOp => regOp, + regAck => regAck, regFail => regFail, + regAddr => regAddr, regDataOut => regDataOut, + regDataIn => regDataIn + ); + + -- Lane 0, VC2, Internal register access control + U_IntReg: Pgp2RegSlave generic map ( FifoType => "V4" ) port map ( + pgpRxClk => pgpClk, pgpRxReset => pgpReset, + pgpTxClk => pgpClk, pgpTxReset => pgpReset, + locClk => pgpClk, locReset => pgpReset, + vcFrameRxValid => vc2FrameRxValid, vcFrameRxSOF => vcFrameRxSOF, + vcFrameRxEOF => vcFrameRxEOF, vcFrameRxEOFE => vcFrameRxEOFE, + vcFrameRxData => vcFrameRxData, vcLocBuffAFull => vc2LocBuffAFull, + vcLocBuffFull => vc2LocBuffFull, vcFrameTxValid => vc2FrameTxValid, + vcFrameTxReady => vc2FrameTxReady, vcFrameTxSOF => vc2FrameTxSOF, + vcFrameTxEOF => vc2FrameTxEOF, vcFrameTxEOFE => vc2FrameTxEOFE, + vcFrameTxData => vc2FrameTxData, vcRemBuffAFull => vc2RemBuffAFull, + vcRemBuffFull => vc2RemBuffFull, regInp => open, + regReq => intRegReq, regOp => intRegOp, + regAck => intRegAck, regFail => intRegFail, + regAddr => intRegAddr, regDataOut => intRegDataOut, + regDataIn => intRegDataIn + ); + + -- VC3, Downstream data + U_DsBuff: Pgp2DsBuff generic map ( FifoType => "V4" ) port map ( + pgpClk => pgpClk, + pgpReset => pgpReset, + locClk => locClk, + locReset => locReset, + vcFrameRxValid => vc3FrameRxValid, + vcFrameRxSOF => vcFrameRxSOF, + vcFrameRxEOF => vcFrameRxEOF, + vcFrameRxEOFE => vcFrameRxEOFE, + vcFrameRxData => vcFrameRxData, + vcLocBuffAFull => vc3LocBuffAFull, + vcLocBuffFull => vc3LocBuffFull, + frameRxValid => frameRxValid, + frameRxReady => frameRxReady, + frameRxSOF => frameRxSOF, + frameRxEOF => frameRxEOF, + frameRxEOFE => frameRxEOFE, + frameRxData => frameRxData + ); + + -- VC3 transmit is unused + vc3FrameTxValid <= '0'; + vc3FrameTxEOFE <= '0'; + vc3FrameTxEOF <= '0'; + vc3FrameTxSOF <= '0'; + vc3FrameTxData <= (others=>'0'); + +end PgpFrontEnd; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/core/Pgp2CorePackage.vhd b/rce/fw-hsio/modules/pgp2/hdl/core/Pgp2CorePackage.vhd new file mode 100755 index 00000000..7caf28fa --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/core/Pgp2CorePackage.vhd @@ -0,0 +1,341 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, Core Package +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2CorePackage.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 05/27/2009 +------------------------------------------------------------------------------- +-- Description: +-- PGP ID and other global constants. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 05/27/2009: created. +-- 11/23/2009: Renamed package. +-- 12/13/2010: Added received init line to help linking. +-- 06/25/2010: Added payload size config as generic. +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; + +package Pgp2CorePackage is + + -- 8B10B Characters + constant K_COM : std_logic_vector(7 downto 0) := "10111100"; -- K28.5, 0xBC + constant K_LTS : std_logic_vector(7 downto 0) := "00111100"; -- K28.1, 0x3C + constant D_102 : std_logic_vector(7 downto 0) := "01001010"; -- D10.2, 0x4A + constant D_215 : std_logic_vector(7 downto 0) := "10110101"; -- D21.5, 0xB5 + constant K_SKP : std_logic_vector(7 downto 0) := "00011100"; -- K28.0, 0x1C + constant K_OTS : std_logic_vector(7 downto 0) := "01111100"; -- K28.3, 0x7C + constant K_ALN : std_logic_vector(7 downto 0) := "11011100"; -- K28.6, 0xDC + constant K_SOC : std_logic_vector(7 downto 0) := "11111011"; -- K27.7, 0xFB + constant K_SOF : std_logic_vector(7 downto 0) := "11110111"; -- K23.7, 0xF7 + constant K_EOF : std_logic_vector(7 downto 0) := "11111101"; -- K29.7, 0xFD + constant K_EOFE : std_logic_vector(7 downto 0) := "11111110"; -- K30.7, 0xFE + constant K_EOC : std_logic_vector(7 downto 0) := "01011100"; -- K28.2, 0x5C + + -- ID Constant + constant Pgp2Id : std_logic_vector(3 downto 0) := "0101"; + + -- PGP Receive Core + component Pgp2Rx + generic ( + RxLaneCnt : integer := 4; + EnShortCells : integer := 1; + PayloadCntTop : integer := 7 + ); + port ( + pgpRxClk : in std_logic; + pgpRxReset : in std_logic; + pgpRxFlush : in std_logic; + pgpRxLinkReady : out std_logic; + pgpRxCellError : out std_logic; + pgpRxLinkDown : out std_logic; + pgpRxLinkError : out std_logic; + pgpRxOpCodeEn : out std_logic; + pgpRxOpCode : out std_logic_vector(7 downto 0); + pgpRemLinkReady : out std_logic; + pgpRemData : out std_logic_vector(7 downto 0); + vcFrameRxSOF : out std_logic; + vcFrameRxEOF : out std_logic; + vcFrameRxEOFE : out std_logic; + vcFrameRxData : out std_logic_vector(RxLaneCnt*16-1 downto 0); + vc0FrameRxValid : out std_logic; + vc0RemBuffAFull : out std_logic; + vc0RemBuffFull : out std_logic; + vc1FrameRxValid : out std_logic; + vc1RemBuffAFull : out std_logic; + vc1RemBuffFull : out std_logic; + vc2FrameRxValid : out std_logic; + vc2RemBuffAFull : out std_logic; + vc2RemBuffFull : out std_logic; + vc3FrameRxValid : out std_logic; + vc3RemBuffAFull : out std_logic; + vc3RemBuffFull : out std_logic; + phyRxPolarity : out std_logic_vector(RxLaneCnt-1 downto 0); + phyRxData : in std_logic_vector(RxLaneCnt*16-1 downto 0); + phyRxDataK : in std_logic_vector(RxLaneCnt*2-1 downto 0); + phyRxDispErr : in std_logic_vector(RxLaneCnt*2-1 downto 0); + phyRxDecErr : in std_logic_vector(RxLaneCnt*2-1 downto 0); + phyRxReady : in std_logic; + phyRxInit : out std_logic; + crcRxIn : out std_logic_vector(RxLaneCnt*16-1 downto 0); + crcRxWidth : out std_logic; + crcRxInit : out std_logic; + crcRxValid : out std_logic; + crcRxOut : in std_logic_vector(31 downto 0); + debug : out std_logic_vector(63 downto 0) + ); + end component; + + -- PGP Transmit Core + component Pgp2Tx + generic ( + TxLaneCnt : integer := 4; + VcInterleave : integer := 1; + PayloadCntTop : integer := 7 + ); + port ( + pgpTxClk : in std_logic; + pgpTxReset : in std_logic; + pgpTxFlush : in std_logic; + pgpTxLinkReady : out std_logic; + pgpTxOpCodeEn : in std_logic; + pgpTxOpCode : in std_logic_vector(7 downto 0); + pgpLocLinkReady : in std_logic; + pgpLocData : in std_logic_vector(7 downto 0); + vc0FrameTxValid : in std_logic; + vc0FrameTxReady : out std_logic; + vc0FrameTxSOF : in std_logic; + vc0FrameTxEOF : in std_logic; + vc0FrameTxEOFE : in std_logic; + vc0FrameTxData : in std_logic_vector(TxLaneCnt*16-1 downto 0); + vc0LocBuffAFull : in std_logic; + vc0LocBuffFull : in std_logic; + vc1FrameTxValid : in std_logic; + vc1FrameTxReady : out std_logic; + vc1FrameTxSOF : in std_logic; + vc1FrameTxEOF : in std_logic; + vc1FrameTxEOFE : in std_logic; + vc1FrameTxData : in std_logic_vector(TxLaneCnt*16-1 downto 0); + vc1LocBuffAFull : in std_logic; + vc1LocBuffFull : in std_logic; + vc2FrameTxValid : in std_logic; + vc2FrameTxReady : out std_logic; + vc2FrameTxSOF : in std_logic; + vc2FrameTxEOF : in std_logic; + vc2FrameTxEOFE : in std_logic; + vc2FrameTxData : in std_logic_vector(TxLaneCnt*16-1 downto 0); + vc2LocBuffAFull : in std_logic; + vc2LocBuffFull : in std_logic; + vc3FrameTxValid : in std_logic; + vc3FrameTxReady : out std_logic; + vc3FrameTxSOF : in std_logic; + vc3FrameTxEOF : in std_logic; + vc3FrameTxEOFE : in std_logic; + vc3FrameTxData : in std_logic_vector(TxLaneCnt*16-1 downto 0); + vc3LocBuffAFull : in std_logic; + vc3LocBuffFull : in std_logic; + phyTxData : out std_logic_vector(TxLaneCnt*16-1 downto 0); + phyTxDataK : out std_logic_vector(TxLaneCnt*2-1 downto 0); + phyTxReady : in std_logic; + crcTxIn : out std_logic_vector(TxLaneCnt*16-1 downto 0); + crcTxInit : out std_logic; + crcTxValid : out std_logic; + crcTxOut : in std_logic_vector(31 downto 0); + debug : out std_logic_vector(63 downto 0) + ); + end component; + + -- Phy Interface + component Pgp2RxPhy + generic ( + RxLaneCnt : integer := 4 -- Number of receive lanes, 1-4 + ); + port ( + pgpRxClk : in std_logic; -- Master clock + pgpRxReset : in std_logic; -- Synchronous reset input + pgpRxLinkReady : out std_logic; -- Local side has link + pgpRxLinkDown : out std_logic; -- A link down event has occured + pgpRxLinkError : out std_logic; -- A link error has occured + pgpRxOpCodeEn : out std_logic; -- Opcode receive enable + pgpRxOpCode : out std_logic_vector(7 downto 0); -- Opcode receive value + pgpRemLinkReady : out std_logic; -- Far end side has link + pgpRemData : out std_logic_vector(7 downto 0); -- Far end side User Data + cellRxPause : out std_logic; -- Cell data pause + cellRxSOC : out std_logic; -- Cell data start of cell + cellRxSOF : out std_logic; -- Cell data start of frame + cellRxEOC : out std_logic; -- Cell data end of cell + cellRxEOF : out std_logic; -- Cell data end of frame + cellRxEOFE : out std_logic; -- Cell data end of frame error + cellRxData : out std_logic_vector(RxLaneCnt*16-1 downto 0); -- Cell data data + phyRxPolarity : out std_logic_vector(RxLaneCnt-1 downto 0); -- PHY receive signal polarity + phyRxData : in std_logic_vector(RxLaneCnt*16-1 downto 0); -- PHY receive data + phyRxDataK : in std_logic_vector(RxLaneCnt*2-1 downto 0); -- PHY receive data is K character + phyRxDispErr : in std_logic_vector(RxLaneCnt*2-1 downto 0); -- PHY receive data has disparity error + phyRxDecErr : in std_logic_vector(RxLaneCnt*2-1 downto 0); -- PHY receive data not in table + phyRxReady : in std_logic; -- PHY receive interface is ready + phyRxInit : out std_logic; + debug : out std_logic_vector(63 downto 0) + ); + end component; + + -- Cell Receiver + component Pgp2RxCell + generic ( + RxLaneCnt : integer := 4; + EnShortCells : integer := 1; + PayloadCntTop : integer := 7 + ); + port ( + pgpRxClk : in std_logic; -- Master clock + pgpRxReset : in std_logic; -- Synchronous reset input + pgpRxFlush : in std_logic; -- Flush the link + pgpRxLinkReady : in std_logic; -- Local side has link + pgpRxCellError : out std_logic; -- A cell error has occured + cellRxPause : in std_logic; -- Cell data pause + cellRxSOC : in std_logic; -- Cell data start of cell + cellRxSOF : in std_logic; -- Cell data start of frame + cellRxEOC : in std_logic; -- Cell data end of cell + cellRxEOF : in std_logic; -- Cell data end of frame + cellRxEOFE : in std_logic; -- Cell data end of frame error + cellRxData : in std_logic_vector(RxLaneCnt*16-1 downto 0); -- Cell data data + vcFrameRxSOF : out std_logic; -- PGP frame data start of frame + vcFrameRxEOF : out std_logic; -- PGP frame data end of frame + vcFrameRxEOFE : out std_logic; -- PGP frame data error + vcFrameRxData : out std_logic_vector(RxLaneCnt*16-1 downto 0); -- PGP frame data + vc0FrameRxValid : out std_logic; -- PGP frame data is valid + vc0RemBuffAFull : out std_logic; -- Remote buffer almost full + vc0RemBuffFull : out std_logic; -- Remote buffer full + vc1FrameRxValid : out std_logic; -- PGP frame data is valid + vc1RemBuffAFull : out std_logic; -- Remote buffer almost full + vc1RemBuffFull : out std_logic; -- Remote buffer full + vc2FrameRxValid : out std_logic; -- PGP frame data is valid + vc2RemBuffAFull : out std_logic; -- Remote buffer almost full + vc2RemBuffFull : out std_logic; -- Remote buffer full + vc3FrameRxValid : out std_logic; -- PGP frame data is valid + vc3RemBuffAFull : out std_logic; -- Remote buffer almost full + vc3RemBuffFull : out std_logic; -- Remote buffer full + crcRxIn : out std_logic_vector(RxLaneCnt*16-1 downto 0); -- Receive data for CRC + crcRxWidth : out std_logic; -- Receive CRC width, 1=full, 0=32-bit + crcRxInit : out std_logic; -- Receive CRC value init + crcRxValid : out std_logic; -- Receive data for CRC is valid + crcRxOut : in std_logic_vector(31 downto 0) -- Receive calculated CRC value + ); + end component; + + -- Phy Interface + component Pgp2TxPhy + generic ( + TxLaneCnt : integer := 4 -- Number of receive lanes, 1-4 + ); + port ( + pgpTxClk : in std_logic; -- Master clock + pgpTxReset : in std_logic; -- Synchronous reset input + pgpTxLinkReady : out std_logic; -- Local side has link + pgpTxOpCodeEn : in std_logic; -- Opcode receive enable + pgpTxOpCode : in std_logic_vector(7 downto 0); -- Opcode receive value + pgpLocLinkReady : in std_logic; -- Far end side has link + pgpLocData : in std_logic_vector(7 downto 0); -- Far end side User Data + cellTxSOC : in std_logic; -- Cell data start of cell + cellTxSOF : in std_logic; -- Cell data start of frame + cellTxEOC : in std_logic; -- Cell data end of cell + cellTxEOF : in std_logic; -- Cell data end of frame + cellTxEOFE : in std_logic; -- Cell data end of frame error + cellTxData : in std_logic_vector(TxLaneCnt*16-1 downto 0); -- Cell data data + phyTxData : out std_logic_vector(TxLaneCnt*16-1 downto 0); -- PHY receive data + phyTxDataK : out std_logic_vector(TxLaneCnt*2-1 downto 0); -- PHY receive data is K character + phyTxReady : in std_logic; -- PHY receive interface is ready + debug : out std_logic_vector(63 downto 0) + ); + end component; + + -- Cell Transmit Block + component Pgp2TxCell + generic ( + TxLaneCnt : integer := 4; + PayloadCntTop : integer := 7 + ); + port ( + pgpTxClk : in std_logic; -- Master clock + pgpTxReset : in std_logic; -- Synchronous reset input + pgpTxLinkReady : in std_logic; -- Local side has link + cellTxSOC : out std_logic; -- Cell data start of cell + cellTxSOF : out std_logic; -- Cell data start of frame + cellTxEOC : out std_logic; -- Cell data end of cell + cellTxEOF : out std_logic; -- Cell data end of frame + cellTxEOFE : out std_logic; -- Cell data end of frame error + cellTxData : out std_logic_vector(TxLaneCnt*16-1 downto 0); -- Cell data data + schTxSOF : out std_logic; -- Cell contained SOF + schTxEOF : out std_logic; -- Cell contained EOF + schTxIdle : in std_logic; -- Force IDLE transmit + schTxReq : in std_logic; -- Cell transmit request + schTxAck : out std_logic; -- Cell transmit acknowledge + schTxDataVc : in std_logic_vector(1 downto 0); -- Cell transmit virtual channel + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc0FrameTxReady : out std_logic; -- PGP is ready + vc0FrameTxSOF : in std_logic; -- User frame data start of frame + vc0FrameTxEOF : in std_logic; -- User frame data end of frame + vc0FrameTxEOFE : in std_logic; -- User frame data error + vc0FrameTxData : in std_logic_vector(TxLaneCnt*16-1 downto 0); -- User frame data + vc0LocBuffAFull : in std_logic; -- Remote buffer almost full + vc0LocBuffFull : in std_logic; -- Remote buffer full + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxReady : out std_logic; -- PGP is ready + vc1FrameTxSOF : in std_logic; -- User frame data start of frame + vc1FrameTxEOF : in std_logic; -- User frame data end of frame + vc1FrameTxEOFE : in std_logic; -- User frame data error + vc1FrameTxData : in std_logic_vector(TxLaneCnt*16-1 downto 0); -- User frame data + vc1LocBuffAFull : in std_logic; -- Remote buffer almost full + vc1LocBuffFull : in std_logic; -- Remote buffer full + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxReady : out std_logic; -- PGP is ready + vc2FrameTxSOF : in std_logic; -- User frame data start of frame + vc2FrameTxEOF : in std_logic; -- User frame data end of frame + vc2FrameTxEOFE : in std_logic; -- User frame data error + vc2FrameTxData : in std_logic_vector(TxLaneCnt*16-1 downto 0); -- User frame data + vc2LocBuffAFull : in std_logic; -- Remote buffer almost full + vc2LocBuffFull : in std_logic; -- Remote buffer full + vc3FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxReady : out std_logic; -- PGP is ready + vc3FrameTxSOF : in std_logic; -- User frame data start of frame + vc3FrameTxEOF : in std_logic; -- User frame data end of frame + vc3FrameTxEOFE : in std_logic; -- User frame data error + vc3FrameTxData : in std_logic_vector(TxLaneCnt*16-1 downto 0); -- User frame data + vc3LocBuffAFull : in std_logic; -- Remote buffer almost full + vc3LocBuffFull : in std_logic; -- Remote buffer full + crcTxIn : out std_logic_vector(TxLaneCnt*16-1 downto 0); -- Transmit data for CRC + crcTxInit : out std_logic; -- Transmit CRC value init + crcTxValid : out std_logic; -- Transmit data for CRC is valid + crcTxOut : in std_logic_vector(31 downto 0) -- Transmit calculated CRC value + ); + end component; + + -- Scheduler + component Pgp2TxSched + generic ( + VcInterleave : integer := 1 -- Interleave Frames + ); + port ( + pgpTxClk : in std_logic; -- Master clock + pgpTxReset : in std_logic; -- Synchronous reset input + pgpTxFlush : in std_logic; -- Transmit state flush + pgpTxLinkReady : in std_logic; -- Local side has link + schTxSOF : in std_logic; -- Cell contained SOF + schTxEOF : in std_logic; -- Cell contained EOF + schTxIdle : out std_logic; -- Force IDLE transmit + schTxReq : out std_logic; -- Cell transmit request + schTxAck : in std_logic; -- Cell transmit acknowledge + schTxDataVc : out std_logic_vector(1 downto 0); -- Cell transmit virtual channel + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxValid : in std_logic -- User frame data is valid + ); + end component; + +end Pgp2CorePackage; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/core/Pgp2Rx.vhd b/rce/fw-hsio/modules/pgp2/hdl/core/Pgp2Rx.vhd new file mode 100755 index 00000000..9bcb1a93 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/core/Pgp2Rx.vhd @@ -0,0 +1,201 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, Receive Top Level +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2Rx.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 05/18/2009 +------------------------------------------------------------------------------- +-- Description: +-- Cell Receive interface module for the Pretty Good Protocol core. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 05/18/2009: created. +-- 11/23/2009: Renamed package. +-- 01/13/2010: Added received init line to help linking. +-- 06/25/2010: Added payload size config as generic. +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE work.ALL; +USE work.Pgp2CorePackage.ALL; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity Pgp2Rx is + generic ( + RxLaneCnt : integer := 4; -- Number of receive lanes, 1-4 + EnShortCells : integer := 1; -- Enable short non-EOF cells + PayloadCntTop : integer := 7 -- Top bit for payload counter + ); + port ( + + -- System clock, reset & control + pgpRxClk : in std_logic; -- Master clock + pgpRxReset : in std_logic; -- Synchronous reset input + + -- Link flush + pgpRxFlush : in std_logic; -- Flush the link + + -- Link is ready + pgpRxLinkReady : out std_logic; -- Local side has link + + -- Error Flags, one pulse per event + pgpRxCellError : out std_logic; -- A cell error has occured + pgpRxLinkDown : out std_logic; -- A link down event has occured + pgpRxLinkError : out std_logic; -- A link error has occured + + -- Opcode Receive Interface + pgpRxOpCodeEn : out std_logic; -- Opcode receive enable + pgpRxOpCode : out std_logic_vector(7 downto 0); -- Opcode receive value + + -- Sideband data + pgpRemLinkReady : out std_logic; -- Far end side has link + pgpRemData : out std_logic_vector(7 downto 0); -- Far end side User Data + + -- Common Frame Receive Interface For All VCs + vcFrameRxSOF : out std_logic; -- PGP frame data start of frame + vcFrameRxEOF : out std_logic; -- PGP frame data end of frame + vcFrameRxEOFE : out std_logic; -- PGP frame data error + vcFrameRxData : out std_logic_vector(RxLaneCnt*16-1 downto 0); -- PGP frame data + + -- Frame Receive Interface, VC 0 + vc0FrameRxValid : out std_logic; -- PGP frame data is valid + vc0RemBuffAFull : out std_logic; -- Remote buffer almost full + vc0RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 1 + vc1FrameRxValid : out std_logic; -- PGP frame data is valid + vc1RemBuffAFull : out std_logic; -- Remote buffer almost full + vc1RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 2 + vc2FrameRxValid : out std_logic; -- PGP frame data is valid + vc2RemBuffAFull : out std_logic; -- Remote buffer almost full + vc2RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 3 + vc3FrameRxValid : out std_logic; -- PGP frame data is valid + vc3RemBuffAFull : out std_logic; -- Remote buffer almost full + vc3RemBuffFull : out std_logic; -- Remote buffer full + + -- Physical Interface Signals + phyRxPolarity : out std_logic_vector(RxLaneCnt-1 downto 0); -- PHY receive signal polarity + phyRxData : in std_logic_vector(RxLaneCnt*16-1 downto 0); -- PHY receive data + phyRxDataK : in std_logic_vector(RxLaneCnt*2-1 downto 0); -- PHY receive data is K character + phyRxDispErr : in std_logic_vector(RxLaneCnt*2-1 downto 0); -- PHY receive data has disparity error + phyRxDecErr : in std_logic_vector(RxLaneCnt*2-1 downto 0); -- PHY receive data not in table + phyRxReady : in std_logic; -- PHY receive interface is ready + phyRxInit : out std_logic; + + -- Receive CRC Interface + crcRxIn : out std_logic_vector(RxLaneCnt*16-1 downto 0); -- Receive data for CRC + crcRxWidth : out std_logic; -- Receive CRC width, 1=full, 0=32-bit + crcRxInit : out std_logic; -- Receive CRC value init + crcRxValid : out std_logic; -- Receive data for CRC is valid + crcRxOut : in std_logic_vector(31 downto 0); -- Receive calculated CRC value + + -- Debug + debug : out std_logic_vector(63 downto 0) + ); + +end Pgp2Rx; + + +-- Define architecture +architecture Pgp2Rx of Pgp2Rx is + + -- Local Signals + signal cellRxPause : std_logic; + signal cellRxSOC : std_logic; + signal cellRxSOF : std_logic; + signal cellRxEOC : std_logic; + signal cellRxEOF : std_logic; + signal cellRxEOFE : std_logic; + signal cellRxData : std_logic_vector(RxLaneCnt*16-1 downto 0); + signal intRxLinkReady : std_logic; + +begin + + -- Link Ready + pgpRxLinkReady <= intRxLinkReady; + + -- PHY Logic + U_Pgp2RxPhy: Pgp2RxPhy + generic map ( + RxLaneCnt => RxLaneCnt + ) port map ( + pgpRxClk => pgpRxClk, + pgpRxReset => pgpRxReset, + pgpRxLinkReady => intRxLinkReady, + pgpRxLinkDown => pgpRxLinkDown, + pgpRxLinkError => pgpRxLinkError, + pgpRxOpCodeEn => pgpRxOpCodeEn, + pgpRxOpCode => pgpRxOpCode, + pgpRemLinkReady => pgpRemLinkReady, + pgpRemData => pgpRemData, + cellRxPause => cellRxPause, + cellRxSOC => cellRxSOC, + cellRxSOF => cellRxSOF, + cellRxEOC => cellRxEOC, + cellRxEOF => cellRxEOF, + cellRxEOFE => cellRxEOFE, + cellRxData => cellRxData, + phyRxPolarity => phyRxPolarity, + phyRxData => phyRxData, + phyRxDataK => phyRxDataK, + phyRxDispErr => phyRxDispErr, + phyRxDecErr => phyRxDecErr, + phyRxReady => phyRxReady, + phyRxInit => phyRxInit, + debug => debug + ); + + + -- Cell Receiver + U_Pgp2RxCell: Pgp2RxCell + generic map ( + RxLaneCnt => RxLaneCnt, + EnShortCells => EnShortCells, + PayloadCntTop => PayloadCntTop + ) port map ( + pgpRxClk => pgpRxClk, + pgpRxReset => pgpRxReset, + pgpRxFlush => pgpRxFlush, + pgpRxLinkReady => intRxLinkReady, + pgpRxCellError => pgpRxCellError, + cellRxPause => cellRxPause, + cellRxSOC => cellRxSOC, + cellRxSOF => cellRxSOF, + cellRxEOC => cellRxEOC, + cellRxEOF => cellRxEOF, + cellRxEOFE => cellRxEOFE, + cellRxData => cellRxData, + vcFrameRxSOF => vcFrameRxSOF, + vcFrameRxEOF => vcFrameRxEOF, + vcFrameRxEOFE => vcFrameRxEOFE, + vcFrameRxData => vcFrameRxData, + vc0FrameRxValid => vc0FrameRxValid, + vc0RemBuffAFull => vc0RemBuffAFull, + vc0RemBuffFull => vc0RemBuffFull, + vc1FrameRxValid => vc1FrameRxValid, + vc1RemBuffAFull => vc1RemBuffAFull, + vc1RemBuffFull => vc1RemBuffFull, + vc2FrameRxValid => vc2FrameRxValid, + vc2RemBuffAFull => vc2RemBuffAFull, + vc2RemBuffFull => vc2RemBuffFull, + vc3FrameRxValid => vc3FrameRxValid, + vc3RemBuffAFull => vc3RemBuffAFull, + vc3RemBuffFull => vc3RemBuffFull, + crcRxIn => crcRxIn, + crcRxWidth => crcRxWidth, + crcRxInit => crcRxInit, + crcRxValid => crcRxValid, + crcRxOut => crcRxOut + ); + +end Pgp2Rx; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/core/Pgp2RxCell.vhd b/rce/fw-hsio/modules/pgp2/hdl/core/Pgp2RxCell.vhd new file mode 100755 index 00000000..ff6ea516 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/core/Pgp2RxCell.vhd @@ -0,0 +1,744 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, Cell Receive Interface +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2RxCell.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 05/18/2009 +------------------------------------------------------------------------------- +-- Description: +-- Cell Receive interface module for the Pretty Good Protocol core. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 05/18/2009: created. +-- 11/23/2009: Renamed package. +-- 06/25/2010: Added payload size config as generic. +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE work.ALL; +USE work.Pgp2CorePackage.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity Pgp2RxCell is + generic ( + RxLaneCnt : integer := 4; -- Number of receive lanes, 1-4 + EnShortCells : integer := 1; -- Enable short non-EOF cells + PayloadCntTop : integer := 7 -- Top bit for payload counter + ); + port ( + + -- System clock, reset & control + pgpRxClk : in std_logic; -- Master clock + pgpRxReset : in std_logic; -- Synchronous reset input + + -- Link flush + pgpRxFlush : in std_logic; -- Flush the link + + -- Link is ready + pgpRxLinkReady : in std_logic; -- Local side has link + + -- Cell Error, one pulse per error + pgpRxCellError : out std_logic; -- A cell error has occured + + -- Interface to PHY Logic + cellRxPause : in std_logic; -- Cell data pause + cellRxSOC : in std_logic; -- Cell data start of cell + cellRxSOF : in std_logic; -- Cell data start of frame + cellRxEOC : in std_logic; -- Cell data end of cell + cellRxEOF : in std_logic; -- Cell data end of frame + cellRxEOFE : in std_logic; -- Cell data end of frame error + cellRxData : in std_logic_vector(RxLaneCnt*16-1 downto 0); -- Cell data data + + -- Common Frame Receive Interface For All VCs + vcFrameRxSOF : out std_logic; -- PGP frame data start of frame + vcFrameRxEOF : out std_logic; -- PGP frame data end of frame + vcFrameRxEOFE : out std_logic; -- PGP frame data error + vcFrameRxData : out std_logic_vector(RxLaneCnt*16-1 downto 0); -- PGP frame data + + -- Frame Receive Interface, VC 0 + vc0FrameRxValid : out std_logic; -- PGP frame data is valid + vc0RemBuffAFull : out std_logic; -- Remote buffer almost full + vc0RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 1 + vc1FrameRxValid : out std_logic; -- PGP frame data is valid + vc1RemBuffAFull : out std_logic; -- Remote buffer almost full + vc1RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 2 + vc2FrameRxValid : out std_logic; -- PGP frame data is valid + vc2RemBuffAFull : out std_logic; -- Remote buffer almost full + vc2RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 3 + vc3FrameRxValid : out std_logic; -- PGP frame data is valid + vc3RemBuffAFull : out std_logic; -- Remote buffer almost full + vc3RemBuffFull : out std_logic; -- Remote buffer full + + -- Receive CRC Interface + crcRxIn : out std_logic_vector(RxLaneCnt*16-1 downto 0); -- Receive data for CRC + crcRxWidth : out std_logic; -- Receive CRC width, 1=full, 0=32-bit + crcRxInit : out std_logic; -- Receive CRC value init + crcRxValid : out std_logic; -- Receive data for CRC is valid + crcRxOut : in std_logic_vector(31 downto 0) -- Receive calculated CRC value + ); + +end Pgp2RxCell; + + +-- Define architecture +architecture Pgp2RxCell of Pgp2RxCell is + + -- Local Signals + signal dly0SOC : std_logic; + signal dly0SOF : std_logic; + signal dly0EOC : std_logic; + signal dly0EOF : std_logic; + signal dly0EOFE : std_logic; + signal dly0Data : std_logic_vector(RxLaneCnt*16-1 downto 0); + signal dly1SOC : std_logic; + signal dly1SOF : std_logic; + signal dly1EOC : std_logic; + signal dly1EOF : std_logic; + signal dly1EOFE : std_logic; + signal dly1Data : std_logic_vector(RxLaneCnt*16-1 downto 0); + signal dly2SOC : std_logic; + signal dly2SOF : std_logic; + signal dly2EOC : std_logic; + signal dly2EOF : std_logic; + signal dly2EOFE : std_logic; + signal dly2Data : std_logic_vector(RxLaneCnt*16-1 downto 0); + signal dly3SOC : std_logic; + signal dly3SOF : std_logic; + signal dly3EOC : std_logic; + signal dly3EOF : std_logic; + signal dly3EOFE : std_logic; + signal dly3Data : std_logic_vector(RxLaneCnt*16-1 downto 0); + signal dly4SOC : std_logic; + signal dly4SOF : std_logic; + signal dly4EOC : std_logic; + signal dly4EOF : std_logic; + signal dly4EOFE : std_logic; + signal dly4Data : std_logic_vector(RxLaneCnt*16-1 downto 0); + signal dly5SOC : std_logic; + signal dly5SOF : std_logic; + signal dly5EOC : std_logic; + signal dly5EOF : std_logic; + signal dly5EOFE : std_logic; + signal dly5Data : std_logic_vector(RxLaneCnt*16-1 downto 0); + signal dly6SOC : std_logic; + signal dly6SOF : std_logic; + signal dly6EOC : std_logic; + signal dly6EOF : std_logic; + signal dly6EOFE : std_logic; + signal dly6Data : std_logic_vector(RxLaneCnt*16-1 downto 0); + signal dly7SOC : std_logic; + signal dly7SOF : std_logic; + signal dly7EOC : std_logic; + signal dly7EOF : std_logic; + signal dly7EOFE : std_logic; + signal dly7Data : std_logic_vector(RxLaneCnt*16-1 downto 0); + signal intCrcRxValid : std_logic; + signal crcNotZero : std_logic; + signal linkDownCnt : std_logic_vector(4 downto 0); + signal compSOC : std_logic; + signal compData : std_logic_vector(RxLaneCnt*16-1 downto 0); + signal detSOC : std_logic; + signal detSOF : std_logic; + signal outData : std_logic_vector(RxLaneCnt*16-1 downto 0); + signal detEOC : std_logic; + signal detEOF : std_logic; + signal detEOFE : std_logic; + signal inCellEn : std_logic; + signal nxtCellEn : std_logic; + signal inCellSerErr : std_logic; + signal inCellSOF : std_logic; + signal inCellEOC : std_logic; + signal inCellEOF : std_logic; + signal inCellEOFE : std_logic; + signal inCellCnt : std_logic_vector(PayloadCntTop downto 0); + signal vcInFrame : std_logic_vector(3 downto 0); + signal currVc : std_logic_vector(1 downto 0); + signal serErr : std_logic; + signal vc0Serial : std_logic_vector(5 downto 0); + signal vc0Valid : std_logic; + signal vc1Serial : std_logic_vector(5 downto 0); + signal vc1Valid : std_logic; + signal vc2Serial : std_logic_vector(5 downto 0); + signal vc2Valid : std_logic; + signal vc3Serial : std_logic_vector(5 downto 0); + signal vc3Valid : std_logic; + signal abortVc : std_logic_vector(1 downto 0); + signal abortEn : std_logic; + signal intCellError : std_logic; + signal dlyCellError : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Delay stages to line up data with CRC calculation + process ( pgpRxClk, pgpRxReset ) begin + if pgpRxReset = '1' then + dly0SOC <= '0' after tpd; + dly0SOF <= '0' after tpd; + dly0EOC <= '0' after tpd; + dly0EOF <= '0' after tpd; + dly0EOFE <= '0' after tpd; + dly0Data <= (others=>'0') after tpd; + dly1SOC <= '0' after tpd; + dly1SOF <= '0' after tpd; + dly1EOC <= '0' after tpd; + dly1EOF <= '0' after tpd; + dly1EOFE <= '0' after tpd; + dly1Data <= (others=>'0') after tpd; + dly2SOC <= '0' after tpd; + dly2SOF <= '0' after tpd; + dly2EOC <= '0' after tpd; + dly2EOF <= '0' after tpd; + dly2EOFE <= '0' after tpd; + dly2Data <= (others=>'0') after tpd; + dly3SOC <= '0' after tpd; + dly3SOF <= '0' after tpd; + dly3EOC <= '0' after tpd; + dly3EOF <= '0' after tpd; + dly3EOFE <= '0' after tpd; + dly3Data <= (others=>'0') after tpd; + dly4SOC <= '0' after tpd; + dly4SOF <= '0' after tpd; + dly4EOC <= '0' after tpd; + dly4EOF <= '0' after tpd; + dly4EOFE <= '0' after tpd; + dly4Data <= (others=>'0') after tpd; + dly5SOC <= '0' after tpd; + dly5SOF <= '0' after tpd; + dly5EOC <= '0' after tpd; + dly5EOF <= '0' after tpd; + dly5EOFE <= '0' after tpd; + dly5Data <= (others=>'0') after tpd; + dly6SOC <= '0' after tpd; + dly6SOF <= '0' after tpd; + dly6EOC <= '0' after tpd; + dly6EOF <= '0' after tpd; + dly6EOFE <= '0' after tpd; + dly6Data <= (others=>'0') after tpd; + dly7SOC <= '0' after tpd; + dly7SOF <= '0' after tpd; + dly7EOC <= '0' after tpd; + dly7EOF <= '0' after tpd; + dly7EOFE <= '0' after tpd; + dly7Data <= (others=>'0') after tpd; + intCrcRxValid <= '0' after tpd; + elsif rising_edge(pgpRxClk) then + + -- Shift when not paused + if cellRxPause = '0' then + + -- Delay stage 0 + dly0SOC <= cellRxSOC after tpd; + dly0SOF <= cellRxSOF after tpd; + dly0EOC <= cellRxEOC after tpd; + dly0EOF <= cellRxEOF after tpd; + dly0EOFE <= cellRxEOFE after tpd; + dly0Data <= cellRxData after tpd; + + -- Delay stage 1 + dly1SOC <= dly0SOC after tpd; + dly1SOF <= dly0SOF after tpd; + dly1EOC <= dly0EOC after tpd; + dly1EOF <= dly0EOF after tpd; + dly1EOFE <= dly0EOFE after tpd; + dly1Data <= dly0Data after tpd; + + -- Delay stage 2 + dly2SOC <= dly1SOC after tpd; + dly2SOF <= dly1SOF after tpd; + dly2EOC <= dly1EOC after tpd; + dly2EOF <= dly1EOF after tpd; + dly2EOFE <= dly1EOFE after tpd; + dly2Data <= dly1Data after tpd; + + -- Delay stage 3 + dly3SOC <= dly2SOC after tpd; + dly3SOF <= dly2SOF after tpd; + dly3EOC <= dly2EOC after tpd; + dly3EOF <= dly2EOF after tpd; + dly3EOFE <= dly2EOFE after tpd; + dly3Data <= dly2Data after tpd; + + -- Delay stage 4 + dly4SOC <= dly3SOC after tpd; + dly4SOF <= dly3SOF after tpd; + dly4EOC <= dly3EOC after tpd; + dly4EOF <= dly3EOF after tpd; + dly4EOFE <= dly3EOFE after tpd; + dly4Data <= dly3Data after tpd; + + -- Delay stage 5 + dly5SOC <= dly4SOC after tpd; + dly5SOF <= dly4SOF after tpd; + dly5EOC <= dly4EOC after tpd; + dly5EOF <= dly4EOF after tpd; + dly5EOFE <= dly4EOFE after tpd; + dly5Data <= dly4Data after tpd; + + -- Delay stage 6 + dly6SOC <= dly5SOC after tpd; + dly6SOF <= dly5SOF after tpd; + dly6EOC <= dly5EOC after tpd; + dly6EOF <= dly5EOF after tpd; + dly6EOFE <= dly5EOFE after tpd; + dly6Data <= dly5Data after tpd; + + -- Delay stage 7 + dly7SOC <= dly6SOC after tpd; + dly7SOF <= dly6SOF after tpd; + dly7EOC <= dly6EOC after tpd; + dly7EOF <= dly6EOF after tpd; + dly7EOFE <= dly6EOFE after tpd; + dly7Data <= dly6Data after tpd; + + -- CRC Enable & partial flag + if cellRxSOC = '1' then + intCrcRxValid <= '1' after tpd; + elsif cellRxEOC = '1' then + intCrcRxValid <= '0' after tpd; + end if; + end if; + end if; + end process; + + + -- CRC Data Output, SOC field overwritten with zeros + GEN_CRC: for i in 0 to (RxLaneCnt-1) generate + process ( dly0SOC, dly0Data ) begin + if dly0SOC = '1' then + crcRxIn(i*16+7 downto i*16) <= (others=>'0'); + else + crcRxIn(i*16+7 downto i*16) <= dly0Data(i*16+7 downto i*16); + end if; + crcRxIn(i*16+15 downto i*16+8) <= dly0Data(i*16+15 downto i*16+8); + end process; + end generate; + + + -- Output to CRC engine + crcRxWidth <= '0' when ( cellRxEOC = '1' and RxLaneCnt > 2 ) else '1'; + crcRxInit <= dly0SOC; + crcRxValid <= intCrcRxValid and not cellRxPause; + + + -- Choose tap positions in delay chain + + -- Serial number compare position, detSOC - 1 + compSOC <= dly6SOC; + compData <= dly6Data; + + -- SOC detect position, + detSOC <= dly7SOC; + detSOF <= dly7SOF; + outData <= dly7Data; + + -- EOC detect position, depends on lane count + -- detSOC - 4 when 1 lane, detSOC - 3 when multiple lanes + detEOC <= dly3EOC when RxLaneCnt = 1 else dly4EOC; + detEOF <= dly3EOF when RxLaneCnt = 1 else dly4EOF; + detEOFE <= dly3EOFE when RxLaneCnt = 1 else dly4EOFE; + + + -- Detect current VC, check cell serial number + process ( pgpRxClk, pgpRxReset ) begin + if pgpRxReset = '1' then + currVc <= (others=>'0') after tpd; + serErr <= '0' after tpd; + vc0Serial <= (others=>'0') after tpd; + vc0Valid <= '0' after tpd; + vc1Serial <= (others=>'0') after tpd; + vc1Valid <= '0' after tpd; + vc2Serial <= (others=>'0') after tpd; + vc2Valid <= '0' after tpd; + vc3Serial <= (others=>'0') after tpd; + vc3Valid <= '0' after tpd; + elsif rising_edge(pgpRxClk) then + + -- Link is down, init counts + if pgpRxLinkReady = '0' then + currVc <= (others=>'0') after tpd; + serErr <= '0' after tpd; + vc0Serial <= (others=>'0') after tpd; + vc0Valid <= '0' after tpd; + vc1Serial <= (others=>'0') after tpd; + vc1Valid <= '0' after tpd; + vc2Serial <= (others=>'0') after tpd; + vc2Valid <= '0' after tpd; + vc3Serial <= (others=>'0') after tpd; + vc3Valid <= '0' after tpd; + + -- Pipeline enable + elsif cellRxPause = '0' then + + -- SOC for compare + if compSOC = '1' then + + -- Register VC value + currVc <= compData(15 downto 14) after tpd; + + -- Compare current count, store current count for future increment + case compData(15 downto 14) is + + -- VC 0 + when "00" => + if compData(13 downto 8) = vc0Serial then + serErr <= '0' after tpd; + else + vc0Serial <= compData(13 downto 8) after tpd; + serErr <= vc0Valid after tpd; + end if; + vc0Valid <= '1' after tpd; + + -- VC 1 + when "01" => + if compData(13 downto 8) = vc1Serial then + serErr <= '0' after tpd; + else + vc1Serial <= compData(13 downto 8) after tpd; + serErr <= vc1Valid after tpd; + end if; + vc1Valid <= '1' after tpd; + + -- VC 2 + when "10" => + if compData(13 downto 8) = vc2Serial then + serErr <= '0' after tpd; + else + vc2Serial <= compData(13 downto 8) after tpd; + serErr <= vc2Valid after tpd; + end if; + vc2Valid <= '1' after tpd; + + -- VC 3 + when others => + if compData(13 downto 8) = vc3Serial then + serErr <= '0' after tpd; + else + vc3Serial <= compData(13 downto 8) after tpd; + serErr <= vc3Valid after tpd; + end if; + vc3Valid <= '1' after tpd; + end case; + + -- SOC for increment + elsif detSOC = '1' then + case currVc is + when "00" => vc0Serial <= vc0Serial + 1 after tpd; + when "01" => vc1Serial <= vc1Serial + 1 after tpd; + when "10" => vc2Serial <= vc2Serial + 1 after tpd; + when others => vc3Serial <= vc3Serial + 1 after tpd; + end case; + end if; + end if; + end if; + end process; + + + -- Receive cell tracking + process ( pgpRxClk, pgpRxReset ) begin + if pgpRxReset = '1' then + crcNotZero <= '0' after tpd; + linkDownCnt <= (others=>'0') after tpd; + inCellEn <= '0' after tpd; + inCellSerErr <= '0' after tpd; + inCellSOF <= '0' after tpd; + inCellEOC <= '0' after tpd; + inCellEOF <= '0' after tpd; + inCellEOFE <= '0' after tpd; + inCellCnt <= (others=>'0') after tpd; + abortEn <= '0' after tpd; + abortVc <= (others=>'0') after tpd; + intCellError <= '0' after tpd; + dlyCellError <= '0' after tpd; + pgpRxCellError <= '0' after tpd; + vcInFrame <= (others=>'0') after tpd; + elsif rising_edge(pgpRxClk) then + + -- Cell error edge generation + dlyCellError <= intCellError after tpd; + pgpRxCellError <= intCellError and not dlyCellError after tpd; + + -- CRC Error + if crcRxOut = 0 then + crcNotZero <= '0' after tpd; + else + crcNotZero <= '1' after tpd; + end if; + + -- Link down counter + if pgpRxLinkReady = '1' then + linkDownCnt <= (others=>'0') after tpd; + elsif linkDownCnt(4) = '0' then + linkDownCnt <= linkDownCnt + 1 after tpd; + end if; + + -- Count size of each cell received + if cellRxPause = '0' then + if inCellEn = '1' then + inCellCnt <= inCellCnt - 1 after tpd; + else + inCellCnt <= (others=>'1') after tpd; + end if; + end if; + + -- Link is down. Terminate transmission for any active VCs + if pgpRxLinkReady = '0' then + + -- Enabled every 4 clocks to ensure proper spacing between generated EOFs + if linkDownCnt(1 downto 0) = "11" then + + -- VC is active + if vcInFrame(conv_integer(linkDownCnt(3 downto 2))) = '1' then + abortEn <= '1' after tpd; + vcInFrame(conv_integer(linkDownCnt(3 downto 2))) <= '0' after tpd; + else + abortEn <= '0' after tpd; + end if; + else + abortEn <= '0' after tpd; + end if; + + -- VC for abort + abortVc <= linkDownCnt(3 downto 2) after tpd; + + -- Clear cell control signals + inCellEn <= '0' after tpd; + inCellSerErr <= '0' after tpd; + inCellSOF <= '0' after tpd; + inCellEOC <= '0' after tpd; + inCellEOF <= '0' after tpd; + inCellEOFE <= '0' after tpd; + intCellError <= '0' after tpd; + + -- Link is ready + else + + -- Clear abort flags + abortVc <= (others=>'0') after tpd; + abortEn <= '0' after tpd; + + -- Link flush set + if pgpRxFlush = '1' then + vcInFrame <= (others=>'0') after tpd; + + -- Pipeline enable + elsif cellRxPause = '0' then + + -- SOC Received + if detSOC = '1' then + + -- Do we output data and mark in frame? + -- Yes if SOF is set and serial number is ok + -- Yes if already in frame + if nxtCellEn = '1' then + inCellEn <= '1' after tpd; + vcInFrame(conv_integer(currVc)) <= '1' after tpd; + end if; + + -- Do we mark output as SOF? + -- Yes if SOF is seen and the serial number is ok and we are not already in frame + if detSOF = '1' and serErr = '0' and vcInFrame(conv_integer(currVc)) = '0' then + inCellSOF <= '1' after tpd; + end if; + + -- Do we mark serial error flag? + -- Yes if SOF is set and we are already in frame + -- Yes if serial number error + if (detSOF = '1' and vcInFrame(conv_integer(currVc)) = '1') or serErr = '1' then + inCellSerErr <= '1' after tpd; + end if; + + -- Mark out of cell after EOC + elsif inCellEOC = '1' then + inCellEn <= '0' after tpd; + inCellSerErr <= '0' after tpd; + inCellSOF <= '0' after tpd; + + -- Clear frame state if EOF + if inCellEOF = '1' then + vcInFrame(conv_integer(currVc)) <= '0' after tpd; + end if; + + -- Clear SOF + else + inCellSOF <= '0' after tpd; + end if; + + -- End of cell, check for short cell case + if detEOC = '1' and (inCellEn = '1' or nxtCellEn = '1') then + inCellEOC <= '1' after tpd; + intCellError <= inCellSerErr or crcNotZero after tpd; + + -- Cell is too short + if detEOF = '0' and inCellCnt /= 1 and EnShortCells = 0 then + inCellEOF <= '1' after tpd; + inCellEOFE <= '1' after tpd; + intCellError <= '1' after tpd; + else + inCellEOF <= detEOF or inCellSerErr or crcNotZero after tpd; + inCellEOFE <= detEOFE or inCellSerErr or crcNotZero after tpd; + intCellError <= inCellSerErr or crcNotZero after tpd; + end if; + + -- Cell might be too long + elsif inCellEn = '1' and inCellCnt = 0 and inCellEOC = '0' then + inCellEOC <= '1' after tpd; + inCellEOF <= '1' after tpd; + inCellEOFE <= '1' after tpd; + intCellError <= '1' after tpd; + else + inCellEOC <= '0' after tpd; + inCellEOF <= '0' after tpd; + inCellEOFE <= '0' after tpd; + intCellError <= '0' after tpd; + end if; + end if; + end if; + end if; + end process; + + + -- Do we output data and mark in frame? + -- Yes if SOF is set and serial number is ok + -- Yes if already in frame + nxtCellEn <= '1' when ((detSOF = '1' and serErr = '0') or vcInFrame(conv_integer(currVc)) = '1') else '0'; + + + -- Data Output + process ( pgpRxClk, pgpRxReset ) begin + if pgpRxReset = '1' then + vcFrameRxData <= (others=>'0') after tpd; + vcFrameRxSOF <= '0' after tpd; + vcFrameRxEOF <= '0' after tpd; + vcFrameRxEOFE <= '0' after tpd; + vc0FrameRxValid <= '0' after tpd; + vc1FrameRxValid <= '0' after tpd; + vc2FrameRxValid <= '0' after tpd; + vc3FrameRxValid <= '0' after tpd; + elsif rising_edge(pgpRxClk) then + + -- Data abort is enabled + if abortEn = '1' then + case abortVc is + when "00" => + vc0FrameRxValid <= '1' after tpd; + vc1FrameRxValid <= '0' after tpd; + vc2FrameRxValid <= '0' after tpd; + vc3FrameRxValid <= '0' after tpd; + when "01" => + vc0FrameRxValid <= '0' after tpd; + vc1FrameRxValid <= '1' after tpd; + vc2FrameRxValid <= '0' after tpd; + vc3FrameRxValid <= '0' after tpd; + when "10" => + vc0FrameRxValid <= '0' after tpd; + vc1FrameRxValid <= '0' after tpd; + vc2FrameRxValid <= '1' after tpd; + vc3FrameRxValid <= '0' after tpd; + when others => + vc0FrameRxValid <= '0' after tpd; + vc1FrameRxValid <= '0' after tpd; + vc2FrameRxValid <= '0' after tpd; + vc3FrameRxValid <= '1' after tpd; + end case; + + -- Abort output + vcFrameRxSOF <= '0' after tpd; + vcFrameRxEOF <= '1' after tpd; + vcFrameRxEOFE <= '1' after tpd; + + -- Pipeline is enabled + elsif cellRxPause = '0' and inCellEn = '1' then + case currVc is + when "00" => + vc0FrameRxValid <= '1' after tpd; + vc1FrameRxValid <= '0' after tpd; + vc2FrameRxValid <= '0' after tpd; + vc3FrameRxValid <= '0' after tpd; + when "01" => + vc0FrameRxValid <= '0' after tpd; + vc1FrameRxValid <= '1' after tpd; + vc2FrameRxValid <= '0' after tpd; + vc3FrameRxValid <= '0' after tpd; + when "10" => + vc0FrameRxValid <= '0' after tpd; + vc1FrameRxValid <= '0' after tpd; + vc2FrameRxValid <= '1' after tpd; + vc3FrameRxValid <= '0' after tpd; + when others => + vc0FrameRxValid <= '0' after tpd; + vc1FrameRxValid <= '0' after tpd; + vc2FrameRxValid <= '0' after tpd; + vc3FrameRxValid <= '1' after tpd; + end case; + + -- Data output + vcFrameRxData <= outData after tpd; + vcFrameRxSOF <= inCellSOF after tpd; + vcFrameRxEOF <= inCellEOF after tpd; + vcFrameRxEOFE <= inCellEOFE after tpd; + + -- Paused or no data + else + vc0FrameRxValid <= '0' after tpd; + vc1FrameRxValid <= '0' after tpd; + vc2FrameRxValid <= '0' after tpd; + vc3FrameRxValid <= '0' after tpd; + end if; + end if; + end process; + + + -- Update buffer status on successfull cell reception + process ( pgpRxClk, pgpRxReset ) begin + if pgpRxReset = '1' then + vc0RemBuffAFull <= '1' after tpd; + vc0RemBuffFull <= '1' after tpd; + vc1RemBuffAFull <= '1' after tpd; + vc1RemBuffFull <= '1' after tpd; + vc2RemBuffAFull <= '1' after tpd; + vc2RemBuffFull <= '1' after tpd; + vc3RemBuffAFull <= '1' after tpd; + vc3RemBuffFull <= '1' after tpd; + elsif rising_edge(pgpRxClk) then + + -- Link is not ready, force buffer states to bad + if pgpRxLinkReady = '0' then + vc0RemBuffAFull <= '1' after tpd; + vc0RemBuffFull <= '1' after tpd; + vc1RemBuffAFull <= '1' after tpd; + vc1RemBuffFull <= '1' after tpd; + vc2RemBuffAFull <= '1' after tpd; + vc2RemBuffFull <= '1' after tpd; + vc3RemBuffAFull <= '1' after tpd; + vc3RemBuffFull <= '1' after tpd; + + -- Update buffer status + elsif cellRxEOC = '1' then + vc0RemBuffAFull <= cellRxData(8) after tpd; + vc0RemBuffFull <= cellRxData(12) after tpd; + vc1RemBuffAFull <= cellRxData(9) after tpd; + vc1RemBuffFull <= cellRxData(13) after tpd; + vc2RemBuffAFull <= cellRxData(10) after tpd; + vc2RemBuffFull <= cellRxData(14) after tpd; + vc3RemBuffAFull <= cellRxData(11) after tpd; + vc3RemBuffFull <= cellRxData(15) after tpd; + end if; + end if; + end process; + +end Pgp2RxCell; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/core/Pgp2RxPhy.vhd b/rce/fw-hsio/modules/pgp2/hdl/core/Pgp2RxPhy.vhd new file mode 100755 index 00000000..6697c247 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/core/Pgp2RxPhy.vhd @@ -0,0 +1,715 @@ +--------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol V2, Physical Interface Receive Module +-- Project : General Purpose Core +--------------------------------------------------------------------------------- +-- File : Pgp2RxPhy.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 05/18/2009 +--------------------------------------------------------------------------------- +-- Description: +-- Physical interface receive module for the Pretty Good Protocol version 2 core. +--------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +--------------------------------------------------------------------------------- +-- Modification history: +-- 05/18/2009: created. +-- 11/23/2009: Renamed package. +-- 01/13/2010: Added init of reset controller if failed to link after 1023 clocks. +-- fixed bug in dealing with an inverted receive link. +-- 02/01/2011: Rem data and rem link not updated if EOF fields don't match. +--------------------------------------------------------------------------------- + +LIBRARY ieee; +USE work.ALL; +USE work.Pgp2CorePackage.ALL; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity Pgp2RxPhy is + generic ( + RxLaneCnt : integer := 4 -- Number of receive lanes, 1-4 + ); + port ( + + -- System clock, reset & control + pgpRxClk : in std_logic; -- Master clock + pgpRxReset : in std_logic; -- Synchronous reset input + + -- Link is ready + pgpRxLinkReady : out std_logic; -- Local side has link + + -- Error Flags, one pulse per event + pgpRxLinkDown : out std_logic; -- A link down event has occured + pgpRxLinkError : out std_logic; -- A link error has occured + + -- Opcode Receive Interface + pgpRxOpCodeEn : out std_logic; -- Opcode receive enable + pgpRxOpCode : out std_logic_vector(7 downto 0); -- Opcode receive value + + -- Sideband data + pgpRemLinkReady : out std_logic; -- Far end side has link + pgpRemData : out std_logic_vector(7 downto 0); -- Far end side User Data + + -- Cell Receive Interface + cellRxPause : out std_logic; -- Cell data pause + cellRxSOC : out std_logic; -- Cell data start of cell + cellRxSOF : out std_logic; -- Cell data start of frame + cellRxEOC : out std_logic; -- Cell data end of cell + cellRxEOF : out std_logic; -- Cell data end of frame + cellRxEOFE : out std_logic; -- Cell data end of frame error + cellRxData : out std_logic_vector(RxLaneCnt*16-1 downto 0); -- Cell data data + + -- Physical Interface Signals + phyRxPolarity : out std_logic_vector(RxLaneCnt-1 downto 0); -- PHY receive signal polarity + phyRxData : in std_logic_vector(RxLaneCnt*16-1 downto 0); -- PHY receive data + phyRxDataK : in std_logic_vector(RxLaneCnt*2-1 downto 0); -- PHY receive data is K character + phyRxDispErr : in std_logic_vector(RxLaneCnt*2-1 downto 0); -- PHY receive data has disparity error + phyRxDecErr : in std_logic_vector(RxLaneCnt*2-1 downto 0); -- PHY receive data not in table + phyRxReady : in std_logic; -- PHY receive interface is ready + phyRxInit : out std_logic; -- PHY receive interface init; + + -- Debug + debug : out std_logic_vector(63 downto 0) + ); + +end Pgp2RxPhy; + + +-- Define architecture +architecture Pgp2RxPhy of Pgp2RxPhy is + + -- Local Signals + signal dly0RxData : std_logic_vector(RxLaneCnt*16-1 downto 0); + signal dly0RxDataK : std_logic_vector(RxLaneCnt*2-1 downto 0); + signal dly0RxDispErr : std_logic_vector(RxLaneCnt*2-1 downto 0); + signal dly0RxDecErr : std_logic_vector(RxLaneCnt*2-1 downto 0); + signal dly1RxData : std_logic_vector(RxLaneCnt*16-1 downto 0); + signal dly1RxDataK : std_logic_vector(RxLaneCnt*2-1 downto 0); + signal dly1RxDispErr : std_logic_vector(RxLaneCnt*2-1 downto 0); + signal dly1RxDecErr : std_logic_vector(RxLaneCnt*2-1 downto 0); + signal rxDetectLts : std_logic; + signal rxDetectLtsOk : std_logic; + signal rxDetectLtsRaw : std_logic_vector(3 downto 0); + signal rxDetectInvert : std_logic_vector(RxLaneCnt-1 downto 0); + signal rxDetectInvertRaw : std_logic_vector(RxLaneCnt-1 downto 0); + signal rxDetectRemLink : std_logic; + signal rxDetectRemData : std_logic_vector(7 downto 0); + signal rxDetectOpCodeEn : std_logic; + signal rxDetectOpCodeEnRaw : std_logic_vector(3 downto 0); + signal rxDetectSOC : std_logic; + signal rxDetectSOCRaw : std_logic_vector(3 downto 0); + signal rxDetectSOF : std_logic; + signal rxDetectSOFRaw : std_logic_vector(3 downto 0); + signal rxDetectEOC : std_logic; + signal rxDetectEOCRaw : std_logic_vector(3 downto 0); + signal rxDetectEOF : std_logic; + signal rxDetectEOFRaw : std_logic_vector(3 downto 0); + signal rxDetectEOFE : std_logic; + signal rxDetectEOFERaw : std_logic_vector(3 downto 0); + signal nxtRxLinkReady : std_logic; + signal stateCntRst : std_logic; + signal stateCnt : std_logic_vector(19 downto 0); + signal ltsCntRst : std_logic; + signal ltsCntEn : std_logic; + signal ltsCnt : std_logic_vector(7 downto 0); + signal intRxLinkReady : std_logic; + signal intRxPolarity : std_logic_vector(RxLaneCnt-1 downto 0); + signal nxtRxPolarity : std_logic_vector(RxLaneCnt-1 downto 0); + signal dlyRxLinkDown : std_logic; + signal intRxLinkError : std_logic; + signal dlyRxLinkError : std_logic; + signal intRxInit : std_logic; + signal nxtRxInit : std_logic; + signal dbgRxData : std_logic_vector(31 downto 0); + signal dbgRxDataK : std_logic_vector(3 downto 0); + signal dbgInvert : std_logic_vector(1 downto 0); + signal dbgPolarity : std_logic_vector(1 downto 0); + signal dbgRxDispErr : std_logic_vector(3 downto 0); + signal dbgRxDecErr : std_logic_vector(3 downto 0); + + -- Physical Link State + constant ST_RESET : std_logic_vector(2 downto 0) := "001"; + constant ST_LOCK : std_logic_vector(2 downto 0) := "010"; + constant ST_WAIT : std_logic_vector(2 downto 0) := "011"; + constant ST_INVRT : std_logic_vector(2 downto 0) := "100"; + constant ST_READY : std_logic_vector(2 downto 0) := "101"; + signal curState : std_logic_vector(2 downto 0); + signal nxtState : std_logic_vector(2 downto 0); + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Link status + pgpRxLinkReady <= intRxLinkReady; + + -- RX Interface Init + phyRxInit <= intRxInit; + + -- Opcode Receive Interface + pgpRxOpCodeEn <= rxDetectOpCodeEn; + pgpRxOpCode <= dly1RxData(15 downto 8); + + -- Cell Receive Interface + cellRxPause <= rxDetectOpCodeEn; + cellRxSOC <= rxDetectSOC; + cellRxSOF <= rxDetectSOF; + cellRxEOC <= rxDetectEOC; + cellRxEOF <= rxDetectEOF; + cellRxEOFE <= rxDetectEOFE; + cellRxData <= dly1RxData; + + -- Drive active polarity control signals + GEN_POL: for i in 0 to (RxLaneCnt-1) generate + phyRxPolarity(i) <= intRxPolarity(i); + end generate; + + -- State transition sync logic. + process ( pgpRxClk, pgpRxReset ) begin + if pgpRxReset = '1' then + curState <= ST_RESET after tpd; + stateCnt <= (others=>'0') after tpd; + ltsCnt <= (others=>'0') after tpd; + intRxLinkReady <= '0' after tpd; + intRxPolarity <= (others=>'0') after tpd; + dlyRxLinkDown <= '0' after tpd; + pgpRxLinkDown <= '0' after tpd; + intRxLinkError <= '0' after tpd; + dlyRxLinkError <= '0' after tpd; + pgpRxLinkError <= '0' after tpd; + intRxInit <= '0' after tpd; + pgpRemLinkReady <= '0' after tpd; + pgpRemData <= (others=>'0') after tpd; + elsif rising_edge(pgpRxClk) then + + -- Sideband data + if intRxLinkReady = '1' then + pgpRemLinkReady <= rxDetectRemLink; + pgpRemData <= rxDetectRemData; + else + pgpRemLinkReady <= '0' after tpd; + pgpRemData <= (others=>'0') after tpd; + end if; + + -- Link down edge detection + dlyRxLinkDown <= (not intRxLinkReady) after tpd; + pgpRxLinkDown <= (not intRxLinkReady) and (not dlyRxLinkDown) after tpd; + + -- Link error generation + if (phyRxDispErr /= 0 or phyRxDecErr /= 0) and intRxLinkReady = '1' then + intRxLinkError <= '1' after tpd; + else + intRxLinkError <= '0' after tpd; + end if; + + -- Link error edge detection + dlyRxLinkError <= intRxLinkError after tpd; + pgpRxLinkError <= intRxLinkError and not dlyRxLinkError after tpd; + + -- Status signals + intRxLinkReady <= nxtRxLinkReady after tpd; + intRxPolarity <= nxtRxPolarity after tpd; + intRxInit <= nxtRxInit after tpd; + + -- State transition + curState <= nxtState after tpd; + + -- In state counter + if stateCntRst = '1' then + stateCnt <= (others=>'0') after tpd; + else + stateCnt <= stateCnt + 1 after tpd; + end if; + + -- LTS Counter + if ltsCntRst = '1' then + ltsCnt <= (others=>'0') after tpd; + elsif ltsCntEn = '1' and ltsCnt /= 255 then + ltsCnt <= ltsCnt + 1 after tpd; + end if; + + end if; + end process; + + + -- Link control state machine + process ( curState, stateCnt, ltsCnt, rxDetectLts, rxDetectLtsOk, + rxDetectInvert, intRxPolarity, phyRxReady, phyRxDecErr, phyRxDispErr ) begin + case curState is + + -- Hold in rx reset for 8 clocks + when ST_RESET => + nxtRxLinkReady <= '0'; + nxtRxPolarity <= (others=>'0'); + ltsCntRst <= '1'; + ltsCntEn <= '0'; + nxtRxInit <= '1'; + + -- Hold reset for 255 clocks + if stateCnt(7 downto 0) = 255 then + stateCntRst <= '1'; + nxtState <= ST_LOCK; + else + stateCntRst <= '0'; + nxtState <= curState; + end if; + + -- Wait for lock state + when ST_LOCK => + nxtRxLinkReady <= '0'; + nxtRxPolarity <= (others=>'0'); + ltsCntRst <= '1'; + ltsCntEn <= '0'; + nxtRxInit <= '0'; + + -- Wait for lock + if phyRxReady = '1' then + nxtState <= ST_WAIT; + stateCntRst <= '1'; + + -- Terminal count without lock + elsif stateCnt = x"FFFFF" then + nxtState <= ST_RESET; + stateCntRst <= '1'; + else + nxtState <= curState; + stateCntRst <= '0'; + end if; + + -- Wait for training pattern + when ST_WAIT => + nxtRxLinkReady <= '0'; + nxtRxInit <= '0'; + + -- Lock is lost + if phyRxReady = '0' then + stateCntRst <= '1'; + ltsCntEn <= '0'; + ltsCntRst <= '0'; + nxtRxPolarity <= intRxPolarity; + nxtState <= ST_RESET; + + -- Decode or disparity error, clear lts count + elsif phyRxReady = '0' or phyRxDispErr /= 0 or phyRxDecErr /= 0 then + stateCntRst <= '0'; + ltsCntEn <= '0'; + ltsCntRst <= '1'; + nxtRxPolarity <= intRxPolarity; + nxtState <= curState; + + -- Training pattern seen + elsif rxDetectLts = '1' then + stateCntRst <= '1'; + + -- No Inversion + if rxDetectInvert = 0 then + nxtRxPolarity <= intRxPolarity; + nxtState <= curState; + + -- ID & Lane Count Ok + if rxDetectLtsOk = '1' then + ltsCntEn <= '1'; + ltsCntRst <= '0'; + else + ltsCntEn <= '0'; + ltsCntRst <= '1'; + end if; + + -- Inverted + else + ltsCntEn <= '0'; + ltsCntRst <= '1'; + nxtRxPolarity <= intRxPolarity xor rxDetectInvert; + nxtState <= ST_INVRT; + end if; + + -- Run after we have seen 256 non-inverted training sequences + -- without any disparity or decode errors. + elsif ltsCnt = 255 then + stateCntRst <= '1'; + ltsCntEn <= '0'; + ltsCntRst <= '1'; + nxtRxPolarity <= intRxPolarity; + nxtState <= ST_READY; + + -- Terminal count without seeing a valid LTS + elsif stateCnt = x"FFFFF" then + stateCntRst <= '1'; + ltsCntEn <= '0'; + ltsCntRst <= '1'; + nxtRxPolarity <= intRxPolarity; + nxtState <= ST_RESET; + + -- Count cycles without LTS + else + stateCntRst <= '0'; + ltsCntEn <= '0'; + ltsCntRst <= '0'; + nxtRxPolarity <= intRxPolarity; + nxtState <= curState; + end if; + + -- Wait a few clocks after inverting receive interface + when ST_INVRT => + nxtRxLinkReady <= '0'; + nxtRxPolarity <= intRxPolarity; + ltsCntRst <= '1'; + ltsCntEn <= '0'; + nxtRxInit <= '0'; + + -- Wait 128 clocks + if stateCnt(6 downto 0) = 127 then + nxtState <= ST_WAIT; + stateCntRst <= '1'; + else + nxtState <= curState; + stateCntRst <= '0'; + end if; + + -- Ready + when ST_READY => + nxtRxLinkReady <= '1'; + nxtRxPolarity <= intRxPolarity; + ltsCntRst <= '1'; + ltsCntEn <= '0'; + nxtRxInit <= '0'; + + -- Lock is lost + if phyRxReady = '0' then + nxtState <= ST_RESET; + stateCntRst <= '1'; + + -- Training sequence seen + elsif rxDetectLts = '1' then + + -- Link is inverted or bad lts, reset and relink + if rxDetectInvert /= 0 or rxDetectLtsOk = '0' then + nxtState <= ST_RESET; + stateCntRst <= '1'; + + -- Good LTS + else + nxtState <= curState; + stateCntRst <= '1'; + end if; + + -- Link is down after long period without seeing a LTS + -- Min spacing of LTS is 2 Cells = 2 * 256 = 512 + -- Timeout set at 4096 = 8 cells + elsif stateCnt(11 downto 0) = x"FFF" then + nxtState <= ST_RESET; + stateCntRst <= '1'; + + -- Count cycles without LTS + else + nxtState <= curState; + stateCntRst <= '0'; + end if; + + -- Default + when others => + nxtRxLinkReady <= '0'; + nxtRxPolarity <= (others=>'0'); + stateCntRst <= '0'; + ltsCntRst <= '0'; + ltsCntEn <= '0'; + nxtRxInit <= '0'; + nxtState <= ST_LOCK; + end case; + end process; + + + -- Receive data pipeline + process ( pgpRxClk, pgpRxReset ) begin + if pgpRxReset = '1' then + dly0RxData <= (others=>'0') after tpd; + dly0RxDataK <= (others=>'0') after tpd; + dly0RxDispErr <= (others=>'0') after tpd; + dly0RxDecErr <= (others=>'0') after tpd; + dly1RxData <= (others=>'0') after tpd; + dly1RxDataK <= (others=>'0') after tpd; + dly1RxDispErr <= (others=>'0') after tpd; + dly1RxDecErr <= (others=>'0') after tpd; + elsif rising_edge(pgpRxClk) then + dly0RxData <= phyRxData after tpd; + dly0RxDataK <= phyRxDataK after tpd; + dly0RxDispErr <= phyRxDispErr after tpd; + dly0RxDecErr <= phyRxDecErr after tpd; + dly1RxData <= dly0RxData after tpd; + dly1RxDataK <= dly0RxDataK after tpd; + dly0RxDispErr <= dly0RxDispErr after tpd; + dly0RxDecErr <= dly0RxDecErr after tpd; + end if; + end process; + + + -- Link init ordered set detect + process ( pgpRxClk, pgpRxReset ) begin + if pgpRxReset = '1' then + rxDetectLts <= '0' after tpd; + rxDetectLtsOk <= '0' after tpd; + rxDetectInvert <= (others=>'0') after tpd; + rxDetectRemLink <= '0' after tpd; + rxDetectRemData <= (others=>'0') after tpd; + rxDetectOpCodeEn <= '0' after tpd; + rxDetectSOC <= '0' after tpd; + rxDetectSOF <= '0' after tpd; + rxDetectEOC <= '0' after tpd; + rxDetectEOF <= '0' after tpd; + rxDetectEOFE <= '0' after tpd; + elsif rising_edge(pgpRxClk) then + + -- LTS is detected when phy is ready + if phyRxReady = '1' then + + -- Detect link init ordered sets + if rxDetectLtsRaw(0) = '1' and + ( rxDetectLtsRaw(1) = '1' or RxLaneCnt < 2 ) and + ( rxDetectLtsRaw(2) = '1' or RxLaneCnt < 3 ) and + ( rxDetectLtsRaw(3) = '1' or RxLaneCnt < 4 ) then + rxDetectInvert <= rxDetectInvertRaw after tpd; + rxDetectLts <= '1' after tpd; + + -- Lane count and ID must match + if dly0RxData(13 downto 12) = conv_std_logic_vector(RxLaneCnt-1,2) and + dly0RxData(11 downto 8) = Pgp2Id then + rxDetectLtsOk <= '1' after tpd; + rxDetectRemLink <= dly0RxData(15) after tpd; + rxDetectRemData <= dly0RxData(7 downto 0) after tpd; + else + rxDetectLtsOk <= '0' after tpd; + end if; + else + rxDetectLts <= '0' after tpd; + rxDetectLtsOk <= '0' after tpd; + end if; + else + rxDetectLts <= '0' after tpd; + rxDetectLtsOk <= '0' after tpd; + rxDetectInvert <= (others=>'0') after tpd; + rxDetectRemLink <= '0' after tpd; + rxDetectRemData <= (others=>'0') after tpd; + end if; + + -- The remaining opcodes are only detected when the link is up + if intRxLinkReady = '1' then + + -- Detect opCode ordered set + if rxDetectOpCodeEnRaw(0) = '1' and + ( rxDetectOpCodeEnRaw(1) = '1' or RxLaneCnt < 2 ) and + ( rxDetectOpCodeEnRaw(2) = '1' or RxLaneCnt < 3 ) and + ( rxDetectOpCodeEnRaw(3) = '1' or RxLaneCnt < 4 ) then + rxDetectOpCodeEn <= '1' after tpd; + else + rxDetectOpCodeEn <= '0' after tpd; + end if; + + -- Detect SOC ordered set + if rxDetectSOCRaw(0) = '1' and + ( rxDetectSOCRaw(1) = '1' or RxLaneCnt < 2 ) and + ( rxDetectSOCRaw(2) = '1' or RxLaneCnt < 3 ) and + ( rxDetectSOCRaw(3) = '1' or RxLaneCnt < 4 ) then + rxDetectSOC <= '1' after tpd; + rxDetectSOF <= '0' after tpd; + + -- Detect SOF ordered set + elsif rxDetectSOFRaw(0) = '1' and + ( rxDetectSOFRaw(1) = '1' or RxLaneCnt < 2 ) and + ( rxDetectSOFRaw(2) = '1' or RxLaneCnt < 3 ) and + ( rxDetectSOFRaw(3) = '1' or RxLaneCnt < 4 ) then + rxDetectSOC <= '1' after tpd; + rxDetectSOF <= '1' after tpd; + else + rxDetectSOC <= '0' after tpd; + rxDetectSOF <= '0' after tpd; + end if; + + -- Detect EOC ordered set + if rxDetectEOCRaw(0) = '1' and + ( rxDetectEOCRaw(1) = '1' or RxLaneCnt < 2 ) and + ( rxDetectEOCRaw(2) = '1' or RxLaneCnt < 3 ) and + ( rxDetectEOCRaw(3) = '1' or RxLaneCnt < 4 ) then + rxDetectEOC <= '1' after tpd; + rxDetectEOF <= '0' after tpd; + rxDetectEOFE <= '0' after tpd; + + -- Detect EOF ordered set + elsif rxDetectEOFRaw(0) = '1' and + ( rxDetectEOFRaw(1) = '1' or RxLaneCnt < 2 ) and + ( rxDetectEOFRaw(2) = '1' or RxLaneCnt < 3 ) and + ( rxDetectEOFRaw(3) = '1' or RxLaneCnt < 4 ) then + rxDetectEOC <= '1' after tpd; + rxDetectEOF <= '1' after tpd; + rxDetectEOFE <= '0' after tpd; + + -- Detect EOFE ordered set + elsif rxDetectEOFERaw(0) = '1' and + ( rxDetectEOFERaw(1) = '1' or RxLaneCnt < 2 ) and + ( rxDetectEOFERaw(2) = '1' or RxLaneCnt < 3 ) and + ( rxDetectEOFERaw(3) = '1' or RxLaneCnt < 4 ) then + rxDetectEOC <= '1' after tpd; + rxDetectEOF <= '1' after tpd; + rxDetectEOFE <= '1' after tpd; + else + rxDetectEOC <= '0' after tpd; + rxDetectEOF <= '0' after tpd; + rxDetectEOFE <= '0' after tpd; + end if; + else + rxDetectOpCodeEn <= '0' after tpd; + rxDetectSOC <= '0' after tpd; + rxDetectSOF <= '0' after tpd; + rxDetectEOC <= '0' after tpd; + rxDetectEOF <= '0' after tpd; + rxDetectEOFE <= '0' after tpd; + end if; + end if; + end process; + + -- Generate Loop + GEN_LANES: for i in 0 to (RxLaneCnt-1) generate + + -- Ordered Set Detection + process ( dly1RxDataK, dly1RxData, dly0RxDataK, dly0RxData, phyRxDispErr, phyRxDecErr ) begin + + -- Skip errored decodes + if phyRxDispErr(i*2) = '0' and phyRxDispErr(i*2+1) = '0' and + phyRxDecErr(i*2) = '0' and phyRxDecErr(i*2+1) = '0' then + + -- Link init ordered set + if ( dly1RxDataK(i*2) = '1' and dly1RxDataK(i*2+1) = '0' and + dly0RxDataK(i*2) = '0' and dly0RxDataK(i*2+1) = '0' and + dly1RxData(i*16+7 downto i*16) = K_LTS and + ( dly1RxData(i*16+15 downto i*16+8) = D_102 or dly1RxData(i*16+15 downto i*16+8) = D_215 ) ) then + rxDetectLtsRaw(i) <= '1'; + + -- Detect Link Inversion + if dly1RxData(i*16+15 downto i*16+8) = D_102 then + rxDetectInvertRaw(i) <= '0'; + else + rxDetectInvertRaw(i) <= '1'; + end if; + else + rxDetectLtsRaw(i) <= '0'; + rxDetectInvertRaw(i) <= '0'; + end if; + + -- OpCode Enable + if ( dly0RxDataK(i*2) = '1' and dly0RxDataK(i*2+1) = '0' and dly0RxData(i*16+7 downto i*16) = K_OTS ) then + rxDetectOpCodeEnRaw(i) <= '1'; + else + rxDetectOpCodeEnRaw(i) <= '0'; + end if; + + -- SOC Detect + if ( dly0RxDataK(i*2) = '1' and dly0RxDataK(i*2+1) = '0' and dly0RxData(i*16+7 downto i*16) = K_SOC ) then + rxDetectSOCRaw(i) <= '1'; + else + rxDetectSOCRaw(i) <= '0'; + end if; + + -- SOF Detect + if ( dly0RxDataK(i*2) = '1' and dly0RxDataK(i*2+1) = '0' and dly0RxData(i*16+7 downto i*16) = K_SOF ) then + rxDetectSOFRaw(i) <= '1'; + else + rxDetectSOFRaw(i) <= '0'; + end if; + + -- EOC Detect + if ( dly0RxDataK(i*2) = '1' and dly0RxDataK(i*2+1) = '0' and dly0RxData(i*16+7 downto i*16) = K_EOC ) then + rxDetectEOCRaw(i) <= '1'; + else + rxDetectEOCRaw(i) <= '0'; + end if; + + -- EOF Detect + if ( dly0RxDataK(i*2) = '1' and dly0RxDataK(i*2+1) = '0' and dly0RxData(i*16+7 downto i*16) = K_EOF ) then + rxDetectEOFRaw(i) <= '1'; + else + rxDetectEOFRaw(i) <= '0'; + end if; + + -- EOFE Detect + if ( dly0RxDataK(i*2) = '1' and dly0RxDataK(i*2+1) = '0' and dly0RxData(i*16+7 downto i*16) = K_EOFE ) then + rxDetectEOFERaw(i) <= '1'; + else + rxDetectEOFERaw(i) <= '0'; + end if; + else + rxDetectLtsRaw(i) <= '0'; + rxDetectInvertRaw(i) <= '0'; + rxDetectOpCodeEnRaw(i) <= '0'; + rxDetectSOCRaw(i) <= '0'; + rxDetectSOFRaw(i) <= '0'; + rxDetectEOCRaw(i) <= '0'; + rxDetectEOFRaw(i) <= '0'; + rxDetectEOFERaw(i) <= '0'; + end if; + end process; + end generate; + + -- Generate Loop for unused lanes + GEN_SPARE: for i in RxLaneCnt to 3 generate + rxDetectLtsRaw(i) <= '0'; + rxDetectOpCodeEnRaw(i) <= '0'; + rxDetectSOCRaw(i) <= '0'; + rxDetectSOFRaw(i) <= '0'; + rxDetectEOCRaw(i) <= '0'; + rxDetectEOFRaw(i) <= '0'; + rxDetectEOFERaw(i) <= '0'; + end generate; + + ----------------------------- + -- Debug + ----------------------------- + + -- Upper debug bits + GEN_DBGA: if RxLaneCnt > 1 generate + dbgInvert(1) <= rxDetectInvert(1); + dbgPolarity(1) <= intRxPolarity(1); + dbgRxDataK(3 downto 2) <= dly0RxDataK(3 downto 2); + dbgRxData(31 downto 16) <= dly0RxData(31 downto 16); + dbgRxDispErr(3 downto 2) <= phyRxDispErr(3 downto 2); + dbgRxDecErr(3 downto 2) <= phyRxDecErr(3 downto 2); + end generate; + GEN_DBGB: if RxLaneCnt = 1 generate + dbgInvert(1) <= '0'; + dbgPolarity(1) <= '0'; + dbgRxDataK(3 downto 2) <= (others=>'0'); + dbgRxData(31 downto 16) <= (others=>'0'); + dbgRxDispErr(3 downto 2) <= (others=>'0'); + dbgRxDecErr(3 downto 2) <= (others=>'0'); + end generate; + dbgInvert(0) <= rxDetectInvert(0); + dbgPolarity(0) <= intRxPolarity(0); + dbgRxDataK(1 downto 0) <= dly0RxDataK(1 downto 0); + dbgRxData(15 downto 0) <= dly0RxData(15 downto 0); + dbgRxDispErr(1 downto 0) <= phyRxDispErr(1 downto 0); + dbgRxDecErr(1 downto 0) <= phyRxDecErr(1 downto 0); + + -- Debug + debug(63 downto 32) <= dbgRxData; + debug(31 downto 28) <= dbgRxDataK; + debug(27 downto 26) <= dbgInvert; + debug(25 downto 24) <= dbgPolarity; + debug(23 downto 21) <= curState; + debug(20) <= ltsCntEn; + debug(19) <= ltsCntRst; + debug(18) <= rxDetectSOF; + debug(17) <= rxDetectEOF; + debug(16) <= phyRxReady; + debug(15 downto 12) <= dbgRxDispErr; + debug(11 downto 8) <= dbgRxDecErr; + debug(7) <= rxDetectRemLink; + debug(6) <= intRxInit; + debug(5) <= rxDetectSOC; + debug(4) <= rxDetectEOC; + debug(3) <= rxDetectLtsOk; + debug(2) <= rxDetectLts; + debug(1) <= rxDetectOpCodeEn; + debug(0) <= intRxLinkReady; + +end Pgp2RxPhy; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/core/Pgp2Tx.vhd b/rce/fw-hsio/modules/pgp2/hdl/core/Pgp2Tx.vhd new file mode 100755 index 00000000..50d7c58e --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/core/Pgp2Tx.vhd @@ -0,0 +1,241 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, Top Level Transmit Interface +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2Tx.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 05/18/2009 +------------------------------------------------------------------------------- +-- Description: +-- Top Level Transmit interface module for the Pretty Good Protocol core. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 05/18/2009: created. +-- 11/23/2009: Renamed package. +-- 01/13/2010: Added received init line to help linking. +-- 06/25/2010: Added payload size config as generic. +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE work.ALL; +USE work.Pgp2CorePackage.ALL; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity Pgp2Tx is + generic ( + TxLaneCnt : integer := 4; -- Number of receive lanes, 1-4 + VcInterleave : integer := 1; -- Interleave Frames + PayloadCntTop : integer := 7 -- Top bit for payload counter + ); + port ( + + -- System clock, reset & control + pgpTxClk : in std_logic; -- Master clock + pgpTxReset : in std_logic; -- Synchronous reset input + + -- Link flush + pgpTxFlush : in std_logic; -- Flush the link + + -- Link is ready + pgpTxLinkReady : out std_logic; -- Local side has link + + -- Opcode Transmit Interface + pgpTxOpCodeEn : in std_logic; -- Opcode receive enable + pgpTxOpCode : in std_logic_vector(7 downto 0); -- Opcode receive value + + -- Sideband data + pgpLocLinkReady : in std_logic; -- Far end side has link + pgpLocData : in std_logic_vector(7 downto 0); -- Far end side User Data + + -- Frame Transmit Interface, VC 0 + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc0FrameTxReady : out std_logic; -- PGP is ready + vc0FrameTxSOF : in std_logic; -- User frame data start of frame + vc0FrameTxEOF : in std_logic; -- User frame data end of frame + vc0FrameTxEOFE : in std_logic; -- User frame data error + vc0FrameTxData : in std_logic_vector(TxLaneCnt*16-1 downto 0); -- User frame data + vc0LocBuffAFull : in std_logic; -- Remote buffer almost full + vc0LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 1 + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxReady : out std_logic; -- PGP is ready + vc1FrameTxSOF : in std_logic; -- User frame data start of frame + vc1FrameTxEOF : in std_logic; -- User frame data end of frame + vc1FrameTxEOFE : in std_logic; -- User frame data error + vc1FrameTxData : in std_logic_vector(TxLaneCnt*16-1 downto 0); -- User frame data + vc1LocBuffAFull : in std_logic; -- Remote buffer almost full + vc1LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 2 + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxReady : out std_logic; -- PGP is ready + vc2FrameTxSOF : in std_logic; -- User frame data start of frame + vc2FrameTxEOF : in std_logic; -- User frame data end of frame + vc2FrameTxEOFE : in std_logic; -- User frame data error + vc2FrameTxData : in std_logic_vector(TxLaneCnt*16-1 downto 0); -- User frame data + vc2LocBuffAFull : in std_logic; -- Remote buffer almost full + vc2LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 3 + vc3FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxReady : out std_logic; -- PGP is ready + vc3FrameTxSOF : in std_logic; -- User frame data start of frame + vc3FrameTxEOF : in std_logic; -- User frame data end of frame + vc3FrameTxEOFE : in std_logic; -- User frame data error + vc3FrameTxData : in std_logic_vector(TxLaneCnt*16-1 downto 0); -- User frame data + vc3LocBuffAFull : in std_logic; -- Remote buffer almost full + vc3LocBuffFull : in std_logic; -- Remote buffer full + + -- Physical Interface + phyTxData : out std_logic_vector(TxLaneCnt*16-1 downto 0); -- PHY receive data + phyTxDataK : out std_logic_vector(TxLaneCnt*2-1 downto 0); -- PHY receive data is K character + phyTxReady : in std_logic; -- PHY receive interface is ready + + -- Transmit CRC Interface + crcTxIn : out std_logic_vector(TxLaneCnt*16-1 downto 0); -- Transmit data for CRC + crcTxInit : out std_logic; -- Transmit CRC value init + crcTxValid : out std_logic; -- Transmit data for CRC is valid + crcTxOut : in std_logic_vector(31 downto 0); -- Transmit calculated CRC value + + -- Debug + debug : out std_logic_vector(63 downto 0) + ); + +end Pgp2Tx; + + +-- Define architecture +architecture Pgp2Tx of Pgp2Tx is + + -- Local Signals + signal cellTxSOC : std_logic; + signal cellTxSOF : std_logic; + signal cellTxEOC : std_logic; + signal cellTxEOF : std_logic; + signal cellTxEOFE : std_logic; + signal cellTxData : std_logic_vector(TxLaneCnt*16-1 downto 0); + signal schTxSOF : std_logic; + signal schTxEOF : std_logic; + signal schTxIdle : std_logic; + signal schTxReq : std_logic; + signal schTxAck : std_logic; + signal schTxDataVc : std_logic_vector(1 downto 0); + signal intTxLinkReady : std_logic; + +begin + + -- Link Ready + pgpTxLinkReady <= intTxLinkReady; + + -- Physical Interface + U_Pgp2TxPhy: Pgp2TxPhy + generic map ( + TxLaneCnt => TxLaneCnt + ) port map ( + pgpTxClk => pgpTxClk, + pgpTxReset => pgpTxReset, + pgpTxLinkReady => intTxLinkReady, + pgpTxOpCodeEn => pgpTxOpCodeEn, + pgpTxOpCode => pgpTxOpCode, + pgpLocLinkReady => pgpLocLinkReady, + pgpLocData => pgpLocData, + cellTxSOC => cellTxSOC, + cellTxSOF => cellTxSOF, + cellTxEOC => cellTxEOC, + cellTxEOF => cellTxEOF, + cellTxEOFE => cellTxEOFE, + cellTxData => cellTxData, + phyTxData => phyTxData, + phyTxDataK => phyTxDataK, + phyTxReady => phyTxReady, + debug => debug + ); + + + -- Scheduler + U_Pgp2TxSched: Pgp2TxSched + generic map ( + VcInterleave => VcInterleave + ) port map ( + pgpTxClk => pgpTxClk, + pgpTxReset => pgpTxReset, + pgpTxFlush => pgpTxFlush, + pgpTxLinkReady => intTxLinkReady, + schTxSOF => schTxSOF, + schTxEOF => schTxEOF, + schTxIdle => schTxIdle, + schTxReq => schTxReq, + schTxAck => schTxAck, + schTxDataVc => schTxDataVc, + vc0FrameTxValid => vc0FrameTxValid, + vc1FrameTxValid => vc1FrameTxValid, + vc2FrameTxValid => vc2FrameTxValid, + vc3FrameTxValid => vc3FrameTxValid + ); + + + -- Cell Transmitter + U_Pgp2TxCell: Pgp2TxCell + generic map ( + TxLaneCnt => TxLaneCnt + ) port map ( + pgpTxClk => pgpTxClk, + pgpTxReset => pgpTxReset, + pgpTxLinkReady => intTxLinkReady, + cellTxSOC => cellTxSOC, + cellTxSOF => cellTxSOF, + cellTxEOC => cellTxEOC, + cellTxEOF => cellTxEOF, + cellTxEOFE => cellTxEOFE, + cellTxData => cellTxData, + schTxSOF => schTxSOF, + schTxEOF => schTxEOF, + schTxIdle => schTxIdle, + schTxReq => schTxReq, + schTxAck => schTxAck, + schTxDataVc => schTxDataVc, + vc0FrameTxValid => vc0FrameTxValid, + vc0FrameTxReady => vc0FrameTxReady, + vc0FrameTxSOF => vc0FrameTxSOF, + vc0FrameTxEOF => vc0FrameTxEOF, + vc0FrameTxEOFE => vc0FrameTxEOFE, + vc0FrameTxData => vc0FrameTxData, + vc0LocBuffAFull => vc0LocBuffAFull, + vc0LocBuffFull => vc0LocBuffFull, + vc1FrameTxValid => vc1FrameTxValid, + vc1FrameTxReady => vc1FrameTxReady, + vc1FrameTxSOF => vc1FrameTxSOF, + vc1FrameTxEOF => vc1FrameTxEOF, + vc1FrameTxEOFE => vc1FrameTxEOFE, + vc1FrameTxData => vc1FrameTxData, + vc1LocBuffAFull => vc1LocBuffAFull, + vc1LocBuffFull => vc1LocBuffFull, + vc2FrameTxValid => vc2FrameTxValid, + vc2FrameTxReady => vc2FrameTxReady, + vc2FrameTxSOF => vc2FrameTxSOF, + vc2FrameTxEOF => vc2FrameTxEOF, + vc2FrameTxEOFE => vc2FrameTxEOFE, + vc2FrameTxData => vc2FrameTxData, + vc2LocBuffAFull => vc2LocBuffAFull, + vc2LocBuffFull => vc2LocBuffFull, + vc3FrameTxValid => vc3FrameTxValid, + vc3FrameTxReady => vc3FrameTxReady, + vc3FrameTxSOF => vc3FrameTxSOF, + vc3FrameTxEOF => vc3FrameTxEOF, + vc3FrameTxEOFE => vc3FrameTxEOFE, + vc3FrameTxData => vc3FrameTxData, + vc3LocBuffAFull => vc3LocBuffAFull, + vc3LocBuffFull => vc3LocBuffFull, + crcTxIn => crcTxIn, + crcTxInit => crcTxInit, + crcTxValid => crcTxValid, + crcTxOut => crcTxOut + ); + +end Pgp2Tx; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/core/Pgp2TxCell.vhd b/rce/fw-hsio/modules/pgp2/hdl/core/Pgp2TxCell.vhd new file mode 100755 index 00000000..16e507bc --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/core/Pgp2TxCell.vhd @@ -0,0 +1,655 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, Cell Transmit Interface +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2TxCell.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 05/18/2009 +------------------------------------------------------------------------------- +-- Description: +-- Cell Transmit interface module for the Pretty Good Protocol core. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 05/18/2009: created. +-- 11/23/2009: Renamed package. +-- 06/25/2010: Added payload size config as generic. +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE work.ALL; +USE work.Pgp2CorePackage.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity Pgp2TxCell is + generic ( + TxLaneCnt : integer := 4; -- Number of receive lanes, 1-4 + PayloadCntTop : integer := 7 -- Top bit for payload counter + ); + port ( + + -- System clock, reset & control + pgpTxClk : in std_logic; -- Master clock + pgpTxReset : in std_logic; -- Synchronous reset input + + -- Link is ready + pgpTxLinkReady : in std_logic; -- Local side has link + + -- Phy Transmit Interface + cellTxSOC : out std_logic; -- Cell data start of cell + cellTxSOF : out std_logic; -- Cell data start of frame + cellTxEOC : out std_logic; -- Cell data end of cell + cellTxEOF : out std_logic; -- Cell data end of frame + cellTxEOFE : out std_logic; -- Cell data end of frame error + cellTxData : out std_logic_vector(TxLaneCnt*16-1 downto 0); -- Cell data data + + -- Transmit Scheduler Interface + schTxSOF : out std_logic; -- Cell contained SOF + schTxEOF : out std_logic; -- Cell contained EOF + schTxIdle : in std_logic; -- Force IDLE transmit + schTxReq : in std_logic; -- Cell transmit request + schTxAck : out std_logic; -- Cell transmit acknowledge + schTxDataVc : in std_logic_vector(1 downto 0); -- Cell transmit virtual channel + + -- Frame Transmit Interface, VC 0 + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc0FrameTxReady : out std_logic; -- PGP is ready + vc0FrameTxSOF : in std_logic; -- User frame data start of frame + vc0FrameTxEOF : in std_logic; -- User frame data end of frame + vc0FrameTxEOFE : in std_logic; -- User frame data error + vc0FrameTxData : in std_logic_vector(TxLaneCnt*16-1 downto 0); -- User frame data + vc0LocBuffAFull : in std_logic; -- Remote buffer almost full + vc0LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 1 + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxReady : out std_logic; -- PGP is ready + vc1FrameTxSOF : in std_logic; -- User frame data start of frame + vc1FrameTxEOF : in std_logic; -- User frame data end of frame + vc1FrameTxEOFE : in std_logic; -- User frame data error + vc1FrameTxData : in std_logic_vector(TxLaneCnt*16-1 downto 0); -- User frame data + vc1LocBuffAFull : in std_logic; -- Remote buffer almost full + vc1LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 2 + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxReady : out std_logic; -- PGP is ready + vc2FrameTxSOF : in std_logic; -- User frame data start of frame + vc2FrameTxEOF : in std_logic; -- User frame data end of frame + vc2FrameTxEOFE : in std_logic; -- User frame data error + vc2FrameTxData : in std_logic_vector(TxLaneCnt*16-1 downto 0); -- User frame data + vc2LocBuffAFull : in std_logic; -- Remote buffer almost full + vc2LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 3 + vc3FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxReady : out std_logic; -- PGP is ready + vc3FrameTxSOF : in std_logic; -- User frame data start of frame + vc3FrameTxEOF : in std_logic; -- User frame data end of frame + vc3FrameTxEOFE : in std_logic; -- User frame data error + vc3FrameTxData : in std_logic_vector(TxLaneCnt*16-1 downto 0); -- User frame data + vc3LocBuffAFull : in std_logic; -- Remote buffer almost full + vc3LocBuffFull : in std_logic; -- Remote buffer full + + -- Transmit CRC Interface + crcTxIn : out std_logic_vector(TxLaneCnt*16-1 downto 0); -- Transmit data for CRC + crcTxInit : out std_logic; -- Transmit CRC value init + crcTxValid : out std_logic; -- Transmit data for CRC is valid + crcTxOut : in std_logic_vector(31 downto 0) -- Transmit calculated CRC value + ); + +end Pgp2TxCell; + + +-- Define architecture +architecture Pgp2TxCell of Pgp2TxCell is + + -- Local Signals + signal muxFrameTxValid : std_logic; + signal muxFrameTxSOF : std_logic; + signal muxFrameTxEOF : std_logic; + signal muxFrameTxEOFE : std_logic; + signal muxFrameTxData : std_logic_vector(TxLaneCnt*16-1 downto 0); + signal cellCnt : std_logic_vector(PayloadCntTop downto 0); + signal cellCntRst : std_logic; + signal nxtFrameTxReady : std_logic; + signal nxtType : std_logic_vector(2 downto 0); + signal nxtTypeLast : std_logic_vector(2 downto 0); + signal curTypeLast : std_logic_vector(2 downto 0); + signal nxtTxSOF : std_logic; + signal nxtTxEOF : std_logic; + signal nxtTxAck : std_logic; + signal nxtData : std_logic_vector(TxLaneCnt*16-1 downto 0); + signal eocWord : std_logic_vector(TxLaneCnt*16-1 downto 0); + signal socWord : std_logic_vector(TxLaneCnt*16-1 downto 0); + signal crcWordA : std_logic_vector(TxLaneCnt*16-1 downto 0); + signal crcWordB : std_logic_vector(TxLaneCnt*16-1 downto 0); + signal serialCntEn : std_logic; + signal vc0Serial : std_logic_vector(5 downto 0); + signal vc1Serial : std_logic_vector(5 downto 0); + signal vc2Serial : std_logic_vector(5 downto 0); + signal vc3Serial : std_logic_vector(5 downto 0); + signal muxSerial : std_logic_vector(5 downto 0); + signal dly0Data : std_logic_vector(TxLaneCnt*16-1 downto 0); + signal dly0Type : std_logic_vector(2 downto 0); + signal dly1Data : std_logic_vector(TxLaneCnt*16-1 downto 0); + signal dly1Type : std_logic_vector(2 downto 0); + signal dly2Data : std_logic_vector(TxLaneCnt*16-1 downto 0); + signal dly2Type : std_logic_vector(2 downto 0); + signal dly3Data : std_logic_vector(TxLaneCnt*16-1 downto 0); + signal dly3Type : std_logic_vector(2 downto 0); + signal dly4Data : std_logic_vector(TxLaneCnt*16-1 downto 0); + signal dly4Type : std_logic_vector(2 downto 0); + signal int0FrameTxReady : std_logic; + signal int1FrameTxReady : std_logic; + signal int2FrameTxReady : std_logic; + signal int3FrameTxReady : std_logic; + + -- Transmit Data Marker + constant TX_DATA : std_logic_vector(2 downto 0) := "000"; + constant TX_SOC : std_logic_vector(2 downto 0) := "001"; + constant TX_SOF : std_logic_vector(2 downto 0) := "010"; + constant TX_EOC : std_logic_vector(2 downto 0) := "011"; + constant TX_EOF : std_logic_vector(2 downto 0) := "100"; + constant TX_EOFE : std_logic_vector(2 downto 0) := "101"; + constant TX_CRCA : std_logic_vector(2 downto 0) := "110"; + constant TX_CRCB : std_logic_vector(2 downto 0) := "111"; + + -- Transmit states + signal curState : std_logic_vector(2 downto 0); + signal nxtState : std_logic_vector(2 downto 0); + constant ST_IDLE : std_logic_vector(2 downto 0) := "001"; + constant ST_EMPTY : std_logic_vector(2 downto 0) := "010"; + constant ST_SOC : std_logic_vector(2 downto 0) := "011"; + constant ST_DATA : std_logic_vector(2 downto 0) := "100"; + constant ST_CRCA : std_logic_vector(2 downto 0) := "101"; + constant ST_CRCB : std_logic_vector(2 downto 0) := "110"; + constant ST_EOC : std_logic_vector(2 downto 0) := "111"; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + + -- Mux incoming data + process ( vc0FrameTxValid, vc0FrameTxSOF, vc0FrameTxEOF, vc0FrameTxEOFE, vc0FrameTxData, + vc1FrameTxValid, vc1FrameTxSOF, vc1FrameTxEOF, vc1FrameTxEOFE, vc1FrameTxData, + vc2FrameTxValid, vc2FrameTxSOF, vc2FrameTxEOF, vc2FrameTxEOFE, vc2FrameTxData, + vc3FrameTxValid, vc3FrameTxSOF, vc3FrameTxEOF, vc3FrameTxEOFE, vc3FrameTxData, + vc0Serial, vc1Serial, vc2Serial, vc3Serial, schTxDataVc ) begin + case schTxDataVc is + when "00" => + muxFrameTxValid <= vc0FrameTxValid; + muxFrameTxSOF <= vc0FrameTxSOF; + muxFrameTxEOF <= vc0FrameTxEOF; + muxFrameTxEOFE <= vc0FrameTxEOFE; + muxFrameTxData <= vc0FrameTxData; + muxSerial <= vc0Serial; + when "01" => + muxFrameTxValid <= vc1FrameTxValid; + muxFrameTxSOF <= vc1FrameTxSOF; + muxFrameTxEOF <= vc1FrameTxEOF; + muxFrameTxEOFE <= vc1FrameTxEOFE; + muxFrameTxData <= vc1FrameTxData; + muxSerial <= vc1Serial; + when "10" => + muxFrameTxValid <= vc2FrameTxValid; + muxFrameTxSOF <= vc2FrameTxSOF; + muxFrameTxEOF <= vc2FrameTxEOF; + muxFrameTxEOFE <= vc2FrameTxEOFE; + muxFrameTxData <= vc2FrameTxData; + muxSerial <= vc2Serial; + when others => + muxFrameTxValid <= vc3FrameTxValid; + muxFrameTxSOF <= vc3FrameTxSOF; + muxFrameTxEOF <= vc3FrameTxEOF; + muxFrameTxEOFE <= vc3FrameTxEOFE; + muxFrameTxData <= vc3FrameTxData; + muxSerial <= vc3Serial; + end case; + end process; + + + -- Choose data for SOF & EOF Positions + GEN_DATA: for i in 0 to (TxLaneCnt-1) generate + + -- SOF, vc number and serial number + socWord(i*16+15 downto i*16+14) <= schTxDataVc; + socWord(i*16+13 downto i*16+8) <= muxSerial; + socWord(i*16+7 downto i*16) <= (others=>'0'); + + -- EOF, buffer status + eocWord(i*16+15 downto i*16+12) <= vc3LocBuffFull & vc2LocBuffFull & vc1LocBuffFull & vc0LocBuffFull; + eocWord(i*16+11 downto i*16+8) <= vc3LocBuffAFull & vc2LocBuffAFull & vc1LocBuffAFull & vc0LocBuffAFull; + eocWord(i*16+7 downto i*16) <= (others=>'0'); + end generate; + + + -- Simple state machine to control transmission of data frames + process ( pgpTxClk, pgpTxReset ) begin + if pgpTxReset = '1' then + curState <= ST_IDLE after tpd; + cellCnt <= (others=>'0') after tpd; + int0FrameTxReady <= '0' after tpd; + int1FrameTxReady <= '0' after tpd; + int2FrameTxReady <= '0' after tpd; + int3FrameTxReady <= '0' after tpd; + schTxSOF <= '0' after tpd; + schTxEOF <= '0' after tpd; + schTxAck <= '0' after tpd; + vc0Serial <= (others=>'0') after tpd; + vc1Serial <= (others=>'0') after tpd; + vc2Serial <= (others=>'0') after tpd; + vc3Serial <= (others=>'0') after tpd; + curTypeLast <= (others=>'0') after tpd; + elsif rising_edge(pgpTxClk) then + + -- State control + if pgpTxLinkReady = '0' then + curState <= ST_IDLE after tpd; + else + curState <= nxtState after tpd; + end if; + + -- Payload Counter + if cellCntRst = '1' then + cellCnt <= (others=>'1') after tpd; + elsif cellCnt /= 0 then + cellCnt <= cellCnt - 1 after tpd; + end if; + + -- Outgoing ready signal + case schTxDataVc is + when "00" => + int0FrameTxReady <= nxtFrameTxReady after tpd; + int1FrameTxReady <= '0' after tpd; + int2FrameTxReady <= '0' after tpd; + int3FrameTxReady <= '0' after tpd; + when "01" => + int0FrameTxReady <= '0' after tpd; + int1FrameTxReady <= nxtFrameTxReady after tpd; + int2FrameTxReady <= '0' after tpd; + int3FrameTxReady <= '0' after tpd; + when "10" => + int0FrameTxReady <= '0' after tpd; + int1FrameTxReady <= '0' after tpd; + int2FrameTxReady <= nxtFrameTxReady after tpd; + int3FrameTxReady <= '0' after tpd; + when others => + int0FrameTxReady <= '0' after tpd; + int1FrameTxReady <= '0' after tpd; + int2FrameTxReady <= '0' after tpd; + int3FrameTxReady <= nxtFrameTxReady after tpd; + end case; + + -- Update Last Type + curTypeLast <= nxtTypeLast after tpd; + + -- VC Serial Numbers + if pgpTxLinkReady = '0' then + vc0Serial <= (others=>'0') after tpd; + vc1Serial <= (others=>'0') after tpd; + vc2Serial <= (others=>'0') after tpd; + vc3Serial <= (others=>'0') after tpd; + elsif serialCntEn = '1' then + case schTxDataVc is + when "00" => vc0Serial <= vc0Serial + 1 after tpd; + when "01" => vc1Serial <= vc1Serial + 1 after tpd; + when "10" => vc2Serial <= vc2Serial + 1 after tpd; + when others => vc3Serial <= vc3Serial + 1 after tpd; + end case; + end if; + + -- Scheduler Signals + schTxSOF <= nxtTxSOF after tpd; + schTxEOF <= nxtTxEOF after tpd; + schTxAck <= nxtTxAck after tpd; + + end if; + end process; + + + -- Drive TX Ready + vc0FrameTxReady <= int0FrameTxReady; + vc1FrameTxReady <= int1FrameTxReady; + vc2FrameTxReady <= int2FrameTxReady; + vc3FrameTxReady <= int3FrameTxReady; + + + -- Async state control + process ( curState, schTxIdle, schTxReq, cellCnt, eocWord, socWord, curTypeLast, + muxFrameTxValid, muxFrameTxSOF, muxFrameTxEOF, muxFrameTxEOFE, muxFrameTxData ) begin + case curState is + + -- Idle + when ST_IDLE => + cellCntRst <= '1'; + nxtFrameTxReady <= '0'; + nxtType <= TX_DATA; + nxtData <= (others=>'0'); + nxtTxSOF <= '0'; + nxtTxEOF <= '0'; + nxtTxAck <= '0'; + serialCntEn <= '0'; + nxtTypeLast <= (others=>'0'); + + -- Idle request + if schTxIdle = '1' then + nxtState <= ST_EMPTY; + + -- Cell transmit request + elsif schTxReq = '1' then + nxtState <= ST_SOC; + else + nxtState <= curState; + end if; + + -- Send empty cell + when ST_EMPTY => + cellCntRst <= '1'; + nxtFrameTxReady <= '0'; + nxtType <= TX_EOC; + nxtTxSOF <= '0'; + nxtTxEOF <= '0'; + nxtTxAck <= '1'; + serialCntEn <= '0'; + nxtData <= eocWord; + nxtTypeLast <= (others=>'0'); + + -- Go back to idle + nxtState <= ST_IDLE; + + -- Send first charactor of cell, assert ready + when ST_SOC => + cellCntRst <= '1'; + nxtFrameTxReady <= '1'; + nxtTxEOF <= '0'; + nxtTxAck <= '0'; + serialCntEn <= '0'; + nxtData <= socWord; + nxtTypeLast <= (others=>'0'); + + -- Determine type + if muxFrameTxSOF = '1' then + nxtType <= TX_SOF; + nxtTxSOF <= '1'; + else + nxtType <= TX_SOC; + nxtTxSOF <= '0'; + end if; + + -- Move on to normal data + nxtState <= ST_DATA; + + -- Send data + when ST_DATA => + cellCntRst <= '0'; + nxtTxEOF <= '0'; + nxtTxSOF <= '0'; + nxtTxAck <= '0'; + serialCntEn <= '0'; + nxtData <= muxFrameTxData; + nxtType <= TX_DATA; + + -- Valid is de-asserted + if muxFrameTxValid = '0' then + nxtTypeLast <= TX_EOC; + nxtFrameTxReady <= '0'; + nxtType <= TX_CRCA; + + -- One or two CRC words? + if TxLaneCnt = 1 then + nxtState <= ST_CRCB; + else + nxtState <= ST_EOC; + end if; + else + nxtType <= TX_DATA; + + -- EOFE is asserted + if muxFrameTxEOFE = '1' then + nxtTypeLast <= TX_EOFE; + nxtState <= ST_CRCA; + nxtFrameTxReady <= '0'; + + -- EOF is asserted + elsif muxFrameTxEOF = '1' then + nxtTypeLast <= TX_EOF; + nxtState <= ST_CRCA; + nxtFrameTxReady <= '0'; + + -- Cell size reached + elsif cellCnt = 0 then + nxtTypeLast <= TX_EOC; + nxtState <= ST_CRCA; + nxtFrameTxReady <= '0'; + + -- Keep sending cell data + else + nxtTypeLast <= curTypeLast; + nxtState <= curState; + nxtFrameTxReady <= '1'; + nxtType <= TX_DATA; + end if; + end if; + + -- Send CRC A + when ST_CRCA => + cellCntRst <= '1'; + nxtTxEOF <= '0'; + nxtTxSOF <= '0'; + nxtTxAck <= '0'; + serialCntEn <= '0'; + nxtData <= (others=>'0'); + nxtType <= TX_CRCA; + nxtTypeLast <= curTypeLast; + nxtFrameTxReady <= '0'; + + -- One or two CRC words? + if TxLaneCnt = 1 then + nxtState <= ST_CRCB; + else + nxtState <= ST_EOC; + end if; + + -- Send CRC B + when ST_CRCB => + cellCntRst <= '1'; + nxtTxEOF <= '0'; + nxtTxSOF <= '0'; + nxtTxAck <= '0'; + serialCntEn <= '0'; + nxtData <= (others=>'0'); + nxtType <= TX_CRCB; + nxtTypeLast <= curTypeLast; + nxtFrameTxReady <= '0'; + nxtState <= ST_EOC; + + -- Send End of Cell + when ST_EOC => + cellCntRst <= '1'; + nxtTxSOF <= '0'; + nxtTxAck <= '1'; + serialCntEn <= '1'; + nxtData <= eocWord; + nxtType <= curTypeLast; + nxtTypeLast <= curTypeLast; + nxtFrameTxReady <= '0'; + nxtState <= ST_IDLE; + + -- EOF? + if curTypeLast /= TX_EOC then + nxtTxEOF <= '1'; + else + nxtTxEOF <= '0'; + end if; + + -- Default State + when others => + cellCntRst <= '0'; + nxtTxEOF <= '0'; + nxtTxSOF <= '0'; + nxtTxAck <= '0'; + serialCntEn <= '0'; + nxtData <= (others=>'0'); + nxtType <= (others=>'0'); + nxtTypeLast <= (others=>'0'); + nxtFrameTxReady <= '0'; + nxtState <= ST_IDLE; + end case; + end process; + + + -- Delay chain to allow CRC data to catch up. + process ( pgpTxClk, pgpTxReset ) begin + if pgpTxReset = '1' then + dly0Data <= (others=>'0'); + dly0Type <= (others=>'0'); + dly1Data <= (others=>'0'); + dly1Type <= (others=>'0'); + dly2Data <= (others=>'0'); + dly2Type <= (others=>'0'); + dly3Data <= (others=>'0'); + dly3Type <= (others=>'0'); + dly4Data <= (others=>'0'); + dly4Type <= (others=>'0'); + elsif rising_edge(pgpTxClk) then + + -- Delay stage 1 + dly0Data <= nxtData after tpd; + dly0Type <= nxtType after tpd; + + -- Delay stage 2 + dly1Data <= dly0Data after tpd; + dly1Type <= dly0Type after tpd; + + -- Delay stage 3 + dly2Data <= dly1Data after tpd; + dly2Type <= dly1Type after tpd; + + -- Delay stage 3 + dly3Data <= dly2Data after tpd; + dly3Type <= dly2Type after tpd; + + -- Delay stage 3 + dly4Data <= dly3Data after tpd; + dly4Type <= dly3Type after tpd; + end if; + end process; + + + -- Output to CRC engine + crcTxIn <= dly0Data; + crcTxInit <= '1' when (dly0Type = TX_SOC or dly0Type = TX_SOF) else '0'; + crcTxValid <= '1' when (dly0Type = TX_SOC or dly0Type = TX_SOF or dly0Type = TX_DATA) else '0'; + + + -- CRC Data, Single lane, split into two 16-bit values + GEN_CRC_NARROW: if TxLaneCnt = 1 generate + crcWordA(7 downto 0) <= crcTxOut(31 downto 24); + crcWordA(15 downto 8) <= crcTxOut(23 downto 16); + crcWordB(7 downto 0) <= crcTxOut(15 downto 8); + crcWordB(15 downto 8) <= crcTxOut(7 downto 0); + end generate; + + -- CRC Data, Multi lane, send one 32-bit value + GEN_CRC_WIDE: if TxLaneCnt /= 1 generate + crcWordA(7 downto 0) <= crcTxOut(31 downto 24); + crcWordA(15 downto 8) <= crcTxOut(23 downto 16); + crcWordA(23 downto 16) <= crcTxOut(15 downto 8); + crcWordA(31 downto 24) <= crcTxOut(7 downto 0); + crcWordB(31 downto 0) <= (others=>'0'); + end generate; + + -- CRC Data, 3 or 4 lanes, Set upper bits to 0. + GEN_CRC_OTHER: if TxLaneCnt >= 3 generate + crcWordA(TxLaneCnt*16-1 downto 32) <= (others=>'0'); + crcWordB(TxLaneCnt*16-1 downto 32) <= (others=>'0'); + end generate; + + -- Output stage + process ( pgpTxClk, pgpTxReset ) begin + if pgpTxReset = '1' then + cellTxSOC <= '0' after tpd; + cellTxSOF <= '0' after tpd; + cellTxEOC <= '0' after tpd; + cellTxEOF <= '0' after tpd; + cellTxEOFE <= '0' after tpd; + cellTxData <= (others=>'0') after tpd; + elsif rising_edge(pgpTxClk) then + + -- Which data type + case dly2Type is + when TX_DATA => + cellTxSOC <= '0' after tpd; + cellTxSOF <= '0' after tpd; + cellTxEOC <= '0' after tpd; + cellTxEOF <= '0' after tpd; + cellTxEOFE <= '0' after tpd; + cellTxData <= dly2Data after tpd; + when TX_SOC => + cellTxSOC <= '1' after tpd; + cellTxSOF <= '0' after tpd; + cellTxEOC <= '0' after tpd; + cellTxEOF <= '0' after tpd; + cellTxEOFE <= '0' after tpd; + cellTxData <= dly2Data after tpd; + when TX_SOF => + cellTxSOC <= '1' after tpd; + cellTxSOF <= '1' after tpd; + cellTxEOC <= '0' after tpd; + cellTxEOF <= '0' after tpd; + cellTxEOFE <= '0' after tpd; + cellTxData <= dly2Data after tpd; + when TX_CRCA => + cellTxSOC <= '0' after tpd; + cellTxSOF <= '0' after tpd; + cellTxEOC <= '0' after tpd; + cellTxEOF <= '0' after tpd; + cellTxEOFE <= '0' after tpd; + cellTxData <= crcWordA after tpd; + when TX_CRCB => + cellTxSOC <= '0' after tpd; + cellTxSOF <= '0' after tpd; + cellTxEOC <= '0' after tpd; + cellTxEOF <= '0' after tpd; + cellTxEOFE <= '0' after tpd; + cellTxData <= crcWordB after tpd; + when TX_EOC => + cellTxSOC <= '0' after tpd; + cellTxSOF <= '0' after tpd; + cellTxEOC <= '1' after tpd; + cellTxEOF <= '0' after tpd; + cellTxEOFE <= '0' after tpd; + cellTxData <= dly2Data after tpd; + when TX_EOF => + cellTxSOC <= '0' after tpd; + cellTxSOF <= '0' after tpd; + cellTxEOC <= '1' after tpd; + cellTxEOF <= '1' after tpd; + cellTxEOFE <= '0' after tpd; + cellTxData <= dly2Data after tpd; + when TX_EOFE => + cellTxSOC <= '0' after tpd; + cellTxSOF <= '0' after tpd; + cellTxEOC <= '1' after tpd; + cellTxEOF <= '1' after tpd; + cellTxEOFE <= '1' after tpd; + cellTxData <= dly2Data after tpd; + when others => + cellTxSOC <= '0' after tpd; + cellTxSOF <= '0' after tpd; + cellTxEOC <= '0' after tpd; + cellTxEOF <= '0' after tpd; + cellTxEOFE <= '0' after tpd; + cellTxData <= (others=>'0') after tpd; + end case; + end if; + end process; + +end Pgp2TxCell; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/core/Pgp2TxPhy.vhd b/rce/fw-hsio/modules/pgp2/hdl/core/Pgp2TxPhy.vhd new file mode 100755 index 00000000..a1e99ac8 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/core/Pgp2TxPhy.vhd @@ -0,0 +1,413 @@ +--------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol V2, Physical Interface Transmit Module +-- Project : General Purpose Core +--------------------------------------------------------------------------------- +-- File : Pgp2TxPhy.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 05/18/2009 +--------------------------------------------------------------------------------- +-- Description: +-- Physical interface receive module for the Pretty Good Protocol version 2 core. +--------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +--------------------------------------------------------------------------------- +-- Modification history: +-- 05/18/2009: created. +-- 11/23/2009: Renamed package. +--------------------------------------------------------------------------------- + +LIBRARY ieee; +USE work.ALL; +USE work.Pgp2CorePackage.ALL; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity Pgp2TxPhy is + generic ( + TxLaneCnt : integer := 4 -- Number of receive lanes, 1-4 + ); + port ( + + -- System clock, reset & control + pgpTxClk : in std_logic; -- Master clock + pgpTxReset : in std_logic; -- Synchronous reset input + + -- Link is ready + pgpTxLinkReady : out std_logic; -- Local side has link + + -- Opcode Transmit Interface + pgpTxOpCodeEn : in std_logic; -- Opcode receive enable + pgpTxOpCode : in std_logic_vector(7 downto 0); -- Opcode receive value + + -- Sideband data + pgpLocLinkReady : in std_logic; -- Far end side has link + pgpLocData : in std_logic_vector(7 downto 0); -- Far end side User Data + + -- Cell Transmit Interface + cellTxSOC : in std_logic; -- Cell data start of cell + cellTxSOF : in std_logic; -- Cell data start of frame + cellTxEOC : in std_logic; -- Cell data end of cell + cellTxEOF : in std_logic; -- Cell data end of frame + cellTxEOFE : in std_logic; -- Cell data end of frame error + cellTxData : in std_logic_vector(TxLaneCnt*16-1 downto 0); -- Cell data data + + -- Physical Interface Signals + phyTxData : out std_logic_vector(TxLaneCnt*16-1 downto 0); -- PHY receive data + phyTxDataK : out std_logic_vector(TxLaneCnt*2-1 downto 0); -- PHY receive data is K character + phyTxReady : in std_logic; -- PHY receive interface is ready + + -- Debug + debug : out std_logic_vector(63 downto 0) + ); + +end Pgp2TxPhy; + + +-- Define architecture +architecture Pgp2TxPhy of Pgp2TxPhy is + + -- Local Signals + signal algnCnt : std_logic_vector(6 downto 0); + signal algnCntRst : std_logic; + signal intTxLinkReady : std_logic; + signal nxtTxLinkReady : std_logic; + signal nxtTxData : std_logic_vector(TxLaneCnt*16-1 downto 0); + signal nxtTxDataK : std_logic_vector(TxLaneCnt*2-1 downto 0); + signal dlyTxData : std_logic_vector(TxLaneCnt*16-1 downto 0); + signal dlyTxDataK : std_logic_vector(TxLaneCnt*2-1 downto 0); + signal dlySelect : std_logic; + signal intTxData : std_logic_vector(TxLaneCnt*16-1 downto 0); + signal intTxDataK : std_logic_vector(TxLaneCnt*2-1 downto 0); + signal intTxOpCode : std_logic_vector(7 downto 0); + signal intTxOpCodeEn : std_logic; + signal skpAData : std_logic_vector(TxLaneCnt*16-1 downto 0); + signal skpADataK : std_logic_vector(TxLaneCnt*2-1 downto 0); + signal skpBData : std_logic_vector(TxLaneCnt*16-1 downto 0); + signal skpBDataK : std_logic_vector(TxLaneCnt*2-1 downto 0); + signal alnAData : std_logic_vector(TxLaneCnt*16-1 downto 0); + signal alnADataK : std_logic_vector(TxLaneCnt*2-1 downto 0); + signal alnBData : std_logic_vector(TxLaneCnt*16-1 downto 0); + signal alnBDataK : std_logic_vector(TxLaneCnt*2-1 downto 0); + signal ltsAData : std_logic_vector(TxLaneCnt*16-1 downto 0); + signal ltsADataK : std_logic_vector(TxLaneCnt*2-1 downto 0); + signal ltsBData : std_logic_vector(TxLaneCnt*16-1 downto 0); + signal ltsBDataK : std_logic_vector(TxLaneCnt*2-1 downto 0); + signal cellData : std_logic_vector(TxLaneCnt*16-1 downto 0); + signal cellDataK : std_logic_vector(TxLaneCnt*2-1 downto 0); + signal dlyTxEOC : std_logic; + + -- Physical Link State + constant ST_LOCK : std_logic_vector(3 downto 0) := "0000"; + constant ST_SKP_A : std_logic_vector(3 downto 0) := "0001"; + constant ST_SKP_B : std_logic_vector(3 downto 0) := "0010"; + constant ST_LTS_A : std_logic_vector(3 downto 0) := "0011"; + constant ST_LTS_B : std_logic_vector(3 downto 0) := "0100"; + constant ST_ALN_A : std_logic_vector(3 downto 0) := "0101"; + constant ST_ALN_B : std_logic_vector(3 downto 0) := "0110"; + constant ST_CELL : std_logic_vector(3 downto 0) := "0111"; + constant ST_EMPTY : std_logic_vector(3 downto 0) := "1000"; + signal curState : std_logic_vector(3 downto 0); + signal nxtState : std_logic_vector(3 downto 0); + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Link status + pgpTxLinkReady <= intTxLinkReady; + + -- State transition sync logic. + process ( pgpTxClk, pgpTxReset ) begin + if pgpTxReset = '1' then + curState <= ST_LOCK after tpd; + algnCnt <= (others=>'0') after tpd; + intTxLinkReady <= '0' after tpd; + intTxOpCode <= (others=>'0') after tpd; + intTxOpCodeEn <= '0' after tpd; + elsif rising_edge(pgpTxClk) then + + -- Opcode Transmit + if pgpTxOpCodeEn = '1' then + intTxOpCode <= pgpTxOpCode after tpd; + end if; + intTxOpCodeEn <= pgpTxOpCodeEn after tpd; + + -- Status signal + intTxLinkReady <= nxtTxLinkReady after tpd; + + -- PLL Lock is lost + if phyTxReady = '0' then + curState <= ST_LOCK after tpd; + else + curState <= nxtState after tpd; + end if; + + -- Cell Counter + if algnCntRst = '1' then + algnCnt <= (others=>'1') after tpd; + elsif algnCnt /= 0 and cellTxEOC = '1' then + algnCnt <= algnCnt - 1 after tpd; + end if; + end if; + end process; + + + -- Link control state machine + process ( curState, intTxLinkReady, cellTxEOC, algnCnt, + skpAData, skpADataK, skpBData, skpBDataK, alnAData, alnADataK, alnBData, + alnBDataK, ltsAData, ltsADataK, ltsBData, ltsBDataK, cellData, cellDataK ) begin + case curState is + + -- Wait for lock state + when ST_LOCK => + algnCntRst <= '1'; + nxtTxLinkReady <= '0'; + nxtTxData <= (others=>'0'); + nxtTxDataK <= (others=>'0'); + nxtState <= ST_SKP_A; + + -- Transmit SKIP word A + when ST_SKP_A => + nxtTxData <= skpAData; + nxtTxDataK <= skpADataK; + algnCntRst <= '0'; + nxtTxLinkReady <= intTxLinkReady; + nxtState <= ST_SKP_B; + + -- Transmit SKIP word B + when ST_SKP_B => + nxtTxData <= skpBData; + nxtTxDataK <= skpBDataK; + algnCntRst <= '0'; + nxtTxLinkReady <= intTxLinkReady; + nxtState <= ST_LTS_A; + + -- Transmit Align word A + when ST_ALN_A => + nxtTxData <= alnAData; + nxtTxDataK <= alnADataK; + algnCntRst <= '0'; + nxtTxLinkReady <= intTxLinkReady; + nxtState <= ST_ALN_B; + + -- Transmit Align word B + when ST_ALN_B => + nxtTxData <= alnBData; + nxtTxDataK <= alnBDataK; + algnCntRst <= '0'; + nxtTxLinkReady <= intTxLinkReady; + nxtState <= ST_LTS_A; + + -- Transmit Link Training word A + when ST_LTS_A => + nxtTxData <= ltsAData; + nxtTxDataK <= ltsADataK; + algnCntRst <= '0'; + nxtTxLinkReady <= intTxLinkReady; + nxtState <= ST_LTS_B; + + -- Transmit Link Training word B + when ST_LTS_B => + nxtTxData <= ltsBData; + nxtTxDataK <= ltsBDataK; + algnCntRst <= '0'; + nxtTxLinkReady <= '1'; + nxtState <= ST_CELL; + + -- Transmit Cell Data + when ST_CELL => + nxtTxLinkReady <= '1'; + nxtTxData <= cellData; + nxtTxDataK <= cellDataK; + algnCntRst <= '0'; + + -- State transition + if cellTxEOC = '1' then + nxtState <= ST_EMPTY; + else + nxtState <= curState; + end if; + + -- Empty location, used to re-adjust delay pipeline + when ST_EMPTY => + nxtTxLinkReady <= '1'; + nxtTxData <= (others=>'0'); + nxtTxDataK <= (others=>'0'); + + -- After enough cells send alignment word + if algnCnt = 0 then + algnCntRst <= '1'; + nxtState <= ST_ALN_A; + else + algnCntRst <= '0'; + nxtState <= ST_SKP_A; + end if; + + -- Default state + when others => + algnCntRst <= '0'; + nxtTxLinkReady <= '0'; + nxtTxData <= (others=>'0'); + nxtTxDataK <= (others=>'0'); + nxtState <= ST_LOCK; + end case; + end process; + + + -- Generate Data + GEN_DATA: for i in 0 to (TxLaneCnt-1) generate + + -- Skip word A + skpAData(i*16+7 downto i*16) <= K_COM; + skpADataK(i*2) <= '1'; + skpAData(i*16+15 downto i*16+8) <= K_SKP; + skpADataK(i*2+1) <= '1'; + + -- Skip word B + skpBData(i*16+7 downto i*16) <= K_SKP; + skpBDataK(i*2) <= '1'; + skpBData(i*16+15 downto i*16+8) <= K_SKP; + skpBDataK(i*2+1) <= '1'; + + -- Alignment Word A + alnAData(i*16+7 downto i*16) <= K_COM; + alnADataK(i*2) <= '1'; + alnAData(i*16+15 downto i*16+8) <= K_ALN; + alnADataK(i*2+1) <= '1'; + + -- Alignment Word B + alnBData(i*16+7 downto i*16) <= K_ALN; + alnBDataK(i*2) <= '1'; + alnBData(i*16+15 downto i*16+8) <= K_ALN; + alnBDataK(i*2+1) <= '1'; + + -- Link Training Word A + ltsAData(i*16+7 downto i*16) <= K_LTS; + ltsADataK(i*2) <= '1'; + ltsAData(i*16+15 downto i*16+8) <= D_102; + ltsADataK(i*2+1) <= '0'; + + -- Link Training Word B + ltsBData(i*16+7 downto i*16) <= pgpLocData; + ltsBDataK(i*2) <= '0'; + ltsBData(i*16+14) <= '0'; -- Spare + ltsBData(i*16+13 downto i*16+12) <= conv_std_logic_vector(TxLaneCnt-1,2); + ltsBData(i*16+11 downto i*16+8) <= pgp2Id; + ltsBData(i*16+15) <= pgpLocLinkReady; + ltsBDataK(i*2+1) <= '0'; + + -- Cell Data, lower byte + cellData(i*16+7 downto i*16) <= K_SOF when cellTxSOF = '1' else + K_SOC when cellTxSOC = '1' else + K_EOFE when cellTxEOFE = '1' else + K_EOF when cellTxEOF = '1' else + K_EOC when cellTxEOC = '1' else + cellTxData(i*16+7 downto i*16); + + -- Cell Data, upper byte + cellData(i*16+15 downto i*16+8) <= cellTxData(i*16+15 downto i*16+8); + + -- Cell Data, lower control + cellDataK(i*2) <= '1' when cellTxSOF = '1' or cellTxSOC = '1' or cellTxEOFE = '1' or + cellTxEOF = '1' or cellTxEOC = '1' else '0'; + + -- Cell Data, upper control + cellDataK(i*2+1) <= '0'; + end generate; + + + -- Delay chain select, used when an opcode is transmitted. + -- opcode will overwrite current position and delay chain will + -- be selected until an EOC is transmitted. At that time the + -- non-delayed chain will be select. An empty position is inserted + -- after EOC so that valid opcodes are not lost. + process ( pgpTxClk, pgpTxReset ) begin + if pgpTxReset = '1' then + dlySelect <= '0' after tpd; + dlyTxEOC <= '0' after tpd; + elsif rising_edge(pgpTxClk) then + + -- Choose delay chain when opcode is transmitted + if intTxOpCodeEn = '1' then + dlySelect <= '1' after tpd; + + -- Reset delay chain when delayed EOC is transmitted + elsif dlyTxEOC = '1' then + dlySelect <= '0' after tpd; + end if; + + -- Delayed copy of EOC + dlyTxEOC <= cellTxEOC after tpd; + + end if; + end process; + + + -- Outgoing data + GEN_OUT: for i in 0 to (TxLaneCnt-1) generate + process ( pgpTxClk, pgpTxReset ) begin + if pgpTxReset = '1' then + intTxData(i*16+15 downto i*16) <= (others=>'0') after tpd; + intTxDataK(i*2+1 downto i*2) <= (others=>'0') after tpd; + dlyTxData(i*16+15 downto i*16) <= (others=>'0') after tpd; + dlyTxDataK(i*2+1 downto i*2) <= (others=>'0') after tpd; + elsif rising_edge(pgpTxClk) then + + -- Delayed copy of data + dlyTxData(i*16+15 downto i*16) <= nxtTxData(i*16+15 downto i*16) after tpd; + dlyTxDataK(i*2+1 downto i*2) <= nxtTxDataK(i*2+1 downto i*2) after tpd; + + -- PLL Lock is lost + if phyTxReady = '0' then + intTxData(i*16+15 downto i*16) <= (others=>'0') after tpd; + intTxDataK(i*2+1 downto i*2) <= (others=>'0') after tpd; + else + + -- Delayed data, opcode transmission is not allowed until delay line resets + if dlySelect = '1' then + intTxData(i*16+15 downto i*16) <= dlyTxData(i*16+15 downto i*16) after tpd; + intTxDataK(i*2+1 downto i*2) <= dlyTxDataK(i*2+1 downto i*2) after tpd; + + -- Transmit opcode + elsif intTxOpCodeEn = '1' then + intTxData(i*16+7 downto i*16) <= K_OTS after tpd; + intTxDataK(i*2) <= '1' after tpd; + intTxData(i*16+15 downto i*16+8) <= intTxOpCode after tpd; + intTxDataK(i*2+1) <= '0' after tpd; + + -- Nornal Data + else + intTxData(i*16+15 downto i*16) <= nxtTxData(i*16+15 downto i*16) after tpd; + intTxDataK(i*2+1 downto i*2) <= nxtTxDataK(i*2+1 downto i*2) after tpd; + end if; + end if; + end if; + end process; + end generate; + + -- Outgoing data + phyTxData <= intTxData; + phyTxDataK <= intTxDataK; + + -- Debug + debug(63 downto 52) <= (others=>'0'); + debug(51) <= cellTxSOC; + debug(50) <= cellTxSOF; + debug(49) <= cellTxEOF; + debug(48) <= cellTxEOFE; + debug(47 downto 32) <= cellTxData(15 downto 0); + debug(31) <= dlySelect; + debug(30) <= dlyTxEOC; + debug(29 downto 26) <= (others=>'0'); + debug(25 downto 24) <= intTxDataK(1 downto 0); + debug(23 downto 8) <= intTxData(15 downto 0); + debug(7) <= '0'; + debug(6 downto 3) <= curState; + debug(2) <= pgpTxOpCodeEn; + debug(1) <= intTxOpCodeEn; + debug(0) <= cellTxEOC; + +end Pgp2TxPhy; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/core/Pgp2TxSched.vhd b/rce/fw-hsio/modules/pgp2/hdl/core/Pgp2TxSched.vhd new file mode 100755 index 00000000..94d9b75f --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/core/Pgp2TxSched.vhd @@ -0,0 +1,257 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, Transmit Scheduler +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2TxSched.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 05/18/2009 +------------------------------------------------------------------------------- +-- Description: +-- Transmit scheduler interface module for the Pretty Good Protocol core. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 05/18/2009: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE work.ALL; +USE work.Pgp2CorePackage.ALL; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity Pgp2TxSched is + generic ( + VcInterleave : integer := 1 -- Interleave Frames + ); + port ( + + -- System clock, reset & control + pgpTxClk : in std_logic; -- Master clock + pgpTxReset : in std_logic; -- Synchronous reset input + + -- Link flush + pgpTxFlush : in std_logic; -- Flush the link + + -- Link is ready + pgpTxLinkReady : in std_logic; -- Local side has link + + -- Cell Transmit Interface + schTxSOF : in std_logic; -- Cell contained SOF + schTxEOF : in std_logic; -- Cell contained EOF + schTxIdle : out std_logic; -- Force IDLE transmit + schTxReq : out std_logic; -- Cell transmit request + schTxAck : in std_logic; -- Cell transmit acknowledge + schTxDataVc : out std_logic_vector(1 downto 0); -- Cell transmit virtual channel + + -- VC Data Valid Signals + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxValid : in std_logic -- User frame data is valid + ); + +end Pgp2TxSched; + + +-- Define architecture +architecture Pgp2TxSched of Pgp2TxSched is + + -- Local Signals + signal currValid : std_logic; + signal currVc : std_logic_vector(1 downto 0); + signal nextVc : std_logic_vector(1 downto 0); + signal arbVc : std_logic_vector(1 downto 0); + signal arbValid : std_logic; + signal vcInFrame : std_logic_vector(3 downto 0); + signal intTxReq : std_logic; + signal intTxIdle : std_logic; + signal nxtTxReq : std_logic; + signal nxtTxIdle : std_logic; + + -- Schedular state + constant ST_RST : std_logic_vector(2 downto 0) := "001"; + constant ST_ARB : std_logic_vector(2 downto 0) := "010"; + constant ST_CELL : std_logic_vector(2 downto 0) := "011"; + constant ST_GAP_A : std_logic_vector(2 downto 0) := "100"; + constant ST_GAP_B : std_logic_vector(2 downto 0) := "101"; + constant ST_GAP_C : std_logic_vector(2 downto 0) := "110"; + signal curState : std_logic_vector(2 downto 0); + signal nxtState : std_logic_vector(2 downto 0); + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Outgoing signals + schTxReq <= intTxReq; + schTxIdle <= intTxIdle; + schTxDataVc <= currVc; + + + -- State transition logic + process ( pgpTxClk, pgpTxReset ) begin + if pgpTxReset = '1' then + curState <= ST_ARB after tpd; + currVc <= "00" after tpd; + intTxReq <= '0' after tpd; + intTxIdle <= '0' after tpd; + elsif rising_edge(pgpTxClk) then + + -- Force state to select state when link goes down + if pgpTxLinkReady = '0' then + curState <= ST_RST after tpd; + else + curState <= nxtState after tpd; + end if; + + -- Control signals + currVc <= nextVc after tpd; + intTxReq <= nxtTxReq after tpd; + intTxIdle <= nxtTxIdle after tpd; + + end if; + end process; + + + -- Scheduler state machine + process ( curState, arbValid, arbVc, currVc, schTxAck, vcInFrame, currValid ) begin + case curState is + + -- Held in reset due to non-link + when ST_RST => + nxtTxIdle <= '0'; + nxtTxReq <= '0'; + nextVc <= (others=>'0'); + nxtState <= ST_ARB; + + -- IDLE, wait for ack receiver to be ready + when ST_ARB => + + -- Non-interleave mode and current is in frame + if VcInterleave = 0 and vcInFrame(conv_integer(currVc)) = '1' then + nxtTxIdle <= not currValid; + nxtTxReq <= currValid; + nextVc <= currVc; + + -- Else use new arb winner if valid + else + nxtTxIdle <= not arbValid; + nxtTxReq <= arbValid; + nextVc <= arbVc; + end if; + nxtState <= ST_CELL; + + -- Transmit Cell Data + when ST_CELL => + nxtTxIdle <= '0'; + nxtTxReq <= '0'; + nextVc <= currVc; + + -- Cell is done + if schTxAck = '1' then + nxtState <= ST_GAP_A; + else + nxtState <= curState; + end if; + + -- Wait between cells + when ST_GAP_A => + nxtTxIdle <= '0'; + nxtTxReq <= '0'; + nextVc <= currVc; + nxtState <= ST_GAP_B; + + -- Wait between cells + when ST_GAP_B => + nxtTxIdle <= '0'; + nxtTxReq <= '0'; + nextVc <= currVc; + nxtState <= ST_GAP_C; + + -- Wait between cells + when ST_GAP_C => + nxtTxIdle <= '0'; + nxtTxReq <= '0'; + nextVc <= currVc; + nxtState <= ST_ARB; + + -- Just in case + when others => + nxtTxIdle <= '0'; + nxtTxReq <= '0'; + nextVc <= (others=>'0'); + nxtState <= ST_ARB; + end case; + end process; + + + -- Current owner has valid asserted + currValid <= vc0FrameTxValid when currVc = "00" else + vc1FrameTxValid when currVc = "01" else + vc2FrameTxValid when currVc = "10" else + vc3FrameTxValid; + + + -- Arbitrate for the next VC value based upon current VC value and status of valid inputs + process ( currVc, vc0FrameTxValid, vc1FrameTxValid, vc2FrameTxValid, vc3FrameTxValid ) begin + case currVc is + when "00" => + if vc1FrameTxValid = '1' then arbVc <= "01"; arbValid <= '1'; + elsif vc2FrameTxValid = '1' then arbVc <= "10"; arbValid <= '1'; + elsif vc3FrameTxValid = '1' then arbVc <= "11"; arbValid <= '1'; + elsif vc0FrameTxValid = '1' then arbVc <= "00"; arbValid <= '1'; + else arbVc <= currVc; arbValid <= '0'; end if; + when "01" => + if vc2FrameTxValid = '1' then arbVc <= "10"; arbValid <= '1'; + elsif vc3FrameTxValid = '1' then arbVc <= "11"; arbValid <= '1'; + elsif vc0FrameTxValid = '1' then arbVc <= "00"; arbValid <= '1'; + elsif vc1FrameTxValid = '1' then arbVc <= "01"; arbValid <= '1'; + else arbVc <= currVc; arbValid <= '0'; end if; + when "10" => + if vc3FrameTxValid = '1' then arbVc <= "11"; arbValid <= '1'; + elsif vc0FrameTxValid = '1' then arbVc <= "00"; arbValid <= '1'; + elsif vc1FrameTxValid = '1' then arbVc <= "01"; arbValid <= '1'; + elsif vc2FrameTxValid = '1' then arbVc <= "10"; arbValid <= '1'; + else arbVc <= currVc; arbValid <= '0'; end if; + when "11" => + if vc0FrameTxValid = '1' then arbVc <= "00"; arbValid <= '1'; + elsif vc1FrameTxValid = '1' then arbVc <= "01"; arbValid <= '1'; + elsif vc2FrameTxValid = '1' then arbVc <= "10"; arbValid <= '1'; + elsif vc3FrameTxValid = '1' then arbVc <= "11"; arbValid <= '1'; + else arbVc <= currVc; arbValid <= '0'; end if; + when others => + arbVc <= "00"; arbValid <= '0'; + end case; + end process; + + + -- Lock in the status of the last cell transmitted + process ( pgpTxClk, pgpTxReset ) begin + if pgpTxReset = '1' then + vcInFrame <= "0000" after tpd; + elsif rising_edge(pgpTxClk) then + + -- Link is down or flush requested, reset status + if pgpTxLinkReady = '0' or pgpTxFlush = '1' then + vcInFrame <= "0000" after tpd; + else + + -- Update state of VC, track if VC is currently in frame or not + -- SOF transmitted + if schTxSOF = '1' then + vcInFrame(conv_integer(currVc)) <= '1' after tpd; + + -- EOF transmitted + elsif schTxEOF = '1' then + vcInFrame(conv_integer(currVc)) <= '0' after tpd; + end if; + end if; + end if; + end process; + +end Pgp2TxSched; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2Gtp16.vhd b/rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2Gtp16.vhd new file mode 100755 index 00000000..ffb82400 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2Gtp16.vhd @@ -0,0 +1,861 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, GTP Wrapper +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2Gtp16.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 08/18/2009 +------------------------------------------------------------------------------- +-- Description: +-- VHDL source file containing the PGP, GTP and CRC blocks. +-- This module also contains the logic to control the reset of the GTP. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 08/18/2009: created. +-- 01/13/2010: Added received init line to help linking. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; +use work.Pgp2GtpPackage.all; +use work.Pgp2CorePackage.all; +library UNISIM; +use UNISIM.VCOMPONENTS.ALL; + + +entity Pgp2Gtp16 is + generic ( + EnShortCells : integer := 1; -- Enable short non-EOF cells + VcInterleave : integer := 1 -- Interleave Frames + ); + port ( + + -- System clock, reset & control + pgpClk : in std_logic; -- 156.25Mhz master clock + pgpClk2x : in std_logic; -- 2x master clock + pgpReset : in std_logic; -- Synchronous reset input + pgpFlush : in std_logic; -- Frame state flash + + -- PLL Reset Control + pllTxRst : in std_logic; -- Reset transmit PLL logic + pllRxRst : in std_logic; -- Reset receive PLL logic + + -- PLL Lock Status + pllRxReady : out std_logic; -- MGT Receive logic is ready + pllTxReady : out std_logic; -- MGT Transmit logic is ready + + -- Sideband data + pgpRemData : out std_logic_vector(7 downto 0); -- Far end side User Data + pgpLocData : in std_logic_vector(7 downto 0); -- Far end side User Data + + -- Opcode Transmit Interface + pgpTxOpCodeEn : in std_logic; -- Opcode receive enable + pgpTxOpCode : in std_logic_vector(7 downto 0); -- Opcode receive value + + -- Opcode Receive Interface + pgpRxOpCodeEn : out std_logic; -- Opcode receive enable + pgpRxOpCode : out std_logic_vector(7 downto 0); -- Opcode receive value + + -- Link status + pgpLocLinkReady : out std_logic; -- Local Link is ready + pgpRemLinkReady : out std_logic; -- Far end side has link + + -- Error Flags, one pulse per event + pgpRxCellError : out std_logic; -- A cell error has occured + pgpRxLinkDown : out std_logic; -- A link down event has occured + pgpRxLinkError : out std_logic; -- A link error has occured + + -- Frame Transmit Interface, VC 0 + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc0FrameTxReady : out std_logic; -- PGP is ready + vc0FrameTxSOF : in std_logic; -- User frame data start of frame + vc0FrameTxEOF : in std_logic; -- User frame data end of frame + vc0FrameTxEOFE : in std_logic; -- User frame data error + vc0FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc0LocBuffAFull : in std_logic; -- Remote buffer almost full + vc0LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 1 + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxReady : out std_logic; -- PGP is ready + vc1FrameTxSOF : in std_logic; -- User frame data start of frame + vc1FrameTxEOF : in std_logic; -- User frame data end of frame + vc1FrameTxEOFE : in std_logic; -- User frame data error + vc1FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc1LocBuffAFull : in std_logic; -- Remote buffer almost full + vc1LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 2 + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxReady : out std_logic; -- PGP is ready + vc2FrameTxSOF : in std_logic; -- User frame data start of frame + vc2FrameTxEOF : in std_logic; -- User frame data end of frame + vc2FrameTxEOFE : in std_logic; -- User frame data error + vc2FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc2LocBuffAFull : in std_logic; -- Remote buffer almost full + vc2LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 3 + vc3FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxReady : out std_logic; -- PGP is ready + vc3FrameTxSOF : in std_logic; -- User frame data start of frame + vc3FrameTxEOF : in std_logic; -- User frame data end of frame + vc3FrameTxEOFE : in std_logic; -- User frame data error + vc3FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc3LocBuffAFull : in std_logic; -- Remote buffer almost full + vc3LocBuffFull : in std_logic; -- Remote buffer full + + -- Common Frame Receive Interface For All VCs + vcFrameRxSOF : out std_logic; -- PGP frame data start of frame + vcFrameRxEOF : out std_logic; -- PGP frame data end of frame + vcFrameRxEOFE : out std_logic; -- PGP frame data error + vcFrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + + -- Frame Receive Interface, VC 0 + vc0FrameRxValid : out std_logic; -- PGP frame data is valid + vc0RemBuffAFull : out std_logic; -- Remote buffer almost full + vc0RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 1 + vc1FrameRxValid : out std_logic; -- PGP frame data is valid + vc1RemBuffAFull : out std_logic; -- Remote buffer almost full + vc1RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 2 + vc2FrameRxValid : out std_logic; -- PGP frame data is valid + vc2RemBuffAFull : out std_logic; -- Remote buffer almost full + vc2RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 3 + vc3FrameRxValid : out std_logic; -- PGP frame data is valid + vc3RemBuffAFull : out std_logic; -- Remote buffer almost full + vc3RemBuffFull : out std_logic; -- Remote buffer full + + -- GTP loopback control + gtpLoopback : in std_logic; -- GTP Serial Loopback Control + + -- GTP Signals + gtpClkIn : in std_logic; -- GTP Reference Clock In + gtpRefClkOut : out std_logic; -- GTP Reference Clock Output + gtpRxRecClk : out std_logic; -- GTP Rx Recovered Clock + gtpRxN : in std_logic; -- GTP Serial Receive Negative + gtpRxP : in std_logic; -- GTP Serial Receive Positive + gtpTxN : out std_logic; -- GTP Serial Transmit Negative + gtpTxP : out std_logic; -- GTP Serial Transmit Positive + + -- Debug + debug : out std_logic_vector(63 downto 0) + ); + +end Pgp2Gtp16; + + +-- Define architecture +architecture Pgp2Gtp16 of Pgp2Gtp16 is + + -- Local Signals + signal crcTxIn : std_logic_vector(15 downto 0); + signal crcTxInGtp : std_logic_vector(31 downto 0); + signal crcTxInit : std_logic; + signal crcTxRst : std_logic; + signal crcTxValid : std_logic; + signal crcTxWidth : std_logic_vector(2 downto 0); + signal crcTxOut : std_logic_vector(31 downto 0); + signal crcTxOutGtp : std_logic_vector(31 downto 0); + signal crcRxIn : std_logic_vector(15 downto 0); + signal crcRxInGtp : std_logic_vector(31 downto 0); + signal crcRxInit : std_logic; + signal crcRxRst : std_logic; + signal crcRxValid : std_logic; + signal crcRxWidth : std_logic_vector(2 downto 0); + signal crcRxOut : std_logic_vector(31 downto 0); + signal crcRxOutGtp : std_logic_vector(31 downto 0); + signal phyRxPolarity : std_logic_vector(0 downto 0); + signal phyRxData : std_logic_vector(15 downto 0); + signal phyRxDataK : std_logic_vector(1 downto 0); + signal phyTxData : std_logic_vector(15 downto 0); + signal phyTxDataK : std_logic_vector(1 downto 0); + signal phyRxDispErr : std_logic_vector(1 downto 0); + signal phyRxDecErr : std_logic_vector(1 downto 0); + signal phyRxReady : std_logic; + signal phyRxInit : std_logic; + signal phyTxReady : std_logic; + signal phyRxReset : std_logic; + signal phyRxElecIdleRst : std_logic; + signal phyRxElecIdle : std_logic; + signal phyRxCdrReset : std_logic; + signal phyRstDone : std_logic; + signal phyRxBuffStatus : std_logic_vector(2 downto 0); + signal phyTxReset : std_logic; + signal phyTxBuffStatus : std_logic_vector(1 downto 0); + signal phyLockDetect : std_logic; + signal intTxRst : std_logic; + signal intRxRst : std_logic; + signal pgpRxLinkReady : std_logic; + signal pgpTxLinkReady : std_logic; + signal intRxRecClk : std_logic; + signal tmpRefClkOut : std_logic; + signal txKerr : std_logic_vector(1 downto 0); + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + + -- PGP RX Block + U_Pgp2Rx: Pgp2CorePackage.Pgp2Rx + generic map ( + RxLaneCnt => 1, + EnShortCells => EnShortCells + ) port map ( + pgpRxClk => pgpClk, + pgpRxReset => pgpReset, + pgpRxFlush => pgpFlush, + pgpRxLinkReady => pgpRxLinkReady, + pgpRxCellError => pgpRxCellError, + pgpRxLinkDown => pgpRxLinkDown, + pgpRxLinkError => pgpRxLinkError, + pgpRxOpCodeEn => pgpRxOpCodeEn, + pgpRxOpCode => pgpRxOpCode, + pgpRemLinkReady => pgpRemLinkReady, + pgpRemData => pgpRemData, + vcFrameRxSOF => vcFrameRxSOF, + vcFrameRxEOF => vcFrameRxEOF, + vcFrameRxEOFE => vcFrameRxEOFE, + vcFrameRxData => vcFrameRxData, + vc0FrameRxValid => vc0FrameRxValid, + vc0RemBuffAFull => vc0RemBuffAFull, + vc0RemBuffFull => vc0RemBuffFull, + vc1FrameRxValid => vc1FrameRxValid, + vc1RemBuffAFull => vc1RemBuffAFull, + vc1RemBuffFull => vc1RemBuffFull, + vc2FrameRxValid => vc2FrameRxValid, + vc2RemBuffAFull => vc2RemBuffAFull, + vc2RemBuffFull => vc2RemBuffFull, + vc3FrameRxValid => vc3FrameRxValid, + vc3RemBuffAFull => vc3RemBuffAFull, + vc3RemBuffFull => vc3RemBuffFull, + phyRxPolarity => phyRxPolarity, + phyRxData => phyRxData, + phyRxDataK => phyRxDataK, + phyRxDispErr => phyRxDispErr, + phyRxDecErr => phyRxDecErr, + phyRxReady => phyRxReady, + phyRxInit => phyRxInit, + crcRxIn => crcRxIn, + crcRxWidth => open, + crcRxInit => crcRxInit, + crcRxValid => crcRxValid, + crcRxOut => crcRxOut, + debug => debug + ); + + + -- PGP TX Block + U_Pgp2Tx: Pgp2CorePackage.Pgp2Tx + generic map ( + TxLaneCnt => 1, + VcInterleave => VcInterleave + ) port map ( + pgpTxClk => pgpClk, + pgpTxReset => pgpReset, + pgpTxFlush => pgpFlush, + pgpTxLinkReady => pgpTxLinkReady, + pgpTxOpCodeEn => pgpTxOpCodeEn, + pgpTxOpCode => pgpTxOpCode, + pgpLocLinkReady => pgpRxLinkReady, + pgpLocData => pgpLocData, + vc0FrameTxValid => vc0FrameTxValid, + vc0FrameTxReady => vc0FrameTxReady, + vc0FrameTxSOF => vc0FrameTxSOF, + vc0FrameTxEOF => vc0FrameTxEOF, + vc0FrameTxEOFE => vc0FrameTxEOFE, + vc0FrameTxData => vc0FrameTxData, + vc0LocBuffAFull => vc0LocBuffAFull, + vc0LocBuffFull => vc0LocBuffFull, + vc1FrameTxValid => vc1FrameTxValid, + vc1FrameTxReady => vc1FrameTxReady, + vc1FrameTxSOF => vc1FrameTxSOF, + vc1FrameTxEOF => vc1FrameTxEOF, + vc1FrameTxEOFE => vc1FrameTxEOFE, + vc1FrameTxData => vc1FrameTxData, + vc1LocBuffAFull => vc1LocBuffAFull, + vc1LocBuffFull => vc1LocBuffFull, + vc2FrameTxValid => vc2FrameTxValid, + vc2FrameTxReady => vc2FrameTxReady, + vc2FrameTxSOF => vc2FrameTxSOF, + vc2FrameTxEOF => vc2FrameTxEOF, + vc2FrameTxEOFE => vc2FrameTxEOFE, + vc2FrameTxData => vc2FrameTxData, + vc2LocBuffAFull => vc2LocBuffAFull, + vc2LocBuffFull => vc2LocBuffFull, + vc3FrameTxValid => vc3FrameTxValid, + vc3FrameTxReady => vc3FrameTxReady, + vc3FrameTxSOF => vc3FrameTxSOF, + vc3FrameTxEOF => vc3FrameTxEOF, + vc3FrameTxEOFE => vc3FrameTxEOFE, + vc3FrameTxData => vc3FrameTxData, + vc3LocBuffAFull => vc3LocBuffAFull, + vc3LocBuffFull => vc3LocBuffFull, + phyTxData => phyTxData, + phyTxDataK => phyTxDataK, + phyTxReady => phyTxReady, + crcTxIn => crcTxIn, + crcTxInit => crcTxInit, + crcTxValid => crcTxValid, + crcTxOut => crcTxOut, + debug => open + ); + + + -- Adapt CRC data width flag + crcTxWidth <= "001"; + crcRxWidth <= "001"; + crcRxRst <= intRxRst or crcRxInit; + crcTxRst <= intTxRst or crcTxInit; + + -- Pass CRC data in on proper bits + crcTxInGtp(31 downto 24) <= crcTxIn(7 downto 0); + crcTxInGtp(23 downto 16) <= crcTxIn(15 downto 8); + crcTxInGtp(15 downto 0) <= (others=>'0'); + crcRxInGtp(31 downto 24) <= crcRxIn(7 downto 0); + crcRxInGtp(23 downto 16) <= crcRxIn(15 downto 8); + crcRxInGtp(15 downto 0) <= (others=>'0'); + + -- Pll Resets + intTxRst <= pllTxRst or pgpReset; + intRxRst <= pllRxRst or pgpReset; + + -- PLL Lock + pllRxReady <= phyRxReady; + pllTxReady <= phyTxReady; + + -- Link Ready + pgpLocLinkReady <= pgpRxLinkReady and pgpTxLinkReady; + + -- Invert Output CRC + crcRxOut <= not crcRxOutGtp; + crcTxOut <= not crcTxOutGtp; + + + -- TX CRC BLock + Tx_CRC: CRC32 + generic map( + CRC_INIT => x"FFFFFFFF" + ) port map( + CRCOUT => crcTxOutGtp, + CRCCLK => pgpClk, + CRCDATAVALID => crcTxValid, + CRCDATAWIDTH => crcTxWidth, + CRCIN => crcTxInGtp, + CRCRESET => crcTxRst + ); + + + -- RX CRC BLock + Rx_CRC: CRC32 + generic map( + CRC_INIT => x"FFFFFFFF" + ) port map( + CRCOUT => crcRxOutGtp, + CRCCLK => pgpClk, + CRCDATAVALID => crcRxValid, + CRCDATAWIDTH => crcRxWidth, + CRCIN => crcRxInGtp, + CRCRESET => crcRxRst + ); + + + -- RX Reset Control + U_Pgp2GtpRxRst: Pgp2GtpPackage.Pgp2GtpRxRst + port map ( + gtpRxClk => pgpClk, + gtpRxRst => intRxRst, + gtpRxReady => phyRxReady, + gtpRxInit => phyRxInit, + gtpLockDetect => phyLockDetect, + gtpRxElecIdle => phyRxElecIdle, + gtpRxBuffStatus => phyRxBuffStatus, + gtpRstDone => phyRstDone, + gtpRxElecIdleRst => phyRxElecIdleRst, + gtpRxReset => phyRxReset, + gtpRxCdrReset => phyRxCdrReset + ); + + + -- TX Reset Control + U_Pgp2GtpTxRst: Pgp2GtpPackage.Pgp2GtpTxRst + port map ( + gtpTxClk => pgpClk, + gtpTxRst => intTxRst, + gtpTxReady => phyTxReady, + gtpLockDetect => phyLockDetect, + gtpTxBuffStatus => phyTxBuffStatus, + gtpRstDone => phyRstDone, + gtpTxReset => phyTxReset + ); + + + ----------------------------- GTP_DUAL Instance -------------------------- + UGtpDual:GTP_DUAL + generic map ( + + --_______________________ Simulation-Only Attributes ___________________ + + SIM_GTPRESET_SPEEDUP => 1, + SIM_PLL_PERDIV2 => x"140", + + --___________________________ Shared Attributes ________________________ + + -------------------------- Tile and PLL Attributes --------------------- + + CLK25_DIVIDER => 10, + CLKINDC_B => TRUE, + OOB_CLK_DIVIDER => 6, + OVERSAMPLE_MODE => FALSE, + PLL_DIVSEL_FB => 2, + PLL_DIVSEL_REF => 1, + PLL_TXDIVSEL_COMM_OUT => 1, + TX_SYNC_FILTERB => 1, + + --____________________ Transmit Interface Attributes ___________________ + + ------------------- TX Buffering and Phase Alignment ------------------- + + TX_BUFFER_USE_0 => TRUE, + TX_XCLK_SEL_0 => "TXOUT", + TXRX_INVERT_0 => "00000", + + TX_BUFFER_USE_1 => TRUE, + TX_XCLK_SEL_1 => "TXOUT", + TXRX_INVERT_1 => "00000", + + --------------------- TX Serial Line Rate settings --------------------- + + PLL_TXDIVSEL_OUT_0 => 1, + + PLL_TXDIVSEL_OUT_1 => 1, + + --------------------- TX Driver and OOB signalling -------------------- + + TX_DIFF_BOOST_0 => TRUE, + + TX_DIFF_BOOST_1 => TRUE, + + ------------------ TX Pipe Control for PCI Express/SATA --------------- + + COM_BURST_VAL_0 => "1111", + + COM_BURST_VAL_1 => "1111", + --_______________________ Receive Interface Attributes ________________ + + ------------ RX Driver,OOB signalling,Coupling and Eq,CDR ------------- + + AC_CAP_DIS_0 => TRUE, + OOBDETECT_THRESHOLD_0 => "001", + PMA_CDR_SCAN_0 => x"6c07640", + PMA_RX_CFG_0 => x"09f0089", + RCV_TERM_GND_0 => FALSE, + RCV_TERM_MID_0 => FALSE, + RCV_TERM_VTTRX_0 => FALSE, + TERMINATION_IMP_0 => 50, + + AC_CAP_DIS_1 => TRUE, + OOBDETECT_THRESHOLD_1 => "001", + PMA_CDR_SCAN_1 => x"6c07640", + PMA_RX_CFG_1 => x"09f0089", + RCV_TERM_GND_1 => FALSE, + RCV_TERM_MID_1 => FALSE, + RCV_TERM_VTTRX_1 => FALSE, + TERMINATION_IMP_1 => 50, + TERMINATION_CTRL => "10100", + TERMINATION_OVRD => FALSE, + + --------------------- RX Serial Line Rate Attributes ------------------ + + PLL_RXDIVSEL_OUT_0 => 1, + PLL_SATA_0 => TRUE, + + PLL_RXDIVSEL_OUT_1 => 1, + PLL_SATA_1 => TRUE, + + ----------------------- PRBS Detection Attributes --------------------- + + PRBS_ERR_THRESHOLD_0 => x"00000001", + + PRBS_ERR_THRESHOLD_1 => x"00000001", + + ---------------- Comma Detection and Alignment Attributes ------------- + + ALIGN_COMMA_WORD_0 => 2, + COMMA_10B_ENABLE_0 => "1111111111", + COMMA_DOUBLE_0 => FALSE, + DEC_MCOMMA_DETECT_0 => TRUE, + DEC_PCOMMA_DETECT_0 => TRUE, + DEC_VALID_COMMA_ONLY_0 => FALSE, + MCOMMA_10B_VALUE_0 => "1010000011", + MCOMMA_DETECT_0 => TRUE, + PCOMMA_10B_VALUE_0 => "0101111100", + PCOMMA_DETECT_0 => TRUE, + RX_SLIDE_MODE_0 => "PCS", + + ALIGN_COMMA_WORD_1 => 2, + COMMA_10B_ENABLE_1 => "1111111111", + COMMA_DOUBLE_1 => FALSE, + DEC_MCOMMA_DETECT_1 => TRUE, + DEC_PCOMMA_DETECT_1 => TRUE, + DEC_VALID_COMMA_ONLY_1 => FALSE, + MCOMMA_10B_VALUE_1 => "1010000011", + MCOMMA_DETECT_1 => TRUE, + PCOMMA_10B_VALUE_1 => "0101111100", + PCOMMA_DETECT_1 => TRUE, + RX_SLIDE_MODE_1 => "PCS", + + ------------------ RX Loss-of-sync State Machine Attributes ----------- + + RX_LOSS_OF_SYNC_FSM_0 => FALSE, + RX_LOS_INVALID_INCR_0 => 8, + RX_LOS_THRESHOLD_0 => 128, + + RX_LOSS_OF_SYNC_FSM_1 => FALSE, + RX_LOS_INVALID_INCR_1 => 8, + RX_LOS_THRESHOLD_1 => 128, + + -------------- RX Elastic Buffer and Phase alignment Attributes ------- + + RX_BUFFER_USE_0 => TRUE, + RX_XCLK_SEL_0 => "RXREC", + + RX_BUFFER_USE_1 => TRUE, + RX_XCLK_SEL_1 => "RXREC", + + ------------------------ Clock Correction Attributes ------------------ + + CLK_CORRECT_USE_0 => TRUE, + CLK_COR_ADJ_LEN_0 => 4, + CLK_COR_DET_LEN_0 => 4, + CLK_COR_INSERT_IDLE_FLAG_0 => FALSE, + CLK_COR_KEEP_IDLE_0 => FALSE, + CLK_COR_MAX_LAT_0 => 48, + CLK_COR_MIN_LAT_0 => 36, + CLK_COR_PRECEDENCE_0 => TRUE, + CLK_COR_REPEAT_WAIT_0 => 0, + CLK_COR_SEQ_1_1_0 => "0110111100", + CLK_COR_SEQ_1_2_0 => "0100011100", + CLK_COR_SEQ_1_3_0 => "0100011100", + CLK_COR_SEQ_1_4_0 => "0100011100", + CLK_COR_SEQ_1_ENABLE_0 => "1111", + CLK_COR_SEQ_2_1_0 => "0000000000", + CLK_COR_SEQ_2_2_0 => "0000000000", + CLK_COR_SEQ_2_3_0 => "0000000000", + CLK_COR_SEQ_2_4_0 => "0000000000", + CLK_COR_SEQ_2_ENABLE_0 => "0000", + CLK_COR_SEQ_2_USE_0 => FALSE, + RX_DECODE_SEQ_MATCH_0 => TRUE, + + CLK_CORRECT_USE_1 => TRUE, + CLK_COR_ADJ_LEN_1 => 4, + CLK_COR_DET_LEN_1 => 4, + CLK_COR_INSERT_IDLE_FLAG_1 => FALSE, + CLK_COR_KEEP_IDLE_1 => FALSE, + CLK_COR_MAX_LAT_1 => 48, + CLK_COR_MIN_LAT_1 => 36, + CLK_COR_PRECEDENCE_1 => TRUE, + CLK_COR_REPEAT_WAIT_1 => 0, + CLK_COR_SEQ_1_1_1 => "1101111100", + CLK_COR_SEQ_1_2_1 => "1000111100", + CLK_COR_SEQ_1_3_1 => "1000111100", + CLK_COR_SEQ_1_4_1 => "1000111100", + CLK_COR_SEQ_1_ENABLE_1 => "1111", + CLK_COR_SEQ_2_1_1 => "0000000000", + CLK_COR_SEQ_2_2_1 => "0000000000", + CLK_COR_SEQ_2_3_1 => "0000000000", + CLK_COR_SEQ_2_4_1 => "0000000000", + CLK_COR_SEQ_2_ENABLE_1 => "0000", + CLK_COR_SEQ_2_USE_1 => FALSE, + RX_DECODE_SEQ_MATCH_1 => TRUE, + + ------------------------ Channel Bonding Attributes ------------------- + + CHAN_BOND_1_MAX_SKEW_0 => 1, + CHAN_BOND_2_MAX_SKEW_0 => 1, + CHAN_BOND_LEVEL_0 => 0, + CHAN_BOND_MODE_0 => "OFF", + CHAN_BOND_SEQ_1_1_0 => "0000000000", + CHAN_BOND_SEQ_1_2_0 => "0000000000", + CHAN_BOND_SEQ_1_3_0 => "0000000000", + CHAN_BOND_SEQ_1_4_0 => "0000000000", + CHAN_BOND_SEQ_1_ENABLE_0 => "0000", + CHAN_BOND_SEQ_2_1_0 => "0000000000", + CHAN_BOND_SEQ_2_2_0 => "0000000000", + CHAN_BOND_SEQ_2_3_0 => "0000000000", + CHAN_BOND_SEQ_2_4_0 => "0000000000", + CHAN_BOND_SEQ_2_ENABLE_0 => "0000", + CHAN_BOND_SEQ_2_USE_0 => FALSE, + CHAN_BOND_SEQ_LEN_0 => 1, + PCI_EXPRESS_MODE_0 => FALSE, + + CHAN_BOND_1_MAX_SKEW_1 => 1, + CHAN_BOND_2_MAX_SKEW_1 => 1, + CHAN_BOND_LEVEL_1 => 0, + CHAN_BOND_MODE_1 => "OFF", + CHAN_BOND_SEQ_1_1_1 => "0000000000", + CHAN_BOND_SEQ_1_2_1 => "0000000000", + CHAN_BOND_SEQ_1_3_1 => "0000000000", + CHAN_BOND_SEQ_1_4_1 => "0000000000", + CHAN_BOND_SEQ_1_ENABLE_1 => "0000", + CHAN_BOND_SEQ_2_1_1 => "0000000000", + CHAN_BOND_SEQ_2_2_1 => "0000000000", + CHAN_BOND_SEQ_2_3_1 => "0000000000", + CHAN_BOND_SEQ_2_4_1 => "0000000000", + CHAN_BOND_SEQ_2_ENABLE_1 => "0000", + CHAN_BOND_SEQ_2_USE_1 => FALSE, + CHAN_BOND_SEQ_LEN_1 => 1, + PCI_EXPRESS_MODE_1 => FALSE, + + ------------------ RX Attributes for PCI Express/SATA --------------- + + RX_STATUS_FMT_0 => "PCIE", + SATA_BURST_VAL_0 => "100", + SATA_IDLE_VAL_0 => "100", + SATA_MAX_BURST_0 => 7, + SATA_MAX_INIT_0 => 22, + SATA_MAX_WAKE_0 => 7, + SATA_MIN_BURST_0 => 4, + SATA_MIN_INIT_0 => 12, + SATA_MIN_WAKE_0 => 4, + TRANS_TIME_FROM_P2_0 => x"0060", + TRANS_TIME_NON_P2_0 => x"0025", + TRANS_TIME_TO_P2_0 => x"0100", + + RX_STATUS_FMT_1 => "PCIE", + SATA_BURST_VAL_1 => "100", + SATA_IDLE_VAL_1 => "100", + SATA_MAX_BURST_1 => 7, + SATA_MAX_INIT_1 => 22, + SATA_MAX_WAKE_1 => 7, + SATA_MIN_BURST_1 => 4, + SATA_MIN_INIT_1 => 12, + SATA_MIN_WAKE_1 => 4, + TRANS_TIME_FROM_P2_1 => x"0060", + TRANS_TIME_NON_P2_1 => x"0025", + TRANS_TIME_TO_P2_1 => x"0100" + + ) port map ( + + ------------------------ Loopback and Powerdown Ports ---------------------- + LOOPBACK0(0) => '0', + LOOPBACK0(1) => gtpLoopback, + LOOPBACK0(2) => '0', + LOOPBACK1 => "000", + RXPOWERDOWN0 => (others=>'0'), + RXPOWERDOWN1 => (others=>'0'), + TXPOWERDOWN0 => (others=>'0'), + TXPOWERDOWN1 => (others=>'0'), + ----------------------- Receive Ports - 8b10b Decoder ---------------------- + RXCHARISCOMMA0 => open, + RXCHARISCOMMA1 => open, + RXCHARISK0 => phyRxDataK, + RXCHARISK1 => open, + RXDEC8B10BUSE0 => '1', + RXDEC8B10BUSE1 => '1', + RXDISPERR0 => phyRxDispErr, + RXDISPERR1 => open, + RXNOTINTABLE0 => phyRxDecErr, + RXNOTINTABLE1 => open, + RXRUNDISP0 => open, + RXRUNDISP1 => open, + ------------------- Receive Ports - Channel Bonding Ports ------------------ + RXCHANBONDSEQ0 => open, + RXCHANBONDSEQ1 => open, + RXCHBONDI0 => (others=>'0'), + RXCHBONDI1 => (others=>'0'), + RXCHBONDO0 => open, + RXCHBONDO1 => open, + RXENCHANSYNC0 => '0', + RXENCHANSYNC1 => '0', + ------------------- Receive Ports - Clock Correction Ports ----------------- + RXCLKCORCNT0 => open, + RXCLKCORCNT1 => open, + --------------- Receive Ports - Comma Detection and Alignment -------------- + RXBYTEISALIGNED0 => open, + RXBYTEISALIGNED1 => open, + RXBYTEREALIGN0 => open, + RXBYTEREALIGN1 => open, + RXCOMMADET0 => open, + RXCOMMADET1 => open, + RXCOMMADETUSE0 => '1', + RXCOMMADETUSE1 => '1', + RXENMCOMMAALIGN0 => '1', + RXENMCOMMAALIGN1 => '1', + RXENPCOMMAALIGN0 => '1', + RXENPCOMMAALIGN1 => '1', + RXSLIDE0 => '0', + RXSLIDE1 => '0', + ----------------------- Receive Ports - PRBS Detection --------------------- + PRBSCNTRESET0 => '0', + PRBSCNTRESET1 => '0', + RXENPRBSTST0 => (others=>'0'), + RXENPRBSTST1 => (others=>'0'), + RXPRBSERR0 => open, + RXPRBSERR1 => open, + ------------------- Receive Ports - RX Data Path interface ----------------- + RXDATA0 => phyRxData, + RXDATA1 => open, + RXDATAWIDTH0 => '1', + RXDATAWIDTH1 => '1', + RXRECCLK0 => intRxRecClk, + RXRECCLK1 => open, + RXRESET0 => phyRxReset, + RXRESET1 => '0', + RXUSRCLK0 => pgpClk2x, + RXUSRCLK1 => pgpClk2x, + RXUSRCLK20 => pgpClk, + RXUSRCLK21 => pgpClk, + ------- Receive Ports - RX Driver,OOB signalling,Coupling and Eq.,CDR ------ + RXCDRRESET0 => phyRxCdrReset, + RXCDRRESET1 => '0', + RXELECIDLE0 => phyRxElecIdle, + RXELECIDLE1 => open, + RXELECIDLERESET0 => phyRxElecIdleRst, + RXELECIDLERESET1 => '0', + RXENEQB0 => '0', + RXENEQB1 => '0', + RXEQMIX0 => (others=>'0'), + RXEQMIX1 => (others=>'0'), + RXEQPOLE0 => (others=>'0'), + RXEQPOLE1 => (others=>'0'), + RXN0 => gtpRxN, + RXN1 => '1', + RXP0 => gtpRxP, + RXP1 => '0', + -------- Receive Ports - RX Elastic Buffer and Phase Alignment Ports ------- + RXBUFRESET0 => '0', + RXBUFRESET1 => '0', + RXBUFSTATUS0 => phyRxBuffStatus, + RXBUFSTATUS1 => open, + RXCHANISALIGNED0 => open, + RXCHANISALIGNED1 => open, + RXCHANREALIGN0 => open, + RXCHANREALIGN1 => open, + RXPMASETPHASE0 => '0', + RXPMASETPHASE1 => '0', + RXSTATUS0 => open, + RXSTATUS1 => open, + --------------- Receive Ports - RX Loss-of-sync State Machine -------------- + RXLOSSOFSYNC0 => open, + RXLOSSOFSYNC1 => open, + ---------------------- Receive Ports - RX Oversampling --------------------- + RXENSAMPLEALIGN0 => '0', + RXENSAMPLEALIGN1 => '0', + RXOVERSAMPLEERR0 => open, + RXOVERSAMPLEERR1 => open, + -------------- Receive Ports - RX Pipe Control for PCI Express ------------- + PHYSTATUS0 => open, + PHYSTATUS1 => open, + RXVALID0 => open, + RXVALID1 => open, + ----------------- Receive Ports - RX Polarity Control Ports ---------------- + RXPOLARITY0 => phyRxPolarity(0), + RXPOLARITY1 => '0', + ------------- Shared Ports - Dynamic Reconfiguration Port (DRP) ------------ + DADDR => (others=>'0'), + DCLK => '0', + DEN => '0', + DI => (others=>'0'), + DO => open, + DRDY => open, + DWE => '0', + --------------------- Shared Ports - Tile and PLL Ports -------------------- + CLKIN => gtpClkIn, + GTPRESET => pgpReset, + GTPTEST => (others=>'0'), + INTDATAWIDTH => '1', + PLLLKDET => phyLockDetect, + PLLLKDETEN => '1', + PLLPOWERDOWN => '0', + REFCLKOUT => tmpRefClkOut, + REFCLKPWRDNB => '1', + RESETDONE0 => phyRstDone, + RESETDONE1 => open, + RXENELECIDLERESETB => '1', + TXENPMAPHASEALIGN => '0', + TXPMASETPHASE => '0', + ---------------- Transmit Ports - 8b10b Encoder Control Ports -------------- + TXBYPASS8B10B0 => (others=>'0'), + TXBYPASS8B10B1 => (others=>'0'), + TXCHARDISPMODE0 => (others=>'0'), + TXCHARDISPMODE1 => (others=>'0'), + TXCHARDISPVAL0 => (others=>'0'), + TXCHARDISPVAL1 => (others=>'0'), + TXCHARISK0 => phyTxDataK, + TXCHARISK1 => "00", + TXENC8B10BUSE0 => '1', + TXENC8B10BUSE1 => '1', + TXKERR0 => txKerr, + TXKERR1 => open, + TXRUNDISP0 => open, + TXRUNDISP1 => open, + ------------- Transmit Ports - TX Buffering and Phase Alignment ------------ + TXBUFSTATUS0 => phyTxBuffStatus, + TXBUFSTATUS1 => open, + ------------------ Transmit Ports - TX Data Path interface ----------------- + TXDATA0 => phyTxData, + TXDATA1 => (others=>'0'), + TXDATAWIDTH0 => '1', + TXDATAWIDTH1 => '1', + TXOUTCLK0 => open, + TXOUTCLK1 => open, + TXRESET0 => phyTxReset, + TXRESET1 => '0', + TXUSRCLK0 => pgpClk2x, + TXUSRCLK1 => pgpClk2x, + TXUSRCLK20 => pgpClk, + TXUSRCLK21 => pgpClk, + --------------- Transmit Ports - TX Driver and OOB signalling -------------- + TXBUFDIFFCTRL0 => "100", -- 800mV + TXBUFDIFFCTRL1 => "100", + TXDIFFCTRL0 => "100", + TXDIFFCTRL1 => "100", + TXINHIBIT0 => '0', + TXINHIBIT1 => '0', + TXN0 => gtpTxN, + TXN1 => open, + TXP0 => gtpTxP, + TXP1 => open, + TXPREEMPHASIS0 => "011", -- 4.5% + TXPREEMPHASIS1 => "011", + --------------------- Transmit Ports - TX PRBS Generator ------------------- + TXENPRBSTST0 => (others=>'0'), + TXENPRBSTST1 => (others=>'0'), + -------------------- Transmit Ports - TX Polarity Control ------------------ + TXPOLARITY0 => '0', + TXPOLARITY1 => '0', + ----------------- Transmit Ports - TX Ports for PCI Express ---------------- + TXDETECTRX0 => '0', + TXDETECTRX1 => '0', + TXELECIDLE0 => '0', + TXELECIDLE1 => '0', + --------------------- Transmit Ports - TX Ports for SATA ------------------- + TXCOMSTART0 => '0', + TXCOMSTART1 => '0', + TXCOMTYPE0 => '0', + TXCOMTYPE1 => '0' + ); + + -- Global Buffer For Ref Clock Output + U_RefClkBuff: BUFG port map ( + O => gtpRefClkOut, + I => tmpRefClkOut + ); + gtpRxRecClk <= intRxRecClk; + + +end Pgp2Gtp16; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2Gtp32.vhd b/rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2Gtp32.vhd new file mode 100755 index 00000000..f624cf61 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2Gtp32.vhd @@ -0,0 +1,899 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, GTP Wrapper +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2Gtp32.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 08/18/2009 +------------------------------------------------------------------------------- +-- Description: +-- VHDL source file containing the PGP, GTP and CRC blocks. +-- This module also contains the logic to control the reset of the GTP. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 08/18/2009: created. +-- 01/13/2010: Added received init line to help linking. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; +use work.Pgp2GtpPackage.all; +use work.Pgp2CorePackage.all; +library UNISIM; +use UNISIM.VCOMPONENTS.ALL; + + +entity Pgp2Gtp32 is + generic ( + EnShortCells : integer := 1; -- Enable short non-EOF cells + VcInterleave : integer := 1 -- Interleave Frames + ); + port ( + + -- System clock, reset & control + pgpClk : in std_logic; -- 156.25Mhz master clock + pgpClk2x : in std_logic; -- 2x master clock + pgpReset : in std_logic; -- Synchronous reset input + pgpFlush : in std_logic; -- Frame status reset + + -- PLL Reset Control + pllTxRst : in std_logic; -- Reset transmit PLL logic + pllRxRst : in std_logic; -- Reset receive PLL logic + + -- PLL Lock Status + pllRxReady : out std_logic; -- MGT Receive logic is ready + pllTxReady : out std_logic; -- MGT Transmit logic is ready + + -- Sideband data + pgpRemData : out std_logic_vector(7 downto 0); -- Far end side User Data + pgpLocData : in std_logic_vector(7 downto 0); -- Far end side User Data + + -- Opcode Transmit Interface + pgpTxOpCodeEn : in std_logic; -- Opcode receive enable + pgpTxOpCode : in std_logic_vector(7 downto 0); -- Opcode receive value + + -- Opcode Receive Interface + pgpRxOpCodeEn : out std_logic; -- Opcode receive enable + pgpRxOpCode : out std_logic_vector(7 downto 0); -- Opcode receive value + + -- Link status + pgpLocLinkReady : out std_logic; -- Local Link is ready + pgpRemLinkReady : out std_logic; -- Far end side has link + + -- Error Flags, one pulse per event + pgpRxCellError : out std_logic; -- A cell error has occured + pgpRxLinkDown : out std_logic; -- A link down event has occured + pgpRxLinkError : out std_logic; -- A link error has occured + + -- Frame Transmit Interface, VC 0 + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc0FrameTxReady : out std_logic; -- PGP is ready + vc0FrameTxSOF : in std_logic; -- User frame data start of frame + vc0FrameTxEOF : in std_logic; -- User frame data end of frame + vc0FrameTxEOFE : in std_logic; -- User frame data error + vc0FrameTxData : in std_logic_vector(31 downto 0); -- User frame data + vc0LocBuffAFull : in std_logic; -- Remote buffer almost full + vc0LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 1 + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxReady : out std_logic; -- PGP is ready + vc1FrameTxSOF : in std_logic; -- User frame data start of frame + vc1FrameTxEOF : in std_logic; -- User frame data end of frame + vc1FrameTxEOFE : in std_logic; -- User frame data error + vc1FrameTxData : in std_logic_vector(31 downto 0); -- User frame data + vc1LocBuffAFull : in std_logic; -- Remote buffer almost full + vc1LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 2 + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxReady : out std_logic; -- PGP is ready + vc2FrameTxSOF : in std_logic; -- User frame data start of frame + vc2FrameTxEOF : in std_logic; -- User frame data end of frame + vc2FrameTxEOFE : in std_logic; -- User frame data error + vc2FrameTxData : in std_logic_vector(31 downto 0); -- User frame data + vc2LocBuffAFull : in std_logic; -- Remote buffer almost full + vc2LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 3 + vc3FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxReady : out std_logic; -- PGP is ready + vc3FrameTxSOF : in std_logic; -- User frame data start of frame + vc3FrameTxEOF : in std_logic; -- User frame data end of frame + vc3FrameTxEOFE : in std_logic; -- User frame data error + vc3FrameTxData : in std_logic_vector(31 downto 0); -- User frame data + vc3LocBuffAFull : in std_logic; -- Remote buffer almost full + vc3LocBuffFull : in std_logic; -- Remote buffer full + + -- Common Frame Receive Interface For All VCs + vcFrameRxSOF : out std_logic; -- PGP frame data start of frame + vcFrameRxEOF : out std_logic; -- PGP frame data end of frame + vcFrameRxEOFE : out std_logic; -- PGP frame data error + vcFrameRxData : out std_logic_vector(31 downto 0); -- PGP frame data + + -- Frame Receive Interface, VC 0 + vc0FrameRxValid : out std_logic; -- PGP frame data is valid + vc0RemBuffAFull : out std_logic; -- Remote buffer almost full + vc0RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 1 + vc1FrameRxValid : out std_logic; -- PGP frame data is valid + vc1RemBuffAFull : out std_logic; -- Remote buffer almost full + vc1RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 2 + vc2FrameRxValid : out std_logic; -- PGP frame data is valid + vc2RemBuffAFull : out std_logic; -- Remote buffer almost full + vc2RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 3 + vc3FrameRxValid : out std_logic; -- PGP frame data is valid + vc3RemBuffAFull : out std_logic; -- Remote buffer almost full + vc3RemBuffFull : out std_logic; -- Remote buffer full + + -- GTP loopback control + gtpLoopback : in std_logic; -- GTP Serial Loopback Control + + -- GTP Signals + gtpClkIn : in std_logic; -- GTP Reference Clock In + gtpRefClkOut : out std_logic; -- GTP Reference Clock Output + gtpRxRecClk : out std_logic; -- GTP Rx Recovered Clock + gtpRxN : in std_logic_vector(1 downto 0); -- GTP Serial Receive Negative + gtpRxP : in std_logic_vector(1 downto 0); -- GTP Serial Receive Positive + gtpTxN : out std_logic_vector(1 downto 0); -- GTP Serial Transmit Negative + gtpTxP : out std_logic_vector(1 downto 0); -- GTP Serial Transmit Positive + + -- Debug + debug : out std_logic_vector(63 downto 0) + ); + +end Pgp2Gtp32; + + +-- Define architecture +architecture Pgp2Gtp32 of Pgp2Gtp32 is + + -- Local Signals + signal crcTxIn : std_logic_vector(31 downto 0); + signal crcTxInGtp : std_logic_vector(31 downto 0); + signal crcTxInit : std_logic; + signal crcTxRst : std_logic; + signal crcTxValid : std_logic; + signal crcTxWidth : std_logic_vector(2 downto 0); + signal crcTxOut : std_logic_vector(31 downto 0); + signal crcTxOutGtp : std_logic_vector(31 downto 0); + signal crcRxIn : std_logic_vector(31 downto 0); + signal crcRxInGtp : std_logic_vector(31 downto 0); + signal crcRxInit : std_logic; + signal crcRxRst : std_logic; + signal crcRxValid : std_logic; + signal crcRxWidth : std_logic_vector(2 downto 0); + signal crcRxOut : std_logic_vector(31 downto 0); + signal crcRxOutGtp : std_logic_vector(31 downto 0); + signal phyRxPolarity : std_logic_vector(1 downto 0); + signal phyRxData : std_logic_vector(31 downto 0); + signal phyRxDataK : std_logic_vector(3 downto 0); + signal phyTxData : std_logic_vector(31 downto 0); + signal phyTxDataK : std_logic_vector(3 downto 0); + signal phyRxDispErr : std_logic_vector(3 downto 0); + signal phyRxDecErr : std_logic_vector(3 downto 0); + signal phyRxReady : std_logic; + signal phyRxInit : std_logic; + signal intRxReady : std_logic_vector(1 downto 0); + signal phyTxReady : std_logic; + signal intTxReady : std_logic_vector(1 downto 0); + signal phyRxReset : std_logic_vector(1 downto 0); + signal phyRxElecIdleRst : std_logic_vector(1 downto 0); + signal phyRxElecIdle : std_logic_vector(1 downto 0); + signal phyRxCdrReset : std_logic_vector(1 downto 0); + signal phyRstDone : std_logic_vector(1 downto 0); + signal phyRxBuffStatusA : std_logic_vector(2 downto 0); + signal phyRxBuffStatusB : std_logic_vector(2 downto 0); + signal phyTxReset : std_logic_vector(1 downto 0); + signal phyTxBuffStatusA : std_logic_vector(1 downto 0); + signal phyTxBuffStatusB : std_logic_vector(1 downto 0); + signal phyLockDetect : std_logic; + signal intTxRst : std_logic; + signal intRxRst : std_logic; + signal pgpRxLinkReady : std_logic; + signal pgpTxLinkReady : std_logic; + signal intRxRecClk : std_logic; + signal tmpRefClkOut : std_logic; + signal phyChanBond : std_logic_vector(2 downto 0); + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + + -- PGP RX Block + U_Pgp2Rx: Pgp2CorePackage.Pgp2Rx + generic map ( + RxLaneCnt => 2, + EnShortCells => EnShortCells + ) port map ( + pgpRxClk => pgpClk, + pgpRxReset => pgpReset, + pgpRxFlush => pgpFlush, + pgpRxLinkReady => pgpRxLinkReady, + pgpRxCellError => pgpRxCellError, + pgpRxLinkDown => pgpRxLinkDown, + pgpRxLinkError => pgpRxLinkError, + pgpRxOpCodeEn => pgpRxOpCodeEn, + pgpRxOpCode => pgpRxOpCode, + pgpRemLinkReady => pgpRemLinkReady, + pgpRemData => pgpRemData, + vcFrameRxSOF => vcFrameRxSOF, + vcFrameRxEOF => vcFrameRxEOF, + vcFrameRxEOFE => vcFrameRxEOFE, + vcFrameRxData => vcFrameRxData, + vc0FrameRxValid => vc0FrameRxValid, + vc0RemBuffAFull => vc0RemBuffAFull, + vc0RemBuffFull => vc0RemBuffFull, + vc1FrameRxValid => vc1FrameRxValid, + vc1RemBuffAFull => vc1RemBuffAFull, + vc1RemBuffFull => vc1RemBuffFull, + vc2FrameRxValid => vc2FrameRxValid, + vc2RemBuffAFull => vc2RemBuffAFull, + vc2RemBuffFull => vc2RemBuffFull, + vc3FrameRxValid => vc3FrameRxValid, + vc3RemBuffAFull => vc3RemBuffAFull, + vc3RemBuffFull => vc3RemBuffFull, + phyRxPolarity => phyRxPolarity, + phyRxData => phyRxData, + phyRxDataK => phyRxDataK, + phyRxDispErr => phyRxDispErr, + phyRxDecErr => phyRxDecErr, + phyRxReady => phyRxReady, + phyRxInit => phyRxInit, + crcRxIn => crcRxIn, + crcRxWidth => open, + crcRxInit => crcRxInit, + crcRxValid => crcRxValid, + crcRxOut => crcRxOut, + debug => debug + ); + + + -- PGP TX Block + U_Pgp2Tx: Pgp2CorePackage.Pgp2Tx + generic map ( + TxLaneCnt => 2, + VcInterleave => VcInterleave + ) port map ( + pgpTxClk => pgpClk, + pgpTxReset => pgpReset, + pgpTxFlush => pgpFlush, + pgpTxLinkReady => pgpTxLinkReady, + pgpTxOpCodeEn => pgpTxOpCodeEn, + pgpTxOpCode => pgpTxOpCode, + pgpLocLinkReady => pgpRxLinkReady, + pgpLocData => pgpLocData, + vc0FrameTxValid => vc0FrameTxValid, + vc0FrameTxReady => vc0FrameTxReady, + vc0FrameTxSOF => vc0FrameTxSOF, + vc0FrameTxEOF => vc0FrameTxEOF, + vc0FrameTxEOFE => vc0FrameTxEOFE, + vc0FrameTxData => vc0FrameTxData, + vc0LocBuffAFull => vc0LocBuffAFull, + vc0LocBuffFull => vc0LocBuffFull, + vc1FrameTxValid => vc1FrameTxValid, + vc1FrameTxReady => vc1FrameTxReady, + vc1FrameTxSOF => vc1FrameTxSOF, + vc1FrameTxEOF => vc1FrameTxEOF, + vc1FrameTxEOFE => vc1FrameTxEOFE, + vc1FrameTxData => vc1FrameTxData, + vc1LocBuffAFull => vc1LocBuffAFull, + vc1LocBuffFull => vc1LocBuffFull, + vc2FrameTxValid => vc2FrameTxValid, + vc2FrameTxReady => vc2FrameTxReady, + vc2FrameTxSOF => vc2FrameTxSOF, + vc2FrameTxEOF => vc2FrameTxEOF, + vc2FrameTxEOFE => vc2FrameTxEOFE, + vc2FrameTxData => vc2FrameTxData, + vc2LocBuffAFull => vc2LocBuffAFull, + vc2LocBuffFull => vc2LocBuffFull, + vc3FrameTxValid => vc3FrameTxValid, + vc3FrameTxReady => vc3FrameTxReady, + vc3FrameTxSOF => vc3FrameTxSOF, + vc3FrameTxEOF => vc3FrameTxEOF, + vc3FrameTxEOFE => vc3FrameTxEOFE, + vc3FrameTxData => vc3FrameTxData, + vc3LocBuffAFull => vc3LocBuffAFull, + vc3LocBuffFull => vc3LocBuffFull, + phyTxData => phyTxData, + phyTxDataK => phyTxDataK, + phyTxReady => phyTxReady, + crcTxIn => crcTxIn, + crcTxInit => crcTxInit, + crcTxValid => crcTxValid, + crcTxOut => crcTxOut, + debug => open + ); + + + -- Adapt CRC data width flag + crcTxWidth <= "011"; + crcRxWidth <= "011"; + crcRxRst <= intRxRst or crcRxInit; + crcTxRst <= intTxRst or crcTxInit; + + -- Pass CRC data in on proper bits + crcTxInGtp(31 downto 24) <= crcTxIn(7 downto 0); + crcTxInGtp(23 downto 16) <= crcTxIn(15 downto 8); + crcTxInGtp(15 downto 8) <= crcTxIn(23 downto 16); + crcTxInGtp(7 downto 0) <= crcTxIn(31 downto 24); + crcRxInGtp(31 downto 24) <= crcRxIn(7 downto 0); + crcRxInGtp(23 downto 16) <= crcRxIn(15 downto 8); + crcRxInGtp(15 downto 8) <= crcRxIn(23 downto 16); + crcRxInGtp(7 downto 0) <= crcRxIn(31 downto 24); + + -- Pll Resets + intTxRst <= pllTxRst or pgpReset; + intRxRst <= pllRxRst or pgpReset; + + -- PLL Lock + phyRxReady <= '1' when intRxReady = "11" else '0'; + phyTxReady <= '1' when intTxReady = "11" else '0'; + pllRxReady <= phyRxReady; + pllTxReady <= phyTxReady; + + -- Link Ready + pgpLocLinkReady <= pgpRxLinkReady and pgpTxLinkReady; + + -- Invert Output CRC + crcRxOut <= not crcRxOutGtp; + crcTxOut <= not crcTxOutGtp; + + + -- TX CRC BLock + Tx_CRC: CRC32 + generic map( + CRC_INIT => x"FFFFFFFF" + ) port map( + CRCOUT => crcTxOutGtp, + CRCCLK => pgpClk, + CRCDATAVALID => crcTxValid, + CRCDATAWIDTH => crcTxWidth, + CRCIN => crcTxInGtp, + CRCRESET => crcTxRst + ); + + + -- RX CRC BLock + Rx_CRC: CRC32 + generic map( + CRC_INIT => x"FFFFFFFF" + ) port map( + CRCOUT => crcRxOutGtp, + CRCCLK => pgpClk, + CRCDATAVALID => crcRxValid, + CRCDATAWIDTH => crcRxWidth, + CRCIN => crcRxInGtp, + CRCRESET => crcRxRst + ); + + + -- RXA Reset Control + U_Pgp2GtpRxRstA: Pgp2GtpPackage.Pgp2GtpRxRst + port map ( + gtpRxClk => pgpClk, + gtpRxRst => intRxRst, + gtpRxReady => intRxReady(0), + gtpRxInit => phyRxInit, + gtpLockDetect => phyLockDetect, + gtpRxElecIdle => phyRxElecIdle(0), + gtpRxBuffStatus => phyRxBuffStatusA, + gtpRstDone => phyRstDone(0), + gtpRxElecIdleRst => phyRxElecIdleRst(0), + gtpRxReset => phyRxReset(0), + gtpRxCdrReset => phyRxCdrReset(0) + ); + + + -- TXA Reset Control + U_Pgp2GtpTxRstA: Pgp2GtpPackage.Pgp2GtpTxRst + port map ( + gtpTxClk => pgpClk, + gtpTxRst => intTxRst, + gtpTxReady => intTxReady(0), + gtpLockDetect => phyLockDetect, + gtpTxBuffStatus => phyTxBuffStatusA, + gtpRstDone => phyRstDone(0), + gtpTxReset => phyTxReset(0) + ); + + + -- RXB Reset Control + U_Pgp2GtpRxRstB: Pgp2GtpPackage.Pgp2GtpRxRst + port map ( + gtpRxClk => pgpClk, + gtpRxRst => intRxRst, + gtpRxReady => intRxReady(1), + gtpRxInit => phyRxInit, + gtpLockDetect => phyLockDetect, + gtpRxElecIdle => phyRxElecIdle(1), + gtpRxBuffStatus => phyRxBuffStatusB, + gtpRstDone => phyRstDone(1), + gtpRxElecIdleRst => phyRxElecIdleRst(1), + gtpRxReset => phyRxReset(1), + gtpRxCdrReset => phyRxCdrReset(1) + ); + + + -- TXA Reset Control + U_Pgp2GtpTxRstB: Pgp2GtpPackage.Pgp2GtpTxRst + port map ( + gtpTxClk => pgpClk, + gtpTxRst => intTxRst, + gtpTxReady => intTxReady(1), + gtpLockDetect => phyLockDetect, + gtpTxBuffStatus => phyTxBuffStatusB, + gtpRstDone => phyRstDone(1), + gtpTxReset => phyTxReset(1) + ); + + + ----------------------------- GTP_DUAL Instance -------------------------- + UGtpDual:GTP_DUAL + generic map ( + + --_______________________ Simulation-Only Attributes ___________________ + + SIM_GTPRESET_SPEEDUP => 1, + SIM_PLL_PERDIV2 => x"140", + + --___________________________ Shared Attributes ________________________ + + -------------------------- Tile and PLL Attributes --------------------- + + CLK25_DIVIDER => 10, + CLKINDC_B => TRUE, + OOB_CLK_DIVIDER => 6, + OVERSAMPLE_MODE => FALSE, + PLL_DIVSEL_FB => 2, + PLL_DIVSEL_REF => 1, + PLL_TXDIVSEL_COMM_OUT => 1, + TX_SYNC_FILTERB => 1, + + --____________________ Transmit Interface Attributes ___________________ + + ------------------- TX Buffering and Phase Alignment ------------------- + + TX_BUFFER_USE_0 => TRUE, + TX_XCLK_SEL_0 => "TXOUT", + TXRX_INVERT_0 => "00000", + + TX_BUFFER_USE_1 => TRUE, + TX_XCLK_SEL_1 => "TXOUT", + TXRX_INVERT_1 => "00000", + + --------------------- TX Serial Line Rate settings --------------------- + + PLL_TXDIVSEL_OUT_0 => 1, + + PLL_TXDIVSEL_OUT_1 => 1, + + --------------------- TX Driver and OOB signalling -------------------- + + TX_DIFF_BOOST_0 => TRUE, + + TX_DIFF_BOOST_1 => TRUE, + + ------------------ TX Pipe Control for PCI Express/SATA --------------- + + COM_BURST_VAL_0 => "1111", + + COM_BURST_VAL_1 => "1111", + --_______________________ Receive Interface Attributes ________________ + + ------------ RX Driver,OOB signalling,Coupling and Eq,CDR ------------- + + AC_CAP_DIS_0 => TRUE, + OOBDETECT_THRESHOLD_0 => "001", + PMA_CDR_SCAN_0 => x"6c07640", + PMA_RX_CFG_0 => x"09f0089", + RCV_TERM_GND_0 => FALSE, + RCV_TERM_MID_0 => FALSE, + RCV_TERM_VTTRX_0 => FALSE, + TERMINATION_IMP_0 => 50, + + AC_CAP_DIS_1 => TRUE, + OOBDETECT_THRESHOLD_1 => "001", + PMA_CDR_SCAN_1 => x"6c07640", + PMA_RX_CFG_1 => x"09f0089", + RCV_TERM_GND_1 => FALSE, + RCV_TERM_MID_1 => FALSE, + RCV_TERM_VTTRX_1 => FALSE, + TERMINATION_IMP_1 => 50, + TERMINATION_CTRL => "10100", + TERMINATION_OVRD => FALSE, + + --------------------- RX Serial Line Rate Attributes ------------------ + + PLL_RXDIVSEL_OUT_0 => 1, + PLL_SATA_0 => TRUE, + + PLL_RXDIVSEL_OUT_1 => 1, + PLL_SATA_1 => TRUE, + + ----------------------- PRBS Detection Attributes --------------------- + + PRBS_ERR_THRESHOLD_0 => x"00000001", + + PRBS_ERR_THRESHOLD_1 => x"00000001", + + ---------------- Comma Detection and Alignment Attributes ------------- + + ALIGN_COMMA_WORD_0 => 2, + COMMA_10B_ENABLE_0 => "1111111111", + COMMA_DOUBLE_0 => FALSE, + DEC_MCOMMA_DETECT_0 => TRUE, + DEC_PCOMMA_DETECT_0 => TRUE, + DEC_VALID_COMMA_ONLY_0 => FALSE, + MCOMMA_10B_VALUE_0 => "1010000011", + MCOMMA_DETECT_0 => TRUE, + PCOMMA_10B_VALUE_0 => "0101111100", + PCOMMA_DETECT_0 => TRUE, + RX_SLIDE_MODE_0 => "PCS", + + ALIGN_COMMA_WORD_1 => 2, + COMMA_10B_ENABLE_1 => "1111111111", + COMMA_DOUBLE_1 => FALSE, + DEC_MCOMMA_DETECT_1 => TRUE, + DEC_PCOMMA_DETECT_1 => TRUE, + DEC_VALID_COMMA_ONLY_1 => FALSE, + MCOMMA_10B_VALUE_1 => "1010000011", + MCOMMA_DETECT_1 => TRUE, + PCOMMA_10B_VALUE_1 => "0101111100", + PCOMMA_DETECT_1 => TRUE, + RX_SLIDE_MODE_1 => "PCS", + + ------------------ RX Loss-of-sync State Machine Attributes ----------- + + RX_LOSS_OF_SYNC_FSM_0 => FALSE, + RX_LOS_INVALID_INCR_0 => 8, + RX_LOS_THRESHOLD_0 => 128, + + RX_LOSS_OF_SYNC_FSM_1 => FALSE, + RX_LOS_INVALID_INCR_1 => 8, + RX_LOS_THRESHOLD_1 => 128, + + -------------- RX Elastic Buffer and Phase alignment Attributes ------- + + RX_BUFFER_USE_0 => TRUE, + RX_XCLK_SEL_0 => "RXREC", + + RX_BUFFER_USE_1 => TRUE, + RX_XCLK_SEL_1 => "RXREC", + + ------------------------ Clock Correction Attributes ------------------ + + CLK_CORRECT_USE_0 => TRUE, + CLK_COR_ADJ_LEN_0 => 4, + CLK_COR_DET_LEN_0 => 4, + CLK_COR_INSERT_IDLE_FLAG_0 => FALSE, + CLK_COR_KEEP_IDLE_0 => FALSE, + CLK_COR_MAX_LAT_0 => 48, + CLK_COR_MIN_LAT_0 => 36, + CLK_COR_PRECEDENCE_0 => TRUE, + CLK_COR_REPEAT_WAIT_0 => 0, + CLK_COR_SEQ_1_1_0 => "0110111100", + CLK_COR_SEQ_1_2_0 => "0100011100", + CLK_COR_SEQ_1_3_0 => "0100011100", + CLK_COR_SEQ_1_4_0 => "0100011100", + CLK_COR_SEQ_1_ENABLE_0 => "1111", + CLK_COR_SEQ_2_1_0 => "0000000000", + CLK_COR_SEQ_2_2_0 => "0000000000", + CLK_COR_SEQ_2_3_0 => "0000000000", + CLK_COR_SEQ_2_4_0 => "0000000000", + CLK_COR_SEQ_2_ENABLE_0 => "0000", + CLK_COR_SEQ_2_USE_0 => FALSE, + RX_DECODE_SEQ_MATCH_0 => TRUE, + + CLK_CORRECT_USE_1 => TRUE, + CLK_COR_ADJ_LEN_1 => 4, + CLK_COR_DET_LEN_1 => 4, + CLK_COR_INSERT_IDLE_FLAG_1 => FALSE, + CLK_COR_KEEP_IDLE_1 => FALSE, + CLK_COR_MAX_LAT_1 => 48, + CLK_COR_MIN_LAT_1 => 36, + CLK_COR_PRECEDENCE_1 => TRUE, + CLK_COR_REPEAT_WAIT_1 => 0, + CLK_COR_SEQ_1_1_1 => "0110111100", + CLK_COR_SEQ_1_2_1 => "0100011100", + CLK_COR_SEQ_1_3_1 => "0100011100", + CLK_COR_SEQ_1_4_1 => "0100011100", + CLK_COR_SEQ_1_ENABLE_1 => "1111", + CLK_COR_SEQ_2_1_1 => "0000000000", + CLK_COR_SEQ_2_2_1 => "0000000000", + CLK_COR_SEQ_2_3_1 => "0000000000", + CLK_COR_SEQ_2_4_1 => "0000000000", + CLK_COR_SEQ_2_ENABLE_1 => "0000", + CLK_COR_SEQ_2_USE_1 => FALSE, + RX_DECODE_SEQ_MATCH_1 => TRUE, + + ------------------------ Channel Bonding Attributes ------------------- + + CHAN_BOND_1_MAX_SKEW_0 => 10, + CHAN_BOND_2_MAX_SKEW_0 => 1, + CHAN_BOND_LEVEL_0 => 1, + CHAN_BOND_MODE_0 => "MASTER", + CHAN_BOND_SEQ_1_1_0 => "0110111100", + CHAN_BOND_SEQ_1_2_0 => "0111011100", + CHAN_BOND_SEQ_1_3_0 => "0111011100", + CHAN_BOND_SEQ_1_4_0 => "0111011100", + CHAN_BOND_SEQ_1_ENABLE_0 => "1111", + CHAN_BOND_SEQ_2_1_0 => "0000000000", + CHAN_BOND_SEQ_2_2_0 => "0000000000", + CHAN_BOND_SEQ_2_3_0 => "0000000000", + CHAN_BOND_SEQ_2_4_0 => "0000000000", + CHAN_BOND_SEQ_2_ENABLE_0 => "0000", + CHAN_BOND_SEQ_2_USE_0 => FALSE, + CHAN_BOND_SEQ_LEN_0 => 1, + PCI_EXPRESS_MODE_0 => FALSE, + + CHAN_BOND_1_MAX_SKEW_1 => 10, + CHAN_BOND_2_MAX_SKEW_1 => 1, + CHAN_BOND_LEVEL_1 => 0, + CHAN_BOND_MODE_1 => "SLAVE", + CHAN_BOND_SEQ_1_1_1 => "0110111100", + CHAN_BOND_SEQ_1_2_1 => "0111011100", + CHAN_BOND_SEQ_1_3_1 => "0111011100", + CHAN_BOND_SEQ_1_4_1 => "0111011100", + CHAN_BOND_SEQ_1_ENABLE_1 => "1111", + CHAN_BOND_SEQ_2_1_1 => "0000000000", + CHAN_BOND_SEQ_2_2_1 => "0000000000", + CHAN_BOND_SEQ_2_3_1 => "0000000000", + CHAN_BOND_SEQ_2_4_1 => "0000000000", + CHAN_BOND_SEQ_2_ENABLE_1 => "0000", + CHAN_BOND_SEQ_2_USE_1 => FALSE, + CHAN_BOND_SEQ_LEN_1 => 1, + PCI_EXPRESS_MODE_1 => FALSE, + + ------------------ RX Attributes for PCI Express/SATA --------------- + + RX_STATUS_FMT_0 => "PCIE", + SATA_BURST_VAL_0 => "100", + SATA_IDLE_VAL_0 => "100", + SATA_MAX_BURST_0 => 7, + SATA_MAX_INIT_0 => 22, + SATA_MAX_WAKE_0 => 7, + SATA_MIN_BURST_0 => 4, + SATA_MIN_INIT_0 => 12, + SATA_MIN_WAKE_0 => 4, + TRANS_TIME_FROM_P2_0 => x"0060", + TRANS_TIME_NON_P2_0 => x"0025", + TRANS_TIME_TO_P2_0 => x"0100", + + RX_STATUS_FMT_1 => "PCIE", + SATA_BURST_VAL_1 => "100", + SATA_IDLE_VAL_1 => "100", + SATA_MAX_BURST_1 => 7, + SATA_MAX_INIT_1 => 22, + SATA_MAX_WAKE_1 => 7, + SATA_MIN_BURST_1 => 4, + SATA_MIN_INIT_1 => 12, + SATA_MIN_WAKE_1 => 4, + TRANS_TIME_FROM_P2_1 => x"0060", + TRANS_TIME_NON_P2_1 => x"0025", + TRANS_TIME_TO_P2_1 => x"0100" + + ) port map ( + + ------------------------ Loopback and Powerdown Ports ---------------------- + LOOPBACK0(0) => '0', + LOOPBACK0(1) => gtpLoopback, + LOOPBACK0(2) => '0', + LOOPBACK1 => "000", + RXPOWERDOWN0 => (others=>'0'), + RXPOWERDOWN1 => (others=>'0'), + TXPOWERDOWN0 => (others=>'0'), + TXPOWERDOWN1 => (others=>'0'), + ----------------------- Receive Ports - 8b10b Decoder ---------------------- + RXCHARISCOMMA0 => open, + RXCHARISCOMMA1 => open, + RXCHARISK0 => phyRxDataK(1 downto 0), + RXCHARISK1 => phyRxDataK(3 downto 2), + RXDEC8B10BUSE0 => '1', + RXDEC8B10BUSE1 => '1', + RXDISPERR0 => phyRxDispErr(1 downto 0), + RXDISPERR1 => phyRxDispErr(3 downto 2), + RXNOTINTABLE0 => phyRxDecErr(1 downto 0), + RXNOTINTABLE1 => phyRxDecErr(3 downto 2), + RXRUNDISP0 => open, + RXRUNDISP1 => open, + ------------------- Receive Ports - Channel Bonding Ports ------------------ + RXCHANBONDSEQ0 => open, + RXCHANBONDSEQ1 => open, + RXCHBONDI0 => (others=>'0'), + RXCHBONDI1 => phyChanBond, + RXCHBONDO0 => phyChanBond, + RXCHBONDO1 => open, + RXENCHANSYNC0 => '1', + RXENCHANSYNC1 => '1', + ------------------- Receive Ports - Clock Correction Ports ----------------- + RXCLKCORCNT0 => open, + RXCLKCORCNT1 => open, + --------------- Receive Ports - Comma Detection and Alignment -------------- + RXBYTEISALIGNED0 => open, + RXBYTEISALIGNED1 => open, + RXBYTEREALIGN0 => open, + RXBYTEREALIGN1 => open, + RXCOMMADET0 => open, + RXCOMMADET1 => open, + RXCOMMADETUSE0 => '1', + RXCOMMADETUSE1 => '1', + RXENMCOMMAALIGN0 => '1', + RXENMCOMMAALIGN1 => '1', + RXENPCOMMAALIGN0 => '1', + RXENPCOMMAALIGN1 => '1', + RXSLIDE0 => '0', + RXSLIDE1 => '0', + ----------------------- Receive Ports - PRBS Detection --------------------- + PRBSCNTRESET0 => '0', + PRBSCNTRESET1 => '0', + RXENPRBSTST0 => (others=>'0'), + RXENPRBSTST1 => (others=>'0'), + RXPRBSERR0 => open, + RXPRBSERR1 => open, + ------------------- Receive Ports - RX Data Path interface ----------------- + RXDATA0 => phyRxData(15 downto 0), + RXDATA1 => phyRxData(31 downto 16), + RXDATAWIDTH0 => '1', + RXDATAWIDTH1 => '1', + RXRECCLK0 => intRxRecClk, + RXRECCLK1 => open, + RXRESET0 => phyRxReset(0), + RXRESET1 => phyRxReset(1), + RXUSRCLK0 => pgpClk2x, + RXUSRCLK1 => pgpClk2x, + RXUSRCLK20 => pgpClk, + RXUSRCLK21 => pgpClk, + ------- Receive Ports - RX Driver,OOB signalling,Coupling and Eq.,CDR ------ + RXCDRRESET0 => phyRxCdrReset(0), + RXCDRRESET1 => phyRxCdrReset(1), + RXELECIDLE0 => phyRxElecIdle(0), + RXELECIDLE1 => phyRxElecIdle(1), + RXELECIDLERESET0 => phyRxElecIdleRst(0), + RXELECIDLERESET1 => phyRxElecIdleRst(1), + RXENEQB0 => '0', + RXENEQB1 => '0', + RXEQMIX0 => (others=>'0'), + RXEQMIX1 => (others=>'0'), + RXEQPOLE0 => (others=>'0'), + RXEQPOLE1 => (others=>'0'), + RXN0 => gtpRxN(0), + RXN1 => gtpRxN(1), + RXP0 => gtpRxP(0), + RXP1 => gtpRxP(1), + -------- Receive Ports - RX Elastic Buffer and Phase Alignment Ports ------- + RXBUFRESET0 => '0', + RXBUFRESET1 => '0', + RXBUFSTATUS0 => phyRxBuffStatusA, + RXBUFSTATUS1 => phyRxBuffStatusB, + RXCHANISALIGNED0 => open, + RXCHANISALIGNED1 => open, + RXCHANREALIGN0 => open, + RXCHANREALIGN1 => open, + RXPMASETPHASE0 => '0', + RXPMASETPHASE1 => '0', + RXSTATUS0 => open, + RXSTATUS1 => open, + --------------- Receive Ports - RX Loss-of-sync State Machine -------------- + RXLOSSOFSYNC0 => open, + RXLOSSOFSYNC1 => open, + ---------------------- Receive Ports - RX Oversampling --------------------- + RXENSAMPLEALIGN0 => '0', + RXENSAMPLEALIGN1 => '0', + RXOVERSAMPLEERR0 => open, + RXOVERSAMPLEERR1 => open, + -------------- Receive Ports - RX Pipe Control for PCI Express ------------- + PHYSTATUS0 => open, + PHYSTATUS1 => open, + RXVALID0 => open, + RXVALID1 => open, + ----------------- Receive Ports - RX Polarity Control Ports ---------------- + RXPOLARITY0 => phyRxPolarity(0), + RXPOLARITY1 => phyRxPolarity(1), + ------------- Shared Ports - Dynamic Reconfiguration Port (DRP) ------------ + DADDR => (others=>'0'), + DCLK => '0', + DEN => '0', + DI => (others=>'0'), + DO => open, + DRDY => open, + DWE => '0', + --------------------- Shared Ports - Tile and PLL Ports -------------------- + CLKIN => gtpClkIn, + GTPRESET => pgpReset, + GTPTEST => (others=>'0'), + INTDATAWIDTH => '1', + PLLLKDET => phyLockDetect, + PLLLKDETEN => '1', + PLLPOWERDOWN => '0', + REFCLKOUT => tmpRefClkOut, + REFCLKPWRDNB => '1', + RESETDONE0 => phyRstDone(0), + RESETDONE1 => phyRstDone(1), + RXENELECIDLERESETB => '1', + TXENPMAPHASEALIGN => '0', + TXPMASETPHASE => '0', + ---------------- Transmit Ports - 8b10b Encoder Control Ports -------------- + TXBYPASS8B10B0 => (others=>'0'), + TXBYPASS8B10B1 => (others=>'0'), + TXCHARDISPMODE0 => (others=>'0'), + TXCHARDISPMODE1 => (others=>'0'), + TXCHARDISPVAL0 => (others=>'0'), + TXCHARDISPVAL1 => (others=>'0'), + TXCHARISK0 => phyTxDataK(1 downto 0), + TXCHARISK1 => phyTxDataK(3 downto 2), + TXENC8B10BUSE0 => '1', + TXENC8B10BUSE1 => '1', + TXKERR0 => open, + TXKERR1 => open, + TXRUNDISP0 => open, + TXRUNDISP1 => open, + ------------- Transmit Ports - TX Buffering and Phase Alignment ------------ + TXBUFSTATUS0 => phyTxBuffStatusA, + TXBUFSTATUS1 => phyTxBuffStatusB, + ------------------ Transmit Ports - TX Data Path interface ----------------- + TXDATA0 => phyTxData(15 downto 0), + TXDATA1 => phyTxData(31 downto 16), + TXDATAWIDTH0 => '1', + TXDATAWIDTH1 => '1', + TXOUTCLK0 => open, + TXOUTCLK1 => open, + TXRESET0 => phyTxReset(0), + TXRESET1 => phyTxReset(1), + TXUSRCLK0 => pgpClk2x, + TXUSRCLK1 => pgpClk2x, + TXUSRCLK20 => pgpClk, + TXUSRCLK21 => pgpClk, + --------------- Transmit Ports - TX Driver and OOB signalling -------------- + TXBUFDIFFCTRL0 => "100", -- 800mV + TXBUFDIFFCTRL1 => "100", + TXDIFFCTRL0 => "100", + TXDIFFCTRL1 => "100", + TXINHIBIT0 => '0', + TXINHIBIT1 => '0', + TXN0 => gtpTxN(0), + TXN1 => gtpTxN(1), + TXP0 => gtpTxP(0), + TXP1 => gtpTxP(1), + TXPREEMPHASIS0 => "011", -- 4.5% + TXPREEMPHASIS1 => "011", + --------------------- Transmit Ports - TX PRBS Generator ------------------- + TXENPRBSTST0 => (others=>'0'), + TXENPRBSTST1 => (others=>'0'), + -------------------- Transmit Ports - TX Polarity Control ------------------ + TXPOLARITY0 => '0', + TXPOLARITY1 => '0', + ----------------- Transmit Ports - TX Ports for PCI Express ---------------- + TXDETECTRX0 => '0', + TXDETECTRX1 => '0', + TXELECIDLE0 => '0', + TXELECIDLE1 => '0', + --------------------- Transmit Ports - TX Ports for SATA ------------------- + TXCOMSTART0 => '0', + TXCOMSTART1 => '0', + TXCOMTYPE0 => '0', + TXCOMTYPE1 => '0' + ); + + -- Global Buffer For Ref Clock Output + U_RefClkBuff: BUFG port map ( + O => gtpRefClkOut, + I => tmpRefClkOut + ); + gtpRxRecClk <= intRxRecClk; + + +end Pgp2Gtp32; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2GtpClk.vhd b/rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2GtpClk.vhd new file mode 100755 index 00000000..f19b9539 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2GtpClk.vhd @@ -0,0 +1,226 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, Clock Generation Block +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2GtpClk.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 08/08/2009 +------------------------------------------------------------------------------- +-- Description: +-- PGP Clock Module. Contains DCM to support PGP clocking for GTP in Virtex5. +-- Used to generate global buffer clocks at the PGP interface rate and the 2X +-- clock required for the internal GTP logic. +-- Will also generate an optional user global clock and reset for external +-- logic use. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 08/08/2009: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; +use work.Pgp2GtpPackage.all; +Library UNISIM; +use UNISIM.VCOMPONENTS.ALL; + +entity Pgp2GtpClk is + generic ( + UserFxDiv : integer := 5; -- DCM FX Output Divide + UserFxMult : integer := 4 -- DCM FX Output Divide, 4/5 * 156.25 = 125Mhz + ); + port ( + + -- Reference Clock Input. + -- This is provided as an output from the GTP tile. + pgpRefClk : in std_logic; + + -- Power On Reset Input + ponResetL : in std_logic; + + -- Locally Generated Reset + locReset : in std_logic; + + -- Global Clock & Reset For PGP Logic, 156.25Mhz + pgpClk : out std_logic; + pgpReset : out std_logic; + + -- 2x clock required by the GTP internal logic + pgpClk2x : out std_logic; + + -- Global Clock & Reset For User Logic + userClk : out std_logic; + userReset : out std_logic; + + -- Inputs clocks for reset generation connect + -- to pgpClk and userClk + pgpClkIn : in std_logic; + userClkIn : in std_logic + ); + +end Pgp2GtpClk; + + +-- Define architecture +architecture Pgp2GtpClk of Pgp2GtpClk is + + -- Local Signals + signal ponReset : std_logic; + signal tmpPgpClk : std_logic; + signal intPgpClk : std_logic; + signal tmpPgpClk2x : std_logic; + signal intPgpClk2x : std_logic; + signal intPgpRst : std_logic; + signal tmpLocClk : std_logic; + signal intUsrClk : std_logic; + signal intUsrRst : std_logic; + signal syncPgpRstIn : std_logic_vector(2 downto 0); + signal pgpRstCnt : std_logic_vector(3 downto 0); + signal syncLocRstIn : std_logic_vector(2 downto 0); + signal locRstCnt : std_logic_vector(3 downto 0); + signal dcmLock : std_logic; + signal resetIn : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Output Generated Clock And Reset Signals + pgpClk <= intPgpClk; + pgpClk2x <= intPgpClk2x; + pgpReset <= intPgpRst; + userClk <= intUsrClk; + userReset <= intUsrRst; + + -- Invert power on reset + ponReset <= not ponResetL; + + + -- DCM For PGP Clock & User Clock + U_PgpDcm: DCM_ADV + generic map ( + DFS_FREQUENCY_MODE => "LOW", + DLL_FREQUENCY_MODE => "HIGH", + CLKIN_DIVIDE_BY_2 => FALSE, + CLK_FEEDBACK => "1X", + CLKOUT_PHASE_SHIFT => "NONE", + STARTUP_WAIT => false, + PHASE_SHIFT => 0, + CLKFX_MULTIPLY => UserFxMult, + CLKFX_DIVIDE => UserFxDiv, + CLKDV_DIVIDE => 2.0, + CLKIN_PERIOD => 6.4, + DCM_PERFORMANCE_MODE => "MAX_SPEED", + FACTORY_JF => X"F0F0", + DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS" + ) + port map ( + CLKIN => pgpRefClk, CLKFB => intPgpClk, + CLK0 => tmpPgpClk, CLK90 => open, + CLK180 => open, CLK270 => open, + CLK2X => tmpPgpClk2x, CLK2X180 => open, + CLKDV => open, CLKFX => tmpLocClk, + CLKFX180 => open, LOCKED => dcmLock, + PSDONE => open, PSCLK => '0', + PSINCDEC => '0', PSEN => '0', + DCLK => '0', DADDR => (others=>'0'), + DI => (others=>'0'), DO => open, + DRDY => open, DWE => '0', + DEN => '0', RST => ponReset + ); + + + -- Global Buffer For PGP Clock + U_PgpClkBuff: BUFG port map ( + O => intPgpClk, + I => tmpPgpClk + ); + + + -- Global Buffer For PGP 2x Clock + U_PgpClk2xBuff: BUFG port map ( + O => intPgpClk2x, + I => tmpPgpClk2x + ); + + + -- Global Buffer For User Clock + U_LocClkBuff: BUFG port map ( + O => intUsrClk, + I => tmpLocClk + ); + + + -- Generate reset input + resetIn <= (not dcmLock) or ponReset or locReset; + + -- PGP Clock Synced Reset + process ( pgpClkIn, resetIn ) begin + if resetIn = '1' then + syncPgpRstIn <= (others=>'0') after tpd; + pgpRstCnt <= (others=>'0') after tpd; + intPgpRst <= '1' after tpd; + elsif rising_edge(pgpClkIn) then + + -- Sync local reset, lock and power on reset to local clock + -- Negative asserted signal + syncPgpRstIn(0) <= '1' after tpd; + syncPgpRstIn(1) <= syncPgpRstIn(0) after tpd; + syncPgpRstIn(2) <= syncPgpRstIn(1) after tpd; + + -- Reset counter on reset + if syncPgpRstIn(2) = '0' then + pgpRstCnt <= (others=>'0') after tpd; + intPgpRst <= '1' after tpd; + + -- Count Up To Max Value + elsif pgpRstCnt = "1111" then + intPgpRst <= '0' after tpd; + + -- Increment counter + else + intPgpRst <= '1' after tpd; + pgpRstCnt <= pgpRstCnt + 1 after tpd; + end if; + end if; + end process; + + + -- Local User Clock Synced Reset + process ( userClkIn, resetIn ) begin + if resetIn = '1' then + syncLocRstIn <= (others=>'0') after tpd; + locRstCnt <= (others=>'0') after tpd; + intUsrRst <= '1' after tpd; + elsif rising_edge(userClkIn) then + + -- Sync local reset, lock and power on reset to local clock + -- Negative asserted signal + syncLocRstIn(0) <= '1' after tpd; + syncLocRstIn(1) <= syncLocRstIn(0) after tpd; + syncLocRstIn(2) <= syncLocRstIn(1) after tpd; + + -- Reset counter on reset + if syncLocRstIn(2) = '0' then + locRstCnt <= (others=>'0') after tpd; + intUsrRst <= '1' after tpd; + + -- Count Up To Max Value + elsif locRstCnt = "1111" then + intUsrRst <= '0' after tpd; + + -- Increment counter + else + intUsrRst <= '1' after tpd; + locRstCnt <= locRstCnt + 1 after tpd; + end if; + end if; + end process; + +end Pgp2GtpClk; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2GtpDual.vhd b/rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2GtpDual.vhd new file mode 100755 index 00000000..5911262f --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2GtpDual.vhd @@ -0,0 +1,1200 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, Dual Channel GTP Wrapper +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2GtpDual.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 06/14/2010 +------------------------------------------------------------------------------- +-- Description: +-- VHDL source file containing the PGP, GTP and CRC blocks. +-- This module also contains the logic to control the reset of the GTP. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 06/14/2010: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; +use work.Pgp2GtpPackage.all; +use work.Pgp2CorePackage.all; +library UNISIM; +use UNISIM.VCOMPONENTS.ALL; + + +entity Pgp2GtpDual is + generic ( + EnShortCells : integer := 1; -- Enable short non-EOF cells + VcInterleave : integer := 1 -- Interleave Frames + ); + port ( + + -- System clock, reset & control + pgpClk : in std_logic; -- 156.25Mhz master clock + pgpClk2x : in std_logic; -- 2x master clock + pgpReset : in std_logic; -- Synchronous reset input + pgpFlush : in std_logic; -- Flash frame state + + -- PLL Reset Control + pll0TxRst : in std_logic; -- Reset transmit PLL logic + pll0RxRst : in std_logic; -- Reset receive PLL logic + + -- PLL Lock Status + pll0RxReady : out std_logic; -- MGT Receive logic is ready + pll0TxReady : out std_logic; -- MGT Transmit logic is ready + + -- Sideband data + pgp0RemData : out std_logic_vector(7 downto 0); -- Far end side User Data + pgp0LocData : in std_logic_vector(7 downto 0); -- Far end side User Data + + -- Opcode Transmit Interface + pgp0TxOpCodeEn : in std_logic; -- Opcode receive enable + pgp0TxOpCode : in std_logic_vector(7 downto 0); -- Opcode receive value + + -- Opcode Receive Interface + pgp0RxOpCodeEn : out std_logic; -- Opcode receive enable + pgp0RxOpCode : out std_logic_vector(7 downto 0); -- Opcode receive value + + -- Link status + pgp0LocLinkReady : out std_logic; -- Local Link is ready + pgp0RemLinkReady : out std_logic; -- Far end side has link + + -- Error Flags, one pulse per event + pgp0RxCellError : out std_logic; -- A cell error has occured + pgp0RxLinkDown : out std_logic; -- A link down event has occured + pgp0RxLinkError : out std_logic; -- A link error has occured + + -- Frame Transmit Interface, Lane 0, VC 0 + vc00FrameTxValid : in std_logic; -- User frame data is valid + vc00FrameTxReady : out std_logic; -- PGP is ready + vc00FrameTxSOF : in std_logic; -- User frame data start of frame + vc00FrameTxEOF : in std_logic; -- User frame data end of frame + vc00FrameTxEOFE : in std_logic; -- User frame data error + vc00FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc00LocBuffAFull : in std_logic; -- Remote buffer almost full + vc00LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, Lane 0, VC 1 + vc01FrameTxValid : in std_logic; -- User frame data is valid + vc01FrameTxReady : out std_logic; -- PGP is ready + vc01FrameTxSOF : in std_logic; -- User frame data start of frame + vc01FrameTxEOF : in std_logic; -- User frame data end of frame + vc01FrameTxEOFE : in std_logic; -- User frame data error + vc01FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc01LocBuffAFull : in std_logic; -- Remote buffer almost full + vc01LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, Lane 0, VC 2 + vc02FrameTxValid : in std_logic; -- User frame data is valid + vc02FrameTxReady : out std_logic; -- PGP is ready + vc02FrameTxSOF : in std_logic; -- User frame data start of frame + vc02FrameTxEOF : in std_logic; -- User frame data end of frame + vc02FrameTxEOFE : in std_logic; -- User frame data error + vc02FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc02LocBuffAFull : in std_logic; -- Remote buffer almost full + vc02LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, Lane 0, VC 3 + vc03FrameTxValid : in std_logic; -- User frame data is valid + vc03FrameTxReady : out std_logic; -- PGP is ready + vc03FrameTxSOF : in std_logic; -- User frame data start of frame + vc03FrameTxEOF : in std_logic; -- User frame data end of frame + vc03FrameTxEOFE : in std_logic; -- User frame data error + vc03FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc03LocBuffAFull : in std_logic; -- Remote buffer almost full + vc03LocBuffFull : in std_logic; -- Remote buffer full + + -- Common Frame Receive Interface For All Lane 0 VCs + vc0FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc0FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc0FrameRxEOFE : out std_logic; -- PGP frame data error + vc0FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + + -- Frame Receive Interface, Lane 0, VC 0 + vc00FrameRxValid : out std_logic; -- PGP frame data is valid + vc00RemBuffAFull : out std_logic; -- Remote buffer almost full + vc00RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, Lane 0, VC 1 + vc01FrameRxValid : out std_logic; -- PGP frame data is valid + vc01RemBuffAFull : out std_logic; -- Remote buffer almost full + vc01RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, Lane 0, VC 2 + vc02FrameRxValid : out std_logic; -- PGP frame data is valid + vc02RemBuffAFull : out std_logic; -- Remote buffer almost full + vc02RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, Lane 0, VC 3 + vc03FrameRxValid : out std_logic; -- PGP frame data is valid + vc03RemBuffAFull : out std_logic; -- Remote buffer almost full + vc03RemBuffFull : out std_logic; -- Remote buffer full + + -- PLL Reset Control + pll1TxRst : in std_logic; -- Reset transmit PLL logic + pll1RxRst : in std_logic; -- Reset receive PLL logic + + -- PLL Lock Status + pll1RxReady : out std_logic; -- MGT Receive logic is ready + pll1TxReady : out std_logic; -- MGT Transmit logic is ready + + -- Sideband data + pgp1RemData : out std_logic_vector(7 downto 0); -- Far end side User Data + pgp1LocData : in std_logic_vector(7 downto 0); -- Far end side User Data + + -- Opcode Transmit Interface + pgp1TxOpCodeEn : in std_logic; -- Opcode receive enable + pgp1TxOpCode : in std_logic_vector(7 downto 0); -- Opcode receive value + + -- Opcode Receive Interface + pgp1RxOpCodeEn : out std_logic; -- Opcode receive enable + pgp1RxOpCode : out std_logic_vector(7 downto 0); -- Opcode receive value + + -- Link status + pgp1LocLinkReady : out std_logic; -- Local Link is ready + pgp1RemLinkReady : out std_logic; -- Far end side has link + + -- Error Flags, one pulse per event + pgp1RxCellError : out std_logic; -- A cell error has occured + pgp1RxLinkDown : out std_logic; -- A link down event has occured + pgp1RxLinkError : out std_logic; -- A link error has occured + + -- Frame Transmit Interface, Lane 1, VC 0 + vc10FrameTxValid : in std_logic; -- User frame data is valid + vc10FrameTxReady : out std_logic; -- PGP is ready + vc10FrameTxSOF : in std_logic; -- User frame data start of frame + vc10FrameTxEOF : in std_logic; -- User frame data end of frame + vc10FrameTxEOFE : in std_logic; -- User frame data error + vc10FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc10LocBuffAFull : in std_logic; -- Remote buffer almost full + vc10LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, Lane 1, VC 1 + vc11FrameTxValid : in std_logic; -- User frame data is valid + vc11FrameTxReady : out std_logic; -- PGP is ready + vc11FrameTxSOF : in std_logic; -- User frame data start of frame + vc11FrameTxEOF : in std_logic; -- User frame data end of frame + vc11FrameTxEOFE : in std_logic; -- User frame data error + vc11FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc11LocBuffAFull : in std_logic; -- Remote buffer almost full + vc11LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, Lane 1, VC 2 + vc12FrameTxValid : in std_logic; -- User frame data is valid + vc12FrameTxReady : out std_logic; -- PGP is ready + vc12FrameTxSOF : in std_logic; -- User frame data start of frame + vc12FrameTxEOF : in std_logic; -- User frame data end of frame + vc12FrameTxEOFE : in std_logic; -- User frame data error + vc12FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc12LocBuffAFull : in std_logic; -- Remote buffer almost full + vc12LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, Lane 1, VC 3 + vc13FrameTxValid : in std_logic; -- User frame data is valid + vc13FrameTxReady : out std_logic; -- PGP is ready + vc13FrameTxSOF : in std_logic; -- User frame data start of frame + vc13FrameTxEOF : in std_logic; -- User frame data end of frame + vc13FrameTxEOFE : in std_logic; -- User frame data error + vc13FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc13LocBuffAFull : in std_logic; -- Remote buffer almost full + vc13LocBuffFull : in std_logic; -- Remote buffer full + + -- Common Frame Receive Interface For All Lane 1 VCs + vc1FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc1FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc1FrameRxEOFE : out std_logic; -- PGP frame data error + vc1FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + + -- Frame Receive Interface, Lane 1, VC 0 + vc10FrameRxValid : out std_logic; -- PGP frame data is valid + vc10RemBuffAFull : out std_logic; -- Remote buffer almost full + vc10RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, Lane 1, VC 1 + vc11FrameRxValid : out std_logic; -- PGP frame data is valid + vc11RemBuffAFull : out std_logic; -- Remote buffer almost full + vc11RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, Lane 1, VC 2 + vc12FrameRxValid : out std_logic; -- PGP frame data is valid + vc12RemBuffAFull : out std_logic; -- Remote buffer almost full + vc12RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, Lane 1, VC 3 + vc13FrameRxValid : out std_logic; -- PGP frame data is valid + vc13RemBuffAFull : out std_logic; -- Remote buffer almost full + vc13RemBuffFull : out std_logic; -- Remote buffer full + + -- GTP loopback control + gtpLoopback : in std_logic_vector(1 downto 0); -- GTP Serial Loopback Control + + -- GTP Signals + gtpClkIn : in std_logic; -- GTP Reference Clock In + gtpRefClkOut : out std_logic; -- GTP Reference Clock Output + gtpRxRecClk : out std_logic_vector(1 downto 0); -- GTP Rx Recovered Clock + gtpRxN : in std_logic_vector(1 downto 0); -- GTP Serial Receive Negative + gtpRxP : in std_logic_vector(1 downto 0); -- GTP Serial Receive Positive + gtpTxN : out std_logic_vector(1 downto 0); -- GTP Serial Transmit Negative + gtpTxP : out std_logic_vector(1 downto 0); -- GTP Serial Transmit Positive + + -- Debug + debug : out std_logic_vector(127 downto 0) + ); + +end Pgp2GtpDual; + + +-- Define architecture +architecture Pgp2GtpDual of Pgp2GtpDual is + + -- Local Signals + signal crc0TxIn : std_logic_vector(15 downto 0); + signal crc0TxInGtp : std_logic_vector(31 downto 0); + signal crc0TxInit : std_logic; + signal crc0TxRst : std_logic; + signal crc0TxValid : std_logic; + signal crc0TxWidth : std_logic_vector(2 downto 0); + signal crc0TxOut : std_logic_vector(31 downto 0); + signal crc0TxOutGtp : std_logic_vector(31 downto 0); + signal crc0RxIn : std_logic_vector(15 downto 0); + signal crc0RxInGtp : std_logic_vector(31 downto 0); + signal crc0RxInit : std_logic; + signal crc0RxRst : std_logic; + signal crc0RxValid : std_logic; + signal crc0RxWidth : std_logic_vector(2 downto 0); + signal crc0RxOut : std_logic_vector(31 downto 0); + signal crc0RxOutGtp : std_logic_vector(31 downto 0); + signal phy0RxPolarity : std_logic_vector(0 downto 0); + signal phy0RxData : std_logic_vector(15 downto 0); + signal phy0RxDataK : std_logic_vector(1 downto 0); + signal phy0TxData : std_logic_vector(15 downto 0); + signal phy0TxDataK : std_logic_vector(1 downto 0); + signal phy0RxDispErr : std_logic_vector(1 downto 0); + signal phy0RxDecErr : std_logic_vector(1 downto 0); + signal phy0RxReady : std_logic; + signal phy0RxInit : std_logic; + signal phy0TxReady : std_logic; + signal phy0RxReset : std_logic; + signal phy0RxElecIdleRst : std_logic; + signal phy0RxElecIdle : std_logic; + signal phy0RxCdrReset : std_logic; + signal phy0RstDone : std_logic; + signal phy0RxBuffStatus : std_logic_vector(2 downto 0); + signal phy0TxReset : std_logic; + signal phy0TxBuffStatus : std_logic_vector(1 downto 0); + signal phyLockDetect : std_logic; + signal int0TxRst : std_logic; + signal int0RxRst : std_logic; + signal pgp0RxLinkReady : std_logic; + signal pgp0TxLinkReady : std_logic; + signal int0RxRecClk : std_logic; + signal crc1TxIn : std_logic_vector(15 downto 0); + signal crc1TxInGtp : std_logic_vector(31 downto 0); + signal crc1TxInit : std_logic; + signal crc1TxRst : std_logic; + signal crc1TxValid : std_logic; + signal crc1TxWidth : std_logic_vector(2 downto 0); + signal crc1TxOut : std_logic_vector(31 downto 0); + signal crc1TxOutGtp : std_logic_vector(31 downto 0); + signal crc1RxIn : std_logic_vector(15 downto 0); + signal crc1RxInGtp : std_logic_vector(31 downto 0); + signal crc1RxInit : std_logic; + signal crc1RxRst : std_logic; + signal crc1RxValid : std_logic; + signal crc1RxWidth : std_logic_vector(2 downto 0); + signal crc1RxOut : std_logic_vector(31 downto 0); + signal crc1RxOutGtp : std_logic_vector(31 downto 0); + signal phy1RxPolarity : std_logic_vector(0 downto 0); + signal phy1RxData : std_logic_vector(15 downto 0); + signal phy1RxDataK : std_logic_vector(1 downto 0); + signal phy1TxData : std_logic_vector(15 downto 0); + signal phy1TxDataK : std_logic_vector(1 downto 0); + signal phy1RxDispErr : std_logic_vector(1 downto 0); + signal phy1RxDecErr : std_logic_vector(1 downto 0); + signal phy1RxReady : std_logic; + signal phy1RxInit : std_logic; + signal phy1TxReady : std_logic; + signal phy1RxReset : std_logic; + signal phy1RxElecIdleRst : std_logic; + signal phy1RxElecIdle : std_logic; + signal phy1RxCdrReset : std_logic; + signal phy1RstDone : std_logic; + signal phy1RxBuffStatus : std_logic_vector(2 downto 0); + signal phy1TxReset : std_logic; + signal phy1TxBuffStatus : std_logic_vector(1 downto 0); + signal int1TxRst : std_logic; + signal int1RxRst : std_logic; + signal pgp1RxLinkReady : std_logic; + signal pgp1TxLinkReady : std_logic; + signal int1RxRecClk : std_logic; + signal tmpRefClkOut : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + ------------------------------------------ + -- PGP Lane 0 + ------------------------------------------ + + -- PGP0 RX Block + U_Pgp2Rx0: Pgp2CorePackage.Pgp2Rx + generic map ( + RxLaneCnt => 1, + EnShortCells => EnShortCells + ) port map ( + pgpRxClk => pgpClk, + pgpRxReset => pgpReset, + pgpRxFlush => pgpFlush, + pgpRxLinkReady => pgp0RxLinkReady, + pgpRxCellError => pgp0RxCellError, + pgpRxLinkDown => pgp0RxLinkDown, + pgpRxLinkError => pgp0RxLinkError, + pgpRxOpCodeEn => pgp0RxOpCodeEn, + pgpRxOpCode => pgp0RxOpCode, + pgpRemLinkReady => pgp0RemLinkReady, + pgpRemData => pgp0RemData, + vcFrameRxSOF => vc0FrameRxSOF, + vcFrameRxEOF => vc0FrameRxEOF, + vcFrameRxEOFE => vc0FrameRxEOFE, + vcFrameRxData => vc0FrameRxData, + vc0FrameRxValid => vc00FrameRxValid, + vc0RemBuffAFull => vc00RemBuffAFull, + vc0RemBuffFull => vc00RemBuffFull, + vc1FrameRxValid => vc01FrameRxValid, + vc1RemBuffAFull => vc01RemBuffAFull, + vc1RemBuffFull => vc01RemBuffFull, + vc2FrameRxValid => vc02FrameRxValid, + vc2RemBuffAFull => vc02RemBuffAFull, + vc2RemBuffFull => vc02RemBuffFull, + vc3FrameRxValid => vc03FrameRxValid, + vc3RemBuffAFull => vc03RemBuffAFull, + vc3RemBuffFull => vc03RemBuffFull, + phyRxPolarity => phy0RxPolarity, + phyRxData => phy0RxData, + phyRxDataK => phy0RxDataK, + phyRxDispErr => phy0RxDispErr, + phyRxDecErr => phy0RxDecErr, + phyRxReady => phy0RxReady, + phyRxInit => phy0RxInit, + crcRxIn => crc0RxIn, + crcRxWidth => open, + crcRxInit => crc0RxInit, + crcRxValid => crc0RxValid, + crcRxOut => crc0RxOut, + debug => debug(63 downto 0) + ); + + + -- PGP TX Block + U_Pgp2Tx0: Pgp2CorePackage.Pgp2Tx + generic map ( + TxLaneCnt => 1, + VcInterleave => VcInterleave + ) port map ( + pgpTxClk => pgpClk, + pgpTxReset => pgpReset, + pgpTxFlush => pgpFlush, + pgpTxLinkReady => pgp0TxLinkReady, + pgpTxOpCodeEn => pgp0TxOpCodeEn, + pgpTxOpCode => pgp0TxOpCode, + pgpLocLinkReady => pgp0RxLinkReady, + pgpLocData => pgp0LocData, + vc0FrameTxValid => vc00FrameTxValid, + vc0FrameTxReady => vc00FrameTxReady, + vc0FrameTxSOF => vc00FrameTxSOF, + vc0FrameTxEOF => vc00FrameTxEOF, + vc0FrameTxEOFE => vc00FrameTxEOFE, + vc0FrameTxData => vc00FrameTxData, + vc0LocBuffAFull => vc00LocBuffAFull, + vc0LocBuffFull => vc00LocBuffFull, + vc1FrameTxValid => vc01FrameTxValid, + vc1FrameTxReady => vc01FrameTxReady, + vc1FrameTxSOF => vc01FrameTxSOF, + vc1FrameTxEOF => vc01FrameTxEOF, + vc1FrameTxEOFE => vc01FrameTxEOFE, + vc1FrameTxData => vc01FrameTxData, + vc1LocBuffAFull => vc01LocBuffAFull, + vc1LocBuffFull => vc01LocBuffFull, + vc2FrameTxValid => vc02FrameTxValid, + vc2FrameTxReady => vc02FrameTxReady, + vc2FrameTxSOF => vc02FrameTxSOF, + vc2FrameTxEOF => vc02FrameTxEOF, + vc2FrameTxEOFE => vc02FrameTxEOFE, + vc2FrameTxData => vc02FrameTxData, + vc2LocBuffAFull => vc02LocBuffAFull, + vc2LocBuffFull => vc02LocBuffFull, + vc3FrameTxValid => vc03FrameTxValid, + vc3FrameTxReady => vc03FrameTxReady, + vc3FrameTxSOF => vc03FrameTxSOF, + vc3FrameTxEOF => vc03FrameTxEOF, + vc3FrameTxEOFE => vc03FrameTxEOFE, + vc3FrameTxData => vc03FrameTxData, + vc3LocBuffAFull => vc03LocBuffAFull, + vc3LocBuffFull => vc03LocBuffFull, + phyTxData => phy0TxData, + phyTxDataK => phy0TxDataK, + phyTxReady => phy0TxReady, + crcTxIn => crc0TxIn, + crcTxInit => crc0TxInit, + crcTxValid => crc0TxValid, + crcTxOut => crc0TxOut, + debug => open + ); + + + -- Adapt CRC data width flag + crc0TxWidth <= "001"; + crc0RxWidth <= "001"; + crc0RxRst <= int0RxRst or crc0RxInit; + crc0TxRst <= int0TxRst or crc0TxInit; + + -- Pass CRC data in on proper bits + crc0TxInGtp(31 downto 24) <= crc0TxIn(7 downto 0); + crc0TxInGtp(23 downto 16) <= crc0TxIn(15 downto 8); + crc0TxInGtp(15 downto 0) <= (others=>'0'); + crc0RxInGtp(31 downto 24) <= crc0RxIn(7 downto 0); + crc0RxInGtp(23 downto 16) <= crc0RxIn(15 downto 8); + crc0RxInGtp(15 downto 0) <= (others=>'0'); + + -- Pll Resets + int0TxRst <= pll0TxRst or pgpReset; + int0RxRst <= pll0RxRst or pgpReset; + + -- PLL Lock + pll0RxReady <= phy0RxReady; + pll0TxReady <= phy0TxReady; + + -- Link Ready + pgp0LocLinkReady <= pgp0RxLinkReady and pgp0TxLinkReady; + + -- Invert Output CRC + crc0RxOut <= not crc0RxOutGtp; + crc0TxOut <= not crc0TxOutGtp; + + + -- TX CRC BLock + Tx_CRC0: CRC32 + generic map( + CRC_INIT => x"FFFFFFFF" + ) port map( + CRCOUT => crc0TxOutGtp, + CRCCLK => pgpClk, + CRCDATAVALID => crc0TxValid, + CRCDATAWIDTH => crc0TxWidth, + CRCIN => crc0TxInGtp, + CRCRESET => crc0TxRst + ); + + + -- RX CRC BLock + Rx_CRC0: CRC32 + generic map( + CRC_INIT => x"FFFFFFFF" + ) port map( + CRCOUT => crc0RxOutGtp, + CRCCLK => pgpClk, + CRCDATAVALID => crc0RxValid, + CRCDATAWIDTH => crc0RxWidth, + CRCIN => crc0RxInGtp, + CRCRESET => crc0RxRst + ); + + + -- RX Reset Control + U_Pgp2GtpRxRst0: Pgp2GtpPackage.Pgp2GtpRxRst + port map ( + gtpRxClk => pgpClk, + gtpRxRst => int0RxRst, + gtpRxReady => phy0RxReady, + gtpRxInit => phy0RxInit, + gtpLockDetect => phyLockDetect, + gtpRxElecIdle => phy0RxElecIdle, + gtpRxBuffStatus => phy0RxBuffStatus, + gtpRstDone => phy0RstDone, + gtpRxElecIdleRst => phy0RxElecIdleRst, + gtpRxReset => phy0RxReset, + gtpRxCdrReset => phy0RxCdrReset + ); + + + -- TX Reset Control + U_Pgp2GtpTxRst0: Pgp2GtpPackage.Pgp2GtpTxRst + port map ( + gtpTxClk => pgpClk, + gtpTxRst => int0TxRst, + gtpTxReady => phy0TxReady, + gtpLockDetect => phyLockDetect, + gtpTxBuffStatus => phy0TxBuffStatus, + gtpRstDone => phy0RstDone, + gtpTxReset => phy0TxReset + ); + + + ------------------------------------------ + -- PGP Lane 1 + ------------------------------------------ + + -- PGP1 RX Block + U_Pgp2Rx1: Pgp2CorePackage.Pgp2Rx + generic map ( + RxLaneCnt => 1, + EnShortCells => EnShortCells + ) port map ( + pgpRxClk => pgpClk, + pgpRxReset => pgpReset, + pgpRxFlush => pgpFlush, + pgpRxLinkReady => pgp1RxLinkReady, + pgpRxCellError => pgp1RxCellError, + pgpRxLinkDown => pgp1RxLinkDown, + pgpRxLinkError => pgp1RxLinkError, + pgpRxOpCodeEn => pgp1RxOpCodeEn, + pgpRxOpCode => pgp1RxOpCode, + pgpRemLinkReady => pgp1RemLinkReady, + pgpRemData => pgp1RemData, + vcFrameRxSOF => vc1FrameRxSOF, + vcFrameRxEOF => vc1FrameRxEOF, + vcFrameRxEOFE => vc1FrameRxEOFE, + vcFrameRxData => vc1FrameRxData, + vc0FrameRxValid => vc10FrameRxValid, + vc0RemBuffAFull => vc10RemBuffAFull, + vc0RemBuffFull => vc10RemBuffFull, + vc1FrameRxValid => vc11FrameRxValid, + vc1RemBuffAFull => vc11RemBuffAFull, + vc1RemBuffFull => vc11RemBuffFull, + vc2FrameRxValid => vc12FrameRxValid, + vc2RemBuffAFull => vc12RemBuffAFull, + vc2RemBuffFull => vc12RemBuffFull, + vc3FrameRxValid => vc13FrameRxValid, + vc3RemBuffAFull => vc13RemBuffAFull, + vc3RemBuffFull => vc13RemBuffFull, + phyRxPolarity => phy1RxPolarity, + phyRxData => phy1RxData, + phyRxDataK => phy1RxDataK, + phyRxDispErr => phy1RxDispErr, + phyRxDecErr => phy1RxDecErr, + phyRxReady => phy1RxReady, + phyRxInit => phy1RxInit, + crcRxIn => crc1RxIn, + crcRxWidth => open, + crcRxInit => crc1RxInit, + crcRxValid => crc1RxValid, + crcRxOut => crc1RxOut, + debug => debug(127 downto 64) + ); + + + -- PGP TX Block + U_Pgp2Tx1: Pgp2CorePackage.Pgp2Tx + generic map ( + TxLaneCnt => 1, + VcInterleave => VcInterleave + ) port map ( + pgpTxClk => pgpClk, + pgpTxReset => pgpReset, + pgpTxFlush => pgpFlush, + pgpTxLinkReady => pgp1TxLinkReady, + pgpTxOpCodeEn => pgp1TxOpCodeEn, + pgpTxOpCode => pgp1TxOpCode, + pgpLocLinkReady => pgp1RxLinkReady, + pgpLocData => pgp1LocData, + vc0FrameTxValid => vc10FrameTxValid, + vc0FrameTxReady => vc10FrameTxReady, + vc0FrameTxSOF => vc10FrameTxSOF, + vc0FrameTxEOF => vc10FrameTxEOF, + vc0FrameTxEOFE => vc10FrameTxEOFE, + vc0FrameTxData => vc10FrameTxData, + vc0LocBuffAFull => vc10LocBuffAFull, + vc0LocBuffFull => vc10LocBuffFull, + vc1FrameTxValid => vc11FrameTxValid, + vc1FrameTxReady => vc11FrameTxReady, + vc1FrameTxSOF => vc11FrameTxSOF, + vc1FrameTxEOF => vc11FrameTxEOF, + vc1FrameTxEOFE => vc11FrameTxEOFE, + vc1FrameTxData => vc11FrameTxData, + vc1LocBuffAFull => vc11LocBuffAFull, + vc1LocBuffFull => vc11LocBuffFull, + vc2FrameTxValid => vc12FrameTxValid, + vc2FrameTxReady => vc12FrameTxReady, + vc2FrameTxSOF => vc12FrameTxSOF, + vc2FrameTxEOF => vc12FrameTxEOF, + vc2FrameTxEOFE => vc12FrameTxEOFE, + vc2FrameTxData => vc12FrameTxData, + vc2LocBuffAFull => vc12LocBuffAFull, + vc2LocBuffFull => vc12LocBuffFull, + vc3FrameTxValid => vc13FrameTxValid, + vc3FrameTxReady => vc13FrameTxReady, + vc3FrameTxSOF => vc13FrameTxSOF, + vc3FrameTxEOF => vc13FrameTxEOF, + vc3FrameTxEOFE => vc13FrameTxEOFE, + vc3FrameTxData => vc13FrameTxData, + vc3LocBuffAFull => vc13LocBuffAFull, + vc3LocBuffFull => vc13LocBuffFull, + phyTxData => phy1TxData, + phyTxDataK => phy1TxDataK, + phyTxReady => phy1TxReady, + crcTxIn => crc1TxIn, + crcTxInit => crc1TxInit, + crcTxValid => crc1TxValid, + crcTxOut => crc1TxOut, + debug => open + ); + + + -- Adapt CRC data width flag + crc1TxWidth <= "001"; + crc1RxWidth <= "001"; + crc1RxRst <= int1RxRst or crc1RxInit; + crc1TxRst <= int1TxRst or crc1TxInit; + + -- Pass CRC data in on proper bits + crc1TxInGtp(31 downto 24) <= crc1TxIn(7 downto 0); + crc1TxInGtp(23 downto 16) <= crc1TxIn(15 downto 8); + crc1TxInGtp(15 downto 0) <= (others=>'0'); + crc1RxInGtp(31 downto 24) <= crc1RxIn(7 downto 0); + crc1RxInGtp(23 downto 16) <= crc1RxIn(15 downto 8); + crc1RxInGtp(15 downto 0) <= (others=>'0'); + + -- Pll Resets + int1TxRst <= pll1TxRst or pgpReset; + int1RxRst <= pll1RxRst or pgpReset; + + -- PLL Lock + pll1RxReady <= phy1RxReady; + pll1TxReady <= phy1TxReady; + + -- Link Ready + pgp1LocLinkReady <= pgp1RxLinkReady and pgp1TxLinkReady; + + -- Invert Output CRC + crc1RxOut <= not crc1RxOutGtp; + crc1TxOut <= not crc1TxOutGtp; + + + -- TX CRC BLock + Tx_CRC1: CRC32 + generic map( + CRC_INIT => x"FFFFFFFF" + ) port map( + CRCOUT => crc1TxOutGtp, + CRCCLK => pgpClk, + CRCDATAVALID => crc1TxValid, + CRCDATAWIDTH => crc1TxWidth, + CRCIN => crc1TxInGtp, + CRCRESET => crc1TxRst + ); + + + -- RX CRC BLock + Rx_CRC1: CRC32 + generic map( + CRC_INIT => x"FFFFFFFF" + ) port map( + CRCOUT => crc1RxOutGtp, + CRCCLK => pgpClk, + CRCDATAVALID => crc1RxValid, + CRCDATAWIDTH => crc1RxWidth, + CRCIN => crc1RxInGtp, + CRCRESET => crc1RxRst + ); + + + -- RX Reset Control + U_Pgp2GtpRxRst1: Pgp2GtpPackage.Pgp2GtpRxRst + port map ( + gtpRxClk => pgpClk, + gtpRxRst => int1RxRst, + gtpRxReady => phy1RxReady, + gtpRxInit => phy1RxInit, + gtpLockDetect => phyLockDetect, + gtpRxElecIdle => phy1RxElecIdle, + gtpRxBuffStatus => phy1RxBuffStatus, + gtpRstDone => phy1RstDone, + gtpRxElecIdleRst => phy1RxElecIdleRst, + gtpRxReset => phy1RxReset, + gtpRxCdrReset => phy1RxCdrReset + ); + + + -- TX Reset Control + U_Pgp2GtpTxRst1: Pgp2GtpPackage.Pgp2GtpTxRst + port map ( + gtpTxClk => pgpClk, + gtpTxRst => int1TxRst, + gtpTxReady => phy1TxReady, + gtpLockDetect => phyLockDetect, + gtpTxBuffStatus => phy1TxBuffStatus, + gtpRstDone => phy1RstDone, + gtpTxReset => phy1TxReset + ); + + + ------------------------------------------ + -- Shared GTP + ------------------------------------------ + + ----------------------------- GTP_DUAL Instance -------------------------- + U_GtpDual:GTP_DUAL + generic map ( + + --_______________________ Simulation-Only Attributes ___________________ + + SIM_GTPRESET_SPEEDUP => 1, + SIM_PLL_PERDIV2 => x"140", + + --___________________________ Shared Attributes ________________________ + + -------------------------- Tile and PLL Attributes --------------------- + + CLK25_DIVIDER => 10, + CLKINDC_B => TRUE, + OOB_CLK_DIVIDER => 6, + OVERSAMPLE_MODE => FALSE, + PLL_DIVSEL_FB => 2, + PLL_DIVSEL_REF => 1, + PLL_TXDIVSEL_COMM_OUT => 1, + TX_SYNC_FILTERB => 1, + + --____________________ Transmit Interface Attributes ___________________ + + ------------------- TX Buffering and Phase Alignment ------------------- + + TX_BUFFER_USE_0 => TRUE, + TX_XCLK_SEL_0 => "TXOUT", + TXRX_INVERT_0 => "00000", + + TX_BUFFER_USE_1 => TRUE, + TX_XCLK_SEL_1 => "TXOUT", + TXRX_INVERT_1 => "00000", + + --------------------- TX Serial Line Rate settings --------------------- + + PLL_TXDIVSEL_OUT_0 => 1, + + PLL_TXDIVSEL_OUT_1 => 1, + + --------------------- TX Driver and OOB signalling -------------------- + + TX_DIFF_BOOST_0 => TRUE, + + TX_DIFF_BOOST_1 => TRUE, + + ------------------ TX Pipe Control for PCI Express/SATA --------------- + + COM_BURST_VAL_0 => "1111", + + COM_BURST_VAL_1 => "1111", + --_______________________ Receive Interface Attributes ________________ + + ------------ RX Driver,OOB signalling,Coupling and Eq,CDR ------------- + + AC_CAP_DIS_0 => TRUE, + OOBDETECT_THRESHOLD_0 => "001", + PMA_CDR_SCAN_0 => x"6c07640", + PMA_RX_CFG_0 => x"09f0089", + RCV_TERM_GND_0 => FALSE, + RCV_TERM_MID_0 => FALSE, + RCV_TERM_VTTRX_0 => FALSE, + TERMINATION_IMP_0 => 50, + + AC_CAP_DIS_1 => TRUE, + OOBDETECT_THRESHOLD_1 => "001", + PMA_CDR_SCAN_1 => x"6c07640", + PMA_RX_CFG_1 => x"09f0089", + RCV_TERM_GND_1 => FALSE, + RCV_TERM_MID_1 => FALSE, + RCV_TERM_VTTRX_1 => FALSE, + TERMINATION_IMP_1 => 50, + TERMINATION_CTRL => "10100", + TERMINATION_OVRD => FALSE, + + --------------------- RX Serial Line Rate Attributes ------------------ + + PLL_RXDIVSEL_OUT_0 => 1, + PLL_SATA_0 => TRUE, + + PLL_RXDIVSEL_OUT_1 => 1, + PLL_SATA_1 => TRUE, + + ----------------------- PRBS Detection Attributes --------------------- + + PRBS_ERR_THRESHOLD_0 => x"00000001", + + PRBS_ERR_THRESHOLD_1 => x"00000001", + + ---------------- Comma Detection and Alignment Attributes ------------- + + ALIGN_COMMA_WORD_0 => 2, + COMMA_10B_ENABLE_0 => "1111111111", + COMMA_DOUBLE_0 => FALSE, + DEC_MCOMMA_DETECT_0 => TRUE, + DEC_PCOMMA_DETECT_0 => TRUE, + DEC_VALID_COMMA_ONLY_0 => FALSE, + MCOMMA_10B_VALUE_0 => "1010000011", + MCOMMA_DETECT_0 => TRUE, + PCOMMA_10B_VALUE_0 => "0101111100", + PCOMMA_DETECT_0 => TRUE, + RX_SLIDE_MODE_0 => "PCS", + + ALIGN_COMMA_WORD_1 => 2, + COMMA_10B_ENABLE_1 => "1111111111", + COMMA_DOUBLE_1 => FALSE, + DEC_MCOMMA_DETECT_1 => TRUE, + DEC_PCOMMA_DETECT_1 => TRUE, + DEC_VALID_COMMA_ONLY_1 => FALSE, + MCOMMA_10B_VALUE_1 => "1010000011", + MCOMMA_DETECT_1 => TRUE, + PCOMMA_10B_VALUE_1 => "0101111100", + PCOMMA_DETECT_1 => TRUE, + RX_SLIDE_MODE_1 => "PCS", + + ------------------ RX Loss-of-sync State Machine Attributes ----------- + + RX_LOSS_OF_SYNC_FSM_0 => FALSE, + RX_LOS_INVALID_INCR_0 => 8, + RX_LOS_THRESHOLD_0 => 128, + + RX_LOSS_OF_SYNC_FSM_1 => FALSE, + RX_LOS_INVALID_INCR_1 => 8, + RX_LOS_THRESHOLD_1 => 128, + + -------------- RX Elastic Buffer and Phase alignment Attributes ------- + + RX_BUFFER_USE_0 => TRUE, + RX_XCLK_SEL_0 => "RXREC", + + RX_BUFFER_USE_1 => TRUE, + RX_XCLK_SEL_1 => "RXREC", + + ------------------------ Clock Correction Attributes ------------------ + + CLK_CORRECT_USE_0 => TRUE, + CLK_COR_ADJ_LEN_0 => 4, + CLK_COR_DET_LEN_0 => 4, + CLK_COR_INSERT_IDLE_FLAG_0 => FALSE, + CLK_COR_KEEP_IDLE_0 => FALSE, + CLK_COR_MAX_LAT_0 => 48, + CLK_COR_MIN_LAT_0 => 36, + CLK_COR_PRECEDENCE_0 => TRUE, + CLK_COR_REPEAT_WAIT_0 => 0, + CLK_COR_SEQ_1_1_0 => "0110111100", + CLK_COR_SEQ_1_2_0 => "0100011100", + CLK_COR_SEQ_1_3_0 => "0100011100", + CLK_COR_SEQ_1_4_0 => "0100011100", + CLK_COR_SEQ_1_ENABLE_0 => "1111", + CLK_COR_SEQ_2_1_0 => "0000000000", + CLK_COR_SEQ_2_2_0 => "0000000000", + CLK_COR_SEQ_2_3_0 => "0000000000", + CLK_COR_SEQ_2_4_0 => "0000000000", + CLK_COR_SEQ_2_ENABLE_0 => "0000", + CLK_COR_SEQ_2_USE_0 => FALSE, + RX_DECODE_SEQ_MATCH_0 => TRUE, + + CLK_CORRECT_USE_1 => TRUE, + CLK_COR_ADJ_LEN_1 => 4, + CLK_COR_DET_LEN_1 => 4, + CLK_COR_INSERT_IDLE_FLAG_1 => FALSE, + CLK_COR_KEEP_IDLE_1 => FALSE, + CLK_COR_MAX_LAT_1 => 48, + CLK_COR_MIN_LAT_1 => 36, + CLK_COR_PRECEDENCE_1 => TRUE, + CLK_COR_REPEAT_WAIT_1 => 0, + CLK_COR_SEQ_1_1_1 => "0110111100", + CLK_COR_SEQ_1_2_1 => "0100011100", + CLK_COR_SEQ_1_3_1 => "0100011100", + CLK_COR_SEQ_1_4_1 => "0100011100", + CLK_COR_SEQ_1_ENABLE_1 => "1111", + CLK_COR_SEQ_2_1_1 => "0000000000", + CLK_COR_SEQ_2_2_1 => "0000000000", + CLK_COR_SEQ_2_3_1 => "0000000000", + CLK_COR_SEQ_2_4_1 => "0000000000", + CLK_COR_SEQ_2_ENABLE_1 => "0000", + CLK_COR_SEQ_2_USE_1 => FALSE, + RX_DECODE_SEQ_MATCH_1 => TRUE, + + ------------------------ Channel Bonding Attributes ------------------- + + CHAN_BOND_1_MAX_SKEW_0 => 1, + CHAN_BOND_2_MAX_SKEW_0 => 1, + CHAN_BOND_LEVEL_0 => 0, + CHAN_BOND_MODE_0 => "OFF", + CHAN_BOND_SEQ_1_1_0 => "0000000000", + CHAN_BOND_SEQ_1_2_0 => "0000000000", + CHAN_BOND_SEQ_1_3_0 => "0000000000", + CHAN_BOND_SEQ_1_4_0 => "0000000000", + CHAN_BOND_SEQ_1_ENABLE_0 => "0000", + CHAN_BOND_SEQ_2_1_0 => "0000000000", + CHAN_BOND_SEQ_2_2_0 => "0000000000", + CHAN_BOND_SEQ_2_3_0 => "0000000000", + CHAN_BOND_SEQ_2_4_0 => "0000000000", + CHAN_BOND_SEQ_2_ENABLE_0 => "0000", + CHAN_BOND_SEQ_2_USE_0 => FALSE, + CHAN_BOND_SEQ_LEN_0 => 1, + PCI_EXPRESS_MODE_0 => FALSE, + + CHAN_BOND_1_MAX_SKEW_1 => 1, + CHAN_BOND_2_MAX_SKEW_1 => 1, + CHAN_BOND_LEVEL_1 => 0, + CHAN_BOND_MODE_1 => "OFF", + CHAN_BOND_SEQ_1_1_1 => "0000000000", + CHAN_BOND_SEQ_1_2_1 => "0000000000", + CHAN_BOND_SEQ_1_3_1 => "0000000000", + CHAN_BOND_SEQ_1_4_1 => "0000000000", + CHAN_BOND_SEQ_1_ENABLE_1 => "0000", + CHAN_BOND_SEQ_2_1_1 => "0000000000", + CHAN_BOND_SEQ_2_2_1 => "0000000000", + CHAN_BOND_SEQ_2_3_1 => "0000000000", + CHAN_BOND_SEQ_2_4_1 => "0000000000", + CHAN_BOND_SEQ_2_ENABLE_1 => "0000", + CHAN_BOND_SEQ_2_USE_1 => FALSE, + CHAN_BOND_SEQ_LEN_1 => 1, + PCI_EXPRESS_MODE_1 => FALSE, + + ------------------ RX Attributes for PCI Express/SATA --------------- + + RX_STATUS_FMT_0 => "PCIE", + SATA_BURST_VAL_0 => "100", + SATA_IDLE_VAL_0 => "100", + SATA_MAX_BURST_0 => 7, + SATA_MAX_INIT_0 => 22, + SATA_MAX_WAKE_0 => 7, + SATA_MIN_BURST_0 => 4, + SATA_MIN_INIT_0 => 12, + SATA_MIN_WAKE_0 => 4, + TRANS_TIME_FROM_P2_0 => x"0060", + TRANS_TIME_NON_P2_0 => x"0025", + TRANS_TIME_TO_P2_0 => x"0100", + + RX_STATUS_FMT_1 => "PCIE", + SATA_BURST_VAL_1 => "100", + SATA_IDLE_VAL_1 => "100", + SATA_MAX_BURST_1 => 7, + SATA_MAX_INIT_1 => 22, + SATA_MAX_WAKE_1 => 7, + SATA_MIN_BURST_1 => 4, + SATA_MIN_INIT_1 => 12, + SATA_MIN_WAKE_1 => 4, + TRANS_TIME_FROM_P2_1 => x"0060", + TRANS_TIME_NON_P2_1 => x"0025", + TRANS_TIME_TO_P2_1 => x"0100" + + ) port map ( + + ------------------------ Loopback and Powerdown Ports ---------------------- + LOOPBACK0(0) => '0', + LOOPBACK0(1) => gtpLoopback(0), + LOOPBACK0(2) => '0', + LOOPBACK1(0) => '0', + LOOPBACK1(1) => gtpLoopback(1), + LOOPBACK1(2) => '0', + RXPOWERDOWN0 => (others=>'0'), + RXPOWERDOWN1 => (others=>'0'), + TXPOWERDOWN0 => (others=>'0'), + TXPOWERDOWN1 => (others=>'0'), + ----------------------- Receive Ports - 8b10b Decoder ---------------------- + RXCHARISCOMMA0 => open, + RXCHARISCOMMA1 => open, + RXCHARISK0 => phy0RxDataK, + RXCHARISK1 => phy1RxDataK, + RXDEC8B10BUSE0 => '1', + RXDEC8B10BUSE1 => '1', + RXDISPERR0 => phy0RxDispErr, + RXDISPERR1 => phy1RxDispErr, + RXNOTINTABLE0 => phy0RxDecErr, + RXNOTINTABLE1 => phy1RxDecErr, + RXRUNDISP0 => open, + RXRUNDISP1 => open, + ------------------- Receive Ports - Channel Bonding Ports ------------------ + RXCHANBONDSEQ0 => open, + RXCHANBONDSEQ1 => open, + RXCHBONDI0 => (others=>'0'), + RXCHBONDI1 => (others=>'0'), + RXCHBONDO0 => open, + RXCHBONDO1 => open, + RXENCHANSYNC0 => '0', + RXENCHANSYNC1 => '0', + ------------------- Receive Ports - Clock Correction Ports ----------------- + RXCLKCORCNT0 => open, + RXCLKCORCNT1 => open, + --------------- Receive Ports - Comma Detection and Alignment -------------- + RXBYTEISALIGNED0 => open, + RXBYTEISALIGNED1 => open, + RXBYTEREALIGN0 => open, + RXBYTEREALIGN1 => open, + RXCOMMADET0 => open, + RXCOMMADET1 => open, + RXCOMMADETUSE0 => '1', + RXCOMMADETUSE1 => '1', + RXENMCOMMAALIGN0 => '1', + RXENMCOMMAALIGN1 => '1', + RXENPCOMMAALIGN0 => '1', + RXENPCOMMAALIGN1 => '1', + RXSLIDE0 => '0', + RXSLIDE1 => '0', + ----------------------- Receive Ports - PRBS Detection --------------------- + PRBSCNTRESET0 => '0', + PRBSCNTRESET1 => '0', + RXENPRBSTST0 => (others=>'0'), + RXENPRBSTST1 => (others=>'0'), + RXPRBSERR0 => open, + RXPRBSERR1 => open, + ------------------- Receive Ports - RX Data Path interface ----------------- + RXDATA0 => phy0RxData, + RXDATA1 => phy1RxData, + RXDATAWIDTH0 => '1', + RXDATAWIDTH1 => '1', + RXRECCLK0 => int0RxRecClk, + RXRECCLK1 => int1RxRecClk, + RXRESET0 => phy0RxReset, + RXRESET1 => phy1RxReset, + RXUSRCLK0 => pgpClk2x, + RXUSRCLK1 => pgpClk2x, + RXUSRCLK20 => pgpClk, + RXUSRCLK21 => pgpClk, + ------- Receive Ports - RX Driver,OOB signalling,Coupling and Eq.,CDR ------ + RXCDRRESET0 => phy0RxCdrReset, + RXCDRRESET1 => phy1RxCdrReset, + RXELECIDLE0 => phy0RxElecIdle, + RXELECIDLE1 => phy1RxElecIdle, + RXELECIDLERESET0 => phy0RxElecIdleRst, + RXELECIDLERESET1 => phy1RxElecIdleRst, + RXENEQB0 => '0', + RXENEQB1 => '0', + RXEQMIX0 => (others=>'0'), + RXEQMIX1 => (others=>'0'), + RXEQPOLE0 => (others=>'0'), + RXEQPOLE1 => (others=>'0'), + RXN0 => gtpRxN(0), + RXN1 => gtpRxN(1), + RXP0 => gtpRxP(0), + RXP1 => gtpRxP(1), + -------- Receive Ports - RX Elastic Buffer and Phase Alignment Ports ------- + RXBUFRESET0 => '0', + RXBUFRESET1 => '0', + RXBUFSTATUS0 => phy0RxBuffStatus, + RXBUFSTATUS1 => phy1RxBuffStatus, + RXCHANISALIGNED0 => open, + RXCHANISALIGNED1 => open, + RXCHANREALIGN0 => open, + RXCHANREALIGN1 => open, + RXPMASETPHASE0 => '0', + RXPMASETPHASE1 => '0', + RXSTATUS0 => open, + RXSTATUS1 => open, + --------------- Receive Ports - RX Loss-of-sync State Machine -------------- + RXLOSSOFSYNC0 => open, + RXLOSSOFSYNC1 => open, + ---------------------- Receive Ports - RX Oversampling --------------------- + RXENSAMPLEALIGN0 => '0', + RXENSAMPLEALIGN1 => '0', + RXOVERSAMPLEERR0 => open, + RXOVERSAMPLEERR1 => open, + -------------- Receive Ports - RX Pipe Control for PCI Express ------------- + PHYSTATUS0 => open, + PHYSTATUS1 => open, + RXVALID0 => open, + RXVALID1 => open, + ----------------- Receive Ports - RX Polarity Control Ports ---------------- + RXPOLARITY0 => phy0RxPolarity(0), + RXPOLARITY1 => phy1RxPolarity(0), + ------------- Shared Ports - Dynamic Reconfiguration Port (DRP) ------------ + DADDR => (others=>'0'), + DCLK => '0', + DEN => '0', + DI => (others=>'0'), + DO => open, + DRDY => open, + DWE => '0', + --------------------- Shared Ports - Tile and PLL Ports -------------------- + CLKIN => gtpClkIn, + GTPRESET => pgpReset, + GTPTEST => (others=>'0'), + INTDATAWIDTH => '1', + PLLLKDET => phyLockDetect, + PLLLKDETEN => '1', + PLLPOWERDOWN => '0', + REFCLKOUT => tmpRefClkOut, + REFCLKPWRDNB => '1', + RESETDONE0 => phy0RstDone, + RESETDONE1 => phy1RstDone, + RXENELECIDLERESETB => '1', + TXENPMAPHASEALIGN => '0', + TXPMASETPHASE => '0', + ---------------- Transmit Ports - 8b10b Encoder Control Ports -------------- + TXBYPASS8B10B0 => (others=>'0'), + TXBYPASS8B10B1 => (others=>'0'), + TXCHARDISPMODE0 => (others=>'0'), + TXCHARDISPMODE1 => (others=>'0'), + TXCHARDISPVAL0 => (others=>'0'), + TXCHARDISPVAL1 => (others=>'0'), + TXCHARISK0 => phy0TxDataK, + TXCHARISK1 => phy1TxDataK, + TXENC8B10BUSE0 => '1', + TXENC8B10BUSE1 => '1', + TXKERR0 => open, + TXKERR1 => open, + TXRUNDISP0 => open, + TXRUNDISP1 => open, + ------------- Transmit Ports - TX Buffering and Phase Alignment ------------ + TXBUFSTATUS0 => phy0TxBuffStatus, + TXBUFSTATUS1 => phy1TxBuffStatus, + ------------------ Transmit Ports - TX Data Path interface ----------------- + TXDATA0 => phy0TxData, + TXDATA1 => phy1TxData, + TXDATAWIDTH0 => '1', + TXDATAWIDTH1 => '1', + TXOUTCLK0 => open, + TXOUTCLK1 => open, + TXRESET0 => phy0TxReset, + TXRESET1 => phy1TxReset, + TXUSRCLK0 => pgpClk2x, + TXUSRCLK1 => pgpClk2x, + TXUSRCLK20 => pgpClk, + TXUSRCLK21 => pgpClk, + --------------- Transmit Ports - TX Driver and OOB signalling -------------- + TXBUFDIFFCTRL0 => "100", -- 800mV + TXBUFDIFFCTRL1 => "100", + TXDIFFCTRL0 => "100", + TXDIFFCTRL1 => "100", + TXINHIBIT0 => '0', + TXINHIBIT1 => '0', + TXN0 => gtpTxN(0), + TXN1 => gtpTxN(1), + TXP0 => gtpTxP(0), + TXP1 => gtpTxP(1), + TXPREEMPHASIS0 => "011", -- 4.5% + TXPREEMPHASIS1 => "011", + --------------------- Transmit Ports - TX PRBS Generator ------------------- + TXENPRBSTST0 => (others=>'0'), + TXENPRBSTST1 => (others=>'0'), + -------------------- Transmit Ports - TX Polarity Control ------------------ + TXPOLARITY0 => '0', + TXPOLARITY1 => '0', + ----------------- Transmit Ports - TX Ports for PCI Express ---------------- + TXDETECTRX0 => '0', + TXDETECTRX1 => '0', + TXELECIDLE0 => '0', + TXELECIDLE1 => '0', + --------------------- Transmit Ports - TX Ports for SATA ------------------- + TXCOMSTART0 => '0', + TXCOMSTART1 => '0', + TXCOMTYPE0 => '0', + TXCOMTYPE1 => '0' + ); + + -- Global Buffer For Ref Clock Output + U_RefClkBuff: BUFG port map ( + O => gtpRefClkOut, + I => tmpRefClkOut + ); + gtpRxRecClk(0) <= int0RxRecClk; + gtpRxRecClk(1) <= int1RxRecClk; + +end Pgp2GtpDual; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2GtpPackage.vhd b/rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2GtpPackage.vhd new file mode 100755 index 00000000..1e00da7d --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2GtpPackage.vhd @@ -0,0 +1,399 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, GTP Package +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2GtpPackage.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 11/23/2009 +------------------------------------------------------------------------------- +-- Description: +-- GTP Components package. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 11/23/2009: created. +-- 01/13/2010: Added received init line to help linking. +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; + +package Pgp2GtpPackage is + + -- 16-bit wrapper + component Pgp2Gtp16 + generic ( + EnShortCells : integer := 1; -- Enable short non-EOF cells + VcInterleave : integer := 1 -- Interleave Frames + ); + port ( + pgpClk : in std_logic; -- 156.25Mhz master clock + pgpClk2x : in std_logic; -- 2x master clock + pgpReset : in std_logic; -- Synchronous reset input + pgpFlush : in std_logic; -- Flash frame state + pllTxRst : in std_logic; -- Reset transmit PLL logic + pllRxRst : in std_logic; -- Reset receive PLL logic + pllRxReady : out std_logic; -- MGT Receive logic is ready + pllTxReady : out std_logic; -- MGT Transmit logic is ready + pgpRemData : out std_logic_vector(7 downto 0); -- Far end side User Data + pgpLocData : in std_logic_vector(7 downto 0); -- Far end side User Data + pgpTxOpCodeEn : in std_logic; -- Opcode receive enable + pgpTxOpCode : in std_logic_vector(7 downto 0); -- Opcode receive value + pgpRxOpCodeEn : out std_logic; -- Opcode receive enable + pgpRxOpCode : out std_logic_vector(7 downto 0); -- Opcode receive value + pgpLocLinkReady : out std_logic; -- Local Link is ready + pgpRemLinkReady : out std_logic; -- Far end side has link + pgpRxCellError : out std_logic; -- A cell error has occured + pgpRxLinkDown : out std_logic; -- A link down event has occured + pgpRxLinkError : out std_logic; -- A link error has occured + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc0FrameTxReady : out std_logic; -- PGP is ready + vc0FrameTxSOF : in std_logic; -- User frame data start of frame + vc0FrameTxEOF : in std_logic; -- User frame data end of frame + vc0FrameTxEOFE : in std_logic; -- User frame data error + vc0FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc0LocBuffAFull : in std_logic; -- Remote buffer almost full + vc0LocBuffFull : in std_logic; -- Remote buffer full + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxReady : out std_logic; -- PGP is ready + vc1FrameTxSOF : in std_logic; -- User frame data start of frame + vc1FrameTxEOF : in std_logic; -- User frame data end of frame + vc1FrameTxEOFE : in std_logic; -- User frame data error + vc1FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc1LocBuffAFull : in std_logic; -- Remote buffer almost full + vc1LocBuffFull : in std_logic; -- Remote buffer full + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxReady : out std_logic; -- PGP is ready + vc2FrameTxSOF : in std_logic; -- User frame data start of frame + vc2FrameTxEOF : in std_logic; -- User frame data end of frame + vc2FrameTxEOFE : in std_logic; -- User frame data error + vc2FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc2LocBuffAFull : in std_logic; -- Remote buffer almost full + vc2LocBuffFull : in std_logic; -- Remote buffer full + vc3FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxReady : out std_logic; -- PGP is ready + vc3FrameTxSOF : in std_logic; -- User frame data start of frame + vc3FrameTxEOF : in std_logic; -- User frame data end of frame + vc3FrameTxEOFE : in std_logic; -- User frame data error + vc3FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc3LocBuffAFull : in std_logic; -- Remote buffer almost full + vc3LocBuffFull : in std_logic; -- Remote buffer full + vcFrameRxSOF : out std_logic; -- PGP frame data start of frame + vcFrameRxEOF : out std_logic; -- PGP frame data end of frame + vcFrameRxEOFE : out std_logic; -- PGP frame data error + vcFrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc0FrameRxValid : out std_logic; -- PGP frame data is valid + vc0RemBuffAFull : out std_logic; -- Remote buffer almost full + vc0RemBuffFull : out std_logic; -- Remote buffer full + vc1FrameRxValid : out std_logic; -- PGP frame data is valid + vc1RemBuffAFull : out std_logic; -- Remote buffer almost full + vc1RemBuffFull : out std_logic; -- Remote buffer full + vc2FrameRxValid : out std_logic; -- PGP frame data is valid + vc2RemBuffAFull : out std_logic; -- Remote buffer almost full + vc2RemBuffFull : out std_logic; -- Remote buffer full + vc3FrameRxValid : out std_logic; -- PGP frame data is valid + vc3RemBuffAFull : out std_logic; -- Remote buffer almost full + vc3RemBuffFull : out std_logic; -- Remote buffer full + gtpLoopback : in std_logic; -- GTP Serial Loopback Control + gtpClkIn : in std_logic; -- GTP Reference Clock In + gtpRefClkOut : out std_logic; -- GTP Reference Clock Output + gtpRxRecClk : out std_logic; -- GTP Rx Recovered Clock + gtpRxN : in std_logic; -- GTP Serial Receive Negative + gtpRxP : in std_logic; -- GTP Serial Receive Positive + gtpTxN : out std_logic; -- GTP Serial Transmit Negative + gtpTxP : out std_logic; -- GTP Serial Transmit Positive + debug : out std_logic_vector(63 downto 0) + ); + end component; + + -- 32-bit wrapper + component Pgp2Gtp32 + generic ( + EnShortCells : integer := 1; -- Enable short non-EOF cells + VcInterleave : integer := 1 -- Interleave Frames + ); + port ( + pgpClk : in std_logic; -- 156.25Mhz master clock + pgpClk2x : in std_logic; -- 2x master clock + pgpReset : in std_logic; -- Synchronous reset input + pgpFlush : in std_logic; -- Flash frame state + pllTxRst : in std_logic; -- Reset transmit PLL logic + pllRxRst : in std_logic; -- Reset receive PLL logic + pllRxReady : out std_logic; -- MGT Receive logic is ready + pllTxReady : out std_logic; -- MGT Transmit logic is ready + pgpRemData : out std_logic_vector(7 downto 0); -- Far end side User Data + pgpLocData : in std_logic_vector(7 downto 0); -- Far end side User Data + pgpTxOpCodeEn : in std_logic; -- Opcode receive enable + pgpTxOpCode : in std_logic_vector(7 downto 0); -- Opcode receive value + pgpRxOpCodeEn : out std_logic; -- Opcode receive enable + pgpRxOpCode : out std_logic_vector(7 downto 0); -- Opcode receive value + pgpLocLinkReady : out std_logic; -- Local Link is ready + pgpRemLinkReady : out std_logic; -- Far end side has link + pgpRxCellError : out std_logic; -- A cell error has occured + pgpRxLinkDown : out std_logic; -- A link down event has occured + pgpRxLinkError : out std_logic; -- A link error has occured + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc0FrameTxReady : out std_logic; -- PGP is ready + vc0FrameTxSOF : in std_logic; -- User frame data start of frame + vc0FrameTxEOF : in std_logic; -- User frame data end of frame + vc0FrameTxEOFE : in std_logic; -- User frame data error + vc0FrameTxData : in std_logic_vector(31 downto 0); -- User frame data + vc0LocBuffAFull : in std_logic; -- Remote buffer almost full + vc0LocBuffFull : in std_logic; -- Remote buffer full + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxReady : out std_logic; -- PGP is ready + vc1FrameTxSOF : in std_logic; -- User frame data start of frame + vc1FrameTxEOF : in std_logic; -- User frame data end of frame + vc1FrameTxEOFE : in std_logic; -- User frame data error + vc1FrameTxData : in std_logic_vector(31 downto 0); -- User frame data + vc1LocBuffAFull : in std_logic; -- Remote buffer almost full + vc1LocBuffFull : in std_logic; -- Remote buffer full + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxReady : out std_logic; -- PGP is ready + vc2FrameTxSOF : in std_logic; -- User frame data start of frame + vc2FrameTxEOF : in std_logic; -- User frame data end of frame + vc2FrameTxEOFE : in std_logic; -- User frame data error + vc2FrameTxData : in std_logic_vector(31 downto 0); -- User frame data + vc2LocBuffAFull : in std_logic; -- Remote buffer almost full + vc2LocBuffFull : in std_logic; -- Remote buffer full + vc3FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxReady : out std_logic; -- PGP is ready + vc3FrameTxSOF : in std_logic; -- User frame data start of frame + vc3FrameTxEOF : in std_logic; -- User frame data end of frame + vc3FrameTxEOFE : in std_logic; -- User frame data error + vc3FrameTxData : in std_logic_vector(31 downto 0); -- User frame data + vc3LocBuffAFull : in std_logic; -- Remote buffer almost full + vc3LocBuffFull : in std_logic; -- Remote buffer full + vcFrameRxSOF : out std_logic; -- PGP frame data start of frame + vcFrameRxEOF : out std_logic; -- PGP frame data end of frame + vcFrameRxEOFE : out std_logic; -- PGP frame data error + vcFrameRxData : out std_logic_vector(31 downto 0); -- PGP frame data + vc0FrameRxValid : out std_logic; -- PGP frame data is valid + vc0RemBuffAFull : out std_logic; -- Remote buffer almost full + vc0RemBuffFull : out std_logic; -- Remote buffer full + vc1FrameRxValid : out std_logic; -- PGP frame data is valid + vc1RemBuffAFull : out std_logic; -- Remote buffer almost full + vc1RemBuffFull : out std_logic; -- Remote buffer full + vc2FrameRxValid : out std_logic; -- PGP frame data is valid + vc2RemBuffAFull : out std_logic; -- Remote buffer almost full + vc2RemBuffFull : out std_logic; -- Remote buffer full + vc3FrameRxValid : out std_logic; -- PGP frame data is valid + vc3RemBuffAFull : out std_logic; -- Remote buffer almost full + vc3RemBuffFull : out std_logic; -- Remote buffer full + gtpLoopback : in std_logic; -- GTP Serial Loopback Control + gtpClkIn : in std_logic; -- GTP Reference Clock In + gtpRefClkOut : out std_logic; -- GTP Reference Clock Output + gtpRxRecClk : out std_logic; -- GTP Rx Recovered Clock + gtpRxN : in std_logic_vector(1 downto 0); -- GTP Serial Receive Negative + gtpRxP : in std_logic_vector(1 downto 0); -- GTP Serial Receive Positive + gtpTxN : out std_logic_vector(1 downto 0); -- GTP Serial Transmit Negative + gtpTxP : out std_logic_vector(1 downto 0); -- GTP Serial Transmit Positive + debug : out std_logic_vector(63 downto 0) + ); + end component; + + -- 16-bit dual wrapper + component Pgp2GtpDual + generic ( + EnShortCells : integer := 1; -- Enable short non-EOF cells + VcInterleave : integer := 1 -- Interleave Frames + ); + port ( + pgpClk : in std_logic; -- 156.25Mhz master clock + pgpClk2x : in std_logic; -- 2x master clock + pgpReset : in std_logic; -- Synchronous reset input + pgpFlush : in std_logic; -- Flash frame state + pll0TxRst : in std_logic; -- Reset transmit PLL logic + pll0RxRst : in std_logic; -- Reset receive PLL logic + pll0RxReady : out std_logic; -- MGT Receive logic is ready + pll0TxReady : out std_logic; -- MGT Transmit logic is ready + pgp0RemData : out std_logic_vector(7 downto 0); -- Far end side User Data + pgp0LocData : in std_logic_vector(7 downto 0); -- Far end side User Data + pgp0TxOpCodeEn : in std_logic; -- Opcode receive enable + pgp0TxOpCode : in std_logic_vector(7 downto 0); -- Opcode receive value + pgp0RxOpCodeEn : out std_logic; -- Opcode receive enable + pgp0RxOpCode : out std_logic_vector(7 downto 0); -- Opcode receive value + pgp0LocLinkReady : out std_logic; -- Local Link is ready + pgp0RemLinkReady : out std_logic; -- Far end side has link + pgp0RxCellError : out std_logic; -- A cell error has occured + pgp0RxLinkDown : out std_logic; -- A link down event has occured + pgp0RxLinkError : out std_logic; -- A link error has occured + vc00FrameTxValid : in std_logic; -- User frame data is valid + vc00FrameTxReady : out std_logic; -- PGP is ready + vc00FrameTxSOF : in std_logic; -- User frame data start of frame + vc00FrameTxEOF : in std_logic; -- User frame data end of frame + vc00FrameTxEOFE : in std_logic; -- User frame data error + vc00FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc00LocBuffAFull : in std_logic; -- Remote buffer almost full + vc00LocBuffFull : in std_logic; -- Remote buffer full + vc01FrameTxValid : in std_logic; -- User frame data is valid + vc01FrameTxReady : out std_logic; -- PGP is ready + vc01FrameTxSOF : in std_logic; -- User frame data start of frame + vc01FrameTxEOF : in std_logic; -- User frame data end of frame + vc01FrameTxEOFE : in std_logic; -- User frame data error + vc01FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc01LocBuffAFull : in std_logic; -- Remote buffer almost full + vc01LocBuffFull : in std_logic; -- Remote buffer full + vc02FrameTxValid : in std_logic; -- User frame data is valid + vc02FrameTxReady : out std_logic; -- PGP is ready + vc02FrameTxSOF : in std_logic; -- User frame data start of frame + vc02FrameTxEOF : in std_logic; -- User frame data end of frame + vc02FrameTxEOFE : in std_logic; -- User frame data error + vc02FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc02LocBuffAFull : in std_logic; -- Remote buffer almost full + vc02LocBuffFull : in std_logic; -- Remote buffer full + vc03FrameTxValid : in std_logic; -- User frame data is valid + vc03FrameTxReady : out std_logic; -- PGP is ready + vc03FrameTxSOF : in std_logic; -- User frame data start of frame + vc03FrameTxEOF : in std_logic; -- User frame data end of frame + vc03FrameTxEOFE : in std_logic; -- User frame data error + vc03FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc03LocBuffAFull : in std_logic; -- Remote buffer almost full + vc03LocBuffFull : in std_logic; -- Remote buffer full + vc0FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc0FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc0FrameRxEOFE : out std_logic; -- PGP frame data error + vc0FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc00FrameRxValid : out std_logic; -- PGP frame data is valid + vc00RemBuffAFull : out std_logic; -- Remote buffer almost full + vc00RemBuffFull : out std_logic; -- Remote buffer full + vc01FrameRxValid : out std_logic; -- PGP frame data is valid + vc01RemBuffAFull : out std_logic; -- Remote buffer almost full + vc01RemBuffFull : out std_logic; -- Remote buffer full + vc02FrameRxValid : out std_logic; -- PGP frame data is valid + vc02RemBuffAFull : out std_logic; -- Remote buffer almost full + vc02RemBuffFull : out std_logic; -- Remote buffer full + vc03FrameRxValid : out std_logic; -- PGP frame data is valid + vc03RemBuffAFull : out std_logic; -- Remote buffer almost full + vc03RemBuffFull : out std_logic; -- Remote buffer full + pll1TxRst : in std_logic; -- Reset transmit PLL logic + pll1RxRst : in std_logic; -- Reset receive PLL logic + pll1RxReady : out std_logic; -- MGT Receive logic is ready + pll1TxReady : out std_logic; -- MGT Transmit logic is ready + pgp1RemData : out std_logic_vector(7 downto 0); -- Far end side User Data + pgp1LocData : in std_logic_vector(7 downto 0); -- Far end side User Data + pgp1TxOpCodeEn : in std_logic; -- Opcode receive enable + pgp1TxOpCode : in std_logic_vector(7 downto 0); -- Opcode receive value + pgp1RxOpCodeEn : out std_logic; -- Opcode receive enable + pgp1RxOpCode : out std_logic_vector(7 downto 0); -- Opcode receive value + pgp1LocLinkReady : out std_logic; -- Local Link is ready + pgp1RemLinkReady : out std_logic; -- Far end side has link + pgp1RxCellError : out std_logic; -- A cell error has occured + pgp1RxLinkDown : out std_logic; -- A link down event has occured + pgp1RxLinkError : out std_logic; -- A link error has occured + vc10FrameTxValid : in std_logic; -- User frame data is valid + vc10FrameTxReady : out std_logic; -- PGP is ready + vc10FrameTxSOF : in std_logic; -- User frame data start of frame + vc10FrameTxEOF : in std_logic; -- User frame data end of frame + vc10FrameTxEOFE : in std_logic; -- User frame data error + vc10FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc10LocBuffAFull : in std_logic; -- Remote buffer almost full + vc10LocBuffFull : in std_logic; -- Remote buffer full + vc11FrameTxValid : in std_logic; -- User frame data is valid + vc11FrameTxReady : out std_logic; -- PGP is ready + vc11FrameTxSOF : in std_logic; -- User frame data start of frame + vc11FrameTxEOF : in std_logic; -- User frame data end of frame + vc11FrameTxEOFE : in std_logic; -- User frame data error + vc11FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc11LocBuffAFull : in std_logic; -- Remote buffer almost full + vc11LocBuffFull : in std_logic; -- Remote buffer full + vc12FrameTxValid : in std_logic; -- User frame data is valid + vc12FrameTxReady : out std_logic; -- PGP is ready + vc12FrameTxSOF : in std_logic; -- User frame data start of frame + vc12FrameTxEOF : in std_logic; -- User frame data end of frame + vc12FrameTxEOFE : in std_logic; -- User frame data error + vc12FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc12LocBuffAFull : in std_logic; -- Remote buffer almost full + vc12LocBuffFull : in std_logic; -- Remote buffer full + vc13FrameTxValid : in std_logic; -- User frame data is valid + vc13FrameTxReady : out std_logic; -- PGP is ready + vc13FrameTxSOF : in std_logic; -- User frame data start of frame + vc13FrameTxEOF : in std_logic; -- User frame data end of frame + vc13FrameTxEOFE : in std_logic; -- User frame data error + vc13FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc13LocBuffAFull : in std_logic; -- Remote buffer almost full + vc13LocBuffFull : in std_logic; -- Remote buffer full + vc1FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc1FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc1FrameRxEOFE : out std_logic; -- PGP frame data error + vc1FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc10FrameRxValid : out std_logic; -- PGP frame data is valid + vc10RemBuffAFull : out std_logic; -- Remote buffer almost full + vc10RemBuffFull : out std_logic; -- Remote buffer full + vc11FrameRxValid : out std_logic; -- PGP frame data is valid + vc11RemBuffAFull : out std_logic; -- Remote buffer almost full + vc11RemBuffFull : out std_logic; -- Remote buffer full + vc12FrameRxValid : out std_logic; -- PGP frame data is valid + vc12RemBuffAFull : out std_logic; -- Remote buffer almost full + vc12RemBuffFull : out std_logic; -- Remote buffer full + vc13FrameRxValid : out std_logic; -- PGP frame data is valid + vc13RemBuffAFull : out std_logic; -- Remote buffer almost full + vc13RemBuffFull : out std_logic; -- Remote buffer full + gtpLoopback : in std_logic_vector(1 downto 0); -- GTP Serial Loopback Control + gtpClkIn : in std_logic; -- GTP Reference Clock In + gtpRefClkOut : out std_logic; -- GTP Reference Clock Output + gtpRxRecClk : out std_logic_vector(1 downto 0); -- GTP Rx Recovered Clock + gtpRxN : in std_logic_vector(1 downto 0); -- GTP Serial Receive Negative + gtpRxP : in std_logic_vector(1 downto 0); -- GTP Serial Receive Positive + gtpTxN : out std_logic_vector(1 downto 0); -- GTP Serial Transmit Negative + gtpTxP : out std_logic_vector(1 downto 0); -- GTP Serial Transmit Positive + debug : out std_logic_vector(127 downto 0) + ); + end component; + + -- PGP Clock Generator + component Pgp2GtpClk + generic ( + UserFxDiv : integer := 5; -- DCM FX Output Divide + UserFxMult : integer := 4 -- DCM FX Output Divide, 4/5 * 156.25 = 125Mhz + ); + port ( + pgpRefClk : in std_logic; + ponResetL : in std_logic; + locReset : in std_logic; + pgpClk : out std_logic; + pgpReset : out std_logic; + pgpClk2x : out std_logic; + userClk : out std_logic; + userReset : out std_logic; + pgpClkIn : in std_logic; + userClkIn : in std_logic + ); + end component; + + -- RX Reset Control + component Pgp2GtpRxRst + port ( + gtpRxClk : in std_logic; + gtpRxRst : in std_logic; + gtpRxReady : out std_logic; + gtpRxInit : in std_logic; + gtpLockDetect : in std_logic; + gtpRxElecIdle : in std_logic; + gtpRxBuffStatus : in std_logic_vector(2 downto 0); + gtpRstDone : in std_logic; + gtpRxElecIdleRst : out std_logic; + gtpRxReset : out std_logic; + gtpRxCdrReset : out std_logic + ); + end component; + + -- TX Reset Control + component Pgp2GtpTxRst + port ( + gtpTxClk : in std_logic; + gtpTxRst : in std_logic; + gtpTxReady : out std_logic; + gtpLockDetect : in std_logic; + gtpTxBuffStatus : in std_logic_vector(1 downto 0); + gtpRstDone : in std_logic; + gtpTxReset : out std_logic + ); + end component; + + + +end Pgp2GtpPackage; + + diff --git a/rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2GtpRxRst.vhd b/rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2GtpRxRst.vhd new file mode 100755 index 00000000..0348001a --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2GtpRxRst.vhd @@ -0,0 +1,205 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, GTP RX Reset Control +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2GtpRxRst.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 08/18/2009 +------------------------------------------------------------------------------- +-- Description: +-- This module contains the logic to control the reset of the RX GTP. +------------------------------------------------------------------------------- +-- Copyright (c) 2009 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 08/18/2009: created. +-- 01/13/2010: Added received init line to help linking. +-- 04/20/2010: Elec idle will no longer cause general reset. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; +use work.Pgp2GtpPackage.all; +library UNISIM; +use UNISIM.VCOMPONENTS.ALL; + + +entity Pgp2GtpRxRst is + port ( + + -- Clock and reset + gtpRxClk : in std_logic; + gtpRxRst : in std_logic; + + -- RX Side is ready + gtpRxReady : out std_logic; + gtpRxInit : in std_logic; + + -- GTP Status + gtpLockDetect : in std_logic; + gtpRxElecIdle : in std_logic; + gtpRxBuffStatus : in std_logic_vector(2 downto 0); + gtpRstDone : in std_logic; + + -- Reset Control + gtpRxElecIdleRst : out std_logic; + gtpRxReset : out std_logic; + gtpRxCdrReset : out std_logic + ); + +end Pgp2GtpRxRst; + + +-- Define architecture +architecture Pgp2GtpRxRst of Pgp2GtpRxRst is + + -- Local Signals + signal intRxElecIdleRst : std_logic; + signal intRxReset : std_logic; + signal intRxCdrReset : std_logic; + signal rxStateCnt : std_logic_vector(1 downto 0); + signal rxStateCntRst : std_logic; + signal rxClockReady : std_logic; + + -- RX Reset State Machine + constant RX_SYSTEM_RESET : std_logic_vector(2 downto 0) := "000"; + constant RX_WAIT_LOCK : std_logic_vector(2 downto 0) := "001"; + constant RX_RESET : std_logic_vector(2 downto 0) := "010"; + constant RX_WAIT_DONE : std_logic_vector(2 downto 0) := "011"; + constant RX_READY : std_logic_vector(2 downto 0) := "100"; + signal curRxState : std_logic_vector(2 downto 0); + signal nxtRxState : std_logic_vector(2 downto 0); + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + + -- RX State Machine Synchronous Logic + process ( gtpRxClk, gtpRxRst ) begin + if gtpRxRst = '1' then + curRxState <= RX_SYSTEM_RESET after tpd; + rxStateCnt <= (others=>'0') after tpd; + gtpRxReady <= '0' after tpd; + gtpRxElecIdleRst <= '1' after tpd; + gtpRxReset <= '1' after tpd; + gtpRxCdrReset <= '1' after tpd; + elsif rising_edge(gtpRxClk) then + + -- Drive PIB Lock + gtpRxReady <= rxClockReady after tpd; + + -- Pass on reset signals + gtpRxElecIdleRst <= intRxElecIdleRst or gtpRxInit after tpd; + gtpRxReset <= intRxReset after tpd; + gtpRxCdrReset <= intRxCdrReset after tpd; + + -- Update state + if gtpRxInit = '1' then + curRxState <= RX_SYSTEM_RESET after tpd; + else + curRxState <= nxtRxState after tpd; + end if; + + -- Rx State Counter + if rxStateCntRst = '1' then + rxStateCnt <= (others=>'0') after tpd; + else + rxStateCnt <= rxStateCnt + 1 after tpd; + end if; + end if; + end process; + + + -- Async RX State Logic + process ( curRxState, rxStateCnt, gtpLockDetect, gtpRxBuffStatus, gtpRstDone ) begin + case curRxState is + + -- System Reset State + when RX_SYSTEM_RESET => + rxStateCntRst <= '1'; + intRxReset <= '1'; + intRxCdrReset <= '1'; + rxClockReady <= '0'; + nxtRxState <= RX_WAIT_LOCK; + + -- Wait for PLL lock + when RX_WAIT_LOCK => + rxStateCntRst <= '1'; + intRxReset <= '1'; + intRxCdrReset <= '0'; + rxClockReady <= '0'; + + -- Wait for lock + if gtpLockDetect = '1' then + nxtRxState <= RX_RESET; + else + nxtRxState <= curRxState; + end if; + + -- RX Reset State + when RX_RESET => + intRxReset <= '1'; + intRxCdrReset <= '0'; + rxClockReady <= '0'; + rxStateCntRst <= '0'; + + -- Wait for three clocks + if rxStateCnt = 3 then + nxtRxState <= RX_WAIT_DONE; + else + nxtRxState <= curRxState; + end if; + + -- RX Wait Reset Done + when RX_WAIT_DONE => + intRxReset <= '0'; + intRxCdrReset <= '0'; + rxClockReady <= '0'; + rxStateCntRst <= '1'; + + -- Wait for reset done + if gtpRstDone = '1' then + nxtRxState <= RX_READY; + else + nxtRxState <= curRxState; + end if; + + -- RX Ready + when RX_READY => + intRxReset <= '0'; + intRxCdrReset <= '0'; + rxClockReady <= '1'; + rxStateCntRst <= '1'; + + -- Look for unlock error + if gtpLockDetect = '0' then + nxtRxState <= RX_WAIT_LOCK; + + -- Look For Buffer Error + elsif gtpRxBuffStatus(2) = '1' then + nxtRxState <= RX_RESET; + + else + nxtRxState <= curRxState; + end if; + + -- Default + when others => + intRxReset <= '0'; + intRxCdrReset <= '0'; + rxClockReady <= '0'; + rxStateCntRst <= '1'; + nxtRxState <= RX_SYSTEM_RESET; + end case; + end process; + + -- Elec idle reset + intRxElecIdleRst <= gtpRxElecIdle and gtpRstDone; + +end Pgp2GtpRxRst; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2GtpTxRst.vhd b/rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2GtpTxRst.vhd new file mode 100755 index 00000000..cf2eae1f --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/gtp/Pgp2GtpTxRst.vhd @@ -0,0 +1,179 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, GTP TX Reset Control +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2GtpTxRst.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 08/18/2009 +------------------------------------------------------------------------------- +-- Description: +-- This module contains the logic to control the reset of the TX GTP. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 08/18/2009: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; +use work.Pgp2GtpPackage.all; +library UNISIM; +use UNISIM.VCOMPONENTS.ALL; + + +entity Pgp2GtpTxRst is + port ( + + -- Clock and reset + gtpTxClk : in std_logic; + gtpTxRst : in std_logic; + + -- TX Side is ready + gtpTxReady : out std_logic; + + -- GTP Status + gtpLockDetect : in std_logic; + gtpTxBuffStatus : in std_logic_vector(1 downto 0); + gtpRstDone : in std_logic; + + -- Reset Control + gtpTxReset : out std_logic + ); + +end Pgp2GtpTxRst; + + +-- Define architecture +architecture Pgp2GtpTxRst of Pgp2GtpTxRst is + + -- Local Signals + signal intTxReset : std_logic; + signal txStateCnt : std_logic_vector(1 downto 0); + signal txStateCntRst : std_logic; + signal txClockReady : std_logic; + + -- TX Reset State Machine + constant TX_SYSTEM_RESET : std_logic_vector(2 downto 0) := "000"; + constant TX_WAIT_LOCK : std_logic_vector(2 downto 0) := "001"; + constant TX_RESET : std_logic_vector(2 downto 0) := "010"; + constant TX_WAIT_DONE : std_logic_vector(2 downto 0) := "011"; + constant TX_READY : std_logic_vector(2 downto 0) := "100"; + signal curTxState : std_logic_vector(2 downto 0); + signal nxtTxState : std_logic_vector(2 downto 0); + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + + -- TX State Machine Synchronous Logic + process ( gtpTxClk, gtpTxRst ) begin + if gtpTxRst = '1' then + curTxState <= TX_SYSTEM_RESET after tpd; + txStateCnt <= (others=>'0') after tpd; + gtpTxReset <= '1' after tpd; + gtpTxReady <= '0' after tpd; + elsif rising_edge(gtpTxClk) then + + -- RX Is Ready + gtpTxReady <= txClockReady after tpd; + + -- Pass on reset signals + gtpTxReset <= intTxReset after tpd; + + -- Update state + curTxState <= nxtTxState after tpd; + + -- Tx State Counter + if txStateCntRst = '1' then + txStateCnt <= (others=>'0') after tpd; + else + txStateCnt <= txStateCnt + 1 after tpd; + end if; + end if; + end process; + + + -- Async TX State Logic + process ( curTxState, txStateCnt, gtpLockDetect, gtpTxBuffStatus, gtpRstDone ) begin + case curTxState is + + -- System Reset State + when TX_SYSTEM_RESET => + txStateCntRst <= '1'; + intTxReset <= '1'; + txClockReady <= '0'; + nxtTxState <= TX_WAIT_LOCK; + + -- Wait for PLL lock + when TX_WAIT_LOCK => + txStateCntRst <= '1'; + intTxReset <= '1'; + txClockReady <= '0'; + + -- Wait for three clocks + if gtpLockDetect = '1' then + nxtTxState <= TX_RESET; + else + nxtTxState <= curTxState; + end if; + + -- TX Reset State + when TX_RESET => + intTxReset <= '1'; + txClockReady <= '0'; + txStateCntRst <= '0'; + + -- Wait for three clocks + if txStateCnt = 3 then + nxtTxState <= TX_WAIT_DONE; + else + nxtTxState <= curTxState; + end if; + + -- TX Wait Reset Done + when TX_WAIT_DONE => + intTxReset <= '0'; + txClockReady <= '0'; + txStateCntRst <= '1'; + + -- Wait for three clocks + if gtpRstDone = '1' then + nxtTxState <= TX_READY; + else + nxtTxState <= curTxState; + end if; + + -- TX Ready + when TX_READY => + intTxReset <= '0'; + txClockReady <= '1'; + txStateCntRst <= '1'; + + -- Look for unlock error + if gtpLockDetect = '0' then + nxtTxState <= TX_WAIT_LOCK; + + -- Look For Buffer Error + elsif gtpTxBuffStatus(1) = '1' then + nxtTxState <= TX_RESET; + else + nxtTxState <= curTxState; + end if; + + -- Default + when others => + intTxReset <= '0'; + txClockReady <= '0'; + txStateCntRst <= '1'; + nxtTxState <= TX_SYSTEM_RESET; + end case; + end process; + +end Pgp2GtpTxRst; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2Gtx16.vhd b/rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2Gtx16.vhd new file mode 100755 index 00000000..7221a466 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2Gtx16.vhd @@ -0,0 +1,954 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, GTX Wrapper +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2Gtx16.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 08/18/2009 +------------------------------------------------------------------------------- +-- Description: +-- VHDL source file containing the PGP, GTX and CRC blocks. +-- This module also contains the logic to control the reset of the GTX. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 08/18/2009: created. +-- 01/13/2010: Added received init line to help linking. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; +use work.Pgp2GtxPackage.all; +use work.Pgp2CorePackage.all; +library UNISIM; +use UNISIM.VCOMPONENTS.ALL; + + +entity Pgp2Gtx16 is + generic ( + EnShortCells : integer := 1; -- Enable short non-EOF cells + VcInterleave : integer := 1 -- Interleave Frames + ); + port ( + + -- System clock, reset & control + pgpClk : in std_logic; -- Pgp master clock + pgpReset : in std_logic; -- Synchronous reset input + pgpFlush : in std_logic; -- Frame sync flush + + -- PLL Reset Control + pllTxRst : in std_logic; -- Reset transmit PLL logic + pllRxRst : in std_logic; -- Reset receive PLL logic + + -- PLL Lock Status + pllRxReady : out std_logic; -- MGT Receive logic is ready + pllTxReady : out std_logic; -- MGT Transmit logic is ready + + -- Sideband data + pgpRemData : out std_logic_vector(7 downto 0); -- Far end side User Data + pgpLocData : in std_logic_vector(7 downto 0); -- Far end side User Data + + -- Opcode Transmit Interface + pgpTxOpCodeEn : in std_logic; -- Opcode receive enable + pgpTxOpCode : in std_logic_vector(7 downto 0); -- Opcode receive value + + -- Opcode Receive Interface + pgpRxOpCodeEn : out std_logic; -- Opcode receive enable + pgpRxOpCode : out std_logic_vector(7 downto 0); -- Opcode receive value + + -- Link status + pgpLocLinkReady : out std_logic; -- Local Link is ready + pgpRemLinkReady : out std_logic; -- Far end side has link + + -- Error Flags, one pulse per event + pgpRxCellError : out std_logic; -- A cell error has occured + pgpRxLinkDown : out std_logic; -- A link down event has occured + pgpRxLinkError : out std_logic; -- A link error has occured + + -- Frame Transmit Interface, VC 0 + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc0FrameTxReady : out std_logic; -- PGP is ready + vc0FrameTxSOF : in std_logic; -- User frame data start of frame + vc0FrameTxEOF : in std_logic; -- User frame data end of frame + vc0FrameTxEOFE : in std_logic; -- User frame data error + vc0FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc0LocBuffAFull : in std_logic; -- Local buffer almost full + vc0LocBuffFull : in std_logic; -- Local buffer full + + -- Frame Transmit Interface, VC 1 + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxReady : out std_logic; -- PGP is ready + vc1FrameTxSOF : in std_logic; -- User frame data start of frame + vc1FrameTxEOF : in std_logic; -- User frame data end of frame + vc1FrameTxEOFE : in std_logic; -- User frame data error + vc1FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc1LocBuffAFull : in std_logic; -- Local buffer almost full + vc1LocBuffFull : in std_logic; -- Local buffer full + + -- Frame Transmit Interface, VC 2 + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxReady : out std_logic; -- PGP is ready + vc2FrameTxSOF : in std_logic; -- User frame data start of frame + vc2FrameTxEOF : in std_logic; -- User frame data end of frame + vc2FrameTxEOFE : in std_logic; -- User frame data error + vc2FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc2LocBuffAFull : in std_logic; -- Local buffer almost full + vc2LocBuffFull : in std_logic; -- Local buffer full + + -- Frame Transmit Interface, VC 3 + vc3FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxReady : out std_logic; -- PGP is ready + vc3FrameTxSOF : in std_logic; -- User frame data start of frame + vc3FrameTxEOF : in std_logic; -- User frame data end of frame + vc3FrameTxEOFE : in std_logic; -- User frame data error + vc3FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc3LocBuffAFull : in std_logic; -- Local buffer almost full + vc3LocBuffFull : in std_logic; -- Local buffer full + + -- Common Frame Receive Interface For All VCs + vcFrameRxSOF : out std_logic; -- PGP frame data start of frame + vcFrameRxEOF : out std_logic; -- PGP frame data end of frame + vcFrameRxEOFE : out std_logic; -- PGP frame data error + vcFrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + + -- Frame Receive Interface, VC 0 + vc0FrameRxValid : out std_logic; -- PGP frame data is valid + vc0RemBuffAFull : out std_logic; -- Remote buffer almost full + vc0RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 1 + vc1FrameRxValid : out std_logic; -- PGP frame data is valid + vc1RemBuffAFull : out std_logic; -- Remote buffer almost full + vc1RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 2 + vc2FrameRxValid : out std_logic; -- PGP frame data is valid + vc2RemBuffAFull : out std_logic; -- Remote buffer almost full + vc2RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 3 + vc3FrameRxValid : out std_logic; -- PGP frame data is valid + vc3RemBuffAFull : out std_logic; -- Remote buffer almost full + vc3RemBuffFull : out std_logic; -- Remote buffer full + + -- GTX Status & Control Signals + gtxLoopback : in std_logic; -- GTX Serial Loopback Control + + -- MGT Signals Clock & IO Signals + gtxClkIn : in std_logic; -- GTX Reference Clock In + gtxRefClkOut : out std_logic; -- GTX Reference Clock Output + gtxRxRecClk : out std_logic; -- GTX Rx Recovered Clock + gtxRxN : in std_logic; -- GTX Serial Receive Negative + gtxRxP : in std_logic; -- GTX Serial Receive Positive + gtxTxN : out std_logic; -- GTX Serial Transmit Negative + gtxTxP : out std_logic; -- GTX Serial Transmit Positive + + -- Debug + debug : out std_logic_vector(63 downto 0) + ); + +end Pgp2Gtx16; + + +-- Define architecture +architecture Pgp2Gtx16 of Pgp2Gtx16 is + + -- Local Signals + signal crcTxIn : std_logic_vector(15 downto 0); + signal crcTxInGtx : std_logic_vector(31 downto 0); + signal crcTxInit : std_logic; + signal crcTxRst : std_logic; + signal crcTxValid : std_logic; + signal crcTxWidth : std_logic_vector(2 downto 0); + signal crcTxOut : std_logic_vector(31 downto 0); + signal crcTxOutGtx : std_logic_vector(31 downto 0); + signal crcRxIn : std_logic_vector(15 downto 0); + signal crcRxInGtx : std_logic_vector(31 downto 0); + signal crcRxInit : std_logic; + signal crcRxRst : std_logic; + signal crcRxValid : std_logic; + signal crcRxWidth : std_logic_vector(2 downto 0); + signal crcRxOut : std_logic_vector(31 downto 0); + signal crcRxOutGtx : std_logic_vector(31 downto 0); + signal phyRxPolarity : std_logic_vector(0 downto 0); + signal phyRxData : std_logic_vector(15 downto 0); + signal phyRxDataK : std_logic_vector(1 downto 0); + signal phyTxData : std_logic_vector(15 downto 0); + signal phyTxDataK : std_logic_vector(1 downto 0); + signal phyRxDispErr : std_logic_vector(1 downto 0); + signal phyRxDecErr : std_logic_vector(1 downto 0); + signal phyRxReady : std_logic; + signal phyRxInit : std_logic; + signal phyTxReady : std_logic; + signal phyRxReset : std_logic; + signal phyRxElecIdle : std_logic; + signal phyRxCdrReset : std_logic; + signal phyRstDone : std_logic; + signal phyRxBuffStatus : std_logic_vector(2 downto 0); + signal phyTxReset : std_logic; + signal phyTxBuffStatus : std_logic_vector(1 downto 0); + signal phyLockDetect : std_logic; + signal intTxRst : std_logic; + signal intRxRst : std_logic; + signal pgpRxLinkReady : std_logic; + signal pgpTxLinkReady : std_logic; + signal intRxRecClk : std_logic; + signal tmpRefClkOut : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + + -- PGP RX Block + U_Pgp2Rx: Pgp2CorePackage.Pgp2Rx + generic map ( + RxLaneCnt => 1, + EnShortCells => EnShortCells + ) port map ( + pgpRxClk => pgpClk, + pgpRxReset => pgpReset, + pgpRxFlush => pgpFlush, + pgpRxLinkReady => pgpRxLinkReady, + pgpRxCellError => pgpRxCellError, + pgpRxLinkDown => pgpRxLinkDown, + pgpRxLinkError => pgpRxLinkError, + pgpRxOpCodeEn => pgpRxOpCodeEn, + pgpRxOpCode => pgpRxOpCode, + pgpRemLinkReady => pgpRemLinkReady, + pgpRemData => pgpRemData, + vcFrameRxSOF => vcFrameRxSOF, + vcFrameRxEOF => vcFrameRxEOF, + vcFrameRxEOFE => vcFrameRxEOFE, + vcFrameRxData => vcFrameRxData, + vc0FrameRxValid => vc0FrameRxValid, + vc0RemBuffAFull => vc0RemBuffAFull, + vc0RemBuffFull => vc0RemBuffFull, + vc1FrameRxValid => vc1FrameRxValid, + vc1RemBuffAFull => vc1RemBuffAFull, + vc1RemBuffFull => vc1RemBuffFull, + vc2FrameRxValid => vc2FrameRxValid, + vc2RemBuffAFull => vc2RemBuffAFull, + vc2RemBuffFull => vc2RemBuffFull, + vc3FrameRxValid => vc3FrameRxValid, + vc3RemBuffAFull => vc3RemBuffAFull, + vc3RemBuffFull => vc3RemBuffFull, + phyRxPolarity => phyRxPolarity, + phyRxData => phyRxData, + phyRxDataK => phyRxDataK, + phyRxDispErr => phyRxDispErr, + phyRxDecErr => phyRxDecErr, + phyRxReady => phyRxReady, + phyRxInit => phyRxInit, + crcRxIn => crcRxIn, + crcRxWidth => open, + crcRxInit => crcRxInit, + crcRxValid => crcRxValid, + crcRxOut => crcRxOut, + debug => debug + ); + + + -- PGP TX Block + U_Pgp2Tx: Pgp2CorePackage.Pgp2Tx + generic map ( + TxLaneCnt => 1, + VcInterleave => VcInterleave + ) port map ( + pgpTxClk => pgpClk, + pgpTxReset => pgpReset, + pgpTxFlush => pgpFlush, + pgpTxLinkReady => pgpTxLinkReady, + pgpTxOpCodeEn => pgpTxOpCodeEn, + pgpTxOpCode => pgpTxOpCode, + pgpLocLinkReady => pgpRxLinkReady, + pgpLocData => pgpLocData, + vc0FrameTxValid => vc0FrameTxValid, + vc0FrameTxReady => vc0FrameTxReady, + vc0FrameTxSOF => vc0FrameTxSOF, + vc0FrameTxEOF => vc0FrameTxEOF, + vc0FrameTxEOFE => vc0FrameTxEOFE, + vc0FrameTxData => vc0FrameTxData, + vc0LocBuffAFull => vc0LocBuffAFull, + vc0LocBuffFull => vc0LocBuffFull, + vc1FrameTxValid => vc1FrameTxValid, + vc1FrameTxReady => vc1FrameTxReady, + vc1FrameTxSOF => vc1FrameTxSOF, + vc1FrameTxEOF => vc1FrameTxEOF, + vc1FrameTxEOFE => vc1FrameTxEOFE, + vc1FrameTxData => vc1FrameTxData, + vc1LocBuffAFull => vc1LocBuffAFull, + vc1LocBuffFull => vc1LocBuffFull, + vc2FrameTxValid => vc2FrameTxValid, + vc2FrameTxReady => vc2FrameTxReady, + vc2FrameTxSOF => vc2FrameTxSOF, + vc2FrameTxEOF => vc2FrameTxEOF, + vc2FrameTxEOFE => vc2FrameTxEOFE, + vc2FrameTxData => vc2FrameTxData, + vc2LocBuffAFull => vc2LocBuffAFull, + vc2LocBuffFull => vc2LocBuffFull, + vc3FrameTxValid => vc3FrameTxValid, + vc3FrameTxReady => vc3FrameTxReady, + vc3FrameTxSOF => vc3FrameTxSOF, + vc3FrameTxEOF => vc3FrameTxEOF, + vc3FrameTxEOFE => vc3FrameTxEOFE, + vc3FrameTxData => vc3FrameTxData, + vc3LocBuffAFull => vc3LocBuffAFull, + vc3LocBuffFull => vc3LocBuffFull, + phyTxData => phyTxData, + phyTxDataK => phyTxDataK, + phyTxReady => phyTxReady, + crcTxIn => crcTxIn, + crcTxInit => crcTxInit, + crcTxValid => crcTxValid, + crcTxOut => crcTxOut, + debug => open + ); + + + -- Adapt CRC data width flag + crcTxWidth <= "001"; + crcRxWidth <= "001"; + crcRxRst <= intRxRst or crcRxInit; + crcTxRst <= intTxRst or crcTxInit; + + -- Pass CRC data in on proper bits + crcTxInGtx(31 downto 24) <= crcTxIn(7 downto 0); + crcTxInGtx(23 downto 16) <= crcTxIn(15 downto 8); + crcTxInGtx(15 downto 0) <= (others=>'0'); + crcRxInGtx(31 downto 24) <= crcRxIn(7 downto 0); + crcRxInGtx(23 downto 16) <= crcRxIn(15 downto 8); + crcRxInGtx(15 downto 0) <= (others=>'0'); + + -- Pll Resets + intTxRst <= pllTxRst or pgpReset; + intRxRst <= pllRxRst or pgpReset; + + -- PLL Lock + pllRxReady <= phyRxReady; + pllTxReady <= phyTxReady; + + -- Link Ready + pgpLocLinkReady <= pgpRxLinkReady and pgpTxLinkReady; + + -- Invert Output CRC + crcRxOut <= not crcRxOutGtx; + crcTxOut <= not crcTxOutGtx; + + + -- TX CRC BLock + Tx_CRC: CRC32 + generic map( + CRC_INIT => x"FFFFFFFF" + ) port map( + CRCOUT => crcTxOutGtx, + CRCCLK => pgpClk, + CRCDATAVALID => crcTxValid, + CRCDATAWIDTH => crcTxWidth, + CRCIN => crcTxInGtx, + CRCRESET => crcTxRst + ); + + + -- RX CRC BLock + Rx_CRC: CRC32 + generic map( + CRC_INIT => x"FFFFFFFF" + ) port map( + CRCOUT => crcRxOutGtx, + CRCCLK => pgpClk, + CRCDATAVALID => crcRxValid, + CRCDATAWIDTH => crcRxWidth, + CRCIN => crcRxInGtx, + CRCRESET => crcRxRst + ); + + + -- RX Reset Control + U_Pgp2GtxRxRst: Pgp2GtxPackage.Pgp2GtxRxRst + port map ( + gtxRxClk => pgpClk, + gtxRxRst => intRxRst, + gtxRxReady => phyRxReady, + gtxRxInit => phyRxInit, + gtxLockDetect => phyLockDetect, + gtxRxElecIdle => phyRxElecIdle, + gtxRxBuffStatus => phyRxBuffStatus, + gtxRstDone => phyRstDone, + gtxRxReset => phyRxReset, + gtxRxCdrReset => phyRxCdrReset + ); + + + -- TX Reset Control + U_Pgp2GtxTxRst: Pgp2GtxPackage.Pgp2GtxTxRst + port map ( + gtxTxClk => pgpClk, + gtxTxRst => intTxRst, + gtxTxReady => phyTxReady, + gtxLockDetect => phyLockDetect, + gtxTxBuffStatus => phyTxBuffStatus, + gtxRstDone => phyRstDone, + gtxTxReset => phyTxReset + ); + + + ----------------------------- GTX_DUAL Instance -------------------------- + UGtxDual:GTX_DUAL + generic map ( + + --_______________________ Simulation-Only Attributes ___________________ + + SIM_RECEIVER_DETECT_PASS_0 => TRUE, + SIM_RECEIVER_DETECT_PASS_1 => TRUE, + SIM_MODE => "FAST", + SIM_GTXRESET_SPEEDUP => 1, + SIM_PLL_PERDIV2 => x"140", + + --___________________________ Shared Attributes ________________________ + + -------------------------- Tile and PLL Attributes --------------------- + + CLK25_DIVIDER => 10, + CLKINDC_B => TRUE, + OOB_CLK_DIVIDER => 6, + OVERSAMPLE_MODE => FALSE, + PLL_DIVSEL_FB => 2, + PLL_DIVSEL_REF => 1, + CLKRCV_TRST => TRUE, + PLL_COM_CFG => x"21680a", + PLL_CP_CFG => x"00", + PLL_FB_DCCEN => FALSE, + PLL_LKDET_CFG => "101", + PLL_TDCC_CFG => "000", + PMA_COM_CFG => x"000000000000000000", + + --____________________ Transmit Interface Attributes ___________________ + + ------------------- TX Buffering and Phase Alignment ------------------- + + TX_BUFFER_USE_0 => TRUE, + TX_XCLK_SEL_0 => "TXOUT", + TXRX_INVERT_0 => "011", + + TX_BUFFER_USE_1 => TRUE, + TX_XCLK_SEL_1 => "TXOUT", + TXRX_INVERT_1 => "011", + + --------------------- TX Gearbox Settings ----------------------------- + + GEARBOX_ENDEC_0 => "000", + TXGEARBOX_USE_0 => FALSE, + + GEARBOX_ENDEC_1 => "000", + TXGEARBOX_USE_1 => FALSE, + + --------------------- TX Serial Line Rate settings --------------------- + + PLL_TXDIVSEL_OUT_0 => 1, + PLL_TXDIVSEL_OUT_1 => 1, + + --------------------- TX Driver and OOB signalling -------------------- + + CM_TRIM_0 => "10", + PMA_TX_CFG_0 => x"80082", + TX_DETECT_RX_CFG_0 => x"1832", + TX_IDLE_DELAY_0 => "010", + CM_TRIM_1 => "10", + PMA_TX_CFG_1 => x"80082", + TX_DETECT_RX_CFG_1 => x"1832", + TX_IDLE_DELAY_1 => "010", + + ------------------ TX Pipe Control for PCI Express/SATA --------------- + + COM_BURST_VAL_0 => "1111", + COM_BURST_VAL_1 => "1111", + + --_______________________ Receive Interface Attributes ________________ + + ------------ RX Driver,OOB signalling,Coupling and Eq,CDR ------------- + + AC_CAP_DIS_0 => TRUE, + OOBDETECT_THRESHOLD_0 => "111", + PMA_CDR_SCAN_0 => x"640403a", + PMA_RX_CFG_0 => x"0f44088", + RCV_TERM_GND_0 => FALSE, + RCV_TERM_VTTRX_0 => TRUE, + TERMINATION_IMP_0 => 50, + AC_CAP_DIS_1 => TRUE, + OOBDETECT_THRESHOLD_1 => "111", + PMA_CDR_SCAN_1 => x"640403a", + PMA_RX_CFG_1 => x"0f44088", + RCV_TERM_GND_1 => FALSE, + RCV_TERM_VTTRX_1 => TRUE, + TERMINATION_IMP_1 => 50, + TERMINATION_CTRL => "10100", + TERMINATION_OVRD => FALSE, + + ---------------- RX Decision Feedback Equalizer(DFE) ---------------- + + DFE_CFG_0 => "1001111011", + DFE_CFG_1 => "1001111011", + DFE_CAL_TIME => "00110", + + --------------------- RX Serial Line Rate Attributes ------------------ + + PLL_RXDIVSEL_OUT_0 => 1, + PLL_SATA_0 => FALSE, + PLL_RXDIVSEL_OUT_1 => 1, + PLL_SATA_1 => FALSE, + + ----------------------- PRBS Detection Attributes --------------------- + + PRBS_ERR_THRESHOLD_0 => x"00000001", + PRBS_ERR_THRESHOLD_1 => x"00000001", + + ---------------- Comma Detection and Alignment Attributes ------------- + + ALIGN_COMMA_WORD_0 => 2, + COMMA_10B_ENABLE_0 => "1111111111", + COMMA_DOUBLE_0 => FALSE, + DEC_MCOMMA_DETECT_0 => TRUE, + DEC_PCOMMA_DETECT_0 => TRUE, + DEC_VALID_COMMA_ONLY_0 => FALSE, + MCOMMA_10B_VALUE_0 => "1010000011", + MCOMMA_DETECT_0 => TRUE, + PCOMMA_10B_VALUE_0 => "0101111100", + PCOMMA_DETECT_0 => TRUE, + RX_SLIDE_MODE_0 => "PCS", + + ALIGN_COMMA_WORD_1 => 2, + COMMA_10B_ENABLE_1 => "1111111111", + COMMA_DOUBLE_1 => FALSE, + DEC_MCOMMA_DETECT_1 => TRUE, + DEC_PCOMMA_DETECT_1 => TRUE, + DEC_VALID_COMMA_ONLY_1 => FALSE, + MCOMMA_10B_VALUE_1 => "1010000011", + MCOMMA_DETECT_1 => TRUE, + PCOMMA_10B_VALUE_1 => "0101111100", + PCOMMA_DETECT_1 => TRUE, + RX_SLIDE_MODE_1 => "PCS", + + ------------------ RX Loss-of-sync State Machine Attributes ----------- + + RX_LOSS_OF_SYNC_FSM_0 => FALSE, + RX_LOS_INVALID_INCR_0 => 8, + RX_LOS_THRESHOLD_0 => 128, + RX_LOSS_OF_SYNC_FSM_1 => FALSE, + RX_LOS_INVALID_INCR_1 => 8, + RX_LOS_THRESHOLD_1 => 128, + + --------------------- RX Gearbox Settings ----------------------------- + + RXGEARBOX_USE_0 => FALSE, + RXGEARBOX_USE_1 => FALSE, + + -------------- RX Elastic Buffer and Phase alignment Attributes ------- + + PMA_RXSYNC_CFG_0 => x"00", + RX_BUFFER_USE_0 => TRUE, + RX_XCLK_SEL_0 => "RXREC", + PMA_RXSYNC_CFG_1 => x"00", + RX_BUFFER_USE_1 => TRUE, + RX_XCLK_SEL_1 => "RXREC", + + ------------------------ Clock Correction Attributes ------------------ + + CLK_CORRECT_USE_0 => TRUE, + CLK_COR_ADJ_LEN_0 => 4, + CLK_COR_DET_LEN_0 => 4, + CLK_COR_INSERT_IDLE_FLAG_0 => FALSE, + CLK_COR_KEEP_IDLE_0 => FALSE, + CLK_COR_MAX_LAT_0 => 48, + CLK_COR_MIN_LAT_0 => 36, + CLK_COR_PRECEDENCE_0 => TRUE, + CLK_COR_REPEAT_WAIT_0 => 0, + CLK_COR_SEQ_1_1_0 => "0110111100", + CLK_COR_SEQ_1_2_0 => "0100011100", + CLK_COR_SEQ_1_3_0 => "0100011100", + CLK_COR_SEQ_1_4_0 => "0100011100", + CLK_COR_SEQ_1_ENABLE_0 => "1111", + CLK_COR_SEQ_2_1_0 => "0000000000", + CLK_COR_SEQ_2_2_0 => "0000000000", + CLK_COR_SEQ_2_3_0 => "0000000000", + CLK_COR_SEQ_2_4_0 => "0000000000", + CLK_COR_SEQ_2_ENABLE_0 => "0000", + CLK_COR_SEQ_2_USE_0 => FALSE, + RX_DECODE_SEQ_MATCH_0 => TRUE, + + CLK_CORRECT_USE_1 => TRUE, + CLK_COR_ADJ_LEN_1 => 4, + CLK_COR_DET_LEN_1 => 4, + CLK_COR_INSERT_IDLE_FLAG_1 => FALSE, + CLK_COR_KEEP_IDLE_1 => FALSE, + CLK_COR_MAX_LAT_1 => 48, + CLK_COR_MIN_LAT_1 => 36, + CLK_COR_PRECEDENCE_1 => TRUE, + CLK_COR_REPEAT_WAIT_1 => 0, + CLK_COR_SEQ_1_1_1 => "1101111100", + CLK_COR_SEQ_1_2_1 => "1000111100", + CLK_COR_SEQ_1_3_1 => "1000111100", + CLK_COR_SEQ_1_4_1 => "1000111100", + CLK_COR_SEQ_1_ENABLE_1 => "1111", + CLK_COR_SEQ_2_1_1 => "0000000000", + CLK_COR_SEQ_2_2_1 => "0000000000", + CLK_COR_SEQ_2_3_1 => "0000000000", + CLK_COR_SEQ_2_4_1 => "0000000000", + CLK_COR_SEQ_2_ENABLE_1 => "0000", + CLK_COR_SEQ_2_USE_1 => FALSE, + RX_DECODE_SEQ_MATCH_1 => TRUE, + + ------------------------ Channel Bonding Attributes ------------------- + + CB2_INH_CC_PERIOD_0 => 8, + CHAN_BOND_KEEP_ALIGN_0 => FALSE, + CHAN_BOND_1_MAX_SKEW_0 => 1, + CHAN_BOND_2_MAX_SKEW_0 => 1, + CHAN_BOND_LEVEL_0 => 0, + CHAN_BOND_MODE_0 => "OFF", + CHAN_BOND_SEQ_1_1_0 => "0000000000", + CHAN_BOND_SEQ_1_2_0 => "0000000000", + CHAN_BOND_SEQ_1_3_0 => "0000000000", + CHAN_BOND_SEQ_1_4_0 => "0000000000", + CHAN_BOND_SEQ_1_ENABLE_0 => "0000", + CHAN_BOND_SEQ_2_1_0 => "0000000000", + CHAN_BOND_SEQ_2_2_0 => "0000000000", + CHAN_BOND_SEQ_2_3_0 => "0000000000", + CHAN_BOND_SEQ_2_4_0 => "0000000000", + CHAN_BOND_SEQ_2_ENABLE_0 => "0000", + CHAN_BOND_SEQ_2_USE_0 => FALSE, + CHAN_BOND_SEQ_LEN_0 => 1, + PCI_EXPRESS_MODE_0 => FALSE, + + CB2_INH_CC_PERIOD_1 => 8, + CHAN_BOND_KEEP_ALIGN_1 => FALSE, + CHAN_BOND_1_MAX_SKEW_1 => 1, + CHAN_BOND_2_MAX_SKEW_1 => 1, + CHAN_BOND_LEVEL_1 => 0, + CHAN_BOND_MODE_1 => "OFF", + CHAN_BOND_SEQ_1_1_1 => "0000000000", + CHAN_BOND_SEQ_1_2_1 => "0000000000", + CHAN_BOND_SEQ_1_3_1 => "0000000000", + CHAN_BOND_SEQ_1_4_1 => "0000000000", + CHAN_BOND_SEQ_1_ENABLE_1 => "0000", + CHAN_BOND_SEQ_2_1_1 => "0000000000", + CHAN_BOND_SEQ_2_2_1 => "0000000000", + CHAN_BOND_SEQ_2_3_1 => "0000000000", + CHAN_BOND_SEQ_2_4_1 => "0000000000", + CHAN_BOND_SEQ_2_ENABLE_1 => "0000", + CHAN_BOND_SEQ_2_USE_1 => FALSE, + CHAN_BOND_SEQ_LEN_1 => 1, + PCI_EXPRESS_MODE_1 => FALSE, + + -------- RX Attributes to Control Reset after Electrical Idle ------ + + RX_EN_IDLE_HOLD_DFE_0 => TRUE, + RX_EN_IDLE_RESET_BUF_0 => TRUE, + RX_IDLE_HI_CNT_0 => "1000", + RX_IDLE_LO_CNT_0 => "0000", + RX_EN_IDLE_HOLD_DFE_1 => TRUE, + RX_EN_IDLE_RESET_BUF_1 => TRUE, + RX_IDLE_HI_CNT_1 => "1000", + RX_IDLE_LO_CNT_1 => "0000", + CDR_PH_ADJ_TIME => "01010", + RX_EN_IDLE_RESET_FR => TRUE, + RX_EN_IDLE_HOLD_CDR => FALSE, + RX_EN_IDLE_RESET_PH => TRUE, + + ------------------ RX Attributes for PCI Express/SATA --------------- + + RX_STATUS_FMT_0 => "PCIE", + SATA_BURST_VAL_0 => "100", + SATA_IDLE_VAL_0 => "100", + SATA_MAX_BURST_0 => 7, + SATA_MAX_INIT_0 => 22, + SATA_MAX_WAKE_0 => 7, + SATA_MIN_BURST_0 => 4, + SATA_MIN_INIT_0 => 12, + SATA_MIN_WAKE_0 => 4, + TRANS_TIME_FROM_P2_0 => x"003C", + TRANS_TIME_NON_P2_0 => x"0019", + TRANS_TIME_TO_P2_0 => x"0064", + + RX_STATUS_FMT_1 => "PCIE", + SATA_BURST_VAL_1 => "100", + SATA_IDLE_VAL_1 => "100", + SATA_MAX_BURST_1 => 7, + SATA_MAX_INIT_1 => 22, + SATA_MAX_WAKE_1 => 7, + SATA_MIN_BURST_1 => 4, + SATA_MIN_INIT_1 => 12, + SATA_MIN_WAKE_1 => 4, + TRANS_TIME_FROM_P2_1 => x"003C", + TRANS_TIME_NON_P2_1 => x"0019", + TRANS_TIME_TO_P2_1 => x"0064" + + ) port map ( + + ------------------------ Loopback and Powerdown Ports ---------------------- + LOOPBACK0(0) => '0', + LOOPBACK0(1) => gtxLoopback, + LOOPBACK0(2) => '0', + LOOPBACK1 => "000", + RXPOWERDOWN0 => (others=>'0'), + RXPOWERDOWN1 => (others=>'0'), + TXPOWERDOWN0 => (others=>'0'), + TXPOWERDOWN1 => (others=>'0'), + -------------- Receive Ports - 64b66b and 64b67b Gearbox Ports ------------- + RXDATAVALID0 => open, + RXDATAVALID1 => open, + RXGEARBOXSLIP0 => '0', + RXGEARBOXSLIP1 => '0', + RXHEADER0 => open, + RXHEADER1 => open, + RXHEADERVALID0 => open, + RXHEADERVALID1 => open, + RXSTARTOFSEQ0 => open, + RXSTARTOFSEQ1 => open, + ----------------------- Receive Ports - 8b10b Decoder ---------------------- + RXCHARISCOMMA0 => open, + RXCHARISCOMMA1 => open, + RXCHARISK0(1 downto 0) => phyRxDataK, + RXCHARISK0(3 downto 2) => open, + RXCHARISK1 => open, + RXDEC8B10BUSE0 => '1', + RXDEC8B10BUSE1 => '1', + RXDISPERR0(1 downto 0) => phyRxDispErr, + RXDISPERR0(3 downto 2) => open, + RXDISPERR1 => open, + RXNOTINTABLE0(1 downto 0) => phyRxDecErr, + RXNOTINTABLE0(3 downto 2) => open, + RXNOTINTABLE1 => open, + RXRUNDISP0 => open, + RXRUNDISP1 => open, + ------------------- Receive Ports - Channel Bonding Ports ------------------ + RXCHANBONDSEQ0 => open, + RXCHANBONDSEQ1 => open, + RXCHBONDI0 => (others=>'0'), + RXCHBONDI1 => (others=>'0'), + RXCHBONDO0 => open, + RXCHBONDO1 => open, + RXENCHANSYNC0 => '0', + RXENCHANSYNC1 => '0', + ------------------- Receive Ports - Clock Correction Ports ----------------- + RXCLKCORCNT0 => open, + RXCLKCORCNT1 => open, + --------------- Receive Ports - Comma Detection and Alignment -------------- + RXBYTEISALIGNED0 => open, + RXBYTEISALIGNED1 => open, + RXBYTEREALIGN0 => open, + RXBYTEREALIGN1 => open, + RXCOMMADET0 => open, + RXCOMMADET1 => open, + RXCOMMADETUSE0 => '1', + RXCOMMADETUSE1 => '1', + RXENMCOMMAALIGN0 => '1', + RXENMCOMMAALIGN1 => '1', + RXENPCOMMAALIGN0 => '1', + RXENPCOMMAALIGN1 => '1', + RXSLIDE0 => '0', + RXSLIDE1 => '0', + ----------------------- Receive Ports - PRBS Detection --------------------- + PRBSCNTRESET0 => '0', + PRBSCNTRESET1 => '0', + RXENPRBSTST0 => (others=>'0'), + RXENPRBSTST1 => (others=>'0'), + RXPRBSERR0 => open, + RXPRBSERR1 => open, + ------------------- Receive Ports - RX Data Path interface ----------------- + RXDATA0(15 downto 0) => phyRxData, + RXDATA0(31 downto 16) => open, + RXDATA1 => open, + RXDATAWIDTH0 => "01", + RXDATAWIDTH1 => "01", + RXRECCLK0 => intRxRecClk, + RXRECCLK1 => open, + RXRESET0 => phyRxReset, + RXRESET1 => '0', + RXUSRCLK0 => pgpClk, + RXUSRCLK1 => pgpClk, + RXUSRCLK20 => pgpClk, + RXUSRCLK21 => pgpClk, + ------------ Receive Ports - RX Decision Feedback Equalizer(DFE) ----------- + DFECLKDLYADJ0 => (others=>'0'), + DFECLKDLYADJ1 => (others=>'0'), + DFECLKDLYADJMONITOR0 => open, + DFECLKDLYADJMONITOR1 => open, + DFEEYEDACMONITOR0 => open, + DFEEYEDACMONITOR1 => open, + DFESENSCAL0 => open, + DFESENSCAL1 => open, + DFETAP10 => (others=>'0'), + DFETAP11 => (others=>'0'), + DFETAP1MONITOR0 => open, + DFETAP1MONITOR1 => open, + DFETAP20 => (others=>'0'), + DFETAP21 => (others=>'0'), + DFETAP2MONITOR0 => open, + DFETAP2MONITOR1 => open, + DFETAP30 => (others=>'0'), + DFETAP31 => (others=>'0'), + DFETAP3MONITOR0 => open, + DFETAP3MONITOR1 => open, + DFETAP40 => (others=>'0'), + DFETAP41 => (others=>'0'), + DFETAP4MONITOR0 => open, + DFETAP4MONITOR1 => open, + ------- Receive Ports - RX Driver,OOB signalling,Coupling and Eq.,CDR ------ + RXCDRRESET0 => phyRxCdrReset, + RXCDRRESET1 => '0', + RXELECIDLE0 => phyRxElecIdle, + RXELECIDLE1 => open, + RXENEQB0 => '0', + RXENEQB1 => '0', + RXEQMIX0 => (others=>'0'), + RXEQMIX1 => (others=>'0'), + RXEQPOLE0 => (others=>'0'), + RXEQPOLE1 => (others=>'0'), + RXN0 => gtxRxN, + RXN1 => '1', + RXP0 => gtxRxP, + RXP1 => '0', + -------- Receive Ports - RX Elastic Buffer and Phase Alignment Ports ------- + RXBUFRESET0 => '0', + RXBUFRESET1 => '0', + RXBUFSTATUS0 => phyRxBuffStatus, + RXBUFSTATUS1 => open, + RXCHANISALIGNED0 => open, + RXCHANISALIGNED1 => open, + RXCHANREALIGN0 => open, + RXCHANREALIGN1 => open, + RXENPMAPHASEALIGN0 => '0', + RXENPMAPHASEALIGN1 => '0', + RXPMASETPHASE0 => '0', + RXPMASETPHASE1 => '0', + RXSTATUS0 => open, + RXSTATUS1 => open, + --------------- Receive Ports - RX Loss-of-sync State Machine -------------- + RXLOSSOFSYNC0 => open, + RXLOSSOFSYNC1 => open, + ---------------------- Receive Ports - RX Oversampling --------------------- + RXENSAMPLEALIGN0 => '0', + RXENSAMPLEALIGN1 => '0', + RXOVERSAMPLEERR0 => open, + RXOVERSAMPLEERR1 => open, + -------------- Receive Ports - RX Pipe Control for PCI Express ------------- + PHYSTATUS0 => open, + PHYSTATUS1 => open, + RXVALID0 => open, + RXVALID1 => open, + ----------------- Receive Ports - RX Polarity Control Ports ---------------- + RXPOLARITY0 => phyRxPolarity(0), + RXPOLARITY1 => '0', + ------------- Shared Ports - Dynamic Reconfiguration Port (DRP) ------------ + DADDR => (others=>'0'), + DCLK => '0', + DEN => '0', + DI => (others=>'0'), + DO => open, + DRDY => open, + DWE => '0', + --------------------- Shared Ports - Tile and PLL Ports -------------------- + CLKIN => gtxClkIn, + GTXRESET => pgpReset, + GTXTEST => "10000000000000", + INTDATAWIDTH => '1', + PLLLKDET => phyLockDetect, + PLLLKDETEN => '1', + PLLPOWERDOWN => '0', + REFCLKOUT => tmpRefClkOut, + REFCLKPWRDNB => '1', + RESETDONE0 => phyRstDone, + RESETDONE1 => open, + -------------- Transmit Ports - 64b66b and 64b67b Gearbox Ports ------------ + TXGEARBOXREADY0 => open, + TXGEARBOXREADY1 => open, + TXHEADER0 => (others=>'0'), + TXHEADER1 => (others=>'0'), + TXSEQUENCE0 => (others=>'0'), + TXSEQUENCE1 => (others=>'0'), + TXSTARTSEQ0 => '0', + TXSTARTSEQ1 => '0', + ---------------- Transmit Ports - 8b10b Encoder Control Ports -------------- + TXBYPASS8B10B0 => (others=>'0'), + TXBYPASS8B10B1 => (others=>'0'), + TXCHARDISPMODE0 => (others=>'0'), + TXCHARDISPMODE1 => (others=>'0'), + TXCHARDISPVAL0 => (others=>'0'), + TXCHARDISPVAL1 => (others=>'0'), + TXCHARISK0(1 downto 0) => phyTxDataK, + TXCHARISK0(3 downto 2) => (others=>'0'), + TXCHARISK1 => (others=>'0'), + TXENC8B10BUSE0 => '1', + TXENC8B10BUSE1 => '1', + TXKERR0 => open, + TXKERR1 => open, + TXRUNDISP0 => open, + TXRUNDISP1 => open, + ------------- Transmit Ports - TX Buffering and Phase Alignment ------------ + TXBUFSTATUS0 => phyTxBuffStatus, + TXBUFSTATUS1 => open, + ------------------ Transmit Ports - TX Data Path interface ----------------- + TXDATA0(15 downto 0) => phyTxData, + TXDATA0(31 downto 16) => (others=>'0'), + TXDATA1 => (others=>'0'), + TXDATAWIDTH0 => "01", + TXDATAWIDTH1 => "01", + TXOUTCLK0 => open, + TXOUTCLK1 => open, + TXRESET0 => phyTxReset, + TXRESET1 => '0', + TXUSRCLK0 => pgpClk, + TXUSRCLK1 => pgpClk, + TXUSRCLK20 => pgpClk, + TXUSRCLK21 => pgpClk, + --------------- Transmit Ports - TX Driver and OOB signalling -------------- + TXBUFDIFFCTRL0 => "100", -- 800mV + TXBUFDIFFCTRL1 => "100", + TXDIFFCTRL0 => "100", + TXDIFFCTRL1 => "100", + TXINHIBIT0 => '0', + TXINHIBIT1 => '0', + TXN0 => gtxTxN, + TXN1 => open, + TXP0 => gtxTxP, + TXP1 => open, + TXPREEMPHASIS0 => "0011", -- 4.5% + TXPREEMPHASIS1 => "0011", + -------- Transmit Ports - TX Elastic Buffer and Phase Alignment Ports ------ + TXENPMAPHASEALIGN0 => '0', + TXENPMAPHASEALIGN1 => '0', + TXPMASETPHASE0 => '0', + TXPMASETPHASE1 => '0', + --------------------- Transmit Ports - TX PRBS Generator ------------------- + TXENPRBSTST0 => (others=>'0'), + TXENPRBSTST1 => (others=>'0'), + -------------------- Transmit Ports - TX Polarity Control ------------------ + TXPOLARITY0 => '0', + TXPOLARITY1 => '0', + ----------------- Transmit Ports - TX Ports for PCI Express ---------------- + TXDETECTRX0 => '0', + TXDETECTRX1 => '0', + TXELECIDLE0 => '0', + TXELECIDLE1 => '0', + --------------------- Transmit Ports - TX Ports for SATA ------------------- + TXCOMSTART0 => '0', + TXCOMSTART1 => '0', + TXCOMTYPE0 => '0', + TXCOMTYPE1 => '0' + ); + + -- Global Buffer For Ref Clock Output + U_RefClkBuff: BUFG port map ( + O => gtxRefClkOut, + I => tmpRefClkOut + ); + gtxRxRecClk <= intRxRecClk; + +end Pgp2Gtx16; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2Gtx16B.vhd b/rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2Gtx16B.vhd new file mode 100755 index 00000000..e2c3436c --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2Gtx16B.vhd @@ -0,0 +1,953 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, GTX Wrapper, Port B +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2Gtx16B.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 10/13/2010 +------------------------------------------------------------------------------- +-- Description: +-- VHDL source file containing the PGP, GTX and CRC blocks. +-- This module also contains the logic to control the reset of the GTX. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 10/13/2010: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; +use work.Pgp2GtxPackage.all; +use work.Pgp2CorePackage.all; +library UNISIM; +use UNISIM.VCOMPONENTS.ALL; + + +entity Pgp2Gtx16B is + generic ( + EnShortCells : integer := 1; -- Enable short non-EOF cells + VcInterleave : integer := 1 -- Interleave Frames + ); + port ( + + -- System clock, reset & control + pgpClk : in std_logic; -- Pgp master clock + pgpReset : in std_logic; -- Synchronous reset input + pgpFlush : in std_logic; -- Frame sync flush + + -- PLL Reset Control + pllTxRst : in std_logic; -- Reset transmit PLL logic + pllRxRst : in std_logic; -- Reset receive PLL logic + + -- PLL Lock Status + pllRxReady : out std_logic; -- MGT Receive logic is ready + pllTxReady : out std_logic; -- MGT Transmit logic is ready + + -- Sideband data + pgpRemData : out std_logic_vector(7 downto 0); -- Far end side User Data + pgpLocData : in std_logic_vector(7 downto 0); -- Far end side User Data + + -- Opcode Transmit Interface + pgpTxOpCodeEn : in std_logic; -- Opcode receive enable + pgpTxOpCode : in std_logic_vector(7 downto 0); -- Opcode receive value + + -- Opcode Receive Interface + pgpRxOpCodeEn : out std_logic; -- Opcode receive enable + pgpRxOpCode : out std_logic_vector(7 downto 0); -- Opcode receive value + + -- Link status + pgpLocLinkReady : out std_logic; -- Local Link is ready + pgpRemLinkReady : out std_logic; -- Far end side has link + + -- Error Flags, one pulse per event + pgpRxCellError : out std_logic; -- A cell error has occured + pgpRxLinkDown : out std_logic; -- A link down event has occured + pgpRxLinkError : out std_logic; -- A link error has occured + + -- Frame Transmit Interface, VC 0 + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc0FrameTxReady : out std_logic; -- PGP is ready + vc0FrameTxSOF : in std_logic; -- User frame data start of frame + vc0FrameTxEOF : in std_logic; -- User frame data end of frame + vc0FrameTxEOFE : in std_logic; -- User frame data error + vc0FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc0LocBuffAFull : in std_logic; -- Local buffer almost full + vc0LocBuffFull : in std_logic; -- Local buffer full + + -- Frame Transmit Interface, VC 1 + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxReady : out std_logic; -- PGP is ready + vc1FrameTxSOF : in std_logic; -- User frame data start of frame + vc1FrameTxEOF : in std_logic; -- User frame data end of frame + vc1FrameTxEOFE : in std_logic; -- User frame data error + vc1FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc1LocBuffAFull : in std_logic; -- Local buffer almost full + vc1LocBuffFull : in std_logic; -- Local buffer full + + -- Frame Transmit Interface, VC 2 + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxReady : out std_logic; -- PGP is ready + vc2FrameTxSOF : in std_logic; -- User frame data start of frame + vc2FrameTxEOF : in std_logic; -- User frame data end of frame + vc2FrameTxEOFE : in std_logic; -- User frame data error + vc2FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc2LocBuffAFull : in std_logic; -- Local buffer almost full + vc2LocBuffFull : in std_logic; -- Local buffer full + + -- Frame Transmit Interface, VC 3 + vc3FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxReady : out std_logic; -- PGP is ready + vc3FrameTxSOF : in std_logic; -- User frame data start of frame + vc3FrameTxEOF : in std_logic; -- User frame data end of frame + vc3FrameTxEOFE : in std_logic; -- User frame data error + vc3FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc3LocBuffAFull : in std_logic; -- Local buffer almost full + vc3LocBuffFull : in std_logic; -- Local buffer full + + -- Common Frame Receive Interface For All VCs + vcFrameRxSOF : out std_logic; -- PGP frame data start of frame + vcFrameRxEOF : out std_logic; -- PGP frame data end of frame + vcFrameRxEOFE : out std_logic; -- PGP frame data error + vcFrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + + -- Frame Receive Interface, VC 0 + vc0FrameRxValid : out std_logic; -- PGP frame data is valid + vc0RemBuffAFull : out std_logic; -- Remote buffer almost full + vc0RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 1 + vc1FrameRxValid : out std_logic; -- PGP frame data is valid + vc1RemBuffAFull : out std_logic; -- Remote buffer almost full + vc1RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 2 + vc2FrameRxValid : out std_logic; -- PGP frame data is valid + vc2RemBuffAFull : out std_logic; -- Remote buffer almost full + vc2RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 3 + vc3FrameRxValid : out std_logic; -- PGP frame data is valid + vc3RemBuffAFull : out std_logic; -- Remote buffer almost full + vc3RemBuffFull : out std_logic; -- Remote buffer full + + -- GTX Status & Control Signals + gtxLoopback : in std_logic; -- GTX Serial Loopback Control + + -- MGT Signals Clock & IO Signals + gtxClkIn : in std_logic; -- GTX Reference Clock In + gtxRefClkOut : out std_logic; -- GTX Reference Clock Output + gtxRxRecClk : out std_logic; -- GTX Rx Recovered Clock + gtxRxN : in std_logic; -- GTX Serial Receive Negative + gtxRxP : in std_logic; -- GTX Serial Receive Positive + gtxTxN : out std_logic; -- GTX Serial Transmit Negative + gtxTxP : out std_logic; -- GTX Serial Transmit Positive + + -- Debug + debug : out std_logic_vector(63 downto 0) + ); + +end Pgp2Gtx16B; + + +-- Define architecture +architecture Pgp2Gtx16B of Pgp2Gtx16B is + + -- Local Signals + signal crcTxIn : std_logic_vector(15 downto 0); + signal crcTxInGtx : std_logic_vector(31 downto 0); + signal crcTxInit : std_logic; + signal crcTxRst : std_logic; + signal crcTxValid : std_logic; + signal crcTxWidth : std_logic_vector(2 downto 0); + signal crcTxOut : std_logic_vector(31 downto 0); + signal crcTxOutGtx : std_logic_vector(31 downto 0); + signal crcRxIn : std_logic_vector(15 downto 0); + signal crcRxInGtx : std_logic_vector(31 downto 0); + signal crcRxInit : std_logic; + signal crcRxRst : std_logic; + signal crcRxValid : std_logic; + signal crcRxWidth : std_logic_vector(2 downto 0); + signal crcRxOut : std_logic_vector(31 downto 0); + signal crcRxOutGtx : std_logic_vector(31 downto 0); + signal phyRxPolarity : std_logic_vector(0 downto 0); + signal phyRxData : std_logic_vector(15 downto 0); + signal phyRxDataK : std_logic_vector(1 downto 0); + signal phyTxData : std_logic_vector(15 downto 0); + signal phyTxDataK : std_logic_vector(1 downto 0); + signal phyRxDispErr : std_logic_vector(1 downto 0); + signal phyRxDecErr : std_logic_vector(1 downto 0); + signal phyRxReady : std_logic; + signal phyRxInit : std_logic; + signal phyTxReady : std_logic; + signal phyRxReset : std_logic; + signal phyRxElecIdle : std_logic; + signal phyRxCdrReset : std_logic; + signal phyRstDone : std_logic; + signal phyRxBuffStatus : std_logic_vector(2 downto 0); + signal phyTxReset : std_logic; + signal phyTxBuffStatus : std_logic_vector(1 downto 0); + signal phyLockDetect : std_logic; + signal intTxRst : std_logic; + signal intRxRst : std_logic; + signal pgpRxLinkReady : std_logic; + signal pgpTxLinkReady : std_logic; + signal intRxRecClk : std_logic; + signal tmpRefClkOut : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + + -- PGP RX Block + U_Pgp2Rx: Pgp2CorePackage.Pgp2Rx + generic map ( + RxLaneCnt => 1, + EnShortCells => EnShortCells + ) port map ( + pgpRxClk => pgpClk, + pgpRxReset => pgpReset, + pgpRxFlush => pgpFlush, + pgpRxLinkReady => pgpRxLinkReady, + pgpRxCellError => pgpRxCellError, + pgpRxLinkDown => pgpRxLinkDown, + pgpRxLinkError => pgpRxLinkError, + pgpRxOpCodeEn => pgpRxOpCodeEn, + pgpRxOpCode => pgpRxOpCode, + pgpRemLinkReady => pgpRemLinkReady, + pgpRemData => pgpRemData, + vcFrameRxSOF => vcFrameRxSOF, + vcFrameRxEOF => vcFrameRxEOF, + vcFrameRxEOFE => vcFrameRxEOFE, + vcFrameRxData => vcFrameRxData, + vc0FrameRxValid => vc0FrameRxValid, + vc0RemBuffAFull => vc0RemBuffAFull, + vc0RemBuffFull => vc0RemBuffFull, + vc1FrameRxValid => vc1FrameRxValid, + vc1RemBuffAFull => vc1RemBuffAFull, + vc1RemBuffFull => vc1RemBuffFull, + vc2FrameRxValid => vc2FrameRxValid, + vc2RemBuffAFull => vc2RemBuffAFull, + vc2RemBuffFull => vc2RemBuffFull, + vc3FrameRxValid => vc3FrameRxValid, + vc3RemBuffAFull => vc3RemBuffAFull, + vc3RemBuffFull => vc3RemBuffFull, + phyRxPolarity => phyRxPolarity, + phyRxData => phyRxData, + phyRxDataK => phyRxDataK, + phyRxDispErr => phyRxDispErr, + phyRxDecErr => phyRxDecErr, + phyRxReady => phyRxReady, + phyRxInit => phyRxInit, + crcRxIn => crcRxIn, + crcRxWidth => open, + crcRxInit => crcRxInit, + crcRxValid => crcRxValid, + crcRxOut => crcRxOut, + debug => debug + ); + + + -- PGP TX Block + U_Pgp2Tx: Pgp2CorePackage.Pgp2Tx + generic map ( + TxLaneCnt => 1, + VcInterleave => VcInterleave + ) port map ( + pgpTxClk => pgpClk, + pgpTxReset => pgpReset, + pgpTxFlush => pgpFlush, + pgpTxLinkReady => pgpTxLinkReady, + pgpTxOpCodeEn => pgpTxOpCodeEn, + pgpTxOpCode => pgpTxOpCode, + pgpLocLinkReady => pgpRxLinkReady, + pgpLocData => pgpLocData, + vc0FrameTxValid => vc0FrameTxValid, + vc0FrameTxReady => vc0FrameTxReady, + vc0FrameTxSOF => vc0FrameTxSOF, + vc0FrameTxEOF => vc0FrameTxEOF, + vc0FrameTxEOFE => vc0FrameTxEOFE, + vc0FrameTxData => vc0FrameTxData, + vc0LocBuffAFull => vc0LocBuffAFull, + vc0LocBuffFull => vc0LocBuffFull, + vc1FrameTxValid => vc1FrameTxValid, + vc1FrameTxReady => vc1FrameTxReady, + vc1FrameTxSOF => vc1FrameTxSOF, + vc1FrameTxEOF => vc1FrameTxEOF, + vc1FrameTxEOFE => vc1FrameTxEOFE, + vc1FrameTxData => vc1FrameTxData, + vc1LocBuffAFull => vc1LocBuffAFull, + vc1LocBuffFull => vc1LocBuffFull, + vc2FrameTxValid => vc2FrameTxValid, + vc2FrameTxReady => vc2FrameTxReady, + vc2FrameTxSOF => vc2FrameTxSOF, + vc2FrameTxEOF => vc2FrameTxEOF, + vc2FrameTxEOFE => vc2FrameTxEOFE, + vc2FrameTxData => vc2FrameTxData, + vc2LocBuffAFull => vc2LocBuffAFull, + vc2LocBuffFull => vc2LocBuffFull, + vc3FrameTxValid => vc3FrameTxValid, + vc3FrameTxReady => vc3FrameTxReady, + vc3FrameTxSOF => vc3FrameTxSOF, + vc3FrameTxEOF => vc3FrameTxEOF, + vc3FrameTxEOFE => vc3FrameTxEOFE, + vc3FrameTxData => vc3FrameTxData, + vc3LocBuffAFull => vc3LocBuffAFull, + vc3LocBuffFull => vc3LocBuffFull, + phyTxData => phyTxData, + phyTxDataK => phyTxDataK, + phyTxReady => phyTxReady, + crcTxIn => crcTxIn, + crcTxInit => crcTxInit, + crcTxValid => crcTxValid, + crcTxOut => crcTxOut, + debug => open + ); + + + -- Adapt CRC data width flag + crcTxWidth <= "001"; + crcRxWidth <= "001"; + crcRxRst <= intRxRst or crcRxInit; + crcTxRst <= intTxRst or crcTxInit; + + -- Pass CRC data in on proper bits + crcTxInGtx(31 downto 24) <= crcTxIn(7 downto 0); + crcTxInGtx(23 downto 16) <= crcTxIn(15 downto 8); + crcTxInGtx(15 downto 0) <= (others=>'0'); + crcRxInGtx(31 downto 24) <= crcRxIn(7 downto 0); + crcRxInGtx(23 downto 16) <= crcRxIn(15 downto 8); + crcRxInGtx(15 downto 0) <= (others=>'0'); + + -- Pll Resets + intTxRst <= pllTxRst or pgpReset; + intRxRst <= pllRxRst or pgpReset; + + -- PLL Lock + pllRxReady <= phyRxReady; + pllTxReady <= phyTxReady; + + -- Link Ready + pgpLocLinkReady <= pgpRxLinkReady and pgpTxLinkReady; + + -- Invert Output CRC + crcRxOut <= not crcRxOutGtx; + crcTxOut <= not crcTxOutGtx; + + + -- TX CRC BLock + Tx_CRC: CRC32 + generic map( + CRC_INIT => x"FFFFFFFF" + ) port map( + CRCOUT => crcTxOutGtx, + CRCCLK => pgpClk, + CRCDATAVALID => crcTxValid, + CRCDATAWIDTH => crcTxWidth, + CRCIN => crcTxInGtx, + CRCRESET => crcTxRst + ); + + + -- RX CRC BLock + Rx_CRC: CRC32 + generic map( + CRC_INIT => x"FFFFFFFF" + ) port map( + CRCOUT => crcRxOutGtx, + CRCCLK => pgpClk, + CRCDATAVALID => crcRxValid, + CRCDATAWIDTH => crcRxWidth, + CRCIN => crcRxInGtx, + CRCRESET => crcRxRst + ); + + + -- RX Reset Control + U_Pgp2GtxRxRst: Pgp2GtxPackage.Pgp2GtxRxRst + port map ( + gtxRxClk => pgpClk, + gtxRxRst => intRxRst, + gtxRxReady => phyRxReady, + gtxRxInit => phyRxInit, + gtxLockDetect => phyLockDetect, + gtxRxElecIdle => phyRxElecIdle, + gtxRxBuffStatus => phyRxBuffStatus, + gtxRstDone => phyRstDone, + gtxRxReset => phyRxReset, + gtxRxCdrReset => phyRxCdrReset + ); + + + -- TX Reset Control + U_Pgp2GtxTxRst: Pgp2GtxPackage.Pgp2GtxTxRst + port map ( + gtxTxClk => pgpClk, + gtxTxRst => intTxRst, + gtxTxReady => phyTxReady, + gtxLockDetect => phyLockDetect, + gtxTxBuffStatus => phyTxBuffStatus, + gtxRstDone => phyRstDone, + gtxTxReset => phyTxReset + ); + + + ----------------------------- GTX_DUAL Instance -------------------------- + UGtxDual:GTX_DUAL + generic map ( + + --_______________________ Simulation-Only Attributes ___________________ + + SIM_RECEIVER_DETECT_PASS_0 => TRUE, + SIM_RECEIVER_DETECT_PASS_1 => TRUE, + SIM_MODE => "FAST", + SIM_GTXRESET_SPEEDUP => 1, + SIM_PLL_PERDIV2 => x"140", + + --___________________________ Shared Attributes ________________________ + + -------------------------- Tile and PLL Attributes --------------------- + + CLK25_DIVIDER => 10, + CLKINDC_B => TRUE, + OOB_CLK_DIVIDER => 6, + OVERSAMPLE_MODE => FALSE, + PLL_DIVSEL_FB => 2, + PLL_DIVSEL_REF => 1, + CLKRCV_TRST => TRUE, + PLL_COM_CFG => x"21680a", + PLL_CP_CFG => x"00", + PLL_FB_DCCEN => FALSE, + PLL_LKDET_CFG => "101", + PLL_TDCC_CFG => "000", + PMA_COM_CFG => x"000000000000000000", + + --____________________ Transmit Interface Attributes ___________________ + + ------------------- TX Buffering and Phase Alignment ------------------- + + TX_BUFFER_USE_0 => TRUE, + TX_XCLK_SEL_0 => "TXOUT", + TXRX_INVERT_0 => "011", + + TX_BUFFER_USE_1 => TRUE, + TX_XCLK_SEL_1 => "TXOUT", + TXRX_INVERT_1 => "011", + + --------------------- TX Gearbox Settings ----------------------------- + + GEARBOX_ENDEC_0 => "000", + TXGEARBOX_USE_0 => FALSE, + + GEARBOX_ENDEC_1 => "000", + TXGEARBOX_USE_1 => FALSE, + + --------------------- TX Serial Line Rate settings --------------------- + + PLL_TXDIVSEL_OUT_0 => 1, + PLL_TXDIVSEL_OUT_1 => 1, + + --------------------- TX Driver and OOB signalling -------------------- + + CM_TRIM_0 => "10", + PMA_TX_CFG_0 => x"80082", + TX_DETECT_RX_CFG_0 => x"1832", + TX_IDLE_DELAY_0 => "010", + CM_TRIM_1 => "10", + PMA_TX_CFG_1 => x"80082", + TX_DETECT_RX_CFG_1 => x"1832", + TX_IDLE_DELAY_1 => "010", + + ------------------ TX Pipe Control for PCI Express/SATA --------------- + + COM_BURST_VAL_0 => "1111", + COM_BURST_VAL_1 => "1111", + + --_______________________ Receive Interface Attributes ________________ + + ------------ RX Driver,OOB signalling,Coupling and Eq,CDR ------------- + + AC_CAP_DIS_0 => TRUE, + OOBDETECT_THRESHOLD_0 => "111", + PMA_CDR_SCAN_0 => x"640403a", + PMA_RX_CFG_0 => x"0f44088", + RCV_TERM_GND_0 => FALSE, + RCV_TERM_VTTRX_0 => TRUE, + TERMINATION_IMP_0 => 50, + AC_CAP_DIS_1 => TRUE, + OOBDETECT_THRESHOLD_1 => "111", + PMA_CDR_SCAN_1 => x"640403a", + PMA_RX_CFG_1 => x"0f44088", + RCV_TERM_GND_1 => FALSE, + RCV_TERM_VTTRX_1 => TRUE, + TERMINATION_IMP_1 => 50, + TERMINATION_CTRL => "10100", + TERMINATION_OVRD => FALSE, + + ---------------- RX Decision Feedback Equalizer(DFE) ---------------- + + DFE_CFG_0 => "1001111011", + DFE_CFG_1 => "1001111011", + DFE_CAL_TIME => "00110", + + --------------------- RX Serial Line Rate Attributes ------------------ + + PLL_RXDIVSEL_OUT_0 => 1, + PLL_SATA_0 => FALSE, + PLL_RXDIVSEL_OUT_1 => 1, + PLL_SATA_1 => FALSE, + + ----------------------- PRBS Detection Attributes --------------------- + + PRBS_ERR_THRESHOLD_0 => x"00000001", + PRBS_ERR_THRESHOLD_1 => x"00000001", + + ---------------- Comma Detection and Alignment Attributes ------------- + + ALIGN_COMMA_WORD_0 => 2, + COMMA_10B_ENABLE_0 => "1111111111", + COMMA_DOUBLE_0 => FALSE, + DEC_MCOMMA_DETECT_0 => TRUE, + DEC_PCOMMA_DETECT_0 => TRUE, + DEC_VALID_COMMA_ONLY_0 => FALSE, + MCOMMA_10B_VALUE_0 => "1010000011", + MCOMMA_DETECT_0 => TRUE, + PCOMMA_10B_VALUE_0 => "0101111100", + PCOMMA_DETECT_0 => TRUE, + RX_SLIDE_MODE_0 => "PCS", + + ALIGN_COMMA_WORD_1 => 2, + COMMA_10B_ENABLE_1 => "1111111111", + COMMA_DOUBLE_1 => FALSE, + DEC_MCOMMA_DETECT_1 => TRUE, + DEC_PCOMMA_DETECT_1 => TRUE, + DEC_VALID_COMMA_ONLY_1 => FALSE, + MCOMMA_10B_VALUE_1 => "1010000011", + MCOMMA_DETECT_1 => TRUE, + PCOMMA_10B_VALUE_1 => "0101111100", + PCOMMA_DETECT_1 => TRUE, + RX_SLIDE_MODE_1 => "PCS", + + ------------------ RX Loss-of-sync State Machine Attributes ----------- + + RX_LOSS_OF_SYNC_FSM_0 => FALSE, + RX_LOS_INVALID_INCR_0 => 8, + RX_LOS_THRESHOLD_0 => 128, + RX_LOSS_OF_SYNC_FSM_1 => FALSE, + RX_LOS_INVALID_INCR_1 => 8, + RX_LOS_THRESHOLD_1 => 128, + + --------------------- RX Gearbox Settings ----------------------------- + + RXGEARBOX_USE_0 => FALSE, + RXGEARBOX_USE_1 => FALSE, + + -------------- RX Elastic Buffer and Phase alignment Attributes ------- + + PMA_RXSYNC_CFG_0 => x"00", + RX_BUFFER_USE_0 => TRUE, + RX_XCLK_SEL_0 => "RXREC", + PMA_RXSYNC_CFG_1 => x"00", + RX_BUFFER_USE_1 => TRUE, + RX_XCLK_SEL_1 => "RXREC", + + ------------------------ Clock Correction Attributes ------------------ + + CLK_CORRECT_USE_0 => TRUE, + CLK_COR_ADJ_LEN_0 => 4, + CLK_COR_DET_LEN_0 => 4, + CLK_COR_INSERT_IDLE_FLAG_0 => FALSE, + CLK_COR_KEEP_IDLE_0 => FALSE, + CLK_COR_MAX_LAT_0 => 48, + CLK_COR_MIN_LAT_0 => 36, + CLK_COR_PRECEDENCE_0 => TRUE, + CLK_COR_REPEAT_WAIT_0 => 0, + CLK_COR_SEQ_1_1_0 => "0110111100", + CLK_COR_SEQ_1_2_0 => "0100011100", + CLK_COR_SEQ_1_3_0 => "0100011100", + CLK_COR_SEQ_1_4_0 => "0100011100", + CLK_COR_SEQ_1_ENABLE_0 => "1111", + CLK_COR_SEQ_2_1_0 => "0000000000", + CLK_COR_SEQ_2_2_0 => "0000000000", + CLK_COR_SEQ_2_3_0 => "0000000000", + CLK_COR_SEQ_2_4_0 => "0000000000", + CLK_COR_SEQ_2_ENABLE_0 => "0000", + CLK_COR_SEQ_2_USE_0 => FALSE, + RX_DECODE_SEQ_MATCH_0 => TRUE, + + CLK_CORRECT_USE_1 => TRUE, + CLK_COR_ADJ_LEN_1 => 4, + CLK_COR_DET_LEN_1 => 4, + CLK_COR_INSERT_IDLE_FLAG_1 => FALSE, + CLK_COR_KEEP_IDLE_1 => FALSE, + CLK_COR_MAX_LAT_1 => 48, + CLK_COR_MIN_LAT_1 => 36, + CLK_COR_PRECEDENCE_1 => TRUE, + CLK_COR_REPEAT_WAIT_1 => 0, + CLK_COR_SEQ_1_1_1 => "0110111100", + CLK_COR_SEQ_1_2_1 => "0100011100", + CLK_COR_SEQ_1_3_1 => "0100011100", + CLK_COR_SEQ_1_4_1 => "0100011100", + CLK_COR_SEQ_1_ENABLE_1 => "1111", + CLK_COR_SEQ_2_1_1 => "0000000000", + CLK_COR_SEQ_2_2_1 => "0000000000", + CLK_COR_SEQ_2_3_1 => "0000000000", + CLK_COR_SEQ_2_4_1 => "0000000000", + CLK_COR_SEQ_2_ENABLE_1 => "0000", + CLK_COR_SEQ_2_USE_1 => FALSE, + RX_DECODE_SEQ_MATCH_1 => TRUE, + + ------------------------ Channel Bonding Attributes ------------------- + + CB2_INH_CC_PERIOD_0 => 8, + CHAN_BOND_KEEP_ALIGN_0 => FALSE, + CHAN_BOND_1_MAX_SKEW_0 => 1, + CHAN_BOND_2_MAX_SKEW_0 => 1, + CHAN_BOND_LEVEL_0 => 0, + CHAN_BOND_MODE_0 => "OFF", + CHAN_BOND_SEQ_1_1_0 => "0000000000", + CHAN_BOND_SEQ_1_2_0 => "0000000000", + CHAN_BOND_SEQ_1_3_0 => "0000000000", + CHAN_BOND_SEQ_1_4_0 => "0000000000", + CHAN_BOND_SEQ_1_ENABLE_0 => "0000", + CHAN_BOND_SEQ_2_1_0 => "0000000000", + CHAN_BOND_SEQ_2_2_0 => "0000000000", + CHAN_BOND_SEQ_2_3_0 => "0000000000", + CHAN_BOND_SEQ_2_4_0 => "0000000000", + CHAN_BOND_SEQ_2_ENABLE_0 => "0000", + CHAN_BOND_SEQ_2_USE_0 => FALSE, + CHAN_BOND_SEQ_LEN_0 => 1, + PCI_EXPRESS_MODE_0 => FALSE, + + CB2_INH_CC_PERIOD_1 => 8, + CHAN_BOND_KEEP_ALIGN_1 => FALSE, + CHAN_BOND_1_MAX_SKEW_1 => 1, + CHAN_BOND_2_MAX_SKEW_1 => 1, + CHAN_BOND_LEVEL_1 => 0, + CHAN_BOND_MODE_1 => "OFF", + CHAN_BOND_SEQ_1_1_1 => "0000000000", + CHAN_BOND_SEQ_1_2_1 => "0000000000", + CHAN_BOND_SEQ_1_3_1 => "0000000000", + CHAN_BOND_SEQ_1_4_1 => "0000000000", + CHAN_BOND_SEQ_1_ENABLE_1 => "0000", + CHAN_BOND_SEQ_2_1_1 => "0000000000", + CHAN_BOND_SEQ_2_2_1 => "0000000000", + CHAN_BOND_SEQ_2_3_1 => "0000000000", + CHAN_BOND_SEQ_2_4_1 => "0000000000", + CHAN_BOND_SEQ_2_ENABLE_1 => "0000", + CHAN_BOND_SEQ_2_USE_1 => FALSE, + CHAN_BOND_SEQ_LEN_1 => 1, + PCI_EXPRESS_MODE_1 => FALSE, + + -------- RX Attributes to Control Reset after Electrical Idle ------ + + RX_EN_IDLE_HOLD_DFE_0 => TRUE, + RX_EN_IDLE_RESET_BUF_0 => TRUE, + RX_IDLE_HI_CNT_0 => "1000", + RX_IDLE_LO_CNT_0 => "0000", + RX_EN_IDLE_HOLD_DFE_1 => TRUE, + RX_EN_IDLE_RESET_BUF_1 => TRUE, + RX_IDLE_HI_CNT_1 => "1000", + RX_IDLE_LO_CNT_1 => "0000", + CDR_PH_ADJ_TIME => "01010", + RX_EN_IDLE_RESET_FR => TRUE, + RX_EN_IDLE_HOLD_CDR => FALSE, + RX_EN_IDLE_RESET_PH => TRUE, + + ------------------ RX Attributes for PCI Express/SATA --------------- + + RX_STATUS_FMT_0 => "PCIE", + SATA_BURST_VAL_0 => "100", + SATA_IDLE_VAL_0 => "100", + SATA_MAX_BURST_0 => 7, + SATA_MAX_INIT_0 => 22, + SATA_MAX_WAKE_0 => 7, + SATA_MIN_BURST_0 => 4, + SATA_MIN_INIT_0 => 12, + SATA_MIN_WAKE_0 => 4, + TRANS_TIME_FROM_P2_0 => x"003C", + TRANS_TIME_NON_P2_0 => x"0019", + TRANS_TIME_TO_P2_0 => x"0064", + + RX_STATUS_FMT_1 => "PCIE", + SATA_BURST_VAL_1 => "100", + SATA_IDLE_VAL_1 => "100", + SATA_MAX_BURST_1 => 7, + SATA_MAX_INIT_1 => 22, + SATA_MAX_WAKE_1 => 7, + SATA_MIN_BURST_1 => 4, + SATA_MIN_INIT_1 => 12, + SATA_MIN_WAKE_1 => 4, + TRANS_TIME_FROM_P2_1 => x"003C", + TRANS_TIME_NON_P2_1 => x"0019", + TRANS_TIME_TO_P2_1 => x"0064" + + ) port map ( + + ------------------------ Loopback and Powerdown Ports ---------------------- + LOOPBACK0 => "000", + LOOPBACK1(0) => '0', + LOOPBACK1(1) => gtxLoopback, + LOOPBACK1(2) => '0', + RXPOWERDOWN0 => (others=>'0'), + RXPOWERDOWN1 => (others=>'0'), + TXPOWERDOWN0 => (others=>'0'), + TXPOWERDOWN1 => (others=>'0'), + -------------- Receive Ports - 64b66b and 64b67b Gearbox Ports ------------- + RXDATAVALID0 => open, + RXDATAVALID1 => open, + RXGEARBOXSLIP0 => '0', + RXGEARBOXSLIP1 => '0', + RXHEADER0 => open, + RXHEADER1 => open, + RXHEADERVALID0 => open, + RXHEADERVALID1 => open, + RXSTARTOFSEQ0 => open, + RXSTARTOFSEQ1 => open, + ----------------------- Receive Ports - 8b10b Decoder ---------------------- + RXCHARISCOMMA0 => open, + RXCHARISCOMMA1 => open, + RXCHARISK0 => open, + RXCHARISK1(1 downto 0) => phyRxDataK, + RXCHARISK1(3 downto 2) => open, + RXDEC8B10BUSE0 => '1', + RXDEC8B10BUSE1 => '1', + RXDISPERR0 => open, + RXDISPERR1(1 downto 0) => phyRxDispErr, + RXDISPERR1(3 downto 2) => open, + RXNOTINTABLE0 => open, + RXNOTINTABLE1(1 downto 0) => phyRxDecErr, + RXNOTINTABLE1(3 downto 2) => open, + RXRUNDISP0 => open, + RXRUNDISP1 => open, + ------------------- Receive Ports - Channel Bonding Ports ------------------ + RXCHANBONDSEQ0 => open, + RXCHANBONDSEQ1 => open, + RXCHBONDI0 => (others=>'0'), + RXCHBONDI1 => (others=>'0'), + RXCHBONDO0 => open, + RXCHBONDO1 => open, + RXENCHANSYNC0 => '0', + RXENCHANSYNC1 => '0', + ------------------- Receive Ports - Clock Correction Ports ----------------- + RXCLKCORCNT0 => open, + RXCLKCORCNT1 => open, + --------------- Receive Ports - Comma Detection and Alignment -------------- + RXBYTEISALIGNED0 => open, + RXBYTEISALIGNED1 => open, + RXBYTEREALIGN0 => open, + RXBYTEREALIGN1 => open, + RXCOMMADET0 => open, + RXCOMMADET1 => open, + RXCOMMADETUSE0 => '1', + RXCOMMADETUSE1 => '1', + RXENMCOMMAALIGN0 => '1', + RXENMCOMMAALIGN1 => '1', + RXENPCOMMAALIGN0 => '1', + RXENPCOMMAALIGN1 => '1', + RXSLIDE0 => '0', + RXSLIDE1 => '0', + ----------------------- Receive Ports - PRBS Detection --------------------- + PRBSCNTRESET0 => '0', + PRBSCNTRESET1 => '0', + RXENPRBSTST0 => (others=>'0'), + RXENPRBSTST1 => (others=>'0'), + RXPRBSERR0 => open, + RXPRBSERR1 => open, + ------------------- Receive Ports - RX Data Path interface ----------------- + RXDATA0 => open, + RXDATA1(15 downto 0) => phyRxData, + RXDATA1(31 downto 16) => open, + RXDATAWIDTH0 => "01", + RXDATAWIDTH1 => "01", + RXRECCLK0 => open, + RXRECCLK1 => intRxRecClk, + RXRESET0 => '0', + RXRESET1 => phyRxReset, + RXUSRCLK0 => pgpClk, + RXUSRCLK1 => pgpClk, + RXUSRCLK20 => pgpClk, + RXUSRCLK21 => pgpClk, + ------------ Receive Ports - RX Decision Feedback Equalizer(DFE) ----------- + DFECLKDLYADJ0 => (others=>'0'), + DFECLKDLYADJ1 => (others=>'0'), + DFECLKDLYADJMONITOR0 => open, + DFECLKDLYADJMONITOR1 => open, + DFEEYEDACMONITOR0 => open, + DFEEYEDACMONITOR1 => open, + DFESENSCAL0 => open, + DFESENSCAL1 => open, + DFETAP10 => (others=>'0'), + DFETAP11 => (others=>'0'), + DFETAP1MONITOR0 => open, + DFETAP1MONITOR1 => open, + DFETAP20 => (others=>'0'), + DFETAP21 => (others=>'0'), + DFETAP2MONITOR0 => open, + DFETAP2MONITOR1 => open, + DFETAP30 => (others=>'0'), + DFETAP31 => (others=>'0'), + DFETAP3MONITOR0 => open, + DFETAP3MONITOR1 => open, + DFETAP40 => (others=>'0'), + DFETAP41 => (others=>'0'), + DFETAP4MONITOR0 => open, + DFETAP4MONITOR1 => open, + ------- Receive Ports - RX Driver,OOB signalling,Coupling and Eq.,CDR ------ + RXCDRRESET0 => '0', + RXCDRRESET1 => phyRxCdrReset, + RXELECIDLE0 => open, + RXELECIDLE1 => phyRxElecIdle, + RXENEQB0 => '0', + RXENEQB1 => '0', + RXEQMIX0 => (others=>'0'), + RXEQMIX1 => (others=>'0'), + RXEQPOLE0 => (others=>'0'), + RXEQPOLE1 => (others=>'0'), + RXN0 => '1', + RXN1 => gtxRxN, + RXP0 => '0', + RXP1 => gtxRxP, + -------- Receive Ports - RX Elastic Buffer and Phase Alignment Ports ------- + RXBUFRESET0 => '0', + RXBUFRESET1 => '0', + RXBUFSTATUS0 => open, + RXBUFSTATUS1 => phyRxBuffStatus, + RXCHANISALIGNED0 => open, + RXCHANISALIGNED1 => open, + RXCHANREALIGN0 => open, + RXCHANREALIGN1 => open, + RXENPMAPHASEALIGN0 => '0', + RXENPMAPHASEALIGN1 => '0', + RXPMASETPHASE0 => '0', + RXPMASETPHASE1 => '0', + RXSTATUS0 => open, + RXSTATUS1 => open, + --------------- Receive Ports - RX Loss-of-sync State Machine -------------- + RXLOSSOFSYNC0 => open, + RXLOSSOFSYNC1 => open, + ---------------------- Receive Ports - RX Oversampling --------------------- + RXENSAMPLEALIGN0 => '0', + RXENSAMPLEALIGN1 => '0', + RXOVERSAMPLEERR0 => open, + RXOVERSAMPLEERR1 => open, + -------------- Receive Ports - RX Pipe Control for PCI Express ------------- + PHYSTATUS0 => open, + PHYSTATUS1 => open, + RXVALID0 => open, + RXVALID1 => open, + ----------------- Receive Ports - RX Polarity Control Ports ---------------- + RXPOLARITY0 => '0', + RXPOLARITY1 => phyRxPolarity(0), + ------------- Shared Ports - Dynamic Reconfiguration Port (DRP) ------------ + DADDR => (others=>'0'), + DCLK => '0', + DEN => '0', + DI => (others=>'0'), + DO => open, + DRDY => open, + DWE => '0', + --------------------- Shared Ports - Tile and PLL Ports -------------------- + CLKIN => gtxClkIn, + GTXRESET => pgpReset, + GTXTEST => "10000000000000", + INTDATAWIDTH => '1', + PLLLKDET => phyLockDetect, + PLLLKDETEN => '1', + PLLPOWERDOWN => '0', + REFCLKOUT => tmpRefClkOut, + REFCLKPWRDNB => '1', + RESETDONE0 => open, + RESETDONE1 => phyRstDone, + -------------- Transmit Ports - 64b66b and 64b67b Gearbox Ports ------------ + TXGEARBOXREADY0 => open, + TXGEARBOXREADY1 => open, + TXHEADER0 => (others=>'0'), + TXHEADER1 => (others=>'0'), + TXSEQUENCE0 => (others=>'0'), + TXSEQUENCE1 => (others=>'0'), + TXSTARTSEQ0 => '0', + TXSTARTSEQ1 => '0', + ---------------- Transmit Ports - 8b10b Encoder Control Ports -------------- + TXBYPASS8B10B0 => (others=>'0'), + TXBYPASS8B10B1 => (others=>'0'), + TXCHARDISPMODE0 => (others=>'0'), + TXCHARDISPMODE1 => (others=>'0'), + TXCHARDISPVAL0 => (others=>'0'), + TXCHARDISPVAL1 => (others=>'0'), + TXCHARISK0 => (others=>'0'), + TXCHARISK1(1 downto 0) => phyTxDataK, + TXCHARISK1(3 downto 2) => (others=>'0'), + TXENC8B10BUSE0 => '1', + TXENC8B10BUSE1 => '1', + TXKERR0 => open, + TXKERR1 => open, + TXRUNDISP0 => open, + TXRUNDISP1 => open, + ------------- Transmit Ports - TX Buffering and Phase Alignment ------------ + TXBUFSTATUS0 => open, + TXBUFSTATUS1 => phyTxBuffStatus, + ------------------ Transmit Ports - TX Data Path interface ----------------- + TXDATA0 => (others=>'0'), + TXDATA1(15 downto 0) => phyTxData, + TXDATA1(31 downto 16) => (others=>'0'), + TXDATAWIDTH0 => "01", + TXDATAWIDTH1 => "01", + TXOUTCLK0 => open, + TXOUTCLK1 => open, + TXRESET0 => '0', + TXRESET1 => phyTxReset, + TXUSRCLK0 => pgpClk, + TXUSRCLK1 => pgpClk, + TXUSRCLK20 => pgpClk, + TXUSRCLK21 => pgpClk, + --------------- Transmit Ports - TX Driver and OOB signalling -------------- + TXBUFDIFFCTRL0 => "100", -- 800mV + TXBUFDIFFCTRL1 => "100", + TXDIFFCTRL0 => "100", + TXDIFFCTRL1 => "100", + TXINHIBIT0 => '0', + TXINHIBIT1 => '0', + TXN0 => open, + TXN1 => gtxTxN, + TXP0 => open, + TXP1 => gtxTxP, + TXPREEMPHASIS0 => "0011", -- 4.5% + TXPREEMPHASIS1 => "0011", + -------- Transmit Ports - TX Elastic Buffer and Phase Alignment Ports ------ + TXENPMAPHASEALIGN0 => '0', + TXENPMAPHASEALIGN1 => '0', + TXPMASETPHASE0 => '0', + TXPMASETPHASE1 => '0', + --------------------- Transmit Ports - TX PRBS Generator ------------------- + TXENPRBSTST0 => (others=>'0'), + TXENPRBSTST1 => (others=>'0'), + -------------------- Transmit Ports - TX Polarity Control ------------------ + TXPOLARITY0 => '0', + TXPOLARITY1 => '0', + ----------------- Transmit Ports - TX Ports for PCI Express ---------------- + TXDETECTRX0 => '0', + TXDETECTRX1 => '0', + TXELECIDLE0 => '0', + TXELECIDLE1 => '0', + --------------------- Transmit Ports - TX Ports for SATA ------------------- + TXCOMSTART0 => '0', + TXCOMSTART1 => '0', + TXCOMTYPE0 => '0', + TXCOMTYPE1 => '0' + ); + + -- Global Buffer For Ref Clock Output + U_RefClkBuff: BUFG port map ( + O => gtxRefClkOut, + I => tmpRefClkOut + ); + gtxRxRecClk <= intRxRecClk; + +end Pgp2Gtx16B; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2GtxClk.vhd b/rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2GtxClk.vhd new file mode 100755 index 00000000..3cdf8694 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2GtxClk.vhd @@ -0,0 +1,213 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, Clock Generation Block +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2GtxClk.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 08/18/2009 +------------------------------------------------------------------------------- +-- Description: +-- PGP Clock Module. Contains DCM to support PGP clocking for GTX in Virtex5. +-- Used to generate global buffer clocks at the PGP interface rate and the 2X +-- clock required for the internal GTX logic. +-- Will also generate an optional user global clock and reset for external +-- logic use. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 08/18/2009: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; +use work.Pgp2GtxPackage.all; +Library UNISIM; +use UNISIM.VCOMPONENTS.ALL; + +entity Pgp2GtxClk is + generic ( + UserFxDiv : integer := 5; -- DCM FX Output Divide + UserFxMult : integer := 4 -- DCM FX Output Divide, 4/5 * 156.25 = 125Mhz + ); + port ( + + -- Reference Clock Input. + -- This is provided as an output from the GTX tile. + pgpRefClk : in std_logic; + + -- Power On Reset Input + ponResetL : in std_logic; + + -- Locally Generated Reset + locReset : in std_logic; + + -- Global Clock & Reset For PGP Logic, 156.25Mhz + pgpClk : out std_logic; + pgpReset : out std_logic; + + -- Global Clock & Reset For User Logic + userClk : out std_logic; + userReset : out std_logic; + + -- Inputs clocks for reset generation connect + -- to pgpClk and userClk + pgpClkIn : in std_logic; + userClkIn : in std_logic + ); + +end Pgp2GtxClk; + + +-- Define architecture +architecture Pgp2GtxClk of Pgp2GtxClk is + + -- Local Signals + signal ponReset : std_logic; + signal tmpPgpClk : std_logic; + signal intPgpClk : std_logic; + signal intPgpRst : std_logic; + signal tmpLocClk : std_logic; + signal intUsrClk : std_logic; + signal intUsrRst : std_logic; + signal syncPgpRstIn : std_logic_vector(2 downto 0); + signal pgpRstCnt : std_logic_vector(3 downto 0); + signal syncLocRstIn : std_logic_vector(2 downto 0); + signal locRstCnt : std_logic_vector(3 downto 0); + signal dcmLock : std_logic; + signal resetIn : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Output Generated Clock And Reset Signals + pgpClk <= intPgpClk; + pgpReset <= intPgpRst; + userClk <= intUsrClk; + userReset <= intUsrRst; + + -- Invert power on reset + ponReset <= not ponResetL; + + + -- DCM For PGP Clock & User Clock + U_PgpDcm: DCM_ADV + generic map ( + DFS_FREQUENCY_MODE => "LOW", + DLL_FREQUENCY_MODE => "HIGH", + CLKIN_DIVIDE_BY_2 => FALSE, + CLK_FEEDBACK => "1X", + CLKOUT_PHASE_SHIFT => "NONE", + STARTUP_WAIT => false, + PHASE_SHIFT => 0, + CLKFX_MULTIPLY => UserFxMult, + CLKFX_DIVIDE => UserFxDiv, + CLKDV_DIVIDE => 2.0, + CLKIN_PERIOD => 6.4, + DCM_PERFORMANCE_MODE => "MAX_SPEED", + FACTORY_JF => X"F0F0", + DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS" + ) + port map ( + CLKIN => pgpRefClk, CLKFB => intPgpClk, + CLK0 => tmpPgpClk, CLK90 => open, + CLK180 => open, CLK270 => open, + CLK2X => open, CLK2X180 => open, + CLKDV => open, CLKFX => tmpLocClk, + CLKFX180 => open, LOCKED => dcmLock, + PSDONE => open, PSCLK => '0', + PSINCDEC => '0', PSEN => '0', + DCLK => '0', DADDR => (others=>'0'), + DI => (others=>'0'), DO => open, + DRDY => open, DWE => '0', + DEN => '0', RST => ponReset + ); + + + -- Global Buffer For PGP Clock + U_PgpClkBuff: BUFG port map ( + O => intPgpClk, + I => tmpPgpClk + ); + + + -- Global Buffer For User Clock + U_LocClkBuff: BUFG port map ( + O => intUsrClk, + I => tmpLocClk + ); + + + -- Generate reset input + resetIn <= (not dcmLock) or ponReset or locReset; + + -- PGP Clock Synced Reset + process ( pgpClkIn, resetIn ) begin + if resetIn = '1' then + syncPgpRstIn <= (others=>'0') after tpd; + pgpRstCnt <= (others=>'0') after tpd; + intPgpRst <= '1' after tpd; + elsif rising_edge(pgpClkIn) then + + -- Sync local reset, lock and power on reset to local clock + -- Negative asserted signal + syncPgpRstIn(0) <= '1' after tpd; + syncPgpRstIn(1) <= syncPgpRstIn(0) after tpd; + syncPgpRstIn(2) <= syncPgpRstIn(1) after tpd; + + -- Reset counter on reset + if syncPgpRstIn(2) = '0' then + pgpRstCnt <= (others=>'0') after tpd; + intPgpRst <= '1' after tpd; + + -- Count Up To Max Value + elsif pgpRstCnt = "1111" then + intPgpRst <= '0' after tpd; + + -- Increment counter + else + intPgpRst <= '1' after tpd; + pgpRstCnt <= pgpRstCnt + 1 after tpd; + end if; + end if; + end process; + + + -- Local User Clock Synced Reset + process ( userClkIn, resetIn ) begin + if resetIn = '1' then + syncLocRstIn <= (others=>'0') after tpd; + locRstCnt <= (others=>'0') after tpd; + intUsrRst <= '1' after tpd; + elsif rising_edge(userClkIn) then + + -- Sync local reset, lock and power on reset to local clock + -- Negative asserted signal + syncLocRstIn(0) <= '1' after tpd; + syncLocRstIn(1) <= syncLocRstIn(0) after tpd; + syncLocRstIn(2) <= syncLocRstIn(1) after tpd; + + -- Reset counter on reset + if syncLocRstIn(2) = '0' then + locRstCnt <= (others=>'0') after tpd; + intUsrRst <= '1' after tpd; + + -- Count Up To Max Value + elsif locRstCnt = "1111" then + intUsrRst <= '0' after tpd; + + -- Increment counter + else + intUsrRst <= '1' after tpd; + locRstCnt <= locRstCnt + 1 after tpd; + end if; + end if; + end process; + +end Pgp2GtxClk; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2GtxDual.vhd b/rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2GtxDual.vhd new file mode 100755 index 00000000..f7dd22d8 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2GtxDual.vhd @@ -0,0 +1,1294 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, Dual Channel GTX Wrapper +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2GtxDual.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 09/24/2010 +------------------------------------------------------------------------------- +-- Description: +-- VHDL source file containing the PGP, GTX and CRC blocks. +-- This module also contains the logic to control the reset of the GTX. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 09/24/2010: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; +use work.Pgp2GtxPackage.all; +use work.Pgp2CorePackage.all; +library UNISIM; +use UNISIM.VCOMPONENTS.ALL; + + +entity Pgp2GtxDual is + generic ( + EnShortCells : integer := 1; -- Enable short non-EOF cells + VcInterleave : integer := 1 -- Interleave Frames + ); + port ( + + -- System clock, reset & control + pgpClk : in std_logic; -- Pgp master clock + pgpReset : in std_logic; -- Synchronous reset input + pgpFlush : in std_logic; -- Frame state flash + + -- PLL Reset Control + pll0TxRst : in std_logic; -- Reset transmit PLL logic + pll0RxRst : in std_logic; -- Reset receive PLL logic + + -- PLL Lock Status + pll0RxReady : out std_logic; -- MGT Receive logic is ready + pll0TxReady : out std_logic; -- MGT Transmit logic is ready + + -- Sideband data + pgp0RemData : out std_logic_vector(7 downto 0); -- Far end side User Data + pgp0LocData : in std_logic_vector(7 downto 0); -- Far end side User Data + + -- Opcode Transmit Interface + pgp0TxOpCodeEn : in std_logic; -- Opcode receive enable + pgp0TxOpCode : in std_logic_vector(7 downto 0); -- Opcode receive value + + -- Opcode Receive Interface + pgp0RxOpCodeEn : out std_logic; -- Opcode receive enable + pgp0RxOpCode : out std_logic_vector(7 downto 0); -- Opcode receive value + + -- Link status + pgp0LocLinkReady : out std_logic; -- Local Link is ready + pgp0RemLinkReady : out std_logic; -- Far end side has link + + -- Error Flags, one pulse per event + pgp0RxCellError : out std_logic; -- A cell error has occured + pgp0RxLinkDown : out std_logic; -- A link down event has occured + pgp0RxLinkError : out std_logic; -- A link error has occured + + -- Frame Transmit Interface, VC 0 + vc00FrameTxValid : in std_logic; -- User frame data is valid + vc00FrameTxReady : out std_logic; -- PGP is ready + vc00FrameTxSOF : in std_logic; -- User frame data start of frame + vc00FrameTxEOF : in std_logic; -- User frame data end of frame + vc00FrameTxEOFE : in std_logic; -- User frame data error + vc00FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc00LocBuffAFull : in std_logic; -- Local buffer almost full + vc00LocBuffFull : in std_logic; -- Local buffer full + + -- Frame Transmit Interface, VC 1 + vc01FrameTxValid : in std_logic; -- User frame data is valid + vc01FrameTxReady : out std_logic; -- PGP is ready + vc01FrameTxSOF : in std_logic; -- User frame data start of frame + vc01FrameTxEOF : in std_logic; -- User frame data end of frame + vc01FrameTxEOFE : in std_logic; -- User frame data error + vc01FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc01LocBuffAFull : in std_logic; -- Local buffer almost full + vc01LocBuffFull : in std_logic; -- Local buffer full + + -- Frame Transmit Interface, VC 2 + vc02FrameTxValid : in std_logic; -- User frame data is valid + vc02FrameTxReady : out std_logic; -- PGP is ready + vc02FrameTxSOF : in std_logic; -- User frame data start of frame + vc02FrameTxEOF : in std_logic; -- User frame data end of frame + vc02FrameTxEOFE : in std_logic; -- User frame data error + vc02FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc02LocBuffAFull : in std_logic; -- Local buffer almost full + vc02LocBuffFull : in std_logic; -- Local buffer full + + -- Frame Transmit Interface, VC 3 + vc03FrameTxValid : in std_logic; -- User frame data is valid + vc03FrameTxReady : out std_logic; -- PGP is ready + vc03FrameTxSOF : in std_logic; -- User frame data start of frame + vc03FrameTxEOF : in std_logic; -- User frame data end of frame + vc03FrameTxEOFE : in std_logic; -- User frame data error + vc03FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc03LocBuffAFull : in std_logic; -- Local buffer almost full + vc03LocBuffFull : in std_logic; -- Local buffer full + + -- Common Frame Receive Interface For All VCs + vc0FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc0FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc0FrameRxEOFE : out std_logic; -- PGP frame data error + vc0FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + + -- Frame Receive Interface, VC 0 + vc00FrameRxValid : out std_logic; -- PGP frame data is valid + vc00RemBuffAFull : out std_logic; -- Remote buffer almost full + vc00RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 1 + vc01FrameRxValid : out std_logic; -- PGP frame data is valid + vc01RemBuffAFull : out std_logic; -- Remote buffer almost full + vc01RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 2 + vc02FrameRxValid : out std_logic; -- PGP frame data is valid + vc02RemBuffAFull : out std_logic; -- Remote buffer almost full + vc02RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 3 + vc03FrameRxValid : out std_logic; -- PGP frame data is valid + vc03RemBuffAFull : out std_logic; -- Remote buffer almost full + vc03RemBuffFull : out std_logic; -- Remote buffer full + + -- PLL Reset Control + pll1TxRst : in std_logic; -- Reset transmit PLL logic + pll1RxRst : in std_logic; -- Reset receive PLL logic + + -- PLL Lock Status + pll1RxReady : out std_logic; -- MGT Receive logic is ready + pll1TxReady : out std_logic; -- MGT Transmit logic is ready + + -- Sideband data + pgp1RemData : out std_logic_vector(7 downto 0); -- Far end side User Data + pgp1LocData : in std_logic_vector(7 downto 0); -- Far end side User Data + + -- Opcode Transmit Interface + pgp1TxOpCodeEn : in std_logic; -- Opcode receive enable + pgp1TxOpCode : in std_logic_vector(7 downto 0); -- Opcode receive value + + -- Opcode Receive Interface + pgp1RxOpCodeEn : out std_logic; -- Opcode receive enable + pgp1RxOpCode : out std_logic_vector(7 downto 0); -- Opcode receive value + + -- Link status + pgp1LocLinkReady : out std_logic; -- Local Link is ready + pgp1RemLinkReady : out std_logic; -- Far end side has link + + -- Error Flags, one pulse per event + pgp1RxCellError : out std_logic; -- A cell error has occured + pgp1RxLinkDown : out std_logic; -- A link down event has occured + pgp1RxLinkError : out std_logic; -- A link error has occured + + -- Frame Transmit Interface, VC 0 + vc10FrameTxValid : in std_logic; -- User frame data is valid + vc10FrameTxReady : out std_logic; -- PGP is ready + vc10FrameTxSOF : in std_logic; -- User frame data start of frame + vc10FrameTxEOF : in std_logic; -- User frame data end of frame + vc10FrameTxEOFE : in std_logic; -- User frame data error + vc10FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc10LocBuffAFull : in std_logic; -- Local buffer almost full + vc10LocBuffFull : in std_logic; -- Local buffer full + + -- Frame Transmit Interface, VC 1 + vc11FrameTxValid : in std_logic; -- User frame data is valid + vc11FrameTxReady : out std_logic; -- PGP is ready + vc11FrameTxSOF : in std_logic; -- User frame data start of frame + vc11FrameTxEOF : in std_logic; -- User frame data end of frame + vc11FrameTxEOFE : in std_logic; -- User frame data error + vc11FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc11LocBuffAFull : in std_logic; -- Local buffer almost full + vc11LocBuffFull : in std_logic; -- Local buffer full + + -- Frame Transmit Interface, VC 2 + vc12FrameTxValid : in std_logic; -- User frame data is valid + vc12FrameTxReady : out std_logic; -- PGP is ready + vc12FrameTxSOF : in std_logic; -- User frame data start of frame + vc12FrameTxEOF : in std_logic; -- User frame data end of frame + vc12FrameTxEOFE : in std_logic; -- User frame data error + vc12FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc12LocBuffAFull : in std_logic; -- Local buffer almost full + vc12LocBuffFull : in std_logic; -- Local buffer full + + -- Frame Transmit Interface, VC 3 + vc13FrameTxValid : in std_logic; -- User frame data is valid + vc13FrameTxReady : out std_logic; -- PGP is ready + vc13FrameTxSOF : in std_logic; -- User frame data start of frame + vc13FrameTxEOF : in std_logic; -- User frame data end of frame + vc13FrameTxEOFE : in std_logic; -- User frame data error + vc13FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc13LocBuffAFull : in std_logic; -- Local buffer almost full + vc13LocBuffFull : in std_logic; -- Local buffer full + + -- Common Frame Receive Interface For All VCs + vc1FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc1FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc1FrameRxEOFE : out std_logic; -- PGP frame data error + vc1FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + + -- Frame Receive Interface, VC 0 + vc10FrameRxValid : out std_logic; -- PGP frame data is valid + vc10RemBuffAFull : out std_logic; -- Remote buffer almost full + vc10RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 1 + vc11FrameRxValid : out std_logic; -- PGP frame data is valid + vc11RemBuffAFull : out std_logic; -- Remote buffer almost full + vc11RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 2 + vc12FrameRxValid : out std_logic; -- PGP frame data is valid + vc12RemBuffAFull : out std_logic; -- Remote buffer almost full + vc12RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 3 + vc13FrameRxValid : out std_logic; -- PGP frame data is valid + vc13RemBuffAFull : out std_logic; -- Remote buffer almost full + vc13RemBuffFull : out std_logic; -- Remote buffer full + + -- GTX Status & Control Signals + gtxLoopback : in std_logic_vector(1 downto 0); -- GTX Serial Loopback Control + + -- MGT Signals Clock & IO Signals + gtxClkIn : in std_logic; -- GTX Reference Clock In + gtxRefClkOut : out std_logic; -- GTX Reference Clock Output + gtxRxRecClk : out std_logic_vector(1 downto 0); -- GTX Rx Recovered Clock + gtxRxN : in std_logic_vector(1 downto 0); -- GTX Serial Receive Negative + gtxRxP : in std_logic_vector(1 downto 0); -- GTX Serial Receive Positive + gtxTxN : out std_logic_vector(1 downto 0); -- GTX Serial Transmit Negative + gtxTxP : out std_logic_vector(1 downto 0); -- GTX Serial Transmit Positive + + -- Debug + debug : out std_logic_vector(127 downto 0) + ); + +end Pgp2GtxDual; + + +-- Define architecture +architecture Pgp2GtxDual of Pgp2GtxDual is + + -- Local Signals + signal crc0TxIn : std_logic_vector(15 downto 0); + signal crc0TxInGtx : std_logic_vector(31 downto 0); + signal crc0TxInit : std_logic; + signal crc0TxRst : std_logic; + signal crc0TxValid : std_logic; + signal crc0TxWidth : std_logic_vector(2 downto 0); + signal crc0TxOut : std_logic_vector(31 downto 0); + signal crc0TxOutGtx : std_logic_vector(31 downto 0); + signal crc0RxIn : std_logic_vector(15 downto 0); + signal crc0RxInGtx : std_logic_vector(31 downto 0); + signal crc0RxInit : std_logic; + signal crc0RxRst : std_logic; + signal crc0RxValid : std_logic; + signal crc0RxWidth : std_logic_vector(2 downto 0); + signal crc0RxOut : std_logic_vector(31 downto 0); + signal crc0RxOutGtx : std_logic_vector(31 downto 0); + signal phy0RxPolarity : std_logic_vector(0 downto 0); + signal phy0RxData : std_logic_vector(15 downto 0); + signal phy0RxDataK : std_logic_vector(1 downto 0); + signal phy0TxData : std_logic_vector(15 downto 0); + signal phy0TxDataK : std_logic_vector(1 downto 0); + signal phy0RxDispErr : std_logic_vector(1 downto 0); + signal phy0RxDecErr : std_logic_vector(1 downto 0); + signal phy0RxReady : std_logic; + signal phy0RxInit : std_logic; + signal phy0TxReady : std_logic; + signal phy0RxReset : std_logic; + signal phy0RxElecIdle : std_logic; + signal phy0RxCdrReset : std_logic; + signal phy0RstDone : std_logic; + signal phy0RxBuffStatus : std_logic_vector(2 downto 0); + signal phy0TxReset : std_logic; + signal phy0TxBuffStatus : std_logic_vector(1 downto 0); + signal phyLockDetect : std_logic; + signal int0TxRst : std_logic; + signal int0RxRst : std_logic; + signal pgp0RxLinkReady : std_logic; + signal pgp0TxLinkReady : std_logic; + signal crc1TxIn : std_logic_vector(15 downto 0); + signal crc1TxInGtx : std_logic_vector(31 downto 0); + signal crc1TxInit : std_logic; + signal crc1TxRst : std_logic; + signal crc1TxValid : std_logic; + signal crc1TxWidth : std_logic_vector(2 downto 0); + signal crc1TxOut : std_logic_vector(31 downto 0); + signal crc1TxOutGtx : std_logic_vector(31 downto 0); + signal crc1RxIn : std_logic_vector(15 downto 0); + signal crc1RxInGtx : std_logic_vector(31 downto 0); + signal crc1RxInit : std_logic; + signal crc1RxRst : std_logic; + signal crc1RxValid : std_logic; + signal crc1RxWidth : std_logic_vector(2 downto 0); + signal crc1RxOut : std_logic_vector(31 downto 0); + signal crc1RxOutGtx : std_logic_vector(31 downto 0); + signal phy1RxPolarity : std_logic_vector(0 downto 0); + signal phy1RxData : std_logic_vector(15 downto 0); + signal phy1RxDataK : std_logic_vector(1 downto 0); + signal phy1TxData : std_logic_vector(15 downto 0); + signal phy1TxDataK : std_logic_vector(1 downto 0); + signal phy1RxDispErr : std_logic_vector(1 downto 0); + signal phy1RxDecErr : std_logic_vector(1 downto 0); + signal phy1RxReady : std_logic; + signal phy1RxInit : std_logic; + signal phy1TxReady : std_logic; + signal phy1RxReset : std_logic; + signal phy1RxElecIdle : std_logic; + signal phy1RxCdrReset : std_logic; + signal phy1RstDone : std_logic; + signal phy1RxBuffStatus : std_logic_vector(2 downto 0); + signal phy1TxReset : std_logic; + signal phy1TxBuffStatus : std_logic_vector(1 downto 0); + signal int1TxRst : std_logic; + signal int1RxRst : std_logic; + signal pgp1RxLinkReady : std_logic; + signal pgp1TxLinkReady : std_logic; + signal intRxRecClk : std_logic; + signal tmpRefClkOut : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + ------------------------------------------ + -- PGP Lane 0 + ------------------------------------------ + + -- PGP RX Block + U_Pgp2Rx0: Pgp2CorePackage.Pgp2Rx + generic map ( + RxLaneCnt => 1, + EnShortCells => EnShortCells + ) port map ( + pgpRxClk => pgpClk, + pgpRxReset => pgpReset, + pgpRxFlush => pgpFlush, + pgpRxLinkReady => pgp0RxLinkReady, + pgpRxCellError => pgp0RxCellError, + pgpRxLinkDown => pgp0RxLinkDown, + pgpRxLinkError => pgp0RxLinkError, + pgpRxOpCodeEn => pgp0RxOpCodeEn, + pgpRxOpCode => pgp0RxOpCode, + pgpRemLinkReady => pgp0RemLinkReady, + pgpRemData => pgp0RemData, + vcFrameRxSOF => vc0FrameRxSOF, + vcFrameRxEOF => vc0FrameRxEOF, + vcFrameRxEOFE => vc0FrameRxEOFE, + vcFrameRxData => vc0FrameRxData, + vc0FrameRxValid => vc00FrameRxValid, + vc0RemBuffAFull => vc00RemBuffAFull, + vc0RemBuffFull => vc00RemBuffFull, + vc1FrameRxValid => vc01FrameRxValid, + vc1RemBuffAFull => vc01RemBuffAFull, + vc1RemBuffFull => vc01RemBuffFull, + vc2FrameRxValid => vc02FrameRxValid, + vc2RemBuffAFull => vc02RemBuffAFull, + vc2RemBuffFull => vc02RemBuffFull, + vc3FrameRxValid => vc03FrameRxValid, + vc3RemBuffAFull => vc03RemBuffAFull, + vc3RemBuffFull => vc03RemBuffFull, + phyRxPolarity => phy0RxPolarity, + phyRxData => phy0RxData, + phyRxDataK => phy0RxDataK, + phyRxDispErr => phy0RxDispErr, + phyRxDecErr => phy0RxDecErr, + phyRxReady => phy0RxReady, + phyRxInit => phy0RxInit, + crcRxIn => crc0RxIn, + crcRxWidth => open, + crcRxInit => crc0RxInit, + crcRxValid => crc0RxValid, + crcRxOut => crc0RxOut, + debug => debug(63 downto 0) + ); + + + -- PGP TX Block + U_Pgp2Tx0: Pgp2CorePackage.Pgp2Tx + generic map ( + TxLaneCnt => 1, + VcInterleave => VcInterleave + ) port map ( + pgpTxClk => pgpClk, + pgpTxReset => pgpReset, + pgpTxFlush => pgpFlush, + pgpTxLinkReady => pgp0TxLinkReady, + pgpTxOpCodeEn => pgp0TxOpCodeEn, + pgpTxOpCode => pgp0TxOpCode, + pgpLocLinkReady => pgp0RxLinkReady, + pgpLocData => pgp0LocData, + vc0FrameTxValid => vc00FrameTxValid, + vc0FrameTxReady => vc00FrameTxReady, + vc0FrameTxSOF => vc00FrameTxSOF, + vc0FrameTxEOF => vc00FrameTxEOF, + vc0FrameTxEOFE => vc00FrameTxEOFE, + vc0FrameTxData => vc00FrameTxData, + vc0LocBuffAFull => vc00LocBuffAFull, + vc0LocBuffFull => vc00LocBuffFull, + vc1FrameTxValid => vc01FrameTxValid, + vc1FrameTxReady => vc01FrameTxReady, + vc1FrameTxSOF => vc01FrameTxSOF, + vc1FrameTxEOF => vc01FrameTxEOF, + vc1FrameTxEOFE => vc01FrameTxEOFE, + vc1FrameTxData => vc01FrameTxData, + vc1LocBuffAFull => vc01LocBuffAFull, + vc1LocBuffFull => vc01LocBuffFull, + vc2FrameTxValid => vc02FrameTxValid, + vc2FrameTxReady => vc02FrameTxReady, + vc2FrameTxSOF => vc02FrameTxSOF, + vc2FrameTxEOF => vc02FrameTxEOF, + vc2FrameTxEOFE => vc02FrameTxEOFE, + vc2FrameTxData => vc02FrameTxData, + vc2LocBuffAFull => vc02LocBuffAFull, + vc2LocBuffFull => vc02LocBuffFull, + vc3FrameTxValid => vc03FrameTxValid, + vc3FrameTxReady => vc03FrameTxReady, + vc3FrameTxSOF => vc03FrameTxSOF, + vc3FrameTxEOF => vc03FrameTxEOF, + vc3FrameTxEOFE => vc03FrameTxEOFE, + vc3FrameTxData => vc03FrameTxData, + vc3LocBuffAFull => vc03LocBuffAFull, + vc3LocBuffFull => vc03LocBuffFull, + phyTxData => phy0TxData, + phyTxDataK => phy0TxDataK, + phyTxReady => phy0TxReady, + crcTxIn => crc0TxIn, + crcTxInit => crc0TxInit, + crcTxValid => crc0TxValid, + crcTxOut => crc0TxOut, + debug => open + ); + + + -- Adapt CRC data width flag + crc0TxWidth <= "001"; + crc0RxWidth <= "001"; + crc0RxRst <= int0RxRst or crc0RxInit; + crc0TxRst <= int0TxRst or crc0TxInit; + + -- Pass CRC data in on proper bits + crc0TxInGtx(31 downto 24) <= crc0TxIn(7 downto 0); + crc0TxInGtx(23 downto 16) <= crc0TxIn(15 downto 8); + crc0TxInGtx(15 downto 0) <= (others=>'0'); + crc0RxInGtx(31 downto 24) <= crc0RxIn(7 downto 0); + crc0RxInGtx(23 downto 16) <= crc0RxIn(15 downto 8); + crc0RxInGtx(15 downto 0) <= (others=>'0'); + + -- Pll Resets + int0TxRst <= pll0TxRst or pgpReset; + int0RxRst <= pll0RxRst or pgpReset; + + -- PLL Lock + pll0RxReady <= phy0RxReady; + pll0TxReady <= phy0TxReady; + + -- Link Ready + pgp0LocLinkReady <= pgp0RxLinkReady and pgp0TxLinkReady; + + -- Invert Output CRC + crc0RxOut <= not crc0RxOutGtx; + crc0TxOut <= not crc0TxOutGtx; + + + -- TX CRC BLock + Tx_CRC0: CRC32 + generic map( + CRC_INIT => x"FFFFFFFF" + ) port map( + CRCOUT => crc0TxOutGtx, + CRCCLK => pgpClk, + CRCDATAVALID => crc0TxValid, + CRCDATAWIDTH => crc0TxWidth, + CRCIN => crc0TxInGtx, + CRCRESET => crc0TxRst + ); + + + -- RX CRC BLock + Rx_CRC0: CRC32 + generic map( + CRC_INIT => x"FFFFFFFF" + ) port map( + CRCOUT => crc0RxOutGtx, + CRCCLK => pgpClk, + CRCDATAVALID => crc0RxValid, + CRCDATAWIDTH => crc0RxWidth, + CRCIN => crc0RxInGtx, + CRCRESET => crc0RxRst + ); + + + -- RX Reset Control + U_Pgp2GtxRxRst0: Pgp2GtxPackage.Pgp2GtxRxRst + port map ( + gtxRxClk => pgpClk, + gtxRxRst => int0RxRst, + gtxRxReady => phy0RxReady, + gtxRxInit => phy0RxInit, + gtxLockDetect => phyLockDetect, + gtxRxElecIdle => phy0RxElecIdle, + gtxRxBuffStatus => phy0RxBuffStatus, + gtxRstDone => phy0RstDone, + gtxRxReset => phy0RxReset, + gtxRxCdrReset => phy0RxCdrReset + ); + + + -- TX Reset Control + U_Pgp2GtxTxRst0: Pgp2GtxPackage.Pgp2GtxTxRst + port map ( + gtxTxClk => pgpClk, + gtxTxRst => int0TxRst, + gtxTxReady => phy0TxReady, + gtxLockDetect => phyLockDetect, + gtxTxBuffStatus => phy0TxBuffStatus, + gtxRstDone => phy0RstDone, + gtxTxReset => phy0TxReset + ); + + + ------------------------------------------ + -- PGP Lane 1 + ------------------------------------------ + + -- PGP RX Block + U_Pgp2Rx1: Pgp2CorePackage.Pgp2Rx + generic map ( + RxLaneCnt => 1, + EnShortCells => EnShortCells + ) port map ( + pgpRxClk => pgpClk, + pgpRxReset => pgpReset, + pgpRxFlush => pgpFlush, + pgpRxLinkReady => pgp1RxLinkReady, + pgpRxCellError => pgp1RxCellError, + pgpRxLinkDown => pgp1RxLinkDown, + pgpRxLinkError => pgp1RxLinkError, + pgpRxOpCodeEn => pgp1RxOpCodeEn, + pgpRxOpCode => pgp1RxOpCode, + pgpRemLinkReady => pgp1RemLinkReady, + pgpRemData => pgp1RemData, + vcFrameRxSOF => vc1FrameRxSOF, + vcFrameRxEOF => vc1FrameRxEOF, + vcFrameRxEOFE => vc1FrameRxEOFE, + vcFrameRxData => vc1FrameRxData, + vc0FrameRxValid => vc10FrameRxValid, + vc0RemBuffAFull => vc10RemBuffAFull, + vc0RemBuffFull => vc10RemBuffFull, + vc1FrameRxValid => vc11FrameRxValid, + vc1RemBuffAFull => vc11RemBuffAFull, + vc1RemBuffFull => vc11RemBuffFull, + vc2FrameRxValid => vc12FrameRxValid, + vc2RemBuffAFull => vc12RemBuffAFull, + vc2RemBuffFull => vc12RemBuffFull, + vc3FrameRxValid => vc13FrameRxValid, + vc3RemBuffAFull => vc13RemBuffAFull, + vc3RemBuffFull => vc13RemBuffFull, + phyRxPolarity => phy1RxPolarity, + phyRxData => phy1RxData, + phyRxDataK => phy1RxDataK, + phyRxDispErr => phy1RxDispErr, + phyRxDecErr => phy1RxDecErr, + phyRxReady => phy1RxReady, + phyRxInit => phy1RxInit, + crcRxIn => crc1RxIn, + crcRxWidth => open, + crcRxInit => crc1RxInit, + crcRxValid => crc1RxValid, + crcRxOut => crc1RxOut, + debug => debug(127 downto 64) + ); + + + -- PGP TX Block + U_Pgp2Tx1: Pgp2CorePackage.Pgp2Tx + generic map ( + TxLaneCnt => 1, + VcInterleave => VcInterleave + ) port map ( + pgpTxClk => pgpClk, + pgpTxReset => pgpReset, + pgpTxFlush => pgpFlush, + pgpTxLinkReady => pgp1TxLinkReady, + pgpTxOpCodeEn => pgp1TxOpCodeEn, + pgpTxOpCode => pgp1TxOpCode, + pgpLocLinkReady => pgp1RxLinkReady, + pgpLocData => pgp1LocData, + vc0FrameTxValid => vc10FrameTxValid, + vc0FrameTxReady => vc10FrameTxReady, + vc0FrameTxSOF => vc10FrameTxSOF, + vc0FrameTxEOF => vc10FrameTxEOF, + vc0FrameTxEOFE => vc10FrameTxEOFE, + vc0FrameTxData => vc10FrameTxData, + vc0LocBuffAFull => vc10LocBuffAFull, + vc0LocBuffFull => vc10LocBuffFull, + vc1FrameTxValid => vc11FrameTxValid, + vc1FrameTxReady => vc11FrameTxReady, + vc1FrameTxSOF => vc11FrameTxSOF, + vc1FrameTxEOF => vc11FrameTxEOF, + vc1FrameTxEOFE => vc11FrameTxEOFE, + vc1FrameTxData => vc11FrameTxData, + vc1LocBuffAFull => vc11LocBuffAFull, + vc1LocBuffFull => vc11LocBuffFull, + vc2FrameTxValid => vc12FrameTxValid, + vc2FrameTxReady => vc12FrameTxReady, + vc2FrameTxSOF => vc12FrameTxSOF, + vc2FrameTxEOF => vc12FrameTxEOF, + vc2FrameTxEOFE => vc12FrameTxEOFE, + vc2FrameTxData => vc12FrameTxData, + vc2LocBuffAFull => vc12LocBuffAFull, + vc2LocBuffFull => vc12LocBuffFull, + vc3FrameTxValid => vc13FrameTxValid, + vc3FrameTxReady => vc13FrameTxReady, + vc3FrameTxSOF => vc13FrameTxSOF, + vc3FrameTxEOF => vc13FrameTxEOF, + vc3FrameTxEOFE => vc13FrameTxEOFE, + vc3FrameTxData => vc13FrameTxData, + vc3LocBuffAFull => vc13LocBuffAFull, + vc3LocBuffFull => vc13LocBuffFull, + phyTxData => phy1TxData, + phyTxDataK => phy1TxDataK, + phyTxReady => phy1TxReady, + crcTxIn => crc1TxIn, + crcTxInit => crc1TxInit, + crcTxValid => crc1TxValid, + crcTxOut => crc1TxOut, + debug => open + ); + + + -- Adapt CRC data width flag + crc1TxWidth <= "001"; + crc1RxWidth <= "001"; + crc1RxRst <= int1RxRst or crc1RxInit; + crc1TxRst <= int1TxRst or crc1TxInit; + + -- Pass CRC data in on proper bits + crc1TxInGtx(31 downto 24) <= crc1TxIn(7 downto 0); + crc1TxInGtx(23 downto 16) <= crc1TxIn(15 downto 8); + crc1TxInGtx(15 downto 0) <= (others=>'0'); + crc1RxInGtx(31 downto 24) <= crc1RxIn(7 downto 0); + crc1RxInGtx(23 downto 16) <= crc1RxIn(15 downto 8); + crc1RxInGtx(15 downto 0) <= (others=>'0'); + + -- Pll Resets + int1TxRst <= pll1TxRst or pgpReset; + int1RxRst <= pll1RxRst or pgpReset; + + -- PLL Lock + pll1RxReady <= phy1RxReady; + pll1TxReady <= phy1TxReady; + + -- Link Ready + pgp1LocLinkReady <= pgp1RxLinkReady and pgp1TxLinkReady; + + -- Invert Output CRC + crc1RxOut <= not crc1RxOutGtx; + crc1TxOut <= not crc1TxOutGtx; + + + -- TX CRC BLock + Tx_CRC1: CRC32 + generic map( + CRC_INIT => x"FFFFFFFF" + ) port map( + CRCOUT => crc1TxOutGtx, + CRCCLK => pgpClk, + CRCDATAVALID => crc1TxValid, + CRCDATAWIDTH => crc1TxWidth, + CRCIN => crc1TxInGtx, + CRCRESET => crc1TxRst + ); + + + -- RX CRC BLock + Rx_CRC1: CRC32 + generic map( + CRC_INIT => x"FFFFFFFF" + ) port map( + CRCOUT => crc1RxOutGtx, + CRCCLK => pgpClk, + CRCDATAVALID => crc1RxValid, + CRCDATAWIDTH => crc1RxWidth, + CRCIN => crc1RxInGtx, + CRCRESET => crc1RxRst + ); + + + -- RX Reset Control + U_Pgp2GtxRxRst1: Pgp2GtxPackage.Pgp2GtxRxRst + port map ( + gtxRxClk => pgpClk, + gtxRxRst => int1RxRst, + gtxRxReady => phy1RxReady, + gtxRxInit => phy1RxInit, + gtxLockDetect => phyLockDetect, + gtxRxElecIdle => phy1RxElecIdle, + gtxRxBuffStatus => phy1RxBuffStatus, + gtxRstDone => phy1RstDone, + gtxRxReset => phy1RxReset, + gtxRxCdrReset => phy1RxCdrReset + ); + + + -- TX Reset Control + U_Pgp2GtxTxRst1: Pgp2GtxPackage.Pgp2GtxTxRst + port map ( + gtxTxClk => pgpClk, + gtxTxRst => int1TxRst, + gtxTxReady => phy1TxReady, + gtxLockDetect => phyLockDetect, + gtxTxBuffStatus => phy1TxBuffStatus, + gtxRstDone => phy1RstDone, + gtxTxReset => phy1TxReset + ); + + + ----------------------------- GTX_DUAL Instance -------------------------- + UGtxDual:GTX_DUAL + generic map ( + + --_______________________ Simulation-Only Attributes ___________________ + + SIM_RECEIVER_DETECT_PASS_0 => TRUE, + SIM_RECEIVER_DETECT_PASS_1 => TRUE, + SIM_MODE => "FAST", + SIM_GTXRESET_SPEEDUP => 1, + SIM_PLL_PERDIV2 => x"140", + + --___________________________ Shared Attributes ________________________ + + -------------------------- Tile and PLL Attributes --------------------- + + CLK25_DIVIDER => 10, + CLKINDC_B => TRUE, + OOB_CLK_DIVIDER => 6, + OVERSAMPLE_MODE => FALSE, + PLL_DIVSEL_FB => 2, + PLL_DIVSEL_REF => 1, + CLKRCV_TRST => TRUE, + PLL_COM_CFG => x"21680a", + PLL_CP_CFG => x"00", + PLL_FB_DCCEN => FALSE, + PLL_LKDET_CFG => "101", + PLL_TDCC_CFG => "000", + PMA_COM_CFG => x"000000000000000000", + + --____________________ Transmit Interface Attributes ___________________ + + ------------------- TX Buffering and Phase Alignment ------------------- + + TX_BUFFER_USE_0 => TRUE, + TX_XCLK_SEL_0 => "TXOUT", + TXRX_INVERT_0 => "011", + + TX_BUFFER_USE_1 => TRUE, + TX_XCLK_SEL_1 => "TXOUT", + TXRX_INVERT_1 => "011", + + --------------------- TX Gearbox Settings ----------------------------- + + GEARBOX_ENDEC_0 => "000", + TXGEARBOX_USE_0 => FALSE, + + GEARBOX_ENDEC_1 => "000", + TXGEARBOX_USE_1 => FALSE, + + --------------------- TX Serial Line Rate settings --------------------- + + PLL_TXDIVSEL_OUT_0 => 1, + PLL_TXDIVSEL_OUT_1 => 1, + + --------------------- TX Driver and OOB signalling -------------------- + + CM_TRIM_0 => "10", + PMA_TX_CFG_0 => x"80082", + TX_DETECT_RX_CFG_0 => x"1832", + TX_IDLE_DELAY_0 => "010", + CM_TRIM_1 => "10", + PMA_TX_CFG_1 => x"80082", + TX_DETECT_RX_CFG_1 => x"1832", + TX_IDLE_DELAY_1 => "010", + + ------------------ TX Pipe Control for PCI Express/SATA --------------- + + COM_BURST_VAL_0 => "1111", + COM_BURST_VAL_1 => "1111", + + --_______________________ Receive Interface Attributes ________________ + + ------------ RX Driver,OOB signalling,Coupling and Eq,CDR ------------- + + AC_CAP_DIS_0 => TRUE, + OOBDETECT_THRESHOLD_0 => "111", + PMA_CDR_SCAN_0 => x"640403a", + PMA_RX_CFG_0 => x"0f44088", + RCV_TERM_GND_0 => FALSE, + RCV_TERM_VTTRX_0 => TRUE, + TERMINATION_IMP_0 => 50, + AC_CAP_DIS_1 => TRUE, + OOBDETECT_THRESHOLD_1 => "111", + PMA_CDR_SCAN_1 => x"640403a", + PMA_RX_CFG_1 => x"0f44088", + RCV_TERM_GND_1 => FALSE, + RCV_TERM_VTTRX_1 => TRUE, + TERMINATION_IMP_1 => 50, + TERMINATION_CTRL => "10100", + TERMINATION_OVRD => FALSE, + + ---------------- RX Decision Feedback Equalizer(DFE) ---------------- + + DFE_CFG_0 => "1001111011", + DFE_CFG_1 => "1001111011", + DFE_CAL_TIME => "00110", + + --------------------- RX Serial Line Rate Attributes ------------------ + + PLL_RXDIVSEL_OUT_0 => 1, + PLL_SATA_0 => FALSE, + PLL_RXDIVSEL_OUT_1 => 1, + PLL_SATA_1 => FALSE, + + ----------------------- PRBS Detection Attributes --------------------- + + PRBS_ERR_THRESHOLD_0 => x"00000001", + PRBS_ERR_THRESHOLD_1 => x"00000001", + + ---------------- Comma Detection and Alignment Attributes ------------- + + ALIGN_COMMA_WORD_0 => 2, + COMMA_10B_ENABLE_0 => "1111111111", + COMMA_DOUBLE_0 => FALSE, + DEC_MCOMMA_DETECT_0 => TRUE, + DEC_PCOMMA_DETECT_0 => TRUE, + DEC_VALID_COMMA_ONLY_0 => FALSE, + MCOMMA_10B_VALUE_0 => "1010000011", + MCOMMA_DETECT_0 => TRUE, + PCOMMA_10B_VALUE_0 => "0101111100", + PCOMMA_DETECT_0 => TRUE, + RX_SLIDE_MODE_0 => "PCS", + + ALIGN_COMMA_WORD_1 => 2, + COMMA_10B_ENABLE_1 => "1111111111", + COMMA_DOUBLE_1 => FALSE, + DEC_MCOMMA_DETECT_1 => TRUE, + DEC_PCOMMA_DETECT_1 => TRUE, + DEC_VALID_COMMA_ONLY_1 => FALSE, + MCOMMA_10B_VALUE_1 => "1010000011", + MCOMMA_DETECT_1 => TRUE, + PCOMMA_10B_VALUE_1 => "0101111100", + PCOMMA_DETECT_1 => TRUE, + RX_SLIDE_MODE_1 => "PCS", + + ------------------ RX Loss-of-sync State Machine Attributes ----------- + + RX_LOSS_OF_SYNC_FSM_0 => FALSE, + RX_LOS_INVALID_INCR_0 => 8, + RX_LOS_THRESHOLD_0 => 128, + RX_LOSS_OF_SYNC_FSM_1 => FALSE, + RX_LOS_INVALID_INCR_1 => 8, + RX_LOS_THRESHOLD_1 => 128, + + --------------------- RX Gearbox Settings ----------------------------- + + RXGEARBOX_USE_0 => FALSE, + RXGEARBOX_USE_1 => FALSE, + + -------------- RX Elastic Buffer and Phase alignment Attributes ------- + + PMA_RXSYNC_CFG_0 => x"00", + RX_BUFFER_USE_0 => TRUE, + RX_XCLK_SEL_0 => "RXREC", + PMA_RXSYNC_CFG_1 => x"00", + RX_BUFFER_USE_1 => TRUE, + RX_XCLK_SEL_1 => "RXREC", + + ------------------------ Clock Correction Attributes ------------------ + + CLK_CORRECT_USE_0 => TRUE, + CLK_COR_ADJ_LEN_0 => 4, + CLK_COR_DET_LEN_0 => 4, + CLK_COR_INSERT_IDLE_FLAG_0 => FALSE, + CLK_COR_KEEP_IDLE_0 => FALSE, + CLK_COR_MAX_LAT_0 => 48, + CLK_COR_MIN_LAT_0 => 36, + CLK_COR_PRECEDENCE_0 => TRUE, + CLK_COR_REPEAT_WAIT_0 => 0, + CLK_COR_SEQ_1_1_0 => "0110111100", + CLK_COR_SEQ_1_2_0 => "0100011100", + CLK_COR_SEQ_1_3_0 => "0100011100", + CLK_COR_SEQ_1_4_0 => "0100011100", + CLK_COR_SEQ_1_ENABLE_0 => "1111", + CLK_COR_SEQ_2_1_0 => "0000000000", + CLK_COR_SEQ_2_2_0 => "0000000000", + CLK_COR_SEQ_2_3_0 => "0000000000", + CLK_COR_SEQ_2_4_0 => "0000000000", + CLK_COR_SEQ_2_ENABLE_0 => "0000", + CLK_COR_SEQ_2_USE_0 => FALSE, + RX_DECODE_SEQ_MATCH_0 => TRUE, + + CLK_CORRECT_USE_1 => TRUE, + CLK_COR_ADJ_LEN_1 => 4, + CLK_COR_DET_LEN_1 => 4, + CLK_COR_INSERT_IDLE_FLAG_1 => FALSE, + CLK_COR_KEEP_IDLE_1 => FALSE, + CLK_COR_MAX_LAT_1 => 48, + CLK_COR_MIN_LAT_1 => 36, + CLK_COR_PRECEDENCE_1 => TRUE, + CLK_COR_REPEAT_WAIT_1 => 0, + CLK_COR_SEQ_1_1_1 => "0110111100", + CLK_COR_SEQ_1_2_1 => "0100011100", + CLK_COR_SEQ_1_3_1 => "0100011100", + CLK_COR_SEQ_1_4_1 => "0100011100", + CLK_COR_SEQ_1_ENABLE_1 => "1111", + CLK_COR_SEQ_2_1_1 => "0000000000", + CLK_COR_SEQ_2_2_1 => "0000000000", + CLK_COR_SEQ_2_3_1 => "0000000000", + CLK_COR_SEQ_2_4_1 => "0000000000", + CLK_COR_SEQ_2_ENABLE_1 => "0000", + CLK_COR_SEQ_2_USE_1 => FALSE, + RX_DECODE_SEQ_MATCH_1 => TRUE, + + ------------------------ Channel Bonding Attributes ------------------- + + CB2_INH_CC_PERIOD_0 => 8, + CHAN_BOND_KEEP_ALIGN_0 => FALSE, + CHAN_BOND_1_MAX_SKEW_0 => 1, + CHAN_BOND_2_MAX_SKEW_0 => 1, + CHAN_BOND_LEVEL_0 => 0, + CHAN_BOND_MODE_0 => "OFF", + CHAN_BOND_SEQ_1_1_0 => "0000000000", + CHAN_BOND_SEQ_1_2_0 => "0000000000", + CHAN_BOND_SEQ_1_3_0 => "0000000000", + CHAN_BOND_SEQ_1_4_0 => "0000000000", + CHAN_BOND_SEQ_1_ENABLE_0 => "0000", + CHAN_BOND_SEQ_2_1_0 => "0000000000", + CHAN_BOND_SEQ_2_2_0 => "0000000000", + CHAN_BOND_SEQ_2_3_0 => "0000000000", + CHAN_BOND_SEQ_2_4_0 => "0000000000", + CHAN_BOND_SEQ_2_ENABLE_0 => "0000", + CHAN_BOND_SEQ_2_USE_0 => FALSE, + CHAN_BOND_SEQ_LEN_0 => 1, + PCI_EXPRESS_MODE_0 => FALSE, + + CB2_INH_CC_PERIOD_1 => 8, + CHAN_BOND_KEEP_ALIGN_1 => FALSE, + CHAN_BOND_1_MAX_SKEW_1 => 1, + CHAN_BOND_2_MAX_SKEW_1 => 1, + CHAN_BOND_LEVEL_1 => 0, + CHAN_BOND_MODE_1 => "OFF", + CHAN_BOND_SEQ_1_1_1 => "0000000000", + CHAN_BOND_SEQ_1_2_1 => "0000000000", + CHAN_BOND_SEQ_1_3_1 => "0000000000", + CHAN_BOND_SEQ_1_4_1 => "0000000000", + CHAN_BOND_SEQ_1_ENABLE_1 => "0000", + CHAN_BOND_SEQ_2_1_1 => "0000000000", + CHAN_BOND_SEQ_2_2_1 => "0000000000", + CHAN_BOND_SEQ_2_3_1 => "0000000000", + CHAN_BOND_SEQ_2_4_1 => "0000000000", + CHAN_BOND_SEQ_2_ENABLE_1 => "0000", + CHAN_BOND_SEQ_2_USE_1 => FALSE, + CHAN_BOND_SEQ_LEN_1 => 1, + PCI_EXPRESS_MODE_1 => FALSE, + + -------- RX Attributes to Control Reset after Electrical Idle ------ + + RX_EN_IDLE_HOLD_DFE_0 => TRUE, + RX_EN_IDLE_RESET_BUF_0 => TRUE, + RX_IDLE_HI_CNT_0 => "1000", + RX_IDLE_LO_CNT_0 => "0000", + RX_EN_IDLE_HOLD_DFE_1 => TRUE, + RX_EN_IDLE_RESET_BUF_1 => TRUE, + RX_IDLE_HI_CNT_1 => "1000", + RX_IDLE_LO_CNT_1 => "0000", + CDR_PH_ADJ_TIME => "01010", + RX_EN_IDLE_RESET_FR => TRUE, + RX_EN_IDLE_HOLD_CDR => FALSE, + RX_EN_IDLE_RESET_PH => TRUE, + + ------------------ RX Attributes for PCI Express/SATA --------------- + + RX_STATUS_FMT_0 => "PCIE", + SATA_BURST_VAL_0 => "100", + SATA_IDLE_VAL_0 => "100", + SATA_MAX_BURST_0 => 7, + SATA_MAX_INIT_0 => 22, + SATA_MAX_WAKE_0 => 7, + SATA_MIN_BURST_0 => 4, + SATA_MIN_INIT_0 => 12, + SATA_MIN_WAKE_0 => 4, + TRANS_TIME_FROM_P2_0 => x"003C", + TRANS_TIME_NON_P2_0 => x"0019", + TRANS_TIME_TO_P2_0 => x"0064", + + RX_STATUS_FMT_1 => "PCIE", + SATA_BURST_VAL_1 => "100", + SATA_IDLE_VAL_1 => "100", + SATA_MAX_BURST_1 => 7, + SATA_MAX_INIT_1 => 22, + SATA_MAX_WAKE_1 => 7, + SATA_MIN_BURST_1 => 4, + SATA_MIN_INIT_1 => 12, + SATA_MIN_WAKE_1 => 4, + TRANS_TIME_FROM_P2_1 => x"003C", + TRANS_TIME_NON_P2_1 => x"0019", + TRANS_TIME_TO_P2_1 => x"0064" + + ) port map ( + + ------------------------ Loopback and Powerdown Ports ---------------------- + LOOPBACK0(0) => '0', + LOOPBACK0(1) => gtxLoopback(0), + LOOPBACK0(2) => '0', + LOOPBACK1(0) => '0', + LOOPBACK1(1) => gtxLoopback(1), + LOOPBACK1(2) => '0', + RXPOWERDOWN0 => (others=>'0'), + RXPOWERDOWN1 => (others=>'0'), + TXPOWERDOWN0 => (others=>'0'), + TXPOWERDOWN1 => (others=>'0'), + -------------- Receive Ports - 64b66b and 64b67b Gearbox Ports ------------- + RXDATAVALID0 => open, + RXDATAVALID1 => open, + RXGEARBOXSLIP0 => '0', + RXGEARBOXSLIP1 => '0', + RXHEADER0 => open, + RXHEADER1 => open, + RXHEADERVALID0 => open, + RXHEADERVALID1 => open, + RXSTARTOFSEQ0 => open, + RXSTARTOFSEQ1 => open, + ----------------------- Receive Ports - 8b10b Decoder ---------------------- + RXCHARISCOMMA0 => open, + RXCHARISCOMMA1 => open, + RXCHARISK0(1 downto 0) => phy0RxDataK, + RXCHARISK0(3 downto 2) => open, + RXCHARISK1(1 downto 0) => phy1RxDataK, + RXCHARISK1(3 downto 2) => open, + RXDEC8B10BUSE0 => '1', + RXDEC8B10BUSE1 => '1', + RXDISPERR0(1 downto 0) => phy0RxDispErr, + RXDISPERR0(3 downto 2) => open, + RXDISPERR1(1 downto 0) => phy1RxDispErr, + RXDISPERR1(3 downto 2) => open, + RXNOTINTABLE0(1 downto 0) => phy0RxDecErr, + RXNOTINTABLE0(3 downto 2) => open, + RXNOTINTABLE1(1 downto 0) => phy1RxDecErr, + RXNOTINTABLE1(3 downto 2) => open, + RXRUNDISP0 => open, + RXRUNDISP1 => open, + ------------------- Receive Ports - Channel Bonding Ports ------------------ + RXCHANBONDSEQ0 => open, + RXCHANBONDSEQ1 => open, + RXCHBONDI0 => (others=>'0'), + RXCHBONDI1 => (others=>'0'), + RXCHBONDO0 => open, + RXCHBONDO1 => open, + RXENCHANSYNC0 => '0', + RXENCHANSYNC1 => '0', + ------------------- Receive Ports - Clock Correction Ports ----------------- + RXCLKCORCNT0 => open, + RXCLKCORCNT1 => open, + --------------- Receive Ports - Comma Detection and Alignment -------------- + RXBYTEISALIGNED0 => open, + RXBYTEISALIGNED1 => open, + RXBYTEREALIGN0 => open, + RXBYTEREALIGN1 => open, + RXCOMMADET0 => open, + RXCOMMADET1 => open, + RXCOMMADETUSE0 => '1', + RXCOMMADETUSE1 => '1', + RXENMCOMMAALIGN0 => '1', + RXENMCOMMAALIGN1 => '1', + RXENPCOMMAALIGN0 => '1', + RXENPCOMMAALIGN1 => '1', + RXSLIDE0 => '0', + RXSLIDE1 => '0', + ----------------------- Receive Ports - PRBS Detection --------------------- + PRBSCNTRESET0 => '0', + PRBSCNTRESET1 => '0', + RXENPRBSTST0 => (others=>'0'), + RXENPRBSTST1 => (others=>'0'), + RXPRBSERR0 => open, + RXPRBSERR1 => open, + ------------------- Receive Ports - RX Data Path interface ----------------- + RXDATA0(15 downto 0) => phy0RxData, + RXDATA0(31 downto 16) => open, + RXDATA1(15 downto 0) => phy1RxData, + RXDATA1(31 downto 16) => open, + RXDATAWIDTH0 => "01", + RXDATAWIDTH1 => "01", + RXRECCLK0 => int0RxRecClk, + RXRECCLK1 => int1RxRecClk, + RXRESET0 => phy0RxReset, + RXRESET1 => phy1RxReset, + RXUSRCLK0 => pgpClk, + RXUSRCLK1 => pgpClk, + RXUSRCLK20 => pgpClk, + RXUSRCLK21 => pgpClk, + ------------ Receive Ports - RX Decision Feedback Equalizer(DFE) ----------- + DFECLKDLYADJ0 => (others=>'0'), + DFECLKDLYADJ1 => (others=>'0'), + DFECLKDLYADJMONITOR0 => open, + DFECLKDLYADJMONITOR1 => open, + DFEEYEDACMONITOR0 => open, + DFEEYEDACMONITOR1 => open, + DFESENSCAL0 => open, + DFESENSCAL1 => open, + DFETAP10 => (others=>'0'), + DFETAP11 => (others=>'0'), + DFETAP1MONITOR0 => open, + DFETAP1MONITOR1 => open, + DFETAP20 => (others=>'0'), + DFETAP21 => (others=>'0'), + DFETAP2MONITOR0 => open, + DFETAP2MONITOR1 => open, + DFETAP30 => (others=>'0'), + DFETAP31 => (others=>'0'), + DFETAP3MONITOR0 => open, + DFETAP3MONITOR1 => open, + DFETAP40 => (others=>'0'), + DFETAP41 => (others=>'0'), + DFETAP4MONITOR0 => open, + DFETAP4MONITOR1 => open, + ------- Receive Ports - RX Driver,OOB signalling,Coupling and Eq.,CDR ------ + RXCDRRESET0 => phy0RxCdrReset, + RXCDRRESET1 => phy1RxCdrReset, + RXELECIDLE0 => phy0RxElecIdle, + RXELECIDLE1 => phy1RxElecIdle, + RXENEQB0 => '0', + RXENEQB1 => '0', + RXEQMIX0 => (others=>'0'), + RXEQMIX1 => (others=>'0'), + RXEQPOLE0 => (others=>'0'), + RXEQPOLE1 => (others=>'0'), + RXN0 => gtxRxN(0), + RXN1 => gtxRxN(1), + RXP0 => gtxRxP(0), + RXP1 => gtxRxP(1), + -------- Receive Ports - RX Elastic Buffer and Phase Alignment Ports ------- + RXBUFRESET0 => '0', + RXBUFRESET1 => '0', + RXBUFSTATUS0 => phy0RxBuffStatus, + RXBUFSTATUS1 => phy1RxBuffStatus, + RXCHANISALIGNED0 => open, + RXCHANISALIGNED1 => open, + RXCHANREALIGN0 => open, + RXCHANREALIGN1 => open, + RXENPMAPHASEALIGN0 => '0', + RXENPMAPHASEALIGN1 => '0', + RXPMASETPHASE0 => '0', + RXPMASETPHASE1 => '0', + RXSTATUS0 => open, + RXSTATUS1 => open, + --------------- Receive Ports - RX Loss-of-sync State Machine -------------- + RXLOSSOFSYNC0 => open, + RXLOSSOFSYNC1 => open, + ---------------------- Receive Ports - RX Oversampling --------------------- + RXENSAMPLEALIGN0 => '0', + RXENSAMPLEALIGN1 => '0', + RXOVERSAMPLEERR0 => open, + RXOVERSAMPLEERR1 => open, + -------------- Receive Ports - RX Pipe Control for PCI Express ------------- + PHYSTATUS0 => open, + PHYSTATUS1 => open, + RXVALID0 => open, + RXVALID1 => open, + ----------------- Receive Ports - RX Polarity Control Ports ---------------- + RXPOLARITY0 => phyRxPolarity(0), + RXPOLARITY1 => phyRxPolarity(1), + ------------- Shared Ports - Dynamic Reconfiguration Port (DRP) ------------ + DADDR => (others=>'0'), + DCLK => '0', + DEN => '0', + DI => (others=>'0'), + DO => open, + DRDY => open, + DWE => '0', + --------------------- Shared Ports - Tile and PLL Ports -------------------- + CLKIN => gtxClkIn, + GTXRESET => pgpReset, + GTXTEST => "10000000000000", + INTDATAWIDTH => '1', + PLLLKDET => phyLockDetect, + PLLLKDETEN => '1', + PLLPOWERDOWN => '0', + REFCLKOUT => tmpRefClkOut, + REFCLKPWRDNB => '1', + RESETDONE0 => phy0RstDone, + RESETDONE1 => phy1RstDone, + -------------- Transmit Ports - 64b66b and 64b67b Gearbox Ports ------------ + TXGEARBOXREADY0 => open, + TXGEARBOXREADY1 => open, + TXHEADER0 => (others=>'0'), + TXHEADER1 => (others=>'0'), + TXSEQUENCE0 => (others=>'0'), + TXSEQUENCE1 => (others=>'0'), + TXSTARTSEQ0 => '0', + TXSTARTSEQ1 => '0', + ---------------- Transmit Ports - 8b10b Encoder Control Ports -------------- + TXBYPASS8B10B0 => (others=>'0'), + TXBYPASS8B10B1 => (others=>'0'), + TXCHARDISPMODE0 => (others=>'0'), + TXCHARDISPMODE1 => (others=>'0'), + TXCHARDISPVAL0 => (others=>'0'), + TXCHARDISPVAL1 => (others=>'0'), + TXCHARISK0(1 downto 0) => phy0TxDataK, + TXCHARISK0(3 downto 2) => (others=>'0'), + TXCHARISK1(1 downto 0) => phy1TxDataK, + TXCHARISK1(3 downto 2) => (others=>'0'), + TXENC8B10BUSE0 => '1', + TXENC8B10BUSE1 => '1', + TXKERR0 => open, + TXKERR1 => open, + TXRUNDISP0 => open, + TXRUNDISP1 => open, + ------------- Transmit Ports - TX Buffering and Phase Alignment ------------ + TXBUFSTATUS0 => phy0TxBuffStatus, + TXBUFSTATUS1 => phy1TxBuffStatus, + ------------------ Transmit Ports - TX Data Path interface ----------------- + TXDATA0(15 downto 0) => phy0TxData, + TXDATA0(31 downto 16) => (others=>'0'), + TXDATA1(15 downto 0) => phy1TxData, + TXDATA1(31 downto 16) => (others=>'0'), + TXDATAWIDTH0 => "01", + TXDATAWIDTH1 => "01", + TXOUTCLK0 => open, + TXOUTCLK1 => open, + TXRESET0 => phy0TxReset, + TXRESET1 => phy1TxReset, + TXUSRCLK0 => pgpClk, + TXUSRCLK1 => pgpClk, + TXUSRCLK20 => pgpClk, + TXUSRCLK21 => pgpClk, + --------------- Transmit Ports - TX Driver and OOB signalling -------------- + TXBUFDIFFCTRL0 => "100", -- 800mV + TXBUFDIFFCTRL1 => "100", + TXDIFFCTRL0 => "100", + TXDIFFCTRL1 => "100", + TXINHIBIT0 => '0', + TXINHIBIT1 => '0', + TXN0 => gtxTxN(0), + TXN1 => gtxTxN(1), + TXP0 => gtxTxP(0), + TXP1 => gtxTxP(1), + TXPREEMPHASIS0 => "0011", -- 4.5% + TXPREEMPHASIS1 => "0011", + -------- Transmit Ports - TX Elastic Buffer and Phase Alignment Ports ------ + TXENPMAPHASEALIGN0 => '0', + TXENPMAPHASEALIGN1 => '0', + TXPMASETPHASE0 => '0', + TXPMASETPHASE1 => '0', + --------------------- Transmit Ports - TX PRBS Generator ------------------- + TXENPRBSTST0 => (others=>'0'), + TXENPRBSTST1 => (others=>'0'), + -------------------- Transmit Ports - TX Polarity Control ------------------ + TXPOLARITY0 => '0', + TXPOLARITY1 => '0', + ----------------- Transmit Ports - TX Ports for PCI Express ---------------- + TXDETECTRX0 => '0', + TXDETECTRX1 => '0', + TXELECIDLE0 => '0', + TXELECIDLE1 => '0', + --------------------- Transmit Ports - TX Ports for SATA ------------------- + TXCOMSTART0 => '0', + TXCOMSTART1 => '0', + TXCOMTYPE0 => '0', + TXCOMTYPE1 => '0' + ); + + -- Global Buffer For Ref Clock Output + U_RefClkBuff: BUFG port map ( + O => gtxRefClkOut, + I => tmpRefClkOut + ); + gtxRxRecClk(0) <= int0RxRecClk; + gtxRxRecClk(1) <= int1RxRecClk; + +end Pgp2GtxDual; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2GtxPackage.vhd b/rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2GtxPackage.vhd new file mode 100755 index 00000000..32a7ce7e --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2GtxPackage.vhd @@ -0,0 +1,391 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, GTX Package +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2GtxPackage.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 11/23/2009 +------------------------------------------------------------------------------- +-- Description: +-- GTX Components package. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 11/23/2009: created. +-- 01/13/2010: Added received init line to help linking. +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; + +package Pgp2GtxPackage is + + -- 16-bit wrapper + component Pgp2Gtx16 + generic ( + EnShortCells : integer := 1; -- Enable short non-EOF cells + VcInterleave : integer := 1 -- Interleave Frames + ); + port ( + pgpClk : in std_logic; -- 156.25Mhz master clock + pgpReset : in std_logic; -- Synchronous reset input + pgpFlush : in std_logic; -- Frame state flush + pllTxRst : in std_logic; -- Reset transmit PLL logic + pllRxRst : in std_logic; -- Reset receive PLL logic + pllRxReady : out std_logic; -- MGT Receive logic is ready + pllTxReady : out std_logic; -- MGT Transmit logic is ready + pgpRemData : out std_logic_vector(7 downto 0); -- Far end side User Data + pgpLocData : in std_logic_vector(7 downto 0); -- Far end side User Data + pgpTxOpCodeEn : in std_logic; -- Opcode receive enable + pgpTxOpCode : in std_logic_vector(7 downto 0); -- Opcode receive value + pgpRxOpCodeEn : out std_logic; -- Opcode receive enable + pgpRxOpCode : out std_logic_vector(7 downto 0); -- Opcode receive value + pgpLocLinkReady : out std_logic; -- Local Link is ready + pgpRemLinkReady : out std_logic; -- Far end side has link + pgpRxCellError : out std_logic; -- A cell error has occured + pgpRxLinkDown : out std_logic; -- A link down event has occured + pgpRxLinkError : out std_logic; -- A link error has occured + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc0FrameTxReady : out std_logic; -- PGP is ready + vc0FrameTxSOF : in std_logic; -- User frame data start of frame + vc0FrameTxEOF : in std_logic; -- User frame data end of frame + vc0FrameTxEOFE : in std_logic; -- User frame data error + vc0FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc0LocBuffAFull : in std_logic; -- Remote buffer almost full + vc0LocBuffFull : in std_logic; -- Remote buffer full + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxReady : out std_logic; -- PGP is ready + vc1FrameTxSOF : in std_logic; -- User frame data start of frame + vc1FrameTxEOF : in std_logic; -- User frame data end of frame + vc1FrameTxEOFE : in std_logic; -- User frame data error + vc1FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc1LocBuffAFull : in std_logic; -- Remote buffer almost full + vc1LocBuffFull : in std_logic; -- Remote buffer full + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxReady : out std_logic; -- PGP is ready + vc2FrameTxSOF : in std_logic; -- User frame data start of frame + vc2FrameTxEOF : in std_logic; -- User frame data end of frame + vc2FrameTxEOFE : in std_logic; -- User frame data error + vc2FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc2LocBuffAFull : in std_logic; -- Remote buffer almost full + vc2LocBuffFull : in std_logic; -- Remote buffer full + vc3FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxReady : out std_logic; -- PGP is ready + vc3FrameTxSOF : in std_logic; -- User frame data start of frame + vc3FrameTxEOF : in std_logic; -- User frame data end of frame + vc3FrameTxEOFE : in std_logic; -- User frame data error + vc3FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc3LocBuffAFull : in std_logic; -- Remote buffer almost full + vc3LocBuffFull : in std_logic; -- Remote buffer full + vcFrameRxSOF : out std_logic; -- PGP frame data start of frame + vcFrameRxEOF : out std_logic; -- PGP frame data end of frame + vcFrameRxEOFE : out std_logic; -- PGP frame data error + vcFrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc0FrameRxValid : out std_logic; -- PGP frame data is valid + vc0RemBuffAFull : out std_logic; -- Remote buffer almost full + vc0RemBuffFull : out std_logic; -- Remote buffer full + vc1FrameRxValid : out std_logic; -- PGP frame data is valid + vc1RemBuffAFull : out std_logic; -- Remote buffer almost full + vc1RemBuffFull : out std_logic; -- Remote buffer full + vc2FrameRxValid : out std_logic; -- PGP frame data is valid + vc2RemBuffAFull : out std_logic; -- Remote buffer almost full + vc2RemBuffFull : out std_logic; -- Remote buffer full + vc3FrameRxValid : out std_logic; -- PGP frame data is valid + vc3RemBuffAFull : out std_logic; -- Remote buffer almost full + vc3RemBuffFull : out std_logic; -- Remote buffer full + gtxLoopback : in std_logic; -- GTX Serial Loopback Control + gtxClkIn : in std_logic; -- GTX Reference Clock In + gtxRefClkOut : out std_logic; -- GTX Reference Clock Output + gtxRxRecClk : out std_logic; -- GTX Rx Recovered Clock + gtxRxN : in std_logic; -- GTX Serial Receive Negative + gtxRxP : in std_logic; -- GTX Serial Receive Positive + gtxTxN : out std_logic; -- GTX Serial Transmit Negative + gtxTxP : out std_logic; -- GTX Serial Transmit Positive + debug : out std_logic_vector(63 downto 0) + ); + end component; + + -- 16-bit wrapper, port b + component Pgp2Gtx16B + generic ( + EnShortCells : integer := 1; -- Enable short non-EOF cells + VcInterleave : integer := 1 -- Interleave Frames + ); + port ( + pgpClk : in std_logic; -- 156.25Mhz master clock + pgpReset : in std_logic; -- Synchronous reset input + pgpFlush : in std_logic; -- Frame state flush + pllTxRst : in std_logic; -- Reset transmit PLL logic + pllRxRst : in std_logic; -- Reset receive PLL logic + pllRxReady : out std_logic; -- MGT Receive logic is ready + pllTxReady : out std_logic; -- MGT Transmit logic is ready + pgpRemData : out std_logic_vector(7 downto 0); -- Far end side User Data + pgpLocData : in std_logic_vector(7 downto 0); -- Far end side User Data + pgpTxOpCodeEn : in std_logic; -- Opcode receive enable + pgpTxOpCode : in std_logic_vector(7 downto 0); -- Opcode receive value + pgpRxOpCodeEn : out std_logic; -- Opcode receive enable + pgpRxOpCode : out std_logic_vector(7 downto 0); -- Opcode receive value + pgpLocLinkReady : out std_logic; -- Local Link is ready + pgpRemLinkReady : out std_logic; -- Far end side has link + pgpRxCellError : out std_logic; -- A cell error has occured + pgpRxLinkDown : out std_logic; -- A link down event has occured + pgpRxLinkError : out std_logic; -- A link error has occured + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc0FrameTxReady : out std_logic; -- PGP is ready + vc0FrameTxSOF : in std_logic; -- User frame data start of frame + vc0FrameTxEOF : in std_logic; -- User frame data end of frame + vc0FrameTxEOFE : in std_logic; -- User frame data error + vc0FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc0LocBuffAFull : in std_logic; -- Remote buffer almost full + vc0LocBuffFull : in std_logic; -- Remote buffer full + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxReady : out std_logic; -- PGP is ready + vc1FrameTxSOF : in std_logic; -- User frame data start of frame + vc1FrameTxEOF : in std_logic; -- User frame data end of frame + vc1FrameTxEOFE : in std_logic; -- User frame data error + vc1FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc1LocBuffAFull : in std_logic; -- Remote buffer almost full + vc1LocBuffFull : in std_logic; -- Remote buffer full + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxReady : out std_logic; -- PGP is ready + vc2FrameTxSOF : in std_logic; -- User frame data start of frame + vc2FrameTxEOF : in std_logic; -- User frame data end of frame + vc2FrameTxEOFE : in std_logic; -- User frame data error + vc2FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc2LocBuffAFull : in std_logic; -- Remote buffer almost full + vc2LocBuffFull : in std_logic; -- Remote buffer full + vc3FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxReady : out std_logic; -- PGP is ready + vc3FrameTxSOF : in std_logic; -- User frame data start of frame + vc3FrameTxEOF : in std_logic; -- User frame data end of frame + vc3FrameTxEOFE : in std_logic; -- User frame data error + vc3FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc3LocBuffAFull : in std_logic; -- Remote buffer almost full + vc3LocBuffFull : in std_logic; -- Remote buffer full + vcFrameRxSOF : out std_logic; -- PGP frame data start of frame + vcFrameRxEOF : out std_logic; -- PGP frame data end of frame + vcFrameRxEOFE : out std_logic; -- PGP frame data error + vcFrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc0FrameRxValid : out std_logic; -- PGP frame data is valid + vc0RemBuffAFull : out std_logic; -- Remote buffer almost full + vc0RemBuffFull : out std_logic; -- Remote buffer full + vc1FrameRxValid : out std_logic; -- PGP frame data is valid + vc1RemBuffAFull : out std_logic; -- Remote buffer almost full + vc1RemBuffFull : out std_logic; -- Remote buffer full + vc2FrameRxValid : out std_logic; -- PGP frame data is valid + vc2RemBuffAFull : out std_logic; -- Remote buffer almost full + vc2RemBuffFull : out std_logic; -- Remote buffer full + vc3FrameRxValid : out std_logic; -- PGP frame data is valid + vc3RemBuffAFull : out std_logic; -- Remote buffer almost full + vc3RemBuffFull : out std_logic; -- Remote buffer full + gtxLoopback : in std_logic; -- GTX Serial Loopback Control + gtxClkIn : in std_logic; -- GTX Reference Clock In + gtxRefClkOut : out std_logic; -- GTX Reference Clock Output + gtxRxRecClk : out std_logic; -- GTX Rx Recovered Clock + gtxRxN : in std_logic; -- GTX Serial Receive Negative + gtxRxP : in std_logic; -- GTX Serial Receive Positive + gtxTxN : out std_logic; -- GTX Serial Transmit Negative + gtxTxP : out std_logic; -- GTX Serial Transmit Positive + debug : out std_logic_vector(63 downto 0) + ); + end component; + + -- Dual Channel Wrapper + component Pgp2GtxDual + generic ( + EnShortCells : integer := 1; -- Enable short non-EOF cells + VcInterleave : integer := 1 -- Interleave Frames + ); + port ( + pgpClk : in std_logic; -- Pgp master clock + pgpReset : in std_logic; -- Synchronous reset input + pgpFlush : in std_logic; -- Frame state flush + pll0TxRst : in std_logic; -- Reset transmit PLL logic + pll0RxRst : in std_logic; -- Reset receive PLL logic + pll0RxReady : out std_logic; -- MGT Receive logic is ready + pll0TxReady : out std_logic; -- MGT Transmit logic is ready + pgp0RemData : out std_logic_vector(7 downto 0); -- Far end side User Data + pgp0LocData : in std_logic_vector(7 downto 0); -- Far end side User Data + pgp0TxOpCodeEn : in std_logic; -- Opcode receive enable + pgp0TxOpCode : in std_logic_vector(7 downto 0); -- Opcode receive value + pgp0RxOpCodeEn : out std_logic; -- Opcode receive enable + pgp0RxOpCode : out std_logic_vector(7 downto 0); -- Opcode receive value + pgp0LocLinkReady : out std_logic; -- Local Link is ready + pgp0RemLinkReady : out std_logic; -- Far end side has link + pgp0RxCellError : out std_logic; -- A cell error has occured + pgp0RxLinkDown : out std_logic; -- A link down event has occured + pgp0RxLinkError : out std_logic; -- A link error has occured + vc00FrameTxValid : in std_logic; -- User frame data is valid + vc00FrameTxReady : out std_logic; -- PGP is ready + vc00FrameTxSOF : in std_logic; -- User frame data start of frame + vc00FrameTxEOF : in std_logic; -- User frame data end of frame + vc00FrameTxEOFE : in std_logic; -- User frame data error + vc00FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc00LocBuffAFull : in std_logic; -- Local buffer almost full + vc00LocBuffFull : in std_logic; -- Local buffer full + vc01FrameTxValid : in std_logic; -- User frame data is valid + vc01FrameTxReady : out std_logic; -- PGP is ready + vc01FrameTxSOF : in std_logic; -- User frame data start of frame + vc01FrameTxEOF : in std_logic; -- User frame data end of frame + vc01FrameTxEOFE : in std_logic; -- User frame data error + vc01FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc01LocBuffAFull : in std_logic; -- Local buffer almost full + vc01LocBuffFull : in std_logic; -- Local buffer full + vc02FrameTxValid : in std_logic; -- User frame data is valid + vc02FrameTxReady : out std_logic; -- PGP is ready + vc02FrameTxSOF : in std_logic; -- User frame data start of frame + vc02FrameTxEOF : in std_logic; -- User frame data end of frame + vc02FrameTxEOFE : in std_logic; -- User frame data error + vc02FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc02LocBuffAFull : in std_logic; -- Local buffer almost full + vc02LocBuffFull : in std_logic; -- Local buffer full + vc03FrameTxValid : in std_logic; -- User frame data is valid + vc03FrameTxReady : out std_logic; -- PGP is ready + vc03FrameTxSOF : in std_logic; -- User frame data start of frame + vc03FrameTxEOF : in std_logic; -- User frame data end of frame + vc03FrameTxEOFE : in std_logic; -- User frame data error + vc03FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc03LocBuffAFull : in std_logic; -- Local buffer almost full + vc03LocBuffFull : in std_logic; -- Local buffer full + vc0FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc0FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc0FrameRxEOFE : out std_logic; -- PGP frame data error + vc0FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc00FrameRxValid : out std_logic; -- PGP frame data is valid + vc00RemBuffAFull : out std_logic; -- Remote buffer almost full + vc00RemBuffFull : out std_logic; -- Remote buffer full + vc01FrameRxValid : out std_logic; -- PGP frame data is valid + vc01RemBuffAFull : out std_logic; -- Remote buffer almost full + vc01RemBuffFull : out std_logic; -- Remote buffer full + vc02FrameRxValid : out std_logic; -- PGP frame data is valid + vc02RemBuffAFull : out std_logic; -- Remote buffer almost full + vc02RemBuffFull : out std_logic; -- Remote buffer full + vc03FrameRxValid : out std_logic; -- PGP frame data is valid + vc03RemBuffAFull : out std_logic; -- Remote buffer almost full + vc03RemBuffFull : out std_logic; -- Remote buffer full + pll1TxRst : in std_logic; -- Reset transmit PLL logic + pll1RxRst : in std_logic; -- Reset receive PLL logic + pll1RxReady : out std_logic; -- MGT Receive logic is ready + pll1TxReady : out std_logic; -- MGT Transmit logic is ready + pgp1RemData : out std_logic_vector(7 downto 0); -- Far end side User Data + pgp1LocData : in std_logic_vector(7 downto 0); -- Far end side User Data + pgp1TxOpCodeEn : in std_logic; -- Opcode receive enable + pgp1TxOpCode : in std_logic_vector(7 downto 0); -- Opcode receive value + pgp1RxOpCodeEn : out std_logic; -- Opcode receive enable + pgp1RxOpCode : out std_logic_vector(7 downto 0); -- Opcode receive value + pgp1LocLinkReady : out std_logic; -- Local Link is ready + pgp1RemLinkReady : out std_logic; -- Far end side has link + pgp1RxCellError : out std_logic; -- A cell error has occured + pgp1RxLinkDown : out std_logic; -- A link down event has occured + pgp1RxLinkError : out std_logic; -- A link error has occured + vc10FrameTxValid : in std_logic; -- User frame data is valid + vc10FrameTxReady : out std_logic; -- PGP is ready + vc10FrameTxSOF : in std_logic; -- User frame data start of frame + vc10FrameTxEOF : in std_logic; -- User frame data end of frame + vc10FrameTxEOFE : in std_logic; -- User frame data error + vc10FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc10LocBuffAFull : in std_logic; -- Local buffer almost full + vc10LocBuffFull : in std_logic; -- Local buffer full + vc11FrameTxValid : in std_logic; -- User frame data is valid + vc11FrameTxReady : out std_logic; -- PGP is ready + vc11FrameTxSOF : in std_logic; -- User frame data start of frame + vc11FrameTxEOF : in std_logic; -- User frame data end of frame + vc11FrameTxEOFE : in std_logic; -- User frame data error + vc11FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc11LocBuffAFull : in std_logic; -- Local buffer almost full + vc11LocBuffFull : in std_logic; -- Local buffer full + vc12FrameTxValid : in std_logic; -- User frame data is valid + vc12FrameTxReady : out std_logic; -- PGP is ready + vc12FrameTxSOF : in std_logic; -- User frame data start of frame + vc12FrameTxEOF : in std_logic; -- User frame data end of frame + vc12FrameTxEOFE : in std_logic; -- User frame data error + vc12FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc12LocBuffAFull : in std_logic; -- Local buffer almost full + vc12LocBuffFull : in std_logic; -- Local buffer full + vc13FrameTxValid : in std_logic; -- User frame data is valid + vc13FrameTxReady : out std_logic; -- PGP is ready + vc13FrameTxSOF : in std_logic; -- User frame data start of frame + vc13FrameTxEOF : in std_logic; -- User frame data end of frame + vc13FrameTxEOFE : in std_logic; -- User frame data error + vc13FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc13LocBuffAFull : in std_logic; -- Local buffer almost full + vc13LocBuffFull : in std_logic; -- Local buffer full + vc1FrameRxSOF : out std_logic; -- PGP frame data start of frame + vc1FrameRxEOF : out std_logic; -- PGP frame data end of frame + vc1FrameRxEOFE : out std_logic; -- PGP frame data error + vc1FrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc10FrameRxValid : out std_logic; -- PGP frame data is valid + vc10RemBuffAFull : out std_logic; -- Remote buffer almost full + vc10RemBuffFull : out std_logic; -- Remote buffer full + vc11FrameRxValid : out std_logic; -- PGP frame data is valid + vc11RemBuffAFull : out std_logic; -- Remote buffer almost full + vc11RemBuffFull : out std_logic; -- Remote buffer full + vc12FrameRxValid : out std_logic; -- PGP frame data is valid + vc12RemBuffAFull : out std_logic; -- Remote buffer almost full + vc12RemBuffFull : out std_logic; -- Remote buffer full + vc13FrameRxValid : out std_logic; -- PGP frame data is valid + vc13RemBuffAFull : out std_logic; -- Remote buffer almost full + vc13RemBuffFull : out std_logic; -- Remote buffer full + gtxLoopback : in std_logic_vector(1 downto 0); -- GTX Serial Loopback Control + gtxClkIn : in std_logic; -- GTX Reference Clock In + gtxRefClkOut : out std_logic; -- GTX Reference Clock Output + gtxRxRecClk : out std_logic_vector(1 downto 0); -- GTX Rx Recovered Clock + gtxRxN : in std_logic_vector(1 downto 0); -- GTX Serial Receive Negative + gtxRxP : in std_logic_vector(1 downto 0); -- GTX Serial Receive Positive + gtxTxN : out std_logic_vector(1 downto 0); -- GTX Serial Transmit Negative + gtxTxP : out std_logic_vector(1 downto 0); -- GTX Serial Transmit Positive + debug : out std_logic_vector(127 downto 0) + ); + end component; + + -- PGP Clock Generator + component Pgp2GtxClk + generic ( + UserFxDiv : integer := 5; -- DCM FX Output Divide + UserFxMult : integer := 4 -- DCM FX Output Divide, 4/5 * 156.25 = 125Mhz + ); + port ( + pgpRefClk : in std_logic; + ponResetL : in std_logic; + locReset : in std_logic; + pgpClk : out std_logic; + pgpReset : out std_logic; + userClk : out std_logic; + userReset : out std_logic; + pgpClkIn : in std_logic; + userClkIn : in std_logic + ); + end component; + + -- RX Reset Control + component Pgp2GtxRxRst + port ( + gtxRxClk : in std_logic; + gtxRxRst : in std_logic; + gtxRxReady : out std_logic; + gtxRxInit : in std_logic; + gtxLockDetect : in std_logic; + gtxRxBuffStatus : in std_logic_vector(2 downto 0); + gtxRxElecIdle : in std_logic; + gtxRstDone : in std_logic; + gtxRxReset : out std_logic; + gtxRxCdrReset : out std_logic + ); + end component; + + -- TX Reset Control + component Pgp2GtxTxRst + port ( + gtxTxClk : in std_logic; + gtxTxRst : in std_logic; + gtxTxReady : out std_logic; + gtxLockDetect : in std_logic; + gtxTxBuffStatus : in std_logic_vector(1 downto 0); + gtxRstDone : in std_logic; + gtxTxReset : out std_logic + ); + end component; + +end Pgp2GtxPackage; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2GtxRxRst.vhd b/rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2GtxRxRst.vhd new file mode 100755 index 00000000..b80943fb --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2GtxRxRst.vhd @@ -0,0 +1,198 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, GTX RX Reset Control +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2GtxRxRst.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 08/18/2009 +------------------------------------------------------------------------------- +-- Description: +-- This module contains the logic to control the reset of the RX GTX. +------------------------------------------------------------------------------- +-- Copyright (c) 2009 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 08/18/2009: created. +-- 01/13/2010: Added received init line to help linking. +-- 04/20/2010: Elec idle will no longer cause general reset. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; +use work.Pgp2GtxPackage.all; +library UNISIM; +use UNISIM.VCOMPONENTS.ALL; + + +entity Pgp2GtxRxRst is + port ( + + -- Clock and reset + gtxRxClk : in std_logic; + gtxRxRst : in std_logic; + + -- RX Side is ready + gtxRxReady : out std_logic; + gtxRxInit : in std_logic; + + -- GTX Status + gtxLockDetect : in std_logic; + gtxRxBuffStatus : in std_logic_vector(2 downto 0); + gtxRxElecIdle : in std_logic; + gtxRstDone : in std_logic; + + -- Reset Control + gtxRxReset : out std_logic; + gtxRxCdrReset : out std_logic + ); + +end Pgp2GtxRxRst; + + +-- Define architecture +architecture Pgp2GtxRxRst of Pgp2GtxRxRst is + + -- Local Signals + signal intRxReset : std_logic; + signal intRxCdrReset : std_logic; + signal rxStateCnt : std_logic_vector(1 downto 0); + signal rxStateCntRst : std_logic; + signal rxClockReady : std_logic; + + -- RX Reset State Machine + constant RX_SYSTEM_RESET : std_logic_vector(2 downto 0) := "000"; + constant RX_WAIT_LOCK : std_logic_vector(2 downto 0) := "001"; + constant RX_RESET : std_logic_vector(2 downto 0) := "010"; + constant RX_WAIT_DONE : std_logic_vector(2 downto 0) := "011"; + constant RX_READY : std_logic_vector(2 downto 0) := "100"; + signal curRxState : std_logic_vector(2 downto 0); + signal nxtRxState : std_logic_vector(2 downto 0); + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + + -- RX State Machine Synchronous Logic + process ( gtxRxClk, gtxRxRst ) begin + if gtxRxRst = '1' then + curRxState <= RX_SYSTEM_RESET after tpd; + rxStateCnt <= (others=>'0') after tpd; + gtxRxReady <= '0' after tpd; + gtxRxReset <= '1' after tpd; + gtxRxCdrReset <= '1' after tpd; + elsif rising_edge(gtxRxClk) then + + -- Drive PIB Lock + gtxRxReady <= rxClockReady after tpd; + + -- Pass on reset signals + gtxRxReset <= intRxReset after tpd; + gtxRxCdrReset <= intRxCdrReset after tpd; + + -- Update state + if gtxRxInit = '1' then + curRxState <= RX_SYSTEM_RESET after tpd; + else + curRxState <= nxtRxState after tpd; + end if; + + -- Rx State Counter + if rxStateCntRst = '1' then + rxStateCnt <= (others=>'0') after tpd; + else + rxStateCnt <= rxStateCnt + 1 after tpd; + end if; + end if; + end process; + + + -- Async RX State Logic + process ( curRxState, rxStateCnt, gtxLockDetect, gtxRxBuffStatus, gtxRstDone ) begin + case curRxState is + + -- System Reset State + when RX_SYSTEM_RESET => + rxStateCntRst <= '1'; + intRxReset <= '1'; + intRxCdrReset <= '1'; + rxClockReady <= '0'; + nxtRxState <= RX_WAIT_LOCK; + + -- Wait for PLL lock + when RX_WAIT_LOCK => + rxStateCntRst <= '1'; + intRxReset <= '1'; + intRxCdrReset <= '0'; + rxClockReady <= '0'; + + -- Wait for three clocks + if gtxLockDetect = '1' then + nxtRxState <= RX_RESET; + else + nxtRxState <= curRxState; + end if; + + -- RX Reset State + when RX_RESET => + intRxReset <= '1'; + intRxCdrReset <= '0'; + rxClockReady <= '0'; + rxStateCntRst <= '0'; + + -- Wait for three clocks + if rxStateCnt = 3 then + nxtRxState <= RX_WAIT_DONE; + else + nxtRxState <= curRxState; + end if; + + -- RX Wait Reset Done + when RX_WAIT_DONE => + intRxReset <= '0'; + intRxCdrReset <= '0'; + rxClockReady <= '0'; + rxStateCntRst <= '1'; + + -- Wait for three clocks + if gtxRstDone = '1' then + nxtRxState <= RX_READY; + else + nxtRxState <= curRxState; + end if; + + -- RX Ready + when RX_READY => + intRxReset <= '0'; + intRxCdrReset <= '0'; + rxClockReady <= '1'; + rxStateCntRst <= '1'; + + -- Look for unlock error + if gtxLockDetect = '0' then + nxtRxState <= RX_WAIT_LOCK; + + -- Look For Buffer Error + elsif gtxRxBuffStatus(2) = '1' then + nxtRxState <= RX_RESET; + + else + nxtRxState <= curRxState; + end if; + + -- Default + when others => + intRxReset <= '0'; + intRxCdrReset <= '0'; + rxClockReady <= '0'; + rxStateCntRst <= '1'; + nxtRxState <= RX_SYSTEM_RESET; + end case; + end process; + +end Pgp2GtxRxRst; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2GtxTxRst.vhd b/rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2GtxTxRst.vhd new file mode 100755 index 00000000..d11adca5 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/gtx/Pgp2GtxTxRst.vhd @@ -0,0 +1,179 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, GTX TX Reset Control +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2GtxTxRst.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 08/18/2009 +------------------------------------------------------------------------------- +-- Description: +-- This module contains the logic to control the reset of the TX GTX. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 08/18/2009: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; +use work.Pgp2GtxPackage.all; +library UNISIM; +use UNISIM.VCOMPONENTS.ALL; + + +entity Pgp2GtxTxRst is + port ( + + -- Clock and reset + gtxTxClk : in std_logic; + gtxTxRst : in std_logic; + + -- TX Side is ready + gtxTxReady : out std_logic; + + -- GTX Status + gtxLockDetect : in std_logic; + gtxTxBuffStatus : in std_logic_vector(1 downto 0); + gtxRstDone : in std_logic; + + -- Reset Control + gtxTxReset : out std_logic + ); + +end Pgp2GtxTxRst; + + +-- Define architecture +architecture Pgp2GtxTxRst of Pgp2GtxTxRst is + + -- Local Signals + signal intTxReset : std_logic; + signal txStateCnt : std_logic_vector(1 downto 0); + signal txStateCntRst : std_logic; + signal txClockReady : std_logic; + + -- TX Reset State Machine + constant TX_SYSTEM_RESET : std_logic_vector(2 downto 0) := "000"; + constant TX_WAIT_LOCK : std_logic_vector(2 downto 0) := "001"; + constant TX_RESET : std_logic_vector(2 downto 0) := "010"; + constant TX_WAIT_DONE : std_logic_vector(2 downto 0) := "011"; + constant TX_READY : std_logic_vector(2 downto 0) := "100"; + signal curTxState : std_logic_vector(2 downto 0); + signal nxtTxState : std_logic_vector(2 downto 0); + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + + -- TX State Machine Synchronous Logic + process ( gtxTxClk, gtxTxRst ) begin + if gtxTxRst = '1' then + curTxState <= TX_SYSTEM_RESET after tpd; + txStateCnt <= (others=>'0') after tpd; + gtxTxReset <= '1' after tpd; + gtxTxReady <= '0' after tpd; + elsif rising_edge(gtxTxClk) then + + -- RX Is Ready + gtxTxReady <= txClockReady after tpd; + + -- Pass on reset signals + gtxTxReset <= intTxReset after tpd; + + -- Update state + curTxState <= nxtTxState after tpd; + + -- Tx State Counter + if txStateCntRst = '1' then + txStateCnt <= (others=>'0') after tpd; + else + txStateCnt <= txStateCnt + 1 after tpd; + end if; + end if; + end process; + + + -- Async TX State Logic + process ( curTxState, txStateCnt, gtxLockDetect, gtxTxBuffStatus, gtxRstDone ) begin + case curTxState is + + -- System Reset State + when TX_SYSTEM_RESET => + txStateCntRst <= '1'; + intTxReset <= '1'; + txClockReady <= '0'; + nxtTxState <= TX_WAIT_LOCK; + + -- Wait for PLL lock + when TX_WAIT_LOCK => + txStateCntRst <= '1'; + intTxReset <= '1'; + txClockReady <= '0'; + + -- Wait for three clocks + if gtxLockDetect = '1' then + nxtTxState <= TX_RESET; + else + nxtTxState <= curTxState; + end if; + + -- TX Reset State + when TX_RESET => + intTxReset <= '1'; + txClockReady <= '0'; + txStateCntRst <= '0'; + + -- Wait for three clocks + if txStateCnt = 3 then + nxtTxState <= TX_WAIT_DONE; + else + nxtTxState <= curTxState; + end if; + + -- TX Wait Reset Done + when TX_WAIT_DONE => + intTxReset <= '0'; + txClockReady <= '0'; + txStateCntRst <= '1'; + + -- Wait for three clocks + if gtxRstDone = '1' then + nxtTxState <= TX_READY; + else + nxtTxState <= curTxState; + end if; + + -- TX Ready + when TX_READY => + intTxReset <= '0'; + txClockReady <= '1'; + txStateCntRst <= '1'; + + -- Look for unlock error + if gtxLockDetect = '0' then + nxtTxState <= TX_WAIT_LOCK; + + -- Look For Buffer Error + elsif gtxTxBuffStatus(1) = '1' then + nxtTxState <= TX_RESET; + else + nxtTxState <= curTxState; + end if; + + -- Default + when others => + intTxReset <= '0'; + txClockReady <= '0'; + txStateCntRst <= '1'; + nxtTxState <= TX_SYSTEM_RESET; + end case; + end process; + +end Pgp2GtxTxRst; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2Mgt16.vhd b/rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2Mgt16.vhd new file mode 100755 index 00000000..79091f4f --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2Mgt16.vhd @@ -0,0 +1,782 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, MGT Wrapper +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2Mgt16.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 05/27/2009 +------------------------------------------------------------------------------- +-- Description: +-- VHDL source file containing the PGP, MGT and CRC blocks. +-- This module supports a standard PGP implementation where a single MGT +-- supports a bi-directional link. Both links operated at the same speed. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 05/27/2009: created. +-- 01/13/2010: Added received init line to help linking. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; +use work.Pgp2MgtPackage.all; +use work.Pgp2CorePackage.all; +library UNISIM; +use UNISIM.VCOMPONENTS.ALL; + +entity Pgp2Mgt16 is + generic ( + EnShortCells : integer := 1; -- Enable short non-EOF cells + VcInterleave : integer := 1; -- Interleave Frames + MgtMode : string := "A"; -- Default Location + RefClkSel : string := "REFCLK1" -- Reference Clock To Use "REFCLK1" or "REFCLK2" + ); + port ( + + -- System clock, reset & control + pgpClk : in std_logic; -- 156.25Mhz master clock + pgpReset : in std_logic; -- Synchronous reset input + + -- Frame state sync + pgpFlush : in std_logic; -- Frame state sync + + -- PLL Reset Control + pllTxRst : in std_logic; -- Reset transmit PLL logic + pllRxRst : in std_logic; -- Reset receive PLL logic + + -- PLL Lock Status + pllRxReady : out std_logic; -- MGT Receive logic is ready + pllTxReady : out std_logic; -- MGT Transmit logic is ready + + -- Sideband data + pgpRemData : out std_logic_vector(7 downto 0); -- Far end side User Data + pgpLocData : in std_logic_vector(7 downto 0); -- Far end side User Data + + -- Opcode Transmit Interface + pgpTxOpCodeEn : in std_logic; -- Opcode receive enable + pgpTxOpCode : in std_logic_vector(7 downto 0); -- Opcode receive value + + -- Opcode Receive Interface + pgpRxOpCodeEn : out std_logic; -- Opcode receive enable + pgpRxOpCode : out std_logic_vector(7 downto 0); -- Opcode receive value + + -- Link status + pgpLocLinkReady : out std_logic; -- Local Link is ready + pgpRemLinkReady : out std_logic; -- Far end side has link + + -- Error Flags, one pulse per event + pgpRxCellError : out std_logic; -- A cell error has occured + pgpRxLinkDown : out std_logic; -- A link down event has occured + pgpRxLinkError : out std_logic; -- A link error has occured + + -- Frame Transmit Interface, VC 0 + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc0FrameTxReady : out std_logic; -- PGP is ready + vc0FrameTxSOF : in std_logic; -- User frame data start of frame + vc0FrameTxEOF : in std_logic; -- User frame data end of frame + vc0FrameTxEOFE : in std_logic; -- User frame data error + vc0FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc0LocBuffAFull : in std_logic; -- Remote buffer almost full + vc0LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 1 + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxReady : out std_logic; -- PGP is ready + vc1FrameTxSOF : in std_logic; -- User frame data start of frame + vc1FrameTxEOF : in std_logic; -- User frame data end of frame + vc1FrameTxEOFE : in std_logic; -- User frame data error + vc1FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc1LocBuffAFull : in std_logic; -- Remote buffer almost full + vc1LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 2 + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxReady : out std_logic; -- PGP is ready + vc2FrameTxSOF : in std_logic; -- User frame data start of frame + vc2FrameTxEOF : in std_logic; -- User frame data end of frame + vc2FrameTxEOFE : in std_logic; -- User frame data error + vc2FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc2LocBuffAFull : in std_logic; -- Remote buffer almost full + vc2LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 3 + vc3FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxReady : out std_logic; -- PGP is ready + vc3FrameTxSOF : in std_logic; -- User frame data start of frame + vc3FrameTxEOF : in std_logic; -- User frame data end of frame + vc3FrameTxEOFE : in std_logic; -- User frame data error + vc3FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc3LocBuffAFull : in std_logic; -- Remote buffer almost full + vc3LocBuffFull : in std_logic; -- Remote buffer full + + -- Common Frame Receive Interface For All VCs + vcFrameRxSOF : out std_logic; -- PGP frame data start of frame + vcFrameRxEOF : out std_logic; -- PGP frame data end of frame + vcFrameRxEOFE : out std_logic; -- PGP frame data error + vcFrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + + -- Frame Receive Interface, VC 0 + vc0FrameRxValid : out std_logic; -- PGP frame data is valid + vc0RemBuffAFull : out std_logic; -- Remote buffer almost full + vc0RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 1 + vc1FrameRxValid : out std_logic; -- PGP frame data is valid + vc1RemBuffAFull : out std_logic; -- Remote buffer almost full + vc1RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 2 + vc2FrameRxValid : out std_logic; -- PGP frame data is valid + vc2RemBuffAFull : out std_logic; -- Remote buffer almost full + vc2RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 3 + vc3FrameRxValid : out std_logic; -- PGP frame data is valid + vc3RemBuffAFull : out std_logic; -- Remote buffer almost full + vc3RemBuffFull : out std_logic; -- Remote buffer full + + -- MGT loopback control + mgtLoopback : in std_logic; -- MGT Serial Loopback Control + + -- MGT Signals, Drive Ref Clock Which Matches RefClkSel Generic Above + mgtRefClk1 : in std_logic; -- MGT Reference Clock In 1 + mgtRefClk2 : in std_logic; -- MGT Reference Clock In 2 + mgtRxRecClk : out std_logic; -- MGT Rx Recovered Clock + mgtRxN : in std_logic; -- MGT Serial Receive Negative + mgtRxP : in std_logic; -- MGT Serial Receive Positive + mgtTxN : out std_logic; -- MGT Serial Transmit Negative + mgtTxP : out std_logic; -- MGT Serial Transmit Positive + + -- MGT Signals For Simulation, + -- Drive mgtCombusIn to 0's, Leave mgtCombusOut open for real use + mgtCombusIn : in std_logic_vector(15 downto 0); + mgtCombusOut : out std_logic_vector(15 downto 0); + + -- Debug + debug : out std_logic_vector(63 downto 0) + ); + +end Pgp2Mgt16; + + +-- Define architecture +architecture Pgp2Mgt16 of Pgp2Mgt16 is + + -- Local Signals + signal crcTxIn : std_logic_vector(15 downto 0); + signal crcTxInMgt : std_logic_vector(63 downto 0); + signal crcTxInit : std_logic; + signal crcTxValid : std_logic; + signal crcTxWidth : std_logic_vector(2 downto 0); + signal crcTxOut : std_logic_vector(31 downto 0); + signal crcRxIn : std_logic_vector(15 downto 0); + signal crcRxInMgt : std_logic_vector(63 downto 0); + signal crcRxInit : std_logic; + signal crcRxValid : std_logic; + signal crcRxWidth : std_logic_vector(2 downto 0); + signal crcRxOut : std_logic_vector(31 downto 0); + signal phyRxPolarity : std_logic_vector(0 downto 0); + signal phyRxData : std_logic_vector(15 downto 0); + signal phyRxDataK : std_logic_vector(1 downto 0); + signal phyTxData : std_logic_vector(15 downto 0); + signal phyTxDataK : std_logic_vector(1 downto 0); + signal mgtRxPmaReset : std_logic; + signal mgtTxPmaReset : std_logic; + signal mgtRxReset : std_logic; + signal mgtTxReset : std_logic; + signal mgtRxBuffError : std_logic; + signal mgtTxBuffError : std_logic; + signal phyRxDispErr : std_logic_vector(1 downto 0); + signal phyRxDecErr : std_logic_vector(1 downto 0); + signal mgtRxLock : std_logic; + signal mgtTxLock : std_logic; + signal crcRxReset : std_logic; + signal crcTxReset : std_logic; + signal intTxRst : std_logic; + signal intRxRst : std_logic; + signal phyRxReady : std_logic; + signal phyRxInit : std_logic; + signal phyTxReady : std_logic; + signal pgpRxLinkReady : std_logic; + signal pgpTxLinkReady : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Adapt CRC data width flag + crcTxWidth <= "001"; + crcRxWidth <= "001"; + crcRxReset <= mgtRxReset; + crcTxReset <= mgtTxReset; + + -- Pass CRC data in on proper bits + crcTxInMgt(63 downto 56) <= crcTxIn(7 downto 0); + crcTxInMgt(55 downto 48) <= crcTxIn(15 downto 8); + crcTxInMgt(47 downto 0) <= (others=>'0'); + crcRxInMgt(63 downto 56) <= crcRxIn(7 downto 0); + crcRxInMgt(55 downto 48) <= crcRxIn(15 downto 8); + crcRxInMgt(47 downto 0) <= (others=>'0'); + + -- Pll Resets + intTxRst <= pllTxRst or pgpReset; + intRxRst <= pllRxRst or pgpReset; + + -- PLL Lock + pllRxReady <= phyRxReady; + pllTxReady <= phyTxReady; + + -- Link Ready + pgpLocLinkReady <= pgpRxLinkReady and pgpTxLinkReady; + + + -- PGP Receive Core + U_Pgp2Rx: Pgp2Rx + generic map ( + RxLaneCnt => 1, + EnShortCells => EnShortCells + ) port map ( + pgpRxClk => pgpClk, + pgpRxReset => pgpReset, + pgpRxFlush => pgpFlush, + pgpRxLinkReady => pgpRxLinkReady, + pgpRxCellError => pgpRxCellError, + pgpRxLinkDown => pgpRxLinkDown, + pgpRxLinkError => pgpRxLinkError, + pgpRxOpCodeEn => pgpRxOpCodeEn, + pgpRxOpCode => pgpRxOpCode, + pgpRemLinkReady => pgpRemLinkReady, + pgpRemData => pgpRemData, + vcFrameRxSOF => vcFrameRxSOF, + vcFrameRxEOF => vcFrameRxEOF, + vcFrameRxEOFE => vcFrameRxEOFE, + vcFrameRxData => vcFrameRxData, + vc0FrameRxValid => vc0FrameRxValid, + vc0RemBuffAFull => vc0RemBuffAFull, + vc0RemBuffFull => vc0RemBuffFull, + vc1FrameRxValid => vc1FrameRxValid, + vc1RemBuffAFull => vc1RemBuffAFull, + vc1RemBuffFull => vc1RemBuffFull, + vc2FrameRxValid => vc2FrameRxValid, + vc2RemBuffAFull => vc2RemBuffAFull, + vc2RemBuffFull => vc2RemBuffFull, + vc3FrameRxValid => vc3FrameRxValid, + vc3RemBuffAFull => vc3RemBuffAFull, + vc3RemBuffFull => vc3RemBuffFull, + phyRxPolarity => phyRxPolarity, + phyRxData => phyRxData, + phyRxDataK => phyRxDataK, + phyRxDispErr => phyRxDispErr, + phyRxDecErr => phyRxDecErr, + phyRxReady => phyRxReady, + phyRxInit => phyRxInit, + crcRxIn => crcRxIn, + crcRxWidth => open, + crcRxInit => crcRxInit, + crcRxValid => crcRxValid, + crcRxOut => crcRxOut, + debug => debug + ); + + + -- PGP Transmit Core + U_Pgp2Tx: Pgp2Tx + generic map ( + TxLaneCnt => 1, + VcInterleave => VcInterleave + ) port map ( + pgpTxClk => pgpClk, + pgpTxReset => pgpReset, + pgpTxFlush => pgpFlush, + pgpTxLinkReady => pgpTxLinkReady, + pgpTxOpCodeEn => pgpTxOpCodeEn, + pgpTxOpCode => pgpTxOpCode, + pgpLocLinkReady => pgpRxLinkReady, + pgpLocData => pgpLocData, + vc0FrameTxValid => vc0FrameTxValid, + vc0FrameTxReady => vc0FrameTxReady, + vc0FrameTxSOF => vc0FrameTxSOF, + vc0FrameTxEOF => vc0FrameTxEOF, + vc0FrameTxEOFE => vc0FrameTxEOFE, + vc0FrameTxData => vc0FrameTxData, + vc0LocBuffAFull => vc0LocBuffAFull, + vc0LocBuffFull => vc0LocBuffFull, + vc1FrameTxValid => vc1FrameTxValid, + vc1FrameTxReady => vc1FrameTxReady, + vc1FrameTxSOF => vc1FrameTxSOF, + vc1FrameTxEOF => vc1FrameTxEOF, + vc1FrameTxEOFE => vc1FrameTxEOFE, + vc1FrameTxData => vc1FrameTxData, + vc1LocBuffAFull => vc1LocBuffAFull, + vc1LocBuffFull => vc1LocBuffFull, + vc2FrameTxValid => vc2FrameTxValid, + vc2FrameTxReady => vc2FrameTxReady, + vc2FrameTxSOF => vc2FrameTxSOF, + vc2FrameTxEOF => vc2FrameTxEOF, + vc2FrameTxEOFE => vc2FrameTxEOFE, + vc2FrameTxData => vc2FrameTxData, + vc2LocBuffAFull => vc2LocBuffAFull, + vc2LocBuffFull => vc2LocBuffFull, + vc3FrameTxValid => vc3FrameTxValid, + vc3FrameTxReady => vc3FrameTxReady, + vc3FrameTxSOF => vc3FrameTxSOF, + vc3FrameTxEOF => vc3FrameTxEOF, + vc3FrameTxEOFE => vc3FrameTxEOFE, + vc3FrameTxData => vc3FrameTxData, + vc3LocBuffAFull => vc3LocBuffAFull, + vc3LocBuffFull => vc3LocBuffFull, + phyTxData => phyTxData, + phyTxDataK => phyTxDataK, + phyTxReady => phyTxReady, + crcTxIn => crcTxIn, + crcTxInit => crcTxInit, + crcTxValid => crcTxValid, + crcTxOut => crcTxOut, + debug => open + ); + + + -- MGT Receive Reset + U_Pgp2MgtRxRst: Pgp2MgtRxRst port map ( + mgtRxClk => pgpClk, + mgtRxRst => intRxRst, + mgtRxReady => phyRxReady, + mgtRxInit => phyRxInit, + mgtRxLock => mgtRxLock, + mgtRxPmaReset => mgtRxPmaReset, + mgtRxReset => mgtRxReset, + mgtRxBuffError => mgtRxBuffError + ); + + + -- MGT Transmit Reset + U_Pgp2MgtTxRst: Pgp2MgtTxRst port map ( + mgtTxClk => pgpClk, + mgtTxRst => intTxRst, + mgtTxReady => phyTxReady, + mgtTxLock => mgtTxLock, + mgtTxPmaReset => mgtTxPmaReset, + mgtTxReset => mgtTxReset, + mgtTxBuffError => mgtTxBuffError + ); + + + --------------------------- GT11 Instantiations --------------------------- + U_MGT : GT11 + generic map + ( + + ---------- RocketIO MGT 64B66B Block Sync State Machine Attributes --------- + + SH_CNT_MAX => 64, + SH_INVALID_CNT_MAX => 16, + + ----------------------- RocketIO MGT Alignment Atrributes ------------------ + + ALIGN_COMMA_WORD => 2, + COMMA_10B_MASK => x"3ff", + COMMA32 => FALSE, + DEC_MCOMMA_DETECT => FALSE, + DEC_PCOMMA_DETECT => FALSE, + DEC_VALID_COMMA_ONLY => FALSE, + MCOMMA_32B_VALUE => x"00000283", + MCOMMA_DETECT => TRUE, + PCOMMA_32B_VALUE => x"0000017c", + PCOMMA_DETECT => TRUE, + PCS_BIT_SLIP => FALSE, + + ---- RocketIO MGT Atrributes Common to Clk Correction & Channel Bonding ---- + + CCCB_ARBITRATOR_DISABLE => FALSE, + CLK_COR_8B10B_DE => TRUE, + + ------------------- RocketIO MGT Channel Bonding Atrributes ---------------- + + CHAN_BOND_LIMIT => 16, + CHAN_BOND_MODE => "NONE", + CHAN_BOND_ONE_SHOT => FALSE, + CHAN_BOND_SEQ_1_1 => "00000000000", + CHAN_BOND_SEQ_1_2 => "00000000000", + CHAN_BOND_SEQ_1_3 => "00000000000", + CHAN_BOND_SEQ_1_4 => "00000000000", + CHAN_BOND_SEQ_1_MASK => "1110", + CHAN_BOND_SEQ_2_1 => "00000000000", + CHAN_BOND_SEQ_2_2 => "00000000000", + CHAN_BOND_SEQ_2_3 => "00000000000", + CHAN_BOND_SEQ_2_4 => "00000000000", + CHAN_BOND_SEQ_2_MASK => "1111", + CHAN_BOND_SEQ_2_USE => FALSE, + CHAN_BOND_SEQ_LEN => 1, + + ------------------ RocketIO MGT Clock Correction Atrributes ---------------- + + CLK_COR_MAX_LAT => 48, + CLK_COR_MIN_LAT => 36, + CLK_COR_SEQ_1_1 => "00110111100", + CLK_COR_SEQ_1_2 => "00100011100", + CLK_COR_SEQ_1_3 => "00100011100", + CLK_COR_SEQ_1_4 => "00100011100", + CLK_COR_SEQ_1_MASK => "0000", + CLK_COR_SEQ_2_1 => "00000000000", + CLK_COR_SEQ_2_2 => "00000000000", + CLK_COR_SEQ_2_3 => "00000000000", + CLK_COR_SEQ_2_4 => "00000000000", + CLK_COR_SEQ_2_MASK => "1111", + CLK_COR_SEQ_2_USE => FALSE, + CLK_COR_SEQ_DROP => FALSE, + CLK_COR_SEQ_LEN => 4, + CLK_CORRECT_USE => TRUE, + + ---------------------- RocketIO MGT Clocking Atrributes -------------------- + + RX_CLOCK_DIVIDER => "01", + RXASYNCDIVIDE => "01", + RXCLK0_FORCE_PMACLK => TRUE, + RXCLKMODE => "000011", + RXOUTDIV2SEL => 2, + RXPLLNDIVSEL => 20, -- 8=1.25, 16=2.5, 20=3.125 + RXPMACLKSEL => RefClkSel, + RXRECCLK1_USE_SYNC => FALSE, + RXUSRDIVISOR => 1, + TX_CLOCK_DIVIDER => "01", + TXABPMACLKSEL => RefClkSel, + TXASYNCDIVIDE => "01", + TXCLK0_FORCE_PMACLK => TRUE, + TXCLKMODE => "0100", + TXOUTCLK1_USE_SYNC => FALSE, + TXOUTDIV2SEL => 2, + TXPHASESEL => FALSE, + TXPLLNDIVSEL => 20, -- 8=1.25, 16=2.5, 20=3.125 + + -------------------------- RocketIO MGT CRC Atrributes --------------------- + + RXCRCCLOCKDOUBLE => FALSE, + RXCRCENABLE => TRUE, + RXCRCINITVAL => x"FFFFFFFF", + RXCRCINVERTGEN => TRUE, + RXCRCSAMECLOCK => TRUE, + TXCRCCLOCKDOUBLE => FALSE, + TXCRCENABLE => TRUE, + TXCRCINITVAL => x"FFFFFFFF", + TXCRCINVERTGEN => TRUE, + TXCRCSAMECLOCK => TRUE, + + --------------------- RocketIO MGT Data Path Atrributes -------------------- + + RXDATA_SEL => "00", + TXDATA_SEL => "00", + + ---------------- RocketIO MGT Digital Receiver Attributes ------------------ + + DIGRX_FWDCLK => "01", + DIGRX_SYNC_MODE => FALSE, + ENABLE_DCDR => FALSE, + RXBY_32 => FALSE, + RXDIGRESET => FALSE, + RXDIGRX => FALSE, + SAMPLE_8X => FALSE, + + ----------------- Rocket IO MGT Miscellaneous Attributes ------------------ + + GT11_MODE => MgtMode, + OPPOSITE_SELECT => FALSE, + PMA_BIT_SLIP => FALSE, + REPEATER => FALSE, + RX_BUFFER_USE => TRUE, + RXCDRLOS => "000000", + RXDCCOUPLE => TRUE, + RXFDCAL_CLOCK_DIVIDE => "NONE", + TX_BUFFER_USE => TRUE, + TXFDCAL_CLOCK_DIVIDE => "NONE", + TXSLEWRATE => FALSE, + + ----------------- Rocket IO MGT Preemphasis and Equalization -------------- + + RXAFEEQ => "000000000", + RXEQ => x"4000FF0303030101", + TXDAT_PRDRV_DAC => "111", + TXDAT_TAP_DAC => "11011", -- = TXPOST_TAP_DAC * 4 + TXHIGHSIGNALEN => TRUE, + TXPOST_PRDRV_DAC => "111", + TXPOST_TAP_DAC => "00010", + TXPOST_TAP_PD => FALSE, + TXPRE_PRDRV_DAC => "111", + TXPRE_TAP_DAC => "00001", -- = TXPOST_TAP_DAC / 2 + TXPRE_TAP_PD => TRUE, + + ----------------------- Restricted RocketIO MGT Attributes ------------------- + + ---Note : THE FOLLOWING ATTRIBUTES ARE RESTRICTED. PLEASE DO NOT EDIT. + + ----------------------------- Restricted: Biasing ------------------------- + + BANDGAPSEL => FALSE, + BIASRESSEL => FALSE, + IREFBIASMODE => "11", + PMAIREFTRIM => "0111", + PMAVREFTRIM => "0111", + TXAREFBIASSEL => TRUE, + TXTERMTRIM => "1100", + VREFBIASMODE => "11", + + ---------------- Restricted: Frequency Detector and Calibration ----------- + + CYCLE_LIMIT_SEL => "00", + FDET_HYS_CAL => "010", + FDET_HYS_SEL => "100", + FDET_LCK_CAL => "101", + FDET_LCK_SEL => "001", + LOOPCAL_WAIT => "00", + RXCYCLE_LIMIT_SEL => "00", + RXFDET_HYS_CAL => "010", + RXFDET_HYS_SEL => "100", + RXFDET_LCK_CAL => "101", + RXFDET_LCK_SEL => "001", + RXLOOPCAL_WAIT => "00", + RXSLOWDOWN_CAL => "00", + SLOWDOWN_CAL => "00", + + --------------------------- Restricted: PLL Settings --------------------- + + PMACLKENABLE => TRUE, + PMACOREPWRENABLE => TRUE, + PMAVBGCTRL => "00000", + RXACTST => FALSE, + RXAFETST => FALSE, + RXCMADJ => "01", + RXCPSEL => TRUE, + RXCPTST => FALSE, + RXCTRL1 => x"200", + RXFECONTROL1 => "00", + RXFECONTROL2 => "000", + RXFETUNE => "01", + RXLKADJ => "00000", + RXLOOPFILT => "1111", + RXPDDTST => TRUE, + RXRCPADJ => "011", + RXRIBADJ => "11", + RXVCO_CTRL_ENABLE => TRUE, + RXVCODAC_INIT => "0000101001", + TXCPSEL => TRUE, + TXCTRL1 => x"200", + TXLOOPFILT => "1101", + VCO_CTRL_ENABLE => TRUE, + VCODAC_INIT => "0000101001", + + --------------------------- Restricted: Powerdowns ------------------------ + + POWER_ENABLE => TRUE, + RXAFEPD => FALSE, + RXAPD => FALSE, + RXLKAPD => FALSE, + RXPD => FALSE, + RXRCPPD => FALSE, + RXRPDPD => FALSE, + RXRSDPD => FALSE, + TXAPD => FALSE, + TXDIGPD => FALSE, + TXLVLSHFTPD => FALSE, + TXPD => FALSE, + + --------------------------- Recent Adds In Latest Software, Unknown ------- + + IN_DELAY => 0 ps, + DCDR_FILTER => "010", + RXAREGCTRL => "00000", + RXCLMODE => "00", + RXLB => FALSE, + RXMODE => "000000", + RXTUNE => X"0000", + TXCLMODE => "00", + TXTUNE => X"0000" + ) + port map + ( + ------------------------------- CRC Ports ------------------------------ + + RXCRCCLK => pgpClk, + RXCRCDATAVALID => crcRxValid, + RXCRCDATAWIDTH => crcRxWidth, + RXCRCIN => crcRxInMgt, + RXCRCINIT => crcRxInit, + RXCRCINTCLK => pgpClk, + RXCRCOUT => crcRxOut, + RXCRCPD => '0', + RXCRCRESET => crcRxReset, + + TXCRCCLK => pgpClk, + TXCRCDATAVALID => crcTxValid, + TXCRCDATAWIDTH => crcTxWidth, + TXCRCIN => crcTxInMgt, + TXCRCINIT => crcTxInit, + TXCRCINTCLK => pgpClk, + TXCRCOUT => crcTxOut, + TXCRCPD => '0', + TXCRCRESET => crcTxReset, + + ---------------------------- Calibration Ports ------------------------ + + RXCALFAIL => open, + RXCYCLELIMIT => open, + TXCALFAIL => open, + TXCYCLELIMIT => open, + + ------------------------------ Serial Ports ---------------------------- + + RX1N => mgtRxN, + RX1P => mgtRxP, + TX1N => mgtTxN, + TX1P => mgtTxP, + + ------------------------------- PLL Lock ------------------------------- + + RXLOCK => mgtRxLock, + TXLOCK => mgtTxLock, + + -------------------------------- Resets ------------------------------- + + RXPMARESET => mgtRxPmaReset, + RXRESET => mgtRxReset, + TXPMARESET => mgtTxPmaReset, + TXRESET => mgtTxReset, + + ---------------------------- Synchronization --------------------------- + + RXSYNC => '0', + TXSYNC => '0', + + ---------------------------- Out of Band Signalling ------------------- + + RXSIGDET => open, + TXENOOB => '0', + + -------------------------------- Status -------------------------------- + + RXBUFERR => mgtRxBuffError, + RXCLKSTABLE => '1', + RXSTATUS => open, + TXBUFERR => mgtTxBuffError, + TXCLKSTABLE => '1', + + ---------------------------- Polarity Control Ports -------------------- + + RXPOLARITY => phyRxPolarity(0), + TXINHIBIT => '0', + TXPOLARITY => '0', + + ------------------------------- Channel Bonding Ports ------------------ + + CHBONDI => (others=>'0'), + CHBONDO => open, + ENCHANSYNC => '0', + + ---------------------------- 64B66B Blocks Use Ports ------------------- + + RXBLOCKSYNC64B66BUSE => '0', + RXDEC64B66BUSE => '0', + RXDESCRAM64B66BUSE => '0', + RXIGNOREBTF => '0', + TXENC64B66BUSE => '0', + TXGEARBOX64B66BUSE => '0', + TXSCRAM64B66BUSE => '0', + + ---------------------------- 8B10B Blocks Use Ports -------------------- + + RXDEC8B10BUSE => '1', + TXBYPASS8B10B(7 downto 2) => "000000", + TXBYPASS8B10B(1 downto 0) => "00", + TXENC8B10BUSE => '1', + + ------------------------------ Transmit Control Ports ------------------ + + TXCHARDISPMODE(7 downto 0) => x"00", + TXCHARDISPVAL(7 downto 0) => x"00", + TXCHARISK(7 downto 2) => "000000", + TXCHARISK(1 downto 0) => phyTxDataK, + TXKERR(7 downto 0) => open, + TXRUNDISP(7 downto 0) => open, + + ------------------------------ Receive Control Ports ------------------- + + RXCHARISCOMMA => open, + RXCHARISK(7 downto 2) => open, + RXCHARISK(1 downto 0) => phyRxDataK, + RXDISPERR(7 downto 2) => open, + RXDISPERR(1 downto 0) => phyRxDispErr, + RXNOTINTABLE(7 downto 2) => open, + RXNOTINTABLE(1 downto 0) => phyRxDecErr, + RXRUNDISP(7 downto 0) => open, + + ------------------------------- Serdes Alignment ----------------------- + + ENMCOMMAALIGN => '1', + ENPCOMMAALIGN => '1', + RXCOMMADET => open, + RXCOMMADETUSE => '1', + RXLOSSOFSYNC => open, + RXREALIGN => open, + RXSLIDE => '0', + + ----------- Data Width Settings - Internal and fabric interface -------- + + RXDATAWIDTH => "01", + RXINTDATAWIDTH => "11", + TXDATAWIDTH => "01", + TXINTDATAWIDTH => "11", + + ------------------------------- Data Ports ----------------------------- + + RXDATA(63 downto 16) => open, + RXDATA(15 downto 0) => phyRxData, + TXDATA(63 downto 16) => x"000000000000", + TXDATA(15 downto 0) => phyTxData, + + ------------------------------- User Clocks ----------------------------- + + RXMCLK => open, + RXPCSHCLKOUT => open, + RXRECCLK1 => mgtRxRecClk, + RXRECCLK2 => open, + RXUSRCLK => '0', + RXUSRCLK2 => pgpClk, + TXOUTCLK1 => open, + TXOUTCLK2 => open, + TXPCSHCLKOUT => open, + TXUSRCLK => '0', + TXUSRCLK2 => pgpClk, + + ---------------------------- Reference Clocks -------------------------- + + GREFCLK => '0', + REFCLK1 => mgtRefClk1, + REFCLK2 => mgtRefClk2, + + ---------------------------- Powerdown and Loopback Ports -------------- + + LOOPBACK(1) => mgtLoopback, + LOOPBACK(0) => mgtLoopback, + POWERDOWN => '0', + + ------------------- Dynamic Reconfiguration Port (DRP) ------------------ + + DADDR => (others=>'0'), + DCLK => '0', + DEN => '0', + DI => (others=>'0'), + DO => open, + DRDY => open, + DWE => '0', + + --------------------- MGT Tile Communication Ports ------------------ + + COMBUSIN => mgtCombusIn, + COMBUSOUT => mgtCombusOut + ); + +end Pgp2Mgt16; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2Mgt32.vhd b/rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2Mgt32.vhd new file mode 100755 index 00000000..b5737e7a --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2Mgt32.vhd @@ -0,0 +1,1227 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, MGT Wrapper, 32-bit +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2Mgt3232.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 08/21/2009 +------------------------------------------------------------------------------- +-- Description: +-- VHDL source file containing the PGP, MGT and CRC blocks. 32-bit version. +-- This module supports a standard PGP implementation where a single MGT +-- supports a bi-directional link. Both links operated at the same speed. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 08/21/2009: created. +-- 01/13/2010: Added received init line to help linking. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; +use work.Pgp2MgtPackage.all; +use work.Pgp2CorePackage.all; +library UNISIM; +use UNISIM.VCOMPONENTS.ALL; + +entity Pgp2Mgt32 is + generic ( + EnShortCells : integer := 1; -- Enable short non-EOF cells + VcInterleave : integer := 1; -- Interleave Frames + RefClkSel : string := "REFCLK1" -- Reference Clock To Use "REFCLK1" or "REFCLK2" + ); + port ( + + -- System clock, reset & control + pgpClk : in std_logic; -- 156.25Mhz master clock + pgpReset : in std_logic; -- Synchronous reset input + + -- Frame state sync + pgpFlush : in std_logic; -- Frame state sync + + -- PLL Reset Control + pllTxRst : in std_logic; -- Reset transmit PLL logic + pllRxRst : in std_logic; -- Reset receive PLL logic + + -- PLL Lock Status + pllRxReady : out std_logic; -- MGT Receive logic is ready + pllTxReady : out std_logic; -- MGT Transmit logic is ready + + -- Sideband data + pgpRemData : out std_logic_vector(7 downto 0); -- Far end side User Data + pgpLocData : in std_logic_vector(7 downto 0); -- Far end side User Data + + -- Opcode Transmit Interface + pgpTxOpCodeEn : in std_logic; -- Opcode receive enable + pgpTxOpCode : in std_logic_vector(7 downto 0); -- Opcode receive value + + -- Opcode Receive Interface + pgpRxOpCodeEn : out std_logic; -- Opcode receive enable + pgpRxOpCode : out std_logic_vector(7 downto 0); -- Opcode receive value + + -- Link status + pgpLocLinkReady : out std_logic; -- Local Link is ready + pgpRemLinkReady : out std_logic; -- Far end side has link + + -- Error Flags, one pulse per event + pgpRxCellError : out std_logic; -- A cell error has occured + pgpRxLinkDown : out std_logic; -- A link down event has occured + pgpRxLinkError : out std_logic; -- A link error has occured + + -- Frame Transmit Interface, VC 0 + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc0FrameTxReady : out std_logic; -- PGP is ready + vc0FrameTxSOF : in std_logic; -- User frame data start of frame + vc0FrameTxEOF : in std_logic; -- User frame data end of frame + vc0FrameTxEOFE : in std_logic; -- User frame data error + vc0FrameTxData : in std_logic_vector(31 downto 0); -- User frame data + vc0LocBuffAFull : in std_logic; -- Remote buffer almost full + vc0LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 1 + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxReady : out std_logic; -- PGP is ready + vc1FrameTxSOF : in std_logic; -- User frame data start of frame + vc1FrameTxEOF : in std_logic; -- User frame data end of frame + vc1FrameTxEOFE : in std_logic; -- User frame data error + vc1FrameTxData : in std_logic_vector(31 downto 0); -- User frame data + vc1LocBuffAFull : in std_logic; -- Remote buffer almost full + vc1LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 2 + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxReady : out std_logic; -- PGP is ready + vc2FrameTxSOF : in std_logic; -- User frame data start of frame + vc2FrameTxEOF : in std_logic; -- User frame data end of frame + vc2FrameTxEOFE : in std_logic; -- User frame data error + vc2FrameTxData : in std_logic_vector(31 downto 0); -- User frame data + vc2LocBuffAFull : in std_logic; -- Remote buffer almost full + vc2LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 3 + vc3FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxReady : out std_logic; -- PGP is ready + vc3FrameTxSOF : in std_logic; -- User frame data start of frame + vc3FrameTxEOF : in std_logic; -- User frame data end of frame + vc3FrameTxEOFE : in std_logic; -- User frame data error + vc3FrameTxData : in std_logic_vector(31 downto 0); -- User frame data + vc3LocBuffAFull : in std_logic; -- Remote buffer almost full + vc3LocBuffFull : in std_logic; -- Remote buffer full + + -- Common Frame Receive Interface For All VCs + vcFrameRxSOF : out std_logic; -- PGP frame data start of frame + vcFrameRxEOF : out std_logic; -- PGP frame data end of frame + vcFrameRxEOFE : out std_logic; -- PGP frame data error + vcFrameRxData : out std_logic_vector(31 downto 0); -- PGP frame data + + -- Frame Receive Interface, VC 0 + vc0FrameRxValid : out std_logic; -- PGP frame data is valid + vc0RemBuffAFull : out std_logic; -- Remote buffer almost full + vc0RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 1 + vc1FrameRxValid : out std_logic; -- PGP frame data is valid + vc1RemBuffAFull : out std_logic; -- Remote buffer almost full + vc1RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 2 + vc2FrameRxValid : out std_logic; -- PGP frame data is valid + vc2RemBuffAFull : out std_logic; -- Remote buffer almost full + vc2RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 3 + vc3FrameRxValid : out std_logic; -- PGP frame data is valid + vc3RemBuffAFull : out std_logic; -- Remote buffer almost full + vc3RemBuffFull : out std_logic; -- Remote buffer full + + -- MGT loopback control + mgtLoopback : in std_logic; -- MGT Serial Loopback Control + + -- MGT Signals, Drive Ref Clock Which Matches RefClkSel Generic Above + mgtRefClk1 : in std_logic; -- MGT Reference Clock In 1 + mgtRefClk2 : in std_logic; -- MGT Reference Clock In 2 + mgtRxRecClk : out std_logic; -- MGT Rx Recovered Clock + mgtRxN : in std_logic_vector(1 downto 0); -- MGT Serial Receive Negative + mgtRxP : in std_logic_vector(1 downto 0); -- MGT Serial Receive Positive + mgtTxN : out std_logic_vector(1 downto 0); -- MGT Serial Transmit Negative + mgtTxP : out std_logic_vector(1 downto 0); -- MGT Serial Transmit Positive + + -- Debug + debug : out std_logic_vector(63 downto 0) + ); + +end Pgp2Mgt32; + + +-- Define architecture +architecture Pgp2Mgt32 of Pgp2Mgt32 is + + -- Local Signals + signal crcTxIn : std_logic_vector(31 downto 0); + signal crcTxInMgt : std_logic_vector(63 downto 0); + signal crcTxInit : std_logic; + signal crcTxValid : std_logic; + signal crcTxWidth : std_logic_vector(2 downto 0); + signal crcTxOut : std_logic_vector(31 downto 0); + signal crcRxIn : std_logic_vector(31 downto 0); + signal crcRxInMgt : std_logic_vector(63 downto 0); + signal crcRxInit : std_logic; + signal crcRxValid : std_logic; + signal crcRxWidth : std_logic_vector(2 downto 0); + signal crcRxOut : std_logic_vector(31 downto 0); + signal phyRxPolarity : std_logic_vector(1 downto 0); + signal phyRxData : std_logic_vector(31 downto 0); + signal phyRxDataK : std_logic_vector(3 downto 0); + signal phyTxData : std_logic_vector(31 downto 0); + signal phyTxDataK : std_logic_vector(3 downto 0); + signal mgtRxPmaReset : std_logic_vector(1 downto 0); + signal mgtTxPmaReset : std_logic_vector(1 downto 0); + signal mgtRxReset : std_logic_vector(1 downto 0); + signal mgtTxReset : std_logic_vector(1 downto 0); + signal mgtRxBuffError : std_logic_vector(1 downto 0); + signal mgtTxBuffError : std_logic_vector(1 downto 0); + signal phyRxDispErr : std_logic_vector(3 downto 0); + signal phyRxDecErr : std_logic_vector(3 downto 0); + signal mgtRxLock : std_logic_vector(1 downto 0); + signal mgtTxLock : std_logic_vector(1 downto 0); + signal crcRxReset : std_logic; + signal crcTxReset : std_logic; + signal intTxRst : std_logic; + signal intRxRst : std_logic; + signal phyRxReady : std_logic; + signal phyRxInit : std_logic; + signal phyTxReady : std_logic; + signal intRxReady : std_logic_vector(1 downto 0); + signal intTxReady : std_logic_vector(1 downto 0); + signal pgpRxLinkReady : std_logic; + signal pgpTxLinkReady : std_logic; + signal mgtCombusOutA : std_logic_vector(15 downto 0); + signal mgtCombusInA : std_logic_vector(15 downto 0); + signal mgtChanBond : std_logic_vector(4 downto 0); + signal mgtStatusA : std_logic_vector(5 downto 0); + signal mgtStatusB : std_logic_vector(5 downto 0); + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Adapt CRC data width flag + crcTxWidth <= "011"; + crcRxWidth <= "011"; + crcRxReset <= mgtRxReset(0); + crcTxReset <= mgtTxReset(0); + + -- Pass CRC data in on proper bits + crcTxInMgt(63 downto 56) <= crcTxIn(7 downto 0); + crcTxInMgt(55 downto 48) <= crcTxIn(15 downto 8); + crcTxInMgt(47 downto 40) <= crcTxIn(23 downto 16); + crcTxInMgt(39 downto 32) <= crcTxIn(31 downto 24); + crcTxInMgt(31 downto 0) <= (others=>'0'); + crcRxInMgt(63 downto 56) <= crcRxIn(7 downto 0); + crcRxInMgt(55 downto 48) <= crcRxIn(15 downto 8); + crcRxInMgt(47 downto 40) <= crcRxIn(23 downto 16); + crcRxInMgt(39 downto 32) <= crcRxIn(31 downto 24); + crcRxInMgt(31 downto 0) <= (others=>'0'); + + -- Pll Resets + intTxRst <= pllTxRst or pgpReset; + intRxRst <= pllRxRst or pgpReset; + + -- PLL Lock + phyRxReady <= '1' when intRxReady = "11" else '0'; + phyTxReady <= '1' when intTxReady = "11" else '0'; + pllRxReady <= phyRxReady; + pllTxReady <= phyTxReady; + + -- Link Ready + pgpLocLinkReady <= pgpRxLinkReady and pgpTxLinkReady; + + + -- PGP Receive Core + U_Pgp2Rx: Pgp2CorePackage.Pgp2Rx + generic map ( + RxLaneCnt => 2, + EnShortCells => EnShortCells + ) port map ( + pgpRxClk => pgpClk, + pgpRxReset => pgpReset, + pgpRxFlush => pgpFlush, + pgpRxLinkReady => pgpRxLinkReady, + pgpRxCellError => pgpRxCellError, + pgpRxLinkDown => pgpRxLinkDown, + pgpRxLinkError => pgpRxLinkError, + pgpRxOpCodeEn => pgpRxOpCodeEn, + pgpRxOpCode => pgpRxOpCode, + pgpRemLinkReady => pgpRemLinkReady, + pgpRemData => pgpRemData, + vcFrameRxSOF => vcFrameRxSOF, + vcFrameRxEOF => vcFrameRxEOF, + vcFrameRxEOFE => vcFrameRxEOFE, + vcFrameRxData => vcFrameRxData, + vc0FrameRxValid => vc0FrameRxValid, + vc0RemBuffAFull => vc0RemBuffAFull, + vc0RemBuffFull => vc0RemBuffFull, + vc1FrameRxValid => vc1FrameRxValid, + vc1RemBuffAFull => vc1RemBuffAFull, + vc1RemBuffFull => vc1RemBuffFull, + vc2FrameRxValid => vc2FrameRxValid, + vc2RemBuffAFull => vc2RemBuffAFull, + vc2RemBuffFull => vc2RemBuffFull, + vc3FrameRxValid => vc3FrameRxValid, + vc3RemBuffAFull => vc3RemBuffAFull, + vc3RemBuffFull => vc3RemBuffFull, + phyRxPolarity => phyRxPolarity, + phyRxData => phyRxData, + phyRxDataK => phyRxDataK, + phyRxDispErr => phyRxDispErr, + phyRxDecErr => phyRxDecErr, + phyRxReady => phyRxReady, + phyRxInit => phyRxInit, + crcRxIn => crcRxIn, + crcRxWidth => open, + crcRxInit => crcRxInit, + crcRxValid => crcRxValid, + crcRxOut => crcRxOut, + debug => debug + ); + + + -- PGP Transmit Core + U_Pgp2Tx: Pgp2CorePackage.Pgp2Tx + generic map ( + TxLaneCnt => 2, + VcInterleave => VcInterleave + ) port map ( + pgpTxClk => pgpClk, + pgpTxReset => pgpReset, + pgpTxFlush => pgpFlush, + pgpTxLinkReady => pgpTxLinkReady, + pgpTxOpCodeEn => pgpTxOpCodeEn, + pgpTxOpCode => pgpTxOpCode, + pgpLocLinkReady => pgpRxLinkReady, + pgpLocData => pgpLocData, + vc0FrameTxValid => vc0FrameTxValid, + vc0FrameTxReady => vc0FrameTxReady, + vc0FrameTxSOF => vc0FrameTxSOF, + vc0FrameTxEOF => vc0FrameTxEOF, + vc0FrameTxEOFE => vc0FrameTxEOFE, + vc0FrameTxData => vc0FrameTxData, + vc0LocBuffAFull => vc0LocBuffAFull, + vc0LocBuffFull => vc0LocBuffFull, + vc1FrameTxValid => vc1FrameTxValid, + vc1FrameTxReady => vc1FrameTxReady, + vc1FrameTxSOF => vc1FrameTxSOF, + vc1FrameTxEOF => vc1FrameTxEOF, + vc1FrameTxEOFE => vc1FrameTxEOFE, + vc1FrameTxData => vc1FrameTxData, + vc1LocBuffAFull => vc1LocBuffAFull, + vc1LocBuffFull => vc1LocBuffFull, + vc2FrameTxValid => vc2FrameTxValid, + vc2FrameTxReady => vc2FrameTxReady, + vc2FrameTxSOF => vc2FrameTxSOF, + vc2FrameTxEOF => vc2FrameTxEOF, + vc2FrameTxEOFE => vc2FrameTxEOFE, + vc2FrameTxData => vc2FrameTxData, + vc2LocBuffAFull => vc2LocBuffAFull, + vc2LocBuffFull => vc2LocBuffFull, + vc3FrameTxValid => vc3FrameTxValid, + vc3FrameTxReady => vc3FrameTxReady, + vc3FrameTxSOF => vc3FrameTxSOF, + vc3FrameTxEOF => vc3FrameTxEOF, + vc3FrameTxEOFE => vc3FrameTxEOFE, + vc3FrameTxData => vc3FrameTxData, + vc3LocBuffAFull => vc3LocBuffAFull, + vc3LocBuffFull => vc3LocBuffFull, + phyTxData => phyTxData, + phyTxDataK => phyTxDataK, + phyTxReady => phyTxReady, + crcTxIn => crcTxIn, + crcTxInit => crcTxInit, + crcTxValid => crcTxValid, + crcTxOut => crcTxOut, + debug => open + ); + + + -- MGTA Receive Reset + U_Pgp2MgtRxRstA: Pgp2MgtPackage.Pgp2MgtRxRst port map ( + mgtRxClk => pgpClk, + mgtRxRst => intRxRst, + mgtRxReady => intRxReady(0), + mgtRxInit => phyRxInit, + mgtRxLock => mgtRxLock(0), + mgtRxPmaReset => mgtRxPmaReset(0), + mgtRxReset => mgtRxReset(0), + mgtRxBuffError => mgtRxBuffError(0) + ); + + + -- MGTB Receive Reset + U_Pgp2MgtRxRstB: Pgp2MgtPackage.Pgp2MgtRxRst port map ( + mgtRxClk => pgpClk, + mgtRxRst => intRxRst, + mgtRxReady => intRxReady(1), + mgtRxInit => phyRxInit, + mgtRxLock => mgtRxLock(1), + mgtRxPmaReset => mgtRxPmaReset(1), + mgtRxReset => mgtRxReset(1), + mgtRxBuffError => mgtRxBuffError(1) + ); + + + -- MGTA Transmit Reset + U_Pgp2MgtTxRstA: Pgp2MgtPackage.Pgp2MgtTxRst port map ( + mgtTxClk => pgpClk, + mgtTxRst => intTxRst, + mgtTxReady => intTxReady(0), + mgtTxLock => mgtTxLock(0), + mgtTxPmaReset => mgtTxPmaReset(0), + mgtTxReset => mgtTxReset(0), + mgtTxBuffError => mgtTxBuffError(0) + ); + + + -- MGTB Transmit Reset + U_Pgp2MgtTxRstB: Pgp2MgtPackage.Pgp2MgtTxRst port map ( + mgtTxClk => pgpClk, + mgtTxRst => intTxRst, + mgtTxReady => intTxReady(1), + mgtTxLock => mgtTxLock(1), + mgtTxPmaReset => mgtTxPmaReset(1), + mgtTxReset => mgtTxReset(1), + mgtTxBuffError => mgtTxBuffError(1) + ); + + + --------------------------- GT11 Instantiations --------------------------- + U_MGTA : GT11 + generic map + ( + + ---------- RocketIO MGT 64B66B Block Sync State Machine Attributes --------- + + SH_CNT_MAX => 64, + SH_INVALID_CNT_MAX => 16, + + ----------------------- RocketIO MGT Alignment Atrributes ------------------ + + ALIGN_COMMA_WORD => 2, + COMMA_10B_MASK => x"3ff", + COMMA32 => FALSE, + DEC_MCOMMA_DETECT => FALSE, + DEC_PCOMMA_DETECT => FALSE, + DEC_VALID_COMMA_ONLY => FALSE, + MCOMMA_32B_VALUE => x"00000283", + MCOMMA_DETECT => TRUE, + PCOMMA_32B_VALUE => x"0000017c", + PCOMMA_DETECT => TRUE, + PCS_BIT_SLIP => FALSE, + + ---- RocketIO MGT Atrributes Common to Clk Correction & Channel Bonding ---- + + CCCB_ARBITRATOR_DISABLE => FALSE, + CLK_COR_8B10B_DE => TRUE, + + ------------------- RocketIO MGT Channel Bonding Atrributes ---------------- + + CHAN_BOND_LIMIT => 16, + CHAN_BOND_MODE => "MASTER", + CHAN_BOND_ONE_SHOT => FALSE, + CHAN_BOND_SEQ_1_1 => "00110111100", + CHAN_BOND_SEQ_1_2 => "00111011100", + CHAN_BOND_SEQ_1_3 => "00111011100", + CHAN_BOND_SEQ_1_4 => "00111011100", + CHAN_BOND_SEQ_1_MASK => "0000", + CHAN_BOND_SEQ_2_1 => "00000000000", + CHAN_BOND_SEQ_2_2 => "00000000000", + CHAN_BOND_SEQ_2_3 => "00000000000", + CHAN_BOND_SEQ_2_4 => "00000000000", + CHAN_BOND_SEQ_2_MASK => "1111", + CHAN_BOND_SEQ_2_USE => FALSE, + CHAN_BOND_SEQ_LEN => 4, + + ------------------ RocketIO MGT Clock Correction Atrributes ---------------- + + CLK_COR_MAX_LAT => 48, + CLK_COR_MIN_LAT => 36, + CLK_COR_SEQ_1_1 => "00110111100", + CLK_COR_SEQ_1_2 => "00100011100", + CLK_COR_SEQ_1_3 => "00100011100", + CLK_COR_SEQ_1_4 => "00100011100", + CLK_COR_SEQ_1_MASK => "0000", + CLK_COR_SEQ_2_1 => "00000000000", + CLK_COR_SEQ_2_2 => "00000000000", + CLK_COR_SEQ_2_3 => "00000000000", + CLK_COR_SEQ_2_4 => "00000000000", + CLK_COR_SEQ_2_MASK => "1111", + CLK_COR_SEQ_2_USE => FALSE, + CLK_COR_SEQ_DROP => FALSE, + CLK_COR_SEQ_LEN => 4, + CLK_CORRECT_USE => TRUE, + + ---------------------- RocketIO MGT Clocking Atrributes -------------------- + + RX_CLOCK_DIVIDER => "01", + RXASYNCDIVIDE => "01", + RXCLK0_FORCE_PMACLK => TRUE, + RXCLKMODE => "000011", + RXOUTDIV2SEL => 2, + RXPLLNDIVSEL => 20, -- 8=1.25, 16=2.5, 20=3.125 + RXPMACLKSEL => RefClkSel, + RXRECCLK1_USE_SYNC => FALSE, + RXUSRDIVISOR => 1, + TX_CLOCK_DIVIDER => "01", + TXABPMACLKSEL => RefClkSel, + TXASYNCDIVIDE => "01", + TXCLK0_FORCE_PMACLK => TRUE, + TXCLKMODE => "0100", + TXOUTCLK1_USE_SYNC => FALSE, + TXOUTDIV2SEL => 2, + TXPHASESEL => FALSE, + TXPLLNDIVSEL => 20, -- 8=1.25, 16=2.5, 20=3.125 + + -------------------------- RocketIO MGT CRC Atrributes --------------------- + + RXCRCCLOCKDOUBLE => FALSE, + RXCRCENABLE => TRUE, + RXCRCINITVAL => x"FFFFFFFF", + RXCRCINVERTGEN => TRUE, + RXCRCSAMECLOCK => TRUE, + TXCRCCLOCKDOUBLE => FALSE, + TXCRCENABLE => TRUE, + TXCRCINITVAL => x"FFFFFFFF", + TXCRCINVERTGEN => TRUE, + TXCRCSAMECLOCK => TRUE, + + --------------------- RocketIO MGT Data Path Atrributes -------------------- + + RXDATA_SEL => "00", + TXDATA_SEL => "00", + + ---------------- RocketIO MGT Digital Receiver Attributes ------------------ + + DIGRX_FWDCLK => "01", + DIGRX_SYNC_MODE => FALSE, + ENABLE_DCDR => FALSE, + RXBY_32 => FALSE, + RXDIGRESET => FALSE, + RXDIGRX => FALSE, + SAMPLE_8X => FALSE, + + ----------------- Rocket IO MGT Miscellaneous Attributes ------------------ + + GT11_MODE => "A", + OPPOSITE_SELECT => FALSE, + PMA_BIT_SLIP => FALSE, + REPEATER => FALSE, + RX_BUFFER_USE => TRUE, + RXCDRLOS => "000000", + RXDCCOUPLE => TRUE, + RXFDCAL_CLOCK_DIVIDE => "NONE", + TX_BUFFER_USE => TRUE, + TXFDCAL_CLOCK_DIVIDE => "NONE", + TXSLEWRATE => FALSE, + + ----------------- Rocket IO MGT Preemphasis and Equalization -------------- + + RXAFEEQ => "000000000", + RXEQ => x"4000FF0303030101", + TXDAT_PRDRV_DAC => "111", + TXDAT_TAP_DAC => "11011", -- = TXPOST_TAP_DAC * 4 + TXHIGHSIGNALEN => TRUE, + TXPOST_PRDRV_DAC => "111", + TXPOST_TAP_DAC => "00010", + TXPOST_TAP_PD => FALSE, + TXPRE_PRDRV_DAC => "111", + TXPRE_TAP_DAC => "00001", -- = TXPOST_TAP_DAC / 2 + TXPRE_TAP_PD => TRUE, + + ----------------------- Restricted RocketIO MGT Attributes ------------------- + + ---Note : THE FOLLOWING ATTRIBUTES ARE RESTRICTED. PLEASE DO NOT EDIT. + + ----------------------------- Restricted: Biasing ------------------------- + + BANDGAPSEL => FALSE, + BIASRESSEL => FALSE, + IREFBIASMODE => "11", + PMAIREFTRIM => "0111", + PMAVREFTRIM => "0111", + TXAREFBIASSEL => TRUE, + TXTERMTRIM => "1100", + VREFBIASMODE => "11", + + ---------------- Restricted: Frequency Detector and Calibration ----------- + + CYCLE_LIMIT_SEL => "00", + FDET_HYS_CAL => "010", + FDET_HYS_SEL => "100", + FDET_LCK_CAL => "101", + FDET_LCK_SEL => "001", + LOOPCAL_WAIT => "00", + RXCYCLE_LIMIT_SEL => "00", + RXFDET_HYS_CAL => "010", + RXFDET_HYS_SEL => "100", + RXFDET_LCK_CAL => "101", + RXFDET_LCK_SEL => "001", + RXLOOPCAL_WAIT => "00", + RXSLOWDOWN_CAL => "00", + SLOWDOWN_CAL => "00", + + --------------------------- Restricted: PLL Settings --------------------- + + PMACLKENABLE => TRUE, + PMACOREPWRENABLE => TRUE, + PMAVBGCTRL => "00000", + RXACTST => FALSE, + RXAFETST => FALSE, + RXCMADJ => "01", + RXCPSEL => TRUE, + RXCPTST => FALSE, + RXCTRL1 => x"200", + RXFECONTROL1 => "00", + RXFECONTROL2 => "000", + RXFETUNE => "01", + RXLKADJ => "00000", + RXLOOPFILT => "1111", + RXPDDTST => TRUE, + RXRCPADJ => "011", + RXRIBADJ => "11", + RXVCO_CTRL_ENABLE => TRUE, + RXVCODAC_INIT => "0000101001", + TXCPSEL => TRUE, + TXCTRL1 => x"200", + TXLOOPFILT => "1101", + VCO_CTRL_ENABLE => TRUE, + VCODAC_INIT => "0000101001", + + --------------------------- Restricted: Powerdowns ------------------------ + + POWER_ENABLE => TRUE, + RXAFEPD => FALSE, + RXAPD => FALSE, + RXLKAPD => FALSE, + RXPD => FALSE, + RXRCPPD => FALSE, + RXRPDPD => FALSE, + RXRSDPD => FALSE, + TXAPD => FALSE, + TXDIGPD => FALSE, + TXLVLSHFTPD => FALSE, + TXPD => FALSE, + + --------------------------- Recent Adds In Latest Software, Unknown ------- + + IN_DELAY => 0 ps, + DCDR_FILTER => "010", + RXAREGCTRL => "00000", + RXCLMODE => "00", + RXLB => FALSE, + RXMODE => "000000", + RXTUNE => X"0000", + TXCLMODE => "00", + TXTUNE => X"0000" + ) + port map + ( + ------------------------------- CRC Ports ------------------------------ + + RXCRCCLK => pgpClk, + RXCRCDATAVALID => crcRxValid, + RXCRCDATAWIDTH => crcRxWidth, + RXCRCIN => crcRxInMgt, + RXCRCINIT => crcRxInit, + RXCRCINTCLK => pgpClk, + RXCRCOUT => crcRxOut, + RXCRCPD => '0', + RXCRCRESET => crcRxReset, + + TXCRCCLK => pgpClk, + TXCRCDATAVALID => crcTxValid, + TXCRCDATAWIDTH => crcTxWidth, + TXCRCIN => crcTxInMgt, + TXCRCINIT => crcTxInit, + TXCRCINTCLK => pgpClk, + TXCRCOUT => crcTxOut, + TXCRCPD => '0', + TXCRCRESET => crcTxReset, + + ---------------------------- Calibration Ports ------------------------ + + RXCALFAIL => open, + RXCYCLELIMIT => open, + TXCALFAIL => open, + TXCYCLELIMIT => open, + + ------------------------------ Serial Ports ---------------------------- + + RX1N => mgtRxN(0), + RX1P => mgtRxP(0), + TX1N => mgtTxN(0), + TX1P => mgtTxP(0), + + ------------------------------- PLL Lock ------------------------------- + + RXLOCK => mgtRxLock(0), + TXLOCK => mgtTxLock(0), + + -------------------------------- Resets ------------------------------- + + RXPMARESET => mgtRxPmaReset(0), + RXRESET => mgtRxReset(0), + TXPMARESET => mgtTxPmaReset(0), + TXRESET => mgtTxReset(0), + + ---------------------------- Synchronization --------------------------- + + RXSYNC => '0', + TXSYNC => '0', + + ---------------------------- Out of Band Signalling ------------------- + + RXSIGDET => open, + TXENOOB => '0', + + -------------------------------- Status -------------------------------- + + RXBUFERR => mgtRxBuffError(0), + RXCLKSTABLE => '1', + RXSTATUS => mgtStatusA, + TXBUFERR => mgtTxBuffError(0), + TXCLKSTABLE => '1', + + ---------------------------- Polarity Control Ports -------------------- + + RXPOLARITY => phyRxPolarity(0), + TXINHIBIT => '0', + TXPOLARITY => '0', + + ------------------------------- Channel Bonding Ports ------------------ + + CHBONDI => (others=>'0'), + CHBONDO => mgtChanBond, + ENCHANSYNC => '1', + + ---------------------------- 64B66B Blocks Use Ports ------------------- + + RXBLOCKSYNC64B66BUSE => '0', + RXDEC64B66BUSE => '0', + RXDESCRAM64B66BUSE => '0', + RXIGNOREBTF => '0', + TXENC64B66BUSE => '0', + TXGEARBOX64B66BUSE => '0', + TXSCRAM64B66BUSE => '0', + + ---------------------------- 8B10B Blocks Use Ports -------------------- + + RXDEC8B10BUSE => '1', + TXBYPASS8B10B(7 downto 2) => (others=>'0'), + TXBYPASS8B10B(1 downto 0) => (others=>'0'), + TXENC8B10BUSE => '1', + + ------------------------------ Transmit Control Ports ------------------ + + TXCHARDISPMODE(7 downto 0) => (others=>'0'), + TXCHARDISPVAL(7 downto 0) => (others=>'0'), + TXCHARISK(7 downto 2) => (others=>'0'), + TXCHARISK(1 downto 0) => phyTxDataK(1 downto 0), + TXKERR(7 downto 0) => open, + TXRUNDISP(7 downto 0) => open, + + ------------------------------ Receive Control Ports ------------------- + + RXCHARISCOMMA => open, + RXCHARISK(7 downto 2) => open, + RXCHARISK(1 downto 0) => phyRxDataK(1 downto 0), + RXDISPERR(7 downto 2) => open, + RXDISPERR(1 downto 0) => phyRxDispErr(1 downto 0), + RXNOTINTABLE(7 downto 2) => open, + RXNOTINTABLE(1 downto 0) => phyRxDecErr(1 downto 0), + RXRUNDISP(7 downto 0) => open, + + ------------------------------- Serdes Alignment ----------------------- + + ENMCOMMAALIGN => '1', + ENPCOMMAALIGN => '1', + RXCOMMADET => open, + RXCOMMADETUSE => '1', + RXLOSSOFSYNC => open, + RXREALIGN => open, + RXSLIDE => '0', + + ----------- Data Width Settings - Internal and fabric interface -------- + + RXDATAWIDTH => "01", + RXINTDATAWIDTH => "11", + TXDATAWIDTH => "01", + TXINTDATAWIDTH => "11", + + ------------------------------- Data Ports ----------------------------- + + RXDATA(63 downto 16) => open, + RXDATA(15 downto 0) => phyRxData(15 downto 0), + TXDATA(63 downto 16) => (others=>'0'), + TXDATA(15 downto 0) => phyTxData(15 downto 0), + + ------------------------------- User Clocks ----------------------------- + + RXMCLK => open, + RXPCSHCLKOUT => open, + RXRECCLK1 => mgtRxRecClk, + RXRECCLK2 => open, + RXUSRCLK => '0', + RXUSRCLK2 => pgpClk, + TXOUTCLK1 => open, + TXOUTCLK2 => open, + TXPCSHCLKOUT => open, + TXUSRCLK => '0', + TXUSRCLK2 => pgpClk, + + ---------------------------- Reference Clocks -------------------------- + + GREFCLK => '0', + REFCLK1 => mgtRefClk1, + REFCLK2 => mgtRefClk2, + + ---------------------------- Powerdown and Loopback Ports -------------- + + LOOPBACK(1) => mgtLoopback, + LOOPBACK(0) => mgtLoopback, + POWERDOWN => '0', + + ------------------- Dynamic Reconfiguration Port (DRP) ------------------ + + DADDR => (others=>'0'), + DCLK => '0', + DEN => '0', + DI => (others=>'0'), + DO => open, + DRDY => open, + DWE => '0', + + --------------------- MGT Tile Communication Ports ------------------ + + COMBUSIN => mgtCombusInA, + COMBUSOUT => mgtCombusOutA + ); + + + --------------------------- GT11 Instantiations --------------------------- + U_MGTB : GT11 + generic map + ( + + ---------- RocketIO MGT 64B66B Block Sync State Machine Attributes --------- + + SH_CNT_MAX => 64, + SH_INVALID_CNT_MAX => 16, + + ----------------------- RocketIO MGT Alignment Atrributes ------------------ + + ALIGN_COMMA_WORD => 2, + COMMA_10B_MASK => x"3ff", + COMMA32 => FALSE, + DEC_MCOMMA_DETECT => FALSE, + DEC_PCOMMA_DETECT => FALSE, + DEC_VALID_COMMA_ONLY => FALSE, + MCOMMA_32B_VALUE => x"00000283", + MCOMMA_DETECT => TRUE, + PCOMMA_32B_VALUE => x"0000017c", + PCOMMA_DETECT => TRUE, + PCS_BIT_SLIP => FALSE, + + ---- RocketIO MGT Atrributes Common to Clk Correction & Channel Bonding ---- + + CCCB_ARBITRATOR_DISABLE => FALSE, + CLK_COR_8B10B_DE => TRUE, + + ------------------- RocketIO MGT Channel Bonding Atrributes ---------------- + + CHAN_BOND_LIMIT => 16, + CHAN_BOND_MODE => "SLAVE_1_HOP", + CHAN_BOND_ONE_SHOT => FALSE, + CHAN_BOND_SEQ_1_1 => "00110111100", + CHAN_BOND_SEQ_1_2 => "00111011100", + CHAN_BOND_SEQ_1_3 => "00111011100", + CHAN_BOND_SEQ_1_4 => "00111011100", + CHAN_BOND_SEQ_1_MASK => "0000", + CHAN_BOND_SEQ_2_1 => "00000000000", + CHAN_BOND_SEQ_2_2 => "00000000000", + CHAN_BOND_SEQ_2_3 => "00000000000", + CHAN_BOND_SEQ_2_4 => "00000000000", + CHAN_BOND_SEQ_2_MASK => "1111", + CHAN_BOND_SEQ_2_USE => FALSE, + CHAN_BOND_SEQ_LEN => 4, + + ------------------ RocketIO MGT Clock Correction Atrributes ---------------- + + CLK_COR_MAX_LAT => 48, + CLK_COR_MIN_LAT => 36, + CLK_COR_SEQ_1_1 => "00110111100", + CLK_COR_SEQ_1_2 => "00100011100", + CLK_COR_SEQ_1_3 => "00100011100", + CLK_COR_SEQ_1_4 => "00100011100", + CLK_COR_SEQ_1_MASK => "0000", + CLK_COR_SEQ_2_1 => "00000000000", + CLK_COR_SEQ_2_2 => "00000000000", + CLK_COR_SEQ_2_3 => "00000000000", + CLK_COR_SEQ_2_4 => "00000000000", + CLK_COR_SEQ_2_MASK => "1111", + CLK_COR_SEQ_2_USE => FALSE, + CLK_COR_SEQ_DROP => FALSE, + CLK_COR_SEQ_LEN => 4, + CLK_CORRECT_USE => TRUE, + + ---------------------- RocketIO MGT Clocking Atrributes -------------------- + + RX_CLOCK_DIVIDER => "01", + RXASYNCDIVIDE => "01", + RXCLK0_FORCE_PMACLK => TRUE, + RXCLKMODE => "000011", + RXOUTDIV2SEL => 2, + RXPLLNDIVSEL => 20, -- 8=1.25, 16=2.5, 20=3.125 + RXPMACLKSEL => RefClkSel, + RXRECCLK1_USE_SYNC => FALSE, + RXUSRDIVISOR => 1, + TX_CLOCK_DIVIDER => "01", + TXABPMACLKSEL => RefClkSel, + TXASYNCDIVIDE => "01", + TXCLK0_FORCE_PMACLK => TRUE, + TXCLKMODE => "0100", + TXOUTCLK1_USE_SYNC => FALSE, + TXOUTDIV2SEL => 2, + TXPHASESEL => FALSE, + TXPLLNDIVSEL => 20, -- 8=1.25, 16=2.5, 20=3.125 + + -------------------------- RocketIO MGT CRC Atrributes --------------------- + + RXCRCCLOCKDOUBLE => FALSE, + RXCRCENABLE => TRUE, + RXCRCINITVAL => x"FFFFFFFF", + RXCRCINVERTGEN => TRUE, + RXCRCSAMECLOCK => TRUE, + TXCRCCLOCKDOUBLE => FALSE, + TXCRCENABLE => TRUE, + TXCRCINITVAL => x"FFFFFFFF", + TXCRCINVERTGEN => TRUE, + TXCRCSAMECLOCK => TRUE, + + --------------------- RocketIO MGT Data Path Atrributes -------------------- + + RXDATA_SEL => "00", + TXDATA_SEL => "00", + + ---------------- RocketIO MGT Digital Receiver Attributes ------------------ + + DIGRX_FWDCLK => "01", + DIGRX_SYNC_MODE => FALSE, + ENABLE_DCDR => FALSE, + RXBY_32 => FALSE, + RXDIGRESET => FALSE, + RXDIGRX => FALSE, + SAMPLE_8X => FALSE, + + ----------------- Rocket IO MGT Miscellaneous Attributes ------------------ + + GT11_MODE => "B", + OPPOSITE_SELECT => FALSE, + PMA_BIT_SLIP => FALSE, + REPEATER => FALSE, + RX_BUFFER_USE => TRUE, + RXCDRLOS => "000000", + RXDCCOUPLE => TRUE, + RXFDCAL_CLOCK_DIVIDE => "NONE", + TX_BUFFER_USE => TRUE, + TXFDCAL_CLOCK_DIVIDE => "NONE", + TXSLEWRATE => FALSE, + + ----------------- Rocket IO MGT Preemphasis and Equalization -------------- + + RXAFEEQ => "000000000", + RXEQ => x"4000FF0303030101", + TXDAT_PRDRV_DAC => "111", + TXDAT_TAP_DAC => "11011", -- = TXPOST_TAP_DAC * 4 + TXHIGHSIGNALEN => TRUE, + TXPOST_PRDRV_DAC => "111", + TXPOST_TAP_DAC => "00010", + TXPOST_TAP_PD => FALSE, + TXPRE_PRDRV_DAC => "111", + TXPRE_TAP_DAC => "00001", -- = TXPOST_TAP_DAC / 2 + TXPRE_TAP_PD => TRUE, + + ----------------------- Restricted RocketIO MGT Attributes ------------------- + + ---Note : THE FOLLOWING ATTRIBUTES ARE RESTRICTED. PLEASE DO NOT EDIT. + + ----------------------------- Restricted: Biasing ------------------------- + + BANDGAPSEL => FALSE, + BIASRESSEL => FALSE, + IREFBIASMODE => "11", + PMAIREFTRIM => "0111", + PMAVREFTRIM => "0111", + TXAREFBIASSEL => TRUE, + TXTERMTRIM => "1100", + VREFBIASMODE => "11", + + ---------------- Restricted: Frequency Detector and Calibration ----------- + + CYCLE_LIMIT_SEL => "00", + FDET_HYS_CAL => "010", + FDET_HYS_SEL => "100", + FDET_LCK_CAL => "101", + FDET_LCK_SEL => "001", + LOOPCAL_WAIT => "00", + RXCYCLE_LIMIT_SEL => "00", + RXFDET_HYS_CAL => "010", + RXFDET_HYS_SEL => "100", + RXFDET_LCK_CAL => "101", + RXFDET_LCK_SEL => "001", + RXLOOPCAL_WAIT => "00", + RXSLOWDOWN_CAL => "00", + SLOWDOWN_CAL => "00", + + --------------------------- Restricted: PLL Settings --------------------- + + PMACLKENABLE => TRUE, + PMACOREPWRENABLE => TRUE, + PMAVBGCTRL => "00000", + RXACTST => FALSE, + RXAFETST => FALSE, + RXCMADJ => "01", + RXCPSEL => TRUE, + RXCPTST => FALSE, + RXCTRL1 => x"200", + RXFECONTROL1 => "00", + RXFECONTROL2 => "000", + RXFETUNE => "01", + RXLKADJ => "00000", + RXLOOPFILT => "1111", + RXPDDTST => TRUE, + RXRCPADJ => "011", + RXRIBADJ => "11", + RXVCO_CTRL_ENABLE => TRUE, + RXVCODAC_INIT => "0000101001", + TXCPSEL => TRUE, + TXCTRL1 => x"200", + TXLOOPFILT => "1101", + VCO_CTRL_ENABLE => TRUE, + VCODAC_INIT => "0000101001", + + --------------------------- Restricted: Powerdowns ------------------------ + + POWER_ENABLE => TRUE, + RXAFEPD => FALSE, + RXAPD => FALSE, + RXLKAPD => FALSE, + RXPD => FALSE, + RXRCPPD => FALSE, + RXRPDPD => FALSE, + RXRSDPD => FALSE, + TXAPD => FALSE, + TXDIGPD => FALSE, + TXLVLSHFTPD => FALSE, + TXPD => FALSE, + + --------------------------- Recent Adds In Latest Software, Unknown ------- + + IN_DELAY => 0 ps, + DCDR_FILTER => "010", + RXAREGCTRL => "00000", + RXCLMODE => "00", + RXLB => FALSE, + RXMODE => "000000", + RXTUNE => X"0000", + TXCLMODE => "00", + TXTUNE => X"0000" + ) + port map + ( + ------------------------------- CRC Ports ------------------------------ + + RXCRCCLK => pgpClk, + RXCRCDATAVALID => '0', + RXCRCDATAWIDTH => (others=>'0'), + RXCRCIN => (others=>'0'), + RXCRCINIT => '0', + RXCRCINTCLK => pgpClk, + RXCRCOUT => open, + RXCRCPD => '0', + RXCRCRESET => '0', + + TXCRCCLK => pgpClk, + TXCRCDATAVALID => '0', + TXCRCDATAWIDTH => (others=>'0'), + TXCRCIN => (others=>'0'), + TXCRCINIT => '0', + TXCRCINTCLK => pgpClk, + TXCRCOUT => open, + TXCRCPD => '0', + TXCRCRESET => '0', + + ---------------------------- Calibration Ports ------------------------ + + RXCALFAIL => open, + RXCYCLELIMIT => open, + TXCALFAIL => open, + TXCYCLELIMIT => open, + + ------------------------------ Serial Ports ---------------------------- + + RX1N => mgtRxN(1), + RX1P => mgtRxP(1), + TX1N => mgtTxN(1), + TX1P => mgtTxP(1), + + ------------------------------- PLL Lock ------------------------------- + + RXLOCK => mgtRxLock(1), + TXLOCK => mgtTxLock(1), + + -------------------------------- Resets ------------------------------- + + RXPMARESET => mgtRxPmaReset(1), + RXRESET => mgtRxReset(1), + TXPMARESET => mgtTxPmaReset(1), + TXRESET => mgtTxReset(1), + + ---------------------------- Synchronization --------------------------- + + RXSYNC => '0', + TXSYNC => '0', + + ---------------------------- Out of Band Signalling ------------------- + + RXSIGDET => open, + TXENOOB => '0', + + -------------------------------- Status -------------------------------- + + RXBUFERR => mgtRxBuffError(1), + RXCLKSTABLE => '1', + RXSTATUS => mgtStatusB, + TXBUFERR => mgtTxBuffError(1), + TXCLKSTABLE => '1', + + ---------------------------- Polarity Control Ports -------------------- + + RXPOLARITY => phyRxPolarity(1), + TXINHIBIT => '0', + TXPOLARITY => '0', + + ------------------------------- Channel Bonding Ports ------------------ + + CHBONDI => mgtChanBond, + CHBONDO => open, + ENCHANSYNC => '1', + + ---------------------------- 64B66B Blocks Use Ports ------------------- + + RXBLOCKSYNC64B66BUSE => '0', + RXDEC64B66BUSE => '0', + RXDESCRAM64B66BUSE => '0', + RXIGNOREBTF => '0', + TXENC64B66BUSE => '0', + TXGEARBOX64B66BUSE => '0', + TXSCRAM64B66BUSE => '0', + + ---------------------------- 8B10B Blocks Use Ports -------------------- + + RXDEC8B10BUSE => '1', + TXBYPASS8B10B(7 downto 2) => (others=>'0'), + TXBYPASS8B10B(1 downto 0) => (others=>'0'), + TXENC8B10BUSE => '1', + + ------------------------------ Transmit Control Ports ------------------ + + TXCHARDISPMODE(7 downto 0) => (others=>'0'), + TXCHARDISPVAL(7 downto 0) => (others=>'0'), + TXCHARISK(7 downto 2) => (others=>'0'), + TXCHARISK(1 downto 0) => phyTxDataK(3 downto 2), + TXKERR(7 downto 0) => open, + TXRUNDISP(7 downto 0) => open, + + ------------------------------ Receive Control Ports ------------------- + + RXCHARISCOMMA => open, + RXCHARISK(7 downto 2) => open, + RXCHARISK(1 downto 0) => phyRxDataK(3 downto 2), + RXDISPERR(7 downto 2) => open, + RXDISPERR(1 downto 0) => phyRxDispErr(3 downto 2), + RXNOTINTABLE(7 downto 2) => open, + RXNOTINTABLE(1 downto 0) => phyRxDecErr(3 downto 2), + RXRUNDISP(7 downto 0) => open, + + ------------------------------- Serdes Alignment ----------------------- + + ENMCOMMAALIGN => '1', + ENPCOMMAALIGN => '1', + RXCOMMADET => open, + RXCOMMADETUSE => '1', + RXLOSSOFSYNC => open, + RXREALIGN => open, + RXSLIDE => '0', + + ----------- Data Width Settings - Internal and fabric interface -------- + + RXDATAWIDTH => "01", + RXINTDATAWIDTH => "11", + TXDATAWIDTH => "01", + TXINTDATAWIDTH => "11", + + ------------------------------- Data Ports ----------------------------- + + RXDATA(63 downto 16) => open, + RXDATA(15 downto 0) => phyRxData(31 downto 16), + TXDATA(63 downto 16) => (others=>'0'), + TXDATA(15 downto 0) => phyTxData(31 downto 16), + + ------------------------------- User Clocks ----------------------------- + + RXMCLK => open, + RXPCSHCLKOUT => open, + RXRECCLK1 => open, + RXRECCLK2 => open, + RXUSRCLK => '0', + RXUSRCLK2 => pgpClk, + TXOUTCLK1 => open, + TXOUTCLK2 => open, + TXPCSHCLKOUT => open, + TXUSRCLK => '0', + TXUSRCLK2 => pgpClk, + + ---------------------------- Reference Clocks -------------------------- + + GREFCLK => '0', + REFCLK1 => mgtRefClk1, + REFCLK2 => mgtRefClk2, + + ---------------------------- Powerdown and Loopback Ports -------------- + + LOOPBACK(1) => mgtLoopback, + LOOPBACK(0) => mgtLoopback, + POWERDOWN => '0', + + ------------------- Dynamic Reconfiguration Port (DRP) ------------------ + + DADDR => (others=>'0'), + DCLK => '0', + DEN => '0', + DI => (others=>'0'), + DO => open, + DRDY => open, + DWE => '0', + + --------------------- MGT Tile Communication Ports ------------------ + + COMBUSIN => mgtCombusOutA, + COMBUSOUT => mgtCombusInA + ); + +end Pgp2Mgt32; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2Mgt64.vhd b/rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2Mgt64.vhd new file mode 100755 index 00000000..7611e3a0 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2Mgt64.vhd @@ -0,0 +1,2114 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, MGT Wrapper, 64-bit +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2Mgt64.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 08/21/2009 +------------------------------------------------------------------------------- +-- Description: +-- VHDL source file containing the PGP, MGT and CRC blocks. 64-bit version. +-- This module supports a standard PGP implementation where a single MGT +-- supports a bi-directional link. Both links operated at the same speed. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 08/21/2009: created. +-- 01/13/2010: Added received init line to help linking. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; +use work.Pgp2MgtPackage.all; +use work.Pgp2CorePackage.all; +library UNISIM; +use UNISIM.VCOMPONENTS.ALL; + +entity Pgp2Mgt64 is + generic ( + EnShortCells : integer := 1; -- Enable short non-EOF cells + VcInterleave : integer := 1; -- Interleave Frames + RefClkSel : string := "REFCLK1" -- Reference Clock To Use "REFCLK1" or "REFCLK2" + ); + port ( + + -- System clock, reset & control + pgpClk : in std_logic; -- 156.25Mhz master clock + pgpReset : in std_logic; -- Synchronous reset input + + -- Frame state flush + pgpFlush : in std_logic; -- Frame state sync + + -- PLL Reset Control + pllTxRst : in std_logic; -- Reset transmit PLL logic + pllRxRst : in std_logic; -- Reset receive PLL logic + + -- PLL Lock Status + pllRxReady : out std_logic; -- MGT Receive logic is ready + pllTxReady : out std_logic; -- MGT Transmit logic is ready + + -- Sideband data + pgpRemData : out std_logic_vector(7 downto 0); -- Far end side User Data + pgpLocData : in std_logic_vector(7 downto 0); -- Far end side User Data + + -- Opcode Transmit Interface + pgpTxOpCodeEn : in std_logic; -- Opcode receive enable + pgpTxOpCode : in std_logic_vector(7 downto 0); -- Opcode receive value + + -- Opcode Receive Interface + pgpRxOpCodeEn : out std_logic; -- Opcode receive enable + pgpRxOpCode : out std_logic_vector(7 downto 0); -- Opcode receive value + + -- Link status + pgpLocLinkReady : out std_logic; -- Local Link is ready + pgpRemLinkReady : out std_logic; -- Far end side has link + + -- Error Flags, one pulse per event + pgpRxCellError : out std_logic; -- A cell error has occured + pgpRxLinkDown : out std_logic; -- A link down event has occured + pgpRxLinkError : out std_logic; -- A link error has occured + + -- Frame Transmit Interface, VC 0 + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc0FrameTxReady : out std_logic; -- PGP is ready + vc0FrameTxSOF : in std_logic; -- User frame data start of frame + vc0FrameTxEOF : in std_logic; -- User frame data end of frame + vc0FrameTxEOFE : in std_logic; -- User frame data error + vc0FrameTxData : in std_logic_vector(63 downto 0); -- User frame data + vc0LocBuffAFull : in std_logic; -- Remote buffer almost full + vc0LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 1 + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxReady : out std_logic; -- PGP is ready + vc1FrameTxSOF : in std_logic; -- User frame data start of frame + vc1FrameTxEOF : in std_logic; -- User frame data end of frame + vc1FrameTxEOFE : in std_logic; -- User frame data error + vc1FrameTxData : in std_logic_vector(63 downto 0); -- User frame data + vc1LocBuffAFull : in std_logic; -- Remote buffer almost full + vc1LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 2 + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxReady : out std_logic; -- PGP is ready + vc2FrameTxSOF : in std_logic; -- User frame data start of frame + vc2FrameTxEOF : in std_logic; -- User frame data end of frame + vc2FrameTxEOFE : in std_logic; -- User frame data error + vc2FrameTxData : in std_logic_vector(63 downto 0); -- User frame data + vc2LocBuffAFull : in std_logic; -- Remote buffer almost full + vc2LocBuffFull : in std_logic; -- Remote buffer full + + -- Frame Transmit Interface, VC 3 + vc3FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxReady : out std_logic; -- PGP is ready + vc3FrameTxSOF : in std_logic; -- User frame data start of frame + vc3FrameTxEOF : in std_logic; -- User frame data end of frame + vc3FrameTxEOFE : in std_logic; -- User frame data error + vc3FrameTxData : in std_logic_vector(63 downto 0); -- User frame data + vc3LocBuffAFull : in std_logic; -- Remote buffer almost full + vc3LocBuffFull : in std_logic; -- Remote buffer full + + -- Common Frame Receive Interface For All VCs + vcFrameRxSOF : out std_logic; -- PGP frame data start of frame + vcFrameRxEOF : out std_logic; -- PGP frame data end of frame + vcFrameRxEOFE : out std_logic; -- PGP frame data error + vcFrameRxData : out std_logic_vector(63 downto 0); -- PGP frame data + + -- Frame Receive Interface, VC 0 + vc0FrameRxValid : out std_logic; -- PGP frame data is valid + vc0RemBuffAFull : out std_logic; -- Remote buffer almost full + vc0RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 1 + vc1FrameRxValid : out std_logic; -- PGP frame data is valid + vc1RemBuffAFull : out std_logic; -- Remote buffer almost full + vc1RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 2 + vc2FrameRxValid : out std_logic; -- PGP frame data is valid + vc2RemBuffAFull : out std_logic; -- Remote buffer almost full + vc2RemBuffFull : out std_logic; -- Remote buffer full + + -- Frame Receive Interface, VC 3 + vc3FrameRxValid : out std_logic; -- PGP frame data is valid + vc3RemBuffAFull : out std_logic; -- Remote buffer almost full + vc3RemBuffFull : out std_logic; -- Remote buffer full + + -- MGT loopback control + mgtLoopback : in std_logic; -- MGT Serial Loopback Control + + -- MGT Signals, Drive Ref Clock Which Matches RefClkSel Generic Above + mgtRefClk1 : in std_logic; -- MGT Reference Clock In 1 + mgtRefClk2 : in std_logic; -- MGT Reference Clock In 2 + mgtRxRecClk : out std_logic; -- MGT Rx Recovered Clock + mgtRxN : in std_logic_vector(3 downto 0); -- MGT Serial Receive Negative + mgtRxP : in std_logic_vector(3 downto 0); -- MGT Serial Receive Positive + mgtTxN : out std_logic_vector(3 downto 0); -- MGT Serial Transmit Negative + mgtTxP : out std_logic_vector(3 downto 0); -- MGT Serial Transmit Positive + + -- Debug + debug : out std_logic_vector(63 downto 0) + ); + +end Pgp2Mgt64; + + +-- Define architecture +architecture Pgp2Mgt64 of Pgp2Mgt64 is + + -- Local Signals + signal crcTxIn : std_logic_vector(63 downto 0); + signal crcTxInMgt : std_logic_vector(63 downto 0); + signal crcTxInit : std_logic; + signal crcTxValid : std_logic; + signal crcTxWidth : std_logic_vector(2 downto 0); + signal crcTxOut : std_logic_vector(31 downto 0); + signal crcRxIn : std_logic_vector(63 downto 0); + signal crcRxInMgt : std_logic_vector(63 downto 0); + signal crcRxInit : std_logic; + signal crcRxValid : std_logic; + signal crcRxWidth : std_logic_vector(2 downto 0); + signal crcRxWidthIn : std_logic; + signal crcRxOut : std_logic_vector(31 downto 0); + signal phyRxPolarity : std_logic_vector(3 downto 0); + signal phyRxData : std_logic_vector(63 downto 0); + signal phyRxDataK : std_logic_vector(7 downto 0); + signal phyTxData : std_logic_vector(63 downto 0); + signal phyTxDataK : std_logic_vector(7 downto 0); + signal mgtRxPmaReset : std_logic_vector(3 downto 0); + signal mgtTxPmaReset : std_logic_vector(3 downto 0); + signal mgtRxReset : std_logic_vector(3 downto 0); + signal mgtTxReset : std_logic_vector(3 downto 0); + signal mgtRxBuffError : std_logic_vector(3 downto 0); + signal mgtTxBuffError : std_logic_vector(3 downto 0); + signal phyRxDispErr : std_logic_vector(7 downto 0); + signal phyRxDecErr : std_logic_vector(7 downto 0); + signal mgtRxLock : std_logic_vector(3 downto 0); + signal mgtTxLock : std_logic_vector(3 downto 0); + signal crcRxReset : std_logic; + signal crcTxReset : std_logic; + signal intTxRst : std_logic; + signal intRxRst : std_logic; + signal phyRxReady : std_logic; + signal phyRxInit : std_logic; + signal phyTxReady : std_logic; + signal intRxReady : std_logic_vector(3 downto 0); + signal intTxReady : std_logic_vector(3 downto 0); + signal pgpRxLinkReady : std_logic; + signal pgpTxLinkReady : std_logic; + signal mgtCombusOutA : std_logic_vector(15 downto 0); + signal mgtCombusInA : std_logic_vector(15 downto 0); + signal mgtCombusOutC : std_logic_vector(15 downto 0); + signal mgtCombusInC : std_logic_vector(15 downto 0); + signal mgtChanBond : std_logic_vector(4 downto 0); + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Adapt CRC data width flag + crcTxWidth <= "111"; + crcRxWidth <= crcRxWidthIn & "11"; + crcRxReset <= mgtRxReset(0); + crcTxReset <= mgtTxReset(0); + + -- Pass CRC data in on proper bits + crcTxInMgt(63 downto 56) <= crcTxIn(7 downto 0); + crcTxInMgt(55 downto 48) <= crcTxIn(15 downto 8); + crcTxInMgt(47 downto 40) <= crcTxIn(23 downto 16); + crcTxInMgt(39 downto 32) <= crcTxIn(31 downto 24); + crcTxInMgt(31 downto 24) <= crcTxIn(39 downto 32); + crcTxInMgt(23 downto 16) <= crcTxIn(47 downto 40); + crcTxInMgt(15 downto 8) <= crcTxIn(55 downto 48); + crcTxInMgt(7 downto 0) <= crcTxIn(63 downto 56); + + crcRxInMgt(63 downto 56) <= crcRxIn(7 downto 0); + crcRxInMgt(55 downto 48) <= crcRxIn(15 downto 8); + crcRxInMgt(47 downto 40) <= crcRxIn(23 downto 16); + crcRxInMgt(39 downto 32) <= crcRxIn(31 downto 24); + crcRxInMgt(31 downto 24) <= crcRxIn(39 downto 32); + crcRxInMgt(23 downto 16) <= crcRxIn(47 downto 40); + crcRxInMgt(15 downto 8) <= crcRxIn(55 downto 48); + crcRxInMgt(7 downto 0) <= crcRxIn(63 downto 56); + + -- Pll Resets + intTxRst <= pllTxRst or pgpReset; + intRxRst <= pllRxRst or pgpReset; + + -- PLL Lock + phyRxReady <= '1' when intRxReady = "1111" else '0'; + phyTxReady <= '1' when intTxReady = "1111" else '0'; + pllRxReady <= phyRxReady; + pllTxReady <= phyTxReady; + + -- Link Ready + pgpLocLinkReady <= pgpRxLinkReady and pgpTxLinkReady; + + + -- PGP Receive Core + U_Pgp2Rx: Pgp2CorePackage.Pgp2Rx + generic map ( + RxLaneCnt => 4, + EnShortCells => EnShortCells + ) port map ( + pgpRxClk => pgpClk, + pgpRxReset => pgpReset, + pgpRxFlush => pgpFlush, + pgpRxLinkReady => pgpRxLinkReady, + pgpRxCellError => pgpRxCellError, + pgpRxLinkReady => pgpRxLinkReady, + pgpRxCellError => pgpRxCellError, + pgpRxLinkDown => pgpRxLinkDown, + pgpRxLinkError => pgpRxLinkError, + pgpRxOpCodeEn => pgpRxOpCodeEn, + pgpRxOpCode => pgpRxOpCode, + pgpRemLinkReady => pgpRemLinkReady, + pgpRemData => pgpRemData, + vcFrameRxSOF => vcFrameRxSOF, + vcFrameRxEOF => vcFrameRxEOF, + vcFrameRxEOFE => vcFrameRxEOFE, + vcFrameRxData => vcFrameRxData, + vc0FrameRxValid => vc0FrameRxValid, + vc0RemBuffAFull => vc0RemBuffAFull, + vc0RemBuffFull => vc0RemBuffFull, + vc1FrameRxValid => vc1FrameRxValid, + vc1RemBuffAFull => vc1RemBuffAFull, + vc1RemBuffFull => vc1RemBuffFull, + vc2FrameRxValid => vc2FrameRxValid, + vc2RemBuffAFull => vc2RemBuffAFull, + vc2RemBuffFull => vc2RemBuffFull, + vc3FrameRxValid => vc3FrameRxValid, + vc3RemBuffAFull => vc3RemBuffAFull, + vc3RemBuffFull => vc3RemBuffFull, + phyRxPolarity => phyRxPolarity, + phyRxData => phyRxData, + phyRxDataK => phyRxDataK, + phyRxDispErr => phyRxDispErr, + phyRxDecErr => phyRxDecErr, + phyRxReady => phyRxReady, + phyRxInit => phyRxInit, + crcRxIn => crcRxIn, + crcRxWidth => crcRxWidthIn, + crcRxInit => crcRxInit, + crcRxValid => crcRxValid, + crcRxOut => crcRxOut, + debug => debug + ); + + + -- PGP Transmit Core + U_Pgp2Tx: Pgp2CorePackage.Pgp2Tx + generic map ( + TxLaneCnt => 4, + VcInterleave => VcInterleave + ) port map ( + pgpTxClk => pgpClk, + pgpTxReset => pgpReset, + pgpTxFlush => pgpFlush, + pgpTxLinkReady => pgpTxLinkReady, + pgpTxOpCodeEn => pgpTxOpCodeEn, + pgpTxOpCode => pgpTxOpCode, + pgpLocLinkReady => pgpRxLinkReady, + pgpLocData => pgpLocData, + vc0FrameTxValid => vc0FrameTxValid, + vc0FrameTxReady => vc0FrameTxReady, + vc0FrameTxSOF => vc0FrameTxSOF, + vc0FrameTxEOF => vc0FrameTxEOF, + vc0FrameTxEOFE => vc0FrameTxEOFE, + vc0FrameTxData => vc0FrameTxData, + vc0LocBuffAFull => vc0LocBuffAFull, + vc0LocBuffFull => vc0LocBuffFull, + vc1FrameTxValid => vc1FrameTxValid, + vc1FrameTxReady => vc1FrameTxReady, + vc1FrameTxSOF => vc1FrameTxSOF, + vc1FrameTxEOF => vc1FrameTxEOF, + vc1FrameTxEOFE => vc1FrameTxEOFE, + vc1FrameTxData => vc1FrameTxData, + vc1LocBuffAFull => vc1LocBuffAFull, + vc1LocBuffFull => vc1LocBuffFull, + vc2FrameTxValid => vc2FrameTxValid, + vc2FrameTxReady => vc2FrameTxReady, + vc2FrameTxSOF => vc2FrameTxSOF, + vc2FrameTxEOF => vc2FrameTxEOF, + vc2FrameTxEOFE => vc2FrameTxEOFE, + vc2FrameTxData => vc2FrameTxData, + vc2LocBuffAFull => vc2LocBuffAFull, + vc2LocBuffFull => vc2LocBuffFull, + vc3FrameTxValid => vc3FrameTxValid, + vc3FrameTxReady => vc3FrameTxReady, + vc3FrameTxSOF => vc3FrameTxSOF, + vc3FrameTxEOF => vc3FrameTxEOF, + vc3FrameTxEOFE => vc3FrameTxEOFE, + vc3FrameTxData => vc3FrameTxData, + vc3LocBuffAFull => vc3LocBuffAFull, + vc3LocBuffFull => vc3LocBuffFull, + phyTxData => phyTxData, + phyTxDataK => phyTxDataK, + phyTxReady => phyTxReady, + crcTxIn => crcTxIn, + crcTxInit => crcTxInit, + crcTxValid => crcTxValid, + crcTxOut => crcTxOut, + debug => open + ); + + + -- MGTA Receive Reset + U_Pgp2MgtRxRstA: Pgp2MgtPackage.Pgp2MgtRxRst port map ( + mgtRxClk => pgpClk, + mgtRxRst => intRxRst, + mgtRxReady => intRxReady(0), + mgtRxInit => phyRxInit, + mgtRxLock => mgtRxLock(0), + mgtRxPmaReset => mgtRxPmaReset(0), + mgtRxReset => mgtRxReset(0), + mgtRxBuffError => mgtRxBuffError(0) + ); + + + -- MGTB Receive Reset + U_Pgp2MgtRxRstB: Pgp2MgtPackage.Pgp2MgtRxRst port map ( + mgtRxClk => pgpClk, + mgtRxRst => intRxRst, + mgtRxReady => intRxReady(1), + mgtRxInit => phyRxInit, + mgtRxLock => mgtRxLock(1), + mgtRxPmaReset => mgtRxPmaReset(1), + mgtRxReset => mgtRxReset(1), + mgtRxBuffError => mgtRxBuffError(1) + ); + + + -- MGTC Receive Reset + U_Pgp2MgtRxRstC: Pgp2MgtPackage.Pgp2MgtRxRst port map ( + mgtRxClk => pgpClk, + mgtRxRst => intRxRst, + mgtRxReady => intRxReady(2), + mgtRxInit => phyRxInit, + mgtRxLock => mgtRxLock(2), + mgtRxPmaReset => mgtRxPmaReset(2), + mgtRxReset => mgtRxReset(2), + mgtRxBuffError => mgtRxBuffError(2) + ); + + + -- MGTD Receive Reset + U_Pgp2MgtRxRstD: Pgp2MgtPackage.Pgp2MgtRxRst port map ( + mgtRxClk => pgpClk, + mgtRxRst => intRxRst, + mgtRxReady => intRxReady(3), + mgtRxInit => phyRxInit, + mgtRxLock => mgtRxLock(3), + mgtRxPmaReset => mgtRxPmaReset(3), + mgtRxReset => mgtRxReset(3), + mgtRxBuffError => mgtRxBuffError(3) + ); + + + -- MGTA Transmit Reset + U_Pgp2MgtTxRstA: Pgp2MgtPackage.Pgp2MgtTxRst port map ( + mgtTxClk => pgpClk, + mgtTxRst => intTxRst, + mgtTxReady => intTxReady(0), + mgtTxLock => mgtTxLock(0), + mgtTxPmaReset => mgtTxPmaReset(0), + mgtTxReset => mgtTxReset(0), + mgtTxBuffError => mgtTxBuffError(0) + ); + + + -- MGTB Transmit Reset + U_Pgp2MgtTxRstB: Pgp2MgtPackage.Pgp2MgtTxRst port map ( + mgtTxClk => pgpClk, + mgtTxRst => intTxRst, + mgtTxReady => intTxReady(1), + mgtTxLock => mgtTxLock(1), + mgtTxPmaReset => mgtTxPmaReset(1), + mgtTxReset => mgtTxReset(1), + mgtTxBuffError => mgtTxBuffError(1) + ); + + + -- MGTC Transmit Reset + U_Pgp2MgtTxRstC: Pgp2MgtPackage.Pgp2MgtTxRst port map ( + mgtTxClk => pgpClk, + mgtTxRst => intTxRst, + mgtTxReady => intTxReady(2), + mgtTxLock => mgtTxLock(2), + mgtTxPmaReset => mgtTxPmaReset(2), + mgtTxReset => mgtTxReset(2), + mgtTxBuffError => mgtTxBuffError(2) + ); + + + -- MGTD Transmit Reset + U_Pgp2MgtTxRstD: Pgp2MgtPackage.Pgp2MgtTxRst port map ( + mgtTxClk => pgpClk, + mgtTxRst => intTxRst, + mgtTxReady => intTxReady(3), + mgtTxLock => mgtTxLock(3), + mgtTxPmaReset => mgtTxPmaReset(3), + mgtTxReset => mgtTxReset(3), + mgtTxBuffError => mgtTxBuffError(3) + ); + + + --------------------------- GT11 Instantiations --------------------------- + U_MGTA : GT11 + generic map + ( + + ---------- RocketIO MGT 64B66B Block Sync State Machine Attributes --------- + + SH_CNT_MAX => 64, + SH_INVALID_CNT_MAX => 16, + + ----------------------- RocketIO MGT Alignment Atrributes ------------------ + + ALIGN_COMMA_WORD => 2, + COMMA_10B_MASK => x"3ff", + COMMA32 => FALSE, + DEC_MCOMMA_DETECT => FALSE, + DEC_PCOMMA_DETECT => FALSE, + DEC_VALID_COMMA_ONLY => FALSE, + MCOMMA_32B_VALUE => x"00000283", + MCOMMA_DETECT => TRUE, + PCOMMA_32B_VALUE => x"0000017c", + PCOMMA_DETECT => TRUE, + PCS_BIT_SLIP => FALSE, + + ---- RocketIO MGT Atrributes Common to Clk Correction & Channel Bonding ---- + + CCCB_ARBITRATOR_DISABLE => FALSE, + CLK_COR_8B10B_DE => TRUE, + + ------------------- RocketIO MGT Channel Bonding Atrributes ---------------- + + CHAN_BOND_LIMIT => 16, + CHAN_BOND_MODE => "MASTER", + CHAN_BOND_ONE_SHOT => FALSE, + CHAN_BOND_SEQ_1_1 => "00110111100", + CHAN_BOND_SEQ_1_2 => "00111011100", + CHAN_BOND_SEQ_1_3 => "00111011100", + CHAN_BOND_SEQ_1_4 => "00111011100", + CHAN_BOND_SEQ_1_MASK => "0000", + CHAN_BOND_SEQ_2_1 => "00000000000", + CHAN_BOND_SEQ_2_2 => "00000000000", + CHAN_BOND_SEQ_2_3 => "00000000000", + CHAN_BOND_SEQ_2_4 => "00000000000", + CHAN_BOND_SEQ_2_MASK => "1111", + CHAN_BOND_SEQ_2_USE => FALSE, + CHAN_BOND_SEQ_LEN => 4, + + ------------------ RocketIO MGT Clock Correction Atrributes ---------------- + + CLK_COR_MAX_LAT => 48, + CLK_COR_MIN_LAT => 36, + CLK_COR_SEQ_1_1 => "00110111100", + CLK_COR_SEQ_1_2 => "00100011100", + CLK_COR_SEQ_1_3 => "00100011100", + CLK_COR_SEQ_1_4 => "00100011100", + CLK_COR_SEQ_1_MASK => "0000", + CLK_COR_SEQ_2_1 => "00000000000", + CLK_COR_SEQ_2_2 => "00000000000", + CLK_COR_SEQ_2_3 => "00000000000", + CLK_COR_SEQ_2_4 => "00000000000", + CLK_COR_SEQ_2_MASK => "1111", + CLK_COR_SEQ_2_USE => FALSE, + CLK_COR_SEQ_DROP => FALSE, + CLK_COR_SEQ_LEN => 4, + CLK_CORRECT_USE => TRUE, + + ---------------------- RocketIO MGT Clocking Atrributes -------------------- + + RX_CLOCK_DIVIDER => "01", + RXASYNCDIVIDE => "01", + RXCLK0_FORCE_PMACLK => TRUE, + RXCLKMODE => "000011", + RXOUTDIV2SEL => 2, + RXPLLNDIVSEL => 20, -- 8=1.25, 16=2.5, 20=3.125 + RXPMACLKSEL => RefClkSel, + RXRECCLK1_USE_SYNC => FALSE, + RXUSRDIVISOR => 1, + TX_CLOCK_DIVIDER => "01", + TXABPMACLKSEL => RefClkSel, + TXASYNCDIVIDE => "01", + TXCLK0_FORCE_PMACLK => TRUE, + TXCLKMODE => "0100", + TXOUTCLK1_USE_SYNC => FALSE, + TXOUTDIV2SEL => 2, + TXPHASESEL => FALSE, + TXPLLNDIVSEL => 20, -- 8=1.25, 16=2.5, 20=3.125 + + -------------------------- RocketIO MGT CRC Atrributes --------------------- + + RXCRCCLOCKDOUBLE => FALSE, + RXCRCENABLE => TRUE, + RXCRCINITVAL => x"FFFFFFFF", + RXCRCINVERTGEN => TRUE, + RXCRCSAMECLOCK => TRUE, + TXCRCCLOCKDOUBLE => FALSE, + TXCRCENABLE => TRUE, + TXCRCINITVAL => x"FFFFFFFF", + TXCRCINVERTGEN => TRUE, + TXCRCSAMECLOCK => TRUE, + + --------------------- RocketIO MGT Data Path Atrributes -------------------- + + RXDATA_SEL => "00", + TXDATA_SEL => "00", + + ---------------- RocketIO MGT Digital Receiver Attributes ------------------ + + DIGRX_FWDCLK => "01", + DIGRX_SYNC_MODE => FALSE, + ENABLE_DCDR => FALSE, + RXBY_32 => FALSE, + RXDIGRESET => FALSE, + RXDIGRX => FALSE, + SAMPLE_8X => FALSE, + + ----------------- Rocket IO MGT Miscellaneous Attributes ------------------ + + GT11_MODE => "A", + OPPOSITE_SELECT => FALSE, + PMA_BIT_SLIP => FALSE, + REPEATER => FALSE, + RX_BUFFER_USE => TRUE, + RXCDRLOS => "000000", + RXDCCOUPLE => TRUE, + RXFDCAL_CLOCK_DIVIDE => "NONE", + TX_BUFFER_USE => TRUE, + TXFDCAL_CLOCK_DIVIDE => "NONE", + TXSLEWRATE => FALSE, + + ----------------- Rocket IO MGT Preemphasis and Equalization -------------- + + RXAFEEQ => "000000000", + RXEQ => x"4000FF0303030101", + TXDAT_PRDRV_DAC => "111", + TXDAT_TAP_DAC => "11011", -- = TXPOST_TAP_DAC * 4 + TXHIGHSIGNALEN => TRUE, + TXPOST_PRDRV_DAC => "111", + TXPOST_TAP_DAC => "00010", + TXPOST_TAP_PD => FALSE, + TXPRE_PRDRV_DAC => "111", + TXPRE_TAP_DAC => "00001", -- = TXPOST_TAP_DAC / 2 + TXPRE_TAP_PD => TRUE, + + ----------------------- Restricted RocketIO MGT Attributes ------------------- + + ---Note : THE FOLLOWING ATTRIBUTES ARE RESTRICTED. PLEASE DO NOT EDIT. + + ----------------------------- Restricted: Biasing ------------------------- + + BANDGAPSEL => FALSE, + BIASRESSEL => FALSE, + IREFBIASMODE => "11", + PMAIREFTRIM => "0111", + PMAVREFTRIM => "0111", + TXAREFBIASSEL => TRUE, + TXTERMTRIM => "1100", + VREFBIASMODE => "11", + + ---------------- Restricted: Frequency Detector and Calibration ----------- + + CYCLE_LIMIT_SEL => "00", + FDET_HYS_CAL => "010", + FDET_HYS_SEL => "100", + FDET_LCK_CAL => "101", + FDET_LCK_SEL => "001", + LOOPCAL_WAIT => "00", + RXCYCLE_LIMIT_SEL => "00", + RXFDET_HYS_CAL => "010", + RXFDET_HYS_SEL => "100", + RXFDET_LCK_CAL => "101", + RXFDET_LCK_SEL => "001", + RXLOOPCAL_WAIT => "00", + RXSLOWDOWN_CAL => "00", + SLOWDOWN_CAL => "00", + + --------------------------- Restricted: PLL Settings --------------------- + + PMACLKENABLE => TRUE, + PMACOREPWRENABLE => TRUE, + PMAVBGCTRL => "00000", + RXACTST => FALSE, + RXAFETST => FALSE, + RXCMADJ => "01", + RXCPSEL => TRUE, + RXCPTST => FALSE, + RXCTRL1 => x"200", + RXFECONTROL1 => "00", + RXFECONTROL2 => "000", + RXFETUNE => "01", + RXLKADJ => "00000", + RXLOOPFILT => "1111", + RXPDDTST => TRUE, + RXRCPADJ => "011", + RXRIBADJ => "11", + RXVCO_CTRL_ENABLE => TRUE, + RXVCODAC_INIT => "0000101001", + TXCPSEL => TRUE, + TXCTRL1 => x"200", + TXLOOPFILT => "1101", + VCO_CTRL_ENABLE => TRUE, + VCODAC_INIT => "0000101001", + + --------------------------- Restricted: Powerdowns ------------------------ + + POWER_ENABLE => TRUE, + RXAFEPD => FALSE, + RXAPD => FALSE, + RXLKAPD => FALSE, + RXPD => FALSE, + RXRCPPD => FALSE, + RXRPDPD => FALSE, + RXRSDPD => FALSE, + TXAPD => FALSE, + TXDIGPD => FALSE, + TXLVLSHFTPD => FALSE, + TXPD => FALSE, + + --------------------------- Recent Adds In Latest Software, Unknown ------- + + IN_DELAY => 0 ps, + DCDR_FILTER => "010", + RXAREGCTRL => "00000", + RXCLMODE => "00", + RXLB => FALSE, + RXMODE => "000000", + RXTUNE => X"0000", + TXCLMODE => "00", + TXTUNE => X"0000" + ) + port map + ( + ------------------------------- CRC Ports ------------------------------ + + RXCRCCLK => pgpClk, + RXCRCDATAVALID => crcRxValid, + RXCRCDATAWIDTH => crcRxWidth, + RXCRCIN => crcRxInMgt, + RXCRCINIT => crcRxInit, + RXCRCINTCLK => pgpClk, + RXCRCOUT => crcRxOut, + RXCRCPD => '0', + RXCRCRESET => crcRxReset, + + TXCRCCLK => pgpClk, + TXCRCDATAVALID => crcTxValid, + TXCRCDATAWIDTH => crcTxWidth, + TXCRCIN => crcTxInMgt, + TXCRCINIT => crcTxInit, + TXCRCINTCLK => pgpClk, + TXCRCOUT => crcTxOut, + TXCRCPD => '0', + TXCRCRESET => crcTxReset, + + ---------------------------- Calibration Ports ------------------------ + + RXCALFAIL => open, + RXCYCLELIMIT => open, + TXCALFAIL => open, + TXCYCLELIMIT => open, + + ------------------------------ Serial Ports ---------------------------- + + RX1N => mgtRxN(0), + RX1P => mgtRxP(0), + TX1N => mgtTxN(0), + TX1P => mgtTxP(0), + + ------------------------------- PLL Lock ------------------------------- + + RXLOCK => mgtRxLock(0), + TXLOCK => mgtTxLock(0), + + -------------------------------- Resets ------------------------------- + + RXPMARESET => mgtRxPmaReset(0), + RXRESET => mgtRxReset(0), + TXPMARESET => mgtTxPmaReset(0), + TXRESET => mgtTxReset(0), + + ---------------------------- Synchronization --------------------------- + + RXSYNC => '0', + TXSYNC => '0', + + ---------------------------- Out of Band Signalling ------------------- + + RXSIGDET => open, + TXENOOB => '0', + + -------------------------------- Status -------------------------------- + + RXBUFERR => mgtRxBuffError(0), + RXCLKSTABLE => '1', + RXSTATUS => open, + TXBUFERR => mgtTxBuffError(0), + TXCLKSTABLE => '1', + + ---------------------------- Polarity Control Ports -------------------- + + RXPOLARITY => phyRxPolarity(0), + TXINHIBIT => '0', + TXPOLARITY => '0', + + ------------------------------- Channel Bonding Ports ------------------ + + CHBONDI => (others=>'0'), + CHBONDO => mgtChanBond, + ENCHANSYNC => '1', + + ---------------------------- 64B66B Blocks Use Ports ------------------- + + RXBLOCKSYNC64B66BUSE => '0', + RXDEC64B66BUSE => '0', + RXDESCRAM64B66BUSE => '0', + RXIGNOREBTF => '0', + TXENC64B66BUSE => '0', + TXGEARBOX64B66BUSE => '0', + TXSCRAM64B66BUSE => '0', + + ---------------------------- 8B10B Blocks Use Ports -------------------- + + RXDEC8B10BUSE => '1', + TXBYPASS8B10B(7 downto 2) => (others=>'0'), + TXBYPASS8B10B(1 downto 0) => (others=>'0'), + TXENC8B10BUSE => '1', + + ------------------------------ Transmit Control Ports ------------------ + + TXCHARDISPMODE(7 downto 0) => (others=>'0'), + TXCHARDISPVAL(7 downto 0) => (others=>'0'), + TXCHARISK(7 downto 2) => (others=>'0'), + TXCHARISK(1 downto 0) => phyTxDataK(1 downto 0), + TXKERR(7 downto 0) => open, + TXRUNDISP(7 downto 0) => open, + + ------------------------------ Receive Control Ports ------------------- + + RXCHARISCOMMA => open, + RXCHARISK(7 downto 2) => open, + RXCHARISK(1 downto 0) => phyRxDataK(1 downto 0), + RXDISPERR(7 downto 2) => open, + RXDISPERR(1 downto 0) => phyRxDispErr(1 downto 0), + RXNOTINTABLE(7 downto 2) => open, + RXNOTINTABLE(1 downto 0) => phyRxDecErr(1 downto 0), + RXRUNDISP(7 downto 0) => open, + + ------------------------------- Serdes Alignment ----------------------- + + ENMCOMMAALIGN => '1', + ENPCOMMAALIGN => '1', + RXCOMMADET => open, + RXCOMMADETUSE => '1', + RXLOSSOFSYNC => open, + RXREALIGN => open, + RXSLIDE => '0', + + ----------- Data Width Settings - Internal and fabric interface -------- + + RXDATAWIDTH => "01", + RXINTDATAWIDTH => "11", + TXDATAWIDTH => "01", + TXINTDATAWIDTH => "11", + + ------------------------------- Data Ports ----------------------------- + + RXDATA(63 downto 16) => open, + RXDATA(15 downto 0) => phyRxData(15 downto 0), + TXDATA(63 downto 16) => (others=>'0'), + TXDATA(15 downto 0) => phyTxData(15 downto 0), + + ------------------------------- User Clocks ----------------------------- + + RXMCLK => open, + RXPCSHCLKOUT => open, + RXRECCLK1 => mgtRxRecClk, + RXRECCLK2 => open, + RXUSRCLK => '0', + RXUSRCLK2 => pgpClk, + TXOUTCLK1 => open, + TXOUTCLK2 => open, + TXPCSHCLKOUT => open, + TXUSRCLK => '0', + TXUSRCLK2 => pgpClk, + + ---------------------------- Reference Clocks -------------------------- + + GREFCLK => '0', + REFCLK1 => mgtRefClk1, + REFCLK2 => mgtRefClk2, + + ---------------------------- Powerdown and Loopback Ports -------------- + + LOOPBACK(1) => mgtLoopback, + LOOPBACK(0) => mgtLoopback, + POWERDOWN => '0', + + ------------------- Dynamic Reconfiguration Port (DRP) ------------------ + + DADDR => (others=>'0'), + DCLK => '0', + DEN => '0', + DI => (others=>'0'), + DO => open, + DRDY => open, + DWE => '0', + + --------------------- MGT Tile Communication Ports ------------------ + + COMBUSIN => mgtCombusInA, + COMBUSOUT => mgtCombusOutA + ); + + + --------------------------- GT11 Instantiations --------------------------- + U_MGTB : GT11 + generic map + ( + + ---------- RocketIO MGT 64B66B Block Sync State Machine Attributes --------- + + SH_CNT_MAX => 64, + SH_INVALID_CNT_MAX => 16, + + ----------------------- RocketIO MGT Alignment Atrributes ------------------ + + ALIGN_COMMA_WORD => 2, + COMMA_10B_MASK => x"3ff", + COMMA32 => FALSE, + DEC_MCOMMA_DETECT => FALSE, + DEC_PCOMMA_DETECT => FALSE, + DEC_VALID_COMMA_ONLY => FALSE, + MCOMMA_32B_VALUE => x"00000283", + MCOMMA_DETECT => TRUE, + PCOMMA_32B_VALUE => x"0000017c", + PCOMMA_DETECT => TRUE, + PCS_BIT_SLIP => FALSE, + + ---- RocketIO MGT Atrributes Common to Clk Correction & Channel Bonding ---- + + CCCB_ARBITRATOR_DISABLE => FALSE, + CLK_COR_8B10B_DE => TRUE, + + ------------------- RocketIO MGT Channel Bonding Atrributes ---------------- + + CHAN_BOND_LIMIT => 16, + CHAN_BOND_MODE => "SLAVE_1_HOP", + CHAN_BOND_ONE_SHOT => FALSE, + CHAN_BOND_SEQ_1_1 => "00110111100", + CHAN_BOND_SEQ_1_2 => "00111011100", + CHAN_BOND_SEQ_1_3 => "00111011100", + CHAN_BOND_SEQ_1_4 => "00111011100", + CHAN_BOND_SEQ_1_MASK => "0000", + CHAN_BOND_SEQ_2_1 => "00000000000", + CHAN_BOND_SEQ_2_2 => "00000000000", + CHAN_BOND_SEQ_2_3 => "00000000000", + CHAN_BOND_SEQ_2_4 => "00000000000", + CHAN_BOND_SEQ_2_MASK => "1111", + CHAN_BOND_SEQ_2_USE => FALSE, + CHAN_BOND_SEQ_LEN => 4, + + ------------------ RocketIO MGT Clock Correction Atrributes ---------------- + + CLK_COR_MAX_LAT => 48, + CLK_COR_MIN_LAT => 36, + CLK_COR_SEQ_1_1 => "00110111100", + CLK_COR_SEQ_1_2 => "00100011100", + CLK_COR_SEQ_1_3 => "00100011100", + CLK_COR_SEQ_1_4 => "00100011100", + CLK_COR_SEQ_1_MASK => "0000", + CLK_COR_SEQ_2_1 => "00000000000", + CLK_COR_SEQ_2_2 => "00000000000", + CLK_COR_SEQ_2_3 => "00000000000", + CLK_COR_SEQ_2_4 => "00000000000", + CLK_COR_SEQ_2_MASK => "1111", + CLK_COR_SEQ_2_USE => FALSE, + CLK_COR_SEQ_DROP => FALSE, + CLK_COR_SEQ_LEN => 4, + CLK_CORRECT_USE => TRUE, + + ---------------------- RocketIO MGT Clocking Atrributes -------------------- + + RX_CLOCK_DIVIDER => "01", + RXASYNCDIVIDE => "01", + RXCLK0_FORCE_PMACLK => TRUE, + RXCLKMODE => "000011", + RXOUTDIV2SEL => 2, + RXPLLNDIVSEL => 20, -- 8=1.25, 16=2.5, 20=3.125 + RXPMACLKSEL => RefClkSel, + RXRECCLK1_USE_SYNC => FALSE, + RXUSRDIVISOR => 1, + TX_CLOCK_DIVIDER => "01", + TXABPMACLKSEL => RefClkSel, + TXASYNCDIVIDE => "01", + TXCLK0_FORCE_PMACLK => TRUE, + TXCLKMODE => "0100", + TXOUTCLK1_USE_SYNC => FALSE, + TXOUTDIV2SEL => 2, + TXPHASESEL => FALSE, + TXPLLNDIVSEL => 20, -- 8=1.25, 16=2.5, 20=3.125 + + -------------------------- RocketIO MGT CRC Atrributes --------------------- + + RXCRCCLOCKDOUBLE => FALSE, + RXCRCENABLE => TRUE, + RXCRCINITVAL => x"FFFFFFFF", + RXCRCINVERTGEN => TRUE, + RXCRCSAMECLOCK => TRUE, + TXCRCCLOCKDOUBLE => FALSE, + TXCRCENABLE => TRUE, + TXCRCINITVAL => x"FFFFFFFF", + TXCRCINVERTGEN => TRUE, + TXCRCSAMECLOCK => TRUE, + + --------------------- RocketIO MGT Data Path Atrributes -------------------- + + RXDATA_SEL => "00", + TXDATA_SEL => "00", + + ---------------- RocketIO MGT Digital Receiver Attributes ------------------ + + DIGRX_FWDCLK => "01", + DIGRX_SYNC_MODE => FALSE, + ENABLE_DCDR => FALSE, + RXBY_32 => FALSE, + RXDIGRESET => FALSE, + RXDIGRX => FALSE, + SAMPLE_8X => FALSE, + + ----------------- Rocket IO MGT Miscellaneous Attributes ------------------ + + GT11_MODE => "B", + OPPOSITE_SELECT => FALSE, + PMA_BIT_SLIP => FALSE, + REPEATER => FALSE, + RX_BUFFER_USE => TRUE, + RXCDRLOS => "000000", + RXDCCOUPLE => TRUE, + RXFDCAL_CLOCK_DIVIDE => "NONE", + TX_BUFFER_USE => TRUE, + TXFDCAL_CLOCK_DIVIDE => "NONE", + TXSLEWRATE => FALSE, + + ----------------- Rocket IO MGT Preemphasis and Equalization -------------- + + RXAFEEQ => "000000000", + RXEQ => x"4000FF0303030101", + TXDAT_PRDRV_DAC => "111", + TXDAT_TAP_DAC => "11011", -- = TXPOST_TAP_DAC * 4 + TXHIGHSIGNALEN => TRUE, + TXPOST_PRDRV_DAC => "111", + TXPOST_TAP_DAC => "00010", + TXPOST_TAP_PD => FALSE, + TXPRE_PRDRV_DAC => "111", + TXPRE_TAP_DAC => "00001", -- = TXPOST_TAP_DAC / 2 + TXPRE_TAP_PD => TRUE, + + ----------------------- Restricted RocketIO MGT Attributes ------------------- + + ---Note : THE FOLLOWING ATTRIBUTES ARE RESTRICTED. PLEASE DO NOT EDIT. + + ----------------------------- Restricted: Biasing ------------------------- + + BANDGAPSEL => FALSE, + BIASRESSEL => FALSE, + IREFBIASMODE => "11", + PMAIREFTRIM => "0111", + PMAVREFTRIM => "0111", + TXAREFBIASSEL => TRUE, + TXTERMTRIM => "1100", + VREFBIASMODE => "11", + + ---------------- Restricted: Frequency Detector and Calibration ----------- + + CYCLE_LIMIT_SEL => "00", + FDET_HYS_CAL => "010", + FDET_HYS_SEL => "100", + FDET_LCK_CAL => "101", + FDET_LCK_SEL => "001", + LOOPCAL_WAIT => "00", + RXCYCLE_LIMIT_SEL => "00", + RXFDET_HYS_CAL => "010", + RXFDET_HYS_SEL => "100", + RXFDET_LCK_CAL => "101", + RXFDET_LCK_SEL => "001", + RXLOOPCAL_WAIT => "00", + RXSLOWDOWN_CAL => "00", + SLOWDOWN_CAL => "00", + + --------------------------- Restricted: PLL Settings --------------------- + + PMACLKENABLE => TRUE, + PMACOREPWRENABLE => TRUE, + PMAVBGCTRL => "00000", + RXACTST => FALSE, + RXAFETST => FALSE, + RXCMADJ => "01", + RXCPSEL => TRUE, + RXCPTST => FALSE, + RXCTRL1 => x"200", + RXFECONTROL1 => "00", + RXFECONTROL2 => "000", + RXFETUNE => "01", + RXLKADJ => "00000", + RXLOOPFILT => "1111", + RXPDDTST => TRUE, + RXRCPADJ => "011", + RXRIBADJ => "11", + RXVCO_CTRL_ENABLE => TRUE, + RXVCODAC_INIT => "0000101001", + TXCPSEL => TRUE, + TXCTRL1 => x"200", + TXLOOPFILT => "1101", + VCO_CTRL_ENABLE => TRUE, + VCODAC_INIT => "0000101001", + + --------------------------- Restricted: Powerdowns ------------------------ + + POWER_ENABLE => TRUE, + RXAFEPD => FALSE, + RXAPD => FALSE, + RXLKAPD => FALSE, + RXPD => FALSE, + RXRCPPD => FALSE, + RXRPDPD => FALSE, + RXRSDPD => FALSE, + TXAPD => FALSE, + TXDIGPD => FALSE, + TXLVLSHFTPD => FALSE, + TXPD => FALSE, + + --------------------------- Recent Adds In Latest Software, Unknown ------- + + IN_DELAY => 0 ps, + DCDR_FILTER => "010", + RXAREGCTRL => "00000", + RXCLMODE => "00", + RXLB => FALSE, + RXMODE => "000000", + RXTUNE => X"0000", + TXCLMODE => "00", + TXTUNE => X"0000" + ) + port map + ( + ------------------------------- CRC Ports ------------------------------ + + RXCRCCLK => pgpClk, + RXCRCDATAVALID => '0', + RXCRCDATAWIDTH => (others=>'0'), + RXCRCIN => (others=>'0'), + RXCRCINIT => '0', + RXCRCINTCLK => pgpClk, + RXCRCOUT => open, + RXCRCPD => '0', + RXCRCRESET => '0', + + TXCRCCLK => pgpClk, + TXCRCDATAVALID => '0', + TXCRCDATAWIDTH => (others=>'0'), + TXCRCIN => (others=>'0'), + TXCRCINIT => '0', + TXCRCINTCLK => pgpClk, + TXCRCOUT => open, + TXCRCPD => '0', + TXCRCRESET => '0', + + ---------------------------- Calibration Ports ------------------------ + + RXCALFAIL => open, + RXCYCLELIMIT => open, + TXCALFAIL => open, + TXCYCLELIMIT => open, + + ------------------------------ Serial Ports ---------------------------- + + RX1N => mgtRxN(1), + RX1P => mgtRxP(1), + TX1N => mgtTxN(1), + TX1P => mgtTxP(1), + + ------------------------------- PLL Lock ------------------------------- + + RXLOCK => mgtRxLock(1), + TXLOCK => mgtTxLock(1), + + -------------------------------- Resets ------------------------------- + + RXPMARESET => mgtRxPmaReset(1), + RXRESET => mgtRxReset(1), + TXPMARESET => mgtTxPmaReset(1), + TXRESET => mgtTxReset(1), + + ---------------------------- Synchronization --------------------------- + + RXSYNC => '0', + TXSYNC => '0', + + ---------------------------- Out of Band Signalling ------------------- + + RXSIGDET => open, + TXENOOB => '0', + + -------------------------------- Status -------------------------------- + + RXBUFERR => mgtRxBuffError(1), + RXCLKSTABLE => '1', + RXSTATUS => open, + TXBUFERR => mgtTxBuffError(1), + TXCLKSTABLE => '1', + + ---------------------------- Polarity Control Ports -------------------- + + RXPOLARITY => phyRxPolarity(1), + TXINHIBIT => '0', + TXPOLARITY => '0', + + ------------------------------- Channel Bonding Ports ------------------ + + CHBONDI => mgtChanBond, + CHBONDO => open, + ENCHANSYNC => '1', + + ---------------------------- 64B66B Blocks Use Ports ------------------- + + RXBLOCKSYNC64B66BUSE => '0', + RXDEC64B66BUSE => '0', + RXDESCRAM64B66BUSE => '0', + RXIGNOREBTF => '0', + TXENC64B66BUSE => '0', + TXGEARBOX64B66BUSE => '0', + TXSCRAM64B66BUSE => '0', + + ---------------------------- 8B10B Blocks Use Ports -------------------- + + RXDEC8B10BUSE => '1', + TXBYPASS8B10B(7 downto 2) => (others=>'0'), + TXBYPASS8B10B(1 downto 0) => (others=>'0'), + TXENC8B10BUSE => '1', + + ------------------------------ Transmit Control Ports ------------------ + + TXCHARDISPMODE(7 downto 0) => (others=>'0'), + TXCHARDISPVAL(7 downto 0) => (others=>'0'), + TXCHARISK(7 downto 2) => (others=>'0'), + TXCHARISK(1 downto 0) => phyTxDataK(3 downto 2), + TXKERR(7 downto 0) => open, + TXRUNDISP(7 downto 0) => open, + + ------------------------------ Receive Control Ports ------------------- + + RXCHARISCOMMA => open, + RXCHARISK(7 downto 2) => open, + RXCHARISK(1 downto 0) => phyRxDataK(3 downto 2), + RXDISPERR(7 downto 2) => open, + RXDISPERR(1 downto 0) => phyRxDispErr(3 downto 2), + RXNOTINTABLE(7 downto 2) => open, + RXNOTINTABLE(1 downto 0) => phyRxDecErr(3 downto 2), + RXRUNDISP(7 downto 0) => open, + + ------------------------------- Serdes Alignment ----------------------- + + ENMCOMMAALIGN => '1', + ENPCOMMAALIGN => '1', + RXCOMMADET => open, + RXCOMMADETUSE => '1', + RXLOSSOFSYNC => open, + RXREALIGN => open, + RXSLIDE => '0', + + ----------- Data Width Settings - Internal and fabric interface -------- + + RXDATAWIDTH => "01", + RXINTDATAWIDTH => "11", + TXDATAWIDTH => "01", + TXINTDATAWIDTH => "11", + + ------------------------------- Data Ports ----------------------------- + + RXDATA(63 downto 16) => open, + RXDATA(15 downto 0) => phyRxData(31 downto 16), + TXDATA(63 downto 16) => (others=>'0'), + TXDATA(15 downto 0) => phyTxData(31 downto 16), + + ------------------------------- User Clocks ----------------------------- + + RXMCLK => open, + RXPCSHCLKOUT => open, + RXRECCLK1 => open, + RXRECCLK2 => open, + RXUSRCLK => '0', + RXUSRCLK2 => pgpClk, + TXOUTCLK1 => open, + TXOUTCLK2 => open, + TXPCSHCLKOUT => open, + TXUSRCLK => '0', + TXUSRCLK2 => pgpClk, + + ---------------------------- Reference Clocks -------------------------- + + GREFCLK => '0', + REFCLK1 => mgtRefClk1, + REFCLK2 => mgtRefClk2, + + ---------------------------- Powerdown and Loopback Ports -------------- + + LOOPBACK(1) => mgtLoopback, + LOOPBACK(0) => mgtLoopback, + POWERDOWN => '0', + + ------------------- Dynamic Reconfiguration Port (DRP) ------------------ + + DADDR => (others=>'0'), + DCLK => '0', + DEN => '0', + DI => (others=>'0'), + DO => open, + DRDY => open, + DWE => '0', + + --------------------- MGT Tile Communication Ports ------------------ + + COMBUSIN => mgtCombusOutA, + COMBUSOUT => mgtCombusInA + ); + + + --------------------------- GT11 Instantiations --------------------------- + U_MGTC : GT11 + generic map + ( + + ---------- RocketIO MGT 64B66B Block Sync State Machine Attributes --------- + + SH_CNT_MAX => 64, + SH_INVALID_CNT_MAX => 16, + + ----------------------- RocketIO MGT Alignment Atrributes ------------------ + + ALIGN_COMMA_WORD => 2, + COMMA_10B_MASK => x"3ff", + COMMA32 => FALSE, + DEC_MCOMMA_DETECT => FALSE, + DEC_PCOMMA_DETECT => FALSE, + DEC_VALID_COMMA_ONLY => FALSE, + MCOMMA_32B_VALUE => x"00000283", + MCOMMA_DETECT => TRUE, + PCOMMA_32B_VALUE => x"0000017c", + PCOMMA_DETECT => TRUE, + PCS_BIT_SLIP => FALSE, + + ---- RocketIO MGT Atrributes Common to Clk Correction & Channel Bonding ---- + + CCCB_ARBITRATOR_DISABLE => FALSE, + CLK_COR_8B10B_DE => TRUE, + + ------------------- RocketIO MGT Channel Bonding Atrributes ---------------- + + CHAN_BOND_LIMIT => 16, + CHAN_BOND_MODE => "SLAVE_1_HOP", + CHAN_BOND_ONE_SHOT => FALSE, + CHAN_BOND_SEQ_1_1 => "00110111100", + CHAN_BOND_SEQ_1_2 => "00111011100", + CHAN_BOND_SEQ_1_3 => "00111011100", + CHAN_BOND_SEQ_1_4 => "00111011100", + CHAN_BOND_SEQ_1_MASK => "0000", + CHAN_BOND_SEQ_2_1 => "00000000000", + CHAN_BOND_SEQ_2_2 => "00000000000", + CHAN_BOND_SEQ_2_3 => "00000000000", + CHAN_BOND_SEQ_2_4 => "00000000000", + CHAN_BOND_SEQ_2_MASK => "1111", + CHAN_BOND_SEQ_2_USE => FALSE, + CHAN_BOND_SEQ_LEN => 4, + + ------------------ RocketIO MGT Clock Correction Atrributes ---------------- + + CLK_COR_MAX_LAT => 48, + CLK_COR_MIN_LAT => 36, + CLK_COR_SEQ_1_1 => "00110111100", + CLK_COR_SEQ_1_2 => "00100011100", + CLK_COR_SEQ_1_3 => "00100011100", + CLK_COR_SEQ_1_4 => "00100011100", + CLK_COR_SEQ_1_MASK => "0000", + CLK_COR_SEQ_2_1 => "00000000000", + CLK_COR_SEQ_2_2 => "00000000000", + CLK_COR_SEQ_2_3 => "00000000000", + CLK_COR_SEQ_2_4 => "00000000000", + CLK_COR_SEQ_2_MASK => "1111", + CLK_COR_SEQ_2_USE => FALSE, + CLK_COR_SEQ_DROP => FALSE, + CLK_COR_SEQ_LEN => 4, + CLK_CORRECT_USE => TRUE, + + ---------------------- RocketIO MGT Clocking Atrributes -------------------- + + RX_CLOCK_DIVIDER => "01", + RXASYNCDIVIDE => "01", + RXCLK0_FORCE_PMACLK => TRUE, + RXCLKMODE => "000011", + RXOUTDIV2SEL => 2, + RXPLLNDIVSEL => 20, -- 8=1.25, 16=2.5, 20=3.125 + RXPMACLKSEL => RefClkSel, + RXRECCLK1_USE_SYNC => FALSE, + RXUSRDIVISOR => 1, + TX_CLOCK_DIVIDER => "01", + TXABPMACLKSEL => RefClkSel, + TXASYNCDIVIDE => "01", + TXCLK0_FORCE_PMACLK => TRUE, + TXCLKMODE => "0100", + TXOUTCLK1_USE_SYNC => FALSE, + TXOUTDIV2SEL => 2, + TXPHASESEL => FALSE, + TXPLLNDIVSEL => 20, -- 8=1.25, 16=2.5, 20=3.125 + + -------------------------- RocketIO MGT CRC Atrributes --------------------- + + RXCRCCLOCKDOUBLE => FALSE, + RXCRCENABLE => TRUE, + RXCRCINITVAL => x"FFFFFFFF", + RXCRCINVERTGEN => TRUE, + RXCRCSAMECLOCK => TRUE, + TXCRCCLOCKDOUBLE => FALSE, + TXCRCENABLE => TRUE, + TXCRCINITVAL => x"FFFFFFFF", + TXCRCINVERTGEN => TRUE, + TXCRCSAMECLOCK => TRUE, + + --------------------- RocketIO MGT Data Path Atrributes -------------------- + + RXDATA_SEL => "00", + TXDATA_SEL => "00", + + ---------------- RocketIO MGT Digital Receiver Attributes ------------------ + + DIGRX_FWDCLK => "01", + DIGRX_SYNC_MODE => FALSE, + ENABLE_DCDR => FALSE, + RXBY_32 => FALSE, + RXDIGRESET => FALSE, + RXDIGRX => FALSE, + SAMPLE_8X => FALSE, + + ----------------- Rocket IO MGT Miscellaneous Attributes ------------------ + + GT11_MODE => "A", + OPPOSITE_SELECT => FALSE, + PMA_BIT_SLIP => FALSE, + REPEATER => FALSE, + RX_BUFFER_USE => TRUE, + RXCDRLOS => "000000", + RXDCCOUPLE => TRUE, + RXFDCAL_CLOCK_DIVIDE => "NONE", + TX_BUFFER_USE => TRUE, + TXFDCAL_CLOCK_DIVIDE => "NONE", + TXSLEWRATE => FALSE, + + ----------------- Rocket IO MGT Preemphasis and Equalization -------------- + + RXAFEEQ => "000000000", + RXEQ => x"4000FF0303030101", + TXDAT_PRDRV_DAC => "111", + TXDAT_TAP_DAC => "11011", -- = TXPOST_TAP_DAC * 4 + TXHIGHSIGNALEN => TRUE, + TXPOST_PRDRV_DAC => "111", + TXPOST_TAP_DAC => "00010", + TXPOST_TAP_PD => FALSE, + TXPRE_PRDRV_DAC => "111", + TXPRE_TAP_DAC => "00001", -- = TXPOST_TAP_DAC / 2 + TXPRE_TAP_PD => TRUE, + + ----------------------- Restricted RocketIO MGT Attributes ------------------- + + ---Note : THE FOLLOWING ATTRIBUTES ARE RESTRICTED. PLEASE DO NOT EDIT. + + ----------------------------- Restricted: Biasing ------------------------- + + BANDGAPSEL => FALSE, + BIASRESSEL => FALSE, + IREFBIASMODE => "11", + PMAIREFTRIM => "0111", + PMAVREFTRIM => "0111", + TXAREFBIASSEL => TRUE, + TXTERMTRIM => "1100", + VREFBIASMODE => "11", + + ---------------- Restricted: Frequency Detector and Calibration ----------- + + CYCLE_LIMIT_SEL => "00", + FDET_HYS_CAL => "010", + FDET_HYS_SEL => "100", + FDET_LCK_CAL => "101", + FDET_LCK_SEL => "001", + LOOPCAL_WAIT => "00", + RXCYCLE_LIMIT_SEL => "00", + RXFDET_HYS_CAL => "010", + RXFDET_HYS_SEL => "100", + RXFDET_LCK_CAL => "101", + RXFDET_LCK_SEL => "001", + RXLOOPCAL_WAIT => "00", + RXSLOWDOWN_CAL => "00", + SLOWDOWN_CAL => "00", + + --------------------------- Restricted: PLL Settings --------------------- + + PMACLKENABLE => TRUE, + PMACOREPWRENABLE => TRUE, + PMAVBGCTRL => "00000", + RXACTST => FALSE, + RXAFETST => FALSE, + RXCMADJ => "01", + RXCPSEL => TRUE, + RXCPTST => FALSE, + RXCTRL1 => x"200", + RXFECONTROL1 => "00", + RXFECONTROL2 => "000", + RXFETUNE => "01", + RXLKADJ => "00000", + RXLOOPFILT => "1111", + RXPDDTST => TRUE, + RXRCPADJ => "011", + RXRIBADJ => "11", + RXVCO_CTRL_ENABLE => TRUE, + RXVCODAC_INIT => "0000101001", + TXCPSEL => TRUE, + TXCTRL1 => x"200", + TXLOOPFILT => "1101", + VCO_CTRL_ENABLE => TRUE, + VCODAC_INIT => "0000101001", + + --------------------------- Restricted: Powerdowns ------------------------ + + POWER_ENABLE => TRUE, + RXAFEPD => FALSE, + RXAPD => FALSE, + RXLKAPD => FALSE, + RXPD => FALSE, + RXRCPPD => FALSE, + RXRPDPD => FALSE, + RXRSDPD => FALSE, + TXAPD => FALSE, + TXDIGPD => FALSE, + TXLVLSHFTPD => FALSE, + TXPD => FALSE, + + --------------------------- Recent Adds In Latest Software, Unknown ------- + + IN_DELAY => 0 ps, + DCDR_FILTER => "010", + RXAREGCTRL => "00000", + RXCLMODE => "00", + RXLB => FALSE, + RXMODE => "000000", + RXTUNE => X"0000", + TXCLMODE => "00", + TXTUNE => X"0000" + ) + port map + ( + ------------------------------- CRC Ports ------------------------------ + + RXCRCCLK => pgpClk, + RXCRCDATAVALID => '0', + RXCRCDATAWIDTH => (others=>'0'), + RXCRCIN => (others=>'0'), + RXCRCINIT => '0', + RXCRCINTCLK => pgpClk, + RXCRCOUT => open, + RXCRCPD => '0', + RXCRCRESET => '0', + + TXCRCCLK => pgpClk, + TXCRCDATAVALID => '0', + TXCRCDATAWIDTH => (others=>'0'), + TXCRCIN => (others=>'0'), + TXCRCINIT => '0', + TXCRCINTCLK => pgpClk, + TXCRCOUT => open, + TXCRCPD => '0', + TXCRCRESET => '0', + + ---------------------------- Calibration Ports ------------------------ + + RXCALFAIL => open, + RXCYCLELIMIT => open, + TXCALFAIL => open, + TXCYCLELIMIT => open, + + ------------------------------ Serial Ports ---------------------------- + + RX1N => mgtRxN(2), + RX1P => mgtRxP(2), + TX1N => mgtTxN(2), + TX1P => mgtTxP(2), + + ------------------------------- PLL Lock ------------------------------- + + RXLOCK => mgtRxLock(2), + TXLOCK => mgtTxLock(2), + + -------------------------------- Resets ------------------------------- + + RXPMARESET => mgtRxPmaReset(2), + RXRESET => mgtRxReset(2), + TXPMARESET => mgtTxPmaReset(2), + TXRESET => mgtTxReset(2), + + ---------------------------- Synchronization --------------------------- + + RXSYNC => '0', + TXSYNC => '0', + + ---------------------------- Out of Band Signalling ------------------- + + RXSIGDET => open, + TXENOOB => '0', + + -------------------------------- Status -------------------------------- + + RXBUFERR => mgtRxBuffError(2), + RXCLKSTABLE => '1', + RXSTATUS => open, + TXBUFERR => mgtTxBuffError(2), + TXCLKSTABLE => '1', + + ---------------------------- Polarity Control Ports -------------------- + + RXPOLARITY => phyRxPolarity(2), + TXINHIBIT => '0', + TXPOLARITY => '0', + + ------------------------------- Channel Bonding Ports ------------------ + + CHBONDI => mgtChanBond, + CHBONDO => open, + ENCHANSYNC => '1', + + ---------------------------- 64B66B Blocks Use Ports ------------------- + + RXBLOCKSYNC64B66BUSE => '0', + RXDEC64B66BUSE => '0', + RXDESCRAM64B66BUSE => '0', + RXIGNOREBTF => '0', + TXENC64B66BUSE => '0', + TXGEARBOX64B66BUSE => '0', + TXSCRAM64B66BUSE => '0', + + ---------------------------- 8B10B Blocks Use Ports -------------------- + + RXDEC8B10BUSE => '1', + TXBYPASS8B10B(7 downto 2) => (others=>'0'), + TXBYPASS8B10B(1 downto 0) => (others=>'0'), + TXENC8B10BUSE => '1', + + ------------------------------ Transmit Control Ports ------------------ + + TXCHARDISPMODE(7 downto 0) => (others=>'0'), + TXCHARDISPVAL(7 downto 0) => (others=>'0'), + TXCHARISK(7 downto 2) => (others=>'0'), + TXCHARISK(1 downto 0) => phyTxDataK(5 downto 4), + TXKERR(7 downto 0) => open, + TXRUNDISP(7 downto 0) => open, + + ------------------------------ Receive Control Ports ------------------- + + RXCHARISCOMMA => open, + RXCHARISK(7 downto 2) => open, + RXCHARISK(1 downto 0) => phyRxDataK(5 downto 4), + RXDISPERR(7 downto 2) => open, + RXDISPERR(1 downto 0) => phyRxDispErr(5 downto 4), + RXNOTINTABLE(7 downto 2) => open, + RXNOTINTABLE(1 downto 0) => phyRxDecErr(5 downto 4), + RXRUNDISP(7 downto 0) => open, + + ------------------------------- Serdes Alignment ----------------------- + + ENMCOMMAALIGN => '1', + ENPCOMMAALIGN => '1', + RXCOMMADET => open, + RXCOMMADETUSE => '1', + RXLOSSOFSYNC => open, + RXREALIGN => open, + RXSLIDE => '0', + + ----------- Data Width Settings - Internal and fabric interface -------- + + RXDATAWIDTH => "01", + RXINTDATAWIDTH => "11", + TXDATAWIDTH => "01", + TXINTDATAWIDTH => "11", + + ------------------------------- Data Ports ----------------------------- + + RXDATA(63 downto 16) => open, + RXDATA(15 downto 0) => phyRxData(47 downto 32), + TXDATA(63 downto 16) => (others=>'0'), + TXDATA(15 downto 0) => phyTxData(47 downto 32), + + ------------------------------- User Clocks ----------------------------- + + RXMCLK => open, + RXPCSHCLKOUT => open, + RXRECCLK1 => open, + RXRECCLK2 => open, + RXUSRCLK => '0', + RXUSRCLK2 => pgpClk, + TXOUTCLK1 => open, + TXOUTCLK2 => open, + TXPCSHCLKOUT => open, + TXUSRCLK => '0', + TXUSRCLK2 => pgpClk, + + ---------------------------- Reference Clocks -------------------------- + + GREFCLK => '0', + REFCLK1 => mgtRefClk1, + REFCLK2 => mgtRefClk2, + + ---------------------------- Powerdown and Loopback Ports -------------- + + LOOPBACK(1) => mgtLoopback, + LOOPBACK(0) => mgtLoopback, + POWERDOWN => '0', + + ------------------- Dynamic Reconfiguration Port (DRP) ------------------ + + DADDR => (others=>'0'), + DCLK => '0', + DEN => '0', + DI => (others=>'0'), + DO => open, + DRDY => open, + DWE => '0', + + --------------------- MGT Tile Communication Ports ------------------ + + COMBUSIN => mgtCombusInC, + COMBUSOUT => mgtCombusOutC + ); + + + --------------------------- GT11 Instantiations --------------------------- + U_MGTD : GT11 + generic map + ( + + ---------- RocketIO MGT 64B66B Block Sync State Machine Attributes --------- + + SH_CNT_MAX => 64, + SH_INVALID_CNT_MAX => 16, + + ----------------------- RocketIO MGT Alignment Atrributes ------------------ + + ALIGN_COMMA_WORD => 2, + COMMA_10B_MASK => x"3ff", + COMMA32 => FALSE, + DEC_MCOMMA_DETECT => FALSE, + DEC_PCOMMA_DETECT => FALSE, + DEC_VALID_COMMA_ONLY => FALSE, + MCOMMA_32B_VALUE => x"00000283", + MCOMMA_DETECT => TRUE, + PCOMMA_32B_VALUE => x"0000017c", + PCOMMA_DETECT => TRUE, + PCS_BIT_SLIP => FALSE, + + ---- RocketIO MGT Atrributes Common to Clk Correction & Channel Bonding ---- + + CCCB_ARBITRATOR_DISABLE => FALSE, + CLK_COR_8B10B_DE => TRUE, + + ------------------- RocketIO MGT Channel Bonding Atrributes ---------------- + + CHAN_BOND_LIMIT => 16, + CHAN_BOND_MODE => "SLAVE_1_HOP", + CHAN_BOND_ONE_SHOT => FALSE, + CHAN_BOND_SEQ_1_1 => "00110111100", + CHAN_BOND_SEQ_1_2 => "00111011100", + CHAN_BOND_SEQ_1_3 => "00111011100", + CHAN_BOND_SEQ_1_4 => "00111011100", + CHAN_BOND_SEQ_1_MASK => "0000", + CHAN_BOND_SEQ_2_1 => "00000000000", + CHAN_BOND_SEQ_2_2 => "00000000000", + CHAN_BOND_SEQ_2_3 => "00000000000", + CHAN_BOND_SEQ_2_4 => "00000000000", + CHAN_BOND_SEQ_2_MASK => "1111", + CHAN_BOND_SEQ_2_USE => FALSE, + CHAN_BOND_SEQ_LEN => 4, + + ------------------ RocketIO MGT Clock Correction Atrributes ---------------- + + CLK_COR_MAX_LAT => 48, + CLK_COR_MIN_LAT => 36, + CLK_COR_SEQ_1_1 => "00110111100", + CLK_COR_SEQ_1_2 => "00100011100", + CLK_COR_SEQ_1_3 => "00100011100", + CLK_COR_SEQ_1_4 => "00100011100", + CLK_COR_SEQ_1_MASK => "0000", + CLK_COR_SEQ_2_1 => "00000000000", + CLK_COR_SEQ_2_2 => "00000000000", + CLK_COR_SEQ_2_3 => "00000000000", + CLK_COR_SEQ_2_4 => "00000000000", + CLK_COR_SEQ_2_MASK => "1111", + CLK_COR_SEQ_2_USE => FALSE, + CLK_COR_SEQ_DROP => FALSE, + CLK_COR_SEQ_LEN => 4, + CLK_CORRECT_USE => TRUE, + + ---------------------- RocketIO MGT Clocking Atrributes -------------------- + + RX_CLOCK_DIVIDER => "01", + RXASYNCDIVIDE => "01", + RXCLK0_FORCE_PMACLK => TRUE, + RXCLKMODE => "000011", + RXOUTDIV2SEL => 2, + RXPLLNDIVSEL => 20, -- 8=1.25, 16=2.5, 20=3.125 + RXPMACLKSEL => RefClkSel, + RXRECCLK1_USE_SYNC => FALSE, + RXUSRDIVISOR => 1, + TX_CLOCK_DIVIDER => "01", + TXABPMACLKSEL => RefClkSel, + TXASYNCDIVIDE => "01", + TXCLK0_FORCE_PMACLK => TRUE, + TXCLKMODE => "0100", + TXOUTCLK1_USE_SYNC => FALSE, + TXOUTDIV2SEL => 2, + TXPHASESEL => FALSE, + TXPLLNDIVSEL => 20, -- 8=1.25, 16=2.5, 20=3.125 + + -------------------------- RocketIO MGT CRC Atrributes --------------------- + + RXCRCCLOCKDOUBLE => FALSE, + RXCRCENABLE => TRUE, + RXCRCINITVAL => x"FFFFFFFF", + RXCRCINVERTGEN => TRUE, + RXCRCSAMECLOCK => TRUE, + TXCRCCLOCKDOUBLE => FALSE, + TXCRCENABLE => TRUE, + TXCRCINITVAL => x"FFFFFFFF", + TXCRCINVERTGEN => TRUE, + TXCRCSAMECLOCK => TRUE, + + --------------------- RocketIO MGT Data Path Atrributes -------------------- + + RXDATA_SEL => "00", + TXDATA_SEL => "00", + + ---------------- RocketIO MGT Digital Receiver Attributes ------------------ + + DIGRX_FWDCLK => "01", + DIGRX_SYNC_MODE => FALSE, + ENABLE_DCDR => FALSE, + RXBY_32 => FALSE, + RXDIGRESET => FALSE, + RXDIGRX => FALSE, + SAMPLE_8X => FALSE, + + ----------------- Rocket IO MGT Miscellaneous Attributes ------------------ + + GT11_MODE => "B", + OPPOSITE_SELECT => FALSE, + PMA_BIT_SLIP => FALSE, + REPEATER => FALSE, + RX_BUFFER_USE => TRUE, + RXCDRLOS => "000000", + RXDCCOUPLE => TRUE, + RXFDCAL_CLOCK_DIVIDE => "NONE", + TX_BUFFER_USE => TRUE, + TXFDCAL_CLOCK_DIVIDE => "NONE", + TXSLEWRATE => FALSE, + + ----------------- Rocket IO MGT Preemphasis and Equalization -------------- + + RXAFEEQ => "000000000", + RXEQ => x"4000FF0303030101", + TXDAT_PRDRV_DAC => "111", + TXDAT_TAP_DAC => "11011", -- = TXPOST_TAP_DAC * 4 + TXHIGHSIGNALEN => TRUE, + TXPOST_PRDRV_DAC => "111", + TXPOST_TAP_DAC => "00010", + TXPOST_TAP_PD => FALSE, + TXPRE_PRDRV_DAC => "111", + TXPRE_TAP_DAC => "00001", -- = TXPOST_TAP_DAC / 2 + TXPRE_TAP_PD => TRUE, + + ----------------------- Restricted RocketIO MGT Attributes ------------------- + + ---Note : THE FOLLOWING ATTRIBUTES ARE RESTRICTED. PLEASE DO NOT EDIT. + + ----------------------------- Restricted: Biasing ------------------------- + + BANDGAPSEL => FALSE, + BIASRESSEL => FALSE, + IREFBIASMODE => "11", + PMAIREFTRIM => "0111", + PMAVREFTRIM => "0111", + TXAREFBIASSEL => TRUE, + TXTERMTRIM => "1100", + VREFBIASMODE => "11", + + ---------------- Restricted: Frequency Detector and Calibration ----------- + + CYCLE_LIMIT_SEL => "00", + FDET_HYS_CAL => "010", + FDET_HYS_SEL => "100", + FDET_LCK_CAL => "101", + FDET_LCK_SEL => "001", + LOOPCAL_WAIT => "00", + RXCYCLE_LIMIT_SEL => "00", + RXFDET_HYS_CAL => "010", + RXFDET_HYS_SEL => "100", + RXFDET_LCK_CAL => "101", + RXFDET_LCK_SEL => "001", + RXLOOPCAL_WAIT => "00", + RXSLOWDOWN_CAL => "00", + SLOWDOWN_CAL => "00", + + --------------------------- Restricted: PLL Settings --------------------- + + PMACLKENABLE => TRUE, + PMACOREPWRENABLE => TRUE, + PMAVBGCTRL => "00000", + RXACTST => FALSE, + RXAFETST => FALSE, + RXCMADJ => "01", + RXCPSEL => TRUE, + RXCPTST => FALSE, + RXCTRL1 => x"200", + RXFECONTROL1 => "00", + RXFECONTROL2 => "000", + RXFETUNE => "01", + RXLKADJ => "00000", + RXLOOPFILT => "1111", + RXPDDTST => TRUE, + RXRCPADJ => "011", + RXRIBADJ => "11", + RXVCO_CTRL_ENABLE => TRUE, + RXVCODAC_INIT => "0000101001", + TXCPSEL => TRUE, + TXCTRL1 => x"200", + TXLOOPFILT => "1101", + VCO_CTRL_ENABLE => TRUE, + VCODAC_INIT => "0000101001", + + --------------------------- Restricted: Powerdowns ------------------------ + + POWER_ENABLE => TRUE, + RXAFEPD => FALSE, + RXAPD => FALSE, + RXLKAPD => FALSE, + RXPD => FALSE, + RXRCPPD => FALSE, + RXRPDPD => FALSE, + RXRSDPD => FALSE, + TXAPD => FALSE, + TXDIGPD => FALSE, + TXLVLSHFTPD => FALSE, + TXPD => FALSE, + + --------------------------- Recent Adds In Latest Software, Unknown ------- + + IN_DELAY => 0 ps, + DCDR_FILTER => "010", + RXAREGCTRL => "00000", + RXCLMODE => "00", + RXLB => FALSE, + RXMODE => "000000", + RXTUNE => X"0000", + TXCLMODE => "00", + TXTUNE => X"0000" + ) + port map + ( + ------------------------------- CRC Ports ------------------------------ + + RXCRCCLK => pgpClk, + RXCRCDATAVALID => '0', + RXCRCDATAWIDTH => (others=>'0'), + RXCRCIN => (others=>'0'), + RXCRCINIT => '0', + RXCRCINTCLK => pgpClk, + RXCRCOUT => open, + RXCRCPD => '0', + RXCRCRESET => '0', + + TXCRCCLK => pgpClk, + TXCRCDATAVALID => '0', + TXCRCDATAWIDTH => (others=>'0'), + TXCRCIN => (others=>'0'), + TXCRCINIT => '0', + TXCRCINTCLK => pgpClk, + TXCRCOUT => open, + TXCRCPD => '0', + TXCRCRESET => '0', + + ---------------------------- Calibration Ports ------------------------ + + RXCALFAIL => open, + RXCYCLELIMIT => open, + TXCALFAIL => open, + TXCYCLELIMIT => open, + + ------------------------------ Serial Ports ---------------------------- + + RX1N => mgtRxN(3), + RX1P => mgtRxP(3), + TX1N => mgtTxN(3), + TX1P => mgtTxP(3), + + ------------------------------- PLL Lock ------------------------------- + + RXLOCK => mgtRxLock(3), + TXLOCK => mgtTxLock(3), + + -------------------------------- Resets ------------------------------- + + RXPMARESET => mgtRxPmaReset(3), + RXRESET => mgtRxReset(3), + TXPMARESET => mgtTxPmaReset(3), + TXRESET => mgtTxReset(3), + + ---------------------------- Synchronization --------------------------- + + RXSYNC => '0', + TXSYNC => '0', + + ---------------------------- Out of Band Signalling ------------------- + + RXSIGDET => open, + TXENOOB => '0', + + -------------------------------- Status -------------------------------- + + RXBUFERR => mgtRxBuffError(3), + RXCLKSTABLE => '1', + RXSTATUS => open, + TXBUFERR => mgtTxBuffError(3), + TXCLKSTABLE => '1', + + ---------------------------- Polarity Control Ports -------------------- + + RXPOLARITY => phyRxPolarity(3), + TXINHIBIT => '0', + TXPOLARITY => '0', + + ------------------------------- Channel Bonding Ports ------------------ + + CHBONDI => mgtChanBond, + CHBONDO => open, + ENCHANSYNC => '1', + + ---------------------------- 64B66B Blocks Use Ports ------------------- + + RXBLOCKSYNC64B66BUSE => '0', + RXDEC64B66BUSE => '0', + RXDESCRAM64B66BUSE => '0', + RXIGNOREBTF => '0', + TXENC64B66BUSE => '0', + TXGEARBOX64B66BUSE => '0', + TXSCRAM64B66BUSE => '0', + + ---------------------------- 8B10B Blocks Use Ports -------------------- + + RXDEC8B10BUSE => '1', + TXBYPASS8B10B(7 downto 2) => (others=>'0'), + TXBYPASS8B10B(1 downto 0) => (others=>'0'), + TXENC8B10BUSE => '1', + + ------------------------------ Transmit Control Ports ------------------ + + TXCHARDISPMODE(7 downto 0) => (others=>'0'), + TXCHARDISPVAL(7 downto 0) => (others=>'0'), + TXCHARISK(7 downto 2) => (others=>'0'), + TXCHARISK(1 downto 0) => phyTxDataK(3 downto 2), + TXKERR(7 downto 0) => open, + TXRUNDISP(7 downto 0) => open, + + ------------------------------ Receive Control Ports ------------------- + + RXCHARISCOMMA => open, + RXCHARISK(7 downto 2) => open, + RXCHARISK(1 downto 0) => phyRxDataK(7 downto 6), + RXDISPERR(7 downto 2) => open, + RXDISPERR(1 downto 0) => phyRxDispErr(7 downto 6), + RXNOTINTABLE(7 downto 2) => open, + RXNOTINTABLE(1 downto 0) => phyRxDecErr(7 downto 6), + RXRUNDISP(7 downto 0) => open, + + ------------------------------- Serdes Alignment ----------------------- + + ENMCOMMAALIGN => '1', + ENPCOMMAALIGN => '1', + RXCOMMADET => open, + RXCOMMADETUSE => '1', + RXLOSSOFSYNC => open, + RXREALIGN => open, + RXSLIDE => '0', + + ----------- Data Width Settings - Internal and fabric interface -------- + + RXDATAWIDTH => "01", + RXINTDATAWIDTH => "11", + TXDATAWIDTH => "01", + TXINTDATAWIDTH => "11", + + ------------------------------- Data Ports ----------------------------- + + RXDATA(63 downto 16) => open, + RXDATA(15 downto 0) => phyRxData(63 downto 48), + TXDATA(63 downto 16) => (others=>'0'), + TXDATA(15 downto 0) => phyTxData(63 downto 48), + + ------------------------------- User Clocks ----------------------------- + + RXMCLK => open, + RXPCSHCLKOUT => open, + RXRECCLK1 => open, + RXRECCLK2 => open, + RXUSRCLK => '0', + RXUSRCLK2 => pgpClk, + TXOUTCLK1 => open, + TXOUTCLK2 => open, + TXPCSHCLKOUT => open, + TXUSRCLK => '0', + TXUSRCLK2 => pgpClk, + + ---------------------------- Reference Clocks -------------------------- + + GREFCLK => '0', + REFCLK1 => mgtRefClk1, + REFCLK2 => mgtRefClk2, + + ---------------------------- Powerdown and Loopback Ports -------------- + + LOOPBACK(1) => mgtLoopback, + LOOPBACK(0) => mgtLoopback, + POWERDOWN => '0', + + ------------------- Dynamic Reconfiguration Port (DRP) ------------------ + + DADDR => (others=>'0'), + DCLK => '0', + DEN => '0', + DI => (others=>'0'), + DO => open, + DRDY => open, + DWE => '0', + + --------------------- MGT Tile Communication Ports ------------------ + + COMBUSIN => mgtCombusOutC, + COMBUSOUT => mgtCombusInC + ); + + +end Pgp2Mgt64; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2MgtClk.vhd b/rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2MgtClk.vhd new file mode 100755 index 00000000..2a81c736 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2MgtClk.vhd @@ -0,0 +1,207 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, Clock Generation Block +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2MgtClk.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 05/28/2009 +------------------------------------------------------------------------------- +-- Description: +-- PGP Clock Module. Contains DCM to support PGP. +-- Used to generate global buffer clock for PGP core at the same frequency +-- as the input reference clock. Will also generate an optional 125Mhz +-- global clock and reset for external logic use. +-- RefClk should be generated from external GT11CLK Module. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 05/28/2009: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; +use work.Pgp2MgtPackage.all; +library UNISIM; +use UNISIM.VCOMPONENTS.ALL; + +entity Pgp2MgtClk is + generic ( + UserFxDiv : integer := 5; -- DCM FX Output Divide + UserFxMult : integer := 4 -- DCM FX Output Divide, 4/5 * 156.25 = 125Mhz + ); + port ( + + -- Reference Clock Input + refClkIn : in std_logic; + + -- Power On Reset Input + ponResetL : in std_logic; + + -- Locally Generated Reset + locReset : in std_logic; + + -- Global Clock & Reset For PGP Logic, 156.25Mhz + pgpClk : out std_logic; + pgpReset : out std_logic; + + -- Global Clock & Reset For User Logic, 125Mhz + userClk : out std_logic; + userReset : out std_logic; + + -- Inputs clocks for reset generation connect + -- to pgpClk and userClk + pgpClkIn : in std_logic; + userClkIn : in std_logic + ); + +end Pgp2MgtClk; + + +-- Define architecture +architecture Pgp2MgtClk of Pgp2MgtClk is + + -- Local Signals + signal ponReset : std_logic; + signal tmpPgpClk : std_logic; + signal intPgpClk : std_logic; + signal intPgpRst : std_logic; + signal tmpLocClk : std_logic; + signal intUsrClk : std_logic; + signal intUsrRst : std_logic; + signal syncPgpRstIn : std_logic_vector(2 downto 0); + signal pgpRstCnt : std_logic_vector(3 downto 0); + signal syncLocRstIn : std_logic_vector(2 downto 0); + signal locRstCnt : std_logic_vector(3 downto 0); + signal dcmLock : std_logic; + signal resetIn : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Output Generated Clock And Reset Signals + pgpClk <= intPgpClk; + pgpReset <= intPgpRst; + userClk <= intUsrClk; + userReset <= intUsrRst; + + -- Invert power on reset + ponReset <= not ponResetL; + + + -- DCM For PGP Clock & User Clock + U_PgpDcm: DCM + generic map ( + DFS_FREQUENCY_MODE => "LOW", DLL_FREQUENCY_MODE => "HIGH", + DUTY_CYCLE_CORRECTION => FALSE, CLKIN_DIVIDE_BY_2 => FALSE, + CLK_FEEDBACK => "1X", CLKOUT_PHASE_SHIFT => "NONE", + STARTUP_WAIT => false, PHASE_SHIFT => 0, + CLKFX_MULTIPLY => UserFxMult, CLKFX_DIVIDE => UserFxDiv, + CLKDV_DIVIDE => 4.0, CLKIN_PERIOD => 6.4, + DSS_MODE => "NONE", FACTORY_JF => X"C080", + DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS" + ) + port map ( + CLKIN => refClkIn, CLKFB => intPgpClk, + CLK0 => tmpPgpClk, CLK90 => open, + CLK180 => open, CLK270 => open, + CLK2X => open, CLK2X180 => open, + CLKDV => tmpLocClk, CLKFX => open, + CLKFX180 => open, LOCKED => dcmLock, + PSDONE => open, STATUS => open, + DSSEN => '0', PSCLK => '0', + PSEN => '0', PSINCDEC => '0', + RST => ponReset + ); + + + -- Global Buffer For PGP Clock + U_PgpClkBuff: BUFGMUX port map ( + O => intPgpClk, + I0 => tmpPgpClk, + I1 => '0', + S => '0' + ); + + + -- Global Buffer For 125Mhz Clock + U_LocClkBuff: BUFGMUX port map ( + O => intUsrClk, + I0 => tmpLocClk, + I1 => '0', + S => '0' + ); + + + -- Generate reset input + resetIn <= (not dcmLock) or ponReset or locReset; + + -- PGP Clock Synced Reset + process ( pgpClkIn, resetIn ) begin + if resetIn = '1' then + syncPgpRstIn <= (others=>'0') after tpd; + pgpRstCnt <= (others=>'0') after tpd; + intPgpRst <= '1' after tpd; + elsif rising_edge(pgpClkIn) then + + -- Sync local reset, lock and power on reset to local clock + -- Negative asserted signal + syncPgpRstIn(0) <= '1' after tpd; + syncPgpRstIn(1) <= syncPgpRstIn(0) after tpd; + syncPgpRstIn(2) <= syncPgpRstIn(1) after tpd; + + -- Reset counter on reset + if syncPgpRstIn(2) = '0' then + pgpRstCnt <= (others=>'0') after tpd; + intPgpRst <= '1' after tpd; + + -- Count Up To Max Value + elsif pgpRstCnt = "1111" then + intPgpRst <= '0' after tpd; + + -- Increment counter + else + intPgpRst <= '1' after tpd; + pgpRstCnt <= pgpRstCnt + 1 after tpd; + end if; + end if; + end process; + + -- Local User Clock Synced Reset + process ( userClkIn, resetIn ) begin + if resetIn = '1' then + syncLocRstIn <= (others=>'0') after tpd; + locRstCnt <= (others=>'0') after tpd; + intUsrRst <= '1' after tpd; + elsif rising_edge(userClkIn) then + + -- Sync local reset, lock and power on reset to local clock + -- Negative asserted signal + syncLocRstIn(0) <= '1' after tpd; + syncLocRstIn(1) <= syncLocRstIn(0) after tpd; + syncLocRstIn(2) <= syncLocRstIn(1) after tpd; + + -- Reset counter on reset + if syncLocRstIn(2) = '0' then + locRstCnt <= (others=>'0') after tpd; + intUsrRst <= '1' after tpd; + + -- Count Up To Max Value + elsif locRstCnt = "1111" then + intUsrRst <= '0' after tpd; + + -- Increment counter + else + intUsrRst <= '1' after tpd; + locRstCnt <= locRstCnt + 1 after tpd; + end if; + end if; + end process; + +end Pgp2MgtClk; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2MgtPackage.vhd b/rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2MgtPackage.vhd new file mode 100755 index 00000000..eb5584d2 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2MgtPackage.vhd @@ -0,0 +1,333 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, MGT Package +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2MgtPackage.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 11/23/2009 +------------------------------------------------------------------------------- +-- Description: +-- MGT Components package. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 11/23/2009: created. +-- 01/13/2010: Added received init line to help linking. +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; + +package Pgp2MgtPackage is + + -- 16-bit wrapper + component Pgp2Mgt16 + generic ( + EnShortCells : integer := 1; -- Enable short non-EOF cells + VcInterleave : integer := 1; -- Interleave Frames + MgtMode : string := "A"; -- Default Location + RefClkSel : string := "REFCLK1" -- Reference Clock To Use "REFCLK1" or "REFCLK2" + ); + port ( + pgpClk : in std_logic; -- 156.25Mhz master clock + pgpReset : in std_logic; -- Synchronous reset input + pgpFlush : in std_logic; -- Frame state reset + pllTxRst : in std_logic; -- Reset transmit PLL logic + pllRxRst : in std_logic; -- Reset receive PLL logic + pllRxReady : out std_logic; -- MGT Receive logic is ready + pllTxReady : out std_logic; -- MGT Transmit logic is ready + pgpRemData : out std_logic_vector(7 downto 0); -- Far end side User Data + pgpLocData : in std_logic_vector(7 downto 0); -- Far end side User Data + pgpTxOpCodeEn : in std_logic; -- Opcode receive enable + pgpTxOpCode : in std_logic_vector(7 downto 0); -- Opcode receive value + pgpRxOpCodeEn : out std_logic; -- Opcode receive enable + pgpRxOpCode : out std_logic_vector(7 downto 0); -- Opcode receive value + pgpLocLinkReady : out std_logic; -- Local Link is ready + pgpRemLinkReady : out std_logic; -- Far end side has link + pgpRxCellError : out std_logic; -- A cell error has occured + pgpRxLinkDown : out std_logic; -- A link down event has occured + pgpRxLinkError : out std_logic; -- A link error has occured + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc0FrameTxReady : out std_logic; -- PGP is ready + vc0FrameTxSOF : in std_logic; -- User frame data start of frame + vc0FrameTxEOF : in std_logic; -- User frame data end of frame + vc0FrameTxEOFE : in std_logic; -- User frame data error + vc0FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc0LocBuffAFull : in std_logic; -- Remote buffer almost full + vc0LocBuffFull : in std_logic; -- Remote buffer full + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxReady : out std_logic; -- PGP is ready + vc1FrameTxSOF : in std_logic; -- User frame data start of frame + vc1FrameTxEOF : in std_logic; -- User frame data end of frame + vc1FrameTxEOFE : in std_logic; -- User frame data error + vc1FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc1LocBuffAFull : in std_logic; -- Remote buffer almost full + vc1LocBuffFull : in std_logic; -- Remote buffer full + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxReady : out std_logic; -- PGP is ready + vc2FrameTxSOF : in std_logic; -- User frame data start of frame + vc2FrameTxEOF : in std_logic; -- User frame data end of frame + vc2FrameTxEOFE : in std_logic; -- User frame data error + vc2FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc2LocBuffAFull : in std_logic; -- Remote buffer almost full + vc2LocBuffFull : in std_logic; -- Remote buffer full + vc3FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxReady : out std_logic; -- PGP is ready + vc3FrameTxSOF : in std_logic; -- User frame data start of frame + vc3FrameTxEOF : in std_logic; -- User frame data end of frame + vc3FrameTxEOFE : in std_logic; -- User frame data error + vc3FrameTxData : in std_logic_vector(15 downto 0); -- User frame data + vc3LocBuffAFull : in std_logic; -- Remote buffer almost full + vc3LocBuffFull : in std_logic; -- Remote buffer full + vcFrameRxSOF : out std_logic; -- PGP frame data start of frame + vcFrameRxEOF : out std_logic; -- PGP frame data end of frame + vcFrameRxEOFE : out std_logic; -- PGP frame data error + vcFrameRxData : out std_logic_vector(15 downto 0); -- PGP frame data + vc0FrameRxValid : out std_logic; -- PGP frame data is valid + vc0RemBuffAFull : out std_logic; -- Remote buffer almost full + vc0RemBuffFull : out std_logic; -- Remote buffer full + vc1FrameRxValid : out std_logic; -- PGP frame data is valid + vc1RemBuffAFull : out std_logic; -- Remote buffer almost full + vc1RemBuffFull : out std_logic; -- Remote buffer full + vc2FrameRxValid : out std_logic; -- PGP frame data is valid + vc2RemBuffAFull : out std_logic; -- Remote buffer almost full + vc2RemBuffFull : out std_logic; -- Remote buffer full + vc3FrameRxValid : out std_logic; -- PGP frame data is valid + vc3RemBuffAFull : out std_logic; -- Remote buffer almost full + vc3RemBuffFull : out std_logic; -- Remote buffer full + mgtLoopback : in std_logic; -- MGT Serial Loopback Control + mgtRefClk1 : in std_logic; -- MGT Reference Clock In 1 + mgtRefClk2 : in std_logic; -- MGT Reference Clock In 2 + mgtRxRecClk : out std_logic; -- MGT Rx Recovered Clock + mgtRxN : in std_logic; -- MGT Serial Receive Negative + mgtRxP : in std_logic; -- MGT Serial Receive Positive + mgtTxN : out std_logic; -- MGT Serial Transmit Negative + mgtTxP : out std_logic; -- MGT Serial Transmit Positive + mgtCombusIn : in std_logic_vector(15 downto 0); + mgtCombusOut : out std_logic_vector(15 downto 0); + debug : out std_logic_vector(63 downto 0) + ); + end component; + + -- 32-bit wrapper + component Pgp2Mgt32 + generic ( + EnShortCells : integer := 1; -- Enable short non-EOF cells + VcInterleave : integer := 1; -- Interleave Frames + RefClkSel : string := "REFCLK1" -- Reference Clock To Use "REFCLK1" or "REFCLK2" + ); + port ( + pgpClk : in std_logic; -- 156.25Mhz master clock + pgpReset : in std_logic; -- Synchronous reset input + pgpFlush : in std_logic; -- Frame state reset + pllTxRst : in std_logic; -- Reset transmit PLL logic + pllRxRst : in std_logic; -- Reset receive PLL logic + pllRxReady : out std_logic; -- MGT Receive logic is ready + pllTxReady : out std_logic; -- MGT Transmit logic is ready + pgpRemData : out std_logic_vector(7 downto 0); -- Far end side User Data + pgpLocData : in std_logic_vector(7 downto 0); -- Far end side User Data + pgpTxOpCodeEn : in std_logic; -- Opcode receive enable + pgpTxOpCode : in std_logic_vector(7 downto 0); -- Opcode receive value + pgpRxOpCodeEn : out std_logic; -- Opcode receive enable + pgpRxOpCode : out std_logic_vector(7 downto 0); -- Opcode receive value + pgpLocLinkReady : out std_logic; -- Local Link is ready + pgpRemLinkReady : out std_logic; -- Far end side has link + pgpRxCellError : out std_logic; -- A cell error has occured + pgpRxLinkDown : out std_logic; -- A link down event has occured + pgpRxLinkError : out std_logic; -- A link error has occured + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc0FrameTxReady : out std_logic; -- PGP is ready + vc0FrameTxSOF : in std_logic; -- User frame data start of frame + vc0FrameTxEOF : in std_logic; -- User frame data end of frame + vc0FrameTxEOFE : in std_logic; -- User frame data error + vc0FrameTxData : in std_logic_vector(31 downto 0); -- User frame data + vc0LocBuffAFull : in std_logic; -- Remote buffer almost full + vc0LocBuffFull : in std_logic; -- Remote buffer full + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxReady : out std_logic; -- PGP is ready + vc1FrameTxSOF : in std_logic; -- User frame data start of frame + vc1FrameTxEOF : in std_logic; -- User frame data end of frame + vc1FrameTxEOFE : in std_logic; -- User frame data error + vc1FrameTxData : in std_logic_vector(31 downto 0); -- User frame data + vc1LocBuffAFull : in std_logic; -- Remote buffer almost full + vc1LocBuffFull : in std_logic; -- Remote buffer full + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxReady : out std_logic; -- PGP is ready + vc2FrameTxSOF : in std_logic; -- User frame data start of frame + vc2FrameTxEOF : in std_logic; -- User frame data end of frame + vc2FrameTxEOFE : in std_logic; -- User frame data error + vc2FrameTxData : in std_logic_vector(31 downto 0); -- User frame data + vc2LocBuffAFull : in std_logic; -- Remote buffer almost full + vc2LocBuffFull : in std_logic; -- Remote buffer full + vc3FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxReady : out std_logic; -- PGP is ready + vc3FrameTxSOF : in std_logic; -- User frame data start of frame + vc3FrameTxEOF : in std_logic; -- User frame data end of frame + vc3FrameTxEOFE : in std_logic; -- User frame data error + vc3FrameTxData : in std_logic_vector(31 downto 0); -- User frame data + vc3LocBuffAFull : in std_logic; -- Remote buffer almost full + vc3LocBuffFull : in std_logic; -- Remote buffer full + vcFrameRxSOF : out std_logic; -- PGP frame data start of frame + vcFrameRxEOF : out std_logic; -- PGP frame data end of frame + vcFrameRxEOFE : out std_logic; -- PGP frame data error + vcFrameRxData : out std_logic_vector(31 downto 0); -- PGP frame data + vc0FrameRxValid : out std_logic; -- PGP frame data is valid + vc0RemBuffAFull : out std_logic; -- Remote buffer almost full + vc0RemBuffFull : out std_logic; -- Remote buffer full + vc1FrameRxValid : out std_logic; -- PGP frame data is valid + vc1RemBuffAFull : out std_logic; -- Remote buffer almost full + vc1RemBuffFull : out std_logic; -- Remote buffer full + vc2FrameRxValid : out std_logic; -- PGP frame data is valid + vc2RemBuffAFull : out std_logic; -- Remote buffer almost full + vc2RemBuffFull : out std_logic; -- Remote buffer full + vc3FrameRxValid : out std_logic; -- PGP frame data is valid + vc3RemBuffAFull : out std_logic; -- Remote buffer almost full + vc3RemBuffFull : out std_logic; -- Remote buffer full + mgtLoopback : in std_logic; -- MGT Serial Loopback Control + mgtRefClk1 : in std_logic; -- MGT Reference Clock In 1 + mgtRefClk2 : in std_logic; -- MGT Reference Clock In 2 + mgtRxRecClk : out std_logic; -- MGT Rx Recovered Clock + mgtRxN : in std_logic_vector(1 downto 0); -- MGT Serial Receive Negative + mgtRxP : in std_logic_vector(1 downto 0); -- MGT Serial Receive Positive + mgtTxN : out std_logic_vector(1 downto 0); -- MGT Serial Transmit Negative + mgtTxP : out std_logic_vector(1 downto 0); -- MGT Serial Transmit Positive + debug : out std_logic_vector(63 downto 0) + ); + end component; + + -- 64-bit wrapper + component Pgp2Mgt64 + generic ( + EnShortCells : integer := 1; -- Enable short non-EOF cells + VcInterleave : integer := 1; -- Interleave Frames + RefClkSel : string := "REFCLK1" -- Reference Clock To Use "REFCLK1" or "REFCLK2" + ); + port ( + pgpClk : in std_logic; -- 156.25Mhz master clock + pgpReset : in std_logic; -- Synchronous reset input + pgpFlush : in std_logic; -- Frame state reset + pllTxRst : in std_logic; -- Reset transmit PLL logic + pllRxRst : in std_logic; -- Reset receive PLL logic + pllRxReady : out std_logic; -- MGT Receive logic is ready + pllTxReady : out std_logic; -- MGT Transmit logic is ready + pgpRemData : out std_logic_vector(7 downto 0); -- Far end side User Data + pgpLocData : in std_logic_vector(7 downto 0); -- Far end side User Data + pgpTxOpCodeEn : in std_logic; -- Opcode receive enable + pgpTxOpCode : in std_logic_vector(7 downto 0); -- Opcode receive value + pgpRxOpCodeEn : out std_logic; -- Opcode receive enable + pgpRxOpCode : out std_logic_vector(7 downto 0); -- Opcode receive value + pgpLocLinkReady : out std_logic; -- Local Link is ready + pgpRemLinkReady : out std_logic; -- Far end side has link + pgpRxCellError : out std_logic; -- A cell error has occured + pgpRxLinkDown : out std_logic; -- A link down event has occured + pgpRxLinkError : out std_logic; -- A link error has occured + vc0FrameTxValid : in std_logic; -- User frame data is valid + vc0FrameTxReady : out std_logic; -- PGP is ready + vc0FrameTxSOF : in std_logic; -- User frame data start of frame + vc0FrameTxEOF : in std_logic; -- User frame data end of frame + vc0FrameTxEOFE : in std_logic; -- User frame data error + vc0FrameTxData : in std_logic_vector(63 downto 0); -- User frame data + vc0LocBuffAFull : in std_logic; -- Remote buffer almost full + vc0LocBuffFull : in std_logic; -- Remote buffer full + vc1FrameTxValid : in std_logic; -- User frame data is valid + vc1FrameTxReady : out std_logic; -- PGP is ready + vc1FrameTxSOF : in std_logic; -- User frame data start of frame + vc1FrameTxEOF : in std_logic; -- User frame data end of frame + vc1FrameTxEOFE : in std_logic; -- User frame data error + vc1FrameTxData : in std_logic_vector(63 downto 0); -- User frame data + vc1LocBuffAFull : in std_logic; -- Remote buffer almost full + vc1LocBuffFull : in std_logic; -- Remote buffer full + vc2FrameTxValid : in std_logic; -- User frame data is valid + vc2FrameTxReady : out std_logic; -- PGP is ready + vc2FrameTxSOF : in std_logic; -- User frame data start of frame + vc2FrameTxEOF : in std_logic; -- User frame data end of frame + vc2FrameTxEOFE : in std_logic; -- User frame data error + vc2FrameTxData : in std_logic_vector(63 downto 0); -- User frame data + vc2LocBuffAFull : in std_logic; -- Remote buffer almost full + vc2LocBuffFull : in std_logic; -- Remote buffer full + vc3FrameTxValid : in std_logic; -- User frame data is valid + vc3FrameTxReady : out std_logic; -- PGP is ready + vc3FrameTxSOF : in std_logic; -- User frame data start of frame + vc3FrameTxEOF : in std_logic; -- User frame data end of frame + vc3FrameTxEOFE : in std_logic; -- User frame data error + vc3FrameTxData : in std_logic_vector(63 downto 0); -- User frame data + vc3LocBuffAFull : in std_logic; -- Remote buffer almost full + vc3LocBuffFull : in std_logic; -- Remote buffer full + vcFrameRxSOF : out std_logic; -- PGP frame data start of frame + vcFrameRxEOF : out std_logic; -- PGP frame data end of frame + vcFrameRxEOFE : out std_logic; -- PGP frame data error + vcFrameRxData : out std_logic_vector(63 downto 0); -- PGP frame data + vc0FrameRxValid : out std_logic; -- PGP frame data is valid + vc0RemBuffAFull : out std_logic; -- Remote buffer almost full + vc0RemBuffFull : out std_logic; -- Remote buffer full + vc1FrameRxValid : out std_logic; -- PGP frame data is valid + vc1RemBuffAFull : out std_logic; -- Remote buffer almost full + vc1RemBuffFull : out std_logic; -- Remote buffer full + vc2FrameRxValid : out std_logic; -- PGP frame data is valid + vc2RemBuffAFull : out std_logic; -- Remote buffer almost full + vc2RemBuffFull : out std_logic; -- Remote buffer full + vc3FrameRxValid : out std_logic; -- PGP frame data is valid + vc3RemBuffAFull : out std_logic; -- Remote buffer almost full + vc3RemBuffFull : out std_logic; -- Remote buffer full + mgtLoopback : in std_logic; -- MGT Serial Loopback Control + mgtRefClk1 : in std_logic; -- MGT Reference Clock In 1 + mgtRefClk2 : in std_logic; -- MGT Reference Clock In 2 + mgtRxRecClk : out std_logic; -- MGT Rx Recovered Clock + mgtRxN : in std_logic_vector(3 downto 0); -- MGT Serial Receive Negative + mgtRxP : in std_logic_vector(3 downto 0); -- MGT Serial Receive Positive + mgtTxN : out std_logic_vector(3 downto 0); -- MGT Serial Transmit Negative + mgtTxP : out std_logic_vector(3 downto 0); -- MGT Serial Transmit Positive + debug : out std_logic_vector(63 downto 0) + ); + end component; + + -- PGP Clock Generator + component Pgp2MgtClk + generic ( + UserFxDiv : integer := 5; -- DCM FX Output Divide + UserFxMult : integer := 4 -- DCM FX Output Divide, 4/5 * 156.25 = 125Mhz + ); + port ( + refClkIn : in std_logic; + ponResetL : in std_logic; + locReset : in std_logic; + pgpClk : out std_logic; + pgpReset : out std_logic; + userClk : out std_logic; + userReset : out std_logic; + pgpClkIn : in std_logic; + userClkIn : in std_logic + ); + end component; + + -- RX Reset Control + component Pgp2MgtRxRst + port ( + mgtRxClk : in std_logic; + mgtRxRst : in std_logic; + mgtRxReady : out std_logic; + mgtRxInit : in std_logic; + mgtRxLock : in std_logic; + mgtRxPmaReset : out std_logic; + mgtRxReset : out std_logic; + mgtRxBuffError : in std_logic + ); + end component; + + -- TX Reset Control + component Pgp2MgtTxRst + port ( + mgtTxClk : in std_logic; + mgtTxRst : in std_logic; + mgtTxReady : out std_logic; + mgtTxLock : in std_logic; + mgtTxPmaReset : out std_logic; + mgtTxReset : out std_logic; + mgtTxBuffError : in std_logic + ); + end component; + +end Pgp2MgtPackage; + + diff --git a/rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2MgtRxRst.vhd b/rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2MgtRxRst.vhd new file mode 100755 index 00000000..1cf0308f --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2MgtRxRst.vhd @@ -0,0 +1,291 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, MGT RX Reset Control +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2MgtRxRst.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 05/27/2009 +------------------------------------------------------------------------------- +-- Description: +-- This module contains the logic to control the reset of the RX MGT. +------------------------------------------------------------------------------- +-- Copyright (c) 2009 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 05/27/2009: created. +-- 01/13/2010: Added received init line to help linking. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; +use work.Pgp2MgtPackage.all; +library UNISIM; +use UNISIM.VCOMPONENTS.ALL; + +entity Pgp2MgtRxRst is + port ( + + -- Clock and reset, must not be derived from MGT receive PLL + mgtRxClk : in std_logic; + mgtRxRst : in std_logic; + + -- RX Side is ready + mgtRxReady : out std_logic; + mgtRxInit : in std_logic; + + -- Lock status + mgtRxLock : in std_logic; + + -- PCS & PMA Reset + mgtRxPmaReset : out std_logic; + mgtRxReset : out std_logic; + + -- Buffer error + mgtRxBuffError : in std_logic + ); + +end Pgp2MgtRxRst; + + +-- Define architecture +architecture Pgp2MgtRxRst of Pgp2MgtRxRst is + + -- Local Signals + signal rxPcsResetCnt : std_logic_vector(3 downto 0); + signal rxPcsResetCntRst : std_logic; + signal rxPcsResetCntEn : std_logic; + signal rxStateCnt : std_logic_vector(13 downto 0); + signal rxStateCntRst : std_logic; + signal intRxPmaReset : std_logic; + signal intRxReset : std_logic; + signal rxClockReady : std_logic; + + -- RX Reset State Machine + constant RX_SYSTEM_RESET : std_logic_vector(2 downto 0) := "000"; + constant RX_PMA_RESET : std_logic_vector(2 downto 0) := "001"; + constant RX_WAIT_LOCK : std_logic_vector(2 downto 0) := "010"; + constant RX_PCS_RESET : std_logic_vector(2 downto 0) := "011"; + constant RX_WAIT_PCS : std_logic_vector(2 downto 0) := "100"; + constant RX_ALMOST_READY : std_logic_vector(2 downto 0) := "101"; + constant RX_READY : std_logic_vector(2 downto 0) := "110"; + signal curRxState : std_logic_vector(2 downto 0); + signal nxtRxState : std_logic_vector(2 downto 0); + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- State Machine Synchronous Logic + process ( mgtRxClk, mgtRxRst ) begin + if mgtRxRst = '1' then + curRxState <= RX_SYSTEM_RESET after tpd; + rxPcsResetCnt <= (others=>'0') after tpd; + rxStateCnt <= (others=>'0') after tpd; + mgtRxPmaReset <= '1' after tpd; + mgtRxReset <= '0' after tpd; + mgtRxReady <= '0' after tpd; + elsif rising_edge(mgtRxClk) then + + -- Pass on reset signals + mgtRxPmaReset <= intRxPmaReset after tpd; + mgtRxReset <= intRxReset after tpd; + + -- Update state + if mgtRxInit = '1' then + curRxState <= RX_SYSTEM_RESET after tpd; + else + curRxState <= nxtRxState after tpd; + end if; + + -- Rx State Counter + if rxStateCntRst = '1' then + rxStateCnt <= (others=>'0') after tpd; + else + rxStateCnt <= rxStateCnt + 1 after tpd; + end if; + + -- RX Loop Counter + if rxPcsResetCntRst = '1' then + rxPcsResetCnt <= (others=>'0') after tpd; + elsif rxPcsResetCntEn = '1' then + rxPcsResetCnt <= rxPcsResetCnt + 1 after tpd; + end if; + + -- Ready flag + mgtRxReady <= rxClockReady after tpd; + + end if; + end process; + + + -- Async RX State Logic + process ( curRxState, rxStateCnt, mgtRxLock, mgtRxBuffError, rxPcsResetCnt ) begin + case curRxState is + + -- System Reset State + when RX_SYSTEM_RESET => + rxPcsResetCntRst <= '1'; + rxPcsResetCntEn <= '0'; + rxStateCntRst <= '1'; + intRxPmaReset <= '1'; + intRxReset <= '0'; + rxClockReady <= '0'; + nxtRxState <= RX_PMA_RESET; + + -- PMA Reset State + when RX_PMA_RESET => + rxPcsResetCntRst <= '0'; + rxPcsResetCntEn <= '0'; + intRxPmaReset <= '1'; + intRxReset <= '0'; + rxClockReady <= '0'; + + -- Wait for three clocks + if rxStateCnt = 3 then + nxtRxState <= RX_WAIT_LOCK; + rxStateCntRst <= '1'; + else + nxtRxState <= curRxState; + rxStateCntRst <= '0'; + end if; + + -- Wait for RX Lock + when RX_WAIT_LOCK => + rxPcsResetCntRst <= '0'; + rxPcsResetCntEn <= '0'; + intRxPmaReset <= '0'; + intRxReset <= '0'; + rxStateCntRst <= not mgtRxLock; + rxClockReady <= '0'; + + -- Wait for rx to be locked for 16K clock cycles + if rxStateCnt = "11111111111111" then + nxtRxState <= RX_PCS_RESET; + else + nxtRxState <= curRxState; + end if; + + -- Assert PCS Reset + when RX_PCS_RESET => + rxPcsResetCntRst <= '0'; + rxPcsResetCntEn <= '0'; + intRxPmaReset <= '0'; + intRxReset <= '1'; + rxClockReady <= '0'; + + -- Loss of Lock + if mgtRxLock = '0' then + nxtRxState <= RX_WAIT_LOCK; + rxStateCntRst <= '1'; + + -- Wait for three clocks + elsif rxStateCnt = 3 then + nxtRxState <= RX_WAIT_PCS; + rxStateCntRst <= '1'; + else + nxtRxState <= curRxState; + rxStateCntRst <= '0'; + end if; + + -- Wait 5 clocks after PCS reset + when RX_WAIT_PCS => + rxPcsResetCntRst <= '0'; + rxPcsResetCntEn <= '0'; + intRxPmaReset <= '0'; + intRxReset <= '0'; + rxClockReady <= '0'; + + -- Loss of Lock + if mgtRxLock = '0' then + nxtRxState <= RX_WAIT_LOCK; + rxStateCntRst <= '1'; + + -- Wait for five clocks + elsif rxStateCnt = 5 then + nxtRxState <= RX_ALMOST_READY; + rxStateCntRst <= '1'; + else + nxtRxState <= curRxState; + rxStateCntRst <= '0'; + end if; + + -- Almost Ready State + when RX_ALMOST_READY => + intRxPmaReset <= '0'; + intRxReset <= '0'; + rxClockReady <= '0'; + + -- Loss of Lock + if mgtRxLock = '0' then + nxtRxState <= RX_WAIT_LOCK; + rxStateCntRst <= '1'; + rxPcsResetCntEn <= '0'; + rxPcsResetCntRst <= '0'; + + -- RX Buffer Error + elsif mgtRxBuffError = '1' then + rxStateCntRst <= '1'; + rxPcsResetCntEn <= '1'; + + -- 16 Cycles have occured, reset PLL + if rxPcsResetCnt = 15 then + nxtRxState <= RX_PMA_RESET; + rxPcsResetCntRst <= '1'; + + -- Go back to PCS Reset + else + nxtRxState <= RX_PCS_RESET; + rxPcsResetCntRst <= '0'; + end if; + + -- Wait for 64 clocks + elsif rxStateCnt = 63 then + nxtRxState <= RX_READY; + rxStateCntRst <= '1'; + rxPcsResetCntEn <= '0'; + rxPcsResetCntRst <= '0'; + else + nxtRxState <= curRxState; + rxStateCntRst <= '0'; + rxPcsResetCntEn <= '0'; + rxPcsResetCntRst <= '0'; + end if; + + -- Ready State + when RX_READY => + rxPcsResetCntRst <= '1'; + rxPcsResetCntEn <= '0'; + intRxPmaReset <= '0'; + intRxReset <= '0'; + rxStateCntRst <= '1'; + rxClockReady <= '1'; + + -- Loss of Lock + if mgtRxLock = '0' then + nxtRxState <= RX_WAIT_LOCK; + + -- Buffer error has occured + elsif mgtRxBuffError = '1' then + nxtRxState <= RX_PCS_RESET; + else + nxtRxState <= curRxState; + end if; + + -- Just in case + when others => + rxPcsResetCntRst <= '0'; + rxPcsResetCntEn <= '0'; + intRxPmaReset <= '0'; + intRxReset <= '0'; + rxStateCntRst <= '0'; + rxClockReady <= '0'; + nxtRxState <= RX_SYSTEM_RESET; + end case; + end process; + +end Pgp2MgtRxRst; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2MgtTxRst.vhd b/rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2MgtTxRst.vhd new file mode 100755 index 00000000..8c855ff9 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/mgt/Pgp2MgtTxRst.vhd @@ -0,0 +1,283 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, MGT TX Reset Control +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2MgtTxRst.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 05/27/2009 +------------------------------------------------------------------------------- +-- Description: +-- This module contains the logic to control the reset of the TX MGT. +------------------------------------------------------------------------------- +-- Copyright (c) 2009 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 05/27/2009: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; +use work.Pgp2MgtPackage.all; +library UNISIM; +use UNISIM.VCOMPONENTS.ALL; + +entity Pgp2MgtTxRst is port ( + + -- Clock and reset, must not be derived from MGT transmit PLL + mgtTxClk : in std_logic; + mgtTxRst : in std_logic; + + -- TX Side is ready + mgtTxReady : out std_logic; + + -- Lock status + mgtTxLock : in std_logic; + + -- PCS & PMA Reset + mgtTxPmaReset : out std_logic; + mgtTxReset : out std_logic; + + -- Buffer error + mgtTxBuffError : in std_logic + ); + +end Pgp2MgtTxRst; + + +-- Define architecture +architecture Pgp2MgtTxRst of Pgp2MgtTxRst is + + -- Local Signals + signal txPcsResetCnt : std_logic_vector(3 downto 0); + signal txPcsResetCntRst : std_logic; + signal txPcsResetCntEn : std_logic; + signal txStateCnt : std_logic_vector(5 downto 0); + signal txStateCntRst : std_logic; + signal intTxPmaReset : std_logic; + signal intTxReset : std_logic; + signal txClockReady : std_logic; + + -- TX Reset State Machine + constant TX_SYSTEM_RESET : std_logic_vector(2 downto 0) := "000"; + constant TX_PMA_RESET : std_logic_vector(2 downto 0) := "001"; + constant TX_WAIT_LOCK : std_logic_vector(2 downto 0) := "010"; + constant TX_PCS_RESET : std_logic_vector(2 downto 0) := "011"; + constant TX_WAIT_PCS : std_logic_vector(2 downto 0) := "100"; + constant TX_ALMOST_READY : std_logic_vector(2 downto 0) := "101"; + constant TX_READY : std_logic_vector(2 downto 0) := "110"; + signal curTxState : std_logic_vector(2 downto 0); + signal nxtTxState : std_logic_vector(2 downto 0); + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- State Machine Synchronous Logic + process ( mgtTxClk, mgtTxRst ) begin + if mgtTxRst = '1' then + curTxState <= TX_SYSTEM_RESET after tpd; + txPcsResetCnt <= (others=>'0') after tpd; + txStateCnt <= (others=>'0') after tpd; + mgtTxPmaReset <= '1' after tpd; + mgtTxReset <= '0' after tpd; + mgtTxReady <= '0' after tpd; + elsif rising_edge(mgtTxClk) then + + -- Pass on reset signals + mgtTxPmaReset <= intTxPmaReset after tpd; + mgtTxReset <= intTxReset after tpd; + + -- Update state + curTxState <= nxtTxState after tpd; + + -- Tx State Counter + if txStateCntRst = '1' then + txStateCnt <= (others=>'0') after tpd; + else + txStateCnt <= txStateCnt + 1 after tpd; + end if; + + -- TX Loop Counter + if txPcsResetCntRst = '1' then + txPcsResetCnt <= (others=>'0') after tpd; + elsif txPcsResetCntEn = '1' then + txPcsResetCnt <= txPcsResetCnt + 1 after tpd; + end if; + + -- Ready flag + mgtTxReady <= txClockReady after tpd; + end if; + end process; + + + -- Async TX State Logic + process ( curTxState, txStateCnt, mgtTxLock, mgtTxBuffError, txPcsResetCnt ) begin + case curTxState is + + -- System Reset State + when TX_SYSTEM_RESET => + txPcsResetCntRst <= '1'; + txPcsResetCntEn <= '0'; + txStateCntRst <= '1'; + intTxPmaReset <= '1'; + intTxReset <= '0'; + txClockReady <= '0'; + nxtTxState <= TX_PMA_RESET; + + -- PMA Reset State + when TX_PMA_RESET => + txPcsResetCntRst <= '0'; + txPcsResetCntEn <= '0'; + intTxPmaReset <= '1'; + intTxReset <= '0'; + txClockReady <= '0'; + + -- Wait for three clocks + if txStateCnt = 3 then + nxtTxState <= TX_WAIT_LOCK; + txStateCntRst <= '1'; + else + nxtTxState <= curTxState; + txStateCntRst <= '0'; + end if; + + -- Wait for TX Lock + when TX_WAIT_LOCK => + txPcsResetCntRst <= '0'; + txPcsResetCntEn <= '0'; + intTxPmaReset <= '0'; + intTxReset <= '0'; + txStateCntRst <= '1'; + txClockReady <= '0'; + + -- Wait for three clocks + if mgtTxLock = '1' then + nxtTxState <= TX_PCS_RESET; + else + nxtTxState <= curTxState; + end if; + + -- Assert PCS Reset + when TX_PCS_RESET => + txPcsResetCntRst <= '0'; + txPcsResetCntEn <= '0'; + intTxPmaReset <= '0'; + intTxReset <= '1'; + txClockReady <= '0'; + + -- Loss of Lock + if mgtTxLock = '0' then + nxtTxState <= TX_WAIT_LOCK; + txStateCntRst <= '1'; + + -- Wait for three clocks + elsif txStateCnt = 3 then + nxtTxState <= TX_WAIT_PCS; + txStateCntRst <= '1'; + else + nxtTxState <= curTxState; + txStateCntRst <= '0'; + end if; + + -- Wait 5 clocks after PCS reset + when TX_WAIT_PCS => + txPcsResetCntRst <= '0'; + txPcsResetCntEn <= '0'; + intTxPmaReset <= '0'; + intTxReset <= '0'; + txClockReady <= '0'; + + -- Loss of Lock + if mgtTxLock = '0' then + nxtTxState <= TX_WAIT_LOCK; + txStateCntRst <= '1'; + + -- Wait for three clocks + elsif txStateCnt = 5 then + nxtTxState <= TX_ALMOST_READY; + txStateCntRst <= '1'; + else + nxtTxState <= curTxState; + txStateCntRst <= '0'; + end if; + + -- Almost Ready State + when TX_ALMOST_READY => + intTxPmaReset <= '0'; + intTxReset <= '0'; + txClockReady <= '0'; + + -- Loss of Lock + if mgtTxLock = '0' then + nxtTxState <= TX_WAIT_LOCK; + txStateCntRst <= '1'; + txPcsResetCntEn <= '0'; + txPcsResetCntRst <= '0'; + + -- TX Buffer Error + elsif mgtTxBuffError = '1' then + txStateCntRst <= '1'; + txPcsResetCntEn <= '1'; + + -- 16 Cycles have occured, reset PLL + if txPcsResetCnt = 15 then + nxtTxState <= TX_PMA_RESET; + txPcsResetCntRst <= '1'; + + -- Go back to PCS Reset + else + nxtTxState <= TX_PCS_RESET; + txPcsResetCntRst <= '0'; + end if; + + -- Wait for 64 clocks + elsif txStateCnt = 63 then + nxtTxState <= TX_READY; + txStateCntRst <= '1'; + txPcsResetCntEn <= '0'; + txPcsResetCntRst <= '0'; + else + nxtTxState <= curTxState; + txStateCntRst <= '0'; + txPcsResetCntEn <= '0'; + txPcsResetCntRst <= '0'; + end if; + + -- Ready State + when TX_READY => + txPcsResetCntRst <= '1'; + txPcsResetCntEn <= '0'; + intTxPmaReset <= '0'; + intTxReset <= '0'; + txStateCntRst <= '1'; + txClockReady <= '1'; + + -- Loss of Lock + if mgtTxLock = '0' then + nxtTxState <= TX_WAIT_LOCK; + + -- Buffer error has occured + elsif mgtTxBuffError = '1' then + nxtTxState <= TX_PCS_RESET; + else + nxtTxState <= curTxState; + end if; + + -- Just in case + when others => + txPcsResetCntRst <= '0'; + txPcsResetCntEn <= '0'; + intTxPmaReset <= '0'; + intTxReset <= '0'; + txStateCntRst <= '0'; + txClockReady <= '0'; + nxtTxState <= TX_SYSTEM_RESET; + end case; + end process; + +end Pgp2MgtTxRst; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/mgt/PgpClkGen.vhd b/rce/fw-hsio/modules/pgp2/hdl/mgt/PgpClkGen.vhd new file mode 100644 index 00000000..4af2acf3 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/mgt/PgpClkGen.vhd @@ -0,0 +1,298 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, V2, Clock Generation Block +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2MgtClk.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 05/28/2009 +------------------------------------------------------------------------------- +-- Description: +-- PGP Clock Module. Contains DCM to support PGP. +-- Used to generate global buffer clock for PGP core at the same frequency +-- as the input reference clock. Will also generate an optional 125Mhz +-- global clock and reset for external logic use. +-- RefClk should be generated from external GT11CLK Module. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 05/28/2009: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; +use work.Pgp2MgtPackage.all; +library UNISIM; +use UNISIM.VCOMPONENTS.ALL; + +entity PgpClkGen is + generic ( + RefClkEn1 : string := "ENABLE"; -- ENABLE or DISABLE + RefClkEn2 : string := "DISABLE"; -- ENABLE or DISABLE + DcmClkSrc : string := "RefClk1"; -- RefClk1 or RefClk2 + UserFxDiv : integer := 5; -- DCM FX Output Divide + UserFxMult : integer := 4 -- DCM FX Output Divide, 4/5 * 156.25 = 125Mhz + ); + port ( + + -- Reference Clock Pad Inputs + pgpRefClkInP : in std_logic; + pgpRefClkInN : in std_logic; + + -- Power On Reset Input + ponResetL : in std_logic; + + -- Locally Generated Reset + locReset : in std_logic; + + -- Reference Clock To PGP MGT + -- Use one, See RefClkEn1 & RefClkEn2 Generics + pgpRefClk1 : out std_logic; + pgpRefClk2 : out std_logic; + + -- Global Clock & Reset For PGP Logic, 156.25Mhz + pgpClk : out std_logic; + pgpClk90 : out std_logic; + pgpReset : out std_logic; + + clk320 : out std_logic; + -- Global Clock & Reset For User Logic, 125Mhz + userClk : out std_logic; + userReset : out std_logic; + + -- Inputs clocks for reset generation connect + -- to pgpClk and userClk + pgpClkIn : in std_logic; + userClkIn : in std_logic; + + -- Output unbuffered clocks + pgpClkUnbuf : out std_logic; + pgpClk90Unbuf : out std_logic; + locClkUnbuf : out std_logic + ); + +end PgpClkGen; + + +-- Define architecture +architecture PgpClkGen of PgpClkGen is + + -- Xilinx GTLL Clock Module + component GT11CLK + generic ( + REFCLKSEL : string := "MGTCLK"; + SYNCLK1OUTEN : string := "ENABLE"; + SYNCLK2OUTEN : string := "DISABLE" + ); + port ( + SYNCLK1OUT : out std_ulogic; + SYNCLK2OUT : out std_ulogic; + MGTCLKN : in std_ulogic; + MGTCLKP : in std_ulogic; + REFCLK : in std_ulogic; + RXBCLK : in std_ulogic; + SYNCLK1IN : in std_ulogic; + SYNCLK2IN : in std_ulogic + ); + end component; + + -- Local Signals + signal ponReset : std_logic; + signal intRefClk1 : std_logic; + signal intRefClk2 : std_logic; + signal tmpPgpClk : std_logic; + signal tmpPgpClk90 : std_logic; + signal intPgpClk : std_logic; + signal intPgpClk90 : std_logic; + signal intPgpRst : std_logic; + signal tmpLocClk : std_logic; + signal tmp320Clk : std_logic; + signal int320Clk : std_logic; + signal intUsrClk : std_logic; + signal intUsrRst : std_logic; + signal syncPgpRstIn : std_logic_vector(2 downto 0); + signal pgpRstCnt : std_logic_vector(3 downto 0); + signal syncLocRstIn : std_logic_vector(2 downto 0); + signal locRstCnt : std_logic_vector(3 downto 0); + signal dcmRefClk : std_logic; + signal dcmLock : std_logic; + signal resetIn : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Output Generated Clock And Reset Signals + pgpRefClk1 <= intRefClk1; + pgpRefClk2 <= intRefClk2; + pgpClk <= intPgpClk; + pgpClk90 <= intPgpClk90; + clk320 <= int320Clk; + pgpReset <= intPgpRst; + userClk <= intUsrClk; + userReset <= intUsrRst; + + -- Output unbuffered clocks + pgpClkUnbuf <= tmpPgpClk; + pgpClk90Unbuf <= tmpPgpClk90; + locClkUnbuf <= tmpLocClk; + + -- Invert power on reset + ponReset <= not ponResetL; + + -- MGT Clock Module + U_PgpClkGT11: GT11CLK generic map ( + SYNCLK1OUTEN => RefClkEn1, + SYNCLK2OUTEN => RefClkEn2, + REFCLKSEL => "MGTCLK" + ) port map ( + MGTCLKN => pgpRefClkInN, + MGTCLKP => pgpRefClkInP, + REFCLK => '0', + RXBCLK => '0', + SYNCLK1IN => '0', + SYNCLK2IN => '0', + SYNCLK1OUT => intRefClk1, + SYNCLK2OUT => intRefClk2 + ); + + + -- REF Clock 1 Is Selected As DCM Source + U_DCM_REF1: if DcmClkSrc = "RefClk1" generate + dcmRefClk <= intRefClk1; + end generate; + + -- REF Clock 2 Is Selected As DCM Source + U_DCM_REF2: if DcmClkSrc = "RefClk2" generate + dcmRefClk <= intRefClk2; + end generate; + + + + -- DCM For PGP Clock & User Clock + U_PgpDcm: DCM + generic map ( + DFS_FREQUENCY_MODE => "LOW", DLL_FREQUENCY_MODE => "HIGH", + DUTY_CYCLE_CORRECTION => FALSE, CLKIN_DIVIDE_BY_2 => FALSE, + CLK_FEEDBACK => "1X", CLKOUT_PHASE_SHIFT => "NONE", + STARTUP_WAIT => false, PHASE_SHIFT => 0, + CLKFX_MULTIPLY => UserFxMult, CLKFX_DIVIDE => UserFxDiv, + CLKDV_DIVIDE => 4.0, CLKIN_PERIOD => 6.4, + DSS_MODE => "NONE", FACTORY_JF => X"C080", + DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS" + ) + port map ( + CLKIN => dcmRefClk, CLKFB => intPgpClk, + CLK0 => tmpPgpClk, CLK90 => tmpPgpClk90, + CLK180 => open, CLK270 => open, + CLK2X => tmp320Clk, CLK2X180 => open, + CLKDV => tmpLocClk, CLKFX => open, + CLKFX180 => open, LOCKED => dcmLock, + PSDONE => open, STATUS => open, + DSSEN => '0', PSCLK => '0', + PSEN => '0', PSINCDEC => '0', + RST => ponReset + ); + + + -- Global Buffer For PGP Clock + U_PgpClkBuff: BUFGMUX port map ( + O => intPgpClk, + I0 => tmpPgpClk, + I1 => '0', + S => '0' + ); + U_PgpClkBuff90: BUFGMUX port map ( + O => intPgpClk90, + I0 => tmpPgpClk90, + I1 => '0', + S => '0' + ); + + + -- Global Buffer For 125Mhz Clock + U_LocClkBuff: BUFGMUX port map ( + O => intUsrClk, + I0 => tmpLocClk, + I1 => '0', + S => '0' + ); + U_320ClkBuff: BUFGMUX port map ( + O => int320Clk, + I0 => tmp320Clk, + I1 => '0', + S => '0' + ); + + + -- Generate reset input + resetIn <= (not dcmLock) or ponReset or locReset; + + -- PGP Clock Synced Reset + process ( pgpClkIn, resetIn ) begin + if resetIn = '1' then + syncPgpRstIn <= (others=>'0') after tpd; + pgpRstCnt <= (others=>'0') after tpd; + intPgpRst <= '1' after tpd; + elsif rising_edge(pgpClkIn) then + + -- Sync local reset, lock and power on reset to local clock + -- Negative asserted signal + syncPgpRstIn(0) <= '1' after tpd; + syncPgpRstIn(1) <= syncPgpRstIn(0) after tpd; + syncPgpRstIn(2) <= syncPgpRstIn(1) after tpd; + + -- Reset counter on reset + if syncPgpRstIn(2) = '0' then + pgpRstCnt <= (others=>'0') after tpd; + intPgpRst <= '1' after tpd; + + -- Count Up To Max Value + elsif pgpRstCnt = "1111" then + intPgpRst <= '0' after tpd; + + -- Increment counter + else + intPgpRst <= '1' after tpd; + pgpRstCnt <= pgpRstCnt + 1 after tpd; + end if; + end if; + end process; + + -- Local User Clock Synced Reset + process ( userClkIn, resetIn ) begin + if resetIn = '1' then + syncLocRstIn <= (others=>'0') after tpd; + locRstCnt <= (others=>'0') after tpd; + intUsrRst <= '1' after tpd; + elsif rising_edge(userClkIn) then + + -- Sync local reset, lock and power on reset to local clock + -- Negative asserted signal + syncLocRstIn(0) <= '1' after tpd; + syncLocRstIn(1) <= syncLocRstIn(0) after tpd; + syncLocRstIn(2) <= syncLocRstIn(1) after tpd; + + -- Reset counter on reset + if syncLocRstIn(2) = '0' then + locRstCnt <= (others=>'0') after tpd; + intUsrRst <= '1' after tpd; + + -- Count Up To Max Value + elsif locRstCnt = "1111" then + intUsrRst <= '0' after tpd; + + -- Increment counter + else + intUsrRst <= '1' after tpd; + locRstCnt <= locRstCnt + 1 after tpd; + end if; + end if; + end process; + +end PgpClkGen; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/rce/Pgp2Rce.vhd b/rce/fw-hsio/modules/pgp2/hdl/rce/Pgp2Rce.vhd new file mode 100755 index 00000000..daedd776 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/rce/Pgp2Rce.vhd @@ -0,0 +1,682 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, RCE Interface +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2Rce.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 06/06/2007 +------------------------------------------------------------------------------- +-- Description: +-- VHDL source for PGP2 interface to RCE. 4-Lane version. +------------------------------------------------------------------------------- +-- Copyright (c) 2010 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 01/18/2010: created. +-- 09/08/2010: Integrated 4x and 2x into one module. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use work.Pgp2RcePackage.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity Pgp2Rce is + generic ( + FreeListA : natural := 1; -- Free List For VC 0 + FreeListB : natural := 2; -- Free List For VC 1 + FreeListC : natural := 3; -- Free List For VC 2 + FreeListD : natural := 4; -- Free List For VC 3 + RefClkSel : string := "REFCLK1"; -- Reference Clock To Use "REFCLK1" or "REFCLK2" + PgpLaneCnt : natural := 4 -- Number of PGP lanes, 2 or 4. + ); + port ( + + -- Import Interface + Import_Clock : out std_logic; + Import_Core_Reset : in std_logic; + Import_Free_List : out std_logic_vector( 3 downto 0); + Import_Advance_Data_Pipeline : out std_logic; + Import_Data_Last_Line : out std_logic; + Import_Data_Last_Valid_Byte : out std_logic_vector( 2 downto 0); + Import_Data : out std_logic_vector(63 downto 0); + Import_Data_Pipeline_Full : in std_logic; + Import_Pause : in std_logic; + + -- Export Interface + Export_Clock : out std_logic; + Export_Core_Reset : in std_logic; + Export_Data_Available : in std_logic; + Export_Data_Start : in std_logic; + Export_Advance_Data_Pipeline : out std_logic; + Export_Data_Last_Line : in std_logic; + Export_Data_Last_Valid_Byte : in std_logic_vector( 2 downto 0); + Export_Data : in std_logic_vector(63 downto 0); + Export_Advance_Status_Pipeline : out std_logic; + Export_Status : out std_logic_vector(31 downto 0); + Export_Status_Full : in std_logic; + + -- DCR Bus + Dcr_Clock : in std_logic; + Dcr_Write : in std_logic; + Dcr_Write_Data : in std_logic_vector(31 downto 0); + Dcr_Read_Address : in std_logic_vector( 1 downto 0); + Dcr_Read_Data : out std_logic_vector(31 downto 0); + + -- Reference Clock, PGP Clock & Reset Signals + -- Use one ref clock, tie other to 0, see RefClkSel above + pgpRefClk1 : in std_logic; + pgpRefClk2 : in std_logic; + pgpClk : in std_logic; + pgpReset : in std_logic; + + -- MGT Serial Pins + mgtRxN : in std_logic_vector(PgpLaneCnt-1 downto 0); + mgtRxP : in std_logic_vector(PgpLaneCnt-1 downto 0); + mgtTxN : out std_logic_vector(PgpLaneCnt-1 downto 0); + mgtTxP : out std_logic_vector(PgpLaneCnt-1 downto 0) + ); +end Pgp2Rce; + + +-- Define architecture +architecture Pgp2Rce of Pgp2Rce is + + -- Local Signals + signal vcFrameTxVc : std_logic_vector(1 downto 0); + signal vcFrameTxSOF : std_logic; + signal vcFrameTxEOF : std_logic; + signal vcFrameTxEOFE : std_logic; + signal vcFrameTxData : std_logic_vector(15 downto 0); + signal vcFrameTxValid : std_logic_vector(3 downto 0); + signal vcFrameTxReady : std_logic_vector(3 downto 0); + signal vcRemBuffAFull : std_logic_vector(15 downto 0); + signal vcRemBuffFull : std_logic_vector(15 downto 0); + signal vcFrameRxSOF : std_logic_vector(3 downto 0); + signal vcFrameRxEOF : std_logic_vector(3 downto 0); + signal vcFrameRxEOFE : std_logic_vector(3 downto 0); + signal vcFrameRxDataA : std_logic_vector(63 downto 0); + signal vcFrameRxDataB : std_logic_vector(63 downto 0); + signal vcFrameRxDataC : std_logic_vector(63 downto 0); + signal vcFrameRxDataD : std_logic_vector(63 downto 0); + signal vcFrameRxReq : std_logic_vector(3 downto 0); + signal vcFrameRxValid : std_logic_vector(3 downto 0); + signal vcFrameRxReady : std_logic_vector(3 downto 0); + signal vcFrameRxWidthA : std_logic_vector(1 downto 0); + signal vcFrameRxWidthB : std_logic_vector(1 downto 0); + signal vcFrameRxWidthC : std_logic_vector(1 downto 0); + signal vcFrameRxWidthD : std_logic_vector(1 downto 0); + signal pgpRemLinkReady : std_logic_vector(3 downto 0); + signal pgpLocLinkReady : std_logic_vector(3 downto 0); + signal cntReset : std_logic; + signal pgpCntCellErrorA : std_logic_vector(3 downto 0); + signal pgpCntCellErrorB : std_logic_vector(3 downto 0); + signal pgpCntCellErrorC : std_logic_vector(3 downto 0); + signal pgpCntCellErrorD : std_logic_vector(3 downto 0); + signal pgpCntLinkDownA : std_logic_vector(3 downto 0); + signal pgpCntLinkDownB : std_logic_vector(3 downto 0); + signal pgpCntLinkDownC : std_logic_vector(3 downto 0); + signal pgpCntLinkDownD : std_logic_vector(3 downto 0); + signal pgpCntLinkErrorA : std_logic_vector(3 downto 0); + signal pgpCntLinkErrorB : std_logic_vector(3 downto 0); + signal pgpCntLinkErrorC : std_logic_vector(3 downto 0); + signal pgpCntLinkErrorD : std_logic_vector(3 downto 0); + signal pgpRxFifoErr : std_logic_vector(3 downto 0); + signal mgtLoopback : std_logic_vector(3 downto 0); + signal mgtCombusOutA : std_logic_vector(15 downto 0); + signal mgtCombusOutB : std_logic_vector(15 downto 0); + signal mgtCombusOutC : std_logic_vector(15 downto 0); + signal mgtCombusOutD : std_logic_vector(15 downto 0); + signal pllTxRst : std_logic_vector(3 downto 0); + signal pllRxRst : std_logic_vector(3 downto 0); + signal pllTxReady : std_logic_vector(3 downto 0); + signal pllRxReady : std_logic_vector(3 downto 0); + signal dcrReset : std_logic; + signal dcrResetSync : std_logic; + signal writeData : std_logic_vector(31 downto 0); + signal writeDataSync : std_logic_vector(31 downto 0); + signal csControl0 : std_logic_vector(35 downto 0); + signal csControl1 : std_logic_vector(35 downto 0); + signal csData : std_logic_vector(63 downto 0); + signal csCntrl : std_logic_vector(15 downto 0); + signal csStat : std_logic_vector(15 downto 0); + signal importDebug : std_logic_vector(63 downto 0); + signal exportDebug : std_logic_vector(63 downto 0); + signal lane0Debug : std_logic_vector(63 downto 0); + signal lane1Debug : std_logic_vector(63 downto 0); + signal importReset : std_logic_vector(3 downto 0); + signal pgpRxCntD : std_logic_vector(3 downto 0); + signal pgpRxCntC : std_logic_vector(3 downto 0); + signal pgpRxCntB : std_logic_vector(3 downto 0); + signal pgpRxCntA : std_logic_vector(3 downto 0); + signal bigEndian : std_logic; + signal importPauseDly : std_logic; + signal importPauseCnt : std_logic_vector(3 downto 0); + + -- ICON + component pgp2_v4_icon + PORT ( + CONTROL0 : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0); + CONTROL1 : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0)); + end component; + + -- ILA + component pgp2_v4_ila + PORT ( + CONTROL : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0); + CLK : IN STD_LOGIC; + DATA : IN STD_LOGIC_VECTOR(63 DOWNTO 0); + TRIG0 : IN STD_LOGIC_VECTOR(7 DOWNTO 0)); + end component; + + -- VIO + component pgp2_v4_vio + PORT ( + CONTROL : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0); + CLK : IN STD_LOGIC; + SYNC_IN : IN STD_LOGIC_VECTOR(15 DOWNTO 0); + SYNC_OUT : OUT STD_LOGIC_VECTOR(15 DOWNTO 0)); + end component; + + -- Chipscope attributes + attribute syn_black_box : boolean; + attribute syn_noprune : boolean; + attribute syn_black_box of pgp2_v4_icon : component is TRUE; + attribute syn_noprune of pgp2_v4_icon : component is TRUE; + attribute syn_black_box of pgp2_v4_ila : component is TRUE; + attribute syn_noprune of pgp2_v4_ila : component is TRUE; + attribute syn_black_box of pgp2_v4_vio : component is TRUE; + attribute syn_noprune of pgp2_v4_vio : component is TRUE; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Create import reset vector + importReset <= Import_Core_Reset & Import_Core_Reset & Import_Core_Reset & Import_Core_Reset; + + -- Dcr Reset generation, Sync to DCR Clock + process ( Dcr_Clock ) begin + if rising_edge(Dcr_Clock) then + dcrResetSync <= pgpReset after tpd; + dcrReset <= dcrResetSync after tpd; + end if; + end process; + + + -- DCR Read + process ( dcrReset, Dcr_Clock ) begin + if dcrReset = '1' then + Dcr_Read_Data <= (others=>'0') after tpd; + elsif rising_edge(Dcr_Clock) then + case Dcr_Read_Address is + when "00" => + Dcr_Read_Data(31 downto 28) <= pgpRemLinkReady after tpd; + Dcr_Read_Data(27 downto 24) <= pgpLocLinkReady after tpd; + Dcr_Read_Data(23 downto 20) <= pllTxReady after tpd; + Dcr_Read_Data(19 downto 16) <= pllRxReady after tpd; + Dcr_Read_Data(15 downto 14) <= (others=>'0') after tpd; + Dcr_Read_Data(13) <= bigEndian after tpd; + Dcr_Read_Data(12) <= cntReset after tpd; + Dcr_Read_Data(11 downto 8) <= pllTxRst after tpd; + Dcr_Read_Data(7 downto 4) <= pllRxRst after tpd; + Dcr_Read_Data(3 downto 0) <= mgtLoopback after tpd; + when "01" => + Dcr_Read_Data(31 downto 28) <= pgpCntCellErrorD after tpd; + Dcr_Read_Data(27 downto 24) <= pgpCntCellErrorC after tpd; + Dcr_Read_Data(23 downto 20) <= pgpCntCellErrorB after tpd; + Dcr_Read_Data(19 downto 16) <= pgpCntCellErrorA after tpd; + Dcr_Read_Data(15 downto 12) <= pgpCntLinkErrorD after tpd; + Dcr_Read_Data(11 downto 8) <= pgpCntLinkErrorC after tpd; + Dcr_Read_Data( 7 downto 4) <= pgpCntLinkErrorB after tpd; + Dcr_Read_Data( 3 downto 0) <= pgpCntLinkErrorA after tpd; + when "10" => + Dcr_Read_Data(31 downto 20) <= (others=>'0') after tpd; + Dcr_Read_Data(19 downto 16) <= pgpRxFifoErr after tpd; + Dcr_Read_Data(15 downto 12) <= pgpCntLinkDownD after tpd; + Dcr_Read_Data(11 downto 8) <= pgpCntLinkDownC after tpd; + Dcr_Read_Data( 7 downto 4) <= pgpCntLinkDownB after tpd; + Dcr_Read_Data( 3 downto 0) <= pgpCntLinkDownA after tpd; + when "11" => + Dcr_Read_Data(31 downto 20) <= (others=>'0') after tpd; + Dcr_Read_Data(19 downto 16) <= importPauseCnt after tpd; + Dcr_Read_Data(15 downto 12) <= pgpRxCntD after tpd; + Dcr_Read_Data(11 downto 8) <= pgpRxCntC after tpd; + Dcr_Read_Data( 7 downto 4) <= pgpRxCntB after tpd; + Dcr_Read_Data( 3 downto 0) <= pgpRxCntA after tpd; + when others => + Dcr_Read_Data <= (others=>'0') after tpd; + end case; + end if; + end process; + + + -- DCR Write + process ( dcrReset, Dcr_Clock ) begin + if dcrReset = '1' then + writeData <= (others=>'0') after tpd; + elsif rising_edge(Dcr_Clock) then + if Dcr_Write = '1' then + writeData <= Dcr_Write_Data after tpd; + end if; + end if; + end process; + + + -- Synchronize Write Data + process ( pgpReset, pgpClk ) begin + if pgpReset = '1' then + writeDataSync <= (others=>'0') after tpd; + cntReset <= '0' after tpd; + bigEndian <= '0' after tpd; + pllTxRst <= (others=>'0') after tpd; + pllRxRst <= (others=>'0') after tpd; + mgtLoopback <= (others=>'0') after tpd; + elsif rising_edge(pgpClk) then + writeDataSync <= writeData after tpd; + bigEndian <= writeDataSync(13) after tpd; + cntReset <= writeDataSync(12) or csCntrl(12) or importReset(0) after tpd; + pllTxRst <= writeDataSync(11 downto 8) or csCntrl(3 downto 0) after tpd; + pllRxRst <= writeDataSync(7 downto 4) or csCntrl(7 downto 4) or importReset after tpd; + mgtLoopback <= writeDataSync(3 downto 0) or csCntrl(11 downto 8) after tpd; + end if; + end process; + + + -- Pause cycle counter + process ( pgpReset, pgpClk ) begin + if pgpReset = '1' then + importPauseDly <= '0' after tpd; + importPauseCnt <= (others=>'0') after tpd; + elsif rising_edge(pgpClk) then + importPauseDly <= Import_Pause after tpd; + + -- Pause assertion counter + if cntReset = '1' then + importPauseCnt <= (others=>'0') after tpd; + elsif Import_Pause = '1' and importPauseDly = '0' and importPauseCnt /= x"F" then + importPauseCnt <= importPauseCnt + 1 after tpd; + end if; + end if; + end process; + + + -- Export Interface + U_Pgp2RceExport: Pgp2RcePackage.Pgp2RceExport port map ( + pgpClk => pgpClk, + pgpReset => pgpReset, + Export_Clock => Export_Clock, + Export_Core_Reset => Export_Core_Reset, + Export_Data_Available => Export_Data_Available, + Export_Data_Start => Export_Data_Start, + Export_Advance_Data_Pipeline => Export_Advance_Data_Pipeline, + Export_Data_Last_Line => Export_Data_Last_Line, + Export_Data_Last_Valid_Byte => Export_Data_Last_Valid_Byte, + Export_Data => Export_Data, + Export_Advance_Status_Pipeline => Export_Advance_Status_Pipeline, + Export_Status => Export_Status, + Export_Status_Full => Export_Status_Full, + pgpRemLinkReady => pgpRemLinkReady, + vcFrameTxVc => vcFrameTxVc, + vcFrameTxSOF => vcFrameTxSOF, + vcFrameTxEOF => vcFrameTxEOF, + vcFrameTxEOFE => vcFrameTxEOFE, + vcFrameTxData => vcFrameTxData, + vcFrameTxValid => vcFrameTxValid, + vcFrameTxReady => vcFrameTxReady, + vcRemBuffAFull => vcRemBuffAFull, + vcRemBuffFull => vcRemBuffFull, + bigEndian => bigEndian, + debug => exportDebug + ); + + + -- Import Interface + U_Pgp2RceImport: Pgp2RcePackage.Pgp2RceImport + generic map ( + FreeListA => FreeListA, + FreeListB => FreeListB, + FreeListC => FreeListC, + FreeListD => FreeListD + ) port map ( + pgpClk => pgpClk, + pgpReset => pgpReset, + Import_Clock => Import_Clock, + Import_Core_Reset => Import_Core_Reset, + Import_Free_List => Import_Free_List, + Import_Advance_Data_Pipeline => Import_Advance_Data_Pipeline, + Import_Data_Last_Line => Import_Data_Last_Line, + Import_Data_Last_Valid_Byte => Import_Data_Last_Valid_Byte, + Import_Data => Import_Data, + Import_Data_Pipeline_Full => Import_Data_Pipeline_Full, + Import_Pause => Import_Pause, + pgpLocLinkReady => pgpLocLinkReady, + vcFrameRxSOF => vcFrameRxSOF, + vcFrameRxEOF => vcFrameRxEOF, + vcFrameRxEOFE => vcFrameRxEOFE, + vcFrameRxDataA => vcFrameRxDataA, + vcFrameRxDataB => vcFrameRxDataB, + vcFrameRxDataC => vcFrameRxDataC, + vcFrameRxDataD => vcFrameRxDataD, + vcFrameRxReq => vcFrameRxReq, + vcFrameRxValid => vcFrameRxValid, + vcFrameRxReady => vcFrameRxReady, + vcFrameRxWidthA => vcFrameRxWidthA, + vcFrameRxWidthB => vcFrameRxWidthB, + vcFrameRxWidthC => vcFrameRxWidthC, + vcFrameRxWidthD => vcFrameRxWidthD, + bigEndian => bigEndian, + debug => importDebug + ); + + + -- Lane A + U_Pgp2RceLaneA: Pgp2RcePackage.Pgp2RceLane + generic map ( + MgtMode => "A", + RefClkSel => RefClkSel + ) port map ( + pgpClk => pgpClk, + pgpReset => pgpReset, + pllTxRst => pllTxRst(0), + pllRxRst => pllRxRst(0), + pllRxReady => pllRxReady(0), + pllTxReady => pllTxReady(0), + pgpLocLinkReady => pgpLocLinkReady(0), + pgpRemLinkReady => pgpRemLinkReady(0), + cntReset => cntReset, + pgpCntCellError => pgpCntCellErrorA, + pgpCntLinkDown => pgpCntLinkDownA, + pgpCntLinkError => pgpCntLinkErrorA, + pgpRxFifoErr => pgpRxFifoErr(0), + pgpRxCnt => pgpRxCntA, + laneNumber => "00", + vcFrameRxSOF => vcFrameRxSOF(0), + vcFrameRxEOF => vcFrameRxEOF(0), + vcFrameRxEOFE => vcFrameRxEOFE(0), + vcFrameRxData => vcFrameRxDataA, + vcFrameRxReq => vcFrameRxReq(0), + vcFrameRxValid => vcFrameRxValid(0), + vcFrameRxReady => vcFrameRxReady(0), + vcFrameRxWidth => vcFrameRxWidthA, + vcFrameTxVc => vcFrameTxVc, + vcFrameTxValid => vcFrameTxValid(0), + vcFrameTxReady => vcFrameTxReady(0), + vcFrameTxSOF => vcFrameTxSOF, + vcFrameTxEOF => vcFrameTxEOF, + vcFrameTxEOFE => vcFrameTxEOFE, + vcFrameTxData => vcFrameTxData, + vcRemBuffAFull => vcRemBuffAFull(3 downto 0), + vcRemBuffFull => vcRemBuffFull(3 downto 0), + mgtLoopback => mgtLoopback(0), + mgtRefClk1 => pgpRefClk1, + mgtRefClk2 => pgpRefClk2, + mgtRxN => mgtRxN(0), + mgtRxP => mgtRxP(0), + mgtTxN => mgtTxN(0), + mgtTxP => mgtTxP(0), + mgtCombusIn => mgtCombusOutB, + mgtCombusOut => mgtCombusOutA, + debug => lane0Debug + ); + + + -- Lane B + U_Pgp2RceLaneB: Pgp2RcePackage.Pgp2RceLane + generic map ( + MgtMode => "B", + RefClkSel => RefClkSel + ) port map ( + pgpClk => pgpClk, + pgpReset => pgpReset, + pllTxRst => pllTxRst(1), + pllRxRst => pllRxRst(1), + pllRxReady => pllRxReady(1), + pllTxReady => pllTxReady(1), + pgpLocLinkReady => pgpLocLinkReady(1), + pgpRemLinkReady => pgpRemLinkReady(1), + cntReset => cntReset, + pgpCntCellError => pgpCntCellErrorB, + pgpCntLinkDown => pgpCntLinkDownB, + pgpCntLinkError => pgpCntLinkErrorB, + pgpRxFifoErr => pgpRxFifoErr(1), + pgpRxCnt => pgpRxCntB, + laneNumber => "01", + vcFrameRxSOF => vcFrameRxSOF(1), + vcFrameRxEOF => vcFrameRxEOF(1), + vcFrameRxEOFE => vcFrameRxEOFE(1), + vcFrameRxData => vcFrameRxDataB, + vcFrameRxReq => vcFrameRxReq(1), + vcFrameRxValid => vcFrameRxValid(1), + vcFrameRxReady => vcFrameRxReady(1), + vcFrameRxWidth => vcFrameRxWidthB, + vcFrameTxVc => vcFrameTxVc, + vcFrameTxValid => vcFrameTxValid(1), + vcFrameTxReady => vcFrameTxReady(1), + vcFrameTxSOF => vcFrameTxSOF, + vcFrameTxEOF => vcFrameTxEOF, + vcFrameTxEOFE => vcFrameTxEOFE, + vcFrameTxData => vcFrameTxData, + vcRemBuffAFull => vcRemBuffAFull(7 downto 4), + vcRemBuffFull => vcRemBuffFull(7 downto 4), + mgtLoopback => mgtLoopback(1), + mgtRefClk1 => pgpRefClk1, + mgtRefClk2 => pgpRefClk2, + mgtRxN => mgtRxN(1), + mgtRxP => mgtRxP(1), + mgtTxN => mgtTxN(1), + mgtTxP => mgtTxP(1), + mgtCombusIn => mgtCombusOutA, + mgtCombusOut => mgtCombusOutB, + debug => lane1Debug + ); + + + -- Enable upper two lanes + Pgp2UpperEn: if ( PgpLaneCnt = 4 ) generate + + -- Lane C + U_Pgp2RceLaneC: Pgp2RcePackage.Pgp2RceLane + generic map ( + MgtMode => "A", + RefClkSel => RefClkSel + ) port map ( + pgpClk => pgpClk, + pgpReset => pgpReset, + pllTxRst => pllTxRst(2), + pllRxRst => pllRxRst(2), + pllRxReady => pllRxReady(2), + pllTxReady => pllTxReady(2), + pgpLocLinkReady => pgpLocLinkReady(2), + pgpRemLinkReady => pgpRemLinkReady(2), + cntReset => cntReset, + pgpCntCellError => pgpCntCellErrorC, + pgpCntLinkDown => pgpCntLinkDownC, + pgpCntLinkError => pgpCntLinkErrorC, + pgpRxFifoErr => pgpRxFifoErr(2), + pgpRxCnt => pgpRxCntC, + laneNumber => "10", + vcFrameRxSOF => vcFrameRxSOF(2), + vcFrameRxEOF => vcFrameRxEOF(2), + vcFrameRxEOFE => vcFrameRxEOFE(2), + vcFrameRxData => vcFrameRxDataC, + vcFrameRxReq => vcFrameRxReq(2), + vcFrameRxValid => vcFrameRxValid(2), + vcFrameRxReady => vcFrameRxReady(2), + vcFrameRxWidth => vcFrameRxWidthC, + vcFrameTxVc => vcFrameTxVc, + vcFrameTxValid => vcFrameTxValid(2), + vcFrameTxReady => vcFrameTxReady(2), + vcFrameTxSOF => vcFrameTxSOF, + vcFrameTxEOF => vcFrameTxEOF, + vcFrameTxEOFE => vcFrameTxEOFE, + vcFrameTxData => vcFrameTxData, + vcRemBuffAFull => vcRemBuffAFull(11 downto 8), + vcRemBuffFull => vcRemBuffFull(11 downto 8), + mgtLoopback => mgtLoopback(2), + mgtRefClk1 => pgpRefClk1, + mgtRefClk2 => pgpRefClk2, + mgtRxN => mgtRxN(2), + mgtRxP => mgtRxP(2), + mgtTxN => mgtTxN(2), + mgtTxP => mgtTxP(2), + mgtCombusIn => mgtCombusOutD, + mgtCombusOut => mgtCombusOutC, + debug => open + ); + + + -- Lane D + U_Pgp2RceLaneD: Pgp2RcePackage.Pgp2RceLane + generic map ( + MgtMode => "B", + RefClkSel => RefClkSel + ) port map ( + pgpClk => pgpClk, + pgpReset => pgpReset, + pllTxRst => pllTxRst(3), + pllRxRst => pllRxRst(3), + pllRxReady => pllRxReady(3), + pllTxReady => pllTxReady(3), + pgpLocLinkReady => pgpLocLinkReady(3), + pgpRemLinkReady => pgpRemLinkReady(3), + cntReset => cntReset, + pgpCntCellError => pgpCntCellErrorD, + pgpCntLinkDown => pgpCntLinkDownD, + pgpCntLinkError => pgpCntLinkErrorD, + pgpRxFifoErr => pgpRxFifoErr(3), + pgpRxCnt => pgpRxCntD, + laneNumber => "11", + vcFrameRxSOF => vcFrameRxSOF(3), + vcFrameRxEOF => vcFrameRxEOF(3), + vcFrameRxEOFE => vcFrameRxEOFE(3), + vcFrameRxData => vcFrameRxDataD, + vcFrameRxReq => vcFrameRxReq(3), + vcFrameRxValid => vcFrameRxValid(3), + vcFrameRxReady => vcFrameRxReady(3), + vcFrameRxWidth => vcFrameRxWidthD, + vcFrameTxVc => vcFrameTxVc, + vcFrameTxValid => vcFrameTxValid(3), + vcFrameTxReady => vcFrameTxReady(3), + vcFrameTxSOF => vcFrameTxSOF, + vcFrameTxEOF => vcFrameTxEOF, + vcFrameTxEOFE => vcFrameTxEOFE, + vcFrameTxData => vcFrameTxData, + vcRemBuffAFull => vcRemBuffAFull(15 downto 12), + vcRemBuffFull => vcRemBuffFull(15 downto 12), + mgtLoopback => mgtLoopback(3), + mgtRefClk1 => pgpRefClk1, + mgtRefClk2 => pgpRefClk2, + mgtRxN => mgtRxN(3), + mgtRxP => mgtRxP(3), + mgtTxN => mgtTxN(3), + mgtTxP => mgtTxP(3), + mgtCombusIn => mgtCombusOutC, + mgtCombusOut => mgtCombusOutD, + debug => open + ); + end generate; + + + -- Disable upper two lanes + Pgp2UpperDis: if ( PgpLaneCnt = 2 ) generate + + -- Lane C + pllRxReady(2) <= '0'; + pllTxReady(2) <= '0'; + pgpLocLinkReady(2) <= '0'; + pgpRemLinkReady(2) <= '0'; + pgpCntCellErrorC <= (others=>'0'); + pgpCntLinkDownC <= (others=>'0'); + pgpCntLinkErrorC <= (others=>'0'); + pgpRxFifoErr(2) <= '0'; + pgpRxCntC <= (others=>'0'); + vcFrameRxSOF(2) <= '0'; + vcFrameRxEOF(2) <= '0'; + vcFrameRxEOFE(2) <= '0'; + vcFrameRxDataC <= (others=>'0'); + vcFrameRxReq(2) <= '0'; + vcFrameRxValid(2) <= '0'; + vcFrameRxWidthC <= (others=>'0'); + vcFrameTxReady(2) <= '0'; + vcRemBuffAFull(11 downto 8) <= (others=>'0'); + vcRemBuffFull(11 downto 8) <= (others=>'0'); + mgtCombusOutC <= (others=>'0'); + + -- Lane D + pllRxReady(3) <= '0'; + pllTxReady(3) <= '0'; + pgpLocLinkReady(3) <= '0'; + pgpRemLinkReady(3) <= '0'; + pgpCntCellErrorD <= (others=>'0'); + pgpCntLinkDownD <= (others=>'0'); + pgpCntLinkErrorD <= (others=>'0'); + pgpRxFifoErr(3) <= '0'; + pgpRxCntD <= (others=>'0'); + vcFrameRxSOF(3) <= '0'; + vcFrameRxEOF(3) <= '0'; + vcFrameRxEOFE(3) <= '0'; + vcFrameRxDataD <= (others=>'0'); + vcFrameRxReq(3) <= '0'; + vcFrameRxValid(3) <= '0'; + vcFrameRxWidthD <= (others=>'0'); + vcFrameTxReady(3) <= '0'; + vcRemBuffAFull(15 downto 12) <= (others=>'0'); + vcRemBuffFull(15 downto 12) <= (others=>'0'); + mgtCombusOutD <= (others=>'0'); + + end generate; + + + ----------------------------- + -- Debug + ----------------------------- + + U_icon : pgp2_v4_icon port map ( + CONTROL0 => csControl0, + CONTROL1 => csControl1 + ); + + U_ila : pgp2_v4_ila port map ( + CONTROL => csControl0, + CLK => pgpClk, + DATA => csData, + TRIG0 => csData(7 downto 0) + ); + + U_vio : pgp2_v4_vio port map ( + CONTROL => csControl1, + CLK => pgpClk, + SYNC_IN => csStat, + SYNC_OUT => csCntrl + ); + + -- Status Bits + csStat(15 downto 4) <= (others=>'0'); + csStat(3 downto 2) <= pgpRemLinkReady(1 downto 0); + csStat(1 downto 0) <= pgpLocLinkReady(1 downto 0); + + -- Control Bits + -- cntReset csCntrl(12) + -- pllTxRst csCntrl(3 downto 0) + -- pllRxRst csCntrl(7 downto 4) + -- mgtLoopback csCntrl(11 downto 8) + + -- Register chipscope signals + process ( pgpClk ) begin + if rising_edge(pgpClk) then + case csCntrl(15 downto 14) is + when "00" => csData <= importDebug after tpd; + when "01" => csData <= exportDebug after tpd; + when "10" => csData <= lane0Debug after tpd; + when others => csData <= lane1Debug after tpd; + end case; + end if; + end process; + + +end Pgp2Rce; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/rce/Pgp2RceExport.vhd b/rce/fw-hsio/modules/pgp2/hdl/rce/Pgp2RceExport.vhd new file mode 100755 index 00000000..ca259b26 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/rce/Pgp2RceExport.vhd @@ -0,0 +1,583 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, RCE Export Block +-- Project : Reconfigurable Cluster Element +------------------------------------------------------------------------------- +-- File : Pgp2RceExport.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 01/16/2010 +------------------------------------------------------------------------------- +-- Description: +-- VHDL source file for the interface between the PIC Export interface and +-- the PGP TX Interface. +------------------------------------------------------------------------------- +-- Copyright (c) 2010 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 01/16/2010: created. +-- 08/24/2010: 32-bit endian swap. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity Pgp2RceExport is port ( + + -- System clock & reset + pgpClk : in std_logic; + pgpReset : in std_logic; + + -- PIC Export Interface + Export_Clock : out std_logic; + Export_Core_Reset : in std_logic; + Export_Data_Available : in std_logic; + Export_Data_Start : in std_logic; + Export_Advance_Data_Pipeline : out std_logic; + Export_Data_Last_Line : in std_logic; + Export_Data_Last_Valid_Byte : in std_logic_vector( 2 downto 0); + Export_Data : in std_logic_vector(63 downto 0); + Export_Advance_Status_Pipeline : out std_logic; + Export_Status : out std_logic_vector(31 downto 0); + Export_Status_Full : in std_logic; + + -- Remote Link Status + pgpRemLinkReady : in std_logic_vector(3 downto 0); + + -- Common Transmit Signals + vcFrameTxVc : out std_logic_vector(1 downto 0); + vcFrameTxSOF : out std_logic; + vcFrameTxEOF : out std_logic; + vcFrameTxEOFE : out std_logic; + vcFrameTxData : out std_logic_vector(15 downto 0); + + -- Transmit Control Signals, one per lane + vcFrameTxValid : out std_logic_vector(3 downto 0); + vcFrameTxReady : in std_logic_vector(3 downto 0); + + -- Remote flow control, one per lane/vc + vcRemBuffAFull : in std_logic_vector(15 downto 0); + vcRemBuffFull : in std_logic_vector(15 downto 0); + + -- Big endian mode + bigEndian : in std_logic; + + -- Debug + debug : out std_logic_vector(63 downto 0) + ); +end Pgp2RceExport; + + +-- Define architecture +architecture Pgp2RceExport of Pgp2RceExport is + + -- Local Signals + signal pgpReady : std_logic; + signal intLinkReady : std_logic; + signal pgpTxValid0 : std_logic; + signal pgpTxSOF0 : std_logic; + signal pgpTxEOF0 : std_logic; + signal pgpTxEOFE0 : std_logic; + signal pgpTxData0 : std_logic_vector(15 downto 0); + signal pgpTxValid1 : std_logic; + signal pgpTxEOF1 : std_logic; + signal pgpTxEOFE1 : std_logic; + signal pgpTxData1 : std_logic_vector(15 downto 0); + signal pgpTxValid2 : std_logic; + signal pgpTxEOF2 : std_logic; + signal pgpTxData2 : std_logic_vector(15 downto 0); + signal pgpTxValid3 : std_logic; + signal pgpTxEOF3 : std_logic; + signal pgpTxData3 : std_logic_vector(15 downto 0); + signal expVc : std_logic_vector(1 downto 0); + signal expLane : std_logic_vector(1 downto 0); + signal expCID : std_logic_vector(23 downto 0); + signal expSOF : std_logic; + signal exportRd : std_logic; + signal exportWr : std_logic; + signal statusWr : std_logic; + signal statusBad : std_logic; + signal pgpAFull : std_logic; + signal pgpFull : std_logic; + + -- Transmit states + signal curTxState : std_logic_vector(3 downto 0); + signal nxtTxState : std_logic_vector(3 downto 0); + constant TX_IDLE : std_logic_vector(3 downto 0) := "0000"; + constant TX_VC : std_logic_vector(3 downto 0) := "0001"; + constant TX_SOF : std_logic_vector(3 downto 0) := "0010"; + constant TX_WAIT : std_logic_vector(3 downto 0) := "0011"; + constant TX_READ : std_logic_vector(3 downto 0) := "0100"; + constant TX_DUMP : std_logic_vector(3 downto 0) := "0101"; + constant TX_SBAD_A : std_logic_vector(3 downto 0) := "0110"; + constant TX_SBAD_B : std_logic_vector(3 downto 0) := "0111"; + constant TX_SOK : std_logic_vector(3 downto 0) := "1000"; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Drive Export Clock and Read + Export_Clock <= pgpClk; + Export_Advance_Data_Pipeline <= exportRd; + + -- Valid to VCs + vcFrameTxValid(0) <= pgpTxValid0 when expLane = 0 else '0'; + vcFrameTxValid(1) <= pgpTxValid0 when expLane = 1 else '0'; + vcFrameTxValid(2) <= pgpTxValid0 when expLane = 2 else '0'; + vcFrameTxValid(3) <= pgpTxValid0 when expLane = 3 else '0'; + vcFrameTxVc <= expVc; + + -- VC Data + vcFrameTxSOF <= pgpTxSOF0; + vcFrameTxEOF <= pgpTxEOF0; + vcFrameTxEOFE <= pgpTxEOFE0; + vcFrameTxData <= pgpTxData0; + vcFrameTxVc <= expVc; + + -- VC Ready Signals + pgpReady <= vcFrameTxReady(conv_integer(expLane)); + + -- Link ready signal + intLinkReady <= pgpRemLinkReady(conv_integer(expLane)); + + -- Select Flow Control + pgpAFull <= vcRemBuffAFull(conv_integer(expLane & expVc)); + pgpFull <= vcRemBuffFull(conv_integer(expLane & expVc)); + + -- Pipeline for data going to PGP + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + pgpTxValid0 <= '0' after tpd; + pgpTxSOF0 <= '0' after tpd; + pgpTxEOF0 <= '0' after tpd; + pgpTxEOFE0 <= '0' after tpd; + pgpTxData0 <= (others=>'0') after tpd; + pgpTxValid1 <= '0' after tpd; + pgpTxEOF1 <= '0' after tpd; + pgpTxEOFE1 <= '0' after tpd; + pgpTxData1 <= (others=>'0') after tpd; + pgpTxValid2 <= '0' after tpd; + pgpTxEOF2 <= '0' after tpd; + pgpTxData2 <= (others=>'0') after tpd; + pgpTxValid3 <= '0' after tpd; + pgpTxEOF3 <= '0' after tpd; + pgpTxData3 <= (others=>'0') after tpd; + elsif rising_edge(pgpClk) then + + -- Core reset or link down. Clear Valid + if Export_Core_Reset = '1' and intLinkReady = '0' then + pgpTxValid0 <= '0' after tpd; + pgpTxValid1 <= '0' after tpd; + pgpTxValid2 <= '0' after tpd; + pgpTxValid3 <= '0' after tpd; + + -- Data shift from Export Control + elsif exportWr = '1' then + + -- Set SOF0 + pgpTxSOF0 <= expSOF after tpd; + + -- Little endian data + if bigEndian = '0' then + pgpTxData0(7 downto 0) <= Export_Data(31 downto 24) after tpd; + pgpTxData0(15 downto 8) <= Export_Data(23 downto 16) after tpd; + pgpTxData1(7 downto 0) <= Export_Data(15 downto 8) after tpd; + pgpTxData1(15 downto 8) <= Export_Data(7 downto 0) after tpd; + pgpTxData2(7 downto 0) <= Export_Data(63 downto 56) after tpd; + pgpTxData2(15 downto 8) <= Export_Data(55 downto 48) after tpd; + pgpTxData3(7 downto 0) <= Export_Data(47 downto 40) after tpd; + pgpTxData3(15 downto 8) <= Export_Data(39 downto 32) after tpd; + + -- Big endian data + else + pgpTxData0 <= Export_Data(15 downto 0) after tpd; + pgpTxData1 <= Export_Data(31 downto 16) after tpd; + pgpTxData2 <= Export_Data(47 downto 32) after tpd; + pgpTxData3 <= Export_Data(63 downto 48) after tpd; + end if; + + -- Valid, EOF & Width Depend On Last Line/Valid Byte Flags + if Export_Data_Last_Line = '1' then + + -- Init VCs and EOF Flags + pgpTxValid0 <= '1' after tpd; + pgpTxEOF0 <= '0' after tpd; + pgpTxEOFE0 <= '0' after tpd; + pgpTxValid1 <= '1' after tpd; + pgpTxEOF2 <= '0' after tpd; + + -- Determine last transfer size + case Export_Data_Last_Valid_Byte is + when "011" => -- 32-bits + pgpTxEOF1 <= '1' after tpd; + pgpTxEOFE1 <= '0' after tpd; + pgpTxValid2 <= '0' after tpd; + pgpTxValid3 <= '0' after tpd; + pgpTxEOF3 <= '0' after tpd; + when "111" => -- 64-bits + pgpTxEOF1 <= '0' after tpd; + pgpTxEOFE1 <= '0' after tpd; + pgpTxValid2 <= '1' after tpd; + pgpTxValid3 <= '1' after tpd; + pgpTxEOF3 <= '1' after tpd; + when others => -- Invalid Alignment + pgpTxEOF1 <= '1' after tpd; + pgpTxEOFE1 <= '1' after tpd; + pgpTxValid2 <= '0' after tpd; + pgpTxValid3 <= '0' after tpd; + pgpTxEOF3 <= '0' after tpd; + end case; + + -- Normal data shift + else + pgpTxValid0 <= '1' after tpd; + pgpTxEOF0 <= '0' after tpd; + pgpTxEOFE0 <= '0' after tpd; + pgpTxValid1 <= '1' after tpd; + pgpTxEOF1 <= '0' after tpd; + pgpTxValid2 <= '1' after tpd; + pgpTxEOF2 <= '0' after tpd; + pgpTxValid3 <= '1' after tpd; + pgpTxEOF3 <= '0' after tpd; + end if; + + -- Otherwise shift data for each PGP transfer + elsif pgpTxValid0 = '1' and pgpReady = '1' then + + -- Clear SOF + pgptxSOF0 <= '0' after tpd; + + -- Shift Data + pgpTxData0 <= pgpTxData1 after tpd; + pgpTxData1 <= pgpTxData2 after tpd; + pgpTxData2 <= pgpTxData3 after tpd; + pgpTxData3 <= (others=>'0') after tpd; + + -- Shift Valid + pgpTxValid0 <= pgpTxValid1 after tpd; + pgpTxValid1 <= pgpTxValid2 after tpd; + pgpTxValid2 <= pgpTxValid3 after tpd; + pgpTxValid3 <= '0' after tpd; + + -- Shift EOF + pgpTxEOF0 <= pgpTxEOF1 after tpd; + pgpTxEOF1 <= pgpTxEOF2 after tpd; + pgpTxEOF2 <= pgpTxEOF3 after tpd; + pgpTxEOF3 <= '0' after tpd; + + -- Shift EOFE + pgpTxEOFE0 <= pgpTxEOFE1 after tpd; + pgpTxEOFE1 <= '0' after tpd; + end if; + end if; + end process; + + + -- State machine to control read from PIC Interface + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + curTxState <= TX_IDLE after tpd; + expVc <= (others=>'0') after tpd; + expLane <= (others=>'0') after tpd; + expCID <= (others=>'0') after tpd; + Export_Advance_Status_Pipeline <= '0' after tpd; + Export_Status <= (others=>'0') after tpd; + elsif rising_edge(pgpClk) then + + -- Reset state on protocol reset or link down + if Export_Core_Reset = '1' then + curTxState <= TX_IDLE after tpd; + else + curTxState <= nxtTxState after tpd; + end if; + + -- Store CID, VC, Lane + if expSOF = '1' then + + -- Little endian + if bigEndian = '0' then + expCID(23 downto 16) <= Export_Data(7 downto 0) after tpd; + expCID(15 downto 8) <= Export_Data(15 downto 8) after tpd; + expCID(7 downto 0) <= Export_Data(23 downto 16) after tpd; + expVc <= Export_Data(25 downto 24) after tpd; + expLane <= Export_Data(31 downto 30) after tpd; + + -- Big endian + else + expCID <= Export_Data(31 downto 8) after tpd; + expVc <= Export_Data(1 downto 0) after tpd; + expLane <= Export_Data(7 downto 6) after tpd; + end if; + end if; + + -- Status Write + Export_Advance_Status_Pipeline <= statusWr after tpd; + Export_Status(31 downto 8) <= expCID after tpd; + Export_Status(7 downto 2) <= (others=>'0') after tpd; + Export_Status(1) <= statusBad after tpd; + Export_Status(0) <= statusBad after tpd; + end if; + end process; + + + -- Combinitorial transmit state logic + process ( curTxState, Export_Data_Available, Export_Data_Start, pgpReset, + Export_Data_Last_Line, Export_Core_Reset, pgpTxValid0, pgpTxValid1, + pgpReady, pgpAFull, pgpFull, Export_Status_Full, intLinkReady ) begin + + case curTxState is + + -- Idle, Ready to read first cell from PIC + when TX_IDLE => + + -- No Write + exportWr <= '0'; + statusWr <= '0'; + statusBad <= '0'; + expSOF <= '0'; + + -- Wait for start indication from PIC, Wait for PGP shift to be idle. + if Export_Core_Reset = '0' and pgpReset = '0' and pgpTxValid0 = '0' and + Export_Data_Start = '1' and Export_Data_Available = '1' then + exportRd <= '1'; + nxtTxState <= TX_VC; + else + exportRd <= '0'; + nxtTxState <= curTxState; + end if; + + -- Register VC, Lane and CID + when TX_VC => + + -- No read or write + exportRd <= '0'; + exportWr <= '0'; + statusWr <= '0'; + statusBad <= '0'; + expSOF <= '1'; + + -- Go to SOF state + nxtTxState <= TX_SOF; + + -- Transfer SOF + when TX_SOF => + + -- No read + exportRd <= '0'; + statusWr <= '0'; + statusBad <= '0'; + expSOF <= '1'; + + -- Link is down for selected lane + if intLinkReady = '0' then + exportWr <= '0'; + nxtTxState <= TX_DUMP; + + -- PGP Almost Full Flag is asserted, pause + elsif pgpAFull = '1' then + exportWr <= '0'; + nxtTxState <= curTxState; + + -- Output of shift register is empty + elsif pgpTxValid0 = '0' then + nxtTxState <= TX_WAIT; + exportWr <= '1'; + + -- Wait + else + nxtTxState <= curTxState; + exportWr <= '0'; + end if; + + -- Write just occured to shift register. Wait for next data + -- to be available on PIC export. Also check for last line. + when TX_WAIT => + + -- No Write + exportWr <= '0'; + statusWr <= '0'; + statusBad <= '0'; + expSOF <= '0'; + + -- Link is down for selected lane + if intLinkReady = '0' then + exportRd <= '0'; + nxtTxState <= TX_DUMP; + + -- Last byte was sent + elsif Export_Data_Last_Line = '1' then + exportRd <= '0'; + nxtTxState <= TX_SOK; + + -- Next data is ready + elsif Export_Data_Available = '1' then + exportRd <= '1'; + nxtTxState <= TX_READ; + + -- Wait + else + exportRd <= '0'; + nxtTxState <= curTxState; + end if; + + -- Data read from PIC Interface + -- Wait for shift of PGP data before writing to shift register + when TX_READ => + + -- No Read + exportRd <= '0'; + statusWr <= '0'; + statusBad <= '0'; + expSOF <= '0'; + + -- Link is down for selected lane + if intLinkReady = '0' then + exportWr <= '0'; + nxtTxState <= TX_DUMP; + + -- Output of shift register is empty + -- or 2nd stage is empty and shift is about to occur + elsif pgpTxValid0 = '0' or (pgpTxValid1 = '0' and pgpReady = '1') then + + -- Full flag is asserted, pause + if pgpFull = '1' then + exportWr <= '0'; + nxtTxState <= curTxState; + else + exportWr <= '1'; + nxtTxState <= TX_WAIT; + end if; + else + exportWr <= '0'; + nxtTxState <= curTxState; + end if; + + -- Dump Data + when TX_DUMP => + + -- No Write + exportWr <= '0'; + statusWr <= '0'; + statusBad <= '0'; + expSOF <= '0'; + + -- Last byte was sent + if Export_Data_Last_Line = '1' then + exportRd <= '0'; + nxtTxState <= TX_SBAD_A; + + -- Next data is ready + elsif Export_Data_Available = '1' then + exportRd <= '1'; + nxtTxState <= curTxState; + + -- Wait + else + exportRd <= '0'; + nxtTxState <= curTxState; + end if; + + -- Write bad status, word 0 + when TX_SBAD_A => + + -- No Write or Read + exportWr <= '0'; + exportRd <= '0'; + expSOF <= '0'; + statusBad <= '1'; + + -- Wait for status to be ready + if Export_Status_Full = '0' then + statusWr <= '1'; + nxtTxState <= TX_SBAD_B; + else + statusWr <= '0'; + nxtTxState <= curTxState; + end if; + + -- Write bad status, word 1 + when TX_SBAD_B => + + -- No Write or Read + exportWr <= '0'; + exportRd <= '0'; + expSOF <= '0'; + statusBad <= '1'; + + -- Wait for status to be ready + if Export_Status_Full = '0' then + statusWr <= '1'; + nxtTxState <= TX_IDLE; + else + statusWr <= '0'; + nxtTxState <= curTxState; + end if; + + -- Write ok status + when TX_SOK => + + -- No Write or Read + exportWr <= '0'; + exportRd <= '0'; + expSOF <= '0'; + statusBad <= '0'; + + -- Wait for status to be ready + if Export_Status_Full = '0' then + statusWr <= '1'; + nxtTxState <= TX_IDLE; + else + statusWr <= '0'; + nxtTxState <= curTxState; + end if; + + when others => + expSOF <= '0'; + exportWr <= '0'; + statusWr <= '0'; + statusBad <= '0'; + exportRd <= '0'; + nxtTxState <= TX_IDLE; + end case; + end process; + + -- Debug + debug(63 downto 56) <= Export_Data(7 downto 0); + debug(55 downto 48) <= vcRemBuffAFull(7 downto 0); + debug(47 downto 40) <= vcRemBuffFull(7 downto 0); + debug(39 downto 36) <= pgpRemLinkReady; + debug(35 downto 32) <= vcFrameTxReady; + debug(31) <= pgpTxValid0; + debug(30) <= pgpTxSOF0; + debug(29) <= pgpTxEOF0; + debug(28) <= pgpTxEOFE0; + debug(27) <= pgpTxValid1; + debug(26) <= pgpTxEOF1; + debug(25) <= pgpTxEOFE1; + debug(24) <= pgpTxValid2; + debug(23) <= pgpTxEOF2; + debug(22) <= pgpTxValid3; + debug(21) <= pgpTxEOF3; + debug(20) <= expSOF; + debug(19) <= pgpAFull; + debug(18) <= pgpFull; + debug(17 downto 16) <= expVc; + debug(15 downto 14) <= expLane; + debug(13) <= Export_Status_Full; + debug(12) <= Export_Data_Last_Line; + debug(11 downto 9) <= Export_Data_Last_Valid_Byte; + debug(8) <= pgpReady; + debug(7) <= intLinkReady; + debug(6) <= statusBad; + debug(5) <= statusWr; + debug(4) <= exportWr; + debug(3) <= exportRd; + debug(2) <= Export_Data_Start; + debug(1) <= Export_Core_Reset; + debug(0) <= Export_Data_Available; + +end Pgp2RceExport; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/rce/Pgp2RceImport.vhd b/rce/fw-hsio/modules/pgp2/hdl/rce/Pgp2RceImport.vhd new file mode 100755 index 00000000..edc63c63 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/rce/Pgp2RceImport.vhd @@ -0,0 +1,457 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, RCE Import Block +-- Project : Reconfigurable Cluster Element +------------------------------------------------------------------------------- +-- File : Pgp2RceImport.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 09/17/2007 +------------------------------------------------------------------------------- +-- Description: +-- VHDL source file for the interface between the PIC Import interface and +-- the PGP RX Interface. +------------------------------------------------------------------------------- +-- Copyright (c) 2010 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 01/16/2010: created. +-- 07/06/2010: Added payload count as generic. +-- 08/24/2010: 32-bit endian swap. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; +USE work.Pgp2CorePackage.all; + +entity Pgp2RceImport is + generic ( + FreeListA : natural := 1; -- Free List For Lane 0 + FreeListB : natural := 2; -- Free List For Lane 1 + FreeListC : natural := 3; -- Free List For Lane 2 + FreeListD : natural := 4; -- Free List For Lane 3 + PayloadCntTop : integer := 7 -- Top bit for payload counter + ); + port ( + + -- System clock & reset + pgpClk : in std_logic; + pgpReset : in std_logic; + + -- Import Interface + Import_Clock : out std_logic; + Import_Core_Reset : in std_logic; + Import_Free_List : out std_logic_vector( 3 downto 0); + Import_Advance_Data_Pipeline : out std_logic; + Import_Data_Last_Line : out std_logic; + Import_Data_Last_Valid_Byte : out std_logic_vector( 2 downto 0); + Import_Data : out std_logic_vector(63 downto 0); + Import_Data_Pipeline_Full : in std_logic; + Import_Pause : in std_logic; + + -- Link states + pgpLocLinkReady : in std_logic_vector(3 downto 0); + + -- Lane Receive Signals + vcFrameRxSOF : in std_logic_vector(3 downto 0); + vcFrameRxEOF : in std_logic_vector(3 downto 0); + vcFrameRxEOFE : in std_logic_vector(3 downto 0); + vcFrameRxDataA : in std_logic_vector(63 downto 0); + vcFrameRxDataB : in std_logic_vector(63 downto 0); + vcFrameRxDataC : in std_logic_vector(63 downto 0); + vcFrameRxDataD : in std_logic_vector(63 downto 0); + vcFrameRxReq : in std_logic_vector(3 downto 0); + vcFrameRxValid : in std_logic_vector(3 downto 0); + vcFrameRxReady : out std_logic_vector(3 downto 0); + vcFrameRxWidthA : in std_logic_vector(1 downto 0); + vcFrameRxWidthB : in std_logic_vector(1 downto 0); + vcFrameRxWidthC : in std_logic_vector(1 downto 0); + vcFrameRxWidthD : in std_logic_vector(1 downto 0); + + -- Big endian mode + bigEndian : in std_logic; + + -- Debug + debug : out std_logic_vector(63 downto 0) + ); +end Pgp2RceImport; + + +-- Define architecture +architecture Pgp2RceImport of Pgp2RceImport is + + -- Local Signals + signal intFrameRxSOF : std_logic; + signal intFrameRxEOF : std_logic; + signal intFrameRxEOFE : std_logic; + signal intFrameRxData : std_logic_vector(63 downto 0); + signal intFrameRxValid : std_logic; + signal intFrameRxWidth : std_logic_vector(1 downto 0); + signal intLocLinkReady : std_logic; + signal curSource : std_logic_vector(1 downto 0); + signal nxtSource : std_logic_vector(1 downto 0); + signal arbSource : std_logic_vector(1 downto 0); + signal userStatus : std_logic_vector(15 downto 0); + signal dataEn : std_logic; + signal statusEn : std_logic; + signal lastEn : std_logic; + signal firstEn : std_logic; + signal curWidthErr : std_logic; + signal curEofeErr : std_logic; + signal curLinkErr : std_logic; + signal nxtLinkErr : std_logic; + signal cellCount : std_logic_vector(PayloadCntTop downto 2); + signal importAdvance : std_logic; + signal importLast : std_logic; + signal importLastValid : std_logic_vector(2 downto 0); + signal importFreeList : std_logic_vector(3 downto 0); + signal importData : std_logic_vector(63 downto 0); + + -- Receive states + signal curState : std_logic_vector(1 downto 0); + signal nxtState : std_logic_vector(1 downto 0); + constant ST_IDLE : std_logic_vector(1 downto 0) := "00"; + constant ST_SOC : std_logic_vector(1 downto 0) := "01"; + constant ST_DATA : std_logic_vector(1 downto 0) := "10"; + constant ST_STATUS : std_logic_vector(1 downto 0) := "11"; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Outgoing clock + Import_Clock <= pgpClk; + + -- Decode lane selection + intFrameRxSOF <= vcFrameRxSOF(conv_integer(curSource)); + intFrameRxEOF <= vcFrameRxEOF(conv_integer(curSource)); + intFrameRxEOFE <= vcFrameRxEOFE(conv_integer(curSource)); + intFrameRxValid <= vcFrameRxValid(conv_integer(curSource)); + + -- Ready outputs + vcFrameRxReady(0) <= dataEn when curSource = 0 else '0'; + vcFrameRxReady(1) <= dataEn when curSource = 1 else '0'; + vcFrameRxReady(2) <= dataEn when curSource = 2 else '0'; + vcFrameRxReady(3) <= dataEn when curSource = 3 else '0'; + + -- Data input + intFrameRxData <= vcFrameRxDataA when curSource = 0 else + vcFrameRxDataB when curSource = 1 else + vcFrameRxDataC when curSource = 2 else + vcFrameRxDataD; + + -- Width input + intFrameRxWidth <= vcFrameRxWidthA when curSource = 0 else + vcFrameRxWidthB when curSource = 1 else + vcFrameRxWidthC when curSource = 2 else + vcFrameRxWidthD; + + -- PIC Signals + Import_Advance_Data_Pipeline <= importAdvance; + Import_Data_Last_Line <= importLast; + Import_Data_Last_Valid_Byte <= importLastValid; + Import_Free_List <= importFreeList; + Import_Data <= importData; + + -- Sync state + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + curState <= ST_IDLE after tpd; + curSource <= "00" after tpd; + importAdvance <= '0' after tpd; + importLast <= '0' after tpd; + importLastValid <= "000" after tpd; + importFreeList <= (others=>'0') after tpd; + importData <= (others=>'0') after tpd; + userStatus <= (others=>'0') after tpd; + curWidthErr <= '0' after tpd; + curEofeErr <= '0' after tpd; + curLinkErr <= '0' after tpd; + cellCount <= (others=>'0') after tpd; + intLocLinkReady <= '0' after tpd; + elsif rising_edge(pgpClk) then + + -- Link ready of current source + intLocLinkReady <= pgpLocLinkReady(conv_integer(curSource)) after tpd; + + -- Arbiter reset + if Import_Core_Reset = '1' then + curState <= ST_IDLE after tpd; + curSource <= "00" after tpd; + else + curState <= nxtState after tpd; + curSource <= nxtSource after tpd; + end if; + + -- Output signals + importAdvance <= dataEn or statusEn or firstEn after tpd; + importLast <= lastEn after tpd; + importLastValid <= "1" & intFrameRxWidth after tpd; + + -- Free list selection + if firstEn = '1' then + importFreeList(3 downto 2) <= (others=>'0') after tpd; + importFreeList(1 downto 0) <= curSource after tpd; + else + case (curSource) is + when "00" => importFreeList <= conv_std_logic_vector(FreeListA,4) after tpd; + when "01" => importFreeList <= conv_std_logic_vector(FreeListB,4) after tpd; + when "10" => importFreeList <= conv_std_logic_vector(FreeListC,4) after tpd; + when "11" => importFreeList <= conv_std_logic_vector(FreeListD,4) after tpd; + when others => importFreeList <= (others=>'0') after tpd; + end case; + end if; + + -- Select Data + if firstEn = '1' then + importData <= (others=>'0') after tpd; + + -- Data + elsif dataEn = '1' then + + -- Little endian + if bigEndian = '0' then + importData(63 downto 56) <= intFrameRxData(39 downto 32) after tpd; + importData(55 downto 48) <= intFrameRxData(47 downto 40) after tpd; + importData(47 downto 40) <= intFrameRxData(55 downto 48) after tpd; + importData(39 downto 32) <= intFrameRxData(63 downto 56) after tpd; + importData(31 downto 24) <= intFrameRxData(7 downto 0) after tpd; + importData(23 downto 16) <= intFrameRxData(15 downto 8) after tpd; + importData(15 downto 8) <= intFrameRxData(23 downto 16) after tpd; + importData(7 downto 0) <= intFrameRxData(31 downto 24) after tpd; + + -- Big endian + else + importData <= intFrameRxData after tpd; + end if; + + -- Status + elsif statusEn = '1' then + importData(63 downto 32) <= (others=>'0') after tpd; + importData(31 downto 16) <= userStatus after tpd; + importData(15 downto 4) <= (others=>'0') after tpd; + importData(3) <= curLinkErr after tpd; + importData(2) <= curWidthErr after tpd; + importData(1) <= curEofeErr after tpd; + + -- User status + if userStatus /= 0 then + importData(5) <= '1' after tpd; + else + importData(5) <= '0' after tpd; + end if; + + -- Error bit + if userStatus /= 0 or curLinkErr = '1' or + curWidthErr = '1' or curEofeErr = '1' then + importData(0) <= '1' after tpd; + else + importData(0) <= '0' after tpd; + end if; + end if; + + -- CELL Counter + if firstEn = '1' then + cellCount <= (others=>'1') after tpd; + elsif dataEn = '1' then + cellCount <= cellCount - 1 after tpd; + end if; + + -- Last line, store status + if lastEn = '1' then + if intFrameRxWidth(1) = '0' then + userStatus <= intFrameRxData(31 downto 16) after tpd; + else + userStatus <= intFrameRxData(63 downto 48) after tpd; + end if; + curWidthErr <= not intFrameRxWidth(0) after tpd; + curEOFEErr <= intFrameRxEOFE after tpd; + end if; + + -- SOF error + curLinkErr <= nxtLinkErr after tpd; + end if; + end process; + + + -- State transition + process ( curState, curSource, arbSource, vcFrameRxReq, Import_Pause, + Import_Data_Pipeline_Full, intLocLinkReady, cellCount, Import_Core_Reset, + intFrameRxEOF, intFrameRxValid, curLinkErr ) begin + + case curState is + + -- Idle, New Request + when ST_IDLE => + dataEn <= '0'; + statusEn <= '0'; + lastEn <= '0'; + firstEn <= '0'; + nxtLinkErr <= '0'; + + -- New requester + if Import_Core_Reset = '0' and vcFrameRxReq /= 0 then + nxtSource <= arbSource; + nxtState <= ST_SOC; + else + nxtSource <= curSource; + nxtState <= curState; + end if; + + -- Start of cell, write blank data and VC value + when ST_SOC => + dataEn <= '0'; + lastEn <= '0'; + nxtLinkErr <= '0'; + statusEn <= '0'; + nxtSource <= curSource; + + -- Link is lost on selected channel + if intLocLinkReady = '0' then + firstEn <= '0'; + nxtState <= ST_IDLE; + + -- Data is ready and pipeline is ready + elsif Import_Pause = '0' and Import_Data_Pipeline_Full = '0' then + firstEn <= '1'; + nxtState <= ST_DATA; + else + firstEn <= '0'; + nxtState <= curState; + end if; + + -- Read Data + when ST_DATA => + firstEn <= '0'; + statusEn <= '0'; + nxtSource <= curSource; + + -- Link is lost on selected channel + if intLocLinkReady = '0' then + nxtLinkErr <= '1'; + dataEn <= '1'; + lastEn <= '1'; + nxtState <= ST_STATUS; + + -- Data is ready and pipeline is ready + elsif Import_Pause = '0' and Import_Data_Pipeline_Full = '0' and intFrameRxValid = '1' then + nxtLinkErr <= '0'; + dataEn <= '1'; + + -- Last line is set + if intFrameRxEOF = '1' then + lastEn <= '1'; + nxtState <= ST_STATUS; + + -- Last word of cell + elsif cellCount = 0 then + lastEn <= '0'; + nxtState <= ST_IDLE; + else + lastEn <= '0'; + nxtState <= curState; + end if; + else + nxtLinkErr <= '0'; + dataEn <= '0'; + lastEn <= '0'; + nxtState <= curState; + end if; + + -- Status Write + when ST_STATUS => + nxtLinkErr <= curLinkErr; + nxtSource <= curSource; + dataEn <= '0'; + lastEn <= '0'; + firstEn <= '0'; + + -- Data is ready and pipeline is ready + if Import_Data_Pipeline_Full = '0' then + statusEn <= '1'; + nxtState <= ST_IDLE; + else + statusEn <= '0'; + nxtState <= curState; + end if; + + -- Default + when others => + nxtLinkErr <= '0'; + nxtSource <= "00"; + dataEn <= '0'; + lastEn <= '0'; + firstEn <= '0'; + statusEn <= '0'; + nxtState <= ST_IDLE; + end case; + end process; + + + -- Block to determine next data source + process ( curSource, vcFrameRxReq ) begin + case curSource is + when "00" => + if vcFrameRxReq(1) = '1' then arbSource <= "01"; + elsif vcFrameRxReq(2) = '1' then arbSource <= "10"; + elsif vcFrameRxReq(3) = '1' then arbSource <= "11"; + elsif vcFrameRxReq(0) = '1' then arbSource <= "00"; + else arbSource <= "00"; end if; + when "01" => + if vcFrameRxReq(2) = '1' then arbSource <= "10"; + elsif vcFrameRxReq(3) = '1' then arbSource <= "11"; + elsif vcFrameRxReq(0) = '1' then arbSource <= "00"; + elsif vcFrameRxReq(1) = '1' then arbSource <= "01"; + else arbSource <= "00"; end if; + when "10" => + if vcFrameRxReq(3) = '1' then arbSource <= "11"; + elsif vcFrameRxReq(0) = '1' then arbSource <= "00"; + elsif vcFrameRxReq(1) = '1' then arbSource <= "01"; + elsif vcFrameRxReq(2) = '1' then arbSource <= "10"; + else arbSource <= "00"; end if; + when "11" => + if vcFrameRxReq(0) = '1' then arbSource <= "00"; + elsif vcFrameRxReq(1) = '1' then arbSource <= "01"; + elsif vcFrameRxReq(2) = '1' then arbSource <= "10"; + elsif vcFrameRxReq(3) = '1' then arbSource <= "11"; + else arbSource <= "00"; end if; + when others => arbSource <= "00"; + end case; + end process; + + -- Debug + debug(63 downto 56) <= importData(7 downto 0); + debug(55 downto 52) <= vcFrameRxReq; + debug(51 downto 48) <= vcFrameRxEOFE; + debug(47 downto 44) <= vcFrameRxEOF; + debug(43 downto 40) <= vcFrameRxSOF; + debug(39 downto 36) <= vcFrameRxValid; + debug(35) <= intFrameRxEOFE; + debug(34) <= Import_Data_Pipeline_Full; + debug(33) <= Import_Pause; + debug(32 downto 29) <= pgpLocLinkReady; + debug(28 downto 27) <= userStatus(1 downto 0); + debug(26 downto 23) <= importFreeList; + debug(22 downto 20) <= importLastValid; + debug(19 downto 18) <= intFrameRxWidth; + debug(17) <= intLocLinkReady; + debug(16) <= curLinkErr; + debug(15) <= curEofeErr; + debug(14) <= curWidthErr; + debug(13) <= firstEn; + debug(12) <= lastEn; + debug(11) <= statusEn; + debug(10) <= dataEn; + debug(9 downto 8) <= curSource; + debug(7) <= intFrameRxValid; + debug(6) <= Import_Core_Reset; + debug(5) <= intFrameRxEOF; + debug(4) <= intFrameRxSOF; + debug(3 downto 2) <= curState; + debug(1) <= importLast; + debug(0) <= importAdvance; + +end Pgp2RceImport; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/rce/Pgp2RceLane.vhd b/rce/fw-hsio/modules/pgp2/hdl/rce/Pgp2RceLane.vhd new file mode 100755 index 00000000..5fe78e16 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/rce/Pgp2RceLane.vhd @@ -0,0 +1,462 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, RCE Lane +-- Project : Reconfigurable Cluster Element +------------------------------------------------------------------------------- +-- File : Pgp2RceLane.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 01/14/2010 +------------------------------------------------------------------------------- +-- Description: +-- VHDL source file for RCE lane interface. +------------------------------------------------------------------------------- +-- Copyright (c) 2010 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 01/14/2010: created. +------------------------------------------------------------------------------- +LIBRARY ieee; +use work.all; +use work.Pgp2MgtPackage.all; +--use work.Pgp2TbPackage.all; -- For Simulation +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity Pgp2RceLane is + generic ( + MgtMode : string := "A"; + RefClkSel : string := "REFCLK1" + ); port ( + + -- Clock and reset + pgpClk : in std_logic; + pgpReset : in std_logic; + + -- PGP Status + pllTxRst : in std_logic; + pllRxRst : in std_logic; + pllRxReady : out std_logic; + pllTxReady : out std_logic; + pgpLocLinkReady : out std_logic; + pgpRemLinkReady : out std_logic; + + -- PGP Counters + cntReset : in std_logic; + pgpCntCellError : out std_logic_vector(3 downto 0); + pgpCntLinkDown : out std_logic_vector(3 downto 0); + pgpCntLinkError : out std_logic_vector(3 downto 0); + pgpRxFifoErr : out std_logic; + pgpRxCnt : out std_logic_vector(3 downto 0); + + -- Lane Number for header + laneNumber : in std_logic_vector(1 downto 0); + + -- VC Receive Signals + vcFrameRxSOF : out std_logic; + vcFrameRxEOF : out std_logic; + vcFrameRxEOFE : out std_logic; + vcFrameRxData : out std_logic_vector(63 downto 0); + vcFrameRxReq : out std_logic; + vcFrameRxValid : out std_logic; + vcFrameRxReady : in std_logic; + vcFrameRxWidth : out std_logic_vector(1 downto 0); + + -- VC Transmit Signals + vcFrameTxVc : in std_logic_vector(1 downto 0); + vcFrameTxValid : in std_logic; + vcFrameTxReady : out std_logic; + vcFrameTxSOF : in std_logic; + vcFrameTxEOF : in std_logic; + vcFrameTxEOFE : in std_logic; + vcFrameTxData : in std_logic_vector(15 downto 0); + + -- Remote flow control + vcRemBuffAFull : out std_logic_vector(3 downto 0); + vcRemBuffFull : out std_logic_vector(3 downto 0); + + -- MGT Signals + mgtLoopback : in std_logic; + mgtRefClk1 : in std_logic; + mgtRefClk2 : in std_logic; + mgtRxN : in std_logic; + mgtRxP : in std_logic; + mgtTxN : out std_logic; + mgtTxP : out std_logic; + mgtCombusIn : in std_logic_vector(15 downto 0); + mgtCombusOut : out std_logic_vector(15 downto 0); + + -- Debug + debug : out std_logic_vector(63 downto 0) + + ); +end Pgp2RceLane; + + +-- Define architecture +architecture Pgp2RceLane of Pgp2RceLane is + + -- Receive FIFO + component pgp2_v4_fifo_69x512 + port ( + clk: IN std_logic; + rst: IN std_logic; + din: IN std_logic_VECTOR(68 downto 0); + wr_en: IN std_logic; + rd_en: IN std_logic; + dout: OUT std_logic_VECTOR(68 downto 0); + full: OUT std_logic; + empty: OUT std_logic; + data_count: OUT std_logic_VECTOR(8 downto 0) + ); + end component; + + -- Local Signals + signal pgpRxCellError : std_logic; + signal pgpRxLinkDown : std_logic; + signal pgpRxLinkError : std_logic; + signal currVc : std_logic_vector(1 downto 0); + signal intCntCellError : std_logic_vector(3 downto 0); + signal intCntLinkDown : std_logic_vector(3 downto 0); + signal intCntLinkError : std_logic_vector(3 downto 0); + signal intCntRx : std_logic_vector(3 downto 0); + signal vcLocBuffAFull : std_logic; + signal vcLocBuffFull : std_logic; + signal intFrameTxValid : std_logic_vector(3 downto 0); + signal intFrameTxReady : std_logic_vector(3 downto 0); + signal intLocLinkReady : std_logic; + signal intFrameRxSOF : std_logic; + signal intFrameRxEOF : std_logic; + signal intFrameRxEOFE : std_logic; + signal intFrameRxData : std_logic_vector(15 downto 0); + signal intFrameRxValid : std_logic_vector(3 downto 0); + signal fifoWrData : std_logic_vector(68 downto 0); + signal fifoWrEn : std_logic; + signal fifoRdEn : std_logic; + signal fifoRdEnDly : std_logic; + signal fifoRdData : std_logic_vector(68 downto 0); + signal fifoFull : std_logic; + signal fifoRst : std_logic; + signal fifoEmpty : std_logic; + signal fifoCount : std_logic_vector(8 downto 0); + signal fifoWrCnt : std_logic_vector(1 downto 0); + signal fifoEofCnt : std_logic_vector(8 downto 0); + signal fifoEofRd : std_logic; + signal fifoEofWr : std_logic; + signal intValid : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Output counters + pgpCntCellError <= intCntCellError; + pgpCntLinkDown <= intCntLinkDown; + pgpCntLinkError <= intCntLinkError; + pgpRxCnt <= intCntRx; + + -- Link status + pgpLocLinkReady <= intLocLinkReady; + + -- Decode VC valid + intFrameTxValid(0) <= vcFrameTxValid when vcFrameTxVc = 0 else '0'; + intFrameTxValid(1) <= vcFrameTxValid when vcFrameTxVc = 1 else '0'; + intFrameTxValid(2) <= vcFrameTxValid when vcFrameTxVc = 2 else '0'; + intFrameTxValid(3) <= vcFrameTxValid when vcFrameTxVc = 3 else '0'; + + -- MUX VC ready + vcFrameTxReady <= intFrameTxReady(0) when vcFrameTxVc = 0 else + intFrameTxReady(1) when vcFrameTxVc = 1 else + intFrameTxReady(2) when vcFrameTxVc = 2 else + intFrameTxReady(3) when vcFrameTxVc = 3 else '0'; + + -- Encode VC + currVc <= "00" when intFrameRxValid(0) = '1' else + "01" when intFrameRxValid(1) = '1' else + "10" when intFrameRxValid(2) = '1' else + "11"; + + -- Error Counters + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + intCntCellError <= (others=>'0') after tpd; + intCntLinkDown <= (others=>'0') after tpd; + intCntLinkError <= (others=>'0') after tpd; + intCntRx <= (others=>'0') after tpd; + elsif rising_edge(pgpClk) then + + -- Cell error counter + if cntReset = '1' then + intCntCellError <= (others=>'0') after tpd; + elsif pgpRxCellError = '1' and intCntCellError /= x"F" then + intCntCellError <= intCntCellError + 1 after tpd; + end if; + + -- Link error counter + if cntReset = '1' then + intCntLinkError <= (others=>'0') after tpd; + elsif pgpRxLinkError = '1' and intCntLinkError /= x"F" then + intCntLinkError <= intCntLinkError + 1 after tpd; + end if; + + -- Link down counter + if cntReset = '1' then + intCntLinkDown <= (others=>'0') after tpd; + elsif pgpRxLinkDown = '1' and intCntLinkDown /= x"F" then + intCntLinkDown <= intCntLinkDown + 1 after tpd; + end if; + + -- Rx Counter + if cntReset = '1' then + intCntRx <= (others=>'0') after tpd; + elsif intFrameRxValid /= 0 and intFrameRxEOF = '1' then + intCntRx <= intCntRx + 1 after tpd; + end if; + + end if; + end process; + + + -- Receive Buffer Writes + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + fifoWrData <= (others=>'0') after tpd; + fifoWrEn <= '0' after tpd; + fifoWrCnt <= "00" after tpd; + vcLocBuffAFull <= '0' after tpd; + vcLocBuffFull <= '0' after tpd; + pgpRxFifoErr <= '0' after tpd; + elsif rising_edge(pgpClk) then + + -- Almost full 1/4 + vcLocBuffAFull <= fifoFull or fifoCount(8) or fifoCount(7) after tpd; + + -- Full 1/2 + vcLocBuffFull <= fifoFull or fifoCount(8) after tpd; + + -- Track write errors + if fifoWrEn = '1' and fifoFull = '1' then + pgpRxFifoErr <= '1' after tpd; + elsif cntReset = '1' then + pgpRxFifoErr <= '0' after tpd; + end if; + + -- Link is down + if intLocLinkReady = '0' then + fifoWrEn <= '0' after tpd; + fifoWrCnt <= "00" after tpd; + + -- FIFO is valid + elsif intFrameRxValid /= 0 then + fifoWrData(68 downto 67) <= fifoWrCnt after tpd; + fifoWrData(66) <= intFrameRxEOFE after tpd; + fifoWrData(65) <= intFrameRxEOF after tpd; + + -- Save SOF + if fifoWrCnt = 0 then + fifoWrData(64) <= intFrameRxSOF after tpd; + end if; + + -- Which word are we on + if ( fifoWrCnt = "00" ) then + fifoWrData(15 downto 8) <= intFrameRxData(15 downto 8) after tpd; + fifoWrData(5 downto 2) <= intFrameRxData(5 downto 2) after tpd; + if intFrameRxSOF = '1' then + fifoWrData(7 downto 6) <= laneNumber after tpd; -- Overwrite Lane number in header + fifoWrData(1 downto 0) <= currVc after tpd; -- Overwrite VC number in header + else + fifoWrData(7 downto 6) <= intFrameRxData(7 downto 6) after tpd; + fifoWrData(1 downto 0) <= intFrameRxData(1 downto 0) after tpd; + end if; + end if; + if ( fifoWrCnt = "01" ) then fifoWrData(31 downto 16) <= intFrameRxData after tpd; end if; + if ( fifoWrCnt = "10" ) then fifoWrData(47 downto 32) <= intFrameRxData after tpd; end if; + if ( fifoWrCnt = "11" ) then fifoWrData(63 downto 48) <= intFrameRxData after tpd; end if; + + -- Reset on EOF + if intFrameRxEOF = '1' then + fifoWrCnt <= "00" after tpd; + else + fifoWrCnt <= fifoWrCnt + 1 after tpd; + end if; + + -- Write on EOF or count of 3 + if intFrameRxEOF = '1' or fifoWrCnt = "11" then + fifoWrEn <= '1' after tpd; + else + fifoWrEn <= '0' after tpd; + end if; + else + fifoWrEn <= '0' after tpd; + end if; + end if; + end process; + + -- FIFO reset + fifoRst <= pgpReset or not intLocLinkReady; + + -- Upstream FIFO, 2 block rams + U_UsFifo: pgp2_v4_fifo_69x512 port map ( + clk => pgpClk, + rst => fifoRst, + din => fifoWrData, + wr_en => fifoWrEn, + rd_en => fifoRdEn, + dout => fifoRdData, + full => fifoFull, + empty => fifoEmpty, + data_count => fifoCount + ); + + -- EOF read/write detect + fifoEofWr <= fifoWrEn and fifoWrData(65); + fifoEofRd <= fifoRdEnDly and fifoRdData(65); + + + -- Read control + process ( pgpClk, pgpReset ) begin + if pgpReset = '1' then + intValid <= '0' after tpd; + fifoRdEnDly <= '0' after tpd; + fifoEofCnt <= (others=>'0') after tpd; + vcFrameRxReq <= '0' after tpd; + elsif rising_edge(pgpClk) then + + -- Read occured + fifoRdEnDly <= fifoRdEn after tpd; + + -- Link is down + if intLocLinkReady = '0' then + fifoEofCnt <= (others=>'0') after tpd; + intValid <= '0' after tpd; + vcFrameRxReq <= '0' after tpd; + else + + -- EOF Counter + if fifoEofWr = '1' and fifoEofRd = '0' then + fifoEofCnt <= fifoEofCnt + 1 after tpd; + elsif fifoEofWr = '0' and fifoEofRd = '1' then + fifoEofCnt <= fifoEofCnt - 1 after tpd; + end if; + + -- Track Valid + if fifoRdEn = '1' then + intValid <= '1' after tpd; + elsif vcFrameRxReady = '1' then + intValid <= '0' after tpd; + end if; + + -- Valid output, EOF is at output or more than 1 EOF in buffer or 127 entries are in buffer + if vcFrameRxReady = '0' and intValid = '1' and + (fifoEofCnt /= 0 or fifoRdData(65) = '1' or fifoCount >= 63) then + vcFrameRxReq <= '1' after tpd; + else + vcFrameRxReq <= '0' after tpd; + end if; + end if; + end if; + end process; + + + -- Control reads + fifoRdEn <= (not fifoEmpty) and ((not intValid) or vcFrameRxReady); + + -- Outgoing signals + vcFrameRxEOFE <= fifoRdData(66); + vcFrameRxEOF <= fifoRdData(65); + vcFrameRxSOF <= fifoRdData(64); + vcFrameRxData <= fifoRdData(63 downto 0); + vcFrameRxValid <= intValid; + vcFrameRxWidth <= fifoRdData(68 downto 67); + + + -- 16-bit wrapper + U_Pgp2Mgt16: Pgp2MgtPackage.Pgp2Mgt16 + --U_Pgp2Mgt16Model: Pgp2TbPackage.Pgp2Mgt16Model -- For Simulation + generic map ( + EnShortCells => 1, + VcInterleave => 1, + MgtMode => MgtMode, + RefClkSel => RefClkSel + ) port map ( + pgpClk => pgpClk, + pgpReset => pgpReset, + pgpFlush => '0', + pllTxRst => pllTxRst, + pllRxRst => pllRxRst, + pllRxReady => pllRxReady, + pllTxReady => pllTxReady, + pgpRemData => open, + pgpLocData => (others=>'0'), + pgpTxOpCodeEn => '0', + pgpTxOpCode => (others=>'0'), + pgpRxOpCodeEn => open, + pgpRxOpCode => open, + pgpLocLinkReady => intLocLinkReady, + pgpRemLinkReady => pgpRemLinkReady, + pgpRxCellError => pgpRxCellError, + pgpRxLinkDown => pgpRxLinkDown, + pgpRxLinkError => pgpRxLinkError, + vc0FrameTxValid => intFrameTxValid(0), + vc0FrameTxReady => intFrameTxReady(0), + vc0FrameTxSOF => vcFrameTxSOF, + vc0FrameTxEOF => vcFrameTxEOF, + vc0FrameTxEOFE => vcFrameTxEOFE, + vc0FrameTxData => vcFrameTxData, + vc0LocBuffAFull => vcLocBuffAFull, + vc0LocBuffFull => vcLocBuffFull, + vc1FrameTxValid => intFrameTxValid(1), + vc1FrameTxReady => intFrameTxReady(1), + vc1FrameTxSOF => vcFrameTxSOF, + vc1FrameTxEOF => vcFrameTxEOF, + vc1FrameTxEOFE => vcFrameTxEOFE, + vc1FrameTxData => vcFrameTxData, + vc1LocBuffAFull => vcLocBuffAFull, + vc1LocBuffFull => vcLocBuffFull, + vc2FrameTxValid => intFrameTxValid(2), + vc2FrameTxReady => intFrameTxReady(2), + vc2FrameTxSOF => vcFrameTxSOF, + vc2FrameTxEOF => vcFrameTxEOF, + vc2FrameTxEOFE => vcFrameTxEOFE, + vc2FrameTxData => vcFrameTxData, + vc2LocBuffAFull => vcLocBuffAFull, + vc2LocBuffFull => vcLocBuffFull, + vc3FrameTxValid => intFrameTxValid(3), + vc3FrameTxReady => intFrameTxReady(3), + vc3FrameTxSOF => vcFrameTxSOF, + vc3FrameTxEOF => vcFrameTxEOF, + vc3FrameTxEOFE => vcFrameTxEOFE, + vc3FrameTxData => vcFrameTxData, + vc3LocBuffAFull => vcLocBuffAFull, + vc3LocBuffFull => vcLocBuffFull, + vcFrameRxSOF => intFrameRxSOF, + vcFrameRxEOF => intFrameRxEOF, + vcFrameRxEOFE => intFrameRxEOFE, + vcFrameRxData => intFrameRxData, + vc0FrameRxValid => intFrameRxValid(0), + vc0RemBuffAFull => vcRemBuffAFull(0), + vc0RemBuffFull => vcRemBuffFull(0), + vc1FrameRxValid => intFrameRxValid(1), + vc1RemBuffAFull => vcRemBuffAFull(1), + vc1RemBuffFull => vcRemBuffFull(1), + vc2FrameRxValid => intFrameRxValid(2), + vc2RemBuffAFull => vcRemBuffAFull(2), + vc2RemBuffFull => vcRemBuffFull(2), + vc3FrameRxValid => intFrameRxValid(3), + vc3RemBuffAFull => vcRemBuffAFull(3), + vc3RemBuffFull => vcRemBuffFull(3), + mgtLoopback => mgtLoopback, + mgtRefClk1 => mgtRefClk1, + mgtRefClk2 => mgtRefClk2, + mgtRxRecClk => open, + mgtRxN => mgtRxN, + mgtRxP => mgtRxP, + mgtTxN => mgtTxN, + mgtTxP => mgtTxP, + mgtCombusIn => mgtCombusIn, + mgtCombusOut => mgtCombusOut, + debug => debug + ); + +end Pgp2RceLane; + diff --git a/rce/fw-hsio/modules/pgp2/hdl/rce/Pgp2RcePackage.vhd b/rce/fw-hsio/modules/pgp2/hdl/rce/Pgp2RcePackage.vhd new file mode 100755 index 00000000..676de005 --- /dev/null +++ b/rce/fw-hsio/modules/pgp2/hdl/rce/Pgp2RcePackage.vhd @@ -0,0 +1,196 @@ +------------------------------------------------------------------------------- +-- Title : Pretty Good Protocol, RCE Package +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : Pgp2RcePackage.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 11/23/2009 +------------------------------------------------------------------------------- +-- Description: +-- Application Components package. +------------------------------------------------------------------------------- +-- Copyright (c) 2006 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 11/23/2009: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; + +package Pgp2RcePackage is + + -- PGP Lane + component Pgp2RceLane + generic ( + MgtMode : string := "A"; + RefClkSel : string := "REFCLK1" + ); port ( + pgpClk : in std_logic; + pgpReset : in std_logic; + pllTxRst : in std_logic; + pllRxRst : in std_logic; + pllRxReady : out std_logic; + pllTxReady : out std_logic; + pgpLocLinkReady : out std_logic; + pgpRemLinkReady : out std_logic; + cntReset : in std_logic; + pgpCntCellError : out std_logic_vector(3 downto 0); + pgpCntLinkDown : out std_logic_vector(3 downto 0); + pgpCntLinkError : out std_logic_vector(3 downto 0); + pgpRxFifoErr : out std_logic; + pgpRxCnt : out std_logic_vector(3 downto 0); + laneNumber : in std_logic_vector(1 downto 0); + vcFrameRxSOF : out std_logic; + vcFrameRxEOF : out std_logic; + vcFrameRxEOFE : out std_logic; + vcFrameRxData : out std_logic_vector(63 downto 0); + vcFrameRxReq : out std_logic; + vcFrameRxValid : out std_logic; + vcFrameRxReady : in std_logic; + vcFrameRxWidth : out std_logic_vector(1 downto 0); + vcFrameTxVc : in std_logic_vector(1 downto 0); + vcFrameTxValid : in std_logic; + vcFrameTxReady : out std_logic; + vcFrameTxSOF : in std_logic; + vcFrameTxEOF : in std_logic; + vcFrameTxEOFE : in std_logic; + vcFrameTxData : in std_logic_vector(15 downto 0); + vcRemBuffAFull : out std_logic_vector(3 downto 0); + vcRemBuffFull : out std_logic_vector(3 downto 0); + mgtLoopback : in std_logic; + mgtRefClk1 : in std_logic; + mgtRefClk2 : in std_logic; + mgtRxN : in std_logic; + mgtRxP : in std_logic; + mgtTxN : out std_logic; + mgtTxP : out std_logic; + mgtCombusIn : in std_logic_vector(15 downto 0); + mgtCombusOut : out std_logic_vector(15 downto 0); + debug : out std_logic_vector(63 downto 0) + ); + end component; + + -- RCE Export Block + component Pgp2RceExport + port ( + pgpClk : in std_logic; + pgpReset : in std_logic; + Export_Clock : out std_logic; + Export_Core_Reset : in std_logic; + Export_Data_Available : in std_logic; + Export_Data_Start : in std_logic; + Export_Advance_Data_Pipeline : out std_logic; + Export_Data_Last_Line : in std_logic; + Export_Data_Last_Valid_Byte : in std_logic_vector(2 downto 0); + Export_Data : in std_logic_vector(63 downto 0); + Export_Advance_Status_Pipeline : out std_logic; + Export_Status : out std_logic_vector(31 downto 0); + Export_Status_Full : in std_logic; + pgpRemLinkReady : in std_logic_vector(3 downto 0); + vcFrameTxVc : out std_logic_vector(1 downto 0); + vcFrameTxSOF : out std_logic; + vcFrameTxEOF : out std_logic; + vcFrameTxEOFE : out std_logic; + vcFrameTxData : out std_logic_vector(15 downto 0); + vcFrameTxValid : out std_logic_vector(3 downto 0); + vcFrameTxReady : in std_logic_vector(3 downto 0); + vcRemBuffAFull : in std_logic_vector(15 downto 0); + vcRemBuffFull : in std_logic_vector(15 downto 0); + bigEndian : in std_logic; + debug : out std_logic_vector(63 downto 0) + ); + end component; + + -- RCE Import Block + component Pgp2RceImport + generic ( + FreeListA : natural := 1; + FreeListB : natural := 2; + FreeListC : natural := 3; + FreeListD : natural := 4; + PayloadCntTop : integer := 7 + ); + port ( + pgpClk : in std_logic; + pgpReset : in std_logic; + Import_Clock : out std_logic; + Import_Core_Reset : in std_logic; + Import_Free_List : out std_logic_vector( 3 downto 0); + Import_Advance_Data_Pipeline : out std_logic; + Import_Data_Last_Line : out std_logic; + Import_Data_Last_Valid_Byte : out std_logic_vector( 2 downto 0); + Import_Data : out std_logic_vector(63 downto 0); + Import_Data_Pipeline_Full : in std_logic; + Import_Pause : in std_logic; + pgpLocLinkReady : in std_logic_vector(3 downto 0); + vcFrameRxSOF : in std_logic_vector(3 downto 0); + vcFrameRxEOF : in std_logic_vector(3 downto 0); + vcFrameRxEOFE : in std_logic_vector(3 downto 0); + vcFrameRxDataA : in std_logic_vector(63 downto 0); + vcFrameRxDataB : in std_logic_vector(63 downto 0); + vcFrameRxDataC : in std_logic_vector(63 downto 0); + vcFrameRxDataD : in std_logic_vector(63 downto 0); + vcFrameRxReq : in std_logic_vector(3 downto 0); + vcFrameRxValid : in std_logic_vector(3 downto 0); + vcFrameRxReady : out std_logic_vector(3 downto 0); + vcFrameRxWidthA : in std_logic_vector(1 downto 0); + vcFrameRxWidthB : in std_logic_vector(1 downto 0); + vcFrameRxWidthC : in std_logic_vector(1 downto 0); + vcFrameRxWidthD : in std_logic_vector(1 downto 0); + bigEndian : in std_logic; + debug : out std_logic_vector(63 downto 0) + ); + end component; + + + -- RCE Wrapper + component Pgp2Rce + generic ( + FreeListA : natural := 1; + FreeListB : natural := 2; + FreeListC : natural := 3; + FreeListD : natural := 4; + RefClkSel : string := "REFCLK1"; + PgpLaneCnt : natural := 4 + ); + port ( + Import_Clock : out std_logic; + Import_Core_Reset : in std_logic; + Import_Free_List : out std_logic_vector( 3 downto 0); + Import_Advance_Data_Pipeline : out std_logic; + Import_Data_Last_Line : out std_logic; + Import_Data_Last_Valid_Byte : out std_logic_vector( 2 downto 0); + Import_Data : out std_logic_vector(63 downto 0); + Import_Data_Pipeline_Full : in std_logic; + Import_Pause : in std_logic; + Export_Clock : out std_logic; + Export_Core_Reset : in std_logic; + Export_Data_Available : in std_logic; + Export_Data_Start : in std_logic; + Export_Advance_Data_Pipeline : out std_logic; + Export_Data_Last_Line : in std_logic; + Export_Data_Last_Valid_Byte : in std_logic_vector( 2 downto 0); + Export_Data : in std_logic_vector(63 downto 0); + Export_Advance_Status_Pipeline : out std_logic; + Export_Status : out std_logic_vector(31 downto 0); + Export_Status_Full : in std_logic; + Dcr_Clock : in std_logic; + Dcr_Write : in std_logic; + Dcr_Write_Data : in std_logic_vector(31 downto 0); + Dcr_Read_Address : in std_logic_vector( 1 downto 0); + Dcr_Read_Data : out std_logic_vector(31 downto 0); + pgpRefClk1 : in std_logic; + pgpRefClk2 : in std_logic; + pgpClk : in std_logic; + pgpReset : in std_logic; + mgtRxN : in std_logic_vector(PgpLaneCnt-1 downto 0); + mgtRxP : in std_logic_vector(PgpLaneCnt-1 downto 0); + mgtTxN : out std_logic_vector(PgpLaneCnt-1 downto 0); + mgtTxP : out std_logic_vector(PgpLaneCnt-1 downto 0) + ); + end component; + + +end Pgp2RcePackage; + diff --git a/rce/fw-hsio/modules/pixelcore/coregen/data24bitfifo4096.xco b/rce/fw-hsio/modules/pixelcore/coregen/data24bitfifo4096.xco new file mode 100644 index 00000000..d4f3988b --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/coregen/data24bitfifo4096.xco @@ -0,0 +1,213 @@ +############################################################## +# +# Xilinx Core Generator version 14.6 +# Date: Wed Jan 14 15:48:02 2015 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# Generated from component: xilinx.com:ip:fifo_generator:9.3 +# +############################################################## +# +# BEGIN Project Options +SET addpads = false +SET asysymbol = false +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = false +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = false +SET foundationsym = false +SET implementationfiletype = Ngc +SET package = ff1152 +SET removerpms = false +SET simulationfiles = Behavioral +SET speedgrade = -11 +SET verilogsim = false +SET vhdlsim = true +# END Project Options +# BEGIN Select +SELECT FIFO_Generator xilinx.com:ip:fifo_generator:9.3 +# END Select +# BEGIN Parameters +CSET add_ngc_constraint_axi=false +CSET almost_empty_flag=true +CSET almost_full_flag=false +CSET aruser_width=1 +CSET awuser_width=1 +CSET axi_address_width=32 +CSET axi_data_width=64 +CSET axi_type=AXI4_Stream +CSET axis_type=FIFO +CSET buser_width=1 +CSET clock_enable_type=Slave_Interface_Clock_Enable +CSET clock_type_axi=Common_Clock +CSET component_name=data24bitfifo4096 +CSET data_count=false +CSET data_count_width=12 +CSET disable_timing_violations=false +CSET disable_timing_violations_axi=false +CSET dout_reset_value=0 +CSET empty_threshold_assert_value=4 +CSET empty_threshold_assert_value_axis=1022 +CSET empty_threshold_assert_value_rach=1022 +CSET empty_threshold_assert_value_rdch=1022 +CSET empty_threshold_assert_value_wach=1022 +CSET empty_threshold_assert_value_wdch=1022 +CSET empty_threshold_assert_value_wrch=1022 +CSET empty_threshold_negate_value=5 +CSET enable_aruser=false +CSET enable_awuser=false +CSET enable_buser=false +CSET enable_common_overflow=false +CSET enable_common_underflow=false +CSET enable_data_counts_axis=false +CSET enable_data_counts_rach=false +CSET enable_data_counts_rdch=false +CSET enable_data_counts_wach=false +CSET enable_data_counts_wdch=false +CSET enable_data_counts_wrch=false +CSET enable_ecc=false +CSET enable_ecc_axis=false +CSET enable_ecc_rach=false +CSET enable_ecc_rdch=false +CSET enable_ecc_wach=false +CSET enable_ecc_wdch=false +CSET enable_ecc_wrch=false +CSET enable_read_channel=false +CSET enable_read_pointer_increment_by2=false +CSET enable_reset_synchronization=true +CSET enable_ruser=false +CSET enable_tdata=false +CSET enable_tdest=false +CSET enable_tid=false +CSET enable_tkeep=false +CSET enable_tlast=false +CSET enable_tready=true +CSET enable_tstrobe=false +CSET enable_tuser=false +CSET enable_write_channel=false +CSET enable_wuser=false +CSET fifo_application_type_axis=Data_FIFO +CSET fifo_application_type_rach=Data_FIFO +CSET fifo_application_type_rdch=Data_FIFO +CSET fifo_application_type_wach=Data_FIFO +CSET fifo_application_type_wdch=Data_FIFO +CSET fifo_application_type_wrch=Data_FIFO +CSET fifo_implementation=Independent_Clocks_Block_RAM +CSET fifo_implementation_axis=Common_Clock_Block_RAM +CSET fifo_implementation_rach=Common_Clock_Block_RAM +CSET fifo_implementation_rdch=Common_Clock_Block_RAM +CSET fifo_implementation_wach=Common_Clock_Block_RAM +CSET fifo_implementation_wdch=Common_Clock_Block_RAM +CSET fifo_implementation_wrch=Common_Clock_Block_RAM +CSET full_flags_reset_value=1 +CSET full_threshold_assert_value=3300 +CSET full_threshold_assert_value_axis=1023 +CSET full_threshold_assert_value_rach=1023 +CSET full_threshold_assert_value_rdch=1023 +CSET full_threshold_assert_value_wach=1023 +CSET full_threshold_assert_value_wdch=1023 +CSET full_threshold_assert_value_wrch=1023 +CSET full_threshold_negate_value=3299 +CSET id_width=4 +CSET inject_dbit_error=false +CSET inject_dbit_error_axis=false +CSET inject_dbit_error_rach=false +CSET inject_dbit_error_rdch=false +CSET inject_dbit_error_wach=false +CSET inject_dbit_error_wdch=false +CSET inject_dbit_error_wrch=false +CSET inject_sbit_error=false +CSET inject_sbit_error_axis=false +CSET inject_sbit_error_rach=false +CSET inject_sbit_error_rdch=false +CSET inject_sbit_error_wach=false +CSET inject_sbit_error_wdch=false +CSET inject_sbit_error_wrch=false +CSET input_data_width=25 +CSET input_depth=4096 +CSET input_depth_axis=1024 +CSET input_depth_rach=16 +CSET input_depth_rdch=1024 +CSET input_depth_wach=16 +CSET input_depth_wdch=1024 +CSET input_depth_wrch=16 +CSET interface_type=Native +CSET output_data_width=25 +CSET output_depth=4096 +CSET overflow_flag=true +CSET overflow_flag_axi=false +CSET overflow_sense=Active_High +CSET overflow_sense_axi=Active_High +CSET performance_options=First_Word_Fall_Through +CSET programmable_empty_type=No_Programmable_Empty_Threshold +CSET programmable_empty_type_axis=No_Programmable_Empty_Threshold +CSET programmable_empty_type_rach=No_Programmable_Empty_Threshold +CSET programmable_empty_type_rdch=No_Programmable_Empty_Threshold +CSET programmable_empty_type_wach=No_Programmable_Empty_Threshold +CSET programmable_empty_type_wdch=No_Programmable_Empty_Threshold +CSET programmable_empty_type_wrch=No_Programmable_Empty_Threshold +CSET programmable_full_type=Single_Programmable_Full_Threshold_Constant +CSET programmable_full_type_axis=No_Programmable_Full_Threshold +CSET programmable_full_type_rach=No_Programmable_Full_Threshold +CSET programmable_full_type_rdch=No_Programmable_Full_Threshold +CSET programmable_full_type_wach=No_Programmable_Full_Threshold +CSET programmable_full_type_wdch=No_Programmable_Full_Threshold +CSET programmable_full_type_wrch=No_Programmable_Full_Threshold +CSET rach_type=FIFO +CSET rdch_type=FIFO +CSET read_clock_frequency=1 +CSET read_data_count=false +CSET read_data_count_width=12 +CSET register_slice_mode_axis=Fully_Registered +CSET register_slice_mode_rach=Fully_Registered +CSET register_slice_mode_rdch=Fully_Registered +CSET register_slice_mode_wach=Fully_Registered +CSET register_slice_mode_wdch=Fully_Registered +CSET register_slice_mode_wrch=Fully_Registered +CSET reset_pin=true +CSET reset_type=Asynchronous_Reset +CSET ruser_width=1 +CSET synchronization_stages=2 +CSET synchronization_stages_axi=2 +CSET tdata_width=64 +CSET tdest_width=4 +CSET tid_width=8 +CSET tkeep_width=4 +CSET tstrb_width=4 +CSET tuser_width=4 +CSET underflow_flag=true +CSET underflow_flag_axi=false +CSET underflow_sense=Active_High +CSET underflow_sense_axi=Active_High +CSET use_clock_enable=false +CSET use_dout_reset=true +CSET use_embedded_registers=false +CSET use_extra_logic=false +CSET valid_flag=true +CSET valid_sense=Active_High +CSET wach_type=FIFO +CSET wdch_type=FIFO +CSET wrch_type=FIFO +CSET write_acknowledge_flag=false +CSET write_acknowledge_sense=Active_High +CSET write_clock_frequency=1 +CSET write_data_count=false +CSET write_data_count_width=12 +CSET wuser_width=1 +# END Parameters +# BEGIN Extra information +MISC pkg_timestamp=2012-11-19T12:39:56Z +# END Extra information +GENERATE +# CRC: 2c9b652f diff --git a/rce/fw-hsio/modules/pixelcore/coregen/data24bitfifo8192.xco b/rce/fw-hsio/modules/pixelcore/coregen/data24bitfifo8192.xco new file mode 100644 index 00000000..53fc3cea --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/coregen/data24bitfifo8192.xco @@ -0,0 +1,213 @@ +############################################################## +# +# Xilinx Core Generator version 14.6 +# Date: Fri Jan 9 16:39:38 2015 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# Generated from component: xilinx.com:ip:fifo_generator:9.3 +# +############################################################## +# +# BEGIN Project Options +SET addpads = false +SET asysymbol = false +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = false +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = false +SET foundationsym = false +SET implementationfiletype = Ngc +SET package = ff1152 +SET removerpms = false +SET simulationfiles = Behavioral +SET speedgrade = -11 +SET verilogsim = false +SET vhdlsim = true +# END Project Options +# BEGIN Select +SELECT FIFO_Generator xilinx.com:ip:fifo_generator:9.3 +# END Select +# BEGIN Parameters +CSET add_ngc_constraint_axi=false +CSET almost_empty_flag=true +CSET almost_full_flag=false +CSET aruser_width=1 +CSET awuser_width=1 +CSET axi_address_width=32 +CSET axi_data_width=64 +CSET axi_type=AXI4_Stream +CSET axis_type=FIFO +CSET buser_width=1 +CSET clock_enable_type=Slave_Interface_Clock_Enable +CSET clock_type_axi=Common_Clock +CSET component_name=data24bitfifo8192 +CSET data_count=false +CSET data_count_width=13 +CSET disable_timing_violations=false +CSET disable_timing_violations_axi=false +CSET dout_reset_value=0 +CSET empty_threshold_assert_value=4 +CSET empty_threshold_assert_value_axis=1022 +CSET empty_threshold_assert_value_rach=1022 +CSET empty_threshold_assert_value_rdch=1022 +CSET empty_threshold_assert_value_wach=1022 +CSET empty_threshold_assert_value_wdch=1022 +CSET empty_threshold_assert_value_wrch=1022 +CSET empty_threshold_negate_value=5 +CSET enable_aruser=false +CSET enable_awuser=false +CSET enable_buser=false +CSET enable_common_overflow=false +CSET enable_common_underflow=false +CSET enable_data_counts_axis=false +CSET enable_data_counts_rach=false +CSET enable_data_counts_rdch=false +CSET enable_data_counts_wach=false +CSET enable_data_counts_wdch=false +CSET enable_data_counts_wrch=false +CSET enable_ecc=false +CSET enable_ecc_axis=false +CSET enable_ecc_rach=false +CSET enable_ecc_rdch=false +CSET enable_ecc_wach=false +CSET enable_ecc_wdch=false +CSET enable_ecc_wrch=false +CSET enable_read_channel=false +CSET enable_read_pointer_increment_by2=false +CSET enable_reset_synchronization=true +CSET enable_ruser=false +CSET enable_tdata=false +CSET enable_tdest=false +CSET enable_tid=false +CSET enable_tkeep=false +CSET enable_tlast=false +CSET enable_tready=true +CSET enable_tstrobe=false +CSET enable_tuser=false +CSET enable_write_channel=false +CSET enable_wuser=false +CSET fifo_application_type_axis=Data_FIFO +CSET fifo_application_type_rach=Data_FIFO +CSET fifo_application_type_rdch=Data_FIFO +CSET fifo_application_type_wach=Data_FIFO +CSET fifo_application_type_wdch=Data_FIFO +CSET fifo_application_type_wrch=Data_FIFO +CSET fifo_implementation=Independent_Clocks_Block_RAM +CSET fifo_implementation_axis=Common_Clock_Block_RAM +CSET fifo_implementation_rach=Common_Clock_Block_RAM +CSET fifo_implementation_rdch=Common_Clock_Block_RAM +CSET fifo_implementation_wach=Common_Clock_Block_RAM +CSET fifo_implementation_wdch=Common_Clock_Block_RAM +CSET fifo_implementation_wrch=Common_Clock_Block_RAM +CSET full_flags_reset_value=1 +CSET full_threshold_assert_value=6122 +CSET full_threshold_assert_value_axis=1023 +CSET full_threshold_assert_value_rach=1023 +CSET full_threshold_assert_value_rdch=1023 +CSET full_threshold_assert_value_wach=1023 +CSET full_threshold_assert_value_wdch=1023 +CSET full_threshold_assert_value_wrch=1023 +CSET full_threshold_negate_value=6121 +CSET id_width=4 +CSET inject_dbit_error=false +CSET inject_dbit_error_axis=false +CSET inject_dbit_error_rach=false +CSET inject_dbit_error_rdch=false +CSET inject_dbit_error_wach=false +CSET inject_dbit_error_wdch=false +CSET inject_dbit_error_wrch=false +CSET inject_sbit_error=false +CSET inject_sbit_error_axis=false +CSET inject_sbit_error_rach=false +CSET inject_sbit_error_rdch=false +CSET inject_sbit_error_wach=false +CSET inject_sbit_error_wdch=false +CSET inject_sbit_error_wrch=false +CSET input_data_width=25 +CSET input_depth=8192 +CSET input_depth_axis=1024 +CSET input_depth_rach=16 +CSET input_depth_rdch=1024 +CSET input_depth_wach=16 +CSET input_depth_wdch=1024 +CSET input_depth_wrch=16 +CSET interface_type=Native +CSET output_data_width=25 +CSET output_depth=8192 +CSET overflow_flag=true +CSET overflow_flag_axi=false +CSET overflow_sense=Active_High +CSET overflow_sense_axi=Active_High +CSET performance_options=First_Word_Fall_Through +CSET programmable_empty_type=No_Programmable_Empty_Threshold +CSET programmable_empty_type_axis=No_Programmable_Empty_Threshold +CSET programmable_empty_type_rach=No_Programmable_Empty_Threshold +CSET programmable_empty_type_rdch=No_Programmable_Empty_Threshold +CSET programmable_empty_type_wach=No_Programmable_Empty_Threshold +CSET programmable_empty_type_wdch=No_Programmable_Empty_Threshold +CSET programmable_empty_type_wrch=No_Programmable_Empty_Threshold +CSET programmable_full_type=Single_Programmable_Full_Threshold_Constant +CSET programmable_full_type_axis=No_Programmable_Full_Threshold +CSET programmable_full_type_rach=No_Programmable_Full_Threshold +CSET programmable_full_type_rdch=No_Programmable_Full_Threshold +CSET programmable_full_type_wach=No_Programmable_Full_Threshold +CSET programmable_full_type_wdch=No_Programmable_Full_Threshold +CSET programmable_full_type_wrch=No_Programmable_Full_Threshold +CSET rach_type=FIFO +CSET rdch_type=FIFO +CSET read_clock_frequency=1 +CSET read_data_count=false +CSET read_data_count_width=13 +CSET register_slice_mode_axis=Fully_Registered +CSET register_slice_mode_rach=Fully_Registered +CSET register_slice_mode_rdch=Fully_Registered +CSET register_slice_mode_wach=Fully_Registered +CSET register_slice_mode_wdch=Fully_Registered +CSET register_slice_mode_wrch=Fully_Registered +CSET reset_pin=true +CSET reset_type=Asynchronous_Reset +CSET ruser_width=1 +CSET synchronization_stages=2 +CSET synchronization_stages_axi=2 +CSET tdata_width=64 +CSET tdest_width=4 +CSET tid_width=8 +CSET tkeep_width=4 +CSET tstrb_width=4 +CSET tuser_width=4 +CSET underflow_flag=true +CSET underflow_flag_axi=false +CSET underflow_sense=Active_High +CSET underflow_sense_axi=Active_High +CSET use_clock_enable=false +CSET use_dout_reset=true +CSET use_embedded_registers=false +CSET use_extra_logic=false +CSET valid_flag=true +CSET valid_sense=Active_High +CSET wach_type=FIFO +CSET wdch_type=FIFO +CSET wrch_type=FIFO +CSET write_acknowledge_flag=false +CSET write_acknowledge_sense=Active_High +CSET write_clock_frequency=1 +CSET write_data_count=false +CSET write_data_count_width=13 +CSET wuser_width=1 +# END Parameters +# BEGIN Extra information +MISC pkg_timestamp=2012-11-19T12:39:56Z +# END Extra information +GENERATE +# CRC: a10a793a diff --git a/rce/fw-hsio/modules/pixelcore/coregen/datafifo1024.xco b/rce/fw-hsio/modules/pixelcore/coregen/datafifo1024.xco new file mode 100644 index 00000000..55a09724 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/coregen/datafifo1024.xco @@ -0,0 +1,203 @@ +############################################################## +# +# Xilinx Core Generator version 12.4 +# Date: Mon Sep 12 21:53:03 2011 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# BEGIN Project Options +SET addpads = false +SET asysymbol = false +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = false +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = false +SET foundationsym = false +SET implementationfiletype = Ngc +SET package = ff1152 +SET removerpms = false +SET simulationfiles = Behavioral +SET speedgrade = -11 +SET verilogsim = false +SET vhdlsim = true +# END Project Options +# BEGIN Select +SELECT Fifo_Generator family Xilinx,_Inc. 7.2 +# END Select +# BEGIN Parameters +CSET add_ngc_constraint_axi=false +CSET almost_empty_flag=false +CSET almost_full_flag=false +CSET aruser_width=1 +CSET awuser_width=1 +CSET axi_address_width=32 +CSET axi_data_width=64 +CSET axi_type=AXI4_Stream +CSET axis_type=FIFO +CSET buser_width=1 +CSET clock_enable_type=Slave_Interface_Clock_Enable +CSET clock_type_axi=Common_Clock +CSET component_name=datafifo1024 +CSET data_count=false +CSET data_count_width=10 +CSET disable_timing_violations=false +CSET disable_timing_violations_axi=false +CSET dout_reset_value=0 +CSET empty_threshold_assert_value=2 +CSET empty_threshold_assert_value_axis=1022 +CSET empty_threshold_assert_value_rach=1022 +CSET empty_threshold_assert_value_rdch=1022 +CSET empty_threshold_assert_value_wach=1022 +CSET empty_threshold_assert_value_wdch=1022 +CSET empty_threshold_assert_value_wrch=1022 +CSET empty_threshold_negate_value=3 +CSET enable_aruser=false +CSET enable_awuser=false +CSET enable_buser=false +CSET enable_common_overflow=false +CSET enable_common_underflow=false +CSET enable_data_counts_axis=false +CSET enable_data_counts_rach=false +CSET enable_data_counts_rdch=false +CSET enable_data_counts_wach=false +CSET enable_data_counts_wdch=false +CSET enable_data_counts_wrch=false +CSET enable_ecc=false +CSET enable_ecc_axis=false +CSET enable_ecc_rach=false +CSET enable_ecc_rdch=false +CSET enable_ecc_wach=false +CSET enable_ecc_wdch=false +CSET enable_ecc_wrch=false +CSET enable_handshake_flag_options_axis=false +CSET enable_handshake_flag_options_rach=false +CSET enable_handshake_flag_options_rdch=false +CSET enable_handshake_flag_options_wach=false +CSET enable_handshake_flag_options_wdch=false +CSET enable_handshake_flag_options_wrch=false +CSET enable_read_channel=false +CSET enable_reset_synchronization=true +CSET enable_ruser=false +CSET enable_tdata=false +CSET enable_tdest=false +CSET enable_tid=false +CSET enable_tkeep=false +CSET enable_tlast=false +CSET enable_tready=true +CSET enable_tstrobe=false +CSET enable_tuser=false +CSET enable_write_channel=false +CSET enable_wuser=false +CSET fifo_application_type_axis=Data_FIFO +CSET fifo_application_type_rach=Data_FIFO +CSET fifo_application_type_rdch=Data_FIFO +CSET fifo_application_type_wach=Data_FIFO +CSET fifo_application_type_wdch=Data_FIFO +CSET fifo_application_type_wrch=Data_FIFO +CSET fifo_implementation=Independent_Clocks_Block_RAM +CSET fifo_implementation_axis=Common_Clock_Block_RAM +CSET fifo_implementation_rach=Common_Clock_Block_RAM +CSET fifo_implementation_rdch=Common_Clock_Block_RAM +CSET fifo_implementation_wach=Common_Clock_Block_RAM +CSET fifo_implementation_wdch=Common_Clock_Block_RAM +CSET fifo_implementation_wrch=Common_Clock_Block_RAM +CSET full_flags_reset_value=1 +CSET full_threshold_assert_value=800 +CSET full_threshold_assert_value_axis=1023 +CSET full_threshold_assert_value_rach=1023 +CSET full_threshold_assert_value_rdch=1023 +CSET full_threshold_assert_value_wach=1023 +CSET full_threshold_assert_value_wdch=1023 +CSET full_threshold_assert_value_wrch=1023 +CSET full_threshold_negate_value=799 +CSET id_width=4 +CSET inject_dbit_error=false +CSET inject_dbit_error_axis=false +CSET inject_dbit_error_rach=false +CSET inject_dbit_error_rdch=false +CSET inject_dbit_error_wach=false +CSET inject_dbit_error_wdch=false +CSET inject_dbit_error_wrch=false +CSET inject_sbit_error=false +CSET inject_sbit_error_axis=false +CSET inject_sbit_error_rach=false +CSET inject_sbit_error_rdch=false +CSET inject_sbit_error_wach=false +CSET inject_sbit_error_wdch=false +CSET inject_sbit_error_wrch=false +CSET input_data_width=18 +CSET input_depth=1024 +CSET input_depth_axis=1024 +CSET input_depth_rach=16 +CSET input_depth_rdch=1024 +CSET input_depth_wach=16 +CSET input_depth_wdch=1024 +CSET input_depth_wrch=16 +CSET interface_type=Native +CSET output_data_width=18 +CSET output_depth=1024 +CSET overflow_flag=true +CSET overflow_flag_axi=false +CSET overflow_sense=Active_High +CSET overflow_sense_axi=Active_High +CSET performance_options=Standard_FIFO +CSET programmable_empty_type=No_Programmable_Empty_Threshold +CSET programmable_empty_type_axis=Empty +CSET programmable_empty_type_rach=Empty +CSET programmable_empty_type_rdch=Empty +CSET programmable_empty_type_wach=Empty +CSET programmable_empty_type_wdch=Empty +CSET programmable_empty_type_wrch=Empty +CSET programmable_full_type=Single_Programmable_Full_Threshold_Constant +CSET programmable_full_type_axis=Full +CSET programmable_full_type_rach=Full +CSET programmable_full_type_rdch=Full +CSET programmable_full_type_wach=Full +CSET programmable_full_type_wdch=Full +CSET programmable_full_type_wrch=Full +CSET rach_type=FIFO +CSET rdch_type=FIFO +CSET read_clock_frequency=1 +CSET read_data_count=false +CSET read_data_count_width=10 +CSET reset_pin=true +CSET reset_type=Asynchronous_Reset +CSET ruser_width=1 +CSET tdata_width=64 +CSET tdest_width=4 +CSET tid_width=8 +CSET tkeep_width=4 +CSET tstrb_width=4 +CSET tuser_width=4 +CSET underflow_flag=true +CSET underflow_flag_axi=false +CSET underflow_sense=Active_High +CSET underflow_sense_axi=Active_High +CSET use_clock_enable=false +CSET use_dout_reset=true +CSET use_embedded_registers=false +CSET use_extra_logic=false +CSET valid_flag=true +CSET valid_sense=Active_High +CSET wach_type=FIFO +CSET wdch_type=FIFO +CSET wrch_type=FIFO +CSET write_acknowledge_flag=false +CSET write_acknowledge_sense=Active_High +CSET write_clock_frequency=1 +CSET write_data_count=false +CSET write_data_count_width=10 +CSET wuser_width=1 +# END Parameters +GENERATE +# CRC: 9d592f8b diff --git a/rce/fw-hsio/modules/pixelcore/coregen/datafifo131072.xco b/rce/fw-hsio/modules/pixelcore/coregen/datafifo131072.xco new file mode 100644 index 00000000..afd476aa --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/coregen/datafifo131072.xco @@ -0,0 +1,219 @@ +############################################################## +# +# Xilinx Core Generator version 13.4 +# Date: Fri Aug 24 21:57:54 2012 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# Generated from component: xilinx.com:ip:fifo_generator:8.4 +# +############################################################## +# +# BEGIN Project Options +SET addpads = false +SET asysymbol = false +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = false +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = false +SET foundationsym = false +SET implementationfiletype = Ngc +SET package = ff1152 +SET removerpms = false +SET simulationfiles = Behavioral +SET speedgrade = -11 +SET verilogsim = false +SET vhdlsim = true +# END Project Options +# BEGIN Select +SELECT Fifo_Generator xilinx.com:ip:fifo_generator:8.4 +# END Select +# BEGIN Parameters +CSET add_ngc_constraint_axi=false +CSET almost_empty_flag=false +CSET almost_full_flag=false +CSET aruser_width=1 +CSET awuser_width=1 +CSET axi_address_width=32 +CSET axi_data_width=64 +CSET axi_type=AXI4_Stream +CSET axis_type=FIFO +CSET buser_width=1 +CSET clock_enable_type=Slave_Interface_Clock_Enable +CSET clock_type_axi=Common_Clock +CSET component_name=datafifo131072 +CSET data_count=false +CSET data_count_width=17 +CSET disable_timing_violations=false +CSET disable_timing_violations_axi=false +CSET dout_reset_value=0 +CSET empty_threshold_assert_value=2 +CSET empty_threshold_assert_value_axis=1022 +CSET empty_threshold_assert_value_rach=1022 +CSET empty_threshold_assert_value_rdch=1022 +CSET empty_threshold_assert_value_wach=1022 +CSET empty_threshold_assert_value_wdch=1022 +CSET empty_threshold_assert_value_wrch=1022 +CSET empty_threshold_negate_value=3 +CSET enable_aruser=false +CSET enable_awuser=false +CSET enable_buser=false +CSET enable_common_overflow=false +CSET enable_common_underflow=false +CSET enable_data_counts_axis=false +CSET enable_data_counts_rach=false +CSET enable_data_counts_rdch=false +CSET enable_data_counts_wach=false +CSET enable_data_counts_wdch=false +CSET enable_data_counts_wrch=false +CSET enable_ecc=false +CSET enable_ecc_axis=false +CSET enable_ecc_rach=false +CSET enable_ecc_rdch=false +CSET enable_ecc_wach=false +CSET enable_ecc_wdch=false +CSET enable_ecc_wrch=false +CSET enable_handshake_flag_options_axis=false +CSET enable_handshake_flag_options_rach=false +CSET enable_handshake_flag_options_rdch=false +CSET enable_handshake_flag_options_wach=false +CSET enable_handshake_flag_options_wdch=false +CSET enable_handshake_flag_options_wrch=false +CSET enable_read_channel=false +CSET enable_read_pointer_increment_by2=false +CSET enable_reset_synchronization=true +CSET enable_ruser=false +CSET enable_tdata=false +CSET enable_tdest=false +CSET enable_tid=false +CSET enable_tkeep=false +CSET enable_tlast=false +CSET enable_tready=true +CSET enable_tstrobe=false +CSET enable_tuser=false +CSET enable_write_channel=false +CSET enable_wuser=false +CSET fifo_application_type_axis=Data_FIFO +CSET fifo_application_type_rach=Data_FIFO +CSET fifo_application_type_rdch=Data_FIFO +CSET fifo_application_type_wach=Data_FIFO +CSET fifo_application_type_wdch=Data_FIFO +CSET fifo_application_type_wrch=Data_FIFO +CSET fifo_implementation=Independent_Clocks_Block_RAM +CSET fifo_implementation_axis=Common_Clock_Block_RAM +CSET fifo_implementation_rach=Common_Clock_Block_RAM +CSET fifo_implementation_rdch=Common_Clock_Block_RAM +CSET fifo_implementation_wach=Common_Clock_Block_RAM +CSET fifo_implementation_wdch=Common_Clock_Block_RAM +CSET fifo_implementation_wrch=Common_Clock_Block_RAM +CSET full_flags_reset_value=1 +CSET full_threshold_assert_value=125000 +CSET full_threshold_assert_value_axis=1023 +CSET full_threshold_assert_value_rach=1023 +CSET full_threshold_assert_value_rdch=1023 +CSET full_threshold_assert_value_wach=1023 +CSET full_threshold_assert_value_wdch=1023 +CSET full_threshold_assert_value_wrch=1023 +CSET full_threshold_negate_value=124999 +CSET id_width=4 +CSET inject_dbit_error=false +CSET inject_dbit_error_axis=false +CSET inject_dbit_error_rach=false +CSET inject_dbit_error_rdch=false +CSET inject_dbit_error_wach=false +CSET inject_dbit_error_wdch=false +CSET inject_dbit_error_wrch=false +CSET inject_sbit_error=false +CSET inject_sbit_error_axis=false +CSET inject_sbit_error_rach=false +CSET inject_sbit_error_rdch=false +CSET inject_sbit_error_wach=false +CSET inject_sbit_error_wdch=false +CSET inject_sbit_error_wrch=false +CSET input_data_width=18 +CSET input_depth=131072 +CSET input_depth_axis=1024 +CSET input_depth_rach=16 +CSET input_depth_rdch=1024 +CSET input_depth_wach=16 +CSET input_depth_wdch=1024 +CSET input_depth_wrch=16 +CSET interface_type=Native +CSET output_data_width=18 +CSET output_depth=131072 +CSET overflow_flag=true +CSET overflow_flag_axi=false +CSET overflow_sense=Active_High +CSET overflow_sense_axi=Active_High +CSET performance_options=Standard_FIFO +CSET programmable_empty_type=No_Programmable_Empty_Threshold +CSET programmable_empty_type_axis=Empty +CSET programmable_empty_type_rach=Empty +CSET programmable_empty_type_rdch=Empty +CSET programmable_empty_type_wach=Empty +CSET programmable_empty_type_wdch=Empty +CSET programmable_empty_type_wrch=Empty +CSET programmable_full_type=Single_Programmable_Full_Threshold_Constant +CSET programmable_full_type_axis=Full +CSET programmable_full_type_rach=Full +CSET programmable_full_type_rdch=Full +CSET programmable_full_type_wach=Full +CSET programmable_full_type_wdch=Full +CSET programmable_full_type_wrch=Full +CSET rach_type=FIFO +CSET rdch_type=FIFO +CSET read_clock_frequency=1 +CSET read_data_count=false +CSET read_data_count_width=17 +CSET register_slice_mode_axis=Fully_Registered +CSET register_slice_mode_rach=Fully_Registered +CSET register_slice_mode_rdch=Fully_Registered +CSET register_slice_mode_wach=Fully_Registered +CSET register_slice_mode_wdch=Fully_Registered +CSET register_slice_mode_wrch=Fully_Registered +CSET reset_pin=true +CSET reset_type=Asynchronous_Reset +CSET ruser_width=1 +CSET synchronization_stages=2 +CSET synchronization_stages_axi=2 +CSET tdata_width=64 +CSET tdest_width=4 +CSET tid_width=8 +CSET tkeep_width=4 +CSET tstrb_width=4 +CSET tuser_width=4 +CSET underflow_flag=true +CSET underflow_flag_axi=false +CSET underflow_sense=Active_High +CSET underflow_sense_axi=Active_High +CSET use_clock_enable=false +CSET use_dout_reset=true +CSET use_embedded_registers=false +CSET use_extra_logic=false +CSET valid_flag=true +CSET valid_sense=Active_High +CSET wach_type=FIFO +CSET wdch_type=FIFO +CSET wrch_type=FIFO +CSET write_acknowledge_flag=false +CSET write_acknowledge_sense=Active_High +CSET write_clock_frequency=1 +CSET write_data_count=false +CSET write_data_count_width=17 +CSET wuser_width=1 +# END Parameters +# BEGIN Extra information +MISC pkg_timestamp=2011-10-22T06:08:52Z +# END Extra information +GENERATE +# CRC: 61e37ce4 diff --git a/rce/fw-hsio/modules/pixelcore/coregen/datafifo16384.xco b/rce/fw-hsio/modules/pixelcore/coregen/datafifo16384.xco new file mode 100644 index 00000000..bdeaa5f6 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/coregen/datafifo16384.xco @@ -0,0 +1,219 @@ +############################################################## +# +# Xilinx Core Generator version 13.4 +# Date: Mon Oct 22 15:12:15 2012 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# Generated from component: xilinx.com:ip:fifo_generator:8.4 +# +############################################################## +# +# BEGIN Project Options +SET addpads = false +SET asysymbol = false +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = false +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = false +SET foundationsym = false +SET implementationfiletype = Ngc +SET package = ff1152 +SET removerpms = false +SET simulationfiles = Behavioral +SET speedgrade = -11 +SET verilogsim = false +SET vhdlsim = true +# END Project Options +# BEGIN Select +SELECT Fifo_Generator xilinx.com:ip:fifo_generator:8.4 +# END Select +# BEGIN Parameters +CSET add_ngc_constraint_axi=false +CSET almost_empty_flag=false +CSET almost_full_flag=false +CSET aruser_width=1 +CSET awuser_width=1 +CSET axi_address_width=32 +CSET axi_data_width=64 +CSET axi_type=AXI4_Stream +CSET axis_type=FIFO +CSET buser_width=1 +CSET clock_enable_type=Slave_Interface_Clock_Enable +CSET clock_type_axi=Common_Clock +CSET component_name=datafifo16384 +CSET data_count=false +CSET data_count_width=14 +CSET disable_timing_violations=false +CSET disable_timing_violations_axi=false +CSET dout_reset_value=0 +CSET empty_threshold_assert_value=2 +CSET empty_threshold_assert_value_axis=1022 +CSET empty_threshold_assert_value_rach=1022 +CSET empty_threshold_assert_value_rdch=1022 +CSET empty_threshold_assert_value_wach=1022 +CSET empty_threshold_assert_value_wdch=1022 +CSET empty_threshold_assert_value_wrch=1022 +CSET empty_threshold_negate_value=3 +CSET enable_aruser=false +CSET enable_awuser=false +CSET enable_buser=false +CSET enable_common_overflow=false +CSET enable_common_underflow=false +CSET enable_data_counts_axis=false +CSET enable_data_counts_rach=false +CSET enable_data_counts_rdch=false +CSET enable_data_counts_wach=false +CSET enable_data_counts_wdch=false +CSET enable_data_counts_wrch=false +CSET enable_ecc=false +CSET enable_ecc_axis=false +CSET enable_ecc_rach=false +CSET enable_ecc_rdch=false +CSET enable_ecc_wach=false +CSET enable_ecc_wdch=false +CSET enable_ecc_wrch=false +CSET enable_handshake_flag_options_axis=false +CSET enable_handshake_flag_options_rach=false +CSET enable_handshake_flag_options_rdch=false +CSET enable_handshake_flag_options_wach=false +CSET enable_handshake_flag_options_wdch=false +CSET enable_handshake_flag_options_wrch=false +CSET enable_read_channel=false +CSET enable_read_pointer_increment_by2=false +CSET enable_reset_synchronization=true +CSET enable_ruser=false +CSET enable_tdata=false +CSET enable_tdest=false +CSET enable_tid=false +CSET enable_tkeep=false +CSET enable_tlast=false +CSET enable_tready=true +CSET enable_tstrobe=false +CSET enable_tuser=false +CSET enable_write_channel=false +CSET enable_wuser=false +CSET fifo_application_type_axis=Data_FIFO +CSET fifo_application_type_rach=Data_FIFO +CSET fifo_application_type_rdch=Data_FIFO +CSET fifo_application_type_wach=Data_FIFO +CSET fifo_application_type_wdch=Data_FIFO +CSET fifo_application_type_wrch=Data_FIFO +CSET fifo_implementation=Independent_Clocks_Block_RAM +CSET fifo_implementation_axis=Common_Clock_Block_RAM +CSET fifo_implementation_rach=Common_Clock_Block_RAM +CSET fifo_implementation_rdch=Common_Clock_Block_RAM +CSET fifo_implementation_wach=Common_Clock_Block_RAM +CSET fifo_implementation_wdch=Common_Clock_Block_RAM +CSET fifo_implementation_wrch=Common_Clock_Block_RAM +CSET full_flags_reset_value=1 +CSET full_threshold_assert_value=14000 +CSET full_threshold_assert_value_axis=1023 +CSET full_threshold_assert_value_rach=1023 +CSET full_threshold_assert_value_rdch=1023 +CSET full_threshold_assert_value_wach=1023 +CSET full_threshold_assert_value_wdch=1023 +CSET full_threshold_assert_value_wrch=1023 +CSET full_threshold_negate_value=13999 +CSET id_width=4 +CSET inject_dbit_error=false +CSET inject_dbit_error_axis=false +CSET inject_dbit_error_rach=false +CSET inject_dbit_error_rdch=false +CSET inject_dbit_error_wach=false +CSET inject_dbit_error_wdch=false +CSET inject_dbit_error_wrch=false +CSET inject_sbit_error=false +CSET inject_sbit_error_axis=false +CSET inject_sbit_error_rach=false +CSET inject_sbit_error_rdch=false +CSET inject_sbit_error_wach=false +CSET inject_sbit_error_wdch=false +CSET inject_sbit_error_wrch=false +CSET input_data_width=18 +CSET input_depth=16384 +CSET input_depth_axis=1024 +CSET input_depth_rach=16 +CSET input_depth_rdch=1024 +CSET input_depth_wach=16 +CSET input_depth_wdch=1024 +CSET input_depth_wrch=16 +CSET interface_type=Native +CSET output_data_width=18 +CSET output_depth=16384 +CSET overflow_flag=true +CSET overflow_flag_axi=false +CSET overflow_sense=Active_High +CSET overflow_sense_axi=Active_High +CSET performance_options=Standard_FIFO +CSET programmable_empty_type=No_Programmable_Empty_Threshold +CSET programmable_empty_type_axis=Empty +CSET programmable_empty_type_rach=Empty +CSET programmable_empty_type_rdch=Empty +CSET programmable_empty_type_wach=Empty +CSET programmable_empty_type_wdch=Empty +CSET programmable_empty_type_wrch=Empty +CSET programmable_full_type=Single_Programmable_Full_Threshold_Constant +CSET programmable_full_type_axis=Full +CSET programmable_full_type_rach=Full +CSET programmable_full_type_rdch=Full +CSET programmable_full_type_wach=Full +CSET programmable_full_type_wdch=Full +CSET programmable_full_type_wrch=Full +CSET rach_type=FIFO +CSET rdch_type=FIFO +CSET read_clock_frequency=1 +CSET read_data_count=false +CSET read_data_count_width=14 +CSET register_slice_mode_axis=Fully_Registered +CSET register_slice_mode_rach=Fully_Registered +CSET register_slice_mode_rdch=Fully_Registered +CSET register_slice_mode_wach=Fully_Registered +CSET register_slice_mode_wdch=Fully_Registered +CSET register_slice_mode_wrch=Fully_Registered +CSET reset_pin=true +CSET reset_type=Asynchronous_Reset +CSET ruser_width=1 +CSET synchronization_stages=2 +CSET synchronization_stages_axi=2 +CSET tdata_width=64 +CSET tdest_width=4 +CSET tid_width=8 +CSET tkeep_width=4 +CSET tstrb_width=4 +CSET tuser_width=4 +CSET underflow_flag=true +CSET underflow_flag_axi=false +CSET underflow_sense=Active_High +CSET underflow_sense_axi=Active_High +CSET use_clock_enable=false +CSET use_dout_reset=true +CSET use_embedded_registers=false +CSET use_extra_logic=false +CSET valid_flag=true +CSET valid_sense=Active_High +CSET wach_type=FIFO +CSET wdch_type=FIFO +CSET wrch_type=FIFO +CSET write_acknowledge_flag=false +CSET write_acknowledge_sense=Active_High +CSET write_clock_frequency=1 +CSET write_data_count=false +CSET write_data_count_width=14 +CSET wuser_width=1 +# END Parameters +# BEGIN Extra information +MISC pkg_timestamp=2011-10-22T06:08:52Z +# END Extra information +GENERATE +# CRC: dfc3057f diff --git a/rce/fw-hsio/modules/pixelcore/coregen/datafifo32768.xco b/rce/fw-hsio/modules/pixelcore/coregen/datafifo32768.xco new file mode 100644 index 00000000..13f5ed50 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/coregen/datafifo32768.xco @@ -0,0 +1,203 @@ +############################################################## +# +# Xilinx Core Generator version 12.4 +# Date: Wed Oct 12 15:32:01 2011 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# BEGIN Project Options +SET addpads = false +SET asysymbol = false +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = false +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = false +SET foundationsym = false +SET implementationfiletype = Ngc +SET package = ff1152 +SET removerpms = false +SET simulationfiles = Behavioral +SET speedgrade = -11 +SET verilogsim = false +SET vhdlsim = true +# END Project Options +# BEGIN Select +SELECT Fifo_Generator family Xilinx,_Inc. 7.2 +# END Select +# BEGIN Parameters +CSET add_ngc_constraint_axi=false +CSET almost_empty_flag=false +CSET almost_full_flag=false +CSET aruser_width=1 +CSET awuser_width=1 +CSET axi_address_width=32 +CSET axi_data_width=64 +CSET axi_type=AXI4_Stream +CSET axis_type=FIFO +CSET buser_width=1 +CSET clock_enable_type=Slave_Interface_Clock_Enable +CSET clock_type_axi=Common_Clock +CSET component_name=datafifo32768 +CSET data_count=false +CSET data_count_width=15 +CSET disable_timing_violations=false +CSET disable_timing_violations_axi=false +CSET dout_reset_value=0 +CSET empty_threshold_assert_value=2 +CSET empty_threshold_assert_value_axis=1022 +CSET empty_threshold_assert_value_rach=1022 +CSET empty_threshold_assert_value_rdch=1022 +CSET empty_threshold_assert_value_wach=1022 +CSET empty_threshold_assert_value_wdch=1022 +CSET empty_threshold_assert_value_wrch=1022 +CSET empty_threshold_negate_value=3 +CSET enable_aruser=false +CSET enable_awuser=false +CSET enable_buser=false +CSET enable_common_overflow=false +CSET enable_common_underflow=false +CSET enable_data_counts_axis=false +CSET enable_data_counts_rach=false +CSET enable_data_counts_rdch=false +CSET enable_data_counts_wach=false +CSET enable_data_counts_wdch=false +CSET enable_data_counts_wrch=false +CSET enable_ecc=false +CSET enable_ecc_axis=false +CSET enable_ecc_rach=false +CSET enable_ecc_rdch=false +CSET enable_ecc_wach=false +CSET enable_ecc_wdch=false +CSET enable_ecc_wrch=false +CSET enable_handshake_flag_options_axis=false +CSET enable_handshake_flag_options_rach=false +CSET enable_handshake_flag_options_rdch=false +CSET enable_handshake_flag_options_wach=false +CSET enable_handshake_flag_options_wdch=false +CSET enable_handshake_flag_options_wrch=false +CSET enable_read_channel=false +CSET enable_reset_synchronization=true +CSET enable_ruser=false +CSET enable_tdata=false +CSET enable_tdest=false +CSET enable_tid=false +CSET enable_tkeep=false +CSET enable_tlast=false +CSET enable_tready=true +CSET enable_tstrobe=false +CSET enable_tuser=false +CSET enable_write_channel=false +CSET enable_wuser=false +CSET fifo_application_type_axis=Data_FIFO +CSET fifo_application_type_rach=Data_FIFO +CSET fifo_application_type_rdch=Data_FIFO +CSET fifo_application_type_wach=Data_FIFO +CSET fifo_application_type_wdch=Data_FIFO +CSET fifo_application_type_wrch=Data_FIFO +CSET fifo_implementation=Independent_Clocks_Block_RAM +CSET fifo_implementation_axis=Common_Clock_Block_RAM +CSET fifo_implementation_rach=Common_Clock_Block_RAM +CSET fifo_implementation_rdch=Common_Clock_Block_RAM +CSET fifo_implementation_wach=Common_Clock_Block_RAM +CSET fifo_implementation_wdch=Common_Clock_Block_RAM +CSET fifo_implementation_wrch=Common_Clock_Block_RAM +CSET full_flags_reset_value=1 +CSET full_threshold_assert_value=31000 +CSET full_threshold_assert_value_axis=1023 +CSET full_threshold_assert_value_rach=1023 +CSET full_threshold_assert_value_rdch=1023 +CSET full_threshold_assert_value_wach=1023 +CSET full_threshold_assert_value_wdch=1023 +CSET full_threshold_assert_value_wrch=1023 +CSET full_threshold_negate_value=30999 +CSET id_width=4 +CSET inject_dbit_error=false +CSET inject_dbit_error_axis=false +CSET inject_dbit_error_rach=false +CSET inject_dbit_error_rdch=false +CSET inject_dbit_error_wach=false +CSET inject_dbit_error_wdch=false +CSET inject_dbit_error_wrch=false +CSET inject_sbit_error=false +CSET inject_sbit_error_axis=false +CSET inject_sbit_error_rach=false +CSET inject_sbit_error_rdch=false +CSET inject_sbit_error_wach=false +CSET inject_sbit_error_wdch=false +CSET inject_sbit_error_wrch=false +CSET input_data_width=18 +CSET input_depth=32768 +CSET input_depth_axis=1024 +CSET input_depth_rach=16 +CSET input_depth_rdch=1024 +CSET input_depth_wach=16 +CSET input_depth_wdch=1024 +CSET input_depth_wrch=16 +CSET interface_type=Native +CSET output_data_width=18 +CSET output_depth=32768 +CSET overflow_flag=true +CSET overflow_flag_axi=false +CSET overflow_sense=Active_High +CSET overflow_sense_axi=Active_High +CSET performance_options=Standard_FIFO +CSET programmable_empty_type=No_Programmable_Empty_Threshold +CSET programmable_empty_type_axis=Empty +CSET programmable_empty_type_rach=Empty +CSET programmable_empty_type_rdch=Empty +CSET programmable_empty_type_wach=Empty +CSET programmable_empty_type_wdch=Empty +CSET programmable_empty_type_wrch=Empty +CSET programmable_full_type=Single_Programmable_Full_Threshold_Constant +CSET programmable_full_type_axis=Full +CSET programmable_full_type_rach=Full +CSET programmable_full_type_rdch=Full +CSET programmable_full_type_wach=Full +CSET programmable_full_type_wdch=Full +CSET programmable_full_type_wrch=Full +CSET rach_type=FIFO +CSET rdch_type=FIFO +CSET read_clock_frequency=1 +CSET read_data_count=false +CSET read_data_count_width=15 +CSET reset_pin=true +CSET reset_type=Asynchronous_Reset +CSET ruser_width=1 +CSET tdata_width=64 +CSET tdest_width=4 +CSET tid_width=8 +CSET tkeep_width=4 +CSET tstrb_width=4 +CSET tuser_width=4 +CSET underflow_flag=true +CSET underflow_flag_axi=false +CSET underflow_sense=Active_High +CSET underflow_sense_axi=Active_High +CSET use_clock_enable=false +CSET use_dout_reset=true +CSET use_embedded_registers=false +CSET use_extra_logic=false +CSET valid_flag=true +CSET valid_sense=Active_High +CSET wach_type=FIFO +CSET wdch_type=FIFO +CSET wrch_type=FIFO +CSET write_acknowledge_flag=false +CSET write_acknowledge_sense=Active_High +CSET write_clock_frequency=1 +CSET write_data_count=false +CSET write_data_count_width=15 +CSET wuser_width=1 +# END Parameters +GENERATE +# CRC: 381e6d04 diff --git a/rce/fw-hsio/modules/pixelcore/coregen/datafifo4096.xco b/rce/fw-hsio/modules/pixelcore/coregen/datafifo4096.xco new file mode 100644 index 00000000..0be2d640 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/coregen/datafifo4096.xco @@ -0,0 +1,219 @@ +############################################################## +# +# Xilinx Core Generator version 14.6 +# Date: Thu Nov 6 16:47:16 2014 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# Generated from component: xilinx.com:ip:fifo_generator:8.4 +# +############################################################## +# +# BEGIN Project Options +SET addpads = false +SET asysymbol = false +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = false +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = false +SET foundationsym = false +SET implementationfiletype = Ngc +SET package = ff1152 +SET removerpms = false +SET simulationfiles = Behavioral +SET speedgrade = -11 +SET verilogsim = false +SET vhdlsim = true +# END Project Options +# BEGIN Select +SELECT Fifo_Generator xilinx.com:ip:fifo_generator:8.4 +# END Select +# BEGIN Parameters +CSET add_ngc_constraint_axi=false +CSET almost_empty_flag=false +CSET almost_full_flag=false +CSET aruser_width=1 +CSET awuser_width=1 +CSET axi_address_width=32 +CSET axi_data_width=64 +CSET axi_type=AXI4_Stream +CSET axis_type=FIFO +CSET buser_width=1 +CSET clock_enable_type=Slave_Interface_Clock_Enable +CSET clock_type_axi=Common_Clock +CSET component_name=datafifo4096 +CSET data_count=false +CSET data_count_width=12 +CSET disable_timing_violations=false +CSET disable_timing_violations_axi=false +CSET dout_reset_value=0 +CSET empty_threshold_assert_value=2 +CSET empty_threshold_assert_value_axis=1022 +CSET empty_threshold_assert_value_rach=1022 +CSET empty_threshold_assert_value_rdch=1022 +CSET empty_threshold_assert_value_wach=1022 +CSET empty_threshold_assert_value_wdch=1022 +CSET empty_threshold_assert_value_wrch=1022 +CSET empty_threshold_negate_value=3 +CSET enable_aruser=false +CSET enable_awuser=false +CSET enable_buser=false +CSET enable_common_overflow=false +CSET enable_common_underflow=false +CSET enable_data_counts_axis=false +CSET enable_data_counts_rach=false +CSET enable_data_counts_rdch=false +CSET enable_data_counts_wach=false +CSET enable_data_counts_wdch=false +CSET enable_data_counts_wrch=false +CSET enable_ecc=false +CSET enable_ecc_axis=false +CSET enable_ecc_rach=false +CSET enable_ecc_rdch=false +CSET enable_ecc_wach=false +CSET enable_ecc_wdch=false +CSET enable_ecc_wrch=false +CSET enable_handshake_flag_options_axis=false +CSET enable_handshake_flag_options_rach=false +CSET enable_handshake_flag_options_rdch=false +CSET enable_handshake_flag_options_wach=false +CSET enable_handshake_flag_options_wdch=false +CSET enable_handshake_flag_options_wrch=false +CSET enable_read_channel=false +CSET enable_read_pointer_increment_by2=false +CSET enable_reset_synchronization=true +CSET enable_ruser=false +CSET enable_tdata=false +CSET enable_tdest=false +CSET enable_tid=false +CSET enable_tkeep=false +CSET enable_tlast=false +CSET enable_tready=true +CSET enable_tstrobe=false +CSET enable_tuser=false +CSET enable_write_channel=false +CSET enable_wuser=false +CSET fifo_application_type_axis=Data_FIFO +CSET fifo_application_type_rach=Data_FIFO +CSET fifo_application_type_rdch=Data_FIFO +CSET fifo_application_type_wach=Data_FIFO +CSET fifo_application_type_wdch=Data_FIFO +CSET fifo_application_type_wrch=Data_FIFO +CSET fifo_implementation=Independent_Clocks_Block_RAM +CSET fifo_implementation_axis=Common_Clock_Block_RAM +CSET fifo_implementation_rach=Common_Clock_Block_RAM +CSET fifo_implementation_rdch=Common_Clock_Block_RAM +CSET fifo_implementation_wach=Common_Clock_Block_RAM +CSET fifo_implementation_wdch=Common_Clock_Block_RAM +CSET fifo_implementation_wrch=Common_Clock_Block_RAM +CSET full_flags_reset_value=1 +CSET full_threshold_assert_value=3300 +CSET full_threshold_assert_value_axis=1023 +CSET full_threshold_assert_value_rach=1023 +CSET full_threshold_assert_value_rdch=1023 +CSET full_threshold_assert_value_wach=1023 +CSET full_threshold_assert_value_wdch=1023 +CSET full_threshold_assert_value_wrch=1023 +CSET full_threshold_negate_value=3299 +CSET id_width=4 +CSET inject_dbit_error=false +CSET inject_dbit_error_axis=false +CSET inject_dbit_error_rach=false +CSET inject_dbit_error_rdch=false +CSET inject_dbit_error_wach=false +CSET inject_dbit_error_wdch=false +CSET inject_dbit_error_wrch=false +CSET inject_sbit_error=false +CSET inject_sbit_error_axis=false +CSET inject_sbit_error_rach=false +CSET inject_sbit_error_rdch=false +CSET inject_sbit_error_wach=false +CSET inject_sbit_error_wdch=false +CSET inject_sbit_error_wrch=false +CSET input_data_width=18 +CSET input_depth=4096 +CSET input_depth_axis=1024 +CSET input_depth_rach=16 +CSET input_depth_rdch=1024 +CSET input_depth_wach=16 +CSET input_depth_wdch=1024 +CSET input_depth_wrch=16 +CSET interface_type=Native +CSET output_data_width=18 +CSET output_depth=4096 +CSET overflow_flag=true +CSET overflow_flag_axi=false +CSET overflow_sense=Active_High +CSET overflow_sense_axi=Active_High +CSET performance_options=Standard_FIFO +CSET programmable_empty_type=No_Programmable_Empty_Threshold +CSET programmable_empty_type_axis=Empty +CSET programmable_empty_type_rach=Empty +CSET programmable_empty_type_rdch=Empty +CSET programmable_empty_type_wach=Empty +CSET programmable_empty_type_wdch=Empty +CSET programmable_empty_type_wrch=Empty +CSET programmable_full_type=Single_Programmable_Full_Threshold_Constant +CSET programmable_full_type_axis=Full +CSET programmable_full_type_rach=Full +CSET programmable_full_type_rdch=Full +CSET programmable_full_type_wach=Full +CSET programmable_full_type_wdch=Full +CSET programmable_full_type_wrch=Full +CSET rach_type=FIFO +CSET rdch_type=FIFO +CSET read_clock_frequency=1 +CSET read_data_count=false +CSET read_data_count_width=12 +CSET register_slice_mode_axis=Fully_Registered +CSET register_slice_mode_rach=Fully_Registered +CSET register_slice_mode_rdch=Fully_Registered +CSET register_slice_mode_wach=Fully_Registered +CSET register_slice_mode_wdch=Fully_Registered +CSET register_slice_mode_wrch=Fully_Registered +CSET reset_pin=true +CSET reset_type=Asynchronous_Reset +CSET ruser_width=1 +CSET synchronization_stages=2 +CSET synchronization_stages_axi=2 +CSET tdata_width=64 +CSET tdest_width=4 +CSET tid_width=8 +CSET tkeep_width=4 +CSET tstrb_width=4 +CSET tuser_width=4 +CSET underflow_flag=true +CSET underflow_flag_axi=false +CSET underflow_sense=Active_High +CSET underflow_sense_axi=Active_High +CSET use_clock_enable=false +CSET use_dout_reset=true +CSET use_embedded_registers=false +CSET use_extra_logic=false +CSET valid_flag=true +CSET valid_sense=Active_High +CSET wach_type=FIFO +CSET wdch_type=FIFO +CSET wrch_type=FIFO +CSET write_acknowledge_flag=false +CSET write_acknowledge_sense=Active_High +CSET write_clock_frequency=1 +CSET write_data_count=false +CSET write_data_count_width=12 +CSET wuser_width=1 +# END Parameters +# BEGIN Extra information +MISC pkg_timestamp=2011-10-22T06:08:52Z +# END Extra information +GENERATE +# CRC: 344ff49c diff --git a/rce/fw-hsio/modules/pixelcore/coregen/datafifo8192.xco b/rce/fw-hsio/modules/pixelcore/coregen/datafifo8192.xco new file mode 100644 index 00000000..1461984b --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/coregen/datafifo8192.xco @@ -0,0 +1,203 @@ +############################################################## +# +# Xilinx Core Generator version 12.4 +# Date: Fri Jun 17 18:39:09 2011 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# BEGIN Project Options +SET addpads = false +SET asysymbol = false +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = false +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = false +SET foundationsym = false +SET implementationfiletype = Ngc +SET package = ff1152 +SET removerpms = false +SET simulationfiles = Behavioral +SET speedgrade = -11 +SET verilogsim = false +SET vhdlsim = true +# END Project Options +# BEGIN Select +SELECT Fifo_Generator family Xilinx,_Inc. 7.2 +# END Select +# BEGIN Parameters +CSET add_ngc_constraint_axi=false +CSET almost_empty_flag=false +CSET almost_full_flag=false +CSET aruser_width=1 +CSET awuser_width=1 +CSET axi_address_width=32 +CSET axi_data_width=64 +CSET axi_type=AXI4_Stream +CSET axis_type=FIFO +CSET buser_width=1 +CSET clock_enable_type=Slave_Interface_Clock_Enable +CSET clock_type_axi=Common_Clock +CSET component_name=datafifo8192 +CSET data_count=false +CSET data_count_width=13 +CSET disable_timing_violations=false +CSET disable_timing_violations_axi=false +CSET dout_reset_value=0 +CSET empty_threshold_assert_value=2 +CSET empty_threshold_assert_value_axis=1022 +CSET empty_threshold_assert_value_rach=1022 +CSET empty_threshold_assert_value_rdch=1022 +CSET empty_threshold_assert_value_wach=1022 +CSET empty_threshold_assert_value_wdch=1022 +CSET empty_threshold_assert_value_wrch=1022 +CSET empty_threshold_negate_value=3 +CSET enable_aruser=false +CSET enable_awuser=false +CSET enable_buser=false +CSET enable_common_overflow=false +CSET enable_common_underflow=false +CSET enable_data_counts_axis=false +CSET enable_data_counts_rach=false +CSET enable_data_counts_rdch=false +CSET enable_data_counts_wach=false +CSET enable_data_counts_wdch=false +CSET enable_data_counts_wrch=false +CSET enable_ecc=false +CSET enable_ecc_axis=false +CSET enable_ecc_rach=false +CSET enable_ecc_rdch=false +CSET enable_ecc_wach=false +CSET enable_ecc_wdch=false +CSET enable_ecc_wrch=false +CSET enable_handshake_flag_options_axis=false +CSET enable_handshake_flag_options_rach=false +CSET enable_handshake_flag_options_rdch=false +CSET enable_handshake_flag_options_wach=false +CSET enable_handshake_flag_options_wdch=false +CSET enable_handshake_flag_options_wrch=false +CSET enable_read_channel=false +CSET enable_reset_synchronization=true +CSET enable_ruser=false +CSET enable_tdata=false +CSET enable_tdest=false +CSET enable_tid=false +CSET enable_tkeep=false +CSET enable_tlast=false +CSET enable_tready=true +CSET enable_tstrobe=false +CSET enable_tuser=false +CSET enable_write_channel=false +CSET enable_wuser=false +CSET fifo_application_type_axis=Data_FIFO +CSET fifo_application_type_rach=Data_FIFO +CSET fifo_application_type_rdch=Data_FIFO +CSET fifo_application_type_wach=Data_FIFO +CSET fifo_application_type_wdch=Data_FIFO +CSET fifo_application_type_wrch=Data_FIFO +CSET fifo_implementation=Independent_Clocks_Block_RAM +CSET fifo_implementation_axis=Common_Clock_Block_RAM +CSET fifo_implementation_rach=Common_Clock_Block_RAM +CSET fifo_implementation_rdch=Common_Clock_Block_RAM +CSET fifo_implementation_wach=Common_Clock_Block_RAM +CSET fifo_implementation_wdch=Common_Clock_Block_RAM +CSET fifo_implementation_wrch=Common_Clock_Block_RAM +CSET full_flags_reset_value=1 +CSET full_threshold_assert_value=6166 +CSET full_threshold_assert_value_axis=1023 +CSET full_threshold_assert_value_rach=1023 +CSET full_threshold_assert_value_rdch=1023 +CSET full_threshold_assert_value_wach=1023 +CSET full_threshold_assert_value_wdch=1023 +CSET full_threshold_assert_value_wrch=1023 +CSET full_threshold_negate_value=6165 +CSET id_width=4 +CSET inject_dbit_error=false +CSET inject_dbit_error_axis=false +CSET inject_dbit_error_rach=false +CSET inject_dbit_error_rdch=false +CSET inject_dbit_error_wach=false +CSET inject_dbit_error_wdch=false +CSET inject_dbit_error_wrch=false +CSET inject_sbit_error=false +CSET inject_sbit_error_axis=false +CSET inject_sbit_error_rach=false +CSET inject_sbit_error_rdch=false +CSET inject_sbit_error_wach=false +CSET inject_sbit_error_wdch=false +CSET inject_sbit_error_wrch=false +CSET input_data_width=18 +CSET input_depth=8192 +CSET input_depth_axis=1024 +CSET input_depth_rach=16 +CSET input_depth_rdch=1024 +CSET input_depth_wach=16 +CSET input_depth_wdch=1024 +CSET input_depth_wrch=16 +CSET interface_type=Native +CSET output_data_width=18 +CSET output_depth=8192 +CSET overflow_flag=true +CSET overflow_flag_axi=false +CSET overflow_sense=Active_High +CSET overflow_sense_axi=Active_High +CSET performance_options=Standard_FIFO +CSET programmable_empty_type=No_Programmable_Empty_Threshold +CSET programmable_empty_type_axis=Empty +CSET programmable_empty_type_rach=Empty +CSET programmable_empty_type_rdch=Empty +CSET programmable_empty_type_wach=Empty +CSET programmable_empty_type_wdch=Empty +CSET programmable_empty_type_wrch=Empty +CSET programmable_full_type=Single_Programmable_Full_Threshold_Constant +CSET programmable_full_type_axis=Full +CSET programmable_full_type_rach=Full +CSET programmable_full_type_rdch=Full +CSET programmable_full_type_wach=Full +CSET programmable_full_type_wdch=Full +CSET programmable_full_type_wrch=Full +CSET rach_type=FIFO +CSET rdch_type=FIFO +CSET read_clock_frequency=1 +CSET read_data_count=false +CSET read_data_count_width=13 +CSET reset_pin=true +CSET reset_type=Asynchronous_Reset +CSET ruser_width=1 +CSET tdata_width=64 +CSET tdest_width=4 +CSET tid_width=8 +CSET tkeep_width=4 +CSET tstrb_width=4 +CSET tuser_width=4 +CSET underflow_flag=true +CSET underflow_flag_axi=false +CSET underflow_sense=Active_High +CSET underflow_sense_axi=Active_High +CSET use_clock_enable=false +CSET use_dout_reset=true +CSET use_embedded_registers=false +CSET use_extra_logic=false +CSET valid_flag=true +CSET valid_sense=Active_High +CSET wach_type=FIFO +CSET wdch_type=FIFO +CSET wrch_type=FIFO +CSET write_acknowledge_flag=false +CSET write_acknowledge_sense=Active_High +CSET write_clock_frequency=1 +CSET write_data_count=false +CSET write_data_count_width=13 +CSET wuser_width=1 +# END Parameters +GENERATE +# CRC: d00dfff1 diff --git a/rce/fw-hsio/modules/pixelcore/coregen/dataflagfifo.xco b/rce/fw-hsio/modules/pixelcore/coregen/dataflagfifo.xco new file mode 100644 index 00000000..98ca6b93 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/coregen/dataflagfifo.xco @@ -0,0 +1,217 @@ +############################################################## +# +# Xilinx Core Generator version 14.6 +# Date: Fri Nov 7 14:50:15 2014 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# Generated from component: xilinx.com:ip:fifo_generator:8.2 +# +############################################################## +# +# BEGIN Project Options +SET addpads = false +SET asysymbol = false +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = false +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = false +SET foundationsym = false +SET implementationfiletype = Ngc +SET package = ff1152 +SET removerpms = false +SET simulationfiles = Behavioral +SET speedgrade = -11 +SET verilogsim = false +SET vhdlsim = true +# END Project Options +# BEGIN Select +SELECT Fifo_Generator xilinx.com:ip:fifo_generator:8.2 +# END Select +# BEGIN Parameters +CSET add_ngc_constraint_axi=false +CSET almost_empty_flag=true +CSET almost_full_flag=false +CSET aruser_width=1 +CSET awuser_width=1 +CSET axi_address_width=32 +CSET axi_data_width=64 +CSET axi_type=AXI4_Stream +CSET axis_type=FIFO +CSET buser_width=1 +CSET clock_enable_type=Slave_Interface_Clock_Enable +CSET clock_type_axi=Common_Clock +CSET component_name=dataflagfifo +CSET data_count=false +CSET data_count_width=14 +CSET disable_timing_violations=false +CSET disable_timing_violations_axi=false +CSET dout_reset_value=0 +CSET empty_threshold_assert_value=2 +CSET empty_threshold_assert_value_axis=1022 +CSET empty_threshold_assert_value_rach=1022 +CSET empty_threshold_assert_value_rdch=1022 +CSET empty_threshold_assert_value_wach=1022 +CSET empty_threshold_assert_value_wdch=1022 +CSET empty_threshold_assert_value_wrch=1022 +CSET empty_threshold_negate_value=3 +CSET enable_aruser=false +CSET enable_awuser=false +CSET enable_buser=false +CSET enable_common_overflow=false +CSET enable_common_underflow=false +CSET enable_data_counts_axis=false +CSET enable_data_counts_rach=false +CSET enable_data_counts_rdch=false +CSET enable_data_counts_wach=false +CSET enable_data_counts_wdch=false +CSET enable_data_counts_wrch=false +CSET enable_ecc=false +CSET enable_ecc_axis=false +CSET enable_ecc_rach=false +CSET enable_ecc_rdch=false +CSET enable_ecc_wach=false +CSET enable_ecc_wdch=false +CSET enable_ecc_wrch=false +CSET enable_handshake_flag_options_axis=false +CSET enable_handshake_flag_options_rach=false +CSET enable_handshake_flag_options_rdch=false +CSET enable_handshake_flag_options_wach=false +CSET enable_handshake_flag_options_wdch=false +CSET enable_handshake_flag_options_wrch=false +CSET enable_read_channel=false +CSET enable_read_pointer_increment_by2=false +CSET enable_reset_synchronization=true +CSET enable_ruser=false +CSET enable_tdata=false +CSET enable_tdest=false +CSET enable_tid=false +CSET enable_tkeep=false +CSET enable_tlast=false +CSET enable_tready=true +CSET enable_tstrobe=false +CSET enable_tuser=false +CSET enable_write_channel=false +CSET enable_wuser=false +CSET fifo_application_type_axis=Data_FIFO +CSET fifo_application_type_rach=Data_FIFO +CSET fifo_application_type_rdch=Data_FIFO +CSET fifo_application_type_wach=Data_FIFO +CSET fifo_application_type_wdch=Data_FIFO +CSET fifo_application_type_wrch=Data_FIFO +CSET fifo_implementation=Independent_Clocks_Block_RAM +CSET fifo_implementation_axis=Common_Clock_Block_RAM +CSET fifo_implementation_rach=Common_Clock_Block_RAM +CSET fifo_implementation_rdch=Common_Clock_Block_RAM +CSET fifo_implementation_wach=Common_Clock_Block_RAM +CSET fifo_implementation_wdch=Common_Clock_Block_RAM +CSET fifo_implementation_wrch=Common_Clock_Block_RAM +CSET full_flags_reset_value=0 +CSET full_threshold_assert_value=16381 +CSET full_threshold_assert_value_axis=1023 +CSET full_threshold_assert_value_rach=1023 +CSET full_threshold_assert_value_rdch=1023 +CSET full_threshold_assert_value_wach=1023 +CSET full_threshold_assert_value_wdch=1023 +CSET full_threshold_assert_value_wrch=1023 +CSET full_threshold_negate_value=16380 +CSET id_width=4 +CSET inject_dbit_error=false +CSET inject_dbit_error_axis=false +CSET inject_dbit_error_rach=false +CSET inject_dbit_error_rdch=false +CSET inject_dbit_error_wach=false +CSET inject_dbit_error_wdch=false +CSET inject_dbit_error_wrch=false +CSET inject_sbit_error=false +CSET inject_sbit_error_axis=false +CSET inject_sbit_error_rach=false +CSET inject_sbit_error_rdch=false +CSET inject_sbit_error_wach=false +CSET inject_sbit_error_wdch=false +CSET inject_sbit_error_wrch=false +CSET input_data_width=1 +CSET input_depth=16384 +CSET input_depth_axis=1024 +CSET input_depth_rach=16 +CSET input_depth_rdch=1024 +CSET input_depth_wach=16 +CSET input_depth_wdch=1024 +CSET input_depth_wrch=16 +CSET interface_type=Native +CSET output_data_width=1 +CSET output_depth=16384 +CSET overflow_flag=false +CSET overflow_flag_axi=false +CSET overflow_sense=Active_High +CSET overflow_sense_axi=Active_High +CSET performance_options=Standard_FIFO +CSET programmable_empty_type=No_Programmable_Empty_Threshold +CSET programmable_empty_type_axis=Empty +CSET programmable_empty_type_rach=Empty +CSET programmable_empty_type_rdch=Empty +CSET programmable_empty_type_wach=Empty +CSET programmable_empty_type_wdch=Empty +CSET programmable_empty_type_wrch=Empty +CSET programmable_full_type=No_Programmable_Full_Threshold +CSET programmable_full_type_axis=Full +CSET programmable_full_type_rach=Full +CSET programmable_full_type_rdch=Full +CSET programmable_full_type_wach=Full +CSET programmable_full_type_wdch=Full +CSET programmable_full_type_wrch=Full +CSET rach_type=FIFO +CSET rdch_type=FIFO +CSET read_clock_frequency=1 +CSET read_data_count=false +CSET read_data_count_width=14 +CSET register_slice_mode_axis=Fully_Registered +CSET register_slice_mode_rach=Fully_Registered +CSET register_slice_mode_rdch=Fully_Registered +CSET register_slice_mode_wach=Fully_Registered +CSET register_slice_mode_wdch=Fully_Registered +CSET register_slice_mode_wrch=Fully_Registered +CSET reset_pin=true +CSET reset_type=Asynchronous_Reset +CSET ruser_width=1 +CSET tdata_width=64 +CSET tdest_width=4 +CSET tid_width=8 +CSET tkeep_width=4 +CSET tstrb_width=4 +CSET tuser_width=4 +CSET underflow_flag=false +CSET underflow_flag_axi=false +CSET underflow_sense=Active_High +CSET underflow_sense_axi=Active_High +CSET use_clock_enable=false +CSET use_dout_reset=true +CSET use_embedded_registers=false +CSET use_extra_logic=false +CSET valid_flag=false +CSET valid_sense=Active_High +CSET wach_type=FIFO +CSET wdch_type=FIFO +CSET wrch_type=FIFO +CSET write_acknowledge_flag=false +CSET write_acknowledge_sense=Active_High +CSET write_clock_frequency=1 +CSET write_data_count=false +CSET write_data_count_width=14 +CSET wuser_width=1 +# END Parameters +# BEGIN Extra information +MISC pkg_timestamp=2011-03-14T07:12:32Z +# END Extra information +GENERATE +# CRC: ef470f0d diff --git a/rce/fw-hsio/modules/pixelcore/coregen/eofcounter.xco b/rce/fw-hsio/modules/pixelcore/coregen/eofcounter.xco new file mode 100644 index 00000000..feba6ec7 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/coregen/eofcounter.xco @@ -0,0 +1,64 @@ +############################################################## +# +# Xilinx Core Generator version K.39 +# Date: Thu Oct 22 20:13:59 2009 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# BEGIN Project Options +SET addpads = False +SET asysymbol = False +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = False +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = False +SET foundationsym = False +SET implementationfiletype = Ngc +SET package = ff1152 +SET removerpms = False +SET simulationfiles = Behavioral +SET speedgrade = -10 +SET verilogsim = False +SET vhdlsim = True +# END Project Options +# BEGIN Select +SELECT Binary_Counter family Xilinx,_Inc. 8.0 +# END Select +# BEGIN Parameters +CSET aclr=true +CSET ainit=false +CSET ainit_value=0 +CSET aset=false +CSET async_threshold_output=false +CSET ce=true +CSET component_name=eofcounter +CSET count_mode=UPDOWN +CSET cycle_early_threshold_output=true +CSET final_count_value=1 +CSET increment_value=1 +CSET load=false +CSET load_ce_priority=CE_Overrides_Load +CSET output_width=16 +CSET restrict_count=false +CSET sclr=false +CSET sinit=false +CSET sinit_value=0 +CSET sset=false +CSET sync_ce_priority=Sync_Overrides_CE +CSET sync_threshold_output=true +CSET syncctrlpriority=Reset_Overrides_Set +CSET threshold_value=0 +# END Parameters +GENERATE +# CRC: f94ff18d + diff --git a/rce/fw-hsio/modules/pixelcore/coregen/pattern_blk_mem.ngc b/rce/fw-hsio/modules/pixelcore/coregen/pattern_blk_mem.ngc new file mode 100644 index 00000000..78b1bc8c --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/coregen/pattern_blk_mem.ngc @@ -0,0 +1,3 @@ +XILINX-XDB 0.1 STUB 0.1 ASCII +XILINX-XDM V1.4e +$26b4g<,[o}e~g`n;"2*413&;$>"9 > %71?*ga{&ygmn!z/da,ojenig%fecgcau-{mioip&He`L}fc.zjhZehzly$x`~ _be,tdrsm{dTnaePmdo-jbi>39:;<=>?0163?56789:;<=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?012346=6&9;87<>5IORVP?gcl{k757>112924?OIX\^1mij}b=;94;7338?1EC^ZT;CG@WG;9=0;2<:4148JJUSS2HNO^O2>4;2=55=62@D[YY4xe`>3>58682;1EC^ZT;uff96=87;97><5IORVP?BNI59:6=0>2:11>LHW]]0OEO2<1;2=56=4:3CE\XZ5dhlb867=87;87><5IORVP?bnfk68=7>112906?IR\Y__6IAN<2394;743:81CXZ_UU8GKG:493:5=85<2;MVPUSS2me~xl2<1;2=50=4:3E^X][[:emvpg:493:5=<5;:HLSQQ<CAYK7?7>11097>LHW]]0OE]L33;2=55=32@D[YY4XE@>0>58682>1EC^ZT;UFF95=87;9794@UURVP?BHXH686=0>2:69KPRW]]0OC]L33;2=b>2qnq<;jk?>53/24==FLMXJ0=06;@FGVD:68730MIJ]A=32:<=FLMXJ0<<19:CG@WG;9:4i7LJKR@>20?6912KOH_O315<;?DBCZH6:255NDEPB878?3HNO^L2<>99B@ATF4=437LJKR@>6:==FLMXJ0;07;@FGVD:0611JHI\N<9<;?DBCZH62255NDEPA858>3HNO^O2>0?;8EABUJ5;:245NDEPA844912KOH_L312<a?DBCZK6:87>19:CG@WD;9=437LJKRC>2:==FLMXI0?07;@FGVG:4611JHI\M<5<;?DBCZK6>255NDEPA838?3HNO^O28>99B@ATE41437LJKRC>::6=FDE90NX<7;CWP[LHAGh1HM^MNDDKMEd=DIZIJHHGABc9@EVEFLLE^XLl4C@Q@EACH]]H:>6MGEBI\HLEBFZOTXT^J4:AOOD2<KEAI56M@MLKWP@B6<2ID^HQHEOGQEQOHFVCEJB94CSGBP@B13MCJ0=08;EKB8469?2NBM1?>>69GMD:6:7=0HDO312<4?AOF48>5;6JFA=36:2=CAH6::394DHC?52803MCJ0<617:FJE97>6?1OEL2>>69GMD:587=0HDO320<4?AOF4;85;6JFA=00:2=CAH698394DHC?60803MCJ0?817:FJE9406>1OEL2=8?58@LG;:04=7IGN<3<4?AOF4::556JFA=12>5803MCJ0>?16:FJE959>2NBM1:16:FJE939>2NBM1816:FJE919>2NBM1616:FJE9?9>2NBN1>17:FJF9776>1OEO2>1?58@LD;9;4<7IGM<01=3>BNJ5;?2:5KIC>21;1<L@H7=;08;EKA8419?2NBN1?7>69GMG:617<0HDL31?58@LD;:94<7IGM<33=3>BNJ5892:5KIC>17;1<L@H7>908;EKA8739?2NBN1<9>69GMG:5?7=0HDL329<4?AOE4;35:6JFB=0=3>BNJ59;245KIC>05?69?2NBN1=>>79GMG:46?1OEO2;>79GMG:26?1OEO29>79GMG:06?1OEO27>79GMG:>6>1OE]O30?58@LVF484<7IG_A=0==>BNXH686=08;EKSE959?2NB\O2?>69GMUD;97=0HD^M<3<:?AOWJ591<394DHRA86813MEJ0=08;EMB8469?2NDM1?>>69GKD:6:7=0HBO312<4?AIF48>5;6J@A=36:2=CGH6::394DNC?52803MEJ0<617:FLE97>6?1OCL2>>69GKD:587=0HBO320<4?AIF4;85;6J@A=00:2=CGH698394DNC?60803MEJ0?817:FLE9406>1OCL2=8?58@JG;:04=7IAN<3<4?AIF4::556J@A=12>5803MEJ0>?16:FLE959>2NDM1:16:FLE939>2NDM1816:FLE919>2NDM1616:FLE9?9?2NDMR\JG79GKG:76>1OCO2>0?58@JD;984<7IAM<00=3>BHJ5;82:5KOC>20;1<LFH7=808;EMA8409?2NDN1?8>69GKG:607=0HBL318<5?AIE484<7IAM<32=3>BHJ58:2:5KOC>16;1<LFH7>>08;EMA8729?2NDN1<:>69GKG:5>7=0HBL326<4?AIE4;25;6J@B=0::3=CGK692:5KOC>04;?<LFH7?<4?>69GKG:497<0HBL33?48@JD;<7<0HBL35?48@JD;>7<0HBL37?48@JD;07<0HBL39?58@JDXZLM<7IA_A=2=3>BHXH6:2:5KOQC?6;?<LFZJ0>4?>69GKUG;;7=0HB^M<1<4?AIWJ5;5;6J@PC>1:<=CGYH7?7>17:FLTG:46:1NBL=4EO@6?CGK[L;0K>5HNE:8MKOSXV:;46GAIUR\44><AGC_\R>=8:KMMQVX8:20ECG[P^27<>OIA]ZT<864IOKWTZ6102CEEY^P0658MKOSW9:<7D@FT^223>OIA]U;>:5FNHV\461<AGC_S=:8;HLJPZ62?2CEEYQ?669JJLRX8>=0ECG[_1:4?LHN\V:2;6GAIU]3E2=NF@^T<O94IOKW[5E03@DBXR>K7:KMMQY7M>1BBDZP0G58MKOSW8:<7D@FT^323>OIA]U:>:5FNHV\561<AGC_S<:8;HLJPZ72?2CEEYQ>669JJLRX9>=0ECG[_0:4?LHN\V;2;6GAIU]2E2=NF@^T=O94IOKW[4E03@DBXR?K7:KMMQY6M>1BBDZP1G58MKOSW;:<7D@FT^023>OIA]U9>:5FNHV\661<AGC_S?:8;HLJPZ42?2CEEYQ=669JJLRX:>=0ECG[_3:4?LHN\V82;6GAIU]1E2=NF@^T>O94IOKW[7E03@DBXR<K7:KMMQY5M>1BBDZP2G58MKOSW::<7D@FT^123>OIA]U8>:5FNHV\761<AGC_S>:8;HLJPZ52?2CEEYQ<669JJLRX;>=0ECG[_2:4?LHN\V92;6GAIU]0E2=NF@^T?O94IOKW[6E03@DBXR=K7:KMMQY4M>1BBDZP3G48MKOSWH<0ECG[_C;8MKOSWOCGI<<4IOTFVQYDDBUOCLQ]EF31?LHQM[^TOAEPDN@\V@A13EEJHHJ8;MMDMFGKk2Gjfb|Yesqjkke<E`dd~[k}shmm7>H68=1E==>;;O3351=I998?7C??359M55233G;;995A1147?K77?=1E==6;;O33=6=I98>0B<??4:L2542<F8;986@>1268J473<2D:=8:4N0350>H69>>0B<?74:L25<5<F88?7C?=059M57733G;9>95A1317?K75<=1E=?8;;O31<1=I9;387C?<4:L2752<F89:86@>3368J454<2D:?9:4N0160>H6;?>0B<=84:L27=2<F892?6@>459M51633G;?=95A1507?K73;=1E=9:;;O3711=I9=<?7C?;759M51>33G;?5>5A1468J437<2D:9<:4N0710>H6=:>0B<;;4:L2102<F8?=86@>5668J43?<2D:94=4N040?K70;2D:4>5A1808J75<F;:87C<>3:L166=I::90B?:<;O067>H5>:1E>:=4N3:0?K4>:2D8?6@<029M745<F:887C=<3:L006=I;<90B>8<;O147>H40:1E?4<4N518J1643G>:?6@;229M065<F=>87C::3:L736=I<080B8=4N420?K36;2D>>>5A5218J0243G?>?6@:629M125<F<287C;62:L57>H18:1E:<=4N700?K04;2D=8>5A6418J3043G<<?6@9829M2<4<F>90B:><;O527>H0::1E;>=4N660?K12;2D<:>5A7618J2>43G=2>6@73:L;46=I0890B5<<;O:07>H?<:1E48=4N940?K>0;2D34>5A8808J<5<F0:87C7>3:L:66=I1:90B4:<;O;67>H>>:1E5:=4N8:0?K?>n2DISO[\PHL\TWIW[>1EIYY@RJ68JJHB12DDSNFNNFG1?JM63Y>0\L\[a:RJJZDR[@NSn6^FN^@VWKGJM?1YM@L>6g9QEHYBP]OE_DAA_@d8VDKXMQ^NB^G@N^@`?WCFLV]BHYFPAb9QADBX_@N_DRL9;SGDG@G13[OLOHL7;RCUAAGSI890_DCPCNNOMVOHFVICINE9;RMVVFC03ZX]MAQN7:QQRDJXJ=1X__O;;RQQF1=SQYO>86[?/cnh[hcjWnoeio{os-ueioc&jy~"|nmmmlt^6Z&{kf"!y4^kmmq(uid%_^XKPDQ,PMKAKMVZYE@ [DQ77?P6(jeaTahcPgdlfvdrhz&|j`dj!crvq+wgjdfe{W<S!r`o-v*p3W`dbx#|nm.VQQ@YCX'YBBJBJ_QPJI+RCXh1^_H\PAMKBWf=R[LXTZD]FBMG0?SED12\BIZQ[YQG5?RCF494=7ZKN<0<5?RCF4;437ZKN<283:3=PMH682;5XEC>3:3=PMK6:2;5XEC>1:==PMK686=09;VGA868d3^XBXHQBOEG\Ef=PZ@^NS@AKE^@g?RTN\LU\EIZG_@f8SWOSMV]BHYFPB0f8\LJNFQ'SHO.?.0"PPPD'8';+M^MFI79[WQJNJ>1S_YQHNE`8\ZEHZLUBBKA9;Yfa[Lba3QncS]|fmWgqwlii991Sh`QBakmqR`ttafd:<6Vkm^OjjjtQm{ybcc64aefqe-6.02koho'1(:8eabui!8"46okdsc+7,><imnym%:&8:cg`wg/= 20mij}a)4*<>gcl{k#;$64aefqe->.02koho'9(:8eabui5:546okdsc?5;><imnym1<18:cg`wg;;720mij}a=6=<>gcl{k79364aefqe90902koho37?:8eabui525m6okdsc?=?6902koho39?:8eabuj!:"46okds`+5,><imnyn%<&8:cg`wd/; 20mij}b)6*<>gcl{h#9$64aefqf-0.02kohl'7(:8eabuj!2"46okds`+=,><imnyn1>18:cg`wd;9720mij}b=0=<>gcl{h7?364aefqf92902kohl35?:8eabuj5<546okds`?3;><imnyn161a:cg`wd;13:546okds`?=;543kf`S`kb_fgm[s4X0%*Seagax!ALV@&@mgoymya} 02-5+64W`z886mck`68gime?2nieyk}r69gmkg/8 =0hd`n(0+;?aoii!;;%55kioc+54/?3mcem%?=)99gmkg/9:#37igaa)37-==cagk#=8'7;ekme-71!11oeco'16+;?aoii!;3%55kioc+5</03mcem%<&8:fjjd.58 20hd`n(33*<>bnfh"9>$64dhlb,75.02nbbl&=4(:8`lhf ;?"46jfn`*12,><l`dj$?9&8:fjjd.50 20hd`n(3;*3>bnfh"8%55kioc+75/?3mcem%=>)69gmkg/< =0hd`n(4+4?aoii!<";6jfn`*4-2=cagk#4$94dhlb,</03mcem1>18:fjjd:68720hd`n<03=<>bnfh6:>364dhlb845902nbbl2>4?:8`lhf48?546jfn`>22;><l`dj0<918:fjjd:60720hd`n<0;=3>bnfh6:255kioc?658?3mcem1<>>99gmkg;:;437igaa=00:==cagk7>907;ekme942611oeco327<;?aoii58<255kioc?6=8?3mcem1<6>69gmkg;:720hd`n<22=e>bnfh68=7>18:fjjd:497=0hd`n<2<4?aoii5>5;6jfn`>6:2=cagk7:394dhlb82803mcem1617:fjjd:>6>1oecl'0(58`lhe 8#37igab)33-==cagh#=<'7;ekmf-75!11oecl'12+;?aoij!;?%55kio`+50/?3mcen%?9)99gmkd/9>#37igab)3;-==cagh#=4'8;ekmf-4.02nbbo&=0(:8`lhe ;;"46jfnc*16,><l`di$?=&8:fjjg.5< 20hd`m(37*<>bnfk"9:$64dhla,71.02nbbo&=8(:8`lhe ;3";6jfnc*0-==cagh#?='7;ekmf-56!>1oecl'4(58`lhe <#<7igab)4*3>bnfk"<%:5kio`+<,1<l`di$4'8;ekmf96902nbbo2>0?:8`lhe48;546jfnc>26;><l`di0<=18:fjjg:6<720hd`m<07=<>bnfk6::364dhla841902nbbo2>8?:8`lhe4835;6jfnc>2:==cagh7>=07;ekmf946611oecl323<;?aoij588255kio`?618?3mcen1<:>99gmkd;:?437igab=04:==cagh7>507;ekmf94>6>1oecl32?:8`lhe4::5m6jfnc>05?6902nbbo2<1?58`lhe4:4<7igab=6=3>bnfk6>2:5kio`?2;1<l`di0:08;ekmf9>9?2nbbo26>99gkprf 9#37iazt`*2-<=cg|~j$<>&9:flqqg/98#27iazt`*26,?<lfm%?<)89gkprf 8>"56j`uuc+50/>3me~xl&>6(;8`jssi!;<%45kotvb,4>.12ndyyo'18+;?air|h"9%45kotvb,76.12ndyyo'20+:?air|h"9>$74dnwwe-44!01ocxzn(36*=>bh}}k#>8'6;emvpd.5> 30hb{{a)04-<=cg|~j$?6&9:flqqg/:0#37iazt`*0-<=cg|~j$>>&9:flqqg/;8#37iazt`*7-==cg|~j$8'7;emvpd.1!11ocxzn(6+;?air|h"3%55kotvb,</?3me~xl2?>89gkprf48:556j`uuc?548>3me~xl2>2?;8`jssi5;8245kotvb842912ndyyo314<:?air|h6::374dnwwe970601ocxzn<0:==>bh}}k7=407;emvpd:6601ocxzn<32==>bh}}k7><06;emvpd:5:730hb{{a=00:<=cg|~j0?:19:flqqg;:<427iazt`>12;?<lfm1<8>89gkprf4;2556j`uuc?6<8?3me~xl2=>89gkprf4::5n6j`uuc?74<7601ocxzn<23=<>bh}}k7?364dnwwe92902ndyyo35?:8`jssi5<546j`uuc?3;><lfm1618:flqqg;1720hb{{b)2*<>bh}}h#=$74dnwwf-77!01ocxzm(03*=>bh}}h#=?'6;emvpg.6; 30hb{{b)37-<=cg|~i$<;&9:flqqd/9?#27iaztc*23,?<lfn%?7)89gkpre 83"46j`uu`+6,?<lfn%<?)89gkpre ;;"56j`uu`+67/>3me~xo&=3(;8`jssj!8?%45kotva,73.12ndyyl'27+:?air|k"9;$74dnwwf-4?!01ocxzm(3;*<>bh}}h#?$74dnwwf-57!01ocxzm(23*<>bh}}h#8$64dnwwf-3.02ndyyl'6(:8`jssj!="46j`uu`+<,><lfn%7&8:flqqd;8730hb{{b=33:<=cg|~i0<?19:flqqd;9;427iaztc>27;?<lfn1?;>89gkpre48?556j`uu`?538>3me~xo2>7?;8`jssj5;3245kotva84?902ndyyl31?;8`jssj58;245kotva877912ndyyl323<:?air|k69?374dnwwf943601ocxzm<37==>bh}}h7>;06;emvpg:5?730hb{{b=0;:<=cg|~i0?718:flqqd;:730hb{{b=13:g=cg|~i0>?50?;8`jssj59:255kotva868?3me~xo2;>99gkpre4<437iaztc>5:==cg|~i0:07;emvpg:?611ocxzm<8<;?`bnn;dlh>5jn`18akd?3gmhnxgcdg9seqrbzgUi`fQbel0b?ugs|lxeSobd_lgn(gjlWdofSjka_w0\<)HHFL&ECCK<769seqrbzgUi`fQbel.ahnYjmdUlicQy2^:/fYoizUyijmjb<2/gZnf{Vxnknkn=1.`[hcjW}s{i0<#c^rqmhYsqyo6=!mPshljpdYqie7; nQ}e`f\slbs`Vh6??"l_sgb`Zqnl}bTm0==,b]gmvgedlU|m`Pbit\gjjk59&hSd`ft^djh`Yiido6bbQlod]emicXdfkoii"l_vpjp`YjgmoTn0@@_BJBJBC+kV}yeykPmnff[d;IGVICMCIJ,b]nq}YwayogeckPsucdav;7$jUcm~Qbel]lqqvr|Vxnk~Qm=1.`[iiflVceeyQiimg>4)eX`hyTahcPotvsqqYumnyTm0>#c^uqmqcXllzdRl21107(fYpz`~nSikti]b9465<%iTdl}Psrpa95*dWakxS`{w_nwwtprXzlmxSo3?,b]kevYt{{k6<!mPh`q\ip~Xg|~{yyQ}efq\e86+kVkohoPwhfwl877$jUjhi|m_vkgpm;68%iThhhnumv\`drf59&hSx}j_da`95*dWhflcg{hl?2(fYcazki`hQxasl\fmpXzhdli0>#c^uqmqcX`ndRl233.`[rtn|lU|eizg_`?06)eXzlkoSikti]a9465<%iT~hok_egspmYf58:98!mPbxvf[vo}m43'oR}fm^alhiotafdToeklk<COH)eXkfgfccQllj?3(fYr{lUym`l>6cufvZtt|Vhcz0>#c^ufeZqnl}b6=!mPh`q\akd:9%iTdl}Peoc>5)eXlhT{dj{h<3/gZunf`~iS{oc=1.`khvhfldScobe<rbpqcufVhggRcjm-a\qvcXjp~nSzkm=1.`[pubWksiRyja<2/gZstmVnnjl{ct^fbpd;6$t8=7}o{tdpm[gjlWdofSobd_lgn[bciW8T4Rv|t^35?wc`klk=7khcd`4?vdn|lxy86}|r`68wvte>2}nm%>&8:ufe96=87<0{ho30?48s`d/8 20{hl30;2=2>qbj5:5qMN4`08DE~62O0?6<u\478072<328994km>:23`76}i:991=6`=0587?!4793;mh6s\458072<328994km>:23`76=T9:91?>o50;306=`d939:o>=4S56976g=83;8>5hl1;12g60<l:9i6=4>:0yP03<4;>0?6<==8ga2>67d;:1}X<k<:182>4<>jrY?:7=<7;69564?nj;1?<m<3:&2a`<6;=1]>=<52zw270<63|;8:7>4}%3g3?7>3k98n7>59`80><g|@8oh7W=l:9y:>d<22?0:=7?=:e8f>x"6m108?o5+212967`<a:936=44i21:>5<<a:>?6=4+1e;9713<f8n36=54i264>5<#9m31?964n0f;>5=<a;:n6=4+1e;964><f8n36=54i32g>5<#9m31><64n0f;>4=<a;:h6=4+1e;964><f8n36?54i32a>5<#9m31><64n0f;>6=<a;:j6=4+1e;964><f8n36954i32:>5<#9m31><64n0f;>0=<a;:36=4+1e;964><f8n36;54i324>5<#9m31><64n0f;>2=<a;:=6=4+1e;964><f8n36554i326>5<#9m31><64n0f;><=<a;886=4+1e;967b<f8n36=54i301>5<#9m31>?j4n0f;>4=<a;8:6=4+1e;967b<f8n36?54i303>5<#9m31>?j4n0f;>6=<a;;m6=4+1e;967b<f8n36954i33f>5<#9m31>?j4n0f;>0=<a;;o6=4+1e;967b<f8n36;54i33`>5<#9m31>?j4n0f;>2=<a;;i6=4+1e;967b<f8n36554i33b>5<#9m31>?j4n0f;><=<g;in6=4+1e;96`b<f8n36=54o3ag>5<#9m31>hj4n0f;>4=<g;ii6=4+1e;96`b<f8n36?54o3ab>5<#9m31>hj4n0f;>6=<g;i26=4+1e;96`b<f8n36954o3a;>5<#9m31>hj4n0f;>0=<g;i<6=4+1e;96`b<f8n36;54o3a5>5<#9m31>hj4n0f;>2=<g;i>6=4+1e;96`b<f8n36554o3a7>5<#9m31>hj4n0f;><=<g;i86=4+1e;96`b<f8n36l54o3a1>5<#9m31>hj4n0f;>g=<g;i;6=4+1e;96`b<f8n36n54o3`e>5<#9m31>hj4n0f;>a=<g;hn6=4+1e;96`b<f8n36h54o3`g>5<#9m31>hj4n0f;>c=<g;hh6=4+1e;96`b<f8n36<>4;n0af?6=,8n26?kk;o3g<?7632e9nl4?:%3g=?4bl2d:h54>2:9l6g?=83.:h44=ee9m5a>=9:10c?l7:18'5a?=:ln0b<j7:068?j4e?3:1(<j6:3gg?k7c03;>76a=d583>!7c138nh6`>d9822>=h:m91<7*>d881aa=i9m21=:54o3f1>5<#9m31>hj4n0f;>4><3f8o=7>5$0f:>7cc3g;o47?6;:m1`5<72-;o57<jd:l2`=<6i21d>nh50;&2`<<5mm1e=i651c98k7ed290/=i752df8j4b?28i07b<l1;29 4b>2;oo7c?k8;3g?>i5j?0;6)?k9;0f`>h6l10:i65`2c794?"6l009ii5a1e:95c=<g::m6=4+1e;977c<f8n36=54o22f>5<#9m31??k4n0f;>4=<g::h6=4+1e;977c<f8n36?54o22a>5<#9m31??k4n0f;>6=<g::j6=4+1e;977c<f8n36954o22:>5<#9m31??k4n0f;>0=<g::36=4+1e;977c<f8n36;54o224>5<#9m31??k4n0f;>2=<g::=6=4+1e;977c<f8n36554o226>5<#9m31??k4n0f;><=<g::?6=4+1e;977c<f8n36l54o220>5<#9m31??k4n0f;>g=<g:::6=4+1e;977c<f8n36n54o223>5<#9m31??k4n0f;>a=<g;lm6=4+1e;977c<f8n36h54o3df>5<#9m31??k4n0f;>c=<g;lo6=4+1e;977c<f8n36<>4;n0eg?6=,8n26><j;o3g<?7632e9jo4?:%3g=?55m2d:h54>2:9l6cg=83.:h44<2d9m5a>=9:10c?h6:18'5a?=;;o0b<j7:068?j4a03:1(<j6:20f?k7c03;>76a<1483>!7c1399i6`>d9822>=h;8>1<7*>d8806`=i9m21=:54o230>5<#9m31??k4n0f;>4><3f9:>7>5$0f:>64b3g;o47?6;:m054<72-;o57==e:l2`=<6i21d?<>50;&2`<<4:l1e=i651c98k66c290/=i7533g8j4b?28i07b=?2;29 4b>2:8n7c?k8;3g?>i5n>0;6)?k9;11a>h6l10:i65`2g494?"6l008>h5a1e:95c=<a;9;6=44i312>5<<a;>h6=4+1e;963d<f8n36=54i36a>5<#9m31>;l4n0f;>4=<a;>26=4+1e;963d<f8n36?54i36;>5<#9m31>;l4n0f;>6=<a;><6=4+1e;963d<f8n36954i365>5<#9m31>;l4n0f;>0=<a;>>6=4+1e;963d<f8n36;54i367>5<#9m31>;l4n0f;>2=<a;>86=4+1e;963d<f8n36554i361>5<#9m31>;l4n0f;><=<a;>:6=4+1e;963d<f8n36l54i363>5<#9m31>;l4n0f;>g=<a;9n6=4+1e;963d<f8n36n54i31g>5<#9m31>;l4n0f;>a=<a;9h6=4+1e;963d<f8n36h54i31a>5<#9m31>;l4n0f;>c=<a;9j6=4+1e;963d<f8n36<>4;h00=?6=,8n26?8m;o3g<?7632c9?54?:%3g=?41j2d:h54>2:9j661=83.:h44=6c9m5a>=9:10e?=9:18'5a?=:?h0b<j7:068?l44=3:1(<j6:34a?k7c03;>76g=5383>!7c138=n6`>d9822>=n:<;1<7*>d8812g=i9m21=:54i373>5<#9m31>;l4n0f;>4><3`8?j7>5$0f:>70e3g;o47?6;:k10`<72-;o57<9b:l2`=<6i21b>9j50;&2`<<5>k1e=i651c98m72f290/=i7527`8j4b?28i07d<<f;29 4b>2;<i7c?k8;3g?>o5;=0;6)?k9;05f>h6l10:i65f22194?"6l009:o5a1e:95c=<a;2o6=4+1e;96de<f8n36=54i3:`>5<#9m31>lm4n0f;>4=<a;2j6=4+1e;96de<f8n36?54i3::>5<#9m31>lm4n0f;>6=<a;236=4+1e;96de<f8n36954i3:4>5<#9m31>lm4n0f;>0=<a;2=6=4+1e;96de<f8n36;54i3:6>5<#9m31>lm4n0f;>2=<a;2?6=4+1e;96de<f8n36554i3:0>5<#9m31>lm4n0f;><=<a;296=4+1e;96de<f8n36l54i3:2>5<#9m31>lm4n0f;>g=<a;=m6=4+1e;96de<f8n36n54i35f>5<#9m31>lm4n0f;>a=<a;=o6=4+1e;96de<f8n36h54i35`>5<#9m31>lm4n0f;>c=<a;=i6=4+1e;96de<f8n36<>4;h04e?6=,8n26?ol;o3g<?7632c9;44?:%3g=?4fk2d:h54>2:9j62>=83.:h44=ab9m5a>=9:10e?98:18'5a?=:hi0b<j7:068?l40>3:1(<j6:3c`?k7c03;>76g=9283>!7c138jo6`>d9822>=n:081<7*>d881ef=i9m21=:54i3;2>5<#9m31>lm4n0f;>4><3`82<7>5$0f:>7gd3g;o47?6;:k1<c<72-;o57<nc:l2`=<6i21b>5k50;&2`<<5ij1e=i651c98m7>e290/=i752`a8j4b?28i07d<70;29 4b>2;kh7c?k8;3g?>o5?<0;6)?k9;0bg>h6l10:i65f26694?"6l009mn5a1e:95c=<j8oo6=4>:183M7bk2.:i54>ee9l5a0=831vnh;50;394?6|@8oh7)?j8;g6?jc32900qo=m:18b4?5=1kqC=hm4Z2a955}>2h0>6;4>1;31>a<b28;1=?46:`86>3<c2l0v(<k7:21f?!262:9h7):::21g?!7c93;o96g<3983>>o4;00;66g<4383>>o4<:0;66g<3g83>>o4<90;66g<4583>!7c139?96`>d983?>o4<>0;6)?k9;17<>h6l10;76g=0d83>!7c138:46`>d983?>o58m0;6)?k9;02<>h6l10:76g=0b83>!7c138:46`>d981?>o58k0;6)?k9;02<>h6l10876g=0`83>!7c138:46`>d987?>o5800;6)?k9;02<>h6l10>76g=0983>!7c138:46`>d985?>o58>0;6)?k9;02<>h6l10<76g=0783>!7c138:46`>d98;?>o58<0;6)?k9;02<>h6l10276g=2283>!7c1389h6`>d983?>o5:;0;6)?k9;01`>h6l10:76g=2083>!7c1389h6`>d981?>o5:90;6)?k9;01`>h6l10876g=1g83>!7c1389h6`>d987?>o59l0;6)?k9;01`>h6l10>76g=1e83>!7c1389h6`>d985?>o59j0;6)?k9;01`>h6l10<76g=1c83>!7c1389h6`>d98;?>o59h0;6)?k9;01`>h6l10276a<4083>>i5kl0;6)?k9;0f`>h6l10;76a=ce83>!7c138nh6`>d982?>i5kk0;6)?k9;0f`>h6l10976a=c`83>!7c138nh6`>d980?>i5k00;6)?k9;0f`>h6l10?76a=c983>!7c138nh6`>d986?>i5k>0;6)?k9;0f`>h6l10=76a=c783>!7c138nh6`>d984?>i5k<0;6)?k9;0f`>h6l10376a=c583>!7c138nh6`>d98:?>i5k:0;6)?k9;0f`>h6l10j76a=c383>!7c138nh6`>d98a?>i5k90;6)?k9;0f`>h6l10h76a=bg83>!7c138nh6`>d98g?>i5jl0;6)?k9;0f`>h6l10n76a=be83>!7c138nh6`>d98e?>i5jj0;6)?k9;0f`>h6l10:<65`2c`94?"6l009ii5a1e:954=<g;hj6=4+1e;96`b<f8n36<<4;n0a=?6=,8n26?kk;o3g<?7432e9n54?:%3g=?4bl2d:h54>4:9l6g1=83.:h44=ee9m5a>=9<10c?j;:18'5a?=:ln0b<j7:048?j4c;3:1(<j6:3gg?k7c03;<76a=d383>!7c138nh6`>d982<>=h:m;1<7*>d881aa=i9m21=454o3f3>5<#9m31>hj4n0f;>4g<3f8hj7>5$0f:>7cc3g;o47?m;:m1gf<72-;o57<jd:l2`=<6k21d>n?50;&2`<<5mm1e=i651e98k7d1290/=i752df8j4b?28o07b<m5;29 4b>2;oo7c?k8;3e?>i48o0;6)?k9;11a>h6l10;76a<0d83>!7c1399i6`>d982?>i48j0;6)?k9;11a>h6l10976a<0c83>!7c1399i6`>d980?>i48h0;6)?k9;11a>h6l10?76a<0883>!7c1399i6`>d986?>i4810;6)?k9;11a>h6l10=76a<0683>!7c1399i6`>d984?>i48?0;6)?k9;11a>h6l10376a<0483>!7c1399i6`>d98:?>i48=0;6)?k9;11a>h6l10j76a<0283>!7c1399i6`>d98a?>i4880;6)?k9;11a>h6l10h76a<0183>!7c1399i6`>d98g?>i5no0;6)?k9;11a>h6l10n76a=fd83>!7c1399i6`>d98e?>i5nm0;6)?k9;11a>h6l10:<65`2ga94?"6l008>h5a1e:954=<g;li6=4+1e;977c<f8n36<<4;n0ee?6=,8n26><j;o3g<?7432e9j44?:%3g=?55m2d:h54>4:9l6c>=83.:h44<2d9m5a>=9<10c>?::18'5a?=;;o0b<j7:048?j56<3:1(<j6:20f?k7c03;<76a<1283>!7c1399i6`>d982<>=h;881<7*>d8806`=i9m21=454o232>5<#9m31??k4n0f;>4g<3f9:<7>5$0f:>64b3g;o47?m;:m04a<72-;o57==e:l2`=<6k21d?=<50;&2`<<4:l1e=i651e98k7`0290/=i7533g8j4b?28o07b<i6;29 4b>2:8n7c?k8;3e?>o5;90;66g=3083>>o5<j0;6)?k9;05f>h6l10;76g=4c83>!7c138=n6`>d982?>o5<00;6)?k9;05f>h6l10976g=4983>!7c138=n6`>d980?>o5<>0;6)?k9;05f>h6l10?76g=4783>!7c138=n6`>d986?>o5<<0;6)?k9;05f>h6l10=76g=4583>!7c138=n6`>d984?>o5<:0;6)?k9;05f>h6l10376g=4383>!7c138=n6`>d98:?>o5<80;6)?k9;05f>h6l10j76g=4183>!7c138=n6`>d98a?>o5;l0;6)?k9;05f>h6l10h76g=3e83>!7c138=n6`>d98g?>o5;j0;6)?k9;05f>h6l10n76g=3c83>!7c138=n6`>d98e?>o5;h0;6)?k9;05f>h6l10:<65f22;94?"6l009:o5a1e:954=<a;936=4+1e;963d<f8n36<<4;h003?6=,8n26?8m;o3g<?7432c9?;4?:%3g=?41j2d:h54>4:9j663=83.:h44=6c9m5a>=9<10e?;=:18'5a?=:?h0b<j7:048?l4293:1(<j6:34a?k7c03;<76g=5183>!7c138=n6`>d982<>=n:=l1<7*>d8812g=i9m21=454i36f>5<#9m31>;l4n0f;>4g<3`8?h7>5$0f:>70e3g;o47?m;:k10d<72-;o57<9b:l2`=<6k21b>>h50;&2`<<5>k1e=i651e98m753290/=i7527`8j4b?28o07d<<3;29 4b>2;<i7c?k8;3e?>o50m0;6)?k9;0bg>h6l10;76g=8b83>!7c138jo6`>d982?>o50h0;6)?k9;0bg>h6l10976g=8883>!7c138jo6`>d980?>o5010;6)?k9;0bg>h6l10?76g=8683>!7c138jo6`>d986?>o50?0;6)?k9;0bg>h6l10=76g=8483>!7c138jo6`>d984?>o50=0;6)?k9;0bg>h6l10376g=8283>!7c138jo6`>d98:?>o50;0;6)?k9;0bg>h6l10j76g=8083>!7c138jo6`>d98a?>o5?o0;6)?k9;0bg>h6l10h76g=7d83>!7c138jo6`>d98g?>o5?m0;6)?k9;0bg>h6l10n76g=7b83>!7c138jo6`>d98e?>o5?k0;6)?k9;0bg>h6l10:<65f26c94?"6l009mn5a1e:954=<a;=26=4+1e;96de<f8n36<<4;h04<?6=,8n26?ol;o3g<?7432c9;:4?:%3g=?4fk2d:h54>4:9j620=83.:h44=ab9m5a>=9<10e?7<:18'5a?=:hi0b<j7:048?l4>:3:1(<j6:3c`?k7c03;<76g=9083>!7c138jo6`>d982<>=n:0:1<7*>d881ef=i9m21=454i3:e>5<#9m31>lm4n0f;>4g<3`83i7>5$0f:>7gd3g;o47?m;:k1<g<72-;o57<nc:l2`=<6k21b>5>50;&2`<<5ij1e=i651e98m712290/=i752`a8j4b?28o07d<84;29 4b>2;kh7c?k8;3e?>i5;;0;66l>fg83>4<729q/=h65e49K5cc<@8oh7bk;:188yg7bi3:1o?4?:1y'5`>=9mk0D<hj;I3fg>\4k3ip;765b;a956<6<3;>6<85f;33>41=910vbo:50:lg2?6<,88n6?5+13d96>"b>390(h953:&f<?5<,l31?6*ja;18 `d=;2.:i<4j3:&2a1<53-on6>5+eg80?!`72:1/j<4<;%d1>6=#n:087)h;:29'b0<43-l=6>5+f680?!`?2:1/j44<;%db>6=#nk087)hl:29'ba<43-ln6>5+fg80?!778390(<>>:29'554=;2.:<>4<;%330?5<,8:>6>5+11497>"68>087)??8;18 46>2:1/==o53:&24g<43-;;o7=4$02g>6=#99o1?6*>0g80?!768390(<?>:29'544=;2.:=>4<;%320?5<,8;>6>5+10497>"69>087)?>8;18 47>2:1/=<o53:&25g<43-;:o7=4$03g>6=#98o1?6*>1g80?!758390(<<>:29'574=;2.:>>4<;%310?5<,88>6>5+13497>"6:>087)?=8;18 44>2:1/=?o53:&26g<43-;9o7=4$00g>6=#9::1=i=4$012>`5<,8996h=4$0fa>4b43-;oo7?k3:l2`a<6:2d:hh4>2:&2a7<4i2.no7=4$df97>"6n00:h95+1gc95a2<f8li6<<4n0d`>44<,8o>6?5f3e83>>o4m3:17d:=:188m15=831bi<4?::k2`c<722c:i=4?::kf6?6=3`;n:7>5;h3f3?6=3f9m6=44o5294?=n:90;6)?k9;3e?k7c03:07d?j:18'5a?=9o1e=i651:9j5a<72-;o57?i;o3g<?4<3`;h6=4+1e;95c=i9m21?65f1c83>!7c13;m7c?k8;68?l4>290/=i751g9m5a>==21b>54?:%3g=?7a3g;o4784;h04>5<#9m31=k5a1e:93>=n:?0;6)?k9;3e?k7c03207d<::18'5a?=9o1e=i659:9j61<72-;o57?i;o3g<?g<3`886=4+1e;95c=i9m21n65f2383>!7c13;m7c?k8;a8?l46290/=i751g9m5a>=l21b=l4?:%3g=?7a3g;o47k4;h13>5<#9m31>k5a1e:94>=n:l0;6)?k9;0e?k7c03;07d<k:18'5a?=:o1e=i652:9j6f<72-;o57<i;o3g<?5<3`8i6=4+1e;96c=i9m21865f3883>!7c138m7c?k8;78?l5?290/=i752g9m5a>=>21b?:4?:%3g=?4a3g;o4794;h15>5<#9m31>k5a1e:9<>=n;<0;6)?k9;0e?k7c03307d=;:18'5a?=:o1e=i65a:9j76<72-;o57<i;o3g<?d<3`996=4+1e;96c=i9m21o65f3083>!7c138m7c?k8;f8?l4f290/=i752g9m5a>=m21b:=4?:%3g=?3a3g;o47>4;h7f>5<#9m319k5a1e:95>=n=j0;6)?k9;7e?k7c03807d;m:18'5a?==o1e=i653:9j1d<72-;o57;i;o3g<?2<3`?26=4+1e;91c=i9m21965f5983>!7c13?m7c?k8;48?l30290/=i755g9m5a>=?21b9;4?:%3g=?3a3g;o4764;h76>5<#9m319k5a1e:9=>=n==0;6)?k9;7e?k7c03k07d;<:18'5a?==o1e=i65b:9j14<72-;o57;i;o3g<?e<3`?;6=4+1e;91c=i9m21h65f4g83>!7c13?m7c?k8;g8?l2b290/=i755g9m5a>=n21b8i4?:%3g=?3a3g;o47??;:k7g?6=,8n268h4n0f;>47<3`>i6=4+1e;91c=i9m21=?54i5c94?"6l00>j6`>d9827>=n<00;6)?k9;7e?k7c03;?76g;8;29 4b>2<l0b<j7:078?l00290/=i755g9m5a>=9?10e;850;&2`<<2n2d:h54>7:9j20<72-;o57;i;o3g<?7?32c=87>5$0f:>0`<f8n36<74;h40>5<#9m319k5a1e:95d=<a?81<7*>d886b>h6l10:n65f6083>!7c13?m7c?k8;3`?>o2l3:1(<j6:4d8j4b?28n07d;=:18'5a?==o1e=i651d98m11=83.:h44:f:l2`=<6n21b4<4?:%3g=?>73g;o47>4;h5e>5<#9m314=5a1e:95>=n?m0;6)?k9;:3?k7c03807d9l:18'5a?=091e=i653:9j3g<72-;o576?;o3g<?2<3`=j6=4+1e;9<5=i9m21965f7883>!7c132;7c?k8;48?l1?290/=i75819m5a>=?21b;:4?:%3g=?>73g;o4764;h55>5<#9m314=5a1e:9=>=n?<0;6)?k9;:3?k7c03k07d9;:18'5a?=091e=i65b:9j37<72-;o576?;o3g<?e<3`=:6=4+1e;9<5=i9m21h65f7183>!7c132;7c?k8;g8?l0a290/=i75819m5a>=n21b:h4?:%3g=?>73g;o47??;:k5`?6=,8n265>4n0f;>47<3`<h6=4+1e;9<5=i9m21=?54i7`94?"6l003<6`>d9827>=n>h0;6)?k9;:3?k7c03;?76g99;29 4b>21:0b<j7:078?l>?290/=i75819m5a>=9?10e5950;&2`<<?82d:h54>7:9j<3<72-;o576?;o3g<?7?32c397>5$0f:>=6<f8n36<74;h:7>5<#9m314=5a1e:95d=<a191<7*>d88;4>h6l10:n65f8383>!7c132;7c?k8;3`?>o0m3:1(<j6:928j4b?28n07d9<:18'5a?=091e=i651d98m3>=83.:h4470:l2`=<6n21b4i4?:%3g=?>d3g;o47>4;h:a>5<#9m314n5a1e:95>=n0h0;6)?k9;:`?k7c03807d66:18'5a?=0j1e=i653:9j=7<72-;o577>;o3g<?6<3`3;6=4+1e;9=4=i9m21=65f8g83>!7c133:7c?k8;08?l>b290/=i75909m5a>=;21b=k=50;&2`<<6n;1e=i650:9j5c7=83.:h44>f39m5a>=921b=k>50;&2`<<6n;1e=i652:9j5``=83.:h44>f39m5a>=;21b=k650;&2`<<6n>1e=i650:9j5c0=83.:h44>f69m5a>=921b=k;50;&2`<<6n>1e=i652:9j5c2=83.:h44>f69m5a>=;21dmn4?:%3g=?ge3g;o47>4;ncb>5<#9m31mo5a1e:95>=hi10;6)?k9;ca?k7c03807bo8:18'5a?=ik1e=i653:9le3<72-;o57om;o3g<?2<3fk>6=4+1e;9eg=i9m21965`a583>!7c13ki7c?k8;48?jg4290/=i75ac9m5a>=?21dm?4?:%3g=?ge3g;o4764;nc2>5<#9m31mo5a1e:9=>=hi90;6)?k9;ca?k7c03k07b7i:18'5a?=ik1e=i65b:9l=a<72-;o57om;o3g<?e<3f3h6=4+1e;9eg=i9m21h65`9c83>!7c13ki7c?k8;g8?j?f290/=i75ac9m5a>=n21d544?:%3g=?ge3g;o47??;:m:<?6=,8n26ll4n0f;>47<3f3<6=4+1e;9eg=i9m21=?54o8494?"6l00jn6`>d9827>=h1<0;6)?k9;ca?k7c03;?76a64;29 4b>2hh0b<j7:078?jd4290/=i75ac9m5a>=9?10co<50;&2`<<fj2d:h54>7:9lf4<72-;o57om;o3g<?7?32ei<7>5$0f:>dd<f8n36<74;nce>5<#9m31mo5a1e:95d=<gho1<7*>d88bf>h6l10:n65`ae83>!7c13ki7c?k8;3`?>if13:1(<j6:``8j4b?28n07b7j:18'5a?=ik1e=i651d98k<5=83.:h44nb:l2`=<6n21doh4?:%3g=?ec3g;o47>4;na`>5<#9m31oi5a1e:95>=hkh0;6)?k9;ag?k7c03807bm6:18'5a?=km1e=i653:9lg=<72-;o57mk;o3g<?2<3fi<6=4+1e;9ga=i9m21965`c783>!7c13io7c?k8;48?je2290/=i75ce9m5a>=?21do94?:%3g=?ec3g;o4764;na0>5<#9m31oi5a1e:9=>=hk;0;6)?k9;ag?k7c03k07bm>:18'5a?=km1e=i65b:9lfc<72-;o57mk;o3g<?e<3fhn6=4+1e;9ga=i9m21h65`be83>!7c13io7c?k8;g8?jdd290/=i75ce9m5a>=n21dno4?:%3g=?ec3g;o47??;:mae?6=,8n26nj4n0f;>47<3fh26=4+1e;9ga=i9m21=?54oc:94?"6l00hh6`>d9827>=hj>0;6)?k9;ag?k7c03;?76am6;29 4b>2jn0b<j7:078?jb2290/=i75ce9m5a>=9?10ci:50;&2`<<dl2d:h54>7:9l`6<72-;o57mk;o3g<?7?32eo>7>5$0f:>fb<f8n36<74;nf2>5<#9m31oi5a1e:95d=<gm:1<7*>d88``>h6l10:n65`cg83>!7c13io7c?k8;3`?>idj3:1(<j6:bf8j4b?28n07bm?:18'5a?=km1e=i651d98kg3=83.:h44ld:l2`=<6n21dho4?:%3g=?bf3g;o47>4;nf:>5<#9m31hl5a1e:95>=hl10;6)?k9;fb?k7c03807bj8:18'5a?=lh1e=i653:9la5<72-;o57ji;o3g<?6<3fnn6=4+1e;9`c=i9m21=65`de83>!7c13nm7c?k8;08?jbd290/=i75dg9m5a>=;21vn<k6:18`6?6=8r.:i54>d`9K5cc<@8oh7W=l:by4>=<e2j0:?7?;:07953<a28:1=:4>8;mf1<73gn=6=5+13g96>"6:o097)k9:29'a2<43-o36>5+e880?!cf2:1/io4<;%3f5?c43-;n87<4$dg97>"bn390(k>53:&e5?5<,o81?6*i3;18 c2=;2.m97=4$g497>"a?390(k653:&e=?5<,ok1?6*ib;18 ce=;2.mh7=4$gg97>"an390(<>?:29'557=;2.:<?4<;%337?5<,8:?6>5+11797>"68?087)??7;18 46?2:1/==753:&24d<43-;;n7=4$02`>6=#99n1?6*>0d80?!77n390(<??:29'547=;2.:=?4<;%327?5<,8;?6>5+10797>"69?087)?>7;18 47?2:1/=<753:&25d<43-;:n7=4$03`>6=#98n1?6*>1d80?!76n390(<<?:29'577=;2.:>?4<;%317?5<,88?6>5+13797>"6:?087)?=7;18 44?2:1/=?753:&26d<43-;9n7=4$00`>6=#9;n1?6*>3182`6=#9:;1i>5+1209a6=#9mh1=i=4$0f`>4b43g;oh7?=;o3ga?753-;n>7=n;%g`>6=#mm087)?i9;3g0>"6nh0:h95a1g`957=i9oi1=?5+1d796>o4l3:17d=j:188m14=831b8>4?::kf5?6=3`;oj7>5;h3f4?6=3`o96=44i0g5>5<<a8o<6=44o2d94?=h<90;66g=0;29 4b>28l0b<j7:198m4c=83.:h44>f:l2`=<632c:h7>5$0f:>4`<f8n36?54i0a94?"6l00:j6`>d980?>o6j3:1(<j6:0d8j4b?2=10e?750;&2`<<6n2d:h54:;:k1<?6=,8n26<h4n0f;>3=<a;=1<7*>d882b>h6l10<76g=6;29 4b>28l0b<j7:998m73=83.:h44>f:l2`=<>32c987>5$0f:>4`<f8n36l54i3194?"6l00:j6`>d98a?>o5:3:1(<j6:0d8j4b?2j10e??50;&2`<<6n2d:h54k;:k2e?6=,8n26<h4n0f;>`=<a::1<7*>d881b>h6l10;76g=e;29 4b>2;l0b<j7:098m7b=83.:h44=f:l2`=<532c9o7>5$0f:>7`<f8n36>54i3`94?"6l009j6`>d987?>o413:1(<j6:3d8j4b?2<10e>650;&2`<<5n2d:h549;:k03?6=,8n26?h4n0f;>2=<a:<1<7*>d881b>h6l10376g<5;29 4b>2;l0b<j7:898m62=83.:h44=f:l2`=<f32c8?7>5$0f:>7`<f8n36o54i2094?"6l009j6`>d98`?>o493:1(<j6:3d8j4b?2m10e?o50;&2`<<5n2d:h54j;:k54?6=,8n268h4n0f;>5=<a<o1<7*>d886b>h6l10:76g:c;29 4b>2<l0b<j7:398m0d=83.:h44:f:l2`=<432c>m7>5$0f:>0`<f8n36954i4;94?"6l00>j6`>d986?>o203:1(<j6:4d8j4b?2?10e8950;&2`<<2n2d:h548;:k62?6=,8n268h4n0f;>==<a<?1<7*>d886b>h6l10276g:4;29 4b>2<l0b<j7:`98m05=83.:h44:f:l2`=<e32c>=7>5$0f:>0`<f8n36n54i4294?"6l00>j6`>d98g?>o3n3:1(<j6:4d8j4b?2l10e9k50;&2`<<2n2d:h54i;:k7`?6=,8n268h4n0f;>46<3`>h6=4+1e;91c=i9m21=<54i5`94?"6l00>j6`>d9826>=n<h0;6)?k9;7e?k7c03;876g;9;29 4b>2<l0b<j7:068?l2?290/=i755g9m5a>=9<10e;950;&2`<<2n2d:h54>6:9j23<72-;o57;i;o3g<?7032c=97>5$0f:>0`<f8n36<64;h47>5<#9m319k5a1e:95<=<a?91<7*>d886b>h6l10:m65f6383>!7c13?m7c?k8;3a?>o193:1(<j6:4d8j4b?28i07d;k:18'5a?==o1e=i651e98m04=83.:h44:f:l2`=<6m21b8:4?:%3g=?3a3g;o47?i;:k;5?6=,8n265>4n0f;>5=<a>l1<7*>d88;4>h6l10:76g8d;29 4b>21:0b<j7:398m2e=83.:h4470:l2`=<432c<n7>5$0f:>=6<f8n36954i6c94?"6l003<6`>d986?>o013:1(<j6:928j4b?2?10e:650;&2`<<?82d:h548;:k43?6=,8n265>4n0f;>==<a><1<7*>d88;4>h6l10276g85;29 4b>21:0b<j7:`98m22=83.:h4470:l2`=<e32c<>7>5$0f:>=6<f8n36n54i6394?"6l003<6`>d98g?>o083:1(<j6:928j4b?2l10e;h50;&2`<<?82d:h54i;:k5a?6=,8n265>4n0f;>46<3`<o6=4+1e;9<5=i9m21=<54i7a94?"6l003<6`>d9826>=n>k0;6)?k9;:3?k7c03;876g9a;29 4b>21:0b<j7:068?l0>290/=i75819m5a>=9<10e5650;&2`<<?82d:h54>6:9j<2<72-;o576?;o3g<?7032c3:7>5$0f:>=6<f8n36<64;h:6>5<#9m314=5a1e:95<=<a1>1<7*>d88;4>h6l10:m65f8283>!7c132;7c?k8;3a?>o?:3:1(<j6:928j4b?28i07d9j:18'5a?=091e=i651e98m25=83.:h4470:l2`=<6m21b:54?:%3g=?>73g;o47?i;:k;`?6=,8n265m4n0f;>5=<a1h1<7*>d88;g>h6l10:76g7a;29 4b>21i0b<j7:398m=?=83.:h447c:l2`=<432c2>7>5$0f:><7<f8n36=54i8294?"6l002=6`>d982?>o?n3:1(<j6:838j4b?2;10e5k50;&2`<<>92d:h54<;:k2b6<72-;o57?i2:l2`=<732c:j<4?:%3g=?7a:2d:h54>;:k2b5<72-;o57?i2:l2`=<532c:ik4?:%3g=?7a:2d:h54<;:k2b=<72-;o57?i7:l2`=<732c:j;4?:%3g=?7a?2d:h54>;:k2b0<72-;o57?i7:l2`=<532c:j94?:%3g=?7a?2d:h54<;:mbg?6=,8n26ll4n0f;>5=<ghk1<7*>d88bf>h6l10:76an8;29 4b>2hh0b<j7:398kd1=83.:h44nb:l2`=<432ej:7>5$0f:>dd<f8n36954o`794?"6l00jn6`>d986?>if<3:1(<j6:``8j4b?2?10cl=50;&2`<<fj2d:h548;:mb6?6=,8n26ll4n0f;>==<gh;1<7*>d88bf>h6l10276an0;29 4b>2hh0b<j7:`98k<`=83.:h44nb:l2`=<e32e2h7>5$0f:>dd<f8n36n54o8a94?"6l00jn6`>d98g?>i>j3:1(<j6:``8j4b?2l10c4o50;&2`<<fj2d:h54i;:m:=?6=,8n26ll4n0f;>46<3f336=4+1e;9eg=i9m21=<54o8594?"6l00jn6`>d9826>=h1?0;6)?k9;ca?k7c03;876a65;29 4b>2hh0b<j7:068?j?3290/=i75ac9m5a>=9<10co=50;&2`<<fj2d:h54>6:9lf7<72-;o57om;o3g<?7032ei=7>5$0f:>dd<f8n36<64;n`3>5<#9m31mo5a1e:95<=<ghl1<7*>d88bf>h6l10:m65`ad83>!7c13ki7c?k8;3a?>ifl3:1(<j6:``8j4b?28i07bo6:18'5a?=ik1e=i651e98k<c=83.:h44nb:l2`=<6m21d5>4?:%3g=?ge3g;o47?i;:m`a?6=,8n26nj4n0f;>5=<gji1<7*>d88``>h6l10:76ala;29 4b>2jn0b<j7:398kf?=83.:h44ld:l2`=<432eh47>5$0f:>fb<f8n36954ob594?"6l00hh6`>d986?>id>3:1(<j6:bf8j4b?2?10cn;50;&2`<<dl2d:h548;:m`0?6=,8n26nj4n0f;>==<gj91<7*>d88``>h6l10276al2;29 4b>2jn0b<j7:`98kf7=83.:h44ld:l2`=<e32eij7>5$0f:>fb<f8n36n54ocg94?"6l00hh6`>d98g?>iel3:1(<j6:bf8j4b?2l10com50;&2`<<dl2d:h54i;:maf?6=,8n26nj4n0f;>46<3fhj6=4+1e;9ga=i9m21=<54oc;94?"6l00hh6`>d9826>=hj10;6)?k9;ag?k7c03;876am7;29 4b>2jn0b<j7:068?jd1290/=i75ce9m5a>=9<10ci;50;&2`<<dl2d:h54>6:9l`1<72-;o57mk;o3g<?7032eo?7>5$0f:>fb<f8n36<64;nf1>5<#9m31oi5a1e:95<=<gm;1<7*>d88``>h6l10:m65`d183>!7c13io7c?k8;3a?>idn3:1(<j6:bf8j4b?28i07bmm:18'5a?=km1e=i651e98kf6=83.:h44ld:l2`=<6m21dn84?:%3g=?ec3g;o47?i;:mgf?6=,8n26io4n0f;>5=<gm31<7*>d88ge>h6l10:76ak8;29 4b>2mk0b<j7:398ka1=83.:h44ka:l2`=<432en<7>5$0f:>a`<f8n36=54oeg94?"6l00oj6`>d982?>icl3:1(<j6:ed8j4b?2;10cim50;&2`<<cn2d:h54<;:p717=83=8wS<<2:\004=:9ol1i9521dc97a=:9lk1?h521dc95a`<58oj6<k?;<3fe?7b>27:il4>e69>5`g=:916=ho5229>5`g=:;16=ho5209>5`g=9h16=ho5319>5`g=;:16=ho5339>5`g=;816=ho52`9>5`g=>916=ho55d9>5`g==j16=ho55c9>5`g==h16=ho5589>5`g==116=ho5569>5`g==?16=ho5549>5`g===16=ho5529>5`g==816=ho5519>5`g=<o16=ho54d9>5`g=<m16=ho5649>5`g=0816=ho57g9>5`g=?m16=ho57b9>5`g=?k16=ho57`9>5`g=?016=ho5799>5`g=?>16=ho5779>5`g=?<16=ho5759>5`g=?;16=ho5709>5`g=?916=ho56g9>5`g=>l16=ho5879>5`g=0m16=ho58c9>5`g=0h16=ho5889>5`g=1;16=ho5919>5`g=0o16=ho58d9>5`?=;m16=h753d9>5`?=9ml01<k6:0g3?87b13;n:63>e882a2=:9l31>=521d;966=:9l31>?521d;964=:9l31=l521d;975=:9l31?>521d;977=:9l31?<521d;96d=:9l31:=521d;91`=:9l319n521d;91g=:9l319l521d;91<=:9l3195521d;912=:9l319;521d;910=:9l3199521d;916=:9l319<521d;915=:9l318k521d;90`=:9l314<521d;93c=:9l31;i521d;93f=:9l31;o521d;93d=:9l31;4521d;93==:9l31;:521d;933=:9l31;8521d;931=:9l31;?521d;934=:9l31;=521d;92c=:9l314i521d;9<g=:9l315?521d;9=5=z{:936=4<{_10<>;6mh0n=63>e88f5>{t;:31<7=t^21:?87bi3o970?j9;g1?xu5;90;6>uQ222894cf2=801<k6:508yv4493:1?vP=309>5`g=<:16=h75429~w7cb2909wS<le:?2ad<>02wx>hm50;0xZ7ec34;nm778;|q1ad<72;qU>nl4=0gb><0<uz8n57>52z\1gd=:9lk1585rs3g;>5<5sW8h563>e`8:0>{t:l=1<7<t^3a;?87bi3h87p}=e783>7}Y:j=01<kn:c08yv4b=3:1>vP=c79>5`g=j91v?k;:181[4d=27:il4nf:p6`5=838pR?m;;<3fe?gb3ty9i?4?:3y]6f5<58oj6lj4}r0f5?6=:rT9o?521dc9e<=z{;nm6=4={_0`4>;6mh02i6s|2eg94?4|V;hm70?ja;;0?xu5lm0;6?uQ2cg894c>2m20q~<kc;296~X5jm16=h75989~w7be2909wS<mc:?2a<<>02wx>io50;0xZ7de34;n5778;|q1`<<72;qU>oo4=0g:><0<uz8o47>52z\1f<=:9l31585rs3f4>5<5sW8i463>e88:0>{t:m<1<7<t^3`4?87b13h87p}=f483>7}Y:m>01<k6:c08yv4a<3:1>vP=d29>5`?=l>1v?h<:181[4c:27:i44m1:p6c4=838pR?j>;<3f=?d73ty9j<4?:3y]6a6<58o26lh4}r0e4?6=:rT9ok521d;9e`=z{;om6=4={_0`g>;6m00jh6s|2d`94?4|V;i:70?j9;c:?xu5m90;6?uQ2c4894c>20o0q~<k5;296~X5j<16=h75929~w64a2909wS=?f:?2ad<ei2wx??j50;0xZ66b34;nm7l6;|q06g<72;qU?=m4=0gb>g><uz99m7>52z\04g=:9lk1n:5rs20:>5<5sW9;m63>e`8a2>{t;;21<7<t^22:?87bi3n>7p}<2683>7}Y;9201<kn:e68yv55>3:1>vP<069>5`g=l;1v><::181[57>27:il4k1:p772=838pR>>:;<3fe?b73ty8>>4?:3y]752<58oj6nh4}r116?6=:rT8<>521dc9gg=z{:8;6=4={_135>;6mh0h<6s|30d94?4|V::;70?ja;`6?xu49l0;6?uQ2gd894c>2mn0q~=>d;296~X5nl16=h75bc9~w67d2909wS<id:?2a<<ei2wx?<l50;0xZ7`d34;n57l6;|q05d<72;qU>kl4=0g:>g><uz9:57>52z\1bd=:9l31n:5rs23;>5<5sW8m563>e88a2>{t;8=1<7<t^3d;?87b13n>7p}<3783>7}Y;8?01<k6:e68yv54=3:1>vP<159>5`?=lj1v>=;:181[56;27:i44k3:p765=838pR>?=;<3f=?b53ty8??4?:3y]747<58o26i?4}r105?6=:rT8==521d;9`5=z{:9;6=4={_13`>;6m00hj6s|33a94?4|V::970?j9;aa?xu4:80;6?uQ2g5894c>2j:0q~=>6;296~X5n?16=h75b49~w6212902wS=;4:?2ad<6n:16=ho51g3894cf28l;70?ja;3fb>;6m00:j>521d;95c7<58o26<h?;<3f=?7bn2wx?9750;;xZ62034;nm7?i8:?2ad<6n?16=ho51g7894cf28l?70?j9;3e<>;6m00:j;521d;95c3<58o26<h;;|q15<<72:qU>=k4=0gb>4c<58o26<k4}r023?6=;rT9<i521dc95a=:9l31=i5rs335>5<4sW8;o63>e`82g>;6m00:o6s|20794?5|V;:i70?ja;3a?87b13;i7p}=1583>6}Y:9k01<kn:3;894c>2;30q~<>3;297~X58016=ho5299>5`?=:11v??=:180[47027:il4=7:?2a<<5?2wx><?50;1xZ76034;nm7<9;<3f=?413ty9==4?:2y]650<58oj6?;4=0g:>73<uz8;j7>53z\140=:9lk1>9521d;961=z{;8n6=4<{_017>;6mh09i63>e881a>{t:;i1<7=t^301?87bi38o70?j9;0g?xu5:k0;6>uQ233894cf2;i01<k6:3a8yv45i3:1?vP=219>5`g=:k16=h752c9~w74>2908wS<>f:?2ad<4127:i44<9:p67>=839pR??j;<3fe?5?34;n57=7;|q162<72:qU><j4=0gb>61<58o26>94}r012?6=;rT9=n521dc973=:9l31?;5rs306>5<4sW8:n63>e`801>;6m00896s|23694?5|V;;j70?ja;17?87b139?7p}=6b83>7}Y:=i01<kn:5a8yv41i3:1>vP=4c9>5`g=<k1v?87:181[43127:il4;a:p631=838pR?:7;<3fe?2>3ty9:;4?:3y]611<58oj6964}r051?6=:rT98;521dc922=z{;<?6=4={_071>;6mh0=:6s|27194?4|V;>?70?ja;47?xu5>;0;6?uQ251894cf2?90q~<91;296~X5<;16=ho5639~w7072909wS<;1:?2ad<192wx>8h50;0xZ72734;nm7;k;|q11a<72;qU>>k4=0gb>04<uz8>o7>52z\17a=:9lk18:5rs37a>5<5sW88o63>e88;e>{t:<k1<7<t^31a?87b13>o7p}=5883>7}Y::k01<k6:5a8yv4203:1>vP=389>5`?=<k1v?;8:181[44027:i44;a:p600=838pR?=8;<3f=?2>3ty9984?:3y]660<58o26964}r060?6=:rT9?8521d;922=z{;=86=4={_066>;6m00=:6s|26094?4|V;?:70?j9;::?xu5?80;6?uQ242894c>2??0q~<80;296~X5<o16=h75659~w70a2909wS<;e:?2a<<1;2wx>;k50;0xZ72c34;n578=;|q12a<72;qU>9o4=0g:>37<uz8=57>52z\17c=:9l319i5rs37f>5<5sW88863>e8866>{t:<91<7<t^310?87b13><7p}=ae83>7}Y:1n01<kn:7f8yv4fj3:1>vP=8b9>5`g=>j1v?o6:181[4?i27:il49b:p6d>=838pR?66;<3fe?0f3ty9m:4?:3y]6=><58oj6;74}r0b2?6=:rT94:521dc9<==z{;k>6=4={_0;2>;6mh03;6s|2`694?4|V;2>70?ja;:6?xu5i:0;6?uQ296894cf21>0q~<n2;296~X50:16=ho5829~w7g62909wS<72:?2ad<?:2wx>l>50;0xZ7>634;nm79j;|q1=`<72;qU>:h4=0gb>25<uz82h7>52z\13`=:9lk1:55rs3;`>5<5sW8<h63>e88;b>{t:0h1<7<t^35`?87b13<n7p}=9`83>7}Y:>h01<k6:7f8yv4>13:1>vP=7`9>5`?=>j1v?77:181[40127:i449b:p6<1=838pR?97;<3f=?0f3ty95;4?:3y]621<58o26;74}r0:1?6=:rT9;;521d;9<==z{;h?6=4={_0:7>;6m003;6s|2c194?4|V;3970?j9;:f?xu5j;0;6?uQ283894c>21<0q~<m1;296~X51916=h75849~w7d72909wS<7f:?2a<<?<2wx>lh50;0xZ7>b34;n576<;|q1e`<72;qU>5l4=0g:>=4<uz8jm7>52z\1<5=:9l31;h5rs3;e>5<5sW8<963>e8847>{t:0>1<7<t^357?87b13<37ps|22294?4|V;9;70=m:313?!7bj3;<n6s|27a94?4|V;>h70=m:36`?!7bj3;3:6s|27c94?4|V;>i70=m:36a?!7bj3;2=6s|27:94?4|V;>270=m:36:?!7bj3;2m6s|27594?4|V;>370=m:36;?!7bj3;j96s|27494?4|V;><70=m:364?!7bj3;i<6s|27794?4|V;>=70=m:365?!7bj3;in6s|27694?4|V;>>70=m:366?!7bj3;h:6s|27194?4|V;>?70=m:367?!7bj3;8;6s|27094?4|V;>870=m:360?!7bj3;?>6s|27394?4|V;>970=m:361?!7bj3;?h6s|27294?4|V;>:70=m:362?!7bj3;>:6s|24d94?4|V;>;70=m:363?!7bj3;==6s|24f94?4|V;9n70=m:31f?!7bj3;=o6s|24a94?4|V;9o70=m:31g?!7bj3;<;6s|24`94?4|V;9h70=m:31`?!7bj3;<46s|24c94?4|V;9i70=m:31a?!7bj3;<56s|24;94?4|V;9j70=m:31b?!7bj3;<m6s|24:94?4|V;9270=m:31:?!7bj3;<o6s|24594?4|V;9370=m:31;?!7bj3;<h6s|24494?4|V;9<70=m:314?!7bj3;<i6s|24794?4|V;9=70=m:315?!7bj3;<j6s|24694?4|V;9>70=m:316?!7bj3;3<6s|26194?4|V;?970=m:371?!7bj3;3=6s|26094?4|V;?:70=m:372?!7bj3;3>6s|26394?4|V;?;70=m:373?!7bj3;3?6s|26294?4|V;>m70=m:36e?!7bj3;386s|27d94?4|V;>n70=m:36f?!7bj3;396s|27g94?4|V;>o70=m:36g?!7bj3;3;6s|27f94?4|V;>j70=m:36b?!7bj3;346s|27;94?4|V;9m70=m:31e?!7bj3;356s|24g94?4|V;9?70=m:317?!7bj3;3m6s|24194?4|V;9870=m:310?!7bj3;3n6s|20;94?4|V;:n70=m:32f?!7bj3;3o6s|20594?4|V;:o70=m:32g?!7bj3;3h6s|20494?4|V;:h70=m:32`?!7bj3;3i6s|20794?4|V;:i70=m:32a?!7bj3;3j6s|20694?4|V;:j70=m:32b?!7bj3;2<6s|20194?4|V;:270=m:32:?!7bj3;2>6s|20094?4|V;:370=m:32;?!7bj3;2?6s|20394?4|V;:<70=m:324?!7bj3;286s|20294?4|V;:=70=m:325?!7bj3;296s|21d94?4|V;:>70=m:326?!7bj3;2:6s|32:94?4|V:9370=m:21;?!7bj3;2;6s|35494?4|V:>?70=m:267?!7bj3;246s|2dg94?4|V;in70=m:3af?!7bj3;256s|2da94?4|V;io70=m:3ag?!7bj3;2n6s|2dc94?4|V;ii70=m:3aa?!7bj3;2o6s|2d;94?4|V;ij70=m:3ab?!7bj3;2h6s|2d:94?4|V;i270=m:3a:?!7bj3;2i6s|2d594?4|V;i370=m:3a;?!7bj3;2j6s|2d494?4|V;i<70=m:3a4?!7bj3;j<6s|2d794?4|V;i=70=m:3a5?!7bj3;j=6s|2d694?4|V;i>70=m:3a6?!7bj3;j>6s|2d194?4|V;i?70=m:3a7?!7bj3;j?6s|2d094?4|V;i870=m:3a0?!7bj3;j86s|2d394?4|V;i970=m:3a1?!7bj3;j:6s|2ed94?4|V;i;70=m:3a3?!7bj3;j;6s|2eg94?4|V;hm70=m:3`e?!7bj3;j46s|2ef94?4|V;hn70=m:3`f?!7bj3;j56s|2ea94?4|V;ho70=m:3`g?!7bj3;jm6s|2e`94?4|V;hh70=m:3``?!7bj3;jn6s|2ec94?4|V;hi70=m:3`a?!7bj3;jo6s|2e;94?4|V;hj70=m:3`b?!7bj3;jh6s|2e:94?4|V;h270=m:3`:?!7bj3;ji6s|2e594?4|V;h370=m:3`;?!7bj3;jj6s|2e494?4|V;h<70=m:3`4?!7bj3;i=6s|2g794?4|V;n?70=m:3f7?!7bj3;i>6s|2g694?4|V;n870=m:3f0?!7bj3;i?6s|2g194?4|V;n970=m:3f1?!7bj3;i86s|2g094?4|V;n:70=m:3f2?!7bj3;i96s|2g394?4|V;n;70=m:3f3?!7bj3;i:6s|2g294?4|V;im70=m:3ae?!7bj3;i;6s|2dd94?4|V;ih70=m:3a`?!7bj3;i46s|2d`94?4|V;i:70=m:3a2?!7bj3;i56s|2d294?4|V;h=70=m:3`5?!7bj3;im6s|2e794?4|V;h>70=m:3`6?!7bj3;io6s|22394?4|V;9:70=m:312?!7bj3;ih6s|2`f94?4|V;2o70=m:3:g?!7bj3;ii6s|2``94?4|V;2h70=m:3:`?!7bj3;ij6s|2`;94?4|V;2j70=m:3:b?!7bj3;h<6s|2`:94?4|V;2270=m:3::?!7bj3;h=6s|2`594?4|V;2370=m:3:;?!7bj3;h>6s|2`494?4|V;2<70=m:3:4?!7bj3;h?6s|2`794?4|V;2=70=m:3:5?!7bj3;h86s|2`694?4|V;2>70=m:3:6?!7bj3;h96s|2`194?4|V;2?70=m:3:7?!7bj3;h;6s|2`094?4|V;2870=m:3:0?!7bj3;h46s|2`394?4|V;2970=m:3:1?!7bj3;h56s|2`294?4|V;2:70=m:3:2?!7bj3;hm6s|28g94?4|V;=m70=m:35e?!7bj3;hn6s|28f94?4|V;=n70=m:35f?!7bj3;ho6s|28a94?4|V;=o70=m:35g?!7bj3;hh6s|28`94?4|V;=h70=m:35`?!7bj3;hi6s|28c94?4|V;=i70=m:35a?!7bj3;hj6s|28;94?4|V;=j70=m:35b?!7bj3;o<6s|28:94?4|V;=270=m:35:?!7bj3;846s|28594?4|V;=370=m:35;?!7bj3;856s|28494?4|V;=<70=m:354?!7bj3;8m6s|28794?4|V;==70=m:355?!7bj3;8n6s|2c694?4|V;3870=m:3;0?!7bj3;8o6s|2c194?4|V;3970=m:3;1?!7bj3;8h6s|2c094?4|V;3:70=m:3;2?!7bj3;8i6s|2c394?4|V;3;70=m:3;3?!7bj3;8j6s|2c294?4|V;2m70=m:3:e?!7bj3;?<6s|2`d94?4|V;2n70=m:3:f?!7bj3;?=6s|2`g94?4|V;2i70=m:3:a?!7bj3;??6s|2`c94?4|V;2;70=m:3:3?!7bj3;?86s|28d94?4|V;=>70=m:356?!7bj3;?96s|28694?4|V;=?70=m:357?!7bj3;?:6s|23g94?4|V;8870=m:300?!7bj3;?;6s|23a94?4|V;8970=m:301?!7bj3;?46s|23`94?4|V;8:70=m:302?!7bj3;?56s|23c94?4|V;8;70=m:303?!7bj3;?m6s|23;94?4|V;;m70=m:33e?!7bj3;?n6s|23:94?4|V;;n70=m:33f?!7bj3;?o6s|23594?4|V;;o70=m:33g?!7bj3;?i6s|23494?4|V;;h70=m:33`?!7bj3;?j6s|23794?4|V;;i70=m:33a?!7bj3;><6s|23694?4|V;;j70=m:33b?!7bj3;>=6s|32;94?4|V:9270=m:21:?!7bj3;>>6s|35;94?4|V:><70=m:264?!7bj3;>?6s|33d94?4|V::m70=m:22e?!7bj3;>86s|33f94?4|V::n70=m:22f?!7bj3;>96s|33`94?4|V::h70=m:22`?!7bj3;>;6s|33c94?4|V::i70=m:22a?!7bj3;>46s|33;94?4|V::j70=m:22b?!7bj3;>56s|33:94?4|V::270=m:22:?!7bj3;>m6s|33594?4|V::370=m:22;?!7bj3;>n6s|33494?4|V::<70=m:224?!7bj3;>o6s|33794?4|V::=70=m:225?!7bj3;>h6s|33694?4|V::>70=m:226?!7bj3;>i6s|33194?4|V::?70=m:227?!7bj3;>j6s|33094?4|V::870=m:220?!7bj3;=<6s|33294?4|V:::70=m:222?!7bj3;=>6s|30d94?4|V::;70=m:223?!7bj3;=?6s|30g94?4|V;lm70=m:3de?!7bj3;=86s|30f94?4|V;ln70=m:3df?!7bj3;=96s|30a94?4|V;lo70=m:3dg?!7bj3;=:6s|30`94?4|V;lh70=m:3d`?!7bj3;=;6s|30c94?4|V;li70=m:3da?!7bj3;=46s|30;94?4|V;lj70=m:3db?!7bj3;=56s|30:94?4|V;l270=m:3d:?!7bj3;=m6s|30594?4|V;l370=m:3d;?!7bj3;=n6s|32494?4|V:;>70=m:236?!7bj3;=h6s|32794?4|V:;?70=m:237?!7bj3;=i6s|32694?4|V:;870=m:230?!7bj3;=j6s|32194?4|V:;970=m:231?!7bj3;<<6s|32094?4|V:;:70=m:232?!7bj3;<=6s|32394?4|V:;;70=m:233?!7bj3;<>6s|32294?4|V::o70=m:22g?!7bj3;<?6s|33a94?4|V::970=m:221?!7bj3;<86s|33394?4|V;l<70=m:3d4?!7bj3;<96s|30494?4|V;l=70=m:3d5?!7bj3;<:6srn24g>5<5sA;no6sa37g94?4|@8oh7p`<6g83>7}O9li0qc=80;296~N6mj1vb>9>:181M7bk2we?:<50;0xL4cd3td8;>4?:3yK5`e<ug9<87>52zJ2af=zf:=>6=4={I3fg>{i;><1<7<tH0g`?xh4?>0;6?uG1da8yk5003:1>vF>eb9~j61>2909wE?jc:m72g=838pD<kl;|l03g<72;qC=hm4}o14g?6=:rB:in5rn25g>5<5sA;no6sa36g94?4|@8oh7p`<7g83>7}O9li0qc=70;296~N6mj1vb>6>:181M7bk2we?5<50;0xL4cd3td84>4?:3yK5`e<ug9387>52zJ2af=zf:2>6=4={I3fg>{i;1<1<7<tH0g`?xh40>0;6?uG1da8yk5?03:1>vF>eb9~j6>>2909wE?jc:m7=g=838pD<kl;|l0<g<72;qC=hm4}o1;g?6=:rB:in5rn2:g>5<5sA;no6sa39g94?4|@8oh7p`<8g83>7}O9li0qc=60;296~N6mj1vb>7>:181M7bk2we?4<50;0xL4cd3td85>4?:3yK5`e<ug9287>52zJ2af=zf:3>6=4={I3fg>{i;0<1<7<tH0g`?xh41>0;6?uG1da8yk5>03:1>vF>eb9~j6?>2909wE?jc:m7<g=838pD<kl;|l0=g<72;qC=hm4}o1:g?6=:rB:in5rn2;g>5<5sA;no6sa38g94?4|@8oh7p`<9g83>7}O9li0qc=n0;296~N6mj1vb>o>:181M7bk2we?l<50;0xL4cd3td8m>4?:3yK5`e<ug9j87>52zJ2af=zf:k>6=4={I3fg>{i;h<1<7<tH0g`?xh4i>0;6?uG1da8yk5f03:1>vF>eb9~j6g>2909wE?jc:m7dg=838pD<kl;|l0eg<72;qC=hm4}o1bg?6=:rB:in5rn2cg>5<5sA;no6sa3`g94?4|@8oh7p`<ag83>7}O9li0qc=m0;296~N6mj1vb>l>:181M7bk2we?o<50;0xL4cd3td8n>4?:3yK5`e<ug9i87>52zJ2af=zf:h>6=4={I3fg>{i;k<1<7<tH0g`?xh4j>0;6?uG1da8yk5e03:1>vF>eb9~j6d>2909wE?jc:m7gg=838pD<kl;|l0fg<72;qC=hm4}o1ag?6=:rB:in5rn2`g>5<5sA;no6sa3cg94?4|@8oh7p`<bg83>7}O9li0qc=l0;296~N6mj1vb>m>:181M7bk2we?n<50;0xL4cd3td8o>4?:3yK5`e<ug9h87>52zJ2af=zf:i>6=4={I3fg>{i;j<1<7<tH0g`?xh4k>0;6?uG1da8yk5d03:1>vF>eb9~j6e>2909wE?jc:m7fg=838pD<kl;|l0gg<72;qC=hm4}o1`g?6=:rB:in5rn2ag>5<5sA;no6sa3bg94?4|@8oh7p`<cg83>7}O9li0qc=k0;296~N6mj1vb>j>:181M7bk2we?i<50;0xL4cd3td8h>4?:3yK5`e<ug9o87>52zJ2af=zf:n>6=4={I3fg>{i;m<1<7<tH0g`?xh4l>0;6?uG1da8yk5c03:1>vF>eb9~j6b>2909wE?jc:m7ag=838pD<kl;|l0`g<72;qC=hm4}o1gg?6=:rB:in5rn2fg>5<5sA;no6sa3eg94?4|@8oh7p`<dg83>7}O9li0qc=j0;296~N6mj1vb>k>:181M7bk2we?h<50;0xL4cd3td8i>4?:3yK5`e<ug9n87>52zJ2af=zf:o>6=4={I3fg>{i;l<1<7<tH0g`?xh4m>0;6?uG1da8yk5b03:1>vF>eb9~j6c>2909wE?jc:m7`g=838pD<kl;|l0ag<72;qC=hm4}o1fg?6=:rB:in5rn2gg>5<5sA;no6sa3dg94?4|@8oh7p`<eg83>7}O9li0qc=i0;296~N6mj1vb>h>:181M7bk2we?k<50;0xL4cd3td8j>4?:3yK5`e<ug9m87>52zJ2af=zf:l>6=4={I3fg>{i;o<1<7<tH0g`?xh4n>0;6?uG1da8yk5a03:1>vF>eb9~j6`>2909wE?jc:m7cg=838pD<kl;|l0bg<72;qC=hm4}o1eg?6=:rB:in5rn2dg>5<5sA;no6sa3gg94?4|@8oh7p`<fg83>7}O9li0qc:?0;296~N6mj1vb9>>:181M7bk2we8=<50;0xL4cd3td?<>4?:3yK5`e<ug>;87>52zJ2af=zf=:>6=4={I3fg>{i<9<1<7<tH0g`?xh5l;0;6<uG1da8yx{zHIIp8l<5a76;e5c4uIJIw=sO@Qy~DE \ No newline at end of file diff --git a/rce/fw-hsio/modules/pixelcore/coregen/pattern_blk_mem.vhd b/rce/fw-hsio/modules/pixelcore/coregen/pattern_blk_mem.vhd new file mode 100644 index 00000000..80684cd1 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/coregen/pattern_blk_mem.vhd @@ -0,0 +1,145 @@ +-------------------------------------------------------------------------------- +-- This file is owned and controlled by Xilinx and must be used -- +-- solely for design, simulation, implementation and creation of -- +-- design files limited to Xilinx devices or technologies. Use -- +-- with non-Xilinx devices or technologies is expressly prohibited -- +-- and immediately terminates your license. -- +-- -- +-- XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" -- +-- SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR -- +-- XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION -- +-- AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION -- +-- OR STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS -- +-- IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, -- +-- AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE -- +-- FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY -- +-- WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE -- +-- IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR -- +-- REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF -- +-- INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -- +-- FOR A PARTICULAR PURPOSE. -- +-- -- +-- Xilinx products are not intended for use in life support -- +-- appliances, devices, or systems. Use in such applications are -- +-- expressly prohibited. -- +-- -- +-- (c) Copyright 1995-2007 Xilinx, Inc. -- +-- All rights reserved. -- +-------------------------------------------------------------------------------- +-- You must compile the wrapper file pattern_blk_mem.vhd when simulating +-- the core, pattern_blk_mem. When compiling the wrapper file, be sure to +-- reference the XilinxCoreLib VHDL simulation library. For detailed +-- instructions, please refer to the "CORE Generator Help". + +-- The synthesis directives "translate_off/translate_on" specified +-- below are supported by Xilinx, Mentor Graphics and Synplicity +-- synthesis tools. Ensure they are correct for your synthesis tool(s). + +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +-- synthesis translate_off +Library XilinxCoreLib; +-- synthesis translate_on +ENTITY pattern_blk_mem IS + port ( + clka: IN std_logic; + dina: IN std_logic_VECTOR(31 downto 0); + addra: IN std_logic_VECTOR(9 downto 0); + ena: IN std_logic; + wea: IN std_logic_VECTOR(0 downto 0); + douta: OUT std_logic_VECTOR(31 downto 0); + clkb: IN std_logic; + dinb: IN std_logic_VECTOR(31 downto 0); + addrb: IN std_logic_VECTOR(9 downto 0); + enb: IN std_logic; + web: IN std_logic_VECTOR(0 downto 0); + doutb: OUT std_logic_VECTOR(31 downto 0)); +END pattern_blk_mem; + +ARCHITECTURE pattern_blk_mem_a OF pattern_blk_mem IS +-- synthesis translate_off +component wrapped_pattern_blk_mem + port ( + clka: IN std_logic; + dina: IN std_logic_VECTOR(31 downto 0); + addra: IN std_logic_VECTOR(9 downto 0); + ena: IN std_logic; + wea: IN std_logic_VECTOR(0 downto 0); + douta: OUT std_logic_VECTOR(31 downto 0); + clkb: IN std_logic; + dinb: IN std_logic_VECTOR(31 downto 0); + addrb: IN std_logic_VECTOR(9 downto 0); + enb: IN std_logic; + web: IN std_logic_VECTOR(0 downto 0); + doutb: OUT std_logic_VECTOR(31 downto 0)); +end component; + +-- Configuration specification + for all : wrapped_pattern_blk_mem use entity XilinxCoreLib.blk_mem_gen_v2_8(behavioral) + generic map( + c_has_regceb => 0, + c_has_regcea => 0, + c_mem_type => 2, + c_prim_type => 1, + c_sinita_val => "0", + c_read_width_b => 32, + c_family => "virtex4", + c_read_width_a => 32, + c_disable_warn_bhv_coll => 0, + c_write_mode_b => "NO_CHANGE", + c_init_file_name => "no_coe_file_loaded", + c_write_mode_a => "NO_CHANGE", + c_mux_pipeline_stages => 0, + c_has_mem_output_regs_b => 0, + c_load_init_file => 0, + c_xdevicefamily => "virtex4", + c_has_mem_output_regs_a => 0, + c_write_depth_b => 1024, + c_write_depth_a => 1024, + c_has_ssrb => 0, + c_has_mux_output_regs_b => 0, + c_has_ssra => 0, + c_has_mux_output_regs_a => 0, + c_addra_width => 10, + c_addrb_width => 10, + c_default_data => "0", + c_use_ecc => 0, + c_algorithm => 1, + c_disable_warn_bhv_range => 0, + c_write_width_b => 32, + c_write_width_a => 32, + c_read_depth_b => 1024, + c_read_depth_a => 1024, + c_byte_size => 9, + c_sim_collision_check => "ALL", + c_use_ramb16bwer_rst_bhv => 0, + c_common_clk => 0, + c_wea_width => 1, + c_has_enb => 1, + c_web_width => 1, + c_has_ena => 1, + c_sinitb_val => "0", + c_use_byte_web => 0, + c_use_byte_wea => 0, + c_use_default_data => 1); +-- synthesis translate_on +BEGIN +-- synthesis translate_off +U0 : wrapped_pattern_blk_mem + port map ( + clka => clka, + dina => dina, + addra => addra, + ena => ena, + wea => wea, + douta => douta, + clkb => clkb, + dinb => dinb, + addrb => addrb, + enb => enb, + web => web, + doutb => doutb); +-- synthesis translate_on + +END pattern_blk_mem_a; + diff --git a/rce/fw-hsio/modules/pixelcore/coregen/pattern_blk_mem.vho b/rce/fw-hsio/modules/pixelcore/coregen/pattern_blk_mem.vho new file mode 100644 index 00000000..6c359283 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/coregen/pattern_blk_mem.vho @@ -0,0 +1,74 @@ +-------------------------------------------------------------------------------- +-- This file is owned and controlled by Xilinx and must be used -- +-- solely for design, simulation, implementation and creation of -- +-- design files limited to Xilinx devices or technologies. Use -- +-- with non-Xilinx devices or technologies is expressly prohibited -- +-- and immediately terminates your license. -- +-- -- +-- XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" -- +-- SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR -- +-- XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION -- +-- AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION -- +-- OR STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS -- +-- IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, -- +-- AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE -- +-- FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY -- +-- WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE -- +-- IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR -- +-- REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF -- +-- INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -- +-- FOR A PARTICULAR PURPOSE. -- +-- -- +-- Xilinx products are not intended for use in life support -- +-- appliances, devices, or systems. Use in such applications are -- +-- expressly prohibited. -- +-- -- +-- (c) Copyright 1995-2007 Xilinx, Inc. -- +-- All rights reserved. -- +-------------------------------------------------------------------------------- +-- The following code must appear in the VHDL architecture header: + +------------- Begin Cut here for COMPONENT Declaration ------ COMP_TAG +component pattern_blk_mem + port ( + clka: IN std_logic; + dina: IN std_logic_VECTOR(31 downto 0); + addra: IN std_logic_VECTOR(9 downto 0); + ena: IN std_logic; + wea: IN std_logic_VECTOR(0 downto 0); + douta: OUT std_logic_VECTOR(31 downto 0); + clkb: IN std_logic; + dinb: IN std_logic_VECTOR(31 downto 0); + addrb: IN std_logic_VECTOR(9 downto 0); + enb: IN std_logic; + web: IN std_logic_VECTOR(0 downto 0); + doutb: OUT std_logic_VECTOR(31 downto 0)); +end component; + +-- COMP_TAG_END ------ End COMPONENT Declaration ------------ + +-- The following code must appear in the VHDL architecture +-- body. Substitute your own instance name and net names. + +------------- Begin Cut here for INSTANTIATION Template ----- INST_TAG +your_instance_name : pattern_blk_mem + port map ( + clka => clka, + dina => dina, + addra => addra, + ena => ena, + wea => wea, + douta => douta, + clkb => clkb, + dinb => dinb, + addrb => addrb, + enb => enb, + web => web, + doutb => doutb); +-- INST_TAG_END ------ End INSTANTIATION Template ------------ + +-- You must compile the wrapper file pattern_blk_mem.vhd when simulating +-- the core, pattern_blk_mem. When compiling the wrapper file, be sure to +-- reference the XilinxCoreLib VHDL simulation library. For detailed +-- instructions, please refer to the "CORE Generator Help". + diff --git a/rce/fw-hsio/modules/pixelcore/coregen/pattern_blk_mem.xco-outdated b/rce/fw-hsio/modules/pixelcore/coregen/pattern_blk_mem.xco-outdated new file mode 100644 index 00000000..ef82ce5d --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/coregen/pattern_blk_mem.xco-outdated @@ -0,0 +1,78 @@ +############################################################## +# +# Xilinx Core Generator version K.39 +# Date: Mon Aug 17 20:38:30 2009 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# BEGIN Project Options +SET addpads = False +SET asysymbol = False +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = False +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = False +SET foundationsym = False +SET implementationfiletype = Ngc +SET package = ff1152 +SET removerpms = False +SET simulationfiles = Behavioral +SET speedgrade = -10 +SET verilogsim = False +SET vhdlsim = True +# END Project Options +# BEGIN Select +SELECT Block_Memory_Generator family Xilinx,_Inc. 2.8 +# END Select +# BEGIN Parameters +CSET algorithm=Minimum_Area +CSET assume_synchronous_clk=false +CSET byte_size=9 +CSET coe_file=no_coe_file_loaded +CSET collision_warnings=ALL +CSET component_name=pattern_blk_mem +CSET disable_collision_warnings=false +CSET disable_out_of_range_warnings=false +CSET ecc=false +CSET enable_a=Use_ENA_Pin +CSET enable_b=Use_ENB_Pin +CSET fill_remaining_memory_locations=true +CSET load_init_file=false +CSET memory_type=True_Dual_Port_RAM +CSET operating_mode_a=NO_CHANGE +CSET operating_mode_b=NO_CHANGE +CSET output_reset_value_a=0 +CSET output_reset_value_b=0 +CSET pipeline_stages=0 +CSET primitive=8kx2 +CSET read_width_a=32 +CSET read_width_b=32 +CSET register_porta_output_of_memory_core=false +CSET register_porta_output_of_memory_primitives=false +CSET register_portb_output_of_memory_core=false +CSET register_portb_output_of_memory_primitives=false +CSET remaining_memory_locations=0 +CSET single_bit_ecc=false +CSET use_byte_write_enable=false +CSET use_ramb16bwer_reset_behavior=false +CSET use_regcea_pin=false +CSET use_regceb_pin=false +CSET use_ssra_pin=false +CSET use_ssrb_pin=false +CSET write_depth_a=1024 +CSET write_width_a=32 +CSET write_width_b=32 +# END Parameters +GENERATE +# CRC: d212e058 + diff --git a/rce/fw-hsio/modules/pixelcore/coregen/triggerfifo.xco b/rce/fw-hsio/modules/pixelcore/coregen/triggerfifo.xco new file mode 100644 index 00000000..6c39c9eb --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/coregen/triggerfifo.xco @@ -0,0 +1,82 @@ +############################################################## +# +# Xilinx Core Generator version K.39 +# Date: Sat Apr 24 17:20:17 2010 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# BEGIN Project Options +SET addpads = False +SET asysymbol = False +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = False +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = False +SET foundationsym = False +SET implementationfiletype = Ngc +SET package = ff1152 +SET removerpms = False +SET simulationfiles = Behavioral +SET speedgrade = -10 +SET verilogsim = False +SET vhdlsim = True +# END Project Options +# BEGIN Select +SELECT Fifo_Generator family Xilinx,_Inc. 4.4 +# END Select +# BEGIN Parameters +CSET almost_empty_flag=false +CSET almost_full_flag=false +CSET component_name=triggerfifo +CSET data_count=true +CSET data_count_width=8 +CSET disable_timing_violations=false +CSET dout_reset_value=0 +CSET empty_threshold_assert_value=2 +CSET empty_threshold_negate_value=3 +CSET enable_ecc=false +CSET enable_int_clk=false +CSET fifo_implementation=Common_Clock_Block_RAM +CSET full_flags_reset_value=1 +CSET full_threshold_assert_value=254 +CSET full_threshold_negate_value=253 +CSET input_data_width=1 +CSET input_depth=256 +CSET output_data_width=1 +CSET output_depth=256 +CSET overflow_flag=false +CSET overflow_sense=Active_High +CSET performance_options=Standard_FIFO +CSET programmable_empty_type=No_Programmable_Empty_Threshold +CSET programmable_full_type=No_Programmable_Full_Threshold +CSET read_clock_frequency=1 +CSET read_data_count=false +CSET read_data_count_width=8 +CSET reset_pin=true +CSET reset_type=Asynchronous_Reset +CSET underflow_flag=false +CSET underflow_sense=Active_High +CSET use_dout_reset=true +CSET use_embedded_registers=false +CSET use_extra_logic=false +CSET valid_flag=false +CSET valid_sense=Active_High +CSET write_acknowledge_flag=false +CSET write_acknowledge_sense=Active_High +CSET write_clock_frequency=1 +CSET write_data_count=false +CSET write_data_count_width=8 +# END Parameters +GENERATE +# CRC: 77b25bef + diff --git a/rce/fw-hsio/modules/pixelcore/coregen/xil_cores.cgp b/rce/fw-hsio/modules/pixelcore/coregen/xil_cores.cgp new file mode 100644 index 00000000..fb23f88b --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/coregen/xil_cores.cgp @@ -0,0 +1,19 @@ +# Date: Wed Jan 26 19:09:37 2011 + +SET addpads = false +SET asysymbol = false +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = false +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = false +SET foundationsym = false +SET implementationfiletype = Ngc +SET package = ff1152 +SET removerpms = false +SET simulationfiles = Behavioral +SET speedgrade = -11 +SET verilogsim = false +SET vhdlsim = true diff --git a/rce/fw-hsio/modules/pixelcore/hdl/BiphaseMarkEncoder.vhd b/rce/fw-hsio/modules/pixelcore/hdl/BiphaseMarkEncoder.vhd new file mode 100644 index 00000000..5c709552 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/BiphaseMarkEncoder.vhd @@ -0,0 +1,41 @@ + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity bpmencoder is + port ( + clock : in std_logic; + rst : in std_logic; + clockx2 : in std_logic; + datain : in std_logic; + encode : in std_logic; + dataout : out std_logic + ); +end bpmencoder; + +architecture BPMENCODER of bpmencoder is + + signal bmp: std_logic; + +begin + + process(clockx2, rst) + begin + if(rst='1') then + bmp<='0'; + elsif(clockx2'event and clockx2='1') then + if(clock='1' or datain='1')then + bmp<=not bmp; + end if; + end if; + end process; + + with encode select + dataout<= datain when '0', + bmp when '1', + datain when others; + +end BPMENCODER; diff --git a/rce/fw-hsio/modules/pixelcore/hdl/DisplayCharacters.vhd b/rce/fw-hsio/modules/pixelcore/hdl/DisplayCharacters.vhd new file mode 100755 index 00000000..55e7e252 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/DisplayCharacters.vhd @@ -0,0 +1,126 @@ +------------------------------------------------------------------------------- +-- Title : OSRAM SCDV5540 Display Controller Characters +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : DisplayCharacters.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 12/06/2007 +------------------------------------------------------------------------------- +-- Description: +-- Package for display chracter lookup table. +------------------------------------------------------------------------------- +-- Copyright (c) 2007 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 12/06/2007: created. +------------------------------------------------------------------------------- +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; + +package DisplayCharacters is + + -- Types For Character Lookup + subtype DISPCHAR is STD_LOGIC_VECTOR(24 downto 0); + type DISPTABLE is array ( NATURAL range <> ) of DISPCHAR; + + -- Constants For Charactors + constant DISPMAX : natural := 18; + constant DISPLOOKUP : DISPTABLE := ( + 0 => "01110" & -- Hex 0 + "10011" & + "10101" & + "11001" & + "01110", + 1 => "00100" & -- Hex 1 + "01100" & + "00100" & + "00100" & + "11111", + 2 => "11110" & -- Hex 2 + "00001" & + "00110" & + "01000" & + "11111", + 3 => "11110" & -- Hex 3 + "00001" & + "01110" & + "00001" & + "11110", + 4 => "00110" & -- Hex 4 + "01010" & + "11111" & + "00010" & + "00010", + 5 => "11111" & -- Hex 5 + "10000" & + "11110" & + "00001" & + "11110", + 6 => "00110" & -- Hex 6 + "01000" & + "11110" & + "10001" & + "01110", + 7 => "11111" & -- Hex 7 + "00010" & + "00100" & + "01000" & + "01000", + 8 => "01110" & -- Hex 8 + "10001" & + "01110" & + "10001" & + "01110", + 9 => "01110" & -- Hex 9 + "10001" & + "01111" & + "00010" & + "01100", + 10 => "00100" & -- Hex A + "01010" & + "11111" & + "10001" & + "10001", + 11 => "11110" & -- Hex B + "01001" & + "01110" & + "01001" & + "11110", + 12 => "01111" & -- Hex C + "10000" & + "10000" & + "10000" & + "11111", + 13 => "11110" & -- Hex D + "01001" & + "01001" & + "01001" & + "11110", + 14 => "11111" & -- Hex E + "10000" & + "11111" & + "10000" & + "11111", + 15 => "11111" & -- Hex F + "10000" & + "11110" & + "10000" & + "10000", + 16 => "11110" & -- State P = No PLL Lock + "10001" & + "11110" & + "10000" & + "10000", + 17 => "10001" & -- State N = No Link + "11001" & + "10101" & + "10011" & + "10001", + 18 => "10000" & -- State L = Link + "10000" & + "10000" & + "10000" & + "11111" + ); + +end DisplayCharacters; diff --git a/rce/fw-hsio/modules/pixelcore/hdl/DisplayControl.vhd b/rce/fw-hsio/modules/pixelcore/hdl/DisplayControl.vhd new file mode 100755 index 00000000..693ab824 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/DisplayControl.vhd @@ -0,0 +1,260 @@ +------------------------------------------------------------------------------- +-- Title : OSRAM SCDV5540 Display Controller +-- Project : General Purpose Core +------------------------------------------------------------------------------- +-- File : DisplayControl.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 12/06/2007 +------------------------------------------------------------------------------- +-- Description: +-- Source code for display controller for OSRAM SCDV5540 4-digit LED +-- display. An 8-bit input value is input for each of the 4 digits on the +-- LED display. This 8-bit value is used to lookup a charactor from a defined +-- table of charactors. +-- See DisplayCharacters file for character definitions. +------------------------------------------------------------------------------- +-- Copyright (c) 2007 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 12/06/2007: created. +-- 03/06/2008: Fixed reset of shiftValue +------------------------------------------------------------------------------- +LIBRARY ieee; +Library Unisim; +USE ieee.std_logic_1164.ALL; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; +USE work.ALL; +use work.DisplayCharacters.all; + +entity DisplayControl is + port ( + + -- Master Clock & reset + sysClk : in std_logic; + sysRst : in std_logic; + + -- Display timing strobe. 200ns min period. + dispStrobe : in std_logic; + + -- Update display + dispUpdate : in std_logic; + + -- Display rotation, 0=0, 1=90, 2=180, 3=270 + dispRotate : in std_logic_vector(1 downto 0); + + -- Index value for charactor digits + dispDigitA : in std_logic_vector(7 downto 0); + dispDigitB : in std_logic_vector(7 downto 0); + dispDigitC : in std_logic_vector(7 downto 0); + dispDigitD : in std_logic_vector(7 downto 0); + + -- Outputs to display device + dispClk : out std_logic; + dispDat : out std_logic; + dispLoadL : out std_logic; + dispRstL : out std_logic + ); + + -- Keep from combinging output clocks + attribute syn_preserve : boolean; + attribute syn_preserve of dispClk: signal is true; + +end DisplayControl; + + +-- Define architecture for first level module +architecture DisplayControl of DisplayControl is + + -- Local signals + signal intLoad : std_logic; + signal intData : std_logic; + signal charCount : std_logic_vector(1 downto 0); + signal wordCount : std_logic_vector(2 downto 0); + signal bitCount : std_logic_vector(3 downto 0); + signal shiftCount : std_logic_vector(6 downto 0); + signal shiftValue : std_logic_vector(39 downto 0); + signal newShift : std_logic_vector(39 downto 0); + signal lookupValue : std_logic_vector(24 downto 0); + signal newDigit : std_logic_vector(7 downto 0); + signal strobeDelay : std_logic; + signal strobeEdge : std_logic; + signal shiftEn : std_logic; + + -- Keep from combinging output clocks + attribute syn_preserve of strobeDelay: signal is true; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Output Control Lines + process ( sysClk, sysRst ) begin + if sysRst = '1' then + dispLoadL <= '1' after tpd; + dispRstL <= '0' after tpd; + dispClk <= '0' after tpd; + dispDat <= '0' after tpd; + elsif rising_edge(sysClk) then + dispLoadL <= not intLoad after tpd; + dispRstL <= '1' after tpd; + dispClk <= not dispStrobe after tpd; + dispDat <= intData after tpd; + end if; + end process; + + + -- Strobe edge detection + strobeEdge <= dispStrobe and not strobeDelay; + + -- Shift sequence control and counters + process ( sysClk, sysRst ) begin + if sysRst = '1' then + charCount <= (others=>'0') after tpd; + wordCount <= (others=>'0') after tpd; + shiftCount <= (others=>'0') after tpd; + bitCount <= (others=>'0') after tpd; + shiftEn <= '0' after tpd; + intLoad <= '0' after tpd; + intData <= '0' after tpd; + strobeDelay <= '0' after tpd; + shiftValue <= (others=>'0') after tpd; + elsif rising_edge(sysClk) then + + -- Delayed copy of shift + strobeDelay <= dispStrobe after tpd; + + -- Sequnce is not running + if shiftEn = '0' then + charCount <= (others=>'0') after tpd; + wordCount <= (others=>'0') after tpd; + shiftCount <= (others=>'0') after tpd; + bitCount <= (others=>'0') after tpd; + shiftEn <= dispUpdate after tpd; + intLoad <= '0' after tpd; + intData <= '0' after tpd; + + -- Sequence Is Running + elsif strobeEdge = '1' then + + -- Bit Counter For 8-bit word plus 3-bit space + if bitCount = 12 then + bitCount <= (others=>'0') after tpd; + else + bitCount <= bitCount + 1 after tpd; + end if; + + -- Word Counter, Digit address, followed by 4 Rows + if bitCount = 12 then + if wordCount = 5 then + wordCount <= (others=>'0') after tpd; + else + wordCount <= wordCount + 1 after tpd; + end if; + end if; + + -- Char Counter, 4 Characters + if bitCount = 12 and wordCount = 5 then + if charCount = 3 then + charCount <= (others=>'0') after tpd; + shiftEn <= '0' after tpd; + else + charCount <= charCount + 1 after tpd; + end if; + end if; + + -- Shift Bit Counter, Shift Output for words 1-5 + if wordCount = 0 then + shiftCount <= (others=>'0') after tpd; + shiftValue <= newShift after tpd; + elsif bitCount < 8 then + shiftCount <= shiftCount + 1 after tpd; + end if; + + -- Character address is first word + if wordCount = 0 then + case bitCount is + when "0000" => intData <= charCount(0) after tpd; + when "0001" => intData <= charCount(1) after tpd; + when "0010" => intData <= '0' after tpd; + when "0011" => intData <= '0' after tpd; + when "0100" => intData <= '0' after tpd; + when "0101" => intData <= '1' after tpd; + when "0110" => intData <= '0' after tpd; + when "0111" => intData <= '1' after tpd; + when others => intData <= '0' after tpd; + end case; + + -- Shift out digit values for words 1-5 + else + intData <= shiftValue(conv_integer(shiftCount)) after tpd; + end if; + + -- Load Strobe asserted for bits 0-7 + if bitCount < 8 then + intLoad <= '1' after tpd; + else + intLoad <= '0' after tpd; + end if; + end if; + end if; + end process; + + + -- Select Digit For Display + newDigit <= dispDigitA when charCount = 0 else + dispDigitB when charCount = 1 else + dispDigitC when charCount = 2 else + dispDigitD; + + -- Get Raw Lookup Value + lookupValue <= (others=>'0') when newDigit > DISPMAX else DISPLOOKUP(conv_integer(newDigit)); + + -- Determine rotation of display digit and add row addresses + newShift <= + + -- No Rotation + "000" & lookupValue(24 downto 20) & + "001" & lookupValue(19 downto 15) & + "010" & lookupValue(14 downto 10) & + "011" & lookupValue(9 downto 5) & + "100" & lookupValue(4 downto 0) when dispRotate = 0 else + + -- 90 Deg Rotation + "000" & lookupValue(4) & lookupValue(9) & + lookupValue(14) & lookupValue(19) & lookupValue(24) & + "001" & lookupValue(3) & lookupValue(8) & + lookupValue(13) & lookupValue(18) & lookupValue(23) & + "010" & lookupValue(2) & lookupValue(7) & + lookupValue(12) & lookupValue(17) & lookupValue(22) & + "011" & lookupValue(1) & lookupValue(6) & + lookupValue(11) & lookupValue(16) & lookupValue(21) & + "100" & lookupValue(0) & lookupValue(5) & + lookupValue(10) & lookupValue(15) & lookupValue(20) when dispRotate = 1 else + + -- 180 Deg Rotation + "000" & lookupValue(0) & lookupValue(1) & + lookupValue(2) & lookupValue(3) & lookupValue(4) & + "001" & lookupValue(5) & lookupValue(6) & + lookupValue(7) & lookupValue(8) & lookupValue(9) & + "010" & lookupValue(10) & lookupValue(11) & + lookupValue(12) & lookupValue(13) & lookupValue(14) & + "011" & lookupValue(15) & lookupValue(16) & + lookupValue(17) & lookupValue(18) & lookupValue(19) & + "100" & lookupValue(20) & lookupValue(21) & + lookupValue(22) & lookupValue(23) & lookupValue(24) when dispRotate = 2 else + + -- 270 Deg Rotation + "000" & lookupValue(20) & lookupValue(15) & + lookupValue(10) & lookupValue(5) & lookupValue(0) & + "001" & lookupValue(21) & lookupValue(16) & + lookupValue(11) & lookupValue(6) & lookupValue(1) & + "010" & lookupValue(22) & lookupValue(17) & + lookupValue(12) & lookupValue(7) & lookupValue(2) & + "011" & lookupValue(23) & lookupValue(18) & + lookupValue(13) & lookupValue(8) & lookupValue(3) & + "100" & lookupValue(24) & lookupValue(19) & + lookupValue(14) & lookupValue(9) & lookupValue(4); + +end DisplayControl; diff --git a/rce/fw-hsio/modules/pixelcore/hdl/HsioPixelCore.vhd b/rce/fw-hsio/modules/pixelcore/hdl/HsioPixelCore.vhd new file mode 100644 index 00000000..d5a95425 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/HsioPixelCore.vhd @@ -0,0 +1,1826 @@ +------------------------------------------------------------------------------- +-- Title : BNL ASIC Test FGPA Core +-- Project : LCLS Detector, BNL ASIC +------------------------------------------------------------------------------- +-- File : BnlAsicCore.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 07/21/2008 +------------------------------------------------------------------------------- +-- Description: +-- Core logic for BNL ASIC test FPGA. +------------------------------------------------------------------------------- +-- Copyright (c) 2008 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 07/21/2008: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; +use work.arraytype.all; +use work.Version.all; +use work.StdRtlPkg.all; + +entity HsioPixelCore is + generic ( + framedFirstChannel : integer := 0; --First framed channel + framedLastChannel : integer := 7; --Last framed channel + rawFirstChannel : integer := 11; --First raw channel + rawLastChannel : integer := 14; -- Last raw channel + buffersizefe : integer := 8192; --FIFO size + buffersizetdc : integer := 8192; --FIFO size + fixed160 : std_logic := '0';-- fixed 160 or choice 40/160 + encodingDefault : std_logic_vector(1 downto 0) := "00"; --BPM or Manchester or nothing on startup + hitbusreadout : std_logic := '0' -- hitbus configuration + ); + port ( + + -- Master system clock, 250Mhz, 125Mhz + sysClk250 : in std_logic; + sysClk125 : in std_logic; + sysRst125 : in std_logic; + sysRst250 : in std_logic; + + -- PGP Clocks + refClock : in std_logic; + pgpClk : in std_logic; + pgpClk90 : in std_logic; + pgpReset : in std_logic; + + pgpClkUnbuf : in std_logic; + pgpClk90Unbuf: in std_logic; + sysClkUnbuf : in std_logic; + + clk320 : in std_logic; + -- reload firmware + reload : out std_logic; + + -- MGT Serial Pins + mgtRxN : in std_logic; + mgtRxP : in std_logic; + mgtTxN : out std_logic; + mgtTxP : out std_logic; + + -- ATLAS Pixel module pins + serialin : in std_logic_vector(15 downto 0); + serialout : out std_logic_vector(15 downto 0); + clock160 : in std_logic; + clock80 : in std_logic; + clock40 : in std_logic; + + -- Reset out to PGP Clock generation + resetOut : out std_logic; + + -- Input from trigger logic + l1a : in std_logic; + latchtriggerword: in std_logic_vector(7 downto 0); + tcounter1 : in std_logic_vector(31 downto 0); + tcounter2 : in std_logic_vector(31 downto 0); + busy : in std_logic; + eudaqdone : in std_logic; + eudaqtrgword : in std_logic_vector(14 downto 0); + + -- Output to trigger logic + present : out std_logic; + calibmodeout : out std_logic_vector(1 downto 0); + startmeas : out std_logic; + pausedout : out std_logic; + trgenabledout : out std_logic; + rstFromCore : out std_logic; + fifothresh : out std_logic; + triggermask : out std_logic_vector(15 downto 0); + discop : out std_logic_vector(15 downto 0); + period : out std_logic_vector(31 downto 0); + telescopeop : out std_logic_vector(2 downto 0); + + resetdelay : out std_logic; + incrementdelay: out std_logic_vector(4 downto 0); + sbusy : out std_logic; --serbusy + tdcbusy : out std_logic; + phaseclksel : out std_logic; + hitbus : out std_logic; + + -- Debug + debug : out std_logic_vector(7 downto 0); + exttriggero : out std_logic; + extrsto : out std_logic; + + doricreset : out std_logic; + phasebusyEn : out std_logic; + phasebusySel : out std_logic_vector(1 downto 0); + + dispDigitA : out std_logic_vector(7 downto 0); + dispDigitB : out std_logic_vector(7 downto 0); + dispDigitC : out std_logic_vector(7 downto 0); + dispDigitD : out std_logic_vector(7 downto 0); + dispDigitE : out std_logic_vector(7 downto 0); + dispDigitF : out std_logic_vector(7 downto 0); + dispDigitG : out std_logic_vector(7 downto 0); + dispDigitH : out std_logic_vector(7 downto 0); + trigAdc : out sl:='0'; + sendAdcData : in sl; + adcData : in Slv16Array(11 downto 0) + + ); +end HsioPixelCore; + + +-- Define architecture +architecture HsioPixelCore of HsioPixelCore is + + component decode_8b10b_wrapper + port ( + CLK : in STD_LOGIC; + DIN : in STD_LOGIC_VECTOR(9 downto 0); + DOUT : out STD_LOGIC_VECTOR(7 downto 0); + KOUT : out STD_LOGIC; + + CE : in STD_LOGIC; + SINIT : in STD_LOGIC; + CODE_ERR : out STD_LOGIC; + ND : out STD_LOGIC + ); + end component; + + component datafifo + generic ( + buffersize : integer :=8192 -- FIFO size + ); + port ( + din: IN std_logic_VECTOR(17 downto 0); + rd_clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_clk: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(17 downto 0); + empty: OUT std_logic; + full: OUT std_logic; + overflow: OUT std_logic; + prog_full: OUT std_logic; + valid: OUT std_logic; + underflow: out std_logic); + end component; + component datafifo8192 + port ( + din: IN std_logic_VECTOR(17 downto 0); + rd_clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_clk: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(17 downto 0); + empty: OUT std_logic; + full: OUT std_logic; + overflow: OUT std_logic; + prog_full: OUT std_logic; + valid: OUT std_logic; + underflow: out std_logic); + end component; + COMPONENT datafifo16384 + PORT ( + rst : IN STD_LOGIC; + wr_clk : IN STD_LOGIC; + rd_clk : IN STD_LOGIC; + din : IN STD_LOGIC_VECTOR(17 DOWNTO 0); + wr_en : IN STD_LOGIC; + rd_en : IN STD_LOGIC; + dout : OUT STD_LOGIC_VECTOR(17 DOWNTO 0); + full : OUT STD_LOGIC; + overflow : OUT STD_LOGIC; + empty : OUT STD_LOGIC; + valid : OUT STD_LOGIC; + underflow : OUT STD_LOGIC; + prog_full : OUT STD_LOGIC + ); + END COMPONENT; + + component datafifo1024 + port ( + din: IN std_logic_VECTOR(17 downto 0); + rd_clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_clk: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(17 downto 0); + empty: OUT std_logic; + full: OUT std_logic; + overflow: OUT std_logic; + prog_full: OUT std_logic; + valid: OUT std_logic; + underflow: out std_logic); + end component; + + component wordswapper + port ( + rst : in std_logic; + clk : in std_logic; + wordin : in std_logic_vector(15 downto 0); + eofin : in std_logic; + eeofin : in std_logic; + sofin : in std_logic; + validin : in std_logic; + wordout : out std_logic_vector(15 downto 0); + eofout : out std_logic; + eeofout : out std_logic; + sofout : out std_logic; + validout : out std_logic + ); + end component; + +component fifo8b10b + port ( + din: IN std_logic_VECTOR(9 downto 0); + rd_clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_clk: IN std_logic; + wr_en: IN std_logic; + almost_empty: OUT std_logic; + dout: OUT std_logic_VECTOR(9 downto 0); + empty: OUT std_logic; + full: OUT std_logic; + underflow: OUT std_logic); +end component; +component fifo8b10bnew + port ( + rst: IN std_logic; + wr_clk: IN std_logic; + rd_clk: IN std_logic; + din: IN std_logic_VECTOR(9 downto 0); + wr_en: IN std_logic; + rd_en: IN std_logic; + dout: OUT std_logic_VECTOR(9 downto 0); + full: OUT std_logic; + empty: OUT std_logic; + almost_empty: OUT std_logic; + valid: OUT std_logic); +end component; + +component noframefifo + port ( + rst: IN std_logic; + wr_clk: IN std_logic; + rd_clk: IN std_logic; + din: IN std_logic_VECTOR(17 downto 0); + wr_en: IN std_logic; + rd_en: IN std_logic; + dout: OUT std_logic_VECTOR(17 downto 0); + full: OUT std_logic; + empty: OUT std_logic; + almost_empty: OUT std_logic; + valid: OUT std_logic); +end component; + + component OBUF port ( O : out std_logic; I : in std_logic ); end component; + -- PGP Front End Wrapper + + component BUFGMUX port (O: out std_logic; I0: in std_logic; I1: in std_logic; S: in std_logic); end component; + + component ila + PORT ( + CONTROL : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0); + CLK : IN STD_LOGIC; + DATA : IN STD_LOGIC_VECTOR(31 DOWNTO 0); + TRIG0 : IN STD_LOGIC_VECTOR(0 DOWNTO 0)); + + end component; + component icon + PORT ( + CONTROL0 : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0)); + + end component; + component ODDR port ( + Q : out std_logic; + CE : in std_logic; + C : in std_logic; + D1 : in std_logic; + D2 : in std_logic; + R : in std_logic; + S : in std_logic + ); + end component; + + --attribute syn_noprune : boolean; + --attribute syn_noprune of chipscope : label is true; + --attribute syn_noprune of chipscopeicon : label is true; + + + component pattern_blk_mem + port ( + clka: IN std_logic; + dina: IN std_logic_VECTOR(31 downto 0); + addra: IN std_logic_VECTOR(9 downto 0); + ena: IN std_logic; + wea: IN std_logic_VECTOR(0 downto 0); + douta: OUT std_logic_VECTOR(31 downto 0); + clkb: IN std_logic; + dinb: IN std_logic_VECTOR(31 downto 0); + addrb: IN std_logic_VECTOR(9 downto 0); + enb: IN std_logic; + web: IN std_logic_VECTOR(0 downto 0); + doutb: OUT std_logic_VECTOR(31 downto 0)); + end component; + + -- Local Signals + signal cmdEn : std_logic; + signal cmdOpCode : std_logic_vector(7 downto 0); + signal cmdCtxOut : std_logic_vector(23 downto 0); + signal readDataValid : std_logic; + signal readDataSOF : std_logic; + signal readDataEOF : std_logic; + signal readDataEOFE : std_logic; + signal readData : std_logic_vector(15 downto 0); + signal pgpDispA : std_logic_vector(7 downto 0); + signal pgpDispB : std_logic_vector(7 downto 0); + signal regReq : std_logic; + signal regOp : std_logic; + signal regAck : std_logic; + signal regFail : std_logic; + signal regAddr : std_logic_vector(23 downto 0); + signal regDataOut : std_logic_vector(31 downto 0); + signal regDataIn : std_logic_vector(31 downto 0); + signal ack : std_logic; + signal err : std_logic; + signal eof : std_logic; + signal sof : std_logic; + signal vvalid : std_logic; + signal req : std_logic; + signal frameRxValid : std_logic; + signal frameRxReady : std_logic; + signal frameRxSOF : std_logic; + signal frameRxEOF : std_logic; + signal frameRxEOFE : std_logic; + signal frameRxData : std_logic_vector(15 downto 0); + signal regInp : std_logic; + signal blockdata : std_logic_vector(17 downto 0); + signal configdataout : std_logic_vector(17 downto 0); + signal blockcounter : std_logic_vector(2 downto 0); + signal handshake : std_logic; + signal replynow : std_logic; + signal readword : std_logic; + signal swapsof : std_logic; + signal swappedeof : std_logic; + signal oldswappedeof : std_logic; + signal gocounter : std_logic_vector(3 downto 0); + signal swapvalid : std_logic; + signal readvalid : std_logic; + signal counter1 : std_logic_vector(3 downto 0); + signal counter2 : std_logic_vector(3 downto 0); + signal idcounter : std_logic_vector(2 downto 0); + signal daddr : std_logic_vector (6 downto 0); + signal denphase : std_logic; + signal phaseclk : std_logic; + signal phaseclk90 : std_logic; + signal phaseclk180 : std_logic; + signal phaseclk270 : std_logic; + signal o01 : std_logic; + signal o23 : std_logic; + signal clockselect : std_logic_vector(1 downto 0); + signal fxclock : std_logic; + signal serclk : std_logic; + signal drdy : std_logic; + signal drdy2 : std_logic; + signal lockedfx : std_logic; + signal lockedid : std_logic; + signal oldlockedid : std_logic; + signal lockedphase : std_logic; + signal lockednophase : std_logic; + signal reqclkphase : std_logic; + signal oldreqclkphase : std_logic; + signal clkenaphase : std_logic; + signal holdrst : std_logic; + signal phaserst : std_logic; + signal clockrst : std_logic; + signal clockrst2 : std_logic; + signal idctrlrst : std_logic; + signal clkdata : std_logic_vector(15 downto 0); + signal holdctr : std_logic_vector(24 downto 0); + signal clockidctrl : std_logic; + signal dreset : std_logic_vector(23 downto 16); + signal ena : std_logic; + signal cout : std_logic; + signal enaold : std_logic; + signal pgpEnaOld : std_logic; + signal countclk : std_logic; + signal clockcountv : std_logic_vector(16 downto 0); + signal starttdcreadout : std_logic; + signal resettdc : std_logic; + signal counterout1 : std_logic_vector(31 downto 0); + signal counterout2 : std_logic_vector(31 downto 0); + signal oldl1a : std_logic; + signal l1amod : std_logic; + signal stop : std_logic; + signal oldstop : std_logic; + signal go : std_logic; + signal qout : std_logic_vector(15 downto 0); + signal tdcdata : std_logic_vector(17 downto 0); + signal tdcld : std_logic; + signal datawaiting : std_logic_vector(31 downto 0); + signal moredatawaiting : std_logic_vector(31 downto 0); + signal indatavalid : std_logic_vector(31 downto 0); + signal chanld : std_logic_vector(31 downto 0); + signal datain : dataarray; + signal channeldata : dataarray; + signal dataout : std_logic_vector(31 downto 0); + signal eofout : std_logic; + signal sofout : std_logic; + signal datavalid : std_logic; + signal reqdata : std_logic_vector(31 downto 0); + signal dfifothresh : std_logic_vector(31 downto 0); + signal andr : std_logic_vector(31 downto 0); + signal empty : std_logic; + signal full : std_logic; + signal configfull : std_logic; + signal bufoverflow : std_logic_vector(31 downto 0); + signal overflow : std_logic_vector(31 downto 0); + signal underflow : std_logic_vector(31 downto 0); + signal prog_full : std_logic; + signal emptyv : std_logic_vector(31 downto 0); + signal fullv : std_logic_vector(31 downto 0); + signal overflowv : std_logic_vector(31 downto 0); + signal underflowv : std_logic_vector(31 downto 0); + signal prog_fullv : std_logic_vector(31 downto 0); + signal isrunning : std_logic_vector(31 downto 0); + signal startdc : std_logic; + signal rst : std_logic; + signal softrst : std_logic; + signal trigenabled : std_logic; + signal exttrgclkeu : std_logic; + signal waitfordata : std_logic; + signal marker : std_logic; + signal mxdata : std_logic_vector(15 downto 0); + signal mxvalid : std_logic; + signal mxeof : std_logic; + signal mxsof : std_logic; + signal ldser : std_logic; + signal configoverflow : std_logic; + signal configunderflow : std_logic; + signal d_out : std_logic; + signal serbusy : std_logic; + signal trgbusy : std_logic; + signal stdc : std_logic; + signal calibmode : std_logic_vector(1 downto 0); + signal edge1 : std_logic; + signal edge2 : std_logic; + signal startrun : std_logic; + signal paused : std_logic; + signal nobackpressure : std_logic; + signal nobackpress : std_logic; + signal reg : std_logic_vector(31 downto 0); + signal backprescounter : std_logic_vector(3 downto 0); + signal counter4 : std_logic_vector(31 downto 0); + signal counter10 : std_logic_vector(31 downto 0); + signal counter10e : std_logic_vector(31 downto 0); + signal tdccounter : std_logic_vector(15 downto 0); + signal counter4m : std_logic_vector(31 downto 0); + signal counter10m : std_logic_vector(31 downto 0); + signal frameTxAFull : std_logic; + signal channelmask : std_logic_vector(31 downto 0); + signal channeloutmask : std_logic_vector(31 downto 0); + signal enablereadout : std_logic_vector(31 downto 0); + signal phases : std_logic_vector(31 downto 0); + signal status : std_logic_vector(31 downto 0); + signal statusd : std_logic_vector(31 downto 0); + signal trgtime : std_logic_vector(63 downto 0); + signal trgtimel : std_logic_vector(63 downto 0); + signal deadtime : std_logic_vector(63 downto 0); + signal deadtimel : std_logic_vector(63 downto 0); + signal l1count : std_logic_vector(3 downto 0); + signal l1countlong : std_logic_vector(31 downto 0); + signal l1countl : std_logic_vector(3 downto 0); + signal rstl1count : std_logic; + signal starttdccount : std_logic_vector(3 downto 0); + signal trgdelay : std_logic_vector(7 downto 0); + signal markercounter : std_logic_vector(9 downto 0); + signal conftrg : std_logic; + signal ld8b10b : std_logic_vector(15 downto 0); + signal ldout8b10b : std_logic_vector(15 downto 0); + signal data8b10b : array10b; + signal dout8b10b : array10b; + signal ldfei4 : std_logic_vector(15 downto 0); + signal ldfifo : std_logic_vector(15 downto 0); + signal dnextvalid : std_logic_vector(15 downto 0); + signal dvalid : std_logic_vector(15 downto 0); + signal frameoverflow : std_logic_vector(15 downto 0); + signal fei4data : fei4array; + signal fifodata : fei4array; + signal dnext : fei4array; + signal aligned : std_logic_vector(15 downto 0); + signal alignout : std_logic_vector(15 downto 0); + signal receiveclock : std_logic; + signal receiveclock90 : std_logic; + signal serdesclock : std_logic; + signal recdata : std_logic_vector(15 downto 0); + signal read8b10bfifo : std_logic_vector(15 downto 0); + signal fifo8b10bempty : std_logic_vector(15 downto 0); + signal valid8b10b : std_logic_vector(15 downto 0); + signal pgpencdatain : array10b; + signal selfei4clk : std_logic_vector(1 downto 0); + signal trgcount : std_logic_vector(15 downto 0); + signal trgcountdown : std_logic_vector(15 downto 0); + + signal encoding : std_logic_vector(1 downto 0); + signal oldbpm : std_logic; + signal doriccounter : std_logic_vector(15 downto 0); + signal doricresetb : std_logic; + signal trgin : std_logic; + signal setdeadtime : std_logic_vector(15 downto 0); + signal serialoutb : std_logic_vector(15 downto 0); + signal ccontrol : std_logic_vector(35 downto 0); + signal cdata : std_logic_vector(31 downto 0); + signal ctrig : std_logic_vector(0 downto 0); + signal setfifothresh : std_logic_vector(15 downto 0); + + signal phaseConfig : std_logic; + + signal hitbusa : std_logic; + signal hitbusb : std_logic; + signal hitbusop : std_logic_vector(15 downto 0); + signal hitbusin : std_logic_vector(5 downto 0); + signal hitbusword : hitbusoutput; + signal hitbusdepth : std_logic_vector(4 downto 0); + signal tdcreadoutdelay: std_logic_vector(4 downto 0); + + signal flatch: std_logic_vector(7 downto 0); + signal ofprotection : std_logic; + + signal phaseClkUnbuf : std_logic; + signal phaseClk90Unbuf : std_logic; + signal phaseClk180Unbuf : std_logic; + signal phaseClk270Unbuf : std_logic; + + signal writemem: std_logic; + signal maxmem: std_logic_vector(9 downto 0); + signal ld32: std_logic; + signal oldld32: std_logic; + signal serdata32: std_logic_vector(31 downto 0); + signal readpointer: std_logic_vector(9 downto 0); + signal memout : std_logic; + signal stop32: std_logic; + signal go32 : std_logic; + signal going32: std_logic; + signal l1route: std_logic; + signal l1modin: std_logic; + signal l1memin: std_logic; + signal readmem: std_logic; + signal bpl: std_logic; + signal multiplicity: std_logic_vector(63 downto 0); + signal tdcfifothresh: std_logic_vector(7 downto 0); + signal oldtdcbusy: std_logic; + signal tdcbusys: std_logic; + + signal adccounter: slv(31 downto 0):=x"00000000"; + signal adcperiod : slv(31 downto 0):=x"02625a00"; + signal oldadcperiod : slv(31 downto 0):=x"02625a00"; + signal enableAdcReadout: sl; + + signal oldbackpressure: sl:='1'; + signal olddft: sl:='1'; + signal maxlength: natural range 0 to 16383; + signal oldindatav: sl; + signal oldindata: slv(23 downto 0); + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + type DELAR is array (0 to 15) of integer; + constant setting: DELAR := (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); + --attribute syn_noprune : boolean; + constant maxchannel : integer := maximum(framedLastChannel, rawLastChannel); + constant ackchannel : integer:=31; + constant tdcchannel: integer:=30; + constant adcchannel: integer:=29; + + function vectorize(s: std_logic) return std_logic_vector is + variable v: std_logic_vector(0 downto 0); + begin + v(0) := s; + return v; + end; + + function vectorize(v: std_logic_vector) return std_logic_vector is + begin + return v; + end; + +begin + + + -- PGP Front End + U_PgpFrontEnd: entity work.PgpFrontEnd port map ( + pgpRefClk1 => refClock, pgpRefClk2 => '0', + mgtRxRecClk => open, pgpClk => pgpClk, + pgpReset => pgpReset, pgpDispA => pgpDispA, + pgpDispB => pgpDispB, resetOut => resetOut, + locClk => sysClk125, locReset => sysRst125, + cmdEn => cmdEn, cmdOpCode => cmdOpCode, + cmdCtxOut => cmdCtxOut, regReq => regReq, + regInp => regInp, + regOp => regOp, regAck => regAck, + regFail => regFail, regAddr => regAddr, + regDataOut => regDataOut, regDataIn => regDataIn, + frameTxEnable => readDataValid, frameTxSOF => readDataSOF, + frameTxEOF => readDataEOF, frameTxEOFE => readDataEOFE, + frameTxData => readData, frameTxAFull => frameTxAFull, + frameRxValid => frameRxValid, + frameRxReady => frameRxReady, frameRxSOF => frameRxSOF, + frameRxEOF => frameRxEOF, frameRxEOFE => frameRxEOFE, + frameRxData => frameRxData, valid => vvalid, + eof => eof, sof => sof, + mgtRxN => mgtRxN, + mgtRxP => mgtRxP, mgtTxN => mgtTxN, + mgtTxP => mgtTxP, mgtCombusIn => (others=>'0'), + mgtCombusOut => open + ); + + pausedout<=paused; + trgenabledout<=trigenabled; + calibmodeout<=calibmode; + andr<= channeloutmask and dfifothresh; + fifothresh<=andr(0) or andr(1) or andr(2) or andr(3) or andr(4) + or andr(5) or andr(6) or andr(7) or andr(8) + or andr(9) or andr(10) or andr(11) or andr(12) + or andr(13) or andr(14) or andr(15) or andr(16) + or andr(17) or andr(18) or andr(19) or andr(20) + or andr(21) or andr(22) or andr(23) or andr(24) + or andr(25) or andr(26) or andr(27) or andr(28) + or andr(30); + + dispDigitA<=pgpDispA; + dispDigitB<=pgpDispB; +-- dispDigitC(7 downto 1)<="000000"&bpl; +-- dispDigitC(0)<=flatch(7) or flatch(6) or flatch(5) or flatch(4) or flatch(3) or flatch(2) or flatch(1) or flatch(0); + dispDigitC(7 downto 2)<=(others => '0'); + dispDigitD<=x"0"&FpgaVersion(3 downto 0); + dispDigitE<=x"00"; + dispDigitF<=x"00"; + dispDigitG<=x"00"; + dispDigitH<=x"00"; + + dispdigitC(0)<=dfifothresh(0); + dispdigitC(1)<=frameTxAFull; + --process(sysRst125, sysClk125) begin + -- if(sysRst125='1')then + -- dispDigitC(0)<='0'; + -- dispDigitC(1)<='0'; + -- elsif(rising_edge(sysClk125))then + -- olddft<=overflowv(0); + -- oldbackpressure<=frameTxAFull; + -- if(overflowv(0)='1' and olddft='0')then + -- dispDigitC(0)<='1'; + -- end if; + -- if(frameTxAFull='1' and oldbackpressure='0')then + -- dispDigitC(1)<='1'; + -- end if; + -- end if; + --end process; + + nobackpressure<= not frameTxAFull; + --blockdata(15 downto 0) <= frameRxData; + blockdata(17 downto 16) <= "00"; + frameRxReady <= not configfull; + vvalid<='0'; + readDataEOFE<='0'; + --readData<=(others=>'0'); + regAck<= drdy2 or ack; + regFail<= '0'; + req<='1' when regReq='1' and regAddr(8 downto 7) = "00" else '0'; + reqclkphase <='1' when regReq='1' and (regAddr(8 downto 4) = "11000" or regAddr(8 downto 4) = "11001" or regAddr(8 downto 4) = "11010") else '0'; + + U_phaseshift: entity work.phaseshift port map( + CLKIN_IN => sysClk125, + DADDR_IN => daddr, + DCLK_IN => sysClk125, + DEN_IN => denphase, + DI_IN => regDataOut(15 downto 0), + DWE_IN => regOp, + RST_IN => clockrst2, + CLK0_OUT => phaseclk, + CLK90_OUT => phaseclk90, + CLK180_OUT => phaseclk180, + CLK270_OUT => phaseclk270, + CLKFX_OUT => open, + CLK2X_OUT => open, + DRDY_OUT => drdy2, + LOCKED_OUT=> lockedphase, + pclkUnbuf => phaseClkUnbuf, + pclk90Unbuf => phaseClk90Unbuf, + pclk180Unbuf => phaseClk180Unbuf, + pclk270Unbuf => phaseClk270Unbuf + ); + + clockrst2<=phaserst; + + + with regAddr(8 downto 4) select + daddr<="1010101" when "11000", + "0010001" when "11001", + "0000000" when others; + process(sysRst125, sysClk125) -- clock interface + begin + if (sysRst125='1') then + holdctr<=(others=>'1'); + elsif(sysClk125'event and sysClk125='1') then + if (holdctr=x"000000"&'0') then + phaserst<='0'; + else + if (holdctr(24)='0') then + phaserst<='1'; + end if; + holdctr<=unsigned(holdctr)-1; + end if; + if (reqclkphase='1' and oldreqclkphase='0') then + clkenaphase<='1'; + else + clkenaphase<='0'; + end if; + denphase<=clkenaphase; + oldreqclkphase<=reqclkphase; + end if; + end process; + + process(sysClk125,sysRst125) -- test for tdc + begin + if(sysRst125='1')then + ena<='0'; + enaold<='0'; + pgpEnaOld<='0'; + clockselect<="00"; + trgcount<=x"0000"; + calibmode<="00"; + resetdelay<='0'; + incrementdelay<="00000"; + conftrg<='0'; + trgdelay<=x"02"; + triggermask<=x"0000"; + period<=x"00000000"; + reg<=x"00000000"; + setdeadtime<=x"0007"; + channelmask<=(others => '0'); + channeloutmask<=(ackchannel => '1', others => '0'); + phases <= (others =>'0'); + encoding<=encodingDefault; + hitbusop<=x"0000"; + discop<=x"0000"; + telescopeop<="000"; + setfifothresh<=x"efff"; + ofprotection<='0'; + writemem<='0'; + maxmem<="0000000000"; + l1route<='0'; + hitbusdepth<="00000"; + tdcreadoutdelay<="00000"; + multiplicity<=x"0000000000000000"; + maxlength<=100; + phasebusyEn<='0'; + phasebusySel<="00"; + elsif(rising_edge(sysClk125))then + if(req='1' and pgpEnaOld='0')then + ena<='1'; + case regOp is + when '1' => -- Write + case regAddr(7 downto 0) is + when x"01" => -- Start TDC measurement when in calib mode + startmeas<='1'; + when x"02" => -- Clock select for calib + clockselect<=regDataOut(1 downto 0); + when x"03" => -- Select calib mode + calibmode<= regDataOut(1 downto 0); + -- 0 is normal + -- 1 is tdc calib + -- 2 is eudaq + when x"00" => -- Set channelmask + channelmask<=regDataOut; + when x"04" => -- Switch TDC/Trigger data on and off + channeloutmask(tdcchannel)<=regDataOut(0); + when x"05" => -- Increment disc delays + incrementdelay<=regDataOut(4 downto 0); + when x"06" => + discop<=regDataOut(15 downto 0); + when x"07" => -- reset input delays + resetdelay<='1'; + when x"08" => -- Set trigger delay + conftrg<='1'; + if(unsigned(regDataOut(7 downto 0))<2)then + trgdelay<=x"02"; + else + trgdelay<=regDataOut(7 downto 0); + end if; + when x"09" => -- Set cyclic trigger period + period<=regDataOut; + when x"0a" => -- Clock select for receive clock + selfei4clk<=regDataOut(1 downto 0); + when x"0d" => -- enable data output + channeloutmask(28 downto 0)<=regDataOut(28 downto 0); + channeloutmask(ackchannel)<='1'; + when x"0b" => -- Set trigger mask -1 is scintillator + -- 2 is cyclic + -- 4 is external + -- 8 is external (HSIO) + -- 16 is hitbus + triggermask<=regDataOut(15 downto 0); + when x"0e" => + trgcount<=regDataOut(15 downto 0); + when x"0f" => + setdeadtime<=regDataOut(15 downto 0); + when x"11" => + phases<=regDataOut; + when x"12" => -- write a word into the command stream buffer + writemem<='1'; + when x"13" => -- clear the command stream buffer + maxmem<="0000000000"; + when x"14" => + encoding<=regDataOut(1 downto 0); + when x"15" => + hitbusop<=regDataOut(15 downto 0); + when x"16" => + multiplicity(31 downto 0)<=regDataOut; + when x"17" => + multiplicity(63 downto 32)<=regDataOut; + when x"19" => + setfifothresh<=regDataOut(15 downto 0); + when x"1a" => + ofprotection<=regDataOut(0); + when x"1b" => + l1route<=regDataOut(0); + when x"1c" => + hitbusdepth <= regDataOut(4 downto 0); + when x"1d" => + tdcreadoutdelay <= regDataOut(4 downto 0); + when x"1e" => + telescopeop<=regDataOut(2 downto 0); + when x"1f" => + adcperiod<=regDataOut; + when x"20" => + channeloutmask(adcchannel)<=regDataOut(0); + when x"21" => + maxlength<=conv_integer(unsigned(regDataOut(13 downto 0))); + when x"22" => + phasebusyEn<=regDataOut(0); + phasebusySel<=regDataOut(2 downto 1); + when others => + + end case; + when '0' => -- Read + startmeas<='0'; + case regAddr(3 downto 0) is + when "0000" => + regDataIn<=tcounter1; + when "0001" => + regDataIn<=tcounter2; + when "0011" => + regDataIn<=status; + when "0100" => + regDataIn<=statusd; + when "0101" => + regDataIn<=trgtimel(63 downto 32); + when "0110" => + regDataIn<=trgtimel(31 downto 0); + when "0111" => + regDataIn<=deadtimel(63 downto 32); + when "1000" => + regDataIn<=deadtimel(31 downto 0); + when "1001" => + regDataIn<=counter4; + when "1010" => + regDataIn<=counter10; + when "1011" => + regDataIn<=l1countlong; + when "1100" => + regDataIn<=counter4m; + when "1101" => + regDataIn<=FpgaVersion; + when "1110" => + regDataIn<=reg; + when "1111" => + regDataIn<=channeloutmask; + when others => + end case; + when others => + end case; + else + if(writemem='1')then + maxmem<=unsigned(maxmem)+1; + writemem<='0'; + end if; + startmeas<='0'; + resettdc<='0'; + ena<='0'; + incrementdelay<="00000"; + resetdelay<='0'; + conftrg<='0'; + extrsto<='0'; + end if; + pgpEnaOld<=req; + enaold<=ena; + ack<=enaold; + err<='0'; + end if; + end process; + process (sysRst125, sysClk125) begin + if(sysRst125='1')then + startrun<='0'; + softrst<='0'; + present<='0'; + trigenabled<='0'; + rstl1count<='0'; + marker<='0'; + reload <='1'; + markercounter<="0000000000"; + phaseConfig <='0'; + elsif rising_edge(sysClk125) then + if(cmdEn='1')then + if(cmdOpCode=x"03")then -- start run + softrst<='1'; + startrun<='1'; + trgcountdown<=trgcount; -- for runs with a finite number of events. + elsif(cmdOpCode=x"04")then -- pause run + trigenabled<='0'; + paused<='1'; + elsif(cmdOpCode=x"05")then -- stop run + trigenabled<='0'; + paused<='0'; + present<='0'; + elsif(cmdOpCode=x"06")then -- resume run + trigenabled<='1'; + paused<='0'; + elsif(cmdOpCode=x"07")then -- resume run and set marker after delay + markercounter<="1111111111"; + elsif(cmdOpCode=x"08")then -- Reboot + reload<='0'; + elsif(cmdOpCode=x"09")then -- soft reset + softrst<='1'; + elsif(cmdOpCode=x"10")then -- FS: Write new phase configuration from phase recognition + phaseConfig <= '1'; + elsif(cmdOpCode=x"11")then -- Tell HSIO that this core is active. + present <= '1'; + elsif(cmdOpCode=x"12")then -- Tell HSIO that this core is not active. + present <= '0'; + end if; + elsif(startrun='1')then + softrst<='0'; + startrun<='0'; + trigenabled<='1'; + paused<='0'; + elsif(softrst='1')then + softrst<='0'; + elsif(trgcountdown=x"0001")then -- stop run + trigenabled<='0'; + paused<='0'; + elsif(markercounter="0000000011")then + softrst<='1'; + elsif(markercounter="0000000001")then + marker<='1'; + trigenabled<='1'; + paused<='0'; + rstl1count<='1'; + else + marker<='0'; + rstl1count<='0'; + phaseConfig<='0'; + end if; + if(markercounter/="0000000000")then + markercounter<=unsigned(markercounter)-1; + end if; + if(l1a='1' and trgcountdown/=x"0000")then + trgcountdown<=unsigned(trgcountdown)-1; + end if; + end if; + end process; + rst<= sysRst125 or softrst; + rstFromCore<= rst; + + process begin + wait until rising_edge(sysClk125); + oldadcperiod<=adcperiod; + if(adccounter=adcperiod)then + adccounter<=(others => '0'); + trigAdc <= '1'; + elsif (adcperiod/=oldadcperiod)then + adccounter<=(others => '0'); + trigAdc <= '0'; + else + adccounter<=unsigned(adccounter)+1; + trigAdc <='0'; + end if; + end process; + + doricreset<=doricresetb; + process(sysClk125, sysRst125) -- reset logic for DORIC + begin + if(sysRst125='1') then + doricresetb<='1'; + doriccounter<=x"0000"; + oldbpm<='0'; + elsif(sysClk125'event and sysClk125='1') then + oldbpm<=encoding(0); + if(encoding(0)='1' and oldbpm='0')then + doricresetb<='0'; + doriccounter<=x"ffff"; + elsif(doriccounter/=x"0000")then + doriccounter<=unsigned(doriccounter)-1; + end if; + if(doriccounter=x"0001")then + doricresetb<='1'; + end if; + end if; + end process; + + process(sysClk125,rst) begin + if(rst='1')then + counter4<=(others=>'0'); + counter10<=(others=>'0'); + counter4m<=(others=>'0'); + counter10m<=(others=>'0'); + elsif(rising_edge(sysClk125))then + if(mxsof='1' and mxvalid='1')then + counter4<=unsigned(counter4)+1; + end if; + if(mxeof='1' and mxvalid='1')then + counter10<=unsigned(counter10)+1; + end if; + if(mxsof='1')then + counter4m<=unsigned(counter4m)+1; + end if; + if(mxvalid='1' and mxeof='1')then + counter10m<=unsigned(counter10m)+1; + end if; + end if; + end process; + process (rst, sysClk125) begin + if(rst='1')then + status<=x"00000000"; + statusd<=x"00000000"; + l1count<=x"1"; + l1countlong<=x"00000000"; + starttdccount<=x"1"; + l1countl<=x"1"; + trgtime<=x"0000000000000000"; + trgtimel<=x"0000000000000000"; + deadtime<=x"0000000000000000"; + deadtimel<=x"0000000000000000"; + elsif (rising_edge(sysClk125)) then + oldl1a<=l1a; + if(trigenabled='1' or paused='1')then + trgtime<=unsigned(trgtime)+1; + end if; + if(busy='1' or paused='1')then + deadtime<=unsigned(deadtime)+1; + end if; + if(rstl1count='1')then + l1count<=x"1"; + elsif(l1a='1')then + l1countl<=l1count; + l1count<=unsigned(l1count)+1; + if(oldl1a='0')then + l1countlong<=unsigned(l1countlong)+1; + end if; + trgtimel<=trgtime; + deadtimel<=deadtime; + end if; + status(10 downto 0)<= dfifothresh(10 downto 0); + status(11)<= paused; + status(12)<= frameTxAFull; + + --statusd(10 downto 0)<= statusd(10 downto 0) or underflow; + statusd(3 downto 0) <= l1count; + statusd(7 downto 4) <= starttdccount; + statusd(10 downto 9) <=(others=>'0'); + statusd(21 downto 11)<= statusd(21 downto 11) or overflow(10 downto 0); + statusd(22)<=statusd(22) or configunderflow; + statusd(23)<=statusd(23) or configoverflow; + statusd(24)<=busy; + --statusd(26)<=extbusy; + statusd(26)<='0'; + end if; + end process; + + --B01: BUFGMUX + -- port map( + -- O=> o01, + -- I0 => phaseclkUnbuf, + -- I1 => phaseclk90Unbuf, + -- S => clockselect(0) + -- ); + --B02: BUFGMUX + -- port map( + -- O=> o23, + -- I0 => phaseclk180Unbuf, + -- I1 => phaseclk270Unbuf, + -- S => clockselect(0) + -- ); + --B04: BUFGMUX + -- port map( + -- O=> phaseclksel, + -- I0 => o01, + -- I1 => o23, + -- S => clockselect(1) + -- ); + phaseclksel<='0'; + + sbusy<=trgbusy or going32; + l1modin<=l1a and not l1route; + l1memin<=l1a and l1route; + trgpipeline: entity work.triggerpipeline + port map( + rst=> sysRst125, + clk=> sysClk125, + L1Ain=> l1modin, -- was l1a + L1Aout=> l1amod, + configure=> conftrg, + delay => trgdelay, + busy => trgbusy, + deadtime => setdeadtime + ); + + with hitbusop(3) select + hitbusa<= (hitbusin(0) and hitbusop(0)) or (hitbusin(1) and hitbusop(1)) or (hitbusin(2) and hitbusop(2)) when '0', + (hitbusin(0) or not hitbusop(0)) and (hitbusin(1) or not hitbusop(1)) and (hitbusin(2) or not hitbusop(2)) + and (hitbusop(0) or hitbusop(1) or hitbusop(2)) when '1', + '0' when others; + with hitbusop(7) select + hitbusb<= (hitbusin(3) and hitbusop(4)) or (hitbusin(4) and hitbusop(5)) or (hitbusin(5) and hitbusop(6)) when '0', + (hitbusin(3) or not hitbusop(4)) and (hitbusin(4) or not hitbusop(5)) and (hitbusin(5) or not hitbusop(6)) + and (hitbusop(4) or hitbusop(5) or hitbusop(6)) when '1', + '0' when others; + with hitbusop(8) select + hitbus <= hitbusa or hitbusb when '0', + hitbusa and hitbusb when '1', + '0' when others; + + hr1: if(hitbusreadout='1') generate + counterout1<=hitbusword(0); + counterout2<=hitbusword(1); + end generate hr1; + hr2: if(hitbusreadout='0') generate + counterout1<=tcounter1; + counterout2<=tcounter2; + end generate hr2; + -- Filter out the message header. The only interesting thing is the handshake + process (rst,sysClk125) begin + if(rst='1')then + blockcounter<="000"; + readword<='0'; + handshake<='0'; + swapsof<='0'; + gocounter<=x"0"; + oldswappedeof<='0'; + elsif rising_edge(sysClk125) then + if(frameRxValid='1' and frameRxSOF='1')then + blockcounter<="111"; + elsif(blockcounter /= "000")then + blockcounter<=unsigned(blockcounter)-1; + if(blockcounter="110")then + handshake<=frameRxData(0); + elsif(blockcounter="001")then + readword<='1'; + swapsof<='1'; + end if; + elsif(frameRxEOF='1')then + swapsof<='0'; + readword<='0'; + else + swapsof<='0'; + end if; + oldswappedeof<=swappedeof; + if(swappedeof='1' and oldswappedeof='0') then + if(stop='0')then + go<='1'; + else + gocounter<=x"4"; + end if; + elsif(gocounter/=x"0")then + gocounter<=unsigned(gocounter)-1; + if(gocounter=x"1")then + go<='1'; + end if; + else + go<='0'; + end if; + end if; + end process; + readvalid<=readword and frameRxValid; + process (sysClk125,sysRst125) begin + if(sysRst125='1')then + oldstop<='0'; + elsif rising_edge(sysClk125) then + oldstop<=stop; + if (stop='1' and oldstop='0')then + replynow<=handshake; + else + replynow<='0'; + end if; + end if; + end process; + swapconfig: wordswapper + port map( + rst=>rst, + clk=>sysClk125, + wordin=>frameRxData, + eofin=>frameRxEOF, + eeofin=>'0', + sofin=>swapsof, + validin=>readvalid, + wordout=>blockdata(15 downto 0), + eofout=>swappedeof, + eeofout=>open, + sofout=>open, + validout=>swapvalid + ); + theconfigfifo: datafifo8192 + port map ( + din => blockdata, + rd_clk => sysClk125, + rd_en => ldser, + rst => sysRst125, + wr_clk => sysClk125, + wr_en => swapvalid, + dout => configdataout, + empty => stop, + full => configfull, + overflow => configoverflow, + prog_full => open, + underflow => open); + theser: entity work.ser + port map( + clk=>sysClk125, + ld=>ldser, +-- l1a=>l1a, + l1a=>l1amod, + go=>go, + busy=>serbusy, + stop=>stop, + rst=>rst, + d_in=>configdataout(15 downto 0), + d_out=>d_out + ); + + process (sysClk125, sysRst125) begin + if(sysRst125='1')then + oldld32<='0'; + stop32<='1'; + readpointer<="0000000000"; + elsif rising_edge(sysClk125)then + oldld32<=ld32 or l1memin; + if(l1memin='1' and going32 ='0' and maxmem/="0000000000")then -- serialize trigger sequence + stop32<='0'; + end if; + if(going32='1')then + if(oldld32='1' and ld32='0' )then + if(readpointer=unsigned(maxmem)-1)then + stop32<='1'; + readpointer<="0000000000"; + else + readpointer<=unsigned(readpointer)+1; + end if; + end if; + end if; + end if; + end process; + + readmem<=ld32 or l1memin; + configmem : pattern_blk_mem + port map ( + clka => sysClk125, + dina => regDataOut, + addra => maxmem, + ena => writemem, + wea => vectorize('1'), + douta => open, + clkb => sysClk125, + dinb => (others=>'0'), + addrb => readpointer, + enb => readmem, + web => vectorize('0'), + doutb => serdata32); + + theser32: entity work.ser32 + port map( + clk => sysClk125, + ld => ld32, + go => l1memin, + busy => going32, + stop => stop32, + rst => sysRst125, + d_in => serdata32, + d_out => memout); + + + fanout: for I in 0 to maxchannel generate + bpmenc: entity work.outputencoder + port map( + clock=>sysClk125, + rst=>sysRst125, + clockx2=>sysClk250, + datain=>serialoutb(I), + encode=>encoding, + dataout=>serialout(I)); + serialoutb(I)<= (d_out or memout) when channelmask(I)='1' and doricresetb='1' else '0'; + end generate fanout; + + pgpack: entity work.deser + generic map( CHANNEL=>toSlv(ackchannel, 8) ) + port map ( + clk => sysClk125, + rst => sysRst125, + d_in => '0', + enabled => channeloutmask(ackchannel), + replynow => replynow, + marker =>'0', + d_out => channeldata(ackchannel)(15 downto 0), + ld => chanld(ackchannel), + sof => channeldata(ackchannel)(16), + eof => channeldata(ackchannel)(17) + ); + pgpackfifo : datafifo1024 + port map ( + din => channeldata(ackchannel), + rd_clk => sysClk125, + rd_en => reqdata(ackchannel), + rst => rst, + wr_clk => sysClk125, + wr_en => chanld(ackchannel), + dout => datain(ackchannel), + empty => open, + full => open, + overflow => overflow(ackchannel), + prog_full => dfifothresh(ackchannel), + valid => indatavalid(ackchannel), + underflow => underflow(ackchannel)); + pgpackdataflag: entity work.dataflag + port map( + eofin=>channeldata(ackchannel)(17), + eofout=>datain(ackchannel)(17), + datawaiting=> datawaiting(ackchannel), + clk=>sysClk125, + rst=>rst, + counter=>open + ); + moredatawaiting(ackchannel)<='0'; + + enableAdcReadout<=not dfifothresh(adcchannel) and channeloutmask(adcchannel) and trigenabled; + adcreadout_inst: entity work.adcreadout + generic map( CHANNEL=>toSlv(adcchannel, 8) ) + port map ( + clk => sysClk125, + rst => rst, + d_in => AdcData, + enabled => enableAdcReadout, + go => sendAdcData, + d_out => channeldata(adcchannel)(15 downto 0), + ld => chanld(adcchannel), + sof => channeldata(adcchannel)(16), + eof => channeldata(adcchannel)(17) + ); + adcfifo: datafifo1024 + port map ( + rd_clk => sysClk125, + wr_clk => sysClk125, + rst => rst, + din => channeldata(adcchannel), + rd_en => reqdata(adcchannel), + wr_en => chanld(adcchannel), + dout => datain(adcchannel), + empty => open, + full => open, + overflow => overflow(adcchannel), + prog_full => dfifothresh(adcchannel), + valid => indatavalid(adcchannel), + underflow => underflow(adcchannel)); + adcdataflag: entity work.dataflag + port map( + eofin=>channeldata(adcchannel)(17), + eofout=>datain(adcchannel)(17), + datawaiting=> datawaiting(adcchannel), + clk=>sysClk125, + rst=>rst, + counter => open + ); + + CHANNELREADOUT: + for I in rawFirstChannel to rawLastChannel generate + enablereadout(I)<=channeloutmask(I) and ((trigenabled and not ofprotection) or not dfifothresh(I)); + channelreadout: entity work.deser + generic map( CHANNEL=> std_logic_vector(conv_unsigned(I,4))) + port map ( + clk => sysClk125, + rst => sysRst125, + d_in => serialin(I), + enabled => enablereadout(I), + replynow => '0', + marker => marker, + d_out => channeldata(I)(15 downto 0), + ld => chanld(I), + sof => channeldata(I)(16), + eof => channeldata(I)(17) + ); + channelfifo : datafifo8192 + port map ( + din => channeldata(I), + rd_clk => sysClk125, + rd_en => reqdata(I), + rst => rst, + wr_clk => sysClk125, + wr_en => chanld(I), + dout => datain(I), + empty => open, + full => open, + overflow => overflow(I), + prog_full => dfifothresh(I), + valid => indatavalid(I), + underflow => underflow(I)); + channeldataflag: entity work.dataflagnew + port map( + eofin=>channeldata(I)(17), + eofout=>datain(I)(17), + datawaiting=> datawaiting(I), + moredatawaiting=> moredatawaiting(I), + clkin=>sysClk125, + clkout=>sysClk125, + rst=>rst + ); + end generate CHANNELREADOUT; + + starttdcreadout<=l1a and channeloutmask(tdcchannel); + + process(rst, pgpClk) begin + if(rst='1')then + oldtdcbusy<='0'; + elsif(rising_edge(pgpClk))then + if(tdcbusys='0' and oldtdcbusy='1') then --tdc readout is done + tdcfifothresh<=(others => '0'); + elsif(andr(10) ='1')then + tdcfifothresh(7)<=andr(10); + elsif(andr(6) ='1')then + tdcfifothresh(6)<=andr(6); + elsif(andr(5) ='1')then + tdcfifothresh(5)<=andr(5); + elsif(andr(4) ='1')then + tdcfifothresh(4)<=andr(4); + elsif(andr(3) ='1')then + tdcfifothresh(3)<=andr(3); + elsif(andr(2) ='1')then + tdcfifothresh(2)<=andr(2); + elsif(andr(1) ='1')then + tdcfifothresh(1)<=andr(1); + elsif(andr(0) ='1')then + tdcfifothresh(0)<=andr(0); + end if; + oldtdcbusy<=tdcbusys; + end if; + end process; + tdcbusy<=tdcbusys; + thereeadout: entity work.tdcreadout + generic map(CHANNEL=>toSlv(tdcchannel, 8)) + port map( + clk=>pgpClk, + slowclock=>sysClk125, + rst=>rst, + go=>starttdcreadout, + delay=>tdcreadoutdelay, + counter1=>counterout1, + counter2=>counterout2, + trgtime=>trgtimel, + deadtime=>deadtimel, + status=>status(14 downto 0), + marker=>marker, + l1count=>l1countl, + bxid=>trgtimel(7 downto 0), + d_out=>tdcdata(15 downto 0), + ld=>tdcld, + busy=>tdcbusys, + sof=>tdcdata(16), + eof=>tdcdata(17), + runmode => calibmode, + eudaqdone => eudaqdone, + eudaqtrgword => eudaqtrgword, + fifothresh => tdcfifothresh, + triggerword => latchtriggerword + ); + tdcfifo : datafifo + generic map( buffersize => buffersizetdc) + port map ( + din => tdcdata, + rd_clk => sysClk125, + rd_en => reqdata(tdcchannel), + rst => rst, + wr_clk => pgpClk, + wr_en => tdcld, + dout => datain(tdcchannel), + empty => empty, + full => full, + overflow => overflow(tdcchannel), + prog_full => dfifothresh(tdcchannel), + valid => indatavalid(tdcchannel), + underflow => underflow(tdcchannel)); + tdcdataflag: entity work.dataflagnew + port map( + eofin=>tdcdata(17), + eofout=>datain(tdcchannel)(17), + datawaiting=>datawaiting(tdcchannel), + moredatawaiting=>moredatawaiting(tdcchannel), + clkin=>pgpClk, + clkout=>sysClk125, + rst=>rst); + + multiplexer: entity work.multiplexdata + generic map ( + maxchannel => maxchannel + ) + port map( + clk=>sysClk125, + rst=>rst, + enabled=>nobackpressure, + channelmask=>channeloutmask, + datawaiting=>datawaiting, + moredatawaiting=>moredatawaiting, + indatavalid => indatavalid, + datain=>datain, + dataout=>mxdata, + eofout=>mxeof, + sofout=>mxsof, + datavalid=>mxvalid, + reqdata=>reqdata, + multiplicity => multiplicity, + counter4=>open, + counter10b=>counter10e, + counter10=>open + ); + swapdata: wordswapper + port map( + rst=>rst, + clk=>sysClk125, + wordin=>mxdata, + eofin=>mxeof, + eeofin=>'0', + sofin=>mxsof, + validin=>mxvalid, + wordout=>readData, + eofout=>readDataEOF, + eeofout=>open, + sofout=>readDataSOF, + validout=>readDataValid + ); + + FULLDISPLAY: + for I in 0 to 7 generate + process (rst, dfifothresh(I)) begin + if(rst='1')then + flatch(I)<='0'; + elsif(rising_edge(dfifothresh(I)))then + flatch(I)<='1'; + end if; + end process; + end generate FULLDISPLAY; + process (rst, frameTxAFull) begin + if(rst='1')then + bpl<='0'; + elsif(rising_edge(frameTxAFull))then + bpl<='1'; + end if; + end process; + + bgmf: if(fixed160='1') generate + receiveclock<=pgpClk; + receiveclock90<=pgpClk90; + end generate bgmf; + bgmv: if(fixed160='0') generate + CLKFEI4: BUFGMUX + port map( + O=> receiveclock, + I0 => phaseclkUnbuf, + I1 => pgpClkUnbuf, + S => selfei4clk(1) + ); + CLKFEI490: BUFGMUX + port map( + O=> receiveclock90, + I0 => phaseclk90Unbuf, + I1 => pgpClk90Unbuf, + S => selfei4clk(1) + ); + end generate bgmv; + FRAMEDCHANNELREADOUT: + for I in framedFirstChannel to framedLastChannel generate + receivedata: entity work.syncdatac + port map( + phaseConfig => phaseConfig, + clk => receiveclock, + clk90 => receiveclock90, + rdatain => serialin(I), + rst => sysRst125, + useaout => open, + usebout => open, + usecout => open, + usedout => open, + sdataout => recdata(I)); + FE_CHANNEL: if ((I/=3 and I/=7) or hitbusreadout='0') generate + alignframe: entity work.framealign + port map( + clk => receiveclock, + rst => rst, + d_in => recdata(I), + d_out => alignout(I), + aligned => aligned(I) + ); + deser8b10b: entity work.deser10b + port map( + clk => receiveclock, + rst => rst, + d_in => alignout(I), + align => aligned(I), + d_out => data8b10b(I), + ld => ld8b10b(I) + ); + decoder8b10b: decode_8b10b_wrapper + port map( + CLK => receiveclock, + DIN => data8b10b(I), + DOUT => dout8b10b(I)(7 downto 0), + KOUT => dout8b10b(I)(8), + CE => ld8b10b(I), + SINIT => rst, + CODE_ERR =>dout8b10b(I)(9), + ND =>ldout8b10b(I) + ); + enablereadout(I)<=channeloutmask(I) and ((trigenabled and not ofprotection) or not dfifothresh(I)); + decode: entity work.decodefei4record + port map(clk => receiveclock, + rst => rst, + enabled => enablereadout(I), + isrunning => isrunning(I), + d_in => dout8b10b(I)(7 downto 0), + k_in => dout8b10b(I)(8), + err_in => dout8b10b(I)(9), + d_out => fei4data(I), + ldin => ldout8b10b(I), + ldout => ldfei4(I), + overflow => bufoverflow(I) + ); + fei4fifo : entity work.lookaheadfifo + generic map( buffersize => buffersizefe) + port map ( + din => fei4data(I), + rd_clk => sysClk125, + rd_en => ldfifo(I), + rst => rst, + wr_clk => receiveclock, + wr_en => ldfei4(I), + dout => fifodata(I), + dnext => dnext(I), + dnextvalid => dnextvalid(I), + empty => emptyv(I), + full => fullv(I), + overflow => overflowv(I), + prog_full => dfifothresh(I), + valid => dvalid(I), + underflow => underflowv(I)); + fei4dataflag: entity work.dataflagff + port map( + eofin=>fei4data(I)(24), + ldin => ldfei4(I), + eofout=>dnext(I)(24), + ldout => ldfifo(I), + datawaiting=>datawaiting(I), + moredatawaiting=>moredatawaiting(I), + clkin=>receiveclock, + clkinrate=>selfei4clk(1), + clkout=>sysClk125, + rst=>rst); + encode: entity work.encodepgp24bit + generic map( CHANNEL=> std_logic_vector(conv_unsigned(I,4))) + port map(clk => sysClk125, + rst => rst, + enabled =>channeloutmask(I), + maxlength => maxlength, + isrunning => open, + d_in => fifodata(I), + d_next => dnext(I), + marker => marker, + d_out => datain(I), + ldin => reqdata(I), + ldout => ldfifo(I), + dnextvalid => dnextvalid(I), + dvalid => dvalid(I), + datawaiting=> datawaiting(I), + moredatawaiting=> moredatawaiting(I), + overflow => frameoverflow(I), + valid => indatavalid(I) +); + end generate FE_CHANNEL; + HITBUS_CHANNEL: if (hitbusreadout='1' and (I=3 or I=7)) generate + dfifothresh(I)<='0'; + alignframe: entity work.framealignhitbus + port map( + clk => receiveclock, + rst => rst, + d_in => recdata(I), + d_out => alignout(I), + aligned => aligned(I) + ); + deserhitbus: entity work.deser4b + port map( + clk => receiveclock, + rst => rst, + d_in => alignout(I), + align => aligned(I), + d_out => data8b10b(I)(3 downto 0), + ld => ld8b10b(I) + ); + hitbusin(I/4*3)<=data8b10b(I)(2); + hitbusin(I/4*3+1)<=data8b10b(I)(1); + hitbusin(I/4*3+2)<=data8b10b(I)(0); + thehitbuspipeline: entity work.hitbuspipeline + port map( + rst => rst, + clk => receiveclock, + ld => ld8b10b(I), + depth => hitbusdepth, + wordin => data8b10b(I)(2 downto 0), + wordout => hitbusword(I/4) + ); + end generate HITBUS_CHANNEL; + end generate FRAMEDCHANNELREADOUT; + hbin: if framedfirstchannel>7 or framedlastchannel<7 or hitbusreadout='0' generate + hitbusin(3)<='0'; + hitbusin(4)<='0'; + hitbusin(5)<='0'; + end generate hbin; + hbin2: if framedfirstchannel>3 or framedlastchannel<3 or hitbusreadout='0' generate + hitbusin(0)<='0'; + hitbusin(1)<='0'; + hitbusin(2)<='0'; + end generate hbin2; + dfifothresh(6 downto framedlastchannel+1)<=(others => '0'); + debug(0)<=recdata(7); + debug(1)<=alignout(7); + debug(2)<=aligned(7); + debug(3)<=data8b10b(7)(3); + debug(4)<=ld8b10b(7); + debug(5)<=hitbusin(3); + debug(6)<=hitbusin(5); + --debug(7)<=hitbus; + + + --process (rst, sysClk125) begin + -- if(rst='1')then + -- ctrig(0)<='0'; + -- oldindatav<='0'; + -- oldindata<=x"000000"; + -- elsif rising_edge(sysClk125) then + -- oldindatav<=ldfifo(1); + -- oldindata<=fifodata(1)(23 downto 0); + -- if(ldfifo(1)='1' and fifodata(1)(23 downto 0)=x"02211f" and + -- oldindatav='1' and oldindata=x"02211f")then + -- ctrig(0)<='1'; + -- else + -- ctrig(0)<='0'; + -- end if; + -- end if; + --end process; +-- cdata(9 downto 0)<=dout8b10b(0); + +ctrig(0)<=dnextvalid(1); +cdata(23 downto 0)<=dnext(1)(23 downto 0); +cdata(24)<=fei4data(1)(24); +cdata(25)<=dnext(1)(24); +cdata(26)<=ldfei4(1); +cdata(30)<=dnextvalid(1); +cdata(28)<=datawaiting(1); +cdata(29)<=moredatawaiting(1); +cdata(27)<=ldfifo(1); +cdata(31)<=indatavalid(1); +--cdata(8)<=alignout(2); +--cdata(9)<=aligned(2); +--cdata(11 downto 10)<=dout8b10b(2)(9 downto 8); + +--cdata(12)<=alignout(3); +--cdata(13)<=aligned(3); +--cdata(15 downto 14)<=dout8b10b(3)(9 downto 8); + +--cdata(16)<=alignout(0); +--cdata(17)<=aligned(0); +--cdata(18)<=datawaiting(0); +--cdata(28 downto 19)<=dout8b10b(0); + +--cdata(29)<=alignout(5); +--cdata(30)<=aligned(5); +--cdata(31)<=dout8b10b(5)(9); + + +--chipscope : ila + --port map ( + --CONTROL => ccontrol, + --CLK => sysClk125, + --DATA => cdata, + --TRIG0 => ctrig); +--chipscopeicon : icon + --port map ( + --CONTROL0 => ccontrol); + -- +end HsioPixelCore; + diff --git a/rce/fw-hsio/modules/pixelcore/hdl/I2cMaster.vhd b/rce/fw-hsio/modules/pixelcore/hdl/I2cMaster.vhd new file mode 100644 index 00000000..a49cb314 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/I2cMaster.vhd @@ -0,0 +1,369 @@ +------------------------------------------------------------------------------ +-- This file is a part of the GRLIB VHDL IP LIBRARY +-- Copyright (C) 2003 - 2008, Gaisler Research +-- Copyright (C) 2008 - 2012, Aeroflex Gaisler +-- +-- This program 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 of the License, or +-- (at your option) any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Entity: I2cMaster +-- File: I2cMaster.vhd +-- Author: Jan Andersson - Gaisler Research +-- Contact: support@gaisler.com +-- Description: +-- +-- Generic interface to OpenCores I2C-master. This is a wrapper +-- that instantiates the byte- and bit-controller of the OpenCores I2C +-- master (OC core developed by Richard Herveille, richard@asics.ws). +-- +-- Modifications: +-- 10/2012 - Ben Reese <bareese@slac.stanford.edu> +-- Removed AMBA bus register based interfaced and replaced with generic +-- IO interface for use anywhere within a firmware design. +-- Interface based on transactions consisting of a i2c device address +-- followed by up to 4 byte-reads or 4 byte-writes. +-- +-- Dynamic filter and bus speed adjustment have been left in as features, +-- though they will probably be rarely used. + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.StdRtlPkg.all; +use work.I2cPkg.all; + +entity I2cMaster is + generic ( + TPD_G : time := 1 ns; -- Simulated propagation delay + OUTPUT_EN_POLARITY_G : integer range 0 to 1 := 0; -- output enable polarity + FILTER_G : integer range 2 to 512 := 126; -- filter bit size + DYNAMIC_FILTER_G : integer range 0 to 1 := 0); + port ( + clk : in sl; + srst : in sl := '0'; + arst : in sl := '0'; + -- Front End + i2cMasterIn : in I2cMasterInType; + i2cMasterOut : out I2cMasterOutType; + + -- I2C signals + i2ci : in i2c_in_type; + i2co : out i2c_out_type + ); +end entity I2cMaster; + +architecture rtl of I2cMaster is + ----------------------------------------------------------------------------- + -- Constants + ----------------------------------------------------------------------------- + + ----------------------------------------------------------------------------- + -- Types + ----------------------------------------------------------------------------- + -- i2c_master_byte_ctrl IO + type ByteCtrlInType is record + start : sl; + stop : sl; + read : sl; + write : sl; + ackIn : sl; + din : slv(7 downto 0); + end record; + + type ByteCtrlOutType is record + cmdAck : sl; + ackOut : sl; + al : sl; + busy : sl; + dout : slv(7 downto 0); + end record; + + type StateType is (WAIT_TXN_REQ_S, + ADDR_S, + WAIT_ADDR_ACK_S, + READ_S, + WAIT_READ_DATA_S, + WRITE_S, + WAIT_WRITE_ACK_S); + + -- Module Registers + type RegType is record + byteCtrlIn : ByteCtrlInType; + state : StateType; + tenbit : sl; + i2cMasterOut : I2cMasterOutType; + end record RegType; + + constant REG_INIT_C : RegType := ( + byteCtrlIn => ( + start => '0', + stop => '0', + read => '0', + write => '0', + ackIn => '0', + din => (others => '0')), + state => WAIT_TXN_REQ_S, + tenbit => '0', + i2cMasterOut => ( + txnError => '0', + wrAck => '0', + rdValid => '0', + rdData => (others => '0'))); + + + -------------------------------------------------------------------------------------------------- + -- Signals + -------------------------------------------------------------------------------------------------- + -- Register interface + signal r : RegType := REG_INIT_C; + signal rin : RegType; + + -- Outputs from byte_ctrl block + signal byteCtrlOut : ByteCtrlOutType; + signal iSclOEn : sl; -- Internal SCL output enable + signal iSdaOEn : sl; -- Internal SDA output enablee + signal filter : slv((FILTER_G-1)*DYNAMIC_FILTER_G downto 0); -- filt input to byte_ctrl + signal arstL : sl; + +begin + + arstL <= not arst; + + -- Byte Controller from OpenCores I2C master, + -- by Richard Herveille (richard@asics.ws). The asynchronous + -- reset is tied to '1'. Only the synchronous reset is used. + -- OC I2C logic has active high reset. + byte_ctrl : i2c_master_byte_ctrl + generic map ( + filter => FILTER_G, + dynfilt => DYNAMIC_FILTER_G) + port map ( + clk => clk, + rst => srst, + nReset => arstL, + ena => i2cMasterIn.enable, + clk_cnt => i2cMasterIn.prescale, + start => r.byteCtrlIn.start, + stop => r.byteCtrlIn.stop, + read => r.byteCtrlIn.read, + write => r.byteCtrlIn.write, + ack_in => r.byteCtrlIn.ackIn, + din => r.byteCtrlIn.din, + filt => filter, + cmd_ack => byteCtrlOut.cmdAck, + ack_out => byteCtrlOut.ackOut, + i2c_busy => byteCtrlOut.busy, + i2c_al => byteCtrlOut.al, + dout => byteCtrlOut.dout, + scl_i => i2ci.scl, + scl_o => i2co.scl, + scl_oen => iscloen, + sda_i => i2ci.sda, + sda_o => i2co.sda, + sda_oen => isdaoen); + + i2co.enable <= i2cMasterIn.enable; + + -- Fix output enable polarity + soepol0 : if OUTPUT_EN_POLARITY_G = 0 generate + i2co.scloen <= iscloen; + i2co.sdaoen <= isdaoen; + end generate soepol0; + soepol1 : if OUTPUT_EN_POLARITY_G /= 0 generate + i2co.scloen <= not iscloen; + i2co.sdaoen <= not isdaoen; + end generate soepol1; + + + + + comb : process (r, byteCtrlOut, i2cMasterIn, srst) + variable v : RegType; + variable indexVar : integer; + begin -- process comb + v := r; + + -- byteCtrl commands default to zero + -- unless overridden in a state below + v.byteCtrlIn.start := '0'; + v.byteCtrlIn.stop := '0'; + v.byteCtrlIn.read := '0'; + v.byteCtrlIn.write := '0'; + v.byteCtrlIn.ackIn := '0'; + + v.i2cMasterOut.wrAck := '0'; -- pulsed + + if (i2cMasterIn.rdAck = '1') then + v.i2cMasterOut.rdValid := '0'; + v.i2cMasterOut.txnError := '0'; + end if; + + case (r.state) is + when WAIT_TXN_REQ_S => + -- Reset front end outputs + v.i2cMasterOut.rdData := (others => '0'); -- Necessary? + -- If new request and any previous rdData has been acked. + if (i2cMasterIn.txnReq = '1' and r.i2cMasterOut.rdValid = '0') then + v.state := ADDR_S; + v.tenbit := i2cMasterIn.tenbit; + end if; + + when ADDR_S => + v.byteCtrlIn.start := '1'; + v.byteCtrlIn.write := '1'; + if (r.tenbit = '0') then + if (i2cMasterIn.tenbit = '0') then + -- Send normal 7 bit address + v.byteCtrlIn.din(7 downto 1) := i2cMasterIn.addr(6 downto 0); + v.byteCtrlIn.din(0) := not i2cMasterIn.op; + else + -- Send second half of 10 bit address + v.byteCtrlIn.din := i2cMasterIn.addr(7 downto 0); + end if; + else + -- Send first half of 10 bit address + v.byteCtrlIn.din(7 downto 3) := "00000"; + v.byteCtrlIn.din(2 downto 1) := i2cMasterIn.addr(9 downto 8); + v.byteCtrlIn.din(0) := not i2cMasterIn.op; + end if; + v.state := WAIT_ADDR_ACK_S; + + + when WAIT_ADDR_ACK_S => + if (byteCtrlOut.cmdAck = '1') then -- Master sent the command + if (byteCtrlOut.ackOut = '0') then -- Slave ack'd the transfer + if (r.tenbit = '1') then -- Must send second half of addr if tenbit set + v.tenbit := '0'; + v.state := ADDR_S; + else + -- Do read or write depending on op + if (i2cMasterIn.op = '0') then + v.state := READ_S; + else + v.state := WRITE_S; + end if; + end if; + else + -- Slave did not ack the transfer, fail the txn + v.i2cMasterOut.txnError := '1'; + v.i2cMasterOut.rdValid := '1'; + v.i2cMasterOut.rdData := I2C_INVALID_ADDR_ERROR_C; + v.state := WAIT_TXN_REQ_S; + end if; + end if; + + + when READ_S => + if (r.i2cMasterOut.rdValid = '0') then -- Previous byte has been ack'd + v.byteCtrlIn.read := '1'; + -- If last byte of txn send nack. + -- Send stop on last byte if enabled (else repeated start will occur on next txn). + v.byteCtrlIn.ackIn := not i2cMasterIn.txnReq; + v.byteCtrlIn.stop := not i2cMasterIn.txnReq and i2cMasterIn.stop; + v.state := WAIT_READ_DATA_S; + end if; + + + when WAIT_READ_DATA_S => + v.byteCtrlIn.stop := r.byteCtrlIn.stop; -- Hold stop or it wont get seen + v.byteCtrlIn.ackIn := r.byteCtrlIn.ackIn; -- This too + if (byteCtrlOut.cmdAck = '1') then -- Master sent the command + v.byteCtrlIn.stop := '0'; -- Drop stop asap or it will be repeated + v.byteCtrlIn.ackIn := '0'; + v.i2cMasterOut.rdData := byteCtrlOut.dout; + v.i2cMasterOut.rdValid := '1'; + if (i2cMasterIn.txnReq = '0') then -- Last byte of txn + v.i2cMasterOut.txnError := '0'; -- Necessary? Should already be 0 + v.state := WAIT_TXN_REQ_S; + else + -- If not last byte, read another. + v.state := READ_S; + end if; + end if; + + when WRITE_S => + -- Write the next byte + if (i2cMasterIn.wrValid = '1' and r.i2cMasterOut.wrAck = '0') then + v.byteCtrlIn.write := '1'; + -- Send stop on last byte if enabled (else repeated start will occur on next txn). + v.byteCtrlIn.stop := not i2cMasterIn.txnReq and i2cMasterIn.stop; + v.byteCtrlIn.din := i2cMasterIn.wrData; + v.state := WAIT_WRITE_ACK_S; + end if; + + when WAIT_WRITE_ACK_S => + v.byteCtrlIn.stop := r.byteCtrlIn.stop; + if (byteCtrlOut.cmdAck = '1') then -- Master sent the command + if (byteCtrlOut.ackOut = '0') then -- Slave ack'd the transfer + v.byteCtrlIn.stop := '0'; + v.i2cMasterOut.wrAck := '1'; -- Pass wr ack to front end + if (i2cMasterIn.txnReq = '0') then -- Last byte of txn + v.i2cMasterOut.txnError := '0'; -- Necessary, should already be 0? + v.state := WAIT_TXN_REQ_S; + else + -- If not last byte, write nother + v.state := WRITE_S; + end if; + else + -- Slave did not ack the transfer, fail the txn + v.i2cMasterOut.txnError := '1'; + v.i2cMasterOut.rdValid := '1'; + v.i2cMasterOut.rdData := I2C_WRITE_ACK_ERROR_C; + v.state := WAIT_TXN_REQ_S; + end if; + end if; + + when others => v.state := WAIT_TXN_REQ_S; + end case; + + -- Must always monitor for arbitration loss + if (byteCtrlOut.al = '1') then + -- Retry the entire TXN. Nothing done has been valid if arbitration is lost. + -- Should probably have a retry limit. + v.state := WAIT_TXN_REQ_S; + v.i2cMasterOut.txnError := '1'; + v.i2cMasterOut.rdValid := '1'; + v.i2cMasterOut.rdData := I2C_ARBITRATION_LOST_ERROR_C; + end if; + + ------------------------------------------------------------------------------------------------ + -- Synchronous Reset + ------------------------------------------------------------------------------------------------ + if (srst = '1') then + v := REG_INIT_C; + end if; + + ------------------------------------------------------------------------------------------------ + -- Signal Assignments + ------------------------------------------------------------------------------------------------ + -- Update registers + rin <= v; + + -- Assign outputs + i2cMasterOut <= r.i2cMasterOut; + + end process comb; + filter <= i2cMasterIn.filter when DYNAMIC_FILTER_G = 1 else (others => '0'); + + reg : process (clk, arst) + begin + if (arst = '1') then + r <= REG_INIT_C after TPD_G; + elsif rising_edge(clk) then + r <= rin after TPD_G; + end if; + end process reg; + + +end architecture rtl; diff --git a/rce/fw-hsio/modules/pixelcore/hdl/I2cPkg.vhd b/rce/fw-hsio/modules/pixelcore/hdl/I2cPkg.vhd new file mode 100644 index 00000000..95db89a0 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/I2cPkg.vhd @@ -0,0 +1,199 @@ +------------------------------------------------------------------------------ +-- This file is a part of the GRLIB VHDL IP LIBRARY +-- Copyright (C) 2003 - 2008, Gaisler Research +-- Copyright (C) 2008 - 2012, Aeroflex Gaisler +-- +-- This program 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 of the License, or +-- (at your option) any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +----------------------------------------------------------------------------- +-- Package: i2c +-- File: i2c.vhd +-- Author: Jiri Gaisler - Gaisler Research +-- Description: I2C interface package +------------------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; +use work.StdRtlPkg.all; + +package I2cPkg is + + type i2c_in_type is record + scl : std_ulogic; + sda : std_ulogic; + end record; + + type i2c_in_array is array (natural range <>) of i2c_in_type; + + type i2c_out_type is record + scl : std_ulogic; + scloen : std_ulogic; + sda : std_ulogic; + sdaoen : std_ulogic; + enable : std_ulogic; + end record; + + type i2c_out_array is array (natural range <>) of i2c_out_type; + + -------------------------------------------------------------------------------------------------- + constant I2C_INVALID_ADDR_ERROR_C : slv(7 downto 0) := X"01"; + constant I2C_WRITE_ACK_ERROR_C : slv(7 downto 0) := X"02"; + constant I2C_ARBITRATION_LOST_ERROR_C : slv(7 downto 0) := X"03"; + + type I2cMasterInType is record + enable : sl; -- Enable the master + prescale : slv(15 downto 0); -- Determines i2c clock speed + filter : slv(15 downto 0); -- Dynamic filter value + txnReq : sl; -- Execute a transaction + stop : sl; -- Set STOP when done + op : sl; -- 1 for write, 0 for read + addr : slv(9 downto 0); -- i2c device address + tenbit : sl; -- use 10 bit addressing + wrValid : sl; + wrData : slv(7 downto 0); -- Data sent during write txn + rdAck : sl; + end record; + + type I2cMasterOutType is record + txnError : sl; -- An error occured during the txn + wrAck : sl; + rdValid : sl; + rdData : slv(7 downto 0); -- Data received during read txn + end record; + -------------------------------------------------------------------------------------------------- + type I2cRegMasterInType is record + i2cAddr : slv(9 downto 0); + tenbit : sl; + regAddr : slv(31 downto 0); + regWrData : slv(31 downto 0); + regOp : sl; + regAddrSize : slv(1 downto 0); + regDataSize : slv(1 downto 0); + regReq : sl; + endianness : sl; + end record; + + constant I2C_REG_MASTER_IN_INIT_C : I2cRegMasterInType := ( + i2cAddr => (others => '0'), + tenbit => '0', + regAddr => (others => '0'), + regWrData => (others => '0'), + regOp => '0', -- 1 for write, 0 for read + regAddrSize => (others => '0'), + regDataSize => (others => '0'), + regReq => '0', + endianness => '0'); + + type I2cRegMasterInArray is array (natural range <>) of I2cRegMasterInType; + + type I2cRegMasterOutType is record + regAck : sl; + regFail : sl; + regFailCode : slv(7 downto 0); + regRdData : slv(31 downto 0); + end record; + + constant I2C_REG_MASTER_OUT_INIT_C : I2cRegMasterOutType := ( + regAck => '0', + regFail => '0', + regFailCode => (others => '0'), + regRdData => (others => '0')); + + type I2cRegMasterOutArray is array (natural range <>) of I2cRegMasterOutType; + + -------------------------------------------------------------------------------------------------- + type I2cSlaveInType is record + enable : sl; + txValid : sl; + txData : slv(7 downto 0); + rxAck : sl; + end record I2cSlaveInType; + + constant I2C_SLAVE_IN_INIT_C : I2cSlaveInType := ( + enable => '0', + txValid => '0', + txData => (others => '0'), + rxAck => '0'); + + type I2cSlaveOutType is record + rxActive : sl; + rxValid : sl; + rxData : slv(7 downto 0); + txActive : sl; + txAck : sl; + nack : sl; + end record I2cSlaveOutType; + + constant I2C_SLAVE_OUT_INIT_C : I2cSlaveOutType := ( + rxActive => '0', + rxValid => '0', + rxData => (others => '0'), + txActive => '0', + txAck => '0', + nack => '0'); + + ------------------------------------------------------------------------------------------------- + -- AXI Bridge Generic Type, stick here for now + ------------------------------------------------------------------------------------------------- + type I2cAxiLiteDevType is record + i2cAddress : slv(9 downto 0); + i2cTenbit : sl; + dataSize : integer; + endianness : sl; + end record I2cAxiLiteDevType; + + type I2cAxiLiteDevArray is array (natural range <>) of I2cAxiLiteDevType; + + -------------------------------------------------------------------------------------------------- + -- Opencores i2c + component i2c_master_byte_ctrl is + generic (filter : integer; dynfilt : integer); + port ( + clk : in std_logic; + rst : in std_logic; -- active high reset + nReset : in std_logic; -- asynchornous active low reset + -- (not used in GRLIB) + ena : in std_logic; -- core enable signal + + clk_cnt : in std_logic_vector(15 downto 0); -- 4x SCL + + -- input signals + start, + stop, + read, + write, + ack_in : std_logic; + din : in std_logic_vector(7 downto 0); + filt : in std_logic_vector((filter-1)*dynfilt downto 0); + + -- output signals + cmd_ack : out std_logic; + ack_out : out std_logic; + i2c_busy : out std_logic; + i2c_al : out std_logic; + dout : out std_logic_vector(7 downto 0); + + -- i2c lines + scl_i : in std_logic; -- i2c clock line input + scl_o : out std_logic; -- i2c clock line output + scl_oen : out std_logic; -- i2c clock line output enable, active low + sda_i : in std_logic; -- i2c data line input + sda_o : out std_logic; -- i2c data line output + sda_oen : out std_logic -- i2c data line output enable, active low + ); + end component i2c_master_byte_ctrl; + + + +end; diff --git a/rce/fw-hsio/modules/pixelcore/hdl/I2cRegMaster.vhd b/rce/fw-hsio/modules/pixelcore/hdl/I2cRegMaster.vhd new file mode 100644 index 00000000..1cdfbb61 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/I2cRegMaster.vhd @@ -0,0 +1,261 @@ +------------------------------------------------------------------------------- +-- Title : +------------------------------------------------------------------------------- +-- File : I2cRegMaster.vhd +-- Author : Benjamin Reese <bareese@slac.stanford.edu> +-- Company : SLAC National Accelerator Laboratory +-- Created : 2013-01-22 +-- Last update: 2014-09-09 +-- Platform : +-- Standard : VHDL'93/02 +------------------------------------------------------------------------------- +-- Description: +-- PRESCALE_G = (clk_freq / (5 * i2c_freq)) - 1 +-- FILTER_G = (min_pulse_time / clk_period) + 1 +------------------------------------------------------------------------------- +-- Copyright (c) 2013 SLAC National Accelerator Laboratory +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.StdRtlPkg.all; +use work.I2cPkg.all; + +entity I2cRegMaster is + + generic ( + TPD_G : time := 1 ns; + OUTPUT_EN_POLARITY_G : integer range 0 to 1 := 0; + FILTER_G : integer range 2 to 512 := 8; + PRESCALE_G : integer range 0 to 655535 := 62); + port ( + clk : in sl; + srst : in sl := '0'; + arst : in sl := '0'; + regIn : in I2cRegMasterInType; + regOut : out I2cRegMasterOutType; + i2ci : in i2c_in_type; + i2co : out i2c_out_type); + +end entity I2cRegMaster; + +architecture rtl of I2cRegMaster is + + type StateType is (WAIT_REQ_S, ADDR_S, WRITE_S, READ_TXN_S, READ_S, REG_ACK_S); + + type RegType is record + state : StateType; + byteCount : unsigned(1 downto 0); + regOut : I2cRegMasterOutType; + i2cMasterIn : I2cMasterInType; + end record RegType; + + constant REG_INIT_C : RegType := ( + state => WAIT_REQ_S, + byteCount => (others => '0'), + regOut => ( + regAck => '0', + regFail => '0', + regFailCode => (others => '0'), + regRdData => (others => '0')), + i2cMasterIn => ( + enable => '0', + prescale => (others => '0'), + filter => (others => '0'), + txnReq => '0', + stop => '0', + op => '0', + addr => (others => '0'), + tenbit => '0', + wrValid => '0', + wrData => (others => '0'), + rdAck => '0')); + + signal r : RegType := REG_INIT_C; + signal rin : RegType; + signal i2cMasterIn : I2cMasterInType; + signal i2cMasterOut : I2cMasterOutType; + + function getIndex ( + endianness : sl; + byteCount : unsigned; + totalBytes : unsigned) + return integer is + begin + if (endianness = '0') then + -- little endian + return to_integer(byteCount)*8; + else + -- big endian + return (to_integer(totalBytes)-to_integer(byteCount))*8; + end if; + end function getIndex; + +begin + + i2cMaster_1 : entity work.I2cMaster + generic map ( + TPD_G => TPD_G, + OUTPUT_EN_POLARITY_G => OUTPUT_EN_POLARITY_G, + FILTER_G => FILTER_G, + DYNAMIC_FILTER_G => 0) + port map ( + clk => clk, + srst => srst, + arst => arst, + i2cMasterIn => i2cMasterIn, + i2cMasterOut => i2cMasterOut, + i2ci => i2ci, + i2co => i2co); + + comb : process (regIn, i2cMasterOut, r, srst) is + variable v : RegType; + variable addrIndexVar : integer; + variable dataIndexVar : integer; + begin + v := r; + + addrIndexVar := getIndex(regIn.endianness, r.byteCount, unsigned(regIn.regAddrSize)); + dataIndexVar := getIndex(regIn.endianness, r.byteCount, unsigned(regIn.regDataSize)); + + v.regOut.regAck := '0'; + v.regOut.regFail := '0'; + + v.i2cMasterIn.rdAck := '0'; + + case r.state is + when WAIT_REQ_S => + v.byteCount := (others => '0'); + if (regIn.regReq = '1') then + v.regOut.regRdData := (others => '0'); + v.i2cMasterIn.txnReq := '1'; + v.i2cMasterIn.op := '1'; -- Write address bytes + v.i2cMasterIn.stop := '1'; --regIn.regOp; -- no i2c stop after addr when reg read + v.state := ADDR_S; + end if; + + when ADDR_S => + -- When a new register access request is seen, + -- Write the register address out on the bus first + -- One byte at a time, order determined by endianness input + v.i2cMasterIn.wrData := regIn.regAddr(addrIndexVar+7 downto addrIndexVar); + v.i2cMasterIn.wrValid := '1'; + -- Must drop txnReq as last byte is sent if reading + v.i2cMasterIn.txnReq := not toSl(slv(r.byteCount) = regIn.regAddrSize and regIn.regOp = '0'); + + if (i2cMasterOut.wrAck = '1') then + v.byteCount := r.byteCount + 1; + v.i2cMasterIn.wrValid := '0'; + if (slv(r.byteCount) = regIn.regAddrSize) then + -- Done sending addr + v.byteCount := (others => '0'); + if (regIn.regOp = '1') then + v.state := WRITE_S; + else + v.state := READ_TXN_S; + end if; + end if; + end if; + + when WRITE_S => + -- Txn started in WAIT_REQ_S still active + -- Put wrData on the bus one byte at a time + v.i2cMasterIn.wrData := regIn.regWrData(dataIndexVar+7 downto dataIndexVar); + v.i2cMasterIn.wrValid := '1'; + v.i2cMasterIn.txnReq := not toSl(slv(r.byteCount) = regIn.regDataSize); + v.i2cMasterIn.stop := '1'; -- Send stop when done writing all bytes + if (i2cMasterOut.wrAck = '1') then + v.byteCount := r.byteCount + 1; + v.i2cMasterIn.wrValid := '0'; + if (slv(r.byteCount) = regIn.regDataSize) then -- could use rxnReq = 0 + v.state := REG_ACK_S; + end if; + end if; + + + when READ_TXN_S => + -- Start new txn to read data bytes + v.i2cMasterIn.txnReq := '1'; + v.i2cMasterIn.op := '0'; + v.i2cMasterIn.stop := '1'; -- i2c stop after all bytes are read + v.state := READ_S; + + when READ_S => + -- Drop txnReq on last byte + v.i2cMasterIn.txnReq := not toSl(slv(r.byteCount) = regIn.regDataSize); + -- Read data bytes as they arrive + if (i2cMasterOut.rdValid = '1' and r.i2cMasterIn.rdAck = '0') then + v.byteCount := r.byteCount + 1; + v.regOut.regRdData(dataIndexVar+7 downto dataIndexVar) := i2cMasterOut.rdData; + v.i2cMasterIn.rdAck := '1'; + if (slv(r.byteCount) = regIn.regDataSize) then + -- Done + v.state := REG_ACK_S; + end if; + end if; + + when REG_ACK_S => + -- Req done. Ack the req. + -- Might have failed so hold regFail (would be set to 0 otherwise). + v.regOut.regAck := '1'; + v.regOut.regFail := r.regOut.regFail; + if (regIn.regReq = '0') then +-- v.regOut.regAck := '0'; Might want this back. + v.state := WAIT_REQ_S; + end if; + + end case; + + -- Always check for errors an cancel the txn if they happen + if (i2cMasterOut.txnError = '1' and i2cMasterOut.rdValid = '1') then + v.regOut.regFail := '1'; + v.regOut.regFailCode := i2cMasterOut.rdData; + v.i2cMasterIn.txnReq := '0'; + v.i2cMasterIn.rdAck := '1'; + v.state := REG_ACK_S; + end if; + + ------------------------------------------------------------------------------------------------ + -- Synchronous Reset + ------------------------------------------------------------------------------------------------ + if (srst = '1') then + v := REG_INIT_C; + end if; + + ------------------------------------------------------------------------------------------------ + -- Signal Assignments + ------------------------------------------------------------------------------------------------ + -- Update registers + rin <= v; + + -- Internal signals + i2cMasterIn.enable <= '1'; + i2cMasterIn.prescale <= slv(to_unsigned(PRESCALE_G, 16)); + i2cMasterIn.filter <= (others => '0'); -- Not using dynamic filtering + i2cMasterIn.addr <= regIn.i2cAddr; + i2cMasterIn.tenbit <= regIn.tenbit; + i2cMasterIn.txnReq <= r.i2cMasterIn.txnReq; + i2cMasterIn.stop <= r.i2cMasterIn.stop; + i2cMasterIn.op <= r.i2cMasterIn.op; + i2cMasterIn.wrValid <= r.i2cMasterIn.wrValid; + i2cMasterIn.wrData <= r.i2cMasterIn.wrData; + i2cMasterIn.rdAck <= r.i2cMasterIn.rdAck; + + -- Outputs + regOut <= r.regOut; + + end process comb; + + seq : process (clk, arst) is + begin + if (arst = '1') then + r <= REG_INIT_C after TPD_G; + elsif (rising_edge(clk)) then + r <= rin after TPD_G; + end if; + end process seq; + + + +end architecture rtl; diff --git a/rce/fw-hsio/modules/pixelcore/hdl/OutputEncoder.vhd b/rce/fw-hsio/modules/pixelcore/hdl/OutputEncoder.vhd new file mode 100644 index 00000000..961f323f --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/OutputEncoder.vhd @@ -0,0 +1,56 @@ + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity outputencoder is + port ( + clock : in std_logic; + rst : in std_logic; + clockx2 : in std_logic; + datain : in std_logic; + encode : in std_logic_vector(1 downto 0); + dataout : out std_logic + ); +end outputencoder; + +architecture OUTPUTENCODER of outputencoder is + + signal bmp: std_logic; + signal man: std_logic; + +begin + + process(clockx2, rst) + begin + if(rst='1') then + bmp<='0'; + elsif(clockx2'event and clockx2='1') then + if(clock='1' or datain='1')then + bmp<=not bmp; + end if; + end if; + end process; + + process(clockx2, rst) + begin + if(rst='1') then + man<='0'; + elsif(clockx2'event and clockx2='1') then + if(clock='1')then + man<= datain; + else + man<=not datain; + end if; + end if; + end process; + + with encode select + dataout<= datain when "00", + bmp when "01", + man when "10", + datain when others; + +end OUTPUTENCODER; diff --git a/rce/fw-hsio/modules/pixelcore/hdl/StdRtlPkg.vhd b/rce/fw-hsio/modules/pixelcore/hdl/StdRtlPkg.vhd new file mode 100644 index 00000000..c26b8eb9 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/StdRtlPkg.vhd @@ -0,0 +1,1267 @@ +------------------------------------------------------------------------------- +-- Title : Standard RTL Package +------------------------------------------------------------------------------- +-- File : StdRtlPkg.vhd +-- Author : Benjamin Reese +-- Standard : VHDL'93/02, Math Packages +------------------------------------------------------------------------------- +-- Description: This package defines "sl" and "slv" shorthand subtypes for +-- std_logic and std_logic_vector receptively. It also defines +-- many handy utility functions. Nearly every .vhd file should +-- use this package. +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.NUMERIC_STD.all; +use ieee.math_real.all; + +package StdRtlPkg is + + -- Typing std_logic(_vector) is annoying + subtype sl is std_logic; + subtype slv is std_logic_vector; + + -- Declare arrays of built in types + --type SlvArray is array (natural range <>) of slv; -- not supported in VCS yet (14APRIL2014 -- LLR) + type IntegerArray is array (natural range <>) of integer; + type NaturalArray is array (natural range <>) of natural; + type PositiveArray is array (natural range <>) of positive; + type RealArray is array (natural range <>) of real; + type TimeArray is array (natural range <>) of time; + type BooleanArray is array (natural range <>) of boolean; + + -- Declare vector arrays of built in types + --type SlvVectorArray is array (natural range<>, natural range<>) of slv; -- not supported in VCS yet (14APRIL2014 -- LLR) + type IntegerVectorArray is array (natural range<>, natural range<>) of integer; + type NaturalVectorArray is array (natural range<>, natural range<>) of natural; + type PositiveVectorArray is array (natural range<>, natural range<>) of positive; + type RealVectorArray is array (natural range<>, natural range<>) of real; + type TimeVectorArray is array (natural range<>, natural range<>) of time; + type BooleanVectorArray is array (natural range<>, natural range<>) of boolean; + + -- Create an arbitrary sized slv with all bits set high or low + function slvAll (size : positive; value : sl) return slv; + function slvZero (size : positive) return slv; + function slvOne (size : positive) return slv; + + -- Very useful functions + function isPowerOf2 (number : natural) return boolean; + function isPowerOf2 (vector : slv) return boolean; + function log2 (constant number : positive) return natural; + function bitSize (constant number : natural) return positive; + function bitReverse (a : slv) return slv; + + -- Similar to python's range() function + function list (constant start, size, step : integer) return IntegerArray; + + -- Simple decoder and mux functions + function decode(v : slv) return slv; + function genmux(s, v : slv) return sl; + + -- This should be unnecessary in VHDL 2008 + function toBoolean (logic : sl) return boolean; + function toSl (bool : boolean) return sl; + function toString (bool : boolean) return string; + function toBoolean (str : string) return boolean; + + -- Unary reduction operators, also unnecessary in VHDL 2008 + function uOr (vec : slv) return sl; + function uAnd (vec : slv) return sl; + function uXor (vec : slv) return sl; + + -- Test if all bits in a vector are set to a given logic value + function allBits (vec : slv; test : sl) return boolean; + function noBits (vec : slv; test : sl) return boolean; + + -- These just use uXor to calculate parity + -- Output is parity bit value needed to achieve that parity given vec. + function evenParity (vec : slv) return sl; + function oddParity (vec : slv) return sl; + + -- Functions for counting the number of '1' in a slv bus + function onesCount (vec : slv) return unsigned; + function onesCount (vec : slv) return slv; + + -- Gray Code functions + function grayEncode (vec : unsigned) return unsigned; + function grayEncode (vec : slv) return slv; + function grayDecode (vec : unsigned) return unsigned; + function grayDecode (vec : slv) return slv; + + -- Linear Feedback Shift Register function + function lfsrShift (lfsr : slv; constant taps : NaturalArray; input : sl := '0') return slv; + + function maximum (left, right : integer) return integer; + function minimum (left, right : integer) return integer; + + -- One line if-then-else functions. Useful for assigning constants based on generics. + function ite(i : boolean; t : boolean; e : boolean) return boolean; + function ite(i : boolean; t : sl; e : sl) return sl; + function ite(i : boolean; t : slv; e : slv) return slv; + function ite(i : boolean; t : bit_vector; e : bit_vector) return bit_vector; + function ite(i : boolean; t : character; e : character) return character; + function ite(i : boolean; t : string; e : string) return string; + function ite(i : boolean; t : integer; e : integer) return integer; + function ite(i : boolean; t : real; e : real) return real; + function ite(i : boolean; t : time; e : time) return time; + + -- conv_std_logic_vector functions + function toSlv(ARG : integer; SIZE : integer) return slv; + + -- gets real multiplication + function getRealMult (A, B : real) return real; + function getRealMult (A : integer; B : real) return real; + function getRealMult (A : real; B : integer) return real; + + -- gets real division + function getRealDiv (A, B : real) return real; + function getRealDiv (A : integer; B : real) return real; + function getRealDiv (A : real; B : integer) return real; + + function adcConversion (ain : real; low : real; high : real; bits : positive; twosComp : boolean) return slv; + + --gets a time ratio + function getTimeRatio (T1, T2 : time) return natural; --not supported by Vivado + function getTimeRatio (T1, T2 : real) return natural; + + procedure assignSlv (i : inout integer; vector : inout slv; value : in slv); + procedure assignSlv (i : inout integer; vector : inout slv; value : in sl); + procedure assignRecord (i : inout integer; vector : in slv; value : inout slv); + procedure assignRecord (i : inout integer; vector : in slv; value : inout sl); + + -- Resize an SLV, either by trimming or padding upper bits + function resizeSlv ( vector : slv; newSize : integer) return slv; + + -- Some synthesis tools wont accept unit types + -- pragma translate_off + type frequency is range 0 to 2147483647 + units + Hz; + kHz = 1000 Hz; + MHz = 1000 kHz; + GHz = 1000 MHz; + end units; + + function toTime(f : frequency) return time; + -- pragma translate_on + + -- Add more slv array sizes here as they become needed + type Slv256Array is array (natural range <>) of slv(255 downto 0); + type Slv255Array is array (natural range <>) of slv(254 downto 0); + type Slv254Array is array (natural range <>) of slv(253 downto 0); + type Slv253Array is array (natural range <>) of slv(252 downto 0); + type Slv252Array is array (natural range <>) of slv(251 downto 0); + type Slv251Array is array (natural range <>) of slv(250 downto 0); + type Slv250Array is array (natural range <>) of slv(249 downto 0); + type Slv249Array is array (natural range <>) of slv(248 downto 0); + type Slv248Array is array (natural range <>) of slv(247 downto 0); + type Slv247Array is array (natural range <>) of slv(246 downto 0); + type Slv246Array is array (natural range <>) of slv(245 downto 0); + type Slv245Array is array (natural range <>) of slv(244 downto 0); + type Slv244Array is array (natural range <>) of slv(243 downto 0); + type Slv243Array is array (natural range <>) of slv(242 downto 0); + type Slv242Array is array (natural range <>) of slv(241 downto 0); + type Slv241Array is array (natural range <>) of slv(240 downto 0); + type Slv240Array is array (natural range <>) of slv(239 downto 0); + type Slv239Array is array (natural range <>) of slv(238 downto 0); + type Slv238Array is array (natural range <>) of slv(237 downto 0); + type Slv237Array is array (natural range <>) of slv(236 downto 0); + type Slv236Array is array (natural range <>) of slv(235 downto 0); + type Slv235Array is array (natural range <>) of slv(234 downto 0); + type Slv234Array is array (natural range <>) of slv(233 downto 0); + type Slv233Array is array (natural range <>) of slv(232 downto 0); + type Slv232Array is array (natural range <>) of slv(231 downto 0); + type Slv231Array is array (natural range <>) of slv(230 downto 0); + type Slv230Array is array (natural range <>) of slv(229 downto 0); + type Slv229Array is array (natural range <>) of slv(228 downto 0); + type Slv228Array is array (natural range <>) of slv(227 downto 0); + type Slv227Array is array (natural range <>) of slv(226 downto 0); + type Slv226Array is array (natural range <>) of slv(225 downto 0); + type Slv225Array is array (natural range <>) of slv(224 downto 0); + type Slv224Array is array (natural range <>) of slv(223 downto 0); + type Slv223Array is array (natural range <>) of slv(222 downto 0); + type Slv222Array is array (natural range <>) of slv(221 downto 0); + type Slv221Array is array (natural range <>) of slv(220 downto 0); + type Slv220Array is array (natural range <>) of slv(219 downto 0); + type Slv219Array is array (natural range <>) of slv(218 downto 0); + type Slv218Array is array (natural range <>) of slv(217 downto 0); + type Slv217Array is array (natural range <>) of slv(216 downto 0); + type Slv216Array is array (natural range <>) of slv(215 downto 0); + type Slv215Array is array (natural range <>) of slv(214 downto 0); + type Slv214Array is array (natural range <>) of slv(213 downto 0); + type Slv213Array is array (natural range <>) of slv(212 downto 0); + type Slv212Array is array (natural range <>) of slv(211 downto 0); + type Slv211Array is array (natural range <>) of slv(210 downto 0); + type Slv210Array is array (natural range <>) of slv(209 downto 0); + type Slv209Array is array (natural range <>) of slv(208 downto 0); + type Slv208Array is array (natural range <>) of slv(207 downto 0); + type Slv207Array is array (natural range <>) of slv(206 downto 0); + type Slv206Array is array (natural range <>) of slv(205 downto 0); + type Slv205Array is array (natural range <>) of slv(204 downto 0); + type Slv204Array is array (natural range <>) of slv(203 downto 0); + type Slv203Array is array (natural range <>) of slv(202 downto 0); + type Slv202Array is array (natural range <>) of slv(201 downto 0); + type Slv201Array is array (natural range <>) of slv(200 downto 0); + type Slv200Array is array (natural range <>) of slv(199 downto 0); + type Slv199Array is array (natural range <>) of slv(198 downto 0); + type Slv198Array is array (natural range <>) of slv(197 downto 0); + type Slv197Array is array (natural range <>) of slv(196 downto 0); + type Slv196Array is array (natural range <>) of slv(195 downto 0); + type Slv195Array is array (natural range <>) of slv(194 downto 0); + type Slv194Array is array (natural range <>) of slv(193 downto 0); + type Slv193Array is array (natural range <>) of slv(192 downto 0); + type Slv192Array is array (natural range <>) of slv(191 downto 0); + type Slv191Array is array (natural range <>) of slv(190 downto 0); + type Slv190Array is array (natural range <>) of slv(189 downto 0); + type Slv189Array is array (natural range <>) of slv(188 downto 0); + type Slv188Array is array (natural range <>) of slv(187 downto 0); + type Slv187Array is array (natural range <>) of slv(186 downto 0); + type Slv186Array is array (natural range <>) of slv(185 downto 0); + type Slv185Array is array (natural range <>) of slv(184 downto 0); + type Slv184Array is array (natural range <>) of slv(183 downto 0); + type Slv183Array is array (natural range <>) of slv(182 downto 0); + type Slv182Array is array (natural range <>) of slv(181 downto 0); + type Slv181Array is array (natural range <>) of slv(180 downto 0); + type Slv180Array is array (natural range <>) of slv(179 downto 0); + type Slv179Array is array (natural range <>) of slv(178 downto 0); + type Slv178Array is array (natural range <>) of slv(177 downto 0); + type Slv177Array is array (natural range <>) of slv(176 downto 0); + type Slv176Array is array (natural range <>) of slv(175 downto 0); + type Slv175Array is array (natural range <>) of slv(174 downto 0); + type Slv174Array is array (natural range <>) of slv(173 downto 0); + type Slv173Array is array (natural range <>) of slv(172 downto 0); + type Slv172Array is array (natural range <>) of slv(171 downto 0); + type Slv171Array is array (natural range <>) of slv(170 downto 0); + type Slv170Array is array (natural range <>) of slv(169 downto 0); + type Slv169Array is array (natural range <>) of slv(168 downto 0); + type Slv168Array is array (natural range <>) of slv(167 downto 0); + type Slv167Array is array (natural range <>) of slv(166 downto 0); + type Slv166Array is array (natural range <>) of slv(165 downto 0); + type Slv165Array is array (natural range <>) of slv(164 downto 0); + type Slv164Array is array (natural range <>) of slv(163 downto 0); + type Slv163Array is array (natural range <>) of slv(162 downto 0); + type Slv162Array is array (natural range <>) of slv(161 downto 0); + type Slv161Array is array (natural range <>) of slv(160 downto 0); + type Slv160Array is array (natural range <>) of slv(159 downto 0); + type Slv159Array is array (natural range <>) of slv(158 downto 0); + type Slv158Array is array (natural range <>) of slv(157 downto 0); + type Slv157Array is array (natural range <>) of slv(156 downto 0); + type Slv156Array is array (natural range <>) of slv(155 downto 0); + type Slv155Array is array (natural range <>) of slv(154 downto 0); + type Slv154Array is array (natural range <>) of slv(153 downto 0); + type Slv153Array is array (natural range <>) of slv(152 downto 0); + type Slv152Array is array (natural range <>) of slv(151 downto 0); + type Slv151Array is array (natural range <>) of slv(150 downto 0); + type Slv150Array is array (natural range <>) of slv(149 downto 0); + type Slv149Array is array (natural range <>) of slv(148 downto 0); + type Slv148Array is array (natural range <>) of slv(147 downto 0); + type Slv147Array is array (natural range <>) of slv(146 downto 0); + type Slv146Array is array (natural range <>) of slv(145 downto 0); + type Slv145Array is array (natural range <>) of slv(144 downto 0); + type Slv144Array is array (natural range <>) of slv(143 downto 0); + type Slv143Array is array (natural range <>) of slv(142 downto 0); + type Slv142Array is array (natural range <>) of slv(141 downto 0); + type Slv141Array is array (natural range <>) of slv(140 downto 0); + type Slv140Array is array (natural range <>) of slv(139 downto 0); + type Slv139Array is array (natural range <>) of slv(138 downto 0); + type Slv138Array is array (natural range <>) of slv(137 downto 0); + type Slv137Array is array (natural range <>) of slv(136 downto 0); + type Slv136Array is array (natural range <>) of slv(135 downto 0); + type Slv135Array is array (natural range <>) of slv(134 downto 0); + type Slv134Array is array (natural range <>) of slv(133 downto 0); + type Slv133Array is array (natural range <>) of slv(132 downto 0); + type Slv132Array is array (natural range <>) of slv(131 downto 0); + type Slv131Array is array (natural range <>) of slv(130 downto 0); + type Slv130Array is array (natural range <>) of slv(129 downto 0); + type Slv129Array is array (natural range <>) of slv(128 downto 0); + type Slv128Array is array (natural range <>) of slv(127 downto 0); + type Slv127Array is array (natural range <>) of slv(126 downto 0); + type Slv126Array is array (natural range <>) of slv(125 downto 0); + type Slv125Array is array (natural range <>) of slv(124 downto 0); + type Slv124Array is array (natural range <>) of slv(123 downto 0); + type Slv123Array is array (natural range <>) of slv(122 downto 0); + type Slv122Array is array (natural range <>) of slv(121 downto 0); + type Slv121Array is array (natural range <>) of slv(120 downto 0); + type Slv120Array is array (natural range <>) of slv(119 downto 0); + type Slv119Array is array (natural range <>) of slv(118 downto 0); + type Slv118Array is array (natural range <>) of slv(117 downto 0); + type Slv117Array is array (natural range <>) of slv(116 downto 0); + type Slv116Array is array (natural range <>) of slv(115 downto 0); + type Slv115Array is array (natural range <>) of slv(114 downto 0); + type Slv114Array is array (natural range <>) of slv(113 downto 0); + type Slv113Array is array (natural range <>) of slv(112 downto 0); + type Slv112Array is array (natural range <>) of slv(111 downto 0); + type Slv111Array is array (natural range <>) of slv(110 downto 0); + type Slv110Array is array (natural range <>) of slv(109 downto 0); + type Slv109Array is array (natural range <>) of slv(108 downto 0); + type Slv108Array is array (natural range <>) of slv(107 downto 0); + type Slv107Array is array (natural range <>) of slv(106 downto 0); + type Slv106Array is array (natural range <>) of slv(105 downto 0); + type Slv105Array is array (natural range <>) of slv(104 downto 0); + type Slv104Array is array (natural range <>) of slv(103 downto 0); + type Slv103Array is array (natural range <>) of slv(102 downto 0); + type Slv102Array is array (natural range <>) of slv(101 downto 0); + type Slv101Array is array (natural range <>) of slv(100 downto 0); + type Slv100Array is array (natural range <>) of slv(99 downto 0); + type Slv99Array is array (natural range <>) of slv(98 downto 0); + type Slv98Array is array (natural range <>) of slv(97 downto 0); + type Slv97Array is array (natural range <>) of slv(96 downto 0); + type Slv96Array is array (natural range <>) of slv(95 downto 0); + type Slv95Array is array (natural range <>) of slv(94 downto 0); + type Slv94Array is array (natural range <>) of slv(93 downto 0); + type Slv93Array is array (natural range <>) of slv(92 downto 0); + type Slv92Array is array (natural range <>) of slv(91 downto 0); + type Slv91Array is array (natural range <>) of slv(90 downto 0); + type Slv90Array is array (natural range <>) of slv(89 downto 0); + type Slv89Array is array (natural range <>) of slv(88 downto 0); + type Slv88Array is array (natural range <>) of slv(87 downto 0); + type Slv87Array is array (natural range <>) of slv(86 downto 0); + type Slv86Array is array (natural range <>) of slv(85 downto 0); + type Slv85Array is array (natural range <>) of slv(84 downto 0); + type Slv84Array is array (natural range <>) of slv(83 downto 0); + type Slv83Array is array (natural range <>) of slv(82 downto 0); + type Slv82Array is array (natural range <>) of slv(81 downto 0); + type Slv81Array is array (natural range <>) of slv(80 downto 0); + type Slv80Array is array (natural range <>) of slv(79 downto 0); + type Slv79Array is array (natural range <>) of slv(78 downto 0); + type Slv78Array is array (natural range <>) of slv(77 downto 0); + type Slv77Array is array (natural range <>) of slv(76 downto 0); + type Slv76Array is array (natural range <>) of slv(75 downto 0); + type Slv75Array is array (natural range <>) of slv(74 downto 0); + type Slv74Array is array (natural range <>) of slv(73 downto 0); + type Slv73Array is array (natural range <>) of slv(72 downto 0); + type Slv72Array is array (natural range <>) of slv(71 downto 0); + type Slv71Array is array (natural range <>) of slv(70 downto 0); + type Slv70Array is array (natural range <>) of slv(69 downto 0); + type Slv69Array is array (natural range <>) of slv(68 downto 0); + type Slv68Array is array (natural range <>) of slv(67 downto 0); + type Slv67Array is array (natural range <>) of slv(66 downto 0); + type Slv66Array is array (natural range <>) of slv(65 downto 0); + type Slv65Array is array (natural range <>) of slv(64 downto 0); + type Slv64Array is array (natural range <>) of slv(63 downto 0); + type Slv63Array is array (natural range <>) of slv(62 downto 0); + type Slv62Array is array (natural range <>) of slv(61 downto 0); + type Slv61Array is array (natural range <>) of slv(60 downto 0); + type Slv60Array is array (natural range <>) of slv(59 downto 0); + type Slv59Array is array (natural range <>) of slv(58 downto 0); + type Slv58Array is array (natural range <>) of slv(57 downto 0); + type Slv57Array is array (natural range <>) of slv(56 downto 0); + type Slv56Array is array (natural range <>) of slv(55 downto 0); + type Slv55Array is array (natural range <>) of slv(54 downto 0); + type Slv54Array is array (natural range <>) of slv(53 downto 0); + type Slv53Array is array (natural range <>) of slv(52 downto 0); + type Slv52Array is array (natural range <>) of slv(51 downto 0); + type Slv51Array is array (natural range <>) of slv(50 downto 0); + type Slv50Array is array (natural range <>) of slv(49 downto 0); + type Slv49Array is array (natural range <>) of slv(48 downto 0); + type Slv48Array is array (natural range <>) of slv(47 downto 0); + type Slv47Array is array (natural range <>) of slv(46 downto 0); + type Slv46Array is array (natural range <>) of slv(45 downto 0); + type Slv45Array is array (natural range <>) of slv(44 downto 0); + type Slv44Array is array (natural range <>) of slv(43 downto 0); + type Slv43Array is array (natural range <>) of slv(42 downto 0); + type Slv42Array is array (natural range <>) of slv(41 downto 0); + type Slv41Array is array (natural range <>) of slv(40 downto 0); + type Slv40Array is array (natural range <>) of slv(39 downto 0); + type Slv39Array is array (natural range <>) of slv(38 downto 0); + type Slv38Array is array (natural range <>) of slv(37 downto 0); + type Slv37Array is array (natural range <>) of slv(36 downto 0); + type Slv36Array is array (natural range <>) of slv(35 downto 0); + type Slv35Array is array (natural range <>) of slv(34 downto 0); + type Slv34Array is array (natural range <>) of slv(33 downto 0); + type Slv33Array is array (natural range <>) of slv(32 downto 0); + type Slv32Array is array (natural range <>) of slv(31 downto 0); + type Slv31Array is array (natural range <>) of slv(30 downto 0); + type Slv30Array is array (natural range <>) of slv(29 downto 0); + type Slv29Array is array (natural range <>) of slv(28 downto 0); + type Slv28Array is array (natural range <>) of slv(27 downto 0); + type Slv27Array is array (natural range <>) of slv(26 downto 0); + type Slv26Array is array (natural range <>) of slv(25 downto 0); + type Slv25Array is array (natural range <>) of slv(24 downto 0); + type Slv24Array is array (natural range <>) of slv(23 downto 0); + type Slv23Array is array (natural range <>) of slv(22 downto 0); + type Slv22Array is array (natural range <>) of slv(21 downto 0); + type Slv21Array is array (natural range <>) of slv(20 downto 0); + type Slv20Array is array (natural range <>) of slv(19 downto 0); + type Slv19Array is array (natural range <>) of slv(18 downto 0); + type Slv18Array is array (natural range <>) of slv(17 downto 0); + type Slv17Array is array (natural range <>) of slv(16 downto 0); + type Slv16Array is array (natural range <>) of slv(15 downto 0); + type Slv15Array is array (natural range <>) of slv(14 downto 0); + type Slv14Array is array (natural range <>) of slv(13 downto 0); + type Slv13Array is array (natural range <>) of slv(12 downto 0); + type Slv12Array is array (natural range <>) of slv(11 downto 0); + type Slv11Array is array (natural range <>) of slv(10 downto 0); + type Slv10Array is array (natural range <>) of slv(9 downto 0); + type Slv9Array is array (natural range <>) of slv(8 downto 0); + type Slv8Array is array (natural range <>) of slv(7 downto 0); + type Slv7Array is array (natural range <>) of slv(6 downto 0); + type Slv6Array is array (natural range <>) of slv(5 downto 0); + type Slv5Array is array (natural range <>) of slv(4 downto 0); + type Slv4Array is array (natural range <>) of slv(3 downto 0); + type Slv3Array is array (natural range <>) of slv(2 downto 0); + type Slv2Array is array (natural range <>) of slv(1 downto 0); + type Slv1Array is array (natural range <>) of slv(0 downto 0); + + -- Add more slv vector array sizes here as they become needed + type Slv256VectorArray is array (natural range<>, natural range<>) of slv(255 downto 0); + type Slv255VectorArray is array (natural range<>, natural range<>) of slv(254 downto 0); + type Slv254VectorArray is array (natural range<>, natural range<>) of slv(253 downto 0); + type Slv253VectorArray is array (natural range<>, natural range<>) of slv(252 downto 0); + type Slv252VectorArray is array (natural range<>, natural range<>) of slv(251 downto 0); + type Slv251VectorArray is array (natural range<>, natural range<>) of slv(250 downto 0); + type Slv250VectorArray is array (natural range<>, natural range<>) of slv(249 downto 0); + type Slv249VectorArray is array (natural range<>, natural range<>) of slv(248 downto 0); + type Slv248VectorArray is array (natural range<>, natural range<>) of slv(247 downto 0); + type Slv247VectorArray is array (natural range<>, natural range<>) of slv(246 downto 0); + type Slv246VectorArray is array (natural range<>, natural range<>) of slv(245 downto 0); + type Slv245VectorArray is array (natural range<>, natural range<>) of slv(244 downto 0); + type Slv244VectorArray is array (natural range<>, natural range<>) of slv(243 downto 0); + type Slv243VectorArray is array (natural range<>, natural range<>) of slv(242 downto 0); + type Slv242VectorArray is array (natural range<>, natural range<>) of slv(241 downto 0); + type Slv241VectorArray is array (natural range<>, natural range<>) of slv(240 downto 0); + type Slv240VectorArray is array (natural range<>, natural range<>) of slv(239 downto 0); + type Slv239VectorArray is array (natural range<>, natural range<>) of slv(238 downto 0); + type Slv238VectorArray is array (natural range<>, natural range<>) of slv(237 downto 0); + type Slv237VectorArray is array (natural range<>, natural range<>) of slv(236 downto 0); + type Slv236VectorArray is array (natural range<>, natural range<>) of slv(235 downto 0); + type Slv235VectorArray is array (natural range<>, natural range<>) of slv(234 downto 0); + type Slv234VectorArray is array (natural range<>, natural range<>) of slv(233 downto 0); + type Slv233VectorArray is array (natural range<>, natural range<>) of slv(232 downto 0); + type Slv232VectorArray is array (natural range<>, natural range<>) of slv(231 downto 0); + type Slv231VectorArray is array (natural range<>, natural range<>) of slv(230 downto 0); + type Slv230VectorArray is array (natural range<>, natural range<>) of slv(229 downto 0); + type Slv229VectorArray is array (natural range<>, natural range<>) of slv(228 downto 0); + type Slv228VectorArray is array (natural range<>, natural range<>) of slv(227 downto 0); + type Slv227VectorArray is array (natural range<>, natural range<>) of slv(226 downto 0); + type Slv226VectorArray is array (natural range<>, natural range<>) of slv(225 downto 0); + type Slv225VectorArray is array (natural range<>, natural range<>) of slv(224 downto 0); + type Slv224VectorArray is array (natural range<>, natural range<>) of slv(223 downto 0); + type Slv223VectorArray is array (natural range<>, natural range<>) of slv(222 downto 0); + type Slv222VectorArray is array (natural range<>, natural range<>) of slv(221 downto 0); + type Slv221VectorArray is array (natural range<>, natural range<>) of slv(220 downto 0); + type Slv220VectorArray is array (natural range<>, natural range<>) of slv(219 downto 0); + type Slv219VectorArray is array (natural range<>, natural range<>) of slv(218 downto 0); + type Slv218VectorArray is array (natural range<>, natural range<>) of slv(217 downto 0); + type Slv217VectorArray is array (natural range<>, natural range<>) of slv(216 downto 0); + type Slv216VectorArray is array (natural range<>, natural range<>) of slv(215 downto 0); + type Slv215VectorArray is array (natural range<>, natural range<>) of slv(214 downto 0); + type Slv214VectorArray is array (natural range<>, natural range<>) of slv(213 downto 0); + type Slv213VectorArray is array (natural range<>, natural range<>) of slv(212 downto 0); + type Slv212VectorArray is array (natural range<>, natural range<>) of slv(211 downto 0); + type Slv211VectorArray is array (natural range<>, natural range<>) of slv(210 downto 0); + type Slv210VectorArray is array (natural range<>, natural range<>) of slv(209 downto 0); + type Slv209VectorArray is array (natural range<>, natural range<>) of slv(208 downto 0); + type Slv208VectorArray is array (natural range<>, natural range<>) of slv(207 downto 0); + type Slv207VectorArray is array (natural range<>, natural range<>) of slv(206 downto 0); + type Slv206VectorArray is array (natural range<>, natural range<>) of slv(205 downto 0); + type Slv205VectorArray is array (natural range<>, natural range<>) of slv(204 downto 0); + type Slv204VectorArray is array (natural range<>, natural range<>) of slv(203 downto 0); + type Slv203VectorArray is array (natural range<>, natural range<>) of slv(202 downto 0); + type Slv202VectorArray is array (natural range<>, natural range<>) of slv(201 downto 0); + type Slv201VectorArray is array (natural range<>, natural range<>) of slv(200 downto 0); + type Slv200VectorArray is array (natural range<>, natural range<>) of slv(199 downto 0); + type Slv199VectorArray is array (natural range<>, natural range<>) of slv(198 downto 0); + type Slv198VectorArray is array (natural range<>, natural range<>) of slv(197 downto 0); + type Slv197VectorArray is array (natural range<>, natural range<>) of slv(196 downto 0); + type Slv196VectorArray is array (natural range<>, natural range<>) of slv(195 downto 0); + type Slv195VectorArray is array (natural range<>, natural range<>) of slv(194 downto 0); + type Slv194VectorArray is array (natural range<>, natural range<>) of slv(193 downto 0); + type Slv193VectorArray is array (natural range<>, natural range<>) of slv(192 downto 0); + type Slv192VectorArray is array (natural range<>, natural range<>) of slv(191 downto 0); + type Slv191VectorArray is array (natural range<>, natural range<>) of slv(190 downto 0); + type Slv190VectorArray is array (natural range<>, natural range<>) of slv(189 downto 0); + type Slv189VectorArray is array (natural range<>, natural range<>) of slv(188 downto 0); + type Slv188VectorArray is array (natural range<>, natural range<>) of slv(187 downto 0); + type Slv187VectorArray is array (natural range<>, natural range<>) of slv(186 downto 0); + type Slv186VectorArray is array (natural range<>, natural range<>) of slv(185 downto 0); + type Slv185VectorArray is array (natural range<>, natural range<>) of slv(184 downto 0); + type Slv184VectorArray is array (natural range<>, natural range<>) of slv(183 downto 0); + type Slv183VectorArray is array (natural range<>, natural range<>) of slv(182 downto 0); + type Slv182VectorArray is array (natural range<>, natural range<>) of slv(181 downto 0); + type Slv181VectorArray is array (natural range<>, natural range<>) of slv(180 downto 0); + type Slv180VectorArray is array (natural range<>, natural range<>) of slv(179 downto 0); + type Slv179VectorArray is array (natural range<>, natural range<>) of slv(178 downto 0); + type Slv178VectorArray is array (natural range<>, natural range<>) of slv(177 downto 0); + type Slv177VectorArray is array (natural range<>, natural range<>) of slv(176 downto 0); + type Slv176VectorArray is array (natural range<>, natural range<>) of slv(175 downto 0); + type Slv175VectorArray is array (natural range<>, natural range<>) of slv(174 downto 0); + type Slv174VectorArray is array (natural range<>, natural range<>) of slv(173 downto 0); + type Slv173VectorArray is array (natural range<>, natural range<>) of slv(172 downto 0); + type Slv172VectorArray is array (natural range<>, natural range<>) of slv(171 downto 0); + type Slv171VectorArray is array (natural range<>, natural range<>) of slv(170 downto 0); + type Slv170VectorArray is array (natural range<>, natural range<>) of slv(169 downto 0); + type Slv169VectorArray is array (natural range<>, natural range<>) of slv(168 downto 0); + type Slv168VectorArray is array (natural range<>, natural range<>) of slv(167 downto 0); + type Slv167VectorArray is array (natural range<>, natural range<>) of slv(166 downto 0); + type Slv166VectorArray is array (natural range<>, natural range<>) of slv(165 downto 0); + type Slv165VectorArray is array (natural range<>, natural range<>) of slv(164 downto 0); + type Slv164VectorArray is array (natural range<>, natural range<>) of slv(163 downto 0); + type Slv163VectorArray is array (natural range<>, natural range<>) of slv(162 downto 0); + type Slv162VectorArray is array (natural range<>, natural range<>) of slv(161 downto 0); + type Slv161VectorArray is array (natural range<>, natural range<>) of slv(160 downto 0); + type Slv160VectorArray is array (natural range<>, natural range<>) of slv(159 downto 0); + type Slv159VectorArray is array (natural range<>, natural range<>) of slv(158 downto 0); + type Slv158VectorArray is array (natural range<>, natural range<>) of slv(157 downto 0); + type Slv157VectorArray is array (natural range<>, natural range<>) of slv(156 downto 0); + type Slv156VectorArray is array (natural range<>, natural range<>) of slv(155 downto 0); + type Slv155VectorArray is array (natural range<>, natural range<>) of slv(154 downto 0); + type Slv154VectorArray is array (natural range<>, natural range<>) of slv(153 downto 0); + type Slv153VectorArray is array (natural range<>, natural range<>) of slv(152 downto 0); + type Slv152VectorArray is array (natural range<>, natural range<>) of slv(151 downto 0); + type Slv151VectorArray is array (natural range<>, natural range<>) of slv(150 downto 0); + type Slv150VectorArray is array (natural range<>, natural range<>) of slv(149 downto 0); + type Slv149VectorArray is array (natural range<>, natural range<>) of slv(148 downto 0); + type Slv148VectorArray is array (natural range<>, natural range<>) of slv(147 downto 0); + type Slv147VectorArray is array (natural range<>, natural range<>) of slv(146 downto 0); + type Slv146VectorArray is array (natural range<>, natural range<>) of slv(145 downto 0); + type Slv145VectorArray is array (natural range<>, natural range<>) of slv(144 downto 0); + type Slv144VectorArray is array (natural range<>, natural range<>) of slv(143 downto 0); + type Slv143VectorArray is array (natural range<>, natural range<>) of slv(142 downto 0); + type Slv142VectorArray is array (natural range<>, natural range<>) of slv(141 downto 0); + type Slv141VectorArray is array (natural range<>, natural range<>) of slv(140 downto 0); + type Slv140VectorArray is array (natural range<>, natural range<>) of slv(139 downto 0); + type Slv139VectorArray is array (natural range<>, natural range<>) of slv(138 downto 0); + type Slv138VectorArray is array (natural range<>, natural range<>) of slv(137 downto 0); + type Slv137VectorArray is array (natural range<>, natural range<>) of slv(136 downto 0); + type Slv136VectorArray is array (natural range<>, natural range<>) of slv(135 downto 0); + type Slv135VectorArray is array (natural range<>, natural range<>) of slv(134 downto 0); + type Slv134VectorArray is array (natural range<>, natural range<>) of slv(133 downto 0); + type Slv133VectorArray is array (natural range<>, natural range<>) of slv(132 downto 0); + type Slv132VectorArray is array (natural range<>, natural range<>) of slv(131 downto 0); + type Slv131VectorArray is array (natural range<>, natural range<>) of slv(130 downto 0); + type Slv130VectorArray is array (natural range<>, natural range<>) of slv(129 downto 0); + type Slv129VectorArray is array (natural range<>, natural range<>) of slv(128 downto 0); + type Slv128VectorArray is array (natural range<>, natural range<>) of slv(127 downto 0); + type Slv127VectorArray is array (natural range<>, natural range<>) of slv(126 downto 0); + type Slv126VectorArray is array (natural range<>, natural range<>) of slv(125 downto 0); + type Slv125VectorArray is array (natural range<>, natural range<>) of slv(124 downto 0); + type Slv124VectorArray is array (natural range<>, natural range<>) of slv(123 downto 0); + type Slv123VectorArray is array (natural range<>, natural range<>) of slv(122 downto 0); + type Slv122VectorArray is array (natural range<>, natural range<>) of slv(121 downto 0); + type Slv121VectorArray is array (natural range<>, natural range<>) of slv(120 downto 0); + type Slv120VectorArray is array (natural range<>, natural range<>) of slv(119 downto 0); + type Slv119VectorArray is array (natural range<>, natural range<>) of slv(118 downto 0); + type Slv118VectorArray is array (natural range<>, natural range<>) of slv(117 downto 0); + type Slv117VectorArray is array (natural range<>, natural range<>) of slv(116 downto 0); + type Slv116VectorArray is array (natural range<>, natural range<>) of slv(115 downto 0); + type Slv115VectorArray is array (natural range<>, natural range<>) of slv(114 downto 0); + type Slv114VectorArray is array (natural range<>, natural range<>) of slv(113 downto 0); + type Slv113VectorArray is array (natural range<>, natural range<>) of slv(112 downto 0); + type Slv112VectorArray is array (natural range<>, natural range<>) of slv(111 downto 0); + type Slv111VectorArray is array (natural range<>, natural range<>) of slv(110 downto 0); + type Slv110VectorArray is array (natural range<>, natural range<>) of slv(109 downto 0); + type Slv109VectorArray is array (natural range<>, natural range<>) of slv(108 downto 0); + type Slv108VectorArray is array (natural range<>, natural range<>) of slv(107 downto 0); + type Slv107VectorArray is array (natural range<>, natural range<>) of slv(106 downto 0); + type Slv106VectorArray is array (natural range<>, natural range<>) of slv(105 downto 0); + type Slv105VectorArray is array (natural range<>, natural range<>) of slv(104 downto 0); + type Slv104VectorArray is array (natural range<>, natural range<>) of slv(103 downto 0); + type Slv103VectorArray is array (natural range<>, natural range<>) of slv(102 downto 0); + type Slv102VectorArray is array (natural range<>, natural range<>) of slv(101 downto 0); + type Slv101VectorArray is array (natural range<>, natural range<>) of slv(100 downto 0); + type Slv100VectorArray is array (natural range<>, natural range<>) of slv(99 downto 0); + type Slv99VectorArray is array (natural range<>, natural range<>) of slv(98 downto 0); + type Slv98VectorArray is array (natural range<>, natural range<>) of slv(97 downto 0); + type Slv97VectorArray is array (natural range<>, natural range<>) of slv(96 downto 0); + type Slv96VectorArray is array (natural range<>, natural range<>) of slv(95 downto 0); + type Slv95VectorArray is array (natural range<>, natural range<>) of slv(94 downto 0); + type Slv94VectorArray is array (natural range<>, natural range<>) of slv(93 downto 0); + type Slv93VectorArray is array (natural range<>, natural range<>) of slv(92 downto 0); + type Slv92VectorArray is array (natural range<>, natural range<>) of slv(91 downto 0); + type Slv91VectorArray is array (natural range<>, natural range<>) of slv(90 downto 0); + type Slv90VectorArray is array (natural range<>, natural range<>) of slv(89 downto 0); + type Slv89VectorArray is array (natural range<>, natural range<>) of slv(88 downto 0); + type Slv88VectorArray is array (natural range<>, natural range<>) of slv(87 downto 0); + type Slv87VectorArray is array (natural range<>, natural range<>) of slv(86 downto 0); + type Slv86VectorArray is array (natural range<>, natural range<>) of slv(85 downto 0); + type Slv85VectorArray is array (natural range<>, natural range<>) of slv(84 downto 0); + type Slv84VectorArray is array (natural range<>, natural range<>) of slv(83 downto 0); + type Slv83VectorArray is array (natural range<>, natural range<>) of slv(82 downto 0); + type Slv82VectorArray is array (natural range<>, natural range<>) of slv(81 downto 0); + type Slv81VectorArray is array (natural range<>, natural range<>) of slv(80 downto 0); + type Slv80VectorArray is array (natural range<>, natural range<>) of slv(79 downto 0); + type Slv79VectorArray is array (natural range<>, natural range<>) of slv(78 downto 0); + type Slv78VectorArray is array (natural range<>, natural range<>) of slv(77 downto 0); + type Slv77VectorArray is array (natural range<>, natural range<>) of slv(76 downto 0); + type Slv76VectorArray is array (natural range<>, natural range<>) of slv(75 downto 0); + type Slv75VectorArray is array (natural range<>, natural range<>) of slv(74 downto 0); + type Slv74VectorArray is array (natural range<>, natural range<>) of slv(73 downto 0); + type Slv73VectorArray is array (natural range<>, natural range<>) of slv(72 downto 0); + type Slv72VectorArray is array (natural range<>, natural range<>) of slv(71 downto 0); + type Slv71VectorArray is array (natural range<>, natural range<>) of slv(70 downto 0); + type Slv70VectorArray is array (natural range<>, natural range<>) of slv(69 downto 0); + type Slv69VectorArray is array (natural range<>, natural range<>) of slv(68 downto 0); + type Slv68VectorArray is array (natural range<>, natural range<>) of slv(67 downto 0); + type Slv67VectorArray is array (natural range<>, natural range<>) of slv(66 downto 0); + type Slv66VectorArray is array (natural range<>, natural range<>) of slv(65 downto 0); + type Slv65VectorArray is array (natural range<>, natural range<>) of slv(64 downto 0); + type Slv64VectorArray is array (natural range<>, natural range<>) of slv(63 downto 0); + type Slv63VectorArray is array (natural range<>, natural range<>) of slv(62 downto 0); + type Slv62VectorArray is array (natural range<>, natural range<>) of slv(61 downto 0); + type Slv61VectorArray is array (natural range<>, natural range<>) of slv(60 downto 0); + type Slv60VectorArray is array (natural range<>, natural range<>) of slv(59 downto 0); + type Slv59VectorArray is array (natural range<>, natural range<>) of slv(58 downto 0); + type Slv58VectorArray is array (natural range<>, natural range<>) of slv(57 downto 0); + type Slv57VectorArray is array (natural range<>, natural range<>) of slv(56 downto 0); + type Slv56VectorArray is array (natural range<>, natural range<>) of slv(55 downto 0); + type Slv55VectorArray is array (natural range<>, natural range<>) of slv(54 downto 0); + type Slv54VectorArray is array (natural range<>, natural range<>) of slv(53 downto 0); + type Slv53VectorArray is array (natural range<>, natural range<>) of slv(52 downto 0); + type Slv52VectorArray is array (natural range<>, natural range<>) of slv(51 downto 0); + type Slv51VectorArray is array (natural range<>, natural range<>) of slv(50 downto 0); + type Slv50VectorArray is array (natural range<>, natural range<>) of slv(49 downto 0); + type Slv49VectorArray is array (natural range<>, natural range<>) of slv(48 downto 0); + type Slv48VectorArray is array (natural range<>, natural range<>) of slv(47 downto 0); + type Slv47VectorArray is array (natural range<>, natural range<>) of slv(46 downto 0); + type Slv46VectorArray is array (natural range<>, natural range<>) of slv(45 downto 0); + type Slv45VectorArray is array (natural range<>, natural range<>) of slv(44 downto 0); + type Slv44VectorArray is array (natural range<>, natural range<>) of slv(43 downto 0); + type Slv43VectorArray is array (natural range<>, natural range<>) of slv(42 downto 0); + type Slv42VectorArray is array (natural range<>, natural range<>) of slv(41 downto 0); + type Slv41VectorArray is array (natural range<>, natural range<>) of slv(40 downto 0); + type Slv40VectorArray is array (natural range<>, natural range<>) of slv(39 downto 0); + type Slv39VectorArray is array (natural range<>, natural range<>) of slv(38 downto 0); + type Slv38VectorArray is array (natural range<>, natural range<>) of slv(37 downto 0); + type Slv37VectorArray is array (natural range<>, natural range<>) of slv(36 downto 0); + type Slv36VectorArray is array (natural range<>, natural range<>) of slv(35 downto 0); + type Slv35VectorArray is array (natural range<>, natural range<>) of slv(34 downto 0); + type Slv34VectorArray is array (natural range<>, natural range<>) of slv(33 downto 0); + type Slv33VectorArray is array (natural range<>, natural range<>) of slv(32 downto 0); + type Slv32VectorArray is array (natural range<>, natural range<>) of slv(31 downto 0); + type Slv31VectorArray is array (natural range<>, natural range<>) of slv(30 downto 0); + type Slv30VectorArray is array (natural range<>, natural range<>) of slv(29 downto 0); + type Slv29VectorArray is array (natural range<>, natural range<>) of slv(28 downto 0); + type Slv28VectorArray is array (natural range<>, natural range<>) of slv(27 downto 0); + type Slv27VectorArray is array (natural range<>, natural range<>) of slv(26 downto 0); + type Slv26VectorArray is array (natural range<>, natural range<>) of slv(25 downto 0); + type Slv25VectorArray is array (natural range<>, natural range<>) of slv(24 downto 0); + type Slv24VectorArray is array (natural range<>, natural range<>) of slv(23 downto 0); + type Slv23VectorArray is array (natural range<>, natural range<>) of slv(22 downto 0); + type Slv22VectorArray is array (natural range<>, natural range<>) of slv(21 downto 0); + type Slv21VectorArray is array (natural range<>, natural range<>) of slv(20 downto 0); + type Slv20VectorArray is array (natural range<>, natural range<>) of slv(19 downto 0); + type Slv19VectorArray is array (natural range<>, natural range<>) of slv(18 downto 0); + type Slv18VectorArray is array (natural range<>, natural range<>) of slv(17 downto 0); + type Slv17VectorArray is array (natural range<>, natural range<>) of slv(16 downto 0); + type Slv16VectorArray is array (natural range<>, natural range<>) of slv(15 downto 0); + type Slv15VectorArray is array (natural range<>, natural range<>) of slv(14 downto 0); + type Slv14VectorArray is array (natural range<>, natural range<>) of slv(13 downto 0); + type Slv13VectorArray is array (natural range<>, natural range<>) of slv(12 downto 0); + type Slv12VectorArray is array (natural range<>, natural range<>) of slv(11 downto 0); + type Slv11VectorArray is array (natural range<>, natural range<>) of slv(10 downto 0); + type Slv10VectorArray is array (natural range<>, natural range<>) of slv(9 downto 0); + type Slv9VectorArray is array (natural range<>, natural range<>) of slv(8 downto 0); + type Slv8VectorArray is array (natural range<>, natural range<>) of slv(7 downto 0); + type Slv7VectorArray is array (natural range<>, natural range<>) of slv(6 downto 0); + type Slv6VectorArray is array (natural range<>, natural range<>) of slv(5 downto 0); + type Slv5VectorArray is array (natural range<>, natural range<>) of slv(4 downto 0); + type Slv4VectorArray is array (natural range<>, natural range<>) of slv(3 downto 0); + type Slv3VectorArray is array (natural range<>, natural range<>) of slv(2 downto 0); + type Slv2VectorArray is array (natural range<>, natural range<>) of slv(1 downto 0); + type Slv1VectorArray is array (natural range<>, natural range<>) of slv(0 downto 0); + type SlVectorArray is array (natural range<>, natural range<>) of sl; + + -- Mux a SlVectorArray into an SLV + function muxSlVectorArray (vec : SlVectorArray; addr : natural; allowOutOfRange : boolean := false) return slv; + +end StdRtlPkg; + +package body StdRtlPkg is + + function slvAll (size : positive; value : sl) return slv is + variable retVar : slv(size-1 downto 0) := (others => value); + begin + return retVar; + end function slvAll; + + function slvZero (size : positive) return slv is + begin + return slvAll(size, '0'); + end function; + + function slvOne (size : positive) return slv is + begin + return slvAll(size, '1'); + end function; + + function isPowerOf2 (number : natural) return boolean is + begin + return isPowerOf2(toSlv(number, 32)); + end function isPowerOf2; + + function isPowerOf2 (vector : slv) return boolean is + begin + return (unsigned(vector) /= 0) and + (unsigned(unsigned(vector) and (unsigned(vector)-1)) = 0); + end function isPowerOf2; + + --------------------------------------------------------------------------------------------------------------------- + -- Function: log2 + -- Purpose: Finds the log base 2 of an integer + -- Input is rounded up to nearest power of two. + -- Therefore log2(5) = log2(8) = 3. + -- Arg: number - integer to find log2 of + -- Returns: Integer containing log base two of input. + --------------------------------------------------------------------------------------------------------------------- + function log2(constant number : positive) return natural is + begin + return integer(ceil(ieee.math_real.log2(real(number)))); + end function; + + -- Find number of bits needed to store a number + function bitSize (constant number : natural ) return positive is + begin + if (number = 0 or number = 1) then + return 1; + else + if (isPowerOf2(number)) then + return log2(number) + 1; + else + return log2(number); + end if; + end if; + end function; + + -- NOTE: XST will crap its pants if you try to pass a constant to this function + function bitReverse (a : slv) return slv is + variable resultVar : slv(a'range); + alias aa : slv(a'reverse_range) is a; + begin + for i in aa'range loop + resultVar(i) := aa(i); + end loop; + return resultVar; + end; + + function list (constant start, size, step : integer) return IntegerArray is + variable retVar : IntegerArray(0 to size-1); + begin + for i in retVar'range loop + retVar(i) := start + (i * step); + end loop; + return retVar; + end function list; + + function toBoolean (logic : sl) return boolean is + begin -- function toBoolean + return logic = '1'; + end function toBoolean; + + function toSl (bool : boolean) return sl is + begin + if (bool) then + return '1'; + else + return '0'; + end if; + end function toSl; + + function toString (bool : boolean) return string is + begin + if (bool) then + return "TRUE"; + else + return "FALSE"; + end if; + end function toString; + + function toBoolean (str : string) return boolean is + begin + if (str = "TRUE" or str = "true") then + return true; + else + return false; + end if; + end function toBoolean; + + -------------------------------------------------------------------------------------------------- + -- Decode and genmux + -------------------------------------------------------------------------------------------------- + -- generic decoder + function decode(v : slv) return slv is + variable res : slv((2**v'length)-1 downto 0); + variable i : integer range res'range; + begin + res := (others => '0'); + i := 0; + i := to_integer(unsigned(v)); + res(i) := '1'; + return res; + end; + + -- generic multiplexer + function genmux(s, v : slv) return sl is + variable res : slv(v'length-1 downto 0); + variable i : integer range res'range; + begin + res := v; + i := 0; + i := to_integer(unsigned(s)); + return res(i); + end; + + --------------------------------------------------------------------------------------------------------------------- + -- Unary reduction operators + --------------------------------------------------------------------------------------------------------------------- + function uOr (vec : slv) return sl is + variable retvar: sl:='0'; + begin + retvar:='0'; + for i in vec'range loop + if (vec(i) = '1') then + retvar:= '1'; + end if; + end loop; + return retvar; + end function uOr; + + function uAnd (vec : slv) return sl is + variable retvar: sl:='1'; + begin + retvar:='1'; + for i in vec'range loop + if (vec(i) = '0') then + retvar:='0'; + end if; + end loop; + return retvar; + end function uAnd; + + function uXor (vec : slv) return sl is + variable intVar : sl; + begin + for i in vec'range loop + if (i = vec'left) then + intVar := vec(i); + else + intVar := intVar xor vec(i); + end if; + end loop; + return intVar; + end function uXor; + + function allBits (vec : slv; test : sl) return boolean is + begin + for i in vec'range loop + if (vec(i) /= test) then + return false; + end if; + end loop; + return true; + end function; + + function noBits (vec : slv; test : sl) return boolean is + begin + for i in vec'range loop + if (vec(i) = test) then + return false; + end if; + end loop; + return true; + end function; + + ----------------------------------------------------------------------------- + -- Functions to determine parity of arbitrary sized slv + ----------------------------------------------------------------------------- + -- returns '1' if vec has even parity + function evenParity (vec : slv) + return sl is + begin + return not uXor(vec); + end function; + + -- return '1' if vec has odd parity + function oddParity (vec : slv) + return sl is + begin + return uXor(vec); + end function; + + ----------------------------------------------------------------------------- + -- Functions for counting the number of '1' in a slv bus + ----------------------------------------------------------------------------- + -- New Non-recursive onesCount Function + function onesCount (vec : slv) + return unsigned is + variable retVar : unsigned((bitSize(vec'length)-1) downto 0) := to_unsigned(0,bitSize(vec'length)); + begin + for i in vec'range loop + if vec(i) = '1' then + retVar := retVar + 1; + end if; + end loop; + return retVar; + end function; + + -- -- Old Recursive onesCount Function + -- function onesCount (vec : slv) return unsigned is + -- variable topVar : slv(vec'high downto vec'low+(vec'length/2)); + -- variable bottomVar : slv(topVar'low-1 downto vec'low); + -- variable tmpVar : slv(2 downto 0); + -- begin + -- if (vec'length = 1) then + -- return '0' & unsigned(vec); + -- end if; + + -- if (vec'length = 2) then + -- return uAnd(vec) & uXor(vec); + -- end if; + + -- if (vec'length = 3) then + -- tmpVar := vec; + -- case tmpVar is + -- when "000" => return "00"; + -- when "001" => return "01"; + -- when "010" => return "01"; + -- when "011" => return "10"; + -- when "100" => return "01"; + -- when "101" => return "10"; + -- when "110" => return "10"; + -- when "111" => return "11"; + -- when others => return "00"; + -- end case; + -- end if; + + -- topVar := vec(vec'high downto (vec'high+1)-((vec'length+1)/2)); + -- bottomVar := vec(vec'high-((vec'length+1)/2) downto vec'low); + + -- return ('0' & onesCount(topVar)) + ('0' & onesCount(bottomVar)); + -- end function; + + -- SLV variant + function onesCount (vec : slv) + return slv is + variable retVar : slv((bitSize(vec'length)-1) downto 0); + variable cntVar : unsigned((bitSize(vec'length)-1) downto 0); + begin + cntVar := onesCount(vec); + retVar := slv(cntVar); + return retVar; + end function; + + ----------------------------------------------------------------------------- + -- Functions for encoding and decoding grey codes + ----------------------------------------------------------------------------- + -- Get next gray code given binary vector + function grayEncode (vec : unsigned) + return unsigned is + begin + return vec xor shift_right(vec, 1); + end function; + + -- SLV variant + function grayEncode (vec : slv) + return slv is + begin + return slv(grayEncode(unsigned(vec))); + end function; + + -- Get the binary equivalent of a Gray code created with gray_encode. + function grayDecode (vec : unsigned) + return unsigned is + variable retVar : unsigned(vec'range) := (others => '0'); + begin + for i in vec'range loop + if (i = vec'left) then + retVar(i) := vec(i); + else + if (vec'ascending) then + retVar(i) := retVar(i-1) xor vec(i); + else + retVar(i) := retVar(i+1) xor vec(i); + end if; + end if; + end loop; + return retVar; + end function; + + -- SLV variant + function grayDecode (vec : slv) + return slv is + variable retVar : slv(vec'range) := (others => '0'); + begin + return slv(grayDecode(unsigned(vec))); + end function; + + ------------------------------------------------------------------------------------------------- + -- Implements an N tap linear feedback shift operation + -- Size of LFSR is variable and determined by length of lfsr parameter + -- Number of taps is variable and determined by length of taps array parameter + -- An input parameter is also available for use in scramblers + -- Output is new lfsr value after one shift operation + -- The lfsr param can be indexed ascending or decending + -- The shift is in the direction of increasing index (left shift for decending, right for ascending) + ------------------------------------------------------------------------------------------------- + function lfsrShift (lfsr : slv; constant taps : NaturalArray; input : sl := '0') return slv is + variable retVar : slv(lfsr'range) := (others => '0'); + begin + if (lfsr'ascending) then + retVar := input & lfsr(lfsr'left to lfsr'right-1); + else + retVar := lfsr(lfsr'left-1 downto lfsr'right) & input; + end if; + + for i in taps'range loop + assert (taps(i) <= lfsr'high) report "lfsrShift() - Tap value exceedes lfsr range" severity failure; + retVar(lfsr'low) := retVar(lfsr'low) xor lfsr(taps(i)); + end loop; + + return retVar; + end function; + + ------------------------------------------------------------------------------------------------- + -- One line if-then-else functions. + ------------------------------------------------------------------------------------------------- + + function ite (i : boolean; t : boolean; e : boolean) return boolean is + begin + if (i) then return t; else return e; end if; + end function ite; + + function ite (i : boolean; t : sl; e : sl) return sl is + begin + if (i) then return t; else return e; end if; + end function ite; + + function ite (i : boolean; t : slv; e : slv) return slv is + begin + if (i) then return t; else return e; end if; + end function ite; + + function ite (i : boolean; t : bit_vector; e : bit_vector) return bit_vector is + begin + if (i) then return t; else return e; end if; + end function ite; + + function ite (i : boolean; t : character; e : character) return character is + begin + if (i) then return t; else return e; end if; + end function ite; + + function ite (i : boolean; t : string; e : string) return string is + begin + if (i) then return t; else return e; end if; + end function ite; + + function ite (i : boolean; t : integer; e : integer) return integer is + begin + if (i) then return t; else return e; end if; + end function ite; + + function ite (i : boolean; t : real; e : real) return real is + begin + if (i) then return t; else return e; end if; + end function ite; + + function ite (i : boolean; t : time; e : time) return time is + begin + if (i) then return t; else return e; end if; + end function ite; + + ----------------------------- + -- Min and Max + ----------------------------- + function maximum (left, right : integer) return integer is + begin + if left > right then return left; + else return right; + end if; + end maximum; + + function minimum (left, right : integer) return integer is + begin + if left < right then return left; + else return right; + end if; + end minimum; + + ----------------------------- + -- conv_std_logic_vector functions + -- without calling the STD_LOGIC_ARITH library + ----------------------------- + + -- convert an integer to an STD_LOGIC_VECTOR + function toSlv(ARG : integer; SIZE : integer) return slv is + begin + return slv(to_unsigned(ARG, SIZE)); + end; + + ----------------------------- + -- gets real multiplication + ----------------------------- + function getRealMult (A, B : real) return real is + begin + return real(A*B); + end function; + + function getRealMult (A : integer; B : real) return real is + begin + return real(real(A)*B); + end function; + + function getRealMult (A : real; B : integer) return real is + begin + return real(A*real(B)); + end function; + + ----------------------------- + -- gets real division + ----------------------------- + function getRealDiv (A, B : real) return real is + begin + return real(A/B); + end function; + + function getRealDiv (A : integer; B : real) return real is + begin + return real(real(A)/B); + end function; + + function getRealDiv (A : real; B : integer) return real is + begin + return real(A/real(B)); + end function; + + ------------------------------------------------------------------------------------------------- + -- Simulates an ADC conversion + ------------------------------------------------------------------------------------------------- + function adcConversion ( + ain : real; + low : real; + high : real; + bits : positive; + twosComp : boolean) + return slv is + variable tmpR : real; + variable tmpI : integer; + + variable retSigned : signed(bits-1 downto 0); + variable retUnsigned : unsigned(bits-1 downto 0); + begin + tmpR := ain; + + -- Constrain input to full scale range + tmpR := realmin(high, tmpR); + tmpR := realmax(low, tmpR); + + -- Scale to [0,1] or [-.5,.5] + tmpR := (tmpR-low)/(high-low) + ite(twosComp, -0.5, 0.0); + + -- Scale to number of bits + tmpR := tmpR * real(2**bits); + + if (twosComp) then + retSigned := to_signed(integer(round(tmpR)), bits); + return slv(retSigned); + else + retUnsigned := to_unsigned(integer(round(tmpR)), bits); + return slv(retUnsigned); + end if; + end function adcConversion; + + ----------------------------- + -- gets a time ratio + ----------------------------- + function getTimeRatio (T1, T2 : time) return natural is + begin + return natural(T1/T2); + end function; + + function getTimeRatio (T1, T2 : real) return natural is + begin + return natural(ROUND(abs(T1/T2))); + end function; + + --------------------------------------------------------------------------------------------------------------------- + -- Convert a frequency to a period (time). + --------------------------------------------------------------------------------------------------------------------- + -- pragma translate_off + function toTime(f : frequency) return time is + begin + return(1.0 sec / (f/Hz)); + end function; + --pragma translate_on + + ----------------------------- + -- Mux a SlVectorArray into an SLV + ----------------------------- + function muxSlVectorArray (vec : SlVectorArray; + addr : natural; + allowOutOfRange : boolean := false) + return slv is + variable retVar : slv(vec'range(2)); + begin + -- Check the limit of the address + if (addr < vec'length(1)) or (allowOutOfRange = false) then + for i in vec'range(2) loop + retVar(i) := vec(addr, i); + end loop; + else + retVar := (others => '0'); + end if; + return retVar; + end function; + + procedure assignSlv ( + i : inout integer; + vector : inout slv; + value : in slv) + is + variable low : integer; + begin + low := i; + i := i+value'length; + vector(i-1 downto low) := value; + end procedure assignSlv; + + procedure assignSlv ( + i : inout integer; + vector : inout slv; + value : in sl) + is + variable low : integer; + begin + vector(i) := value; + i := i+1; + end procedure assignSlv; + + procedure assignRecord ( + i : inout integer; + vector : in slv; + value : inout slv) + is + variable low : integer; + begin + low := i; + i := i+value'length; + value := vector(i-1 downto low); + end procedure assignRecord; + + procedure assignRecord ( + i : inout integer; + vector : in slv; + value : inout sl) + is + variable low : integer; + begin + value := vector(i); + i := i+1; + end procedure assignRecord; + + -- Resize an SLV, either by trimming or padding upper bits + function resizeSlv ( vector : slv; newSize : integer) return slv is + variable retVar : slv(newSize-1 downto 0); + variable top : integer; + begin + retVar := (others=>'0'); + + top := minimum( newSize, vector'length) - 1; + + retVar(top downto 0) := vector(top downto 0); + + return retVar; + end function; + +end package body StdRtlPkg; diff --git a/rce/fw-hsio/modules/pixelcore/hdl/adcreadout.vhd b/rce/fw-hsio/modules/pixelcore/hdl/adcreadout.vhd new file mode 100644 index 00000000..484cf98d --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/adcreadout.vhd @@ -0,0 +1,77 @@ +-------------------------------------------------------------- +-- Serializer for High Speed I/O board (ATLAS Pixel teststand) +-- Martin Kocian 01/2009 +-------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use work.StdRtlPkg.all; +use work.all; + +-------------------------------------------------------------- + +entity adcreadout is +generic( CHANNEL: std_logic_vector(7 downto 0):=x"ff"); +port( clk: in std_logic; + rst: in std_logic; + d_in: in Slv16Array(11 downto 0); + enabled: in std_logic; + go: in std_logic; + d_out: out std_logic_vector(15 downto 0); + ld: out std_logic; + sof: out std_logic; + eof: out std_logic +); +end adcreadout; + +-------------------------------------------------------------- + +architecture ADCREADOUT of adcreadout is + +begin + + + process(rst, clk) + + variable headercounter: natural range 0 to 29 := 0; + begin + if(rst='1') then + d_out<=x"0000"; + eof<='0'; + sof<='0'; + headercounter:=0; + ld<='0'; + elsif (clk'event and clk='1') then + if(headercounter=0 and enabled='1' and go='1')then + headercounter:=29; + end if; + if (headercounter/=0)then + if(headercounter=29)then + ld<='1'; + sof<='1'; + d_out<=(others=>'0'); + elsif(headercounter=28)then + sof<='0'; + d_out(7 downto 0)<=(others=>'0'); + d_out(15 downto 8)<=CHANNEL; + elsif(headercounter<14 and headercounter>1)then + d_out<=d_in(13-headercounter); + else + d_out<=(others=>'0'); + end if; + if(headercounter=2)then + eof<='1'; + elsif(headercounter=1)then + eof<='0'; + ld<='0'; + end if; + headercounter:=headercounter-1; + end if; + end if; + + end process; + +end ADCREADOUT; + +-------------------------------------------------------------- diff --git a/rce/fw-hsio/modules/pixelcore/hdl/arraytype.vhd b/rce/fw-hsio/modules/pixelcore/hdl/arraytype.vhd new file mode 100644 index 00000000..6bc145fb --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/arraytype.vhd @@ -0,0 +1,12 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use work.all; +package arraytype is + type dataarray is array(31 downto 0) of std_logic_vector(17 downto 0); + type fei4array is array(31 downto 0) of std_logic_vector(24 downto 0); + type array10b is array(31 downto 0) of std_logic_vector(9 downto 0); + type hb is array(1 downto 0) of std_logic_vector(4 downto 0); + type hbpipeline is array(40 downto 0) of std_logic_vector(2 downto 0); + type hitbusoutput is array(1 downto 0) of std_logic_vector(31 downto 0); +end package arraytype; diff --git a/rce/fw-hsio/modules/pixelcore/hdl/clock160.vhd b/rce/fw-hsio/modules/pixelcore/hdl/clock160.vhd new file mode 100644 index 00000000..17be9c42 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/clock160.vhd @@ -0,0 +1,113 @@ +-------------------------------------------------------------------------------- +-- Copyright (c) 1995-2008 Xilinx, Inc. All rights reserved. +-------------------------------------------------------------------------------- +-- ____ ____ +-- / /\/ / +-- /___/ \ / Vendor: Xilinx +-- \ \ \/ Version : 10.1.03 +-- \ \ Application : xaw2vhdl +-- / / Filename : clock40.vhd +-- /___/ /\ Timestamp : 09/08/2009 09:18:06 +-- \ \ / \ +-- \___\/\___\ +-- +--Command: xaw2vhdl-st /a/sulky20/g.ee.u07/kocian/minilat/xilinx/IBL/xil_cores/clock40.xaw /a/sulky20/g.ee.u07/kocian/minilat/xilinx/IBL/xil_cores/clock40 +--Design Name: clock40 +--Device: xc4vfx60-10ff1152 +-- +-- Module clock40 +-- Generated by Xilinx Architecture Wizard +-- Written for synthesis tool: Synplify +-- Period Jitter (unit interval) for block DCM_ADV_INST = 0.012 UI +-- Period Jitter (Peak-to-Peak) for block DCM_ADV_INST = 0.297 ns + +library ieee; +use ieee.std_logic_1164.ALL; +use ieee.numeric_std.ALL; +library UNISIM; +use UNISIM.Vcomponents.ALL; + +entity clock160 is + port ( CLKIN_N_IN : in std_logic; + CLKIN_P_IN : in std_logic; + RST_IN : in std_logic; + CLKFX_OUT : out std_logic; + CLKIN_IBUFGDS_OUT : out std_logic; + CLK0_OUT : out std_logic; + LOCKED_OUT : out std_logic); +end clock160; + +architecture BEHAVIORAL of clock160 is + signal CLKFB_IN : std_logic; + signal CLKFX_BUF : std_logic; + signal CLKIN_IBUFGDS : std_logic; + signal CLK0_BUF : std_logic; + signal GND_BIT : std_logic; + signal GND_BUS_7 : std_logic_vector (6 downto 0); + signal GND_BUS_16 : std_logic_vector (15 downto 0); +begin + GND_BIT <= '0'; + GND_BUS_7(6 downto 0) <= "0000000"; + GND_BUS_16(15 downto 0) <= "0000000000000000"; + CLKIN_IBUFGDS_OUT <= CLKIN_IBUFGDS; + CLK0_OUT <= CLKFB_IN; + CLKFX_BUFG_INST : BUFG + port map (I=>CLKFX_BUF, + O=>CLKFX_OUT); + + CLKIN_IBUFGDS_INST : IBUFGDS + generic map(DIFF_TERM=>TRUE, + IOSTANDARD=>"LVDS_25") + port map (I=>CLKIN_P_IN, + IB=>CLKIN_N_IN, + O=>CLKIN_IBUFGDS); + + CLK0_BUFG_INST : BUFG + port map (I=>CLK0_BUF, + O=>CLKFB_IN); + + DCM_ADV_INST : DCM_ADV + generic map( CLK_FEEDBACK => "1X", + CLKDV_DIVIDE => 2.0, + CLKFX_DIVIDE => 25, + CLKFX_MULTIPLY => 32, + CLKIN_DIVIDE_BY_2 => FALSE, + CLKIN_PERIOD => 8.000, + CLKOUT_PHASE_SHIFT => "NONE", + DCM_AUTOCALIBRATION => TRUE, + DCM_PERFORMANCE_MODE => "MAX_SPEED", + DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS", + DFS_FREQUENCY_MODE => "LOW", + DLL_FREQUENCY_MODE => "LOW", + DUTY_CYCLE_CORRECTION => TRUE, + FACTORY_JF => x"F0F0", + PHASE_SHIFT => 0, + STARTUP_WAIT => FALSE) + port map (CLKFB=>CLKFB_IN, + CLKIN=>CLKIN_IBUFGDS, + DADDR(6 downto 0)=>GND_BUS_7(6 downto 0), + DCLK=>GND_BIT, + DEN=>GND_BIT, + DI(15 downto 0)=>GND_BUS_16(15 downto 0), + DWE=>GND_BIT, + PSCLK=>GND_BIT, + PSEN=>GND_BIT, + PSINCDEC=>GND_BIT, + RST=>RST_IN, + CLKDV=>open, + CLKFX=>CLKFX_BUF, + CLKFX180=>open, + CLK0=>CLK0_BUF, + CLK2X=>open, + CLK2X180=>open, + CLK90=>open, + CLK180=>open, + CLK270=>open, + DO=>open, + DRDY=>open, + LOCKED=>LOCKED_OUT, + PSDONE=>open); + +end BEHAVIORAL; + + diff --git a/rce/fw-hsio/modules/pixelcore/hdl/clock200.vhd b/rce/fw-hsio/modules/pixelcore/hdl/clock200.vhd new file mode 100644 index 00000000..daa834da --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/clock200.vhd @@ -0,0 +1,102 @@ +-------------------------------------------------------------------------------- +-- Copyright (c) 1995-2008 Xilinx, Inc. All rights reserved. +-------------------------------------------------------------------------------- +-- ____ ____ +-- / /\/ / +-- /___/ \ / Vendor: Xilinx +-- \ \ \/ Version : 10.1.03 +-- \ \ Application : xaw2vhdl +-- / / Filename : clock200.vhd +-- /___/ /\ Timestamp : 09/17/2009 10:43:18 +-- \ \ / \ +-- \___\/\___\ +-- +--Command: xaw2vhdl-st /a/sulky20/g.ee.u07/kocian/minilat/xilinx/IBL/xil_cores/clock200.xaw /a/sulky20/g.ee.u07/kocian/minilat/xilinx/IBL/xil_cores/clock200 +--Design Name: clock200 +--Device: xc4vfx60-10ff1152 +-- +-- Module clock200 +-- Generated by Xilinx Architecture Wizard +-- Written for synthesis tool: Synplify +-- Period Jitter (unit interval) for block DCM_ADV_INST = 0.042 UI +-- Period Jitter (Peak-to-Peak) for block DCM_ADV_INST = 0.208 ns + +library ieee; +use ieee.std_logic_1164.ALL; +use ieee.numeric_std.ALL; +library UNISIM; +use UNISIM.Vcomponents.ALL; + +entity clock200 is + port ( CLKIN_IN : in std_logic; + RST_IN : in std_logic; + CLKFX_OUT : out std_logic; + CLK0_OUT : out std_logic; + LOCKED_OUT : out std_logic); +end clock200; + +architecture BEHAVIORAL of clock200 is + signal CLKFB_IN : std_logic; + signal CLKFX_BUF : std_logic; + signal CLK0_BUF : std_logic; + signal GND_BIT : std_logic; + signal GND_BUS_7 : std_logic_vector (6 downto 0); + signal GND_BUS_16 : std_logic_vector (15 downto 0); +begin + GND_BIT <= '0'; + GND_BUS_7(6 downto 0) <= "0000000"; + GND_BUS_16(15 downto 0) <= "0000000000000000"; + CLK0_OUT <= CLKFB_IN; + CLKFX_BUFG_INST : BUFG + port map (I=>CLKFX_BUF, + O=>CLKFX_OUT); + + CLK0_BUFG_INST : BUFG + port map (I=>CLK0_BUF, + O=>CLKFB_IN); + + DCM_ADV_INST : DCM_ADV + generic map( CLK_FEEDBACK => "1X", + CLKDV_DIVIDE => 2.0, + CLKFX_DIVIDE => 4, + CLKFX_MULTIPLY => 5, + CLKIN_DIVIDE_BY_2 => FALSE, + CLKIN_PERIOD => 6.250, + CLKOUT_PHASE_SHIFT => "NONE", + DCM_AUTOCALIBRATION => TRUE, + DCM_PERFORMANCE_MODE => "MAX_SPEED", + DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS", + DFS_FREQUENCY_MODE => "LOW", + DLL_FREQUENCY_MODE => "HIGH", + DUTY_CYCLE_CORRECTION => TRUE, + FACTORY_JF => x"F0F0", + PHASE_SHIFT => 0, + STARTUP_WAIT => FALSE) + port map (CLKFB=>CLKFB_IN, + CLKIN=>CLKIN_IN, + DADDR(6 downto 0)=>GND_BUS_7(6 downto 0), + DCLK=>GND_BIT, + DEN=>GND_BIT, + DI(15 downto 0)=>GND_BUS_16(15 downto 0), + DWE=>GND_BIT, + PSCLK=>GND_BIT, + PSEN=>GND_BIT, + PSINCDEC=>GND_BIT, + RST=>RST_IN, + CLKDV=>open, + CLKFX=>CLKFX_BUF, + CLKFX180=>open, + CLK0=>CLK0_BUF, + CLK2X=>open, + CLK2X180=>open, + CLK90=>open, + CLK180=>open, + CLK270=>open, + DO=>open, + DRDY=>open, + LOCKED=>LOCKED_OUT, + PSDONE=>open); + +end BEHAVIORAL; + + diff --git a/rce/fw-hsio/modules/pixelcore/hdl/coincidence.vhd b/rce/fw-hsio/modules/pixelcore/hdl/coincidence.vhd new file mode 100644 index 00000000..fe474592 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/coincidence.vhd @@ -0,0 +1,117 @@ +-------------------------------------------------------------- +-- Serializer for High Speed I/O board (ATLAS Pixel teststand) +-- Martin Kocian 01/2009 +-------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use work.all; +use work.arraytype.all; + +-------------------------------------------------------------- + + +entity coincidence is + +port( clk: in std_logic; + rst: in std_logic; + enabled: in std_logic; + fifothresh: in std_logic; + trgin: in std_logic; + serbusy: in std_logic; + tdcreadoutbusy: in std_logic; + extbusy: in std_logic; + firstphase: in std_logic; + tdcready: in std_logic; + starttdc: out std_logic; + l1a: out std_logic; + trgdelay: in std_logic_vector(7 downto 0); + busy: out std_logic; + coinc: out std_logic; + coincd: out std_logic +); +end coincidence; + +-------------------------------------------------------------- + +architecture COINCIDENCE of coincidence is + +signal andr: std_logic_vector(15 downto 0); +signal delaycounter: std_logic_vector(7 downto 0); +signal busys: std_logic; +signal coinct: std_logic; +signal rescoin: std_logic; +signal oldcoinct: std_logic; +signal oldoldcoinct: std_logic; +signal oldbusys: std_logic; +signal oldoldbusys: std_logic; +signal oldtdcreadoutbusy: std_logic; +signal oldenabled: std_logic; +signal l1asig: std_logic; +signal go: std_logic; + +begin + l1a<=l1asig; + busys<=fifothresh or serbusy or tdcreadoutbusy or extbusy or firstphase; + go <= tdcready and enabled and not busys; + busy<= enabled and (busys or not tdcready); + coinc<=coinct; + coincd<=trgin; + + process (rst,rescoin, go,trgin) + begin + if( rst='1' or rescoin='1')then + coinct<='0'; + elsif(rising_edge(trgin))then + if(go='1')then + coinct<='1'; + end if; + end if; + end process; + + process (rst,clk) + begin + if(rst='1')then + starttdc<= '0'; + oldcoinct<='0'; + oldoldcoinct<='0'; + oldbusys<='0'; + oldoldbusys<='0'; + oldenabled<='0'; + l1asig<='0'; + delaycounter<=x"00"; + oldtdcreadoutbusy<='0'; + elsif(rising_edge(clk))then + if(delaycounter/=x"00")then + delaycounter<=unsigned(delaycounter)-1; + elsif(coinct='1' and oldoldcoinct='0')then -- keep one bin as a buffer + delaycounter<=trgdelay; + end if; + if(delaycounter=x"01")then + l1asig<='1'; + else + l1asig<='0'; + end if; + if(l1asig='1')then + rescoin<='1'; + elsif(go='0')then + rescoin<='0'; + end if; + if(tdcready='0' and tdcreadoutbusy='0' and oldtdcreadoutbusy='1')then + starttdc<='1'; + elsif(enabled='1' and oldenabled='0') then + starttdc<='1'; + else + starttdc<='0'; + end if; + oldcoinct<=coinct; + oldoldcoinct<=oldcoinct; + oldbusys<=busys; + oldoldbusys<=oldbusys; + oldtdcreadoutbusy<=tdcreadoutbusy; + oldenabled<=enabled; + end if; + end process; + +end COINCIDENCE; diff --git a/rce/fw-hsio/modules/pixelcore/hdl/datafifo.vhd b/rce/fw-hsio/modules/pixelcore/hdl/datafifo.vhd new file mode 100644 index 00000000..b7ea4a7a --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/datafifo.vhd @@ -0,0 +1,242 @@ +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity datafifo is + generic ( + buffersize : integer :=8192 -- FIFO size + ); + port ( + din: IN std_logic_VECTOR(17 downto 0); + rd_clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_clk: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(17 downto 0); + empty: OUT std_logic; + full: OUT std_logic; + overflow: OUT std_logic; + prog_full: OUT std_logic; + valid: OUT std_logic; + underflow: out std_logic); + end datafifo; + +architecture datafifo of datafifo is + + component datafifo4096 + port ( + din: IN std_logic_VECTOR(17 downto 0); + rd_clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_clk: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(17 downto 0); + empty: OUT std_logic; + full: OUT std_logic; + overflow: OUT std_logic; + prog_full: OUT std_logic; + valid: OUT std_logic; + underflow: out std_logic); + end component; + + component datafifo8192 + port ( + din: IN std_logic_VECTOR(17 downto 0); + rd_clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_clk: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(17 downto 0); + empty: OUT std_logic; + full: OUT std_logic; + overflow: OUT std_logic; + prog_full: OUT std_logic; + valid: OUT std_logic; + underflow: out std_logic); + end component; + + COMPONENT datafifo16384 + PORT ( + rst : IN STD_LOGIC; + wr_clk : IN STD_LOGIC; + rd_clk : IN STD_LOGIC; + din : IN STD_LOGIC_VECTOR(17 DOWNTO 0); + wr_en : IN STD_LOGIC; + rd_en : IN STD_LOGIC; + dout : OUT STD_LOGIC_VECTOR(17 DOWNTO 0); + full : OUT STD_LOGIC; + overflow : OUT STD_LOGIC; + empty : OUT STD_LOGIC; + valid : OUT STD_LOGIC; + underflow : OUT STD_LOGIC; + prog_full : OUT STD_LOGIC + ); + END COMPONENT; + component datafifo32768 + port ( + din: IN std_logic_VECTOR(17 downto 0); + rd_clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_clk: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(17 downto 0); + empty: OUT std_logic; + full: OUT std_logic; + overflow: OUT std_logic; + prog_full: OUT std_logic; + valid: OUT std_logic; + underflow: out std_logic); + end component; + component datafifo65536 + port ( + din: IN std_logic_VECTOR(17 downto 0); + rd_clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_clk: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(17 downto 0); + empty: OUT std_logic; + full: OUT std_logic; + overflow: OUT std_logic; + prog_full: OUT std_logic; + valid: OUT std_logic; + underflow: out std_logic); + end component; + COMPONENT datafifo131072 + PORT ( + rst : IN STD_LOGIC; + wr_clk : IN STD_LOGIC; + rd_clk : IN STD_LOGIC; + din : IN STD_LOGIC_VECTOR(17 DOWNTO 0); + wr_en : IN STD_LOGIC; + rd_en : IN STD_LOGIC; + dout : OUT STD_LOGIC_VECTOR(17 DOWNTO 0); + full : OUT STD_LOGIC; + overflow : OUT STD_LOGIC; + empty : OUT STD_LOGIC; + valid : OUT STD_LOGIC; + underflow : OUT STD_LOGIC; + prog_full : OUT STD_LOGIC + ); + END COMPONENT; + +begin + + buf_4096: if (buffersize=4096) generate + fifo4096 : datafifo4096 + port map ( + din => din, + rd_clk => rd_clk, + rd_en => rd_en, + rst => rst, + wr_clk => wr_clk, + wr_en => wr_en, + dout => dout, + empty => empty, + full => full, + overflow => overflow, + prog_full => prog_full, + valid => valid, + underflow => underflow); + end generate; + + buf_8192: if (buffersize=8192) generate + fifo8192 : datafifo8192 + port map ( + din => din, + rd_clk => rd_clk, + rd_en => rd_en, + rst => rst, + wr_clk => wr_clk, + wr_en => wr_en, + dout => dout, + empty => empty, + full => full, + overflow => overflow, + prog_full => prog_full, + valid => valid, + underflow => underflow); + end generate; + + buf_16384: if (buffersize=16384) generate + fifo16384 : datafifo16384 + port map ( + din => din, + rd_clk => rd_clk, + rd_en => rd_en, + rst => rst, + wr_clk => wr_clk, + wr_en => wr_en, + dout => dout, + empty => empty, + full => full, + overflow => overflow, + prog_full => prog_full, + valid => valid, + underflow => underflow); + end generate; + + buf_32768: if (buffersize=32768) generate + fifo32768 : datafifo32768 + port map ( + din => din, + rd_clk => rd_clk, + rd_en => rd_en, + rst => rst, + wr_clk => wr_clk, + wr_en => wr_en, + dout => dout, + empty => empty, + full => full, + overflow => overflow, + prog_full => prog_full, + valid => valid, + underflow => underflow); + end generate; + + buf_65536: if (buffersize=65536) generate + fifo65536 : datafifo65536 + port map ( + din => din, + rd_clk => rd_clk, + rd_en => rd_en, + rst => rst, + wr_clk => wr_clk, + wr_en => wr_en, + dout => dout, + empty => empty, + full => full, + overflow => overflow, + prog_full => prog_full, + valid => valid, + underflow => underflow); + end generate; + + buf_131072: if (buffersize=131072) generate + fifo131072 : datafifo131072 + port map ( + din => din, + rd_clk => rd_clk, + rd_en => rd_en, + rst => rst, + wr_clk => wr_clk, + wr_en => wr_en, + dout => dout, + empty => empty, + full => full, + overflow => overflow, + prog_full => prog_full, + valid => valid, + underflow => underflow); + end generate; + + +end datafifo; + diff --git a/rce/fw-hsio/modules/pixelcore/hdl/dataflag.vhd b/rce/fw-hsio/modules/pixelcore/hdl/dataflag.vhd new file mode 100644 index 00000000..af926d90 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/dataflag.vhd @@ -0,0 +1,90 @@ +------------------------------------------------------------------------------- +-- Description: +-- Core logic for BNL ASIC test FPGA. +------------------------------------------------------------------------------- +-- Copyright (c) 2008 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 07/21/2008: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity dataflag is + port ( + eofin : in std_logic; + eofout : in std_logic; + datawaiting: out std_logic; + clk : in std_logic; + rst : in std_logic; + counter : out std_logic_vector(15 downto 0) + ); +end dataflag; + +architecture DATAFLAG of dataflag is + + component eofcounter + port ( + clk: IN std_logic; + up: IN std_logic; + ce: IN std_logic; + aclr: IN std_logic; + q_thresh0: OUT std_logic; + q: OUT std_logic_VECTOR(15 downto 0)); + end component; + signal iszero: std_logic; + signal oldeofin: std_logic; + signal oldeofout: std_logic; + signal cond: std_logic; + signal eofincond: std_logic; + signal eofoutcond: std_logic; + signal updown: std_logic; + signal init: std_logic; + +begin + +-- datawaiting<=not iszero; + -- reset resets the threshold flag, too :-( + datawaiting<=not iszero when init='1' else '0'; + process (rst,clk) + begin + if(rst='1')then + oldeofin<='1'; + oldeofout<='1'; + cond<='0'; + init<='0'; + elsif(rising_edge(clk))then + oldeofin<=eofin; + oldeofout<=eofout; + if(eofin='1' and oldeofin='0')then + eofincond<='1'; + init<='1'; + else + eofincond<='0'; + end if; + if(eofout='1' and oldeofout='0')then + eofoutcond<='1'; + else + eofoutcond<='0'; + end if; + cond<=eofincond xor eofoutcond; + updown<=eofincond; + + end if; + end process; + + + theeofcounter: eofcounter + port map( + clk=>clk, + up=>updown, + ce=>cond, + aclr=>rst, + q_thresh0=>iszero, + q=>counter); + +end DATAFLAG; diff --git a/rce/fw-hsio/modules/pixelcore/hdl/dataflagff.vhd b/rce/fw-hsio/modules/pixelcore/hdl/dataflagff.vhd new file mode 100644 index 00000000..1581a021 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/dataflagff.vhd @@ -0,0 +1,85 @@ +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity dataflagff is + port ( + eofin : in std_logic; + ldin : in std_logic; + eofout : in std_logic; + ldout : in std_logic; + datawaiting: out std_logic; + moredatawaiting: out std_logic; + clkin : in std_logic; + clkinrate : in std_logic; + clkout : in std_logic; + rst : in std_logic + ); +end dataflagff; + +architecture DATAFLAGFF of dataflagff is + COMPONENT dataflagfifo + PORT ( + rst : IN STD_LOGIC; + wr_clk : IN STD_LOGIC; + rd_clk : IN STD_LOGIC; + din : IN STD_LOGIC_VECTOR(0 DOWNTO 0); + wr_en : IN STD_LOGIC; + rd_en : IN STD_LOGIC; + dout : OUT STD_LOGIC_VECTOR(0 DOWNTO 0); + full : OUT STD_LOGIC; + almost_empty : OUT STD_LOGIC; + empty : OUT STD_LOGIC + ); + END COMPONENT; + + signal datain: std_logic; + signal dataout: std_logic; + signal empty: std_logic; + signal almostempty: std_logic; + signal olddatain: std_logic; + signal oldolddatain: std_logic; + signal oldoldolddatain: std_logic; + signal seldatain: std_logic; + + begin + process(rst, clkin) + begin + if(rst='1')then + datain<='0'; + olddatain<='0'; + oldolddatain<='0'; + oldoldolddatain<='0'; + elsif (rising_edge(clkin))then + datain<=eofin and ldin; + olddatain<=datain; + oldolddatain<=olddatain; + oldoldolddatain<=oldolddatain; + end if; + end process; + + dataout<=eofout and ldout; + with clkinrate select + seldatain<=olddatain when '0', + oldoldolddatain when others; + + + thedataflagfifo : dataflagfifo + PORT MAP ( + rst => rst, + wr_clk => clkin, + rd_clk => clkout, + din => "1", + wr_en => seldatain, + rd_en => dataout, + dout => open, + full => open, + almost_empty => almostempty, + empty => empty + ); + datawaiting <= not empty; + moredatawaiting <= not almostempty; + +end DATAFLAGFF; diff --git a/rce/fw-hsio/modules/pixelcore/hdl/dataflagnew.vhd b/rce/fw-hsio/modules/pixelcore/hdl/dataflagnew.vhd new file mode 100644 index 00000000..1a006e75 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/dataflagnew.vhd @@ -0,0 +1,79 @@ +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity dataflagnew is + port ( + eofin : in std_logic; + eofout : in std_logic; + datawaiting: out std_logic; + moredatawaiting: out std_logic; + clkin : in std_logic; + clkout : in std_logic; + rst : in std_logic + ); +end dataflagnew; + +architecture DATAFLAGNEW of dataflagnew is + COMPONENT dataflagfifo + PORT ( + rst : IN STD_LOGIC; + wr_clk : IN STD_LOGIC; + rd_clk : IN STD_LOGIC; + din : IN STD_LOGIC_VECTOR(0 DOWNTO 0); + wr_en : IN STD_LOGIC; + rd_en : IN STD_LOGIC; + dout : OUT STD_LOGIC_VECTOR(0 DOWNTO 0); + full : OUT STD_LOGIC; + almost_empty : OUT STD_LOGIC; + empty : OUT STD_LOGIC + ); + END COMPONENT; + + signal oldeofin: std_logic; + signal oldeofout: std_logic; + signal datain: std_logic; + signal dataout: std_logic; + signal empty: std_logic; + signal almostempty: std_logic; + + begin + + process(rst, clkin) + begin + if(rst='1')then + oldeofin<='0'; + elsif (rising_edge(clkin))then + oldeofin<=eofin; + datain<=eofin and not oldeofin; + end if; + end process; + + process(rst, clkout) + begin + if(rst='1')then + oldeofout<='0'; + elsif (rising_edge(clkout))then + oldeofout<=eofout; + dataout<=eofout and not oldeofout; + end if; + end process; + thedataflagfifo : dataflagfifo + PORT MAP ( + rst => rst, + wr_clk => clkin, + rd_clk => clkout, + din => "1", + wr_en => datain, + rd_en => dataout, + dout => open, + full => open, + almost_empty => almostempty, + empty => empty + ); + datawaiting <= not empty; + moredatawaiting <= not empty and not almostempty; + +end DATAFLAGNEW; diff --git a/rce/fw-hsio/modules/pixelcore/hdl/dec.mif b/rce/fw-hsio/modules/pixelcore/hdl/dec.mif new file mode 100644 index 00000000..14424887 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/dec.mif @@ -0,0 +1,1024 @@ +10101111111111 +10101111111111 +10101111111111 +10101111111100 +10101011111111 +10101011101111 +10101011100000 +10101011100111 +10101011111111 +10101011110000 +10101011111111 +00101011101011 +10101011111000 +00101011101101 +00101011101110 +10001011111111 +10101111111111 +10101111100001 +10101111100010 +00101111110011 +10101111100100 +00101111110101 +00101111110110 +10001111110111 +10101111101000 +00101111111001 +00101111111010 +10001111111011 +00101111111100 +10001111111101 +10001111111110 +10001111111111 +10101011111111 +10101011111110 +10101011111101 +00101011100011 +10101011111011 +00101011100101 +00101011100110 +10001011101000 +10101011110111 +00101011101001 +00101011101010 +10001011100100 +00101011101100 +10001011100010 +10001011100001 +10001011111111 +10101011111111 +00101011110001 +00101011110010 +10001011111000 +00101011110100 +10001011111111 +10001011110000 +10001011111111 +00101011100111 +10001011100000 +10001011101111 +10001011111111 +10001111111100 +10001111111111 +10001111111111 +10001111111111 +10101111111111 +10101111111111 +10101111111111 +10101111111100 +10101011111111 +10101011101111 +10101011100000 +10101011100111 +10101011111111 +10101011110000 +10101011111111 +00100011101011 +10101011111000 +00100011101101 +00100011101110 +10001011111111 +10101111111111 +10101111100001 +10101111100010 +00101111110011 +10101111100100 +00101111110101 +00101111110110 +10000111110111 +10101111101000 +00101111111001 +00101111111010 +10000111111011 +00101111111100 +10000111111101 +10000111111110 +10001111111111 +10101011111111 +10101011111110 +10101011111101 +00101011100011 +10101011111011 +00101011100101 +00101011100110 +10001011101000 +10101011110111 +00101011101001 +00101011101010 +10001011100100 +00101011101100 +10001011100010 +10001011100001 +10001011111111 +10101011111111 +00101011110001 +00101011110010 +10001011111000 +00101011110100 +10001011111111 +10001011110000 +10001011111111 +00101011100111 +10001011100000 +10001011101111 +10001011111111 +10000111111100 +10001111111111 +10001111111111 +10001111111111 +10101100011111 +10101100011111 +10101100011111 +10101100011100 +10101000011111 +10101000001111 +10101000000000 +10101000000111 +10101000011111 +10101000010000 +10101000011111 +00100000001011 +10101000011000 +00100000001101 +00100000001110 +10001000011111 +10101000011111 +10101000000001 +10101000000010 +00100000010011 +10101000000100 +00100000010101 +00100000010110 +10000000010111 +10101000001000 +00100000011001 +00100000011010 +10000000011011 +00100000011100 +10000000011101 +10000000011110 +10001000011111 +10101000011111 +10101000011110 +10101000011101 +00100000000011 +10101000011011 +00100000000101 +00100000000110 +10000000001000 +10101000010111 +00100000001001 +00100000001010 +10000000000100 +00100000001100 +10000000000010 +10000000000001 +10001000011111 +10101000011111 +00100000010001 +00100000010010 +10000000011000 +00100000010100 +10000000011111 +10000000010000 +10001000011111 +00100000000111 +10000000000000 +10000000001111 +10001000011111 +10000100011100 +10001100011111 +10001100011111 +10001100011111 +00101101111111 +00101101111111 +00101101111111 +00100101111100 +00101001111111 +00100001101111 +00100001100000 +10000001100111 +00101001111111 +00100001110000 +00100001111111 +10000001101011 +00100001111000 +10000001101101 +10000001101110 +10001001111111 +00101001111111 +00100001100001 +00100001100010 +10000001110011 +00100001100100 +10000001110101 +10000001110110 +10001001110111 +00100001101000 +10000001111001 +10000001111010 +10001001111011 +10000001111100 +10001001111101 +10001001111110 +10001001111111 +00101001111111 +00100001111110 +00100001111101 +10000001100011 +00100001111011 +10000001100101 +10000001100110 +10001001101000 +00100001110111 +10000001101001 +10000001101010 +10001001100100 +10000001101100 +10001001100010 +10001001100001 +10001001111111 +00101001111111 +10000001110001 +10000001110010 +10001001111000 +10000001110100 +10001001111111 +10001001110000 +10001001111111 +10101001100111 +10001001100000 +10001001101111 +10001001111111 +10001101111100 +10001101111111 +10001101111111 +10001101111111 +10101110011111 +10101110011111 +10101110011111 +10101110011100 +10101010011111 +10101010001111 +10101010000000 +10101010000111 +10101010011111 +10101010010000 +10101010011111 +00100010001011 +10101010011000 +00100010001101 +00100010001110 +10001010011111 +10101010011111 +10101010000001 +10101010000010 +00100010010011 +10101010000100 +00100010010101 +00100010010110 +10000010010111 +10101010001000 +00100010011001 +00100010011010 +10000010011011 +00100010011100 +10000010011101 +10000010011110 +10001010011111 +10101010011111 +10101010011110 +10101010011101 +00100010000011 +10101010011011 +00100010000101 +00100010000110 +10000010001000 +10101010010111 +00100010001001 +00100010001010 +10000010000100 +00100010001100 +10000010000010 +10000010000001 +10001010011111 +10101010011111 +00100010010001 +00100010010010 +10000010011000 +00100010010100 +10000010011111 +10000010010000 +10001010011111 +00100010000111 +10000010000000 +10000010001111 +10001010011111 +10000110011100 +10001110011111 +10001110011111 +10001110011111 +00101101011111 +00101101011111 +00101101011111 +00100101011100 +00101010111111 +00100010101111 +00100010100000 +10000010100111 +00101010111111 +00100010110000 +00100010111111 +01000010101011 +00100010111000 +01000010101101 +01000010101110 +11011010111111 +00101010111111 +00100010100001 +00100010100010 +01000010110011 +00100010100100 +01000010110101 +01000010110110 +11010010110111 +00100010101000 +01000010111001 +01000010111010 +11010010111011 +01000010111100 +11010010111101 +11010010111110 +11011010111111 +00101010111111 +00100010111110 +00100010111101 +01000010100011 +00100010111011 +01000010100101 +01000010100110 +11010010101000 +00100010110111 +01000010101001 +01000010101010 +11010010100100 +01000010101100 +11010010100010 +11010010100001 +11011010111111 +00101010111111 +01000010110001 +01000010110010 +11010010111000 +01000010110100 +11010010111111 +11010010110000 +11011010111111 +01110010100111 +11010010100000 +11010010101111 +11011010111111 +11010110111100 +11011110111111 +11011110111111 +11011110111111 +00101100111111 +00101100111111 +00101100111111 +00100100111100 +00101011011111 +00100011001111 +00100011000000 +10000011000111 +00101011011111 +00100011010000 +00100011011111 +01000011001011 +00100011011000 +01000011001101 +01000011001110 +11011011011111 +00101011011111 +00100011000001 +00100011000010 +01000011010011 +00100011000100 +01000011010101 +01000011010110 +11010011010111 +00100011001000 +01000011011001 +01000011011010 +11010011011011 +01000011011100 +11010011011101 +11010011011110 +11011011011111 +00101011011111 +00100011011110 +00100011011101 +01000011000011 +00100011011011 +01000011000101 +01000011000110 +11010011001000 +00100011010111 +01000011001001 +01000011001010 +11010011000100 +01000011001100 +11010011000010 +11010011000001 +11011011011111 +00101011011111 +01000011010001 +01000011010010 +11010011011000 +01000011010100 +11010011011111 +11010011010000 +11011011011111 +01110011000111 +11010011000000 +11010011001111 +11011011011111 +11010111011100 +11011111011111 +11011111011111 +11011111011111 +01111111111111 +01111111111111 +01111111111111 +01111111111100 +01111011111111 +01110011101111 +01110011100000 +11010011100111 +01111011111111 +01110011110000 +01110011111111 +11010011101011 +01110011111000 +11010011101101 +11010011101110 +11111011111111 +01111011111111 +01110011100001 +01110011100010 +11010011110011 +01110011100100 +11010011110101 +11010011110110 +11111011110111 +01110011101000 +11010011111001 +11010011111010 +11111011111011 +11010011111100 +11111011111101 +11111011111110 +11111011111111 +01111011111111 +01110011111110 +01110011111101 +11010011100011 +01110011111011 +11010011100101 +11010011100110 +11111011101000 +01110011110111 +11010011101001 +11010011101010 +11111011100100 +11010011101100 +11111011100010 +11111011100001 +11111011111111 +01111011111111 +11011011110001 +11011011110010 +11111011111000 +11011011110100 +11111011111111 +11111011110000 +11111011111111 +11111011100111 +11111011100000 +11111011101111 +11111011111111 +11111111111100 +11111111111111 +11111111111111 +11111111111111 +10101111111111 +10101111111111 +10101111111111 +10101111111100 +10101011111111 +10101011101111 +10101011100000 +10101011100111 +10101011111111 +10101011110000 +10101011111111 +00101011101011 +10101011111000 +00101011101101 +00101011101110 +10001011111111 +10101011111111 +10101011100001 +10101011100010 +00100011110011 +10101011100100 +00100011110101 +00100011110110 +10000011110111 +10101011101000 +00100011111001 +00100011111010 +10000011111011 +00100011111100 +10000011111101 +10000011111110 +10001011111111 +10101011111111 +10101011111110 +10101011111101 +00100011100011 +10101011111011 +00100011100101 +00100011100110 +10000011101000 +10101011110111 +00100011101001 +00100011101010 +10000011100100 +00100011101100 +10000011100010 +10000011100001 +10001011111111 +10101011111111 +00100011110001 +00100011110010 +10000011111000 +00100011110100 +10000011111111 +10000011110000 +10001011111111 +00100011100111 +10000011100000 +10000011101111 +10001011111111 +10001111111100 +10001111111111 +10001111111111 +10001111111111 +00101111011111 +00101111011111 +00101111011111 +00100111011100 +00101000111111 +00100000101111 +00100000100000 +10000000100111 +00101000111111 +00100000110000 +00100000111111 +01000000101011 +00100000111000 +01000000101101 +01000000101110 +11011000111111 +00101000111111 +00100000100001 +00100000100010 +01000000110011 +00100000100100 +01000000110101 +01000000110110 +11010000110111 +00100000101000 +01000000111001 +01000000111010 +11010000111011 +01000000111100 +11010000111101 +11010000111110 +11011000111111 +00101000111111 +00100000111110 +00100000111101 +01000000100011 +00100000111011 +01000000100101 +01000000100110 +11010000101000 +00100000110111 +01000000101001 +01000000101010 +11010000100100 +01000000101100 +11010000100010 +11010000100001 +11011000111111 +00101000111111 +01000000110001 +01000000110010 +11010000111000 +01000000110100 +11010000111111 +11010000110000 +11011000111111 +01110000100111 +11010000100000 +11010000101111 +11011000111111 +11010100111100 +11011100111111 +11011100111111 +11011100111111 +00101110111111 +00101110111111 +00101110111111 +00100110111100 +00101001011111 +00100001001111 +00100001000000 +10000001000111 +00101001011111 +00100001010000 +00100001011111 +01000001001011 +00100001011000 +01000001001101 +01000001001110 +11011001011111 +00101001011111 +00100001000001 +00100001000010 +01000001010011 +00100001000100 +01000001010101 +01000001010110 +11010001010111 +00100001001000 +01000001011001 +01000001011010 +11010001011011 +01000001011100 +11010001011101 +11010001011110 +11011001011111 +00101001011111 +00100001011110 +00100001011101 +01000001000011 +00100001011011 +01000001000101 +01000001000110 +11010001001000 +00100001010111 +01000001001001 +01000001001010 +11010001000100 +01000001001100 +11010001000010 +11010001000001 +11011001011111 +00101001011111 +01000001010001 +01000001010010 +11010001011000 +01000001010100 +11010001011111 +11010001010000 +11011001011111 +01110001000111 +11010001000000 +11010001001111 +11011001011111 +11010101011100 +11011101011111 +11011101011111 +11011101011111 +01111110011111 +01111110011111 +01111110011111 +01110110011100 +01111010011111 +01110010001111 +01110010000000 +11010010000111 +01111010011111 +01110010010000 +01110010011111 +11010010001011 +01110010011000 +11010010001101 +11010010001110 +11111010011111 +01111010011111 +01110010000001 +01110010000010 +11010010010011 +01110010000100 +11010010010101 +11010010010110 +11111010010111 +01110010001000 +11010010011001 +11010010011010 +11111010011011 +11010010011100 +11111010011101 +11111010011110 +11111010011111 +01111010011111 +01110010011110 +01110010011101 +11010010000011 +01110010011011 +11010010000101 +11010010000110 +11111010001000 +01110010010111 +11010010001001 +11010010001010 +11111010000100 +11010010001100 +11111010000010 +11111010000001 +11111010011111 +01111010011111 +11010010010001 +11010010010010 +11111010011000 +11010010010100 +11111010011111 +11111010010000 +11111010011111 +11111010000111 +11111010000000 +11111010001111 +11111010011111 +11111110011100 +11111110011111 +11111110011111 +11111110011111 +01111101111111 +01111101111111 +01111101111111 +01111101111100 +01111001111111 +01111001101111 +01111001100000 +11111001100111 +01111001111111 +01111001110000 +01111001111111 +01110001101011 +01111001111000 +01110001101101 +01110001101110 +11011001111111 +01111001111111 +01111001100001 +01111001100010 +01110001110011 +01111001100100 +01110001110101 +01110001110110 +11010001110111 +01111001101000 +01110001111001 +01110001111010 +11010001111011 +01110001111100 +11010001111101 +11010001111110 +11011001111111 +01111001111111 +01111001111110 +01111001111101 +01110001100011 +01111001111011 +01110001100101 +01110001100110 +11010001101000 +01111001110111 +01110001101001 +01110001101010 +11010001100100 +01110001101100 +11010001100010 +11010001100001 +11011001111111 +01111001111111 +01110001110001 +01110001110010 +11010001111000 +01110001110100 +11010001111111 +11010001110000 +11011001111111 +01110001100111 +11010001100000 +11010001101111 +11011001111111 +11010101111100 +11011101111111 +11011101111111 +11011101111111 +01111100011111 +01111100011111 +01111100011111 +01110100011100 +01111000011111 +01110000001111 +01110000000000 +11010000000111 +01111000011111 +01110000010000 +01110000011111 +11010000001011 +01110000011000 +11010000001101 +11010000001110 +11111000011111 +01111000011111 +01110000000001 +01110000000010 +11010000010011 +01110000000100 +11010000010101 +11010000010110 +11111000010111 +01110000001000 +11010000011001 +11010000011010 +11111000011011 +11010000011100 +11111000011101 +11111000011110 +11111000011111 +01111000011111 +01110000011110 +01110000011101 +11010000000011 +01110000011011 +11010000000101 +11010000000110 +11111000001000 +01110000010111 +11010000001001 +11010000001010 +11111000000100 +11010000001100 +11111000000010 +11111000000001 +11111000011111 +01111000011111 +11010000010001 +11010000010010 +11111000011000 +11010000010100 +11111000011111 +11111000010000 +11111000011111 +11111000000111 +11111000000000 +11111000001111 +11111000011111 +11111100011100 +11111100011111 +11111100011111 +11111100011111 +01111111111111 +01111111111111 +01111111111111 +01110111111100 +01111011111111 +01111011101111 +01111011100000 +11011011100111 +01111011111111 +01111011110000 +01111011111111 +11011011101011 +01111011111000 +11011011101101 +11011011101110 +11111011111111 +01111011111111 +01111011100001 +01111011100010 +11011011110011 +01111011100100 +11011011110101 +11011011110110 +11111011110111 +01111011101000 +11011011111001 +11011011111010 +11111011111011 +11011011111100 +11111011111101 +11111011111110 +11111011111111 +01111111111111 +01110111111110 +01110111111101 +11011111100011 +01110111111011 +11011111100101 +11011111100110 +11111111101000 +01110111110111 +11011111101001 +11011111101010 +11111111100100 +11011111101100 +11111111100010 +11111111100001 +11111111111111 +01111011111111 +11010011110001 +11010011110010 +11111011111000 +11010011110100 +11111011111111 +11111011110000 +11111011111111 +11111011100111 +11111011100000 +11111011101111 +11111011111111 +11111111111100 +11111111111111 +11111111111111 +11111111111111 +01111111111111 +01111111111111 +01111111111111 +01111111111100 +01111011111111 +01111011101111 +01111011100000 +11011011100111 +01111011111111 +01111011110000 +01111011111111 +11011011101011 +01111011111000 +11011011101101 +11011011101110 +11111011111111 +01111011111111 +01111011100001 +01111011100010 +11011011110011 +01111011100100 +11011011110101 +11011011110110 +11111011110111 +01111011101000 +11011011111001 +11011011111010 +11111011111011 +11011011111100 +11111011111101 +11111011111110 +11111011111111 +01111111111111 +01111111111110 +01111111111101 +11011111100011 +01111111111011 +11011111100101 +11011111100110 +11111111101000 +01111111110111 +11011111101001 +11011111101010 +11111111100100 +11011111101100 +11111111100010 +11111111100001 +11111111111111 +01111011111111 +11011011110001 +11011011110010 +11111011111000 +11011011110100 +11111011111111 +11111011110000 +11111011111111 +11111011100111 +11111011100000 +11111011101111 +11111011111111 +11111111111100 +11111111111111 +11111111111111 +11111111111111 diff --git a/rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_bram.vhd b/rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_bram.vhd new file mode 100644 index 00000000..b0f0adb5 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_bram.vhd @@ -0,0 +1,337 @@ +--------------------------------------------------------------------------- +-- +-- Module : decode_8b10b_bram.vhd +-- +-- Version : 1.1 +-- +-- Last Update : 2008-10-31 +-- +-- Project : 8b/10b Decoder Reference Design +-- +-- Description : Block memory-based Decoder for decoding 8b/10b encoded symbols +-- +-- Company : Xilinx, Inc. +-- +-- DISCLAIMER OF LIABILITY +-- +-- This file contains proprietary and confidential information of +-- Xilinx, Inc. ("Xilinx"), that is distributed under a license +-- from Xilinx, and may be used, copied and/or disclosed only +-- pursuant to the terms of a valid license agreement with Xilinx. +-- +-- XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION +-- ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +-- EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT +-- LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT, +-- MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx +-- does not warrant that functions included in the Materials will +-- meet the requirements of Licensee, or that the operation of the +-- Materials will be uninterrupted or error-free, or that defects +-- in the Materials will be corrected. Furthermore, Xilinx does +-- not warrant or make any representations regarding use, or the +-- results of the use, of the Materials in terms of correctness, +-- accuracy, reliability or otherwise. +-- +-- Xilinx products are not designed or intended to be fail-safe, +-- or for use in any application requiring fail-safe performance, +-- such as life-support or safety devices or systems, Class III +-- medical devices, nuclear facilities, applications related to +-- the deployment of airbags, or any other applications that could +-- lead to death, personal injury or severe property or +-- environmental damage (individually and collectively, "critical +-- applications"). Customer assumes the sole risk and liability +-- of any use of Xilinx products in critical applications, +-- subject only to applicable laws and regulations governing +-- limitations on product liability. +-- +-- Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2008 Xilinx, Inc. +-- All rights reserved. +-- +-- This disclaimer and copyright notice must be retained as part +-- of this file at all times. +-- +------------------------------------------------------------------------------- +-- +-- History +-- +-- Date Version Description +-- +-- 10/31/2008 1.1 Initial release +-- +------------------------------------------------------------------------------- + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE IEEE.std_logic_arith.ALL; +USE IEEE.std_logic_unsigned.ALL; +USE STD.textio.ALL; -- required to initialize bram from .mif + + +LIBRARY decode_8b10b; +USE work.decode_8b10b_pkg.ALL; + +----------------------------------------------------------------------------- +-- Entity Declaration +----------------------------------------------------------------------------- +ENTITY decode_8b10b_bram IS + GENERIC ( + C_ELABORATION_DIR : STRING := "./"; + C_HAS_BPORTS : INTEGER := 0; + C_HAS_DISP_IN : INTEGER := 0; + C_HAS_DISP_IN_B : INTEGER := 0; + C_HAS_DISP_ERR : INTEGER := 0; + C_HAS_DISP_ERR_B : INTEGER := 0; + C_HAS_RUN_DISP : INTEGER := 0; + C_HAS_RUN_DISP_B : INTEGER := 0; + C_HAS_SYM_DISP : INTEGER := 0; + C_HAS_SYM_DISP_B : INTEGER := 0; + C_HAS_ND : INTEGER := 0; + C_HAS_ND_B : INTEGER := 0; + C_SINIT_DOUT : STRING := "00000000"; + C_SINIT_DOUT_B : STRING := "00000000"; + C_SINIT_KOUT : INTEGER := 0; + C_SINIT_KOUT_B : INTEGER := 0; + C_SINIT_RUN_DISP : INTEGER := 0; + C_SINIT_RUN_DISP_B : INTEGER := 0 + ); + + PORT ( + CLK : IN STD_LOGIC := '0'; + DIN : IN STD_LOGIC_VECTOR(9 DOWNTO 0) := (OTHERS => '0'); + DOUT : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) ; + KOUT : OUT STD_LOGIC ; + + CE : IN STD_LOGIC := '0'; + CE_B : IN STD_LOGIC := '0'; + CLK_B : IN STD_LOGIC := '0'; + DIN_B : IN STD_LOGIC_VECTOR(9 DOWNTO 0) := "0000000000"; + DISP_IN : IN STD_LOGIC := '0'; + DISP_IN_B : IN STD_LOGIC := '0'; + SINIT : IN STD_LOGIC := '0'; + SINIT_B : IN STD_LOGIC := '0'; + CODE_ERR : OUT STD_LOGIC := '0'; + CODE_ERR_B : OUT STD_LOGIC := '0'; + DISP_ERR : OUT STD_LOGIC := '0'; + DISP_ERR_B : OUT STD_LOGIC := '0'; + DOUT_B : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) ; + KOUT_B : OUT STD_LOGIC ; + ND : OUT STD_LOGIC := '0'; + ND_B : OUT STD_LOGIC := '0'; + RUN_DISP : OUT STD_LOGIC ; + RUN_DISP_B : OUT STD_LOGIC ; + SYM_DISP : OUT STD_LOGIC_VECTOR(1 DOWNTO 0) ; + SYM_DISP_B : OUT STD_LOGIC_VECTOR(1 DOWNTO 0) + ); + +END decode_8b10b_bram; + + +----------------------------------------------------------------------------- +-- Architecture +----------------------------------------------------------------------------- +ARCHITECTURE xilinx OF decode_8b10b_bram IS + +----------------------------------------------------------------------------- +-- .MIF file support +----------------------------------------------------------------------------- + -- Specify relative path for .mif file + CONSTANT mif_file_name : STRING := C_ELABORATION_DIR & "dec.mif"; + + -- Initialize inferred ROM from mif file + TYPE RomType IS ARRAY(0 TO 1023) OF BIT_VECTOR(13 DOWNTO 0); + IMPURE FUNCTION InitRomFromFile (RomFileName : IN STRING) RETURN RomType IS + FILE RomFile : TEXT OPEN READ_MODE IS RomFileName; + VARIABLE RomFileLine : LINE; + VARIABLE ROM : RomType; + BEGIN + FOR I IN RomType'range LOOP + READLINE (RomFile, RomFileLine); + for J in 13 downto 0 LOOP + READ (RomFileLine, ROM(I)(J)); + END LOOP; + end LOOP; + RETURN ROM; + END FUNCTION; + SIGNAL ROM : RomType := InitRomFromFile(mif_file_name); + +----------------------------------------------------------------------------- +-- Constant initialization values for internal signals ROM_data(_b) +----------------------------------------------------------------------------- + CONSTANT INIT_DATA : STRING := + concat_sinit(C_SINIT_RUN_DISP,C_SINIT_KOUT, C_SINIT_DOUT); + CONSTANT INIT_DATA_B : STRING := + concat_sinit(C_SINIT_RUN_DISP_B,C_SINIT_KOUT_B, C_SINIT_DOUT_B); + +----------------------------------------------------------------------------- +-- Signal Declarations +----------------------------------------------------------------------------- + SIGNAL dout_i : STD_LOGIC_VECTOR(7 DOWNTO 0) := + str_to_slv(C_SINIT_DOUT,8); + SIGNAL kout_i : STD_LOGIC := + bint_2_sl(C_SINIT_KOUT); + SIGNAL dout_b_i : STD_LOGIC_VECTOR(7 DOWNTO 0) := + str_to_slv(C_SINIT_DOUT_B,8); + SIGNAL kout_b_i : STD_LOGIC := + bint_2_sl(C_SINIT_KOUT_B); + SIGNAL run_disp_i : STD_LOGIC := + bint_2_sl(C_SINIT_RUN_DISP); + SIGNAL run_disp_b_i : STD_LOGIC := + bint_2_sl(C_SINIT_RUN_DISP_B); + SIGNAL sym_disp_i : STD_LOGIC_VECTOR(1 DOWNTO 0) := + conv_std_logic_vector(C_SINIT_RUN_DISP,2); + SIGNAL sym_disp_b_i : STD_LOGIC_VECTOR(1 DOWNTO 0) := + conv_std_logic_vector(C_SINIT_RUN_DISP_B,2); + +--Internal signals tied to the 14x1k block memory---------------------------- + SIGNAL ROM_address : STD_LOGIC_VECTOR(9 DOWNTO 0) := (OTHERS => '0'); + SIGNAL ROM_data : STD_LOGIC_VECTOR(13 DOWNTO 0) := + str_to_slv(INIT_DATA, 14); + +----------------------------------------------------------------------------- +-- BEGIN ARCHITECTURE +----------------------------------------------------------------------------- +BEGIN + + -- Map internal signals to outputs + DOUT <= dout_i; + KOUT <= kout_i; + DOUT_B <= dout_b_i; + KOUT_B <= kout_b_i; + RUN_DISP <= run_disp_i; + RUN_DISP_B <= run_disp_b_i; + SYM_DISP <= sym_disp_i; + SYM_DISP_B <= sym_disp_b_i; + +----------------------------------------------------------------------------- +-- Decoder A +----------------------------------------------------------------------------- + + ROM_address <= DIN; + PROCESS (CLK) + BEGIN + IF (CLK'event AND CLK = '1') THEN + IF (CE = '1') THEN + IF (SINIT = '1') THEN + ROM_data <= str_to_slv(INIT_DATA, 14) AFTER TFF; + ELSE + ROM_data <= to_stdlogicvector(ROM(conv_integer(ROM_address))) AFTER TFF; + END IF; + END IF; + END IF; + END PROCESS; + -- Map ROM data into dout, kout, and code_err outputs + dout_i <= ROM_data(7 DOWNTO 0); + kout_i <= ROM_data(8); + CODE_ERR <= ROM_data(9); + + + ----------------------------------------------------------------------------- + -- Instantiate disparity logic block for Decoder A + ----------------------------------------------------------------------------- + dla : ENTITY decode_8b10b_disp + GENERIC MAP( + C_SINIT_DOUT => C_SINIT_DOUT, + C_SINIT_RUN_DISP => C_SINIT_RUN_DISP, + C_HAS_DISP_IN => C_HAS_DISP_IN, + C_HAS_DISP_ERR => C_HAS_DISP_ERR, + C_HAS_RUN_DISP => C_HAS_RUN_DISP, + C_HAS_SYM_DISP => C_HAS_SYM_DISP + ) + PORT MAP( + SINIT => SINIT, + CE => CE, + CLK => CLK, + SYM_DISP => ROM_data(13 DOWNTO 10), + DISP_IN => DISP_IN, + RUN_DISP => run_disp_i, + DISP_ERR => DISP_ERR, + USER_SYM_DISP => sym_disp_i + ); + + -- create ND output + gndr : IF (C_HAS_ND = 1) GENERATE + PROCESS (CLK) + BEGIN + IF (CLK'event AND CLK = '1') THEN + IF ((SINIT = '1') AND (CE = '1')) THEN + ND <= '0' AFTER TFF; + ELSE + ND <= CE AFTER TFF; + END IF; + END IF; + END PROCESS; + END GENERATE gndr; + + +------------------------------------------------------------------------------- +-- Generate Decoder B +------------------------------------------------------------------------------- + gdp : IF (C_HAS_BPORTS=1) GENERATE + --Internal signals tied to the 14x1k block memory (B)---------------------- + SIGNAL ROM_address_b : STD_LOGIC_VECTOR(9 DOWNTO 0) := (OTHERS => '0'); + SIGNAL ROM_data_b : STD_LOGIC_VECTOR(13 DOWNTO 0) := + str_to_slv(INIT_DATA_B, 14); + + BEGIN + ROM_address_b <= DIN_B; + PROCESS (CLK_B) + BEGIN + IF (CLK_B'event AND CLK_B = '1') THEN + IF (CE_B = '1') THEN + IF (SINIT_B = '1') THEN + ROM_data_b <= str_to_slv(INIT_DATA_B, 14) AFTER TFF; + ELSE + ROM_data_b <= to_stdlogicvector(ROM(conv_integer(ROM_address_b))) + AFTER TFF; + END IF; + END IF; + END IF; + END PROCESS; + -- Map ROM_data_b into dout_b, kout_b, and code_err_b outputs + dout_b_i <= ROM_data_b(7 DOWNTO 0); + kout_b_i <= ROM_data_b(8); + CODE_ERR_B <= ROM_data_b(9); + + ----------------------------------------------------------------------------- + -- Instantiate disparity logic block for Decoder B + ----------------------------------------------------------------------------- + dlb : ENTITY decode_8b10b_disp + GENERIC MAP( + C_SINIT_DOUT => C_SINIT_DOUT_B, + C_SINIT_RUN_DISP => C_SINIT_RUN_DISP_B, + C_HAS_DISP_IN => C_HAS_DISP_IN_B, + C_HAS_DISP_ERR => C_HAS_DISP_ERR_B, + C_HAS_RUN_DISP => C_HAS_RUN_DISP_B, + C_HAS_SYM_DISP => C_HAS_SYM_DISP_B + ) + PORT MAP( + SINIT => SINIT_B, + CE => CE_B, + CLK => CLK_B, + SYM_DISP => ROM_data_b(13 DOWNTO 10), + DISP_IN => DISP_IN_B, + RUN_DISP => run_disp_b_i, + DISP_ERR => DISP_ERR_B, + USER_SYM_DISP => sym_disp_b_i + ); + + -- create ND_B output + gndbr : IF (C_HAS_ND_B = 1) GENERATE + PROCESS (CLK_B) + BEGIN + IF (CLK_B'event AND CLK_B = '1') THEN + IF ((SINIT_B = '1') AND (CE_B = '1')) THEN + ND_B <= '0' AFTER TFF; + ELSE + ND_B <= CE_B AFTER TFF; + END IF; + END IF; + END PROCESS; + END GENERATE gndbr; + + END GENERATE gdp; + +END xilinx; + + + diff --git a/rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_disp.vhd b/rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_disp.vhd new file mode 100644 index 00000000..9753ec44 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_disp.vhd @@ -0,0 +1,207 @@ +--------------------------------------------------------------------------- +-- +-- Module : decode_8b10b_disp.vhd +-- +-- Version : 1.1 +-- +-- Last Update : 2008-10-31 +-- +-- Project : 8b/10b Decoder Reference Design +-- +-- Description : Block memory-based Decoder disparity logic +-- +-- Company : Xilinx, Inc. +-- +-- DISCLAIMER OF LIABILITY +-- +-- This file contains proprietary and confidential information of +-- Xilinx, Inc. ("Xilinx"), that is distributed under a license +-- from Xilinx, and may be used, copied and/or disclosed only +-- pursuant to the terms of a valid license agreement with Xilinx. +-- +-- XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION +-- ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +-- EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT +-- LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT, +-- MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx +-- does not warrant that functions included in the Materials will +-- meet the requirements of Licensee, or that the operation of the +-- Materials will be uninterrupted or error-free, or that defects +-- in the Materials will be corrected. Furthermore, Xilinx does +-- not warrant or make any representations regarding use, or the +-- results of the use, of the Materials in terms of correctness, +-- accuracy, reliability or otherwise. +-- +-- Xilinx products are not designed or intended to be fail-safe, +-- or for use in any application requiring fail-safe performance, +-- such as life-support or safety devices or systems, Class III +-- medical devices, nuclear facilities, applications related to +-- the deployment of airbags, or any other applications that could +-- lead to death, personal injury or severe property or +-- environmental damage (individually and collectively, "critical +-- applications"). Customer assumes the sole risk and liability +-- of any use of Xilinx products in critical applications, +-- subject only to applicable laws and regulations governing +-- limitations on product liability. +-- +-- Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2008 Xilinx, Inc. +-- All rights reserved. +-- +-- This disclaimer and copyright notice must be retained as part +-- of this file at all times. +-- +------------------------------------------------------------------------------- +-- +-- History +-- +-- Date Version Description +-- +-- 10/31/2008 1.1 Initial release +-- +------------------------------------------------------------------------------- + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; + +LIBRARY decode_8b10b; +USE work.decode_8b10b_pkg.ALL; + +------------------------------------------------------------------------------ +--Entity Declaration +------------------------------------------------------------------------------ +ENTITY decode_8b10b_disp IS + GENERIC( + C_SINIT_DOUT : STRING := "00000000"; + C_SINIT_RUN_DISP : INTEGER := 0; + C_HAS_DISP_IN : INTEGER := 0; + C_HAS_DISP_ERR : INTEGER := 0; + C_HAS_RUN_DISP : INTEGER := 0; + C_HAS_SYM_DISP : INTEGER := 0 + ); + PORT( + CE : IN STD_LOGIC := '0'; + CLK : IN STD_LOGIC := '0'; + SINIT : IN STD_LOGIC := '0'; + SYM_DISP : IN STD_LOGIC_VECTOR(3 DOWNTO 0) := (OTHERS => '0'); + DISP_IN : IN STD_LOGIC := '0'; + RUN_DISP : OUT STD_LOGIC := '0'; + DISP_ERR : OUT STD_LOGIC := '0'; + USER_SYM_DISP : OUT STD_LOGIC_VECTOR(1 DOWNTO 0) := (OTHERS => '0') + ); +END decode_8b10b_disp; + + +------------------------------------------------------------------------------ +-- Architecture +------------------------------------------------------------------------------ +ARCHITECTURE xilinx OF decode_8b10b_disp IS + +---------------------------------------------------------------------------- +-- Signal Declarations +---------------------------------------------------------------------------- + SIGNAL run_disp_q : STD_LOGIC := '0'; + SIGNAL run_disp_d : STD_LOGIC := '0'; + SIGNAL disp_in_q : STD_LOGIC := '0'; + SIGNAL disp_err_i : STD_LOGIC := '0'; + +------------------------------------------------------------------------------- +-- Begin Architecture +------------------------------------------------------------------------------- +BEGIN + + gmndi : IF (C_HAS_DISP_IN/=1 AND (C_HAS_RUN_DISP = 1 OR + C_HAS_SYM_DISP = 1 OR + C_HAS_DISP_ERR = 1)) GENERATE + -- store the current running disparity in run_disp_q as a mux selector for + -- the next code's run_disp and disp_err + PROCESS (CLK) + BEGIN + IF (CLK'event AND CLK='1') THEN + IF (CE = '1') THEN + IF (SINIT = '1') THEN + run_disp_q <= bint_2_sl(C_SINIT_RUN_DISP) AFTER TFF; + ELSE + run_disp_q <= run_disp_d AFTER TFF; + END IF; + END IF; + END IF; + END PROCESS; + + -- mux the sym_disp bus and decode it into disp_err and run_disp + gde1 : IF (C_HAS_DISP_ERR = 1 OR C_HAS_SYM_DISP = 1) GENERATE + PROCESS (run_disp_q, SYM_DISP) + BEGIN + IF (run_disp_q = '1') THEN + disp_err_i <= SYM_DISP(3); + ELSE + disp_err_i <= SYM_DISP(1); + END IF; + END PROCESS; + END GENERATE gde1; + + grd1 : IF (C_HAS_RUN_DISP = 1 OR C_HAS_SYM_DISP = 1 OR + C_HAS_DISP_ERR = 1) GENERATE + PROCESS (run_disp_q, SYM_DISP) + BEGIN + IF (run_disp_q = '1') THEN + run_disp_d <= SYM_DISP(2); + ELSE + run_disp_d <= SYM_DISP(0); + END IF; + END PROCESS; + END GENERATE grd1; + END GENERATE gmndi; + + gmdi: IF (C_HAS_DISP_IN = 1 AND (C_HAS_RUN_DISP = 1 OR + C_HAS_SYM_DISP = 1 OR + C_HAS_DISP_ERR = 1)) GENERATE + -- use the current disp_in as a mux selector for the next code's run_disp + -- and disp_err + PROCESS (CLK) + BEGIN + IF (CLK'event AND CLK='1') THEN + IF (CE = '1') THEN + IF (SINIT = '1') THEN + disp_in_q <= bint_2_sl(C_SINIT_RUN_DISP) AFTER TFF; + ELSE + disp_in_q <= DISP_IN AFTER TFF; + END IF; + END IF; + END IF; + END PROCESS; + + -- mux the sym_disp bus and decode it into disp_err and run_disp + gde2 : IF (C_HAS_DISP_ERR = 1 OR C_HAS_SYM_DISP = 1) GENERATE + PROCESS (disp_in_q, SYM_DISP) + BEGIN + IF (disp_in_q = '1') THEN + disp_err_i <= SYM_DISP(3); + ELSE + disp_err_i <= SYM_DISP(1); + END IF; + END PROCESS; + END GENERATE gde2; + + grd2 : IF (C_HAS_RUN_DISP = 1 OR C_HAS_SYM_DISP = 1) GENERATE + PROCESS (disp_in_q, SYM_DISP) + BEGIN + IF (disp_in_q = '1') THEN + run_disp_d <= SYM_DISP(2); + ELSE + run_disp_d <= SYM_DISP(0); + END IF; + END PROCESS; + END GENERATE grd2; + END GENERATE gmdi; + +-- map internal signals to outputs + DISP_ERR <= disp_err_i; + RUN_DISP <= run_disp_d; + USER_SYM_DISP(1) <= disp_err_i; + USER_SYM_DISP(0) <= run_disp_d; + +END xilinx; + + + + diff --git a/rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_lut.vhd b/rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_lut.vhd new file mode 100644 index 00000000..a419a55c --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_lut.vhd @@ -0,0 +1,197 @@ +--------------------------------------------------------------------------- +-- +-- Module : decode_8b10b_lut.vhd +-- +-- Version : 1.1 +-- +-- Last Update : 2008-10-31 +-- +-- Project : 8b/10b Decoder Reference Design +-- +-- Description : LUT-based Decoder for decoding 8b/10b encoded symbols +-- +-- Company : Xilinx, Inc. +-- +-- DISCLAIMER OF LIABILITY +-- +-- This file contains proprietary and confidential information of +-- Xilinx, Inc. ("Xilinx"), that is distributed under a license +-- from Xilinx, and may be used, copied and/or disclosed only +-- pursuant to the terms of a valid license agreement with Xilinx. +-- +-- XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION +-- ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +-- EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT +-- LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT, +-- MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx +-- does not warrant that functions included in the Materials will +-- meet the requirements of Licensee, or that the operation of the +-- Materials will be uninterrupted or error-free, or that defects +-- in the Materials will be corrected. Furthermore, Xilinx does +-- not warrant or make any representations regarding use, or the +-- results of the use, of the Materials in terms of correctness, +-- accuracy, reliability or otherwise. +-- +-- Xilinx products are not designed or intended to be fail-safe, +-- or for use in any application requiring fail-safe performance, +-- such as life-support or safety devices or systems, Class III +-- medical devices, nuclear facilities, applications related to +-- the deployment of airbags, or any other applications that could +-- lead to death, personal injury or severe property or +-- environmental damage (individually and collectively, "critical +-- applications"). Customer assumes the sole risk and liability +-- of any use of Xilinx products in critical applications, +-- subject only to applicable laws and regulations governing +-- limitations on product liability. +-- +-- Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2008 Xilinx, Inc. +-- All rights reserved. +-- +-- This disclaimer and copyright notice must be retained as part +-- of this file at all times. +-- +------------------------------------------------------------------------------- +-- +-- History +-- +-- Date Version Description +-- +-- 10/31/2008 1.1 Initial release +-- +------------------------------------------------------------------------------- + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; + +LIBRARY decode_8b10b; + +----------------------------------------------------------------------------- +-- Entity Declaration +----------------------------------------------------------------------------- +ENTITY decode_8b10b_lut IS + GENERIC ( + C_HAS_BPORTS : INTEGER := 0; + C_HAS_CODE_ERR : INTEGER := 0; + C_HAS_CODE_ERR_B : INTEGER := 0; + C_HAS_DISP_ERR : INTEGER := 0; + C_HAS_DISP_ERR_B : INTEGER := 0; + C_HAS_DISP_IN : INTEGER := 0; + C_HAS_DISP_IN_B : INTEGER := 0; + C_HAS_ND : INTEGER := 0; + C_HAS_ND_B : INTEGER := 0; + C_HAS_SYM_DISP : INTEGER := 0; + C_HAS_SYM_DISP_B : INTEGER := 0; + C_HAS_RUN_DISP : INTEGER := 0; + C_HAS_RUN_DISP_B : INTEGER := 0; + C_SINIT_DOUT : STRING := "00000000"; + C_SINIT_DOUT_B : STRING := "00000000"; + C_SINIT_KOUT : INTEGER := 0; + C_SINIT_KOUT_B : INTEGER := 0; + C_SINIT_RUN_DISP : INTEGER := 0; + C_SINIT_RUN_DISP_B : INTEGER := 0 + ); + PORT ( + CLK : IN STD_LOGIC := '0'; + DIN : IN STD_LOGIC_VECTOR(9 DOWNTO 0) := (OTHERS => '0'); + DOUT : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) ; + KOUT : OUT STD_LOGIC ; + + CE : IN STD_LOGIC := '0'; + CE_B : IN STD_LOGIC := '0'; + CLK_B : IN STD_LOGIC := '0'; + DIN_B : IN STD_LOGIC_VECTOR(9 DOWNTO 0) := (OTHERS => '0'); + DISP_IN : IN STD_LOGIC := '0'; + DISP_IN_B : IN STD_LOGIC := '0'; + SINIT : IN STD_LOGIC := '0'; + SINIT_B : IN STD_LOGIC := '0'; + CODE_ERR : OUT STD_LOGIC := '0'; + CODE_ERR_B : OUT STD_LOGIC := '0'; + DISP_ERR : OUT STD_LOGIC := '0'; + DISP_ERR_B : OUT STD_LOGIC := '0'; + DOUT_B : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) ; + KOUT_B : OUT STD_LOGIC ; + ND : OUT STD_LOGIC := '0'; + ND_B : OUT STD_LOGIC := '0'; + RUN_DISP : OUT STD_LOGIC ; + RUN_DISP_B : OUT STD_LOGIC ; + SYM_DISP : OUT STD_LOGIC_VECTOR(1 DOWNTO 0) ; + SYM_DISP_B : OUT STD_LOGIC_VECTOR(1 DOWNTO 0) + ); + +END decode_8b10b_lut; + +------------------------------------------------------------------------------- +-- Architecture +------------------------------------------------------------------------------- +ARCHITECTURE xilinx OF decode_8b10b_lut IS + +------------------------------------------------------------------------------- +-- Begin Architecture +------------------------------------------------------------------------------- +BEGIN + + ----Instantiate the first decoder (A decoder)-------------------------------- + deca : ENTITY decode_8b10b_lut_base + GENERIC MAP ( + C_HAS_CODE_ERR => C_HAS_CODE_ERR, + C_HAS_DISP_ERR => C_HAS_DISP_ERR, + C_HAS_DISP_IN => C_HAS_DISP_IN, + C_HAS_ND => C_HAS_ND, + C_HAS_SYM_DISP => C_HAS_SYM_DISP, + C_HAS_RUN_DISP => C_HAS_RUN_DISP, + C_SINIT_DOUT => C_SINIT_DOUT, + C_SINIT_KOUT => C_SINIT_KOUT, + C_SINIT_RUN_DISP => C_SINIT_RUN_DISP + ) + PORT MAP ( + CLK => CLK, + DIN => DIN, + DOUT => DOUT, + KOUT => KOUT, + + CE => CE, + DISP_IN => DISP_IN, + SINIT => SINIT, + CODE_ERR => CODE_ERR, + DISP_ERR => DISP_ERR, + ND => ND, + RUN_DISP => RUN_DISP, + SYM_DISP => SYM_DISP + ); + + + + gdecb : IF (C_HAS_BPORTS=1) GENERATE + ----Instantiate second decoder (B decoder, only if bports are present)------ + decb : ENTITY decode_8b10b_lut_base + GENERIC MAP ( + C_HAS_CODE_ERR => C_HAS_CODE_ERR_B, + C_HAS_DISP_ERR => C_HAS_DISP_ERR_B, + C_HAS_DISP_IN => C_HAS_DISP_IN_B, + C_HAS_ND => C_HAS_ND_B, + C_HAS_SYM_DISP => C_HAS_SYM_DISP_B, + C_HAS_RUN_DISP => C_HAS_RUN_DISP_B, + C_SINIT_DOUT => C_SINIT_DOUT_B, + C_SINIT_KOUT => C_SINIT_KOUT_B, + C_SINIT_RUN_DISP => C_SINIT_RUN_DISP_B + ) + PORT MAP ( + CLK => CLK_B, + DIN => DIN_B, + DOUT => DOUT_B, + KOUT => KOUT_B, + + CE => CE_B, + DISP_IN => DISP_IN_B, + SINIT => SINIT_B, + CODE_ERR => CODE_ERR_B, + DISP_ERR => DISP_ERR_B, + ND => ND_B, + RUN_DISP => RUN_DISP_B, + SYM_DISP => SYM_DISP_B + ); + END GENERATE gdecb; + +END xilinx ; + + diff --git a/rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_lut_base.vhd b/rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_lut_base.vhd new file mode 100644 index 00000000..f4de593b --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_lut_base.vhd @@ -0,0 +1,801 @@ +--------------------------------------------------------------------------- +-- +-- Module : decode_8b10b_lut_base.vhd +-- +-- Version : 1.1 +-- +-- Last Update : 2008-10-31 +-- +-- Project : 8b/10b Decoder Reference Design +-- +-- Description : LUT-based Single-port Base Decoder for decoding 8b/10b +-- encoded symbols +-- +-- Company : Xilinx, Inc. +-- +-- DISCLAIMER OF LIABILITY +-- +-- This file contains proprietary and confidential information of +-- Xilinx, Inc. ("Xilinx"), that is distributed under a license +-- from Xilinx, and may be used, copied and/or disclosed only +-- pursuant to the terms of a valid license agreement with Xilinx. +-- +-- XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION +-- ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +-- EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT +-- LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT, +-- MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx +-- does not warrant that functions included in the Materials will +-- meet the requirements of Licensee, or that the operation of the +-- Materials will be uninterrupted or error-free, or that defects +-- in the Materials will be corrected. Furthermore, Xilinx does +-- not warrant or make any representations regarding use, or the +-- results of the use, of the Materials in terms of correctness, +-- accuracy, reliability or otherwise. +-- +-- Xilinx products are not designed or intended to be fail-safe, +-- or for use in any application requiring fail-safe performance, +-- such as life-support or safety devices or systems, Class III +-- medical devices, nuclear facilities, applications related to +-- the deployment of airbags, or any other applications that could +-- lead to death, personal injury or severe property or +-- environmental damage (individually and collectively, "critical +-- applications"). Customer assumes the sole risk and liability +-- of any use of Xilinx products in critical applications, +-- subject only to applicable laws and regulations governing +-- limitations on product liability. +-- +-- Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2008 Xilinx, Inc. +-- All rights reserved. +-- +-- This disclaimer and copyright notice must be retained as part +-- of this file at all times. +-- +------------------------------------------------------------------------------- +-- +-- History +-- +-- Date Version Description +-- +-- 10/31/2008 1.1 Initial release +-- +------------------------------------------------------------------------------- + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE IEEE.std_logic_arith.ALL; + +LIBRARY decode_8b10b; +USE work.decode_8b10b_pkg.ALL; + +------------------------------------------------------------------------------- +-- Entity Declaration +------------------------------------------------------------------------------- +ENTITY decode_8b10b_lut_base IS + GENERIC ( + C_HAS_CODE_ERR : INTEGER := 0; + C_HAS_DISP_ERR : INTEGER := 0; + C_HAS_DISP_IN : INTEGER := 0; + C_HAS_ND : INTEGER := 0; + C_HAS_SYM_DISP : INTEGER := 0; + C_HAS_RUN_DISP : INTEGER := 0; + C_SINIT_DOUT : STRING := "00000000"; + C_SINIT_KOUT : INTEGER := 0; + C_SINIT_RUN_DISP : INTEGER := 0 + ); + PORT ( + CLK : IN STD_LOGIC := '0'; + DIN : IN STD_LOGIC_VECTOR(9 DOWNTO 0) := (OTHERS => '0'); + DOUT : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) ; + KOUT : OUT STD_LOGIC ; + + CE : IN STD_LOGIC := '0'; + DISP_IN : IN STD_LOGIC := '0'; + SINIT : IN STD_LOGIC := '0'; + CODE_ERR : OUT STD_LOGIC := '0'; + DISP_ERR : OUT STD_LOGIC := '0'; + ND : OUT STD_LOGIC := '0'; + RUN_DISP : OUT STD_LOGIC ; + SYM_DISP : OUT STD_LOGIC_VECTOR(1 DOWNTO 0) + ); +END decode_8b10b_lut_base; + +------------------------------------------------------------------------------- +-- Architecture +------------------------------------------------------------------------------- +ARCHITECTURE xilinx OF decode_8b10b_lut_base IS + + ----------------------------------------------------------------------------- + -- Type Declarations + ----------------------------------------------------------------------------- + TYPE disparity IS (neg, pos, zero, invalid, specneg, specpos) ; + + ----------------------------------------------------------------------------- + -- Constant Declarations + ----------------------------------------------------------------------------- + -- set the default decoder output for invalid codes + CONSTANT DEFAULTB5 : STD_LOGIC_VECTOR(4 DOWNTO 0) := "11111" ; + CONSTANT DEFAULTB3 : STD_LOGIC_VECTOR(2 DOWNTO 0) := "111" ; + + ----------------------------------------------------------------------------- + -- Signal Declarations + ----------------------------------------------------------------------------- + SIGNAL dout_i : STD_LOGIC_VECTOR(7 DOWNTO 0) := + str_to_slv(C_SINIT_DOUT,8); + SIGNAL kout_i : STD_LOGIC := + bint_2_sl(C_SINIT_KOUT); + SIGNAL run_disp_i : STD_LOGIC := + bint_2_sl(C_SINIT_RUN_DISP); + SIGNAL sym_disp_i : STD_LOGIC_VECTOR(1 DOWNTO 0) := + conv_std_logic_vector(C_SINIT_RUN_DISP,2); + SIGNAL code_err_i : STD_LOGIC := '0'; + + SIGNAL symrd : STD_LOGIC_VECTOR(3 DOWNTO 0); + SIGNAL b6_disp : disparity := zero; + SIGNAL b4_disp : disparity := zero; + + SIGNAL b5 : STD_LOGIC_VECTOR(4 DOWNTO 0) := DEFAULTB5; + SIGNAL b3 : STD_LOGIC_VECTOR(7 DOWNTO 5) := DEFAULTB3; + SIGNAL k : STD_LOGIC := '0'; + SIGNAL k28 : STD_LOGIC := '0'; + + ALIAS b6 : STD_LOGIC_VECTOR(5 DOWNTO 0) IS DIN(5 DOWNTO 0) ; --iedcba + ALIAS b4 : STD_LOGIC_VECTOR(3 DOWNTO 0) IS DIN(9 DOWNTO 6) ; --jhgf + ALIAS a : STD_LOGIC IS DIN(0) ; + ALIAS b : STD_LOGIC IS DIN(1) ; + ALIAS c : STD_LOGIC IS DIN(2) ; + ALIAS d : STD_LOGIC IS DIN(3) ; + ALIAS e : STD_LOGIC IS DIN(4) ; + ALIAS i : STD_LOGIC IS DIN(5) ; + ALIAS f : STD_LOGIC IS DIN(6) ; + ALIAS g : STD_LOGIC IS DIN(7) ; + ALIAS h : STD_LOGIC IS DIN(8) ; + ALIAS j : STD_LOGIC IS DIN(9) ; + +--Signals for calculating code_error + SIGNAL p04 : STD_LOGIC := '0'; + SIGNAL p13 : STD_LOGIC := '0'; + SIGNAL p22 : STD_LOGIC := '0'; + SIGNAL p31 : STD_LOGIC := '0'; + SIGNAL p40 : STD_LOGIC := '0'; + SIGNAL fghj : STD_LOGIC := '0'; + SIGNAL eifgh : STD_LOGIC := '0'; + SIGNAL sK28 : STD_LOGIC := '0'; + SIGNAL e_i : STD_LOGIC := '0'; + SIGNAL ighj : STD_LOGIC := '0'; + SIGNAL i_ghj : STD_LOGIC := '0'; + SIGNAL kx7 : STD_LOGIC := '0'; + SIGNAL invr6 : STD_LOGIC := '0'; + SIGNAL pdbr6 : STD_LOGIC := '0'; + SIGNAL ndbr6 : STD_LOGIC := '0'; + SIGNAL pdur6 : STD_LOGIC := '0'; + SIGNAL pdbr4 : STD_LOGIC := '0'; + SIGNAL ndrr4 : STD_LOGIC := '0'; + SIGNAL ndur6 : STD_LOGIC := '0'; + SIGNAL ndbr4 : STD_LOGIC := '0'; + SIGNAL pdrr4 : STD_LOGIC := '0'; + SIGNAL fgh : STD_LOGIC := '0'; + SIGNAL invby_a : STD_LOGIC := '0'; + SIGNAL invby_b : STD_LOGIC := '0'; + SIGNAL invby_c : STD_LOGIC := '0'; + SIGNAL invby_d : STD_LOGIC := '0'; + SIGNAL invby_e : STD_LOGIC := '0'; + SIGNAL invby_f : STD_LOGIC := '0'; + SIGNAL invby_g : STD_LOGIC := '0'; + SIGNAL invby_h : STD_LOGIC := '0'; + + +------------------------------------------------------------------------------- +-- Begin Architecture +------------------------------------------------------------------------------- +BEGIN + + ----------------------------------------------------------------------------- + -- Conditionally tie optional ports to internal signals + ----------------------------------------------------------------------------- + + ----New Data----------------------------------------------------------------- + gnd : IF (C_HAS_ND = 1) GENERATE + + ----Update the New Data output------------------------------- + PROCESS (CLK) + BEGIN + IF (CLK'event AND CLK = '1') THEN + IF ((CE = '1') AND (SINIT = '1')) THEN + ND <= '0' AFTER TFF; + ELSE + ND <= CE AFTER TFF; + END IF ; + END IF ; + END PROCESS ; + + END GENERATE gnd ; + + ----Code Error--------------------------------------------------------------- + gcerr : IF (C_HAS_CODE_ERR = 1) GENERATE + + ----Update CODE_ERR output------------------- + PROCESS (CLK) + BEGIN + IF (CLK'event AND CLK = '1') THEN + IF (CE = '1') THEN + IF (SINIT = '1') THEN + CODE_ERR <= '0' AFTER TFF; + ELSE + CODE_ERR <= code_err_i AFTER TFF; + END IF; + END IF ; + END IF ; + END PROCESS ; + + END GENERATE gcerr ; + + + +-- The following code uses notation and logic from the 8b/10b specification + +------------------------------------------------------------------------------- +-- Set the value of k28 signal +------------------------------------------------------------------------------- + k28 <= NOT((c OR d OR e OR i) OR NOT(h XOR j)) ; + +------------------------------------------------------------------------------- +-- Do the 6B/5B conversion +------------------------------------------------------------------------------- + PROCESS (b6) + BEGIN + CASE b6 IS + WHEN "000110" => b5 <= "00000" ; --D.0 + WHEN "111001" => b5 <= "00000" ; --D.0 + WHEN "010001" => b5 <= "00001" ; --D.1 + WHEN "101110" => b5 <= "00001" ; --D.1 + WHEN "010010" => b5 <= "00010" ; --D.2 + WHEN "101101" => b5 <= "00010" ; --D.2 + WHEN "100011" => b5 <= "00011" ; --D.3 + WHEN "010100" => b5 <= "00100" ; --D.4 + WHEN "101011" => b5 <= "00100" ; --D.4 + WHEN "100101" => b5 <= "00101" ; --D.5 + WHEN "100110" => b5 <= "00110" ; --D.6 + WHEN "000111" => b5 <= "00111" ; --D.7 + WHEN "111000" => b5 <= "00111" ; --D.7 + WHEN "011000" => b5 <= "01000" ; --D.8 + WHEN "100111" => b5 <= "01000" ; --D.8 + WHEN "101001" => b5 <= "01001" ; --D.9 + WHEN "101010" => b5 <= "01010" ; --D.10 + WHEN "001011" => b5 <= "01011" ; --D.11 + WHEN "101100" => b5 <= "01100" ; --D.12 + WHEN "001101" => b5 <= "01101" ; --D.13 + WHEN "001110" => b5 <= "01110" ; --D.14 + WHEN "000101" => b5 <= "01111" ; --D.15 + WHEN "111010" => b5 <= "01111" ; --D.15 + + WHEN "110110" => b5 <= "10000" ; --D.16 + WHEN "001001" => b5 <= "10000" ; --D.16 + WHEN "110001" => b5 <= "10001" ; --D.17 + WHEN "110010" => b5 <= "10010" ; --D.18 + WHEN "010011" => b5 <= "10011" ; --D.19 + WHEN "110100" => b5 <= "10100" ; --D.20 + WHEN "010101" => b5 <= "10101" ; --D.21 + WHEN "010110" => b5 <= "10110" ; --D.22 + WHEN "010111" => b5 <= "10111" ; --D/K.23 + WHEN "101000" => b5 <= "10111" ; --D/K.23 + WHEN "001100" => b5 <= "11000" ; --D.24 + WHEN "110011" => b5 <= "11000" ; --D.24 + WHEN "011001" => b5 <= "11001" ; --D.25 + WHEN "011010" => b5 <= "11010" ; --D.26 + WHEN "011011" => b5 <= "11011" ; --D/K.27 + WHEN "100100" => b5 <= "11011" ; --D/K.27 + WHEN "011100" => b5 <= "11100" ; --D.28 + WHEN "111100" => b5 <= "11100" ; --K.28 + WHEN "000011" => b5 <= "11100" ; --K.28 + WHEN "011101" => b5 <= "11101" ; --D/K.29 + WHEN "100010" => b5 <= "11101" ; --D/K.29 + WHEN "011110" => b5 <= "11110" ; --D.30 + WHEN "100001" => b5 <= "11110" ; --D.30 + WHEN "110101" => b5 <= "11111" ; --D.31 + WHEN "001010" => b5 <= "11111" ; --D.31 + WHEN OTHERS => b5 <= DEFAULTB5 ; --CODE VIOLATION! + END CASE ; + END PROCESS ; + +------------------------------------------------------------------------------- +-- Disparity for the 6B block +------------------------------------------------------------------------------- + PROCESS (b6) + BEGIN + CASE b6 IS + WHEN "000000" => b6_disp <= neg ; --invalid ; + WHEN "000001" => b6_disp <= neg ; --invalid ; + WHEN "000010" => b6_disp <= neg ; --invalid ; + WHEN "000011" => b6_disp <= neg ; --K.28 + WHEN "000100" => b6_disp <= neg ; --invalid ; + WHEN "000101" => b6_disp <= neg ; --D.15 + WHEN "000110" => b6_disp <= neg ; --D.0 + WHEN "000111" => b6_disp <= specneg; --D.7 + WHEN "001000" => b6_disp <= neg ; --invalid ; + WHEN "001001" => b6_disp <= neg ; --D.16 + WHEN "001010" => b6_disp <= neg ; --D.31 + WHEN "001011" => b6_disp <= zero ; --D.11 + WHEN "001100" => b6_disp <= neg ; --D.24 + WHEN "001101" => b6_disp <= zero ; --D.13 + WHEN "001110" => b6_disp <= zero ; --D.14 + WHEN "001111" => b6_disp <= pos ; --invalid ; + + WHEN "010000" => b6_disp <= neg ; --invalid ; + WHEN "010001" => b6_disp <= neg ; --D.1 + WHEN "010010" => b6_disp <= neg ; --D.2 + WHEN "010011" => b6_disp <= zero ; --D.19 + WHEN "010100" => b6_disp <= neg ; --D.4 + WHEN "010101" => b6_disp <= zero ; --D.21 + WHEN "010110" => b6_disp <= zero ; --D.22 + WHEN "010111" => b6_disp <= pos ; --D.23 + WHEN "011000" => b6_disp <= neg ; --D.8 + WHEN "011001" => b6_disp <= zero ; --D.25 + WHEN "011010" => b6_disp <= zero ; --D.26 + WHEN "011011" => b6_disp <= pos ; --D.27 + WHEN "011100" => b6_disp <= zero ; --D.28 + WHEN "011101" => b6_disp <= pos ; --D.29 + WHEN "011110" => b6_disp <= pos ; --D.30 + WHEN "011111" => b6_disp <= pos ; --invalid ; + + WHEN "100000" => b6_disp <= neg ; --invalid ; + WHEN "100001" => b6_disp <= neg ; --D.30 ; + WHEN "100010" => b6_disp <= neg ; --D.29 ; + WHEN "100011" => b6_disp <= zero ; --D.3 + WHEN "100100" => b6_disp <= neg ; --D.27 + WHEN "100101" => b6_disp <= zero ; --D.5 + WHEN "100110" => b6_disp <= zero ; --D.6 + WHEN "100111" => b6_disp <= pos ; --D.8 + WHEN "101000" => b6_disp <= neg ; --D.23 + WHEN "101001" => b6_disp <= zero ; --D.9 + WHEN "101010" => b6_disp <= zero ; --D.10 + WHEN "101011" => b6_disp <= pos ; --D.4 + WHEN "101100" => b6_disp <= zero ; --D.12 + WHEN "101101" => b6_disp <= pos ; --D.2 + WHEN "101110" => b6_disp <= pos ; --D.1 + WHEN "101111" => b6_disp <= pos ; --invalid ; + + WHEN "110000" => b6_disp <= neg ; --invalid ; + WHEN "110001" => b6_disp <= zero ; --D.17 + WHEN "110010" => b6_disp <= zero ; --D.18 + WHEN "110011" => b6_disp <= pos ; --D.24 + WHEN "110100" => b6_disp <= zero ; --D.20 + WHEN "110101" => b6_disp <= pos ; --D.31 + WHEN "110110" => b6_disp <= pos ; --D.16 + WHEN "110111" => b6_disp <= pos ; --invalid ; + WHEN "111000" => b6_disp <= specpos; --D.7 + WHEN "111001" => b6_disp <= pos ; --D.0 + WHEN "111010" => b6_disp <= pos ; --D.15 + WHEN "111011" => b6_disp <= pos ; --invalid ; + WHEN "111100" => b6_disp <= pos ; --K.28 + WHEN "111101" => b6_disp <= pos ; --invalid ; + WHEN "111110" => b6_disp <= pos ; --invalid ; + WHEN "111111" => b6_disp <= pos ; --invalid ; + + WHEN OTHERS => b6_disp <= zero ; + END CASE ; + END PROCESS ; + +------------------------------------------------------------------------------- +-- Do the 3B/4B conversion +------------------------------------------------------------------------------- + PROCESS (b4, k28) + BEGIN + CASE b4 IS + WHEN "0010" => b3 <= "000" ; --D/K.x.0 + WHEN "1101" => b3 <= "000" ; --D/K.x.0 + WHEN "1001" => + IF (k28 = '0') + THEN b3 <= "001" ; --D/K.x.1 + ELSE b3 <= "110" ; --K28.6 + END IF ; + WHEN "0110" => + IF (k28 = '1') + THEN b3 <= "001" ; --K.28.1 + ELSE b3 <= "110" ; --D/K.x.6 + END IF ; + WHEN "1010" => + IF (k28 = '0') + THEN b3 <= "010" ; --D/K.x.2 + ELSE b3 <= "101" ; --K28.5 + END IF ; + WHEN "0101" => + IF (k28 = '1') + THEN b3 <= "010" ; --K28.2 + ELSE b3 <= "101" ; --D/K.x.5 + END IF ; + WHEN "0011" => b3 <= "011" ; --D/K.x.3 + WHEN "1100" => b3 <= "011" ; --D/K.x.3 + WHEN "0100" => b3 <= "100" ; --D/K.x.4 + WHEN "1011" => b3 <= "100" ; --D/K.x.4 + WHEN "0111" => b3 <= "111" ; --D.x.7 + WHEN "1000" => b3 <= "111" ; --D.x.7 + WHEN "1110" => b3 <= "111" ; --D/K.x.7 + WHEN "0001" => b3 <= "111" ; --D/K.x.7 + WHEN OTHERS => b3 <= DEFAULTB3 ; --CODE VIOLATION! + END CASE ; + END PROCESS ; + +------------------------------------------------------------------------------- +-- Disparity for the 4B block +------------------------------------------------------------------------------- + PROCESS (b4) + BEGIN + CASE b4 IS + WHEN "0000" => b4_disp <= neg ; + WHEN "0001" => b4_disp <= neg ; + WHEN "0010" => b4_disp <= neg ; + WHEN "0011" => b4_disp <= specneg; + WHEN "0100" => b4_disp <= neg ; + WHEN "0101" => b4_disp <= zero ; + WHEN "0110" => b4_disp <= zero ; + WHEN "0111" => b4_disp <= pos ; + WHEN "1000" => b4_disp <= neg ; + WHEN "1001" => b4_disp <= zero ; + WHEN "1010" => b4_disp <= zero ; + WHEN "1011" => b4_disp <= pos ; + WHEN "1100" => b4_disp <= specpos; + WHEN "1101" => b4_disp <= pos ; + WHEN "1110" => b4_disp <= pos ; + WHEN "1111" => b4_disp <= pos ; + WHEN OTHERS => b4_disp <= zero ; + END CASE ; + END PROCESS ; + +------------------------------------------------------------------------------- +-- Special Code for calculating symrd[3:0] +-- +-- +---------+---------+-------+------------+-------+------------+ +-- | | | symrd | +-- | | | + Start Disp | - Start Disp | +-- | b6_disp | b4_disp | Error | NewRunDisp | Error | NewRunDisp | +-- +---------+---------+-------+------------+-------+------------+ +-- | + | + | 1 | 1 | 1 | 1 | +-- | + | - | 1 | 0 | 0 | 0 | +-- | + | 0 | 1 | 1 | 0 | 1 | +-- | - | + | 0 | 1 | 1 | 1 | +-- | - | - | 1 | 0 | 1 | 0 | +-- | - | 0 | 0 | 0 | 1 | 0 | +-- | 0 | + | 1 | 1 | 0 | 1 | +-- | 0 | - | 0 | 0 | 1 | 0 | +-- | 0 | 0 | 0 | 1 | 0 | 0 | +-- +---------+---------+-------+------------+-------+------------+ +-- +------------------------------------------------------------------------------- + PROCESS (b4_disp, b6_disp) + BEGIN + CASE b6_disp IS + WHEN pos => + CASE b4_disp IS + WHEN pos => symrd(3 DOWNTO 0) <= "1111"; + WHEN neg => symrd(3 DOWNTO 0) <= "1000"; + WHEN specpos=> symrd(3 DOWNTO 0) <= "1101"; --Ex: D1.3- + WHEN specneg=> symrd(3 DOWNTO 0) <= "1000"; + WHEN zero => symrd(3 DOWNTO 0) <= "1101"; + WHEN OTHERS => symrd(3 DOWNTO 0) <= "XXXX"; + END CASE; + WHEN neg => + CASE b4_disp IS + WHEN pos => symrd(3 DOWNTO 0) <= "0111"; + WHEN neg => symrd(3 DOWNTO 0) <= "1010"; + WHEN specpos=> symrd(3 DOWNTO 0) <= "0111"; + WHEN specneg=> symrd(3 DOWNTO 0) <= "0010"; --Ex: D1.3+ + WHEN zero => symrd(3 DOWNTO 0) <= "0010"; + WHEN OTHERS => symrd(3 DOWNTO 0) <= "XXXX"; + END CASE; + WHEN zero => + CASE b4_disp IS + WHEN pos => symrd(3 DOWNTO 0) <= "1101"; + WHEN neg => symrd(3 DOWNTO 0) <= "0010"; + WHEN specpos=> symrd(3 DOWNTO 0) <= "0111"; --Ex: D11.3+ + WHEN specneg=> symrd(3 DOWNTO 0) <= "1000"; --Ex: D11.3- + WHEN zero => symrd(3 DOWNTO 0) <= "0100"; + WHEN OTHERS => symrd(3 DOWNTO 0) <= "XXXX"; + END CASE; + WHEN specpos => + CASE b4_disp IS + WHEN pos => symrd(3 DOWNTO 0) <= "1111"; + WHEN neg => symrd(3 DOWNTO 0) <= "0010"; --Ex: D7.0+ + WHEN specpos=> symrd(3 DOWNTO 0) <= "0111"; --Ex: D7.3+ + WHEN specneg=> symrd(3 DOWNTO 0) <= "1010"; + WHEN zero => symrd(3 DOWNTO 0) <= "0111"; --Ex: D7.5+ + WHEN OTHERS => symrd(3 DOWNTO 0) <= "XXXX"; + END CASE; + WHEN specneg => + CASE b4_disp IS + WHEN pos => symrd(3 DOWNTO 0) <= "1101"; --Ex: D7.0- + WHEN neg => symrd(3 DOWNTO 0) <= "1010"; + WHEN specpos=> symrd(3 DOWNTO 0) <= "1111"; + WHEN specneg=> symrd(3 DOWNTO 0) <= "1000"; --Ex: D7.3- + WHEN zero => symrd(3 DOWNTO 0) <= "1000"; --Ex: D7.5- + WHEN OTHERS => symrd(3 DOWNTO 0) <= "XXXX"; + END CASE; + WHEN OTHERS => symrd(3 DOWNTO 0) <= "XXXX"; + END CASE; + END PROCESS; + + -- the new running disparity is calculated from the input disparity + -- and the disparity of the 10-bit word + grdi : IF (C_HAS_DISP_IN = 1 AND C_HAS_RUN_DISP=1) GENERATE + PROCESS (CLK) + BEGIN + IF (CLK'event and CLK='1') THEN + IF (CE = '1') THEN + IF (SINIT = '1') THEN + run_disp_i <= bint_2_sl(C_SINIT_RUN_DISP) AFTER TFF; + ELSIF (DISP_IN = '1') THEN + run_disp_i <= symrd(2) AFTER TFF; + ELSE + run_disp_i <= symrd(0) AFTER TFF; + END IF; + END IF; + END IF; + END PROCESS; + END GENERATE grdi; + + -- the new running disparity is calculated from the old running disparity + -- and the disparity of the 10-bit word. run_disp is also used to + -- calculate disp_err and sym_disp when disp_in is not present + grdni : IF (C_HAS_DISP_IN /= 1 AND (C_HAS_RUN_DISP=1 OR + C_HAS_DISP_ERR=1 OR + C_HAS_SYM_DISP=1)) GENERATE + PROCESS (CLK) + BEGIN + IF (CLK'event and CLK='1') THEN + IF (CE = '1') THEN + IF (SINIT = '1') THEN + run_disp_i <= bint_2_sl(C_SINIT_RUN_DISP) AFTER TFF; + ELSIF (run_disp_i = '1') THEN + run_disp_i <= symrd(2) AFTER TFF; + ELSE + run_disp_i <= symrd(0) AFTER TFF; + END IF; + END IF; + END IF; + END PROCESS; + END GENERATE grdni; + + gde : IF (C_HAS_DISP_ERR = 1) GENERATE + -- the new disparity error is calculated from the old running disparity + -- and the error information from the 10-bit word + gdei : IF (C_HAS_DISP_IN = 1) GENERATE + PROCESS (CLK) + BEGIN + IF (CLK'event AND CLK='1') THEN + IF (CE = '1') THEN + IF (SINIT = '1') THEN + disp_err <= '0' AFTER TFF; + ELSIF (DISP_IN='1') THEN + disp_err <= symrd(3) AFTER TFF; + ELSE + disp_err <= symrd(1) AFTER TFF; + END IF; + END IF; + END IF; + END PROCESS; + END GENERATE gdei; + + gdeni : IF (C_HAS_DISP_IN /= 1) GENERATE + PROCESS (CLK) + BEGIN + IF (CLK'event AND CLK='1') THEN + IF (CE = '1') THEN + IF (SINIT = '1') THEN + disp_err <= '0' AFTER TFF; + ELSIF (run_disp_i='1') THEN + disp_err <= symrd(3) AFTER TFF; + ELSE + disp_err <= symrd(1) AFTER TFF; + END IF; + END IF; + END IF; + END PROCESS; + END GENERATE gdeni; + END GENERATE gde; + + gsd : IF (C_HAS_SYM_DISP = 1) GENERATE + gsdi : IF (C_HAS_DISP_IN = 1) GENERATE + PROCESS (CLK) + BEGIN + IF (CLK'event AND CLK='1') THEN + IF (CE = '1') THEN + IF (SINIT = '1') THEN + sym_disp_i <= conv_std_logic_vector(C_SINIT_RUN_DISP,2) AFTER TFF; + ELSIF (DISP_IN='1') THEN + sym_disp_i <= symrd(3 DOWNTO 2) AFTER TFF; + ELSE + sym_disp_i <= symrd(1 DOWNTO 0) AFTER TFF; + END IF; + END IF; + END IF; + END PROCESS; + END GENERATE gsdi; + + gsdni : IF (C_HAS_DISP_IN /= 1) GENERATE + PROCESS (CLK) + BEGIN + IF (CLK'event AND CLK='1') THEN + IF (CE = '1') THEN + IF (SINIT = '1') THEN + sym_disp_i <= conv_std_logic_vector(C_SINIT_RUN_DISP,2) AFTER TFF; + ELSIF (run_disp_i='1') THEN + sym_disp_i <= symrd(3 DOWNTO 2) AFTER TFF; + ELSE + sym_disp_i <= symrd(1 DOWNTO 0) AFTER TFF; + END IF; + END IF; + END IF; + END PROCESS; + END GENERATE gsdni; + END GENERATE gsd; + + -- map internal signals to outputs + run_disp <= run_disp_i; + sym_disp <= sym_disp_i; + +------------------------------------------------------------------------------- +-- Decode the K codes +------------------------------------------------------------------------------- + PROCESS (c, d, e, i, g, h, j) + BEGIN + k <= (c AND d AND e AND i) OR NOT(c OR d OR e OR i) OR + ((e XOR i) AND ((i AND g AND h AND j) OR + NOT(i OR g OR h OR j))) ; + END PROCESS ; + +------------------------------------------------------------------------------- +-- Update the outputs on the clock +------------------------------------------------------------------------------- + ----Update DOUT output------------------- + PROCESS (CLK) + BEGIN + IF (CLK'event AND CLK = '1') THEN + IF (CE = '1') THEN + IF (SINIT = '1') THEN + dout_i <= str_to_slv(C_SINIT_DOUT, 8) AFTER TFF ; + ELSE + dout_i <= (b3 & b5) AFTER TFF; + END IF; + END IF ; + END IF ; + END PROCESS ; + DOUT <= dout_i; + ----Update KOUT output------------------- + PROCESS (CLK) + BEGIN + IF (CLK'event AND CLK = '1') THEN + IF (CE = '1') THEN + IF (SINIT = '1') THEN + kout_i <= bint_2_sl(C_SINIT_KOUT) AFTER TFF; + ELSE + kout_i <= k AFTER TFF; + END IF; + END IF ; + END IF ; + END PROCESS ; + KOUT <= kout_i; + +------------------------------------------------------------------------------- +-- Calculate code_error (uses notation from IBM spec) +------------------------------------------------------------------------------- + bitcount: PROCESS (DIN) + BEGIN + CASE DIN(3 DOWNTO 0) IS + WHEN "0000" => p04 <= '1'; + p13 <= '0'; + p22 <= '0'; + p31 <= '0'; + p40 <= '0'; + WHEN "0001" => p04 <= '0'; + p13 <= '1'; + p22 <= '0'; + p31 <= '0'; + p40 <= '0'; + WHEN "0010" => p04 <= '0'; + p13 <= '1'; + p22 <= '0'; + p31 <= '0'; + p40 <= '0'; + WHEN "0011" => p04 <= '0'; + p13 <= '0'; + p22 <= '1'; + p31 <= '0'; + p40 <= '0'; + WHEN "0100" => p04 <= '0'; + p13 <= '1'; + p22 <= '0'; + p31 <= '0'; + p40 <= '0'; + WHEN "0101" => p04 <= '0'; + p13 <= '0'; + p22 <= '1'; + p31 <= '0'; + p40 <= '0'; + WHEN "0110" => p04 <= '0'; + p13 <= '0'; + p22 <= '1'; + p31 <= '0'; + p40 <= '0'; + WHEN "0111" => p04 <= '0'; + p13 <= '0'; + p22 <= '0'; + p31 <= '1'; + p40 <= '0'; + WHEN "1000" => p04 <= '0'; + p13 <= '1'; + p22 <= '0'; + p31 <= '0'; + p40 <= '0'; + WHEN "1001" => p04 <= '0'; + p13 <= '0'; + p22 <= '1'; + p31 <= '0'; + p40 <= '0'; + WHEN "1010" => p04 <= '0'; + p13 <= '0'; + p22 <= '1'; + p31 <= '0'; + p40 <= '0'; + WHEN "1011" => p04 <= '0'; + p13 <= '0'; + p22 <= '0'; + p31 <= '1'; + p40 <= '0'; + WHEN "1100" => p04 <= '0'; + p13 <= '0'; + p22 <= '1'; + p31 <= '0'; + p40 <= '0'; + WHEN "1101" => p04 <= '0'; + p13 <= '0'; + p22 <= '0'; + p31 <= '1'; + p40 <= '0'; + WHEN "1110" => p04 <= '0'; + p13 <= '0'; + p22 <= '0'; + p31 <= '1'; + p40 <= '0'; + WHEN "1111" => p04 <= '0'; + p13 <= '0'; + p22 <= '0'; + p31 <= '0'; + p40 <= '1'; + WHEN OTHERS => NULL; + END CASE; + END PROCESS bitcount; + + fghj <= (f AND g AND h AND j) OR (NOT f AND NOT g AND NOT h AND NOT j); + eifgh <= (e AND i AND f AND g AND h) OR (NOT e AND NOT i AND NOT f AND NOT g + AND NOT h); + sk28 <= (c AND d AND e AND i) OR (NOT c AND NOT d AND NOT e AND NOT i); + e_i <= (e AND NOT i) OR (NOT e AND i); + ighj <= (i AND g AND h AND j) OR (NOT i AND NOT g AND NOT h AND NOT j); + i_ghj <= (NOT i AND g AND h AND j) OR (i AND NOT g AND NOT h AND NOT j); + kx7 <= e_i AND ighj; + invr6 <= p40 OR p04 OR (p31 AND e AND i) OR (p13 AND NOT e AND NOT i); + pdbr6 <= (p31 AND (e OR i)) OR (p22 AND e AND i) OR p40; + ndbr6 <= (p13 AND (NOT e OR NOT i)) OR (p22 AND NOT e AND NOT i) OR p04; + pdur6 <= pdbr6 OR (d AND e AND i); + pdbr4 <= (f AND g AND (h OR j)) OR ((f OR g) AND h AND j); + ndrr4 <= pdbr4 OR (f AND g); + ndur6 <= ndbr6 OR (NOT d AND NOT e AND NOT i); + fgh <= (f AND g AND h) OR (NOT f AND NOT g AND NOT h); + ndbr4 <= (NOT f AND NOT g AND (NOT h OR NOT j)) OR ((NOT f OR NOT g) AND + NOT h AND NOT j); + pdrr4 <= ndbr4 OR (NOT f AND NOT g); + + invby_a <= invr6; + invby_b <= fghj; + invby_c <= eifgh; + invby_d <= (NOT sk28 AND i_ghj); + invby_e <= (sk28 AND fgh); + invby_f <= (kx7 AND NOT pdbr6 AND NOT ndbr6); + invby_g <= (pdur6 AND ndrr4); + invby_h <= (ndur6 AND pdrr4); + + --Update internal code error signal + code_err_i <= invby_a OR invby_b OR invby_c OR invby_d OR invby_e OR invby_f OR + invby_g OR invby_h; + +END xilinx ; diff --git a/rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_pkg.vhd b/rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_pkg.vhd new file mode 100644 index 00000000..01cdcb7f --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_pkg.vhd @@ -0,0 +1,251 @@ +--------------------------------------------------------------------------- +-- +-- Module : decode_8b10b_pkg.vhd +-- +-- Version : 1.1 +-- +-- Last Update : 2008-10-31 +-- +-- Project : 8b/10b Decoder Reference Design +-- +-- Description : 8b/10b Decoder package file +-- +-- Company : Xilinx, Inc. +-- +-- DISCLAIMER OF LIABILITY +-- +-- This file contains proprietary and confidential information of +-- Xilinx, Inc. ("Xilinx"), that is distributed under a license +-- from Xilinx, and may be used, copied and/or disclosed only +-- pursuant to the terms of a valid license agreement with Xilinx. +-- +-- XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION +-- ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +-- EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT +-- LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT, +-- MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx +-- does not warrant that functions included in the Materials will +-- meet the requirements of Licensee, or that the operation of the +-- Materials will be uninterrupted or error-free, or that defects +-- in the Materials will be corrected. Furthermore, Xilinx does +-- not warrant or make any representations regarding use, or the +-- results of the use, of the Materials in terms of correctness, +-- accuracy, reliability or otherwise. +-- +-- Xilinx products are not designed or intended to be fail-safe, +-- or for use in any application requiring fail-safe performance, +-- such as life-support or safety devices or systems, Class III +-- medical devices, nuclear facilities, applications related to +-- the deployment of airbags, or any other applications that could +-- lead to death, personal injury or severe property or +-- environmental damage (individually and collectively, "critical +-- applications"). Customer assumes the sole risk and liability +-- of any use of Xilinx products in critical applications, +-- subject only to applicable laws and regulations governing +-- limitations on product liability. +-- +-- Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2008 Xilinx, Inc. +-- All rights reserved. +-- +-- This disclaimer and copyright notice must be retained as part +-- of this file at all times. +-- +--------------------------------------------------------------------------- +-- +-- History +-- +-- Date Version Description +-- +-- 10/31/2008 1.1 Initial release +-- +------------------------------------------------------------------------------- + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; + +------------------------------------------------------------------------------- +-- Package Declaration +------------------------------------------------------------------------------- +PACKAGE decode_8b10b_pkg IS + +------------------------------------------------------------------------------- +-- Constant Declarations +------------------------------------------------------------------------------- + CONSTANT TFF : TIME := 2 ns; + CONSTANT CONST_NEG : STRING (1 TO 2) := "00"; + CONSTANT CONST_POS : STRING (1 TO 2) := "01"; + +------------------------------------------------------------------------------- +-- Function Declarations +------------------------------------------------------------------------------- + FUNCTION int_to_str_1bit ( + bit : INTEGER + ) RETURN STRING; + FUNCTION bint_2_sl ( + X : INTEGER + ) RETURN STD_LOGIC; + FUNCTION concat_sinit ( + integer_run_disp : INTEGER; + integer_kout : INTEGER; + string_dout : STRING + ) RETURN STRING; + FUNCTION str_to_slv( + bitsin : STRING; + nbits : INTEGER + ) RETURN STD_LOGIC_VECTOR; + FUNCTION calc_init_val_rd ( + SINIT_VAL : STRING(10 DOWNTO 1) + ) RETURN INTEGER; + FUNCTION has_bport ( + C_HAS_BPORTS : INTEGER; + has_aport : INTEGER + ) RETURN INTEGER; + +END decode_8b10b_pkg; + +------------------------------------------------------------------------------- +-- Package Body +------------------------------------------------------------------------------- +PACKAGE BODY decode_8b10b_pkg IS + +------------------------------------------------------------------------------- +-- Convert binary integer (0 or 1) into a single-character-string ("0" or "1") +------------------------------------------------------------------------------- + FUNCTION int_to_str_1bit(bit : INTEGER) RETURN STRING IS + BEGIN + IF (bit = 1) THEN + RETURN "1"; + ELSE + RETURN "0"; + END IF; + END int_to_str_1bit; + +------------------------------------------------------------------------------- +-- Convert binary integer (0 or 1) into std_logic ('0' or '1') +------------------------------------------------------------------------------- + FUNCTION bint_2_sl (X : INTEGER) RETURN STD_LOGIC IS + BEGIN + IF (X = 0) THEN + RETURN '0'; + ELSE + RETURN '1'; + END IF; + END bint_2_sl; + +------------------------------------------------------------------------------- +-- Calculate the SINIT value for the inferred BRAM using the generics: +-- C_SINIT_DOUT, C_SINIT_KOUT, and C_SINIT_RUN_DISP +------------------------------------------------------------------------------- + FUNCTION concat_sinit( + integer_run_disp : INTEGER; + integer_kout : INTEGER; + string_dout : STRING) + RETURN STRING IS + VARIABLE tmp_sym_disp : STRING(1 TO 2); + CONSTANT TMP_CODE_ERR : STRING(1 TO 1) := "0"; + CONSTANT TMP_KOUT_0 : STRING(1 TO 1) := "0"; + CONSTANT TMP_KOUT_1 : STRING(1 TO 1) := "1"; + VARIABLE tmp_str : STRING(1 TO 14); + BEGIN + IF (integer_run_disp = 1) THEN + tmp_sym_disp := CONST_POS; -- D0.0+ has sym_disp of pos + ELSE + tmp_sym_disp := CONST_NEG; -- D0.0- has sym_disp of neg + END IF; + IF (integer_kout = 1) THEN + tmp_str := tmp_sym_disp & tmp_sym_disp & TMP_CODE_ERR & + TMP_KOUT_1 & string_dout; + ELSE + tmp_str := tmp_sym_disp & tmp_sym_disp & TMP_CODE_ERR & + TMP_KOUT_0 & string_dout; + END IF; + RETURN tmp_str; + END concat_sinit; + +----------------------------------------------------------------------------- +-- Convert a string containing 1's and 0's into a std_logic_vector of +-- width nbits +----------------------------------------------------------------------------- + FUNCTION str_to_slv( + bitsin : STRING; + nbits : INTEGER) + RETURN STD_LOGIC_VECTOR IS + VARIABLE ret : STD_LOGIC_VECTOR(bitsin'range); + VARIABLE ret0s : STD_LOGIC_VECTOR(1 TO nbits) := (OTHERS => '0'); + VARIABLE retpadded : STD_LOGIC_VECTOR(1 TO nbits) := (OTHERS => '0'); + VARIABLE offset : INTEGER := 0; + BEGIN + IF(bitsin'length = 0) THEN -- Make all '0's + RETURN ret0s; + END IF; + IF(bitsin'length < nbits) THEN -- pad MSBs with '0's + offset := nbits - bitsin'length; + FOR i IN bitsin'range LOOP + IF bitsin(i) = '1' THEN + retpadded(i+offset) := '1'; + ELSIF (bitsin(i) = 'X' OR bitsin(i) = 'x') THEN + retpadded(i+offset) := 'X'; + ELSIF (bitsin(i) = 'Z' OR bitsin(i) = 'z') THEN + retpadded(i+offset) := 'Z'; + ELSIF (bitsin(i) = '0') THEN + retpadded(i+offset) := '0'; + END IF; + END LOOP; + retpadded(1 TO offset) := (OTHERS => '0'); + RETURN retpadded; + END IF; + FOR i IN bitsin'range LOOP + IF bitsin(i) = '1' THEN + ret(i) := '1'; + ELSIF (bitsin(i) = 'X' OR bitsin(i) = 'x') THEN + ret(i) := 'X'; + ELSIF (bitsin(i) = 'Z' OR bitsin(i) = 'z') THEN + ret(i) := 'Z'; + ELSIF (bitsin(i) = '0') THEN + ret(i) := '0'; + END IF; + END LOOP; + + RETURN ret; + END str_to_slv; + +----------------------------------------------------------------------------- +-- Translate the SINIT string value from the core wrapper to +-- C_SINIT_RUN_DISP +----------------------------------------------------------------------------- + FUNCTION calc_init_val_rd (SINIT_VAL : STRING(10 DOWNTO 1)) RETURN INTEGER IS + VARIABLE tmp_init_val : INTEGER; + BEGIN + CASE SINIT_VAL IS + WHEN "0000000001" => tmp_init_val := 1; --D.0.0 (pos) + WHEN "0000000000" => tmp_init_val := 0; --D.0.0 (neg) + WHEN "0100101001" => tmp_init_val := 1; --D.10.2 (pos) + WHEN "0100101000" => tmp_init_val := 0; --D.10.2 (neg) + WHEN "1011010101" => tmp_init_val := 1; --D.21.5 (pos) + WHEN "1011010100" => tmp_init_val := 0; --D.21.5 (neg) + WHEN OTHERS => tmp_init_val := 0; --invalid init value + END CASE; + RETURN tmp_init_val; + END calc_init_val_rd; + +----------------------------------------------------------------------------- +-- If C_HAS_BPORTS = 1, then the optional B ports are configured the +-- same as the optional A ports +-- If C_HAS_BPORTS = 0, then the optional B ports are disabled (= 0) +----------------------------------------------------------------------------- + FUNCTION has_bport ( + C_HAS_BPORTS : INTEGER; + has_aport : INTEGER) + RETURN INTEGER IS + VARIABLE has_bport : INTEGER; + BEGIN + IF (C_HAS_BPORTS = 1) THEN + has_bport := has_aport; + ELSE + has_bport := 0; + END IF; + RETURN has_bport; + END has_bport; + +END decode_8b10b_pkg; + diff --git a/rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_rtl.vhd b/rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_rtl.vhd new file mode 100644 index 00000000..89e5be8d --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_rtl.vhd @@ -0,0 +1,565 @@ +--------------------------------------------------------------------------- +-- +-- Module : decode_8b10b_rtl.vhd +-- +-- Version : 1.1 +-- +-- Last Update : 2008-10-31 +-- +-- Project : 8b/10b Decoder Reference Design +-- +-- Description : Top-level, synthesizable 8b/10b decoder core file +-- +-- Company : Xilinx, Inc. +-- +-- DISCLAIMER OF LIABILITY +-- +-- This file contains proprietary and confidential information of +-- Xilinx, Inc. ("Xilinx"), that is distributed under a license +-- from Xilinx, and may be used, copied and/or disclosed only +-- pursuant to the terms of a valid license agreement with Xilinx. +-- +-- XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION +-- ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +-- EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT +-- LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT, +-- MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx +-- does not warrant that functions included in the Materials will +-- meet the requirements of Licensee, or that the operation of the +-- Materials will be uninterrupted or error-free, or that defects +-- in the Materials will be corrected. Furthermore, Xilinx does +-- not warrant or make any representations regarding use, or the +-- results of the use, of the Materials in terms of correctness, +-- accuracy, reliability or otherwise. +-- +-- Xilinx products are not designed or intended to be fail-safe, +-- or for use in any application requiring fail-safe performance, +-- such as life-support or safety devices or systems, Class III +-- medical devices, nuclear facilities, applications related to +-- the deployment of airbags, or any other applications that could +-- lead to death, personal injury or severe property or +-- environmental damage (individually and collectively, "critical +-- applications"). Customer assumes the sole risk and liability +-- of any use of Xilinx products in critical applications, +-- subject only to applicable laws and regulations governing +-- limitations on product liability. +-- +-- Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2008 Xilinx, Inc. +-- All rights reserved. +-- +-- This disclaimer and copyright notice must be retained as part +-- of this file at all times. +-- +------------------------------------------------------------------------------- +-- +-- History +-- +-- Date Version Description +-- +-- 10/31/2008 1.1 Initial release +-- +------------------------------------------------------------------------------- + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE IEEE.std_logic_arith.ALL; + +LIBRARY decode_8b10b; +USE work.decode_8b10b_pkg.ALL; + +----------------------------------------------------------------------------- +-- Entity Declaration +----------------------------------------------------------------------------- +ENTITY decode_8b10b_rtl IS + GENERIC ( + C_DECODE_TYPE : INTEGER := 0; + C_ELABORATION_DIR : STRING := "./"; + C_HAS_BPORTS : INTEGER := 0; + C_HAS_CE : INTEGER := 0; + C_HAS_CE_B : INTEGER := 0; + C_HAS_CODE_ERR : INTEGER := 0; + C_HAS_CODE_ERR_B : INTEGER := 0; + C_HAS_DISP_ERR : INTEGER := 0; + C_HAS_DISP_ERR_B : INTEGER := 0; + C_HAS_DISP_IN : INTEGER := 0; + C_HAS_DISP_IN_B : INTEGER := 0; + C_HAS_ND : INTEGER := 0; + C_HAS_ND_B : INTEGER := 0; + C_HAS_RUN_DISP : INTEGER := 0; + C_HAS_RUN_DISP_B : INTEGER := 0; + C_HAS_SINIT : INTEGER := 0; + C_HAS_SINIT_B : INTEGER := 0; + C_HAS_SYM_DISP : INTEGER := 0; + C_HAS_SYM_DISP_B : INTEGER := 0; + C_SINIT_DOUT : STRING := "00000000"; + C_SINIT_DOUT_B : STRING := "00000000"; + C_SINIT_KOUT : INTEGER := 0; + C_SINIT_KOUT_B : INTEGER := 0; + C_SINIT_RUN_DISP : INTEGER := 0; + C_SINIT_RUN_DISP_B : INTEGER := 0 + ); + PORT ( + CLK : IN STD_LOGIC := '0'; + DIN : IN STD_LOGIC_VECTOR(9 DOWNTO 0) := (OTHERS => '0'); + DOUT : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) ; + KOUT : OUT STD_LOGIC ; + + CE : IN STD_LOGIC := '0'; + CE_B : IN STD_LOGIC := '0'; + CLK_B : IN STD_LOGIC := '0'; + DIN_B : IN STD_LOGIC_VECTOR(9 DOWNTO 0) := (OTHERS => '0'); + DISP_IN : IN STD_LOGIC := '0'; + DISP_IN_B : IN STD_LOGIC := '0'; + SINIT : IN STD_LOGIC := '0'; + SINIT_B : IN STD_LOGIC := '0'; + CODE_ERR : OUT STD_LOGIC := '0'; + CODE_ERR_B : OUT STD_LOGIC := '0'; + DISP_ERR : OUT STD_LOGIC := '0'; + DISP_ERR_B : OUT STD_LOGIC := '0'; + DOUT_B : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) ; + KOUT_B : OUT STD_LOGIC ; + ND : OUT STD_LOGIC := '0'; + ND_B : OUT STD_LOGIC := '0'; + RUN_DISP : OUT STD_LOGIC ; + RUN_DISP_B : OUT STD_LOGIC ; + SYM_DISP : OUT STD_LOGIC_VECTOR(1 DOWNTO 0) ; + SYM_DISP_B : OUT STD_LOGIC_VECTOR(1 DOWNTO 0) + ); +END decode_8b10b_rtl; + +-------------------------------------------------------------------------------- +-- Generic Definitions: +-------------------------------------------------------------------------------- + -- C_DECODE_TYPE : Implementation: 0=Slice based, 1=BlockRam + -- C_ELABORATION_DIR : Directory path for mif file + -- C_HAS_BPORTS : 1 indicates second decoder should be generated + -- C_HAS_CE : 1 indicates ce port is present + -- C_HAS_CE_B : 1 indicates ce_b port is present (if c_has_bports=1) + -- C_HAS_CODE_ERR : 1 indicates code_err port is present + -- C_HAS_CODE_ERR_B : 1 indicates code_err_b port is present + -- (if c_has_bports=1) + -- C_HAS_DISP_ERR : 1 indicates disp_err port is present + -- C_HAS_DISP_ERR_B : 1 indicates disp_err_b port is present + -- (if c_has_bports=1) + -- C_HAS_DISP_IN : 1 indicates disp_in port is present + -- C_HAS_DISP_IN_B : 1 indicates disp_in_b port is present + -- (if c_has_bports=1) + -- C_HAS_ND : 1 indicates nd port is present + -- C_HAS_ND_B : 1 indicates nd_b port is present (if c_has_bports=1) + -- C_HAS_RUN_DISP : 1 indicates run_disp port is present + -- C_HAS_RUN_DISP_B : 1 indicates run_disp_b port is present + -- (if c_has_bports=1) + -- C_HAS_SINIT : 1 indicates sinit port is present + -- C_HAS_SINIT_B : 1 indicates sinit_b port is present + -- (if c_has_bports=1) + -- C_HAS_SYM_DISP : 1 indicates sym_disp port is present + -- C_HAS_SYM_DISP_B : 1 indicates sym_disp_b port is present + -- (if c_has_bports=1) + -- C_SINIT_DOUT : 8-bit binary string, dout value when sinit is active + -- C_SINIT_DOUT_B : 8-bit binary string, dout_b value when sinit_b is + -- active + -- C_SINIT_KOUT : controls kout output when sinit is active + -- C_SINIT_KOUT_B : controls kout_b output when sinit_b is active + -- C_SINIT_RUN_DISP : Initializes run_disp (and disp_in) value to + -- positive(1) or negative(0) + -- C_SINIT_RUN_DISP_B : Initializes run_disp_b (and disp_in_b) value to + -- positive(1) or negative(0) +-------------------------------------------------------------------------------- +-- Port Definitions: +-------------------------------------------------------------------------------- + -- Mandatory Pins + -- CLK : Clock Input + -- DIN : Encoded Symbol Input + -- DOUT : Data Output, decoded data byte + -- KOUT : Command Output + ------------------------------------------------------------------------- + -- Optional Pins + -- CE : Clock Enable + -- CE_B : Clock Enable (B port) + -- CLK_B : Clock Input (B port) + -- DIN_B : Encoded Symbol Input (B port) + -- DISP_IN : Disparity Input (running disparity in) + -- DISP_IN_B : Disparity Input (running disparity in) (B port) + -- SINIT : Synchronous Initialization. Resets core to known state. + -- SINIT_B : Synchronous Initialization. Resets core to known state. + -- (B port) + -- CODE_ERR : Code Error, indicates that input symbol did not correspond + -- to a valid member of the code set. + -- CODE_ERR_B : Code Error, indicates that input symbol did not correspond + -- to a valid member of the code set. (B port) + -- DISP_ERR : Disparity Error + -- DISP_ERR_B : Disparity Error (B port) + -- DOUT_B : Data Output, decoded data byte (B port) + -- KOUT_B : Command Output (B port) + -- ND : New Data + -- ND_B : New Data (B port) + -- RUN_DISP : Running Disparity + -- RUN_DISP_B : Running Disparity (B port) + -- SYM_DISP : Symbol Disparity + -- SYM_DISP_B : Symbol Disparity (B port) + ------------------------------------------------------------------------- + + +------------------------------------------------------------------------------- +-- Architecture +------------------------------------------------------------------------------- +ARCHITECTURE xilinx OF decode_8b10b_rtl IS + +------------------------------------------------------------------------------- +-- Signal Declarations +------------------------------------------------------------------------------- + SIGNAL dout_i : STD_LOGIC_VECTOR(7 DOWNTO 0) := + str_to_slv(C_SINIT_DOUT,8); + --convert C_SINIT_DOUT string to 8bit std_logic_vector + SIGNAL kout_i : STD_LOGIC := + bint_2_sl(C_SINIT_KOUT); + --convert C_SINIT_KOUT integer to std_logic + SIGNAL clk_b_i : STD_LOGIC := '0'; + SIGNAL din_b_i : STD_LOGIC_VECTOR(9 DOWNTO 0) := (OTHERS => '0'); + SIGNAL ce_i : STD_LOGIC := '0'; + SIGNAL ce_b_i : STD_LOGIC := '0'; + SIGNAL disp_in_i : STD_LOGIC := '0'; + SIGNAL disp_in_b_i : STD_LOGIC := '0'; + SIGNAL sinit_i : STD_LOGIC := '0'; + SIGNAL sinit_b_i : STD_LOGIC := '0'; + SIGNAL code_err_i : STD_LOGIC := '0'; + SIGNAL code_err_b_i : STD_LOGIC := '0'; + SIGNAL disp_err_i : STD_LOGIC := '0'; + SIGNAL disp_err_b_i : STD_LOGIC := '0'; + SIGNAL dout_b_i : STD_LOGIC_VECTOR(7 DOWNTO 0) := + str_to_slv(C_SINIT_DOUT_B,8); + --convert C_SINIT_DOUT_B string to 8bit std_logic_vector + SIGNAL kout_b_i : STD_LOGIC := + bint_2_sl(C_SINIT_KOUT_B); + --convert C_SINIT_KOUT_B integer to std_logic + SIGNAL nd_i : STD_LOGIC := '0'; + SIGNAL nd_b_i : STD_LOGIC := '0'; + SIGNAL run_disp_i : STD_LOGIC := + bint_2_sl(C_SINIT_RUN_DISP); + --convert C_SINIT_RUN_DISP integer to std logic + SIGNAL run_disp_b_i : STD_LOGIC := + bint_2_sl(C_SINIT_RUN_DISP_B); + --convert C_SINIT_RUN_DISP_B integer to std logic + SIGNAL sym_disp_i : STD_LOGIC_VECTOR(1 DOWNTO 0) := + conv_std_logic_vector(C_SINIT_RUN_DISP,2); + --convert C_SINIT_RUN_DISP integer to slv + SIGNAL sym_disp_b_i : STD_LOGIC_VECTOR(1 DOWNTO 0) := + conv_std_logic_vector(C_SINIT_RUN_DISP_B,2); + --convert C_SINIT_RUN_DISP_B integer to slv + +------------------------------------------------------------------------------- +-- Begin Architecture +------------------------------------------------------------------------------- +BEGIN + + ----------------------------------------------------------------------------- + -- LUT-based decoder + ----------------------------------------------------------------------------- + glut : IF (C_DECODE_TYPE = 0) GENERATE + ldec : ENTITY decode_8b10b_lut + GENERIC MAP ( + C_HAS_BPORTS => C_HAS_BPORTS, + C_HAS_CODE_ERR => C_HAS_CODE_ERR, + C_HAS_CODE_ERR_B => C_HAS_CODE_ERR_B, + C_HAS_DISP_ERR => C_HAS_DISP_ERR, + C_HAS_DISP_ERR_B => C_HAS_DISP_ERR_B, + C_HAS_DISP_IN => C_HAS_DISP_IN, + C_HAS_DISP_IN_B => C_HAS_DISP_IN_B, + C_HAS_ND => C_HAS_ND, + C_HAS_ND_B => C_HAS_ND_B, + C_HAS_SYM_DISP => C_HAS_SYM_DISP, + C_HAS_SYM_DISP_B => C_HAS_SYM_DISP_B, + C_HAS_RUN_DISP => C_HAS_RUN_DISP, + C_HAS_RUN_DISP_B => C_HAS_RUN_DISP_B, + C_SINIT_DOUT => C_SINIT_DOUT, + C_SINIT_DOUT_B => C_SINIT_DOUT_B, + C_SINIT_KOUT => C_SINIT_KOUT, + C_SINIT_KOUT_B => C_SINIT_KOUT_B, + C_SINIT_RUN_DISP => C_SINIT_RUN_DISP, + C_SINIT_RUN_DISP_B => C_SINIT_RUN_DISP_B + ) + PORT MAP( + CLK => CLK, + DIN => DIN, + DOUT => dout_i, + KOUT => kout_i, + + CE => ce_i, + DISP_IN => disp_in_i, + SINIT => sinit_i, + CODE_ERR => code_err_i, + DISP_ERR => disp_err_i, + ND => nd_i, + RUN_DISP => run_disp_i, + SYM_DISP => sym_disp_i, + + CLK_B => clk_b_i, + DIN_B => din_b_i, + DOUT_B => dout_b_i, + KOUT_B => kout_b_i, + + CE_B => ce_b_i, + DISP_IN_B => disp_in_b_i, + SINIT_B => sinit_b_i, + CODE_ERR_B => code_err_b_i, + DISP_ERR_B => disp_err_b_i, + ND_B => nd_b_i, + RUN_DISP_B => run_disp_b_i, + SYM_DISP_B => sym_disp_b_i + ); + END GENERATE glut; + + ----------------------------------------------------------------------------- + -- BRAM-based decoder + ----------------------------------------------------------------------------- + gbram : IF (C_DECODE_TYPE /= 0) GENERATE + bdec : ENTITY decode_8b10b_bram + GENERIC MAP ( + C_ELABORATION_DIR => C_ELABORATION_DIR, + C_HAS_BPORTS => C_HAS_BPORTS, + C_HAS_DISP_IN => C_HAS_DISP_IN, + C_HAS_DISP_IN_B => C_HAS_DISP_IN_B, + C_HAS_DISP_ERR => C_HAS_DISP_ERR, + C_HAS_DISP_ERR_B => C_HAS_DISP_ERR_B, + C_HAS_RUN_DISP => C_HAS_RUN_DISP, + C_HAS_RUN_DISP_B => C_HAS_RUN_DISP_B, + C_HAS_SYM_DISP => C_HAS_SYM_DISP, + C_HAS_SYM_DISP_B => C_HAS_SYM_DISP_B, + C_HAS_ND => C_HAS_ND, + C_HAS_ND_B => C_HAS_ND_B, + C_SINIT_DOUT => C_SINIT_DOUT, + C_SINIT_DOUT_B => C_SINIT_DOUT_B, + C_SINIT_KOUT => C_SINIT_KOUT, + C_SINIT_KOUT_B => C_SINIT_KOUT_B, + C_SINIT_RUN_DISP => C_SINIT_RUN_DISP, + C_SINIT_RUN_DISP_B => C_SINIT_RUN_DISP_B + ) + + PORT MAP( + CLK => CLK, + DIN => DIN, + DOUT => dout_i, + KOUT => kout_i, + + CE => ce_i, + DISP_IN => disp_in_i, + SINIT => sinit_i, + CODE_ERR => code_err_i, + DISP_ERR => disp_err_i, + ND => nd_i, + RUN_DISP => run_disp_i, + SYM_DISP => sym_disp_i, + + CLK_B => clk_b_i, + DIN_B => din_b_i, + DOUT_B => dout_b_i, + KOUT_B => kout_b_i, + + CE_B => ce_b_i, + DISP_IN_B => disp_in_b_i, + SINIT_B => sinit_b_i, + CODE_ERR_B => code_err_b_i, + DISP_ERR_B => disp_err_b_i, + ND_B => nd_b_i, + RUN_DISP_B => run_disp_b_i, + SYM_DISP_B => sym_disp_b_i + ); + END GENERATE gbram; + + + --------------------------------------------------------------------------- + -- Mandatory A Ports + --------------------------------------------------------------------------- + DOUT <= dout_i; + KOUT <= kout_i; + + --------------------------------------------------------------------------- + -- Optional A Ports --tying off unused ports + --------------------------------------------------------------------------- + --Inputs + --ce + gen : IF (C_HAS_CE/=0) GENERATE + ce_i <= CE; + END GENERATE gen; + ngen : IF (C_HAS_CE = 0) GENERATE + ce_i <= '1'; + END GENERATE ngen; + + --disp_in + gdi : IF (C_HAS_DISP_IN /= 0) GENERATE + disp_in_i <= DISP_IN; + END GENERATE gdi; + ngdi : IF (C_HAS_DISP_IN = 0) GENERATE + disp_in_i <= '0'; + END GENERATE ngdi; + + --sinit + gs : IF (C_HAS_SINIT /= 0) GENERATE + sinit_i <= SINIT; + END GENERATE gs; + ngs : IF (C_HAS_SINIT = 0) GENERATE + sinit_i <= '0'; + END GENERATE ngs; + + + --Outputs + --nd + gnd : IF (C_HAS_ND /= 0) GENERATE + ASSERT (C_HAS_CE /= 0) + REPORT "Invalid configuration: ND port requires CE port" + SEVERITY WARNING; + ND <= nd_i; + END GENERATE gnd; + ngnd : IF (C_HAS_ND = 0) GENERATE + ND <= '0'; + END GENERATE ngnd; + + --code_err + gce : IF (C_HAS_CODE_ERR /= 0) GENERATE + CODE_ERR <= code_err_i; + END GENERATE gce; + ngce : IF (C_HAS_CODE_ERR = 0) GENERATE + CODE_ERR <= '0'; + END GENERATE ngce; + + --disp_err + gder : IF (C_HAS_DISP_ERR /= 0) GENERATE + DISP_ERR <= disp_err_i; + END GENERATE gder; + ngder : IF (C_HAS_DISP_ERR = 0) GENERATE + DISP_ERR <= '0'; + END GENERATE ngder; + + --run_disp + grd : IF (C_HAS_RUN_DISP /= 0) GENERATE + RUN_DISP <= run_disp_i; + END GENERATE grd; + ngrd : IF (C_HAS_RUN_DISP = 0) GENERATE + RUN_DISP <= '0'; + END GENERATE ngrd; + + --sym_disp + gsd : IF (C_HAS_SYM_DISP /= 0) GENERATE + SYM_DISP <= sym_disp_i; + END GENERATE gsd; + ngsd : IF (C_HAS_SYM_DISP = 0) GENERATE + SYM_DISP <= "00"; + END GENERATE ngsd; + + ---------------------------------------------------------------------------- + -- Optional B Ports -- tying off unused ports + ---------------------------------------------------------------------------- + --Mandatory B ports (if B ports are selected) + gbpt : IF (C_HAS_BPORTS /= 0) GENERATE + din_b_i <= DIN_B; + clk_b_i <= CLK_B; + DOUT_B <= dout_b_i; + KOUT_B <= kout_b_i; + END GENERATE gbpt; + ngbpt : IF (C_HAS_BPORTS = 0) GENERATE + din_b_i <= (OTHERS => '0'); + clk_b_i <= '0'; + DOUT_B <= (OTHERS => '0'); + KOUT_B <= '0'; + END GENERATE ngbpt; + + --Inputs + --ce_b + genb : IF (C_HAS_CE_B /= 0 AND C_HAS_BPORTS /= 0) GENERATE + ce_b_i <= CE_B; + END GENERATE genb; + ngenb : IF (C_HAS_CE_B = 0 OR C_HAS_BPORTS = 0) GENERATE + ce_b_i <= '1'; + END GENERATE ngenb; + ASSERT (NOT(C_HAS_CE_B /= 0 AND C_HAS_BPORTS = 0)) + REPORT "Invalid configuration: Will not generate CE_B when C_HAS_BPORTS=0" + SEVERITY WARNING; + + --disp_in_b + gdib : IF (C_HAS_DISP_IN_B /= 0 AND C_HAS_BPORTS /= 0) GENERATE + disp_in_b_i <= DISP_IN_B; + END GENERATE gdib; + ngdib : IF (C_HAS_DISP_IN_B = 0 OR C_HAS_BPORTS = 0) GENERATE + disp_in_b_i <= '0'; + END GENERATE ngdib; + ASSERT (NOT(C_HAS_DISP_IN_B /= 0 AND C_HAS_BPORTS = 0)) + REPORT "Invalid configuration: Will not generate DISP_IN_B when " & + "C_HAS_BPORTS=0" + SEVERITY WARNING; + + --sinit_b + gsb : IF (C_HAS_SINIT_B /= 0 AND C_HAS_BPORTS /= 0) GENERATE + sinit_b_i <= SINIT_B; + END GENERATE gsb; + ngsb : IF (C_HAS_SINIT_B = 0 OR C_HAS_BPORTS = 0) GENERATE + sinit_b_i <= '0'; + END GENERATE ngsb; + ASSERT (NOT(C_HAS_SINIT_B /= 0 AND C_HAS_BPORTS = 0)) + REPORT "Invalid configuration: Will not generate SINIT_B when C_HAS_BPORTS=0" + SEVERITY WARNING; + + --Outputs + --code_err_b + gceb : IF (C_HAS_CODE_ERR_B /= 0 AND C_HAS_BPORTS /= 0) GENERATE + CODE_ERR_B <= code_err_b_i; + END GENERATE gceb; + ngceb : IF (C_HAS_CODE_ERR_B = 0 OR C_HAS_BPORTS = 0) GENERATE + CODE_ERR_B <= '0'; + END GENERATE ngceb; + ASSERT (NOT(C_HAS_CODE_ERR_B /= 0 AND C_HAS_BPORTS = 0)) + REPORT "Invalid configuration: Will not generate CODE_ERR_B when " & + "C_HAS_BPORTS=0" + SEVERITY WARNING; + + --disp_err_b + gdeb : IF (C_HAS_DISP_ERR_B /= 0 AND C_HAS_BPORTS /= 0) GENERATE + DISP_ERR_B <= disp_err_b_i; + END GENERATE gdeb; + ngdeb : IF (C_HAS_DISP_ERR_B = 0 OR C_HAS_BPORTS = 0) GENERATE + DISP_ERR_B <= '0'; + END GENERATE ngdeb; + ASSERT (NOT(C_HAS_DISP_ERR_B /= 0 AND C_HAS_BPORTS = 0)) + REPORT "Invalid configuration: Will not generate DISP_ERR_B when " & + "C_HAS_BPORTS=0" + SEVERITY WARNING; + + --nd_b + gndb : IF (C_HAS_ND_B /= 0 AND C_HAS_BPORTS /= 0) GENERATE + ASSERT (C_HAS_CE_B /= 0) + REPORT "Invalid configuration: ND_B port requires CE_B port" + SEVERITY WARNING; + ND_B <= nd_b_i; + END GENERATE gndb; + ngndb : IF (C_HAS_ND_B = 0 OR C_HAS_BPORTS = 0) GENERATE + ND_B <= '0'; + END GENERATE ngndb; + ASSERT (NOT(C_HAS_ND_B /= 0 AND C_HAS_BPORTS = 0)) + REPORT "Invalid configuration: Will not generate ND_B when C_HAS_BPORTS=0" + SEVERITY WARNING; + + --run_disp_b + grdb : IF (C_HAS_RUN_DISP_B /= 0 AND C_HAS_BPORTS /= 0) GENERATE + RUN_DISP_B <= run_disp_b_i; + END GENERATE grdb; + ngrdb : IF (C_HAS_RUN_DISP_B = 0 OR C_HAS_BPORTS = 0) GENERATE + RUN_DISP_B <= '0'; + END GENERATE ngrdb; + ASSERT (NOT(C_HAS_RUN_DISP_B /= 0 AND C_HAS_BPORTS = 0)) + REPORT "Invalid configuration: Will not generate RUN_DISP_B when " & + "C_HAS_BPORTS=0" + SEVERITY WARNING; + + --sym_disp_b + gsdb : IF (C_HAS_SYM_DISP_B /= 0 AND C_HAS_BPORTS /= 0) GENERATE + SYM_DISP_B <= sym_disp_b_i; + END GENERATE gsdb; + ngsdb : IF (C_HAS_SYM_DISP_B = 0 OR C_HAS_BPORTS = 0) GENERATE + SYM_DISP_B <= "00"; + END GENERATE ngsdb; + ASSERT (NOT(C_HAS_SYM_DISP_B /= 0 AND C_HAS_BPORTS = 0)) + REPORT "Invalid configuration: Will not generate SYM_DISP_B when " & + "C_HAS_BPORTS=0" + SEVERITY WARNING; + +END xilinx; + diff --git a/rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_top.vhd b/rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_top.vhd new file mode 100644 index 00000000..b9f4d238 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_top.vhd @@ -0,0 +1,280 @@ +------------------------------------------------------------------------------- +-- +-- Module : decode_8b10b_top.vhd +-- +-- Version : 1.1 +-- +-- Last Update : 2008-10-31 +-- +-- Project : 8b/10b Decoder Reference Design +-- +-- Description : Core wrapper file +-- +-- Company : Xilinx, Inc. +-- +-- DISCLAIMER OF LIABILITY +-- +-- This file contains proprietary and confidential information of +-- Xilinx, Inc. ("Xilinx"), that is distributed under a license +-- from Xilinx, and may be used, copied and/or disclosed only +-- pursuant to the terms of a valid license agreement with Xilinx. +-- +-- XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION +-- ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +-- EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT +-- LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT, +-- MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx +-- does not warrant that functions included in the Materials will +-- meet the requirements of Licensee, or that the operation of the +-- Materials will be uninterrupted or error-free, or that defects +-- in the Materials will be corrected. Furthermore, Xilinx does +-- not warrant or make any representations regarding use, or the +-- results of the use, of the Materials in terms of correctness, +-- accuracy, reliability or otherwise. +-- +-- Xilinx products are not designed or intended to be fail-safe, +-- or for use in any application requiring fail-safe performance, +-- such as life-support or safety devices or systems, Class III +-- medical devices, nuclear facilities, applications related to +-- the deployment of airbags, or any other applications that could +-- lead to death, personal injury or severe property or +-- environmental damage (individually and collectively, "critical +-- applications"). Customer assumes the sole risk and liability +-- of any use of Xilinx products in critical applications, +-- subject only to applicable laws and regulations governing +-- limitations on product liability. +-- +-- Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2008 Xilinx, Inc. +-- All rights reserved. +-- +-- This disclaimer and copyright notice must be retained as part +-- of this file at all times. +-- +------------------------------------------------------------------------------- +-- +-- History +-- +-- Date Version Description +-- +-- 10/31/2008 1.1 Initial release +-- +------------------------------------------------------------------------------- + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; + + +LIBRARY decode_8b10b; +USE work.decode_8b10b_pkg.ALL; + +------------------------------------------------------------------------------- +-- Entity Declaration +------------------------------------------------------------------------------- +ENTITY decode_8b10b_top IS + GENERIC ( + C_DECODE_TYPE : INTEGER := 0; + C_HAS_BPORTS : INTEGER := 0; + C_HAS_CE : INTEGER := 0; + C_HAS_CODE_ERR : INTEGER := 0; + C_HAS_DISP_ERR : INTEGER := 0; + C_HAS_DISP_IN : INTEGER := 0; + C_HAS_ND : INTEGER := 0; + C_HAS_RUN_DISP : INTEGER := 0; + C_HAS_SINIT : INTEGER := 0; + C_HAS_SYM_DISP : INTEGER := 0; + C_SINIT_VAL : STRING(1 TO 10) := "0000000000"; + C_SINIT_VAL_B : STRING(1 TO 10) := "0000000000" + ); + + PORT ( + CLK : IN STD_LOGIC := '0'; + DIN : IN STD_LOGIC_VECTOR(9 DOWNTO 0) := (OTHERS => '0'); + DOUT : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) ; + KOUT : OUT STD_LOGIC ; + + CE : IN STD_LOGIC := '0'; + CE_B : IN STD_LOGIC := '0'; + CLK_B : IN STD_LOGIC := '0'; + DIN_B : IN STD_LOGIC_VECTOR(9 DOWNTO 0) := (OTHERS => '0'); + DISP_IN : IN STD_LOGIC := '0'; + DISP_IN_B : IN STD_LOGIC := '0'; + SINIT : IN STD_LOGIC := '0'; + SINIT_B : IN STD_LOGIC := '0'; + CODE_ERR : OUT STD_LOGIC := '0'; + CODE_ERR_B : OUT STD_LOGIC := '0'; + DISP_ERR : OUT STD_LOGIC := '0'; + DISP_ERR_B : OUT STD_LOGIC := '0'; + DOUT_B : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) ; + KOUT_B : OUT STD_LOGIC ; + ND : OUT STD_LOGIC := '0'; + ND_B : OUT STD_LOGIC := '0'; + RUN_DISP : OUT STD_LOGIC ; + RUN_DISP_B : OUT STD_LOGIC ; + SYM_DISP : OUT STD_LOGIC_VECTOR(1 DOWNTO 0) ; + SYM_DISP_B : OUT STD_LOGIC_VECTOR(1 DOWNTO 0) + ); +-------------------------------------------------------------------------------- +-- Port Definitions: +-------------------------------------------------------------------------------- + -- Mandatory Pins + -- CLK : Clock Input + -- DIN : Encoded Symbol Input + -- DOUT : Data Output, decoded data byte + -- KOUT : Command Output + ------------------------------------------------------------------------- + -- Optional Pins + -- CE : Clock Enable + -- CE_B : Clock Enable (B port) + -- CLK_B : Clock Input (B port) + -- DIN_B : Encoded Symbol Input (B port) + -- DISP_IN : Disparity Input (running disparity in) + -- DISP_IN_B : Disparity Input (running disparity in) (B port) + -- SINIT : Synchronous Initialization. Resets core to known state. + -- SINIT_B : Synchronous Initialization. Resets core to known state. + -- (B port) + -- CODE_ERR : Code Error, indicates that input symbol did not correspond + -- to a valid member of the code set. + -- CODE_ERR_B : Code Error, indicates that input symbol did not correspond + -- to a valid member of the code set. (B port) + -- DISP_ERR : Disparity Error + -- DISP_ERR_B : Disparity Error (B port) + -- DOUT_B : Data Output, decoded data byte (B port) + -- KOUT_B : Command Output (B port) + -- ND : New Data + -- ND_B : New Data (B port) + -- RUN_DISP : Running Disparity + -- RUN_DISP_B : Running Disparity (B port) + -- SYM_DISP : Symbol Disparity + -- SYM_DISP_B : Symbol Disparity (B port) + ------------------------------------------------------------------------- +END decode_8b10b_top; + + +------------------------------------------------------------------------------- +-- Architecture +------------------------------------------------------------------------------- +ARCHITECTURE xilinx OF decode_8b10b_top IS + +CONSTANT SINIT_DOUT : STRING(1 TO 8) := C_SINIT_VAL(1 TO 8); +CONSTANT SINIT_DOUT_B : STRING(1 TO 8) := C_SINIT_VAL_B(1 TO 8); +CONSTANT SINIT_RD : INTEGER := calc_init_val_rd(C_SINIT_VAL); + -- converts C_SINIT_VAL string to integer +CONSTANT SINIT_RD_B : INTEGER := calc_init_val_rd(C_SINIT_VAL_B); + -- converts C_SINIT_VAL_B string to integer + +-- If C_HAS_BPORTS=1, the optional B ports are configured the same way as the +-- optional A ports. Otherwise, all the B ports are disabled. +CONSTANT C_HAS_CE_B : INTEGER := has_bport(C_HAS_BPORTS, C_HAS_CE); +CONSTANT C_HAS_CODE_ERR_B : INTEGER := has_bport(C_HAS_BPORTS, C_HAS_CODE_ERR); +CONSTANT C_HAS_DISP_ERR_B : INTEGER := has_bport(C_HAS_BPORTS, C_HAS_DISP_ERR); +CONSTANT C_HAS_DISP_IN_B : INTEGER := has_bport(C_HAS_BPORTS, C_HAS_DISP_IN); +CONSTANT C_HAS_ND_B : INTEGER := has_bport(C_HAS_BPORTS, C_HAS_ND); +CONSTANT C_HAS_RUN_DISP_B : INTEGER := has_bport(C_HAS_BPORTS, C_HAS_RUN_DISP); +CONSTANT C_HAS_SINIT_B : INTEGER := has_bport(C_HAS_BPORTS, C_HAS_SINIT); +CONSTANT C_HAS_SYM_DISP_B : INTEGER := has_bport(C_HAS_BPORTS, C_HAS_SYM_DISP); + +------------------------------------------------------------------------------- +-- BEGIN ARCHITECTURE +------------------------------------------------------------------------------- +BEGIN + +dec : ENTITY decode_8b10b_rtl + GENERIC MAP ( + C_DECODE_TYPE => C_DECODE_TYPE, + C_ELABORATION_DIR => "./", + C_HAS_BPORTS => C_HAS_BPORTS, + C_HAS_CE => C_HAS_CE, + C_HAS_CE_B => C_HAS_CE_B, + C_HAS_CODE_ERR => C_HAS_CODE_ERR, + C_HAS_CODE_ERR_B => C_HAS_CODE_ERR_B, + C_HAS_DISP_ERR => C_HAS_DISP_ERR, + C_HAS_DISP_ERR_B => C_HAS_DISP_ERR_B, + C_HAS_DISP_IN => C_HAS_DISP_IN, + C_HAS_DISP_IN_B => C_HAS_DISP_IN_B, + C_HAS_ND => C_HAS_ND, + C_HAS_ND_B => C_HAS_ND_B, + C_HAS_RUN_DISP => C_HAS_RUN_DISP, + C_HAS_RUN_DISP_B => C_HAS_RUN_DISP_B, + C_HAS_SINIT => C_HAS_SINIT, + C_HAS_SINIT_B => C_HAS_SINIT_B, + C_HAS_SYM_DISP => C_HAS_SYM_DISP, + C_HAS_SYM_DISP_B => C_HAS_SYM_DISP_B, + C_SINIT_DOUT => SINIT_DOUT, + C_SINIT_DOUT_B => SINIT_DOUT_B, + C_SINIT_KOUT => 0, + C_SINIT_KOUT_B => 0, + C_SINIT_RUN_DISP => SINIT_RD, + C_SINIT_RUN_DISP_B => SINIT_RD_B + ) + PORT MAP( + CLK => CLK, + DIN => DIN, + DOUT => DOUT, + KOUT => KOUT, + CE => CE, + CE_B => CE_B, + CLK_B => CLK_B, + DIN_B => DIN_B, + DISP_IN => DISP_IN, + DISP_IN_B => DISP_IN_B, + SINIT => SINIT, + SINIT_B => SINIT_B, + CODE_ERR => CODE_ERR, + CODE_ERR_B => CODE_ERR_B, + DISP_ERR => DISP_ERR, + DISP_ERR_B => DISP_ERR_B, + DOUT_B => DOUT_B, + KOUT_B => KOUT_B, + ND => ND, + ND_B => ND_B, + RUN_DISP => RUN_DISP, + RUN_DISP_B => RUN_DISP_B, + SYM_DISP => SYM_DISP, + SYM_DISP_B => SYM_DISP_B + ); +-------------------------------------------------------------------------------- +-- Generic Definitions: +-------------------------------------------------------------------------------- + -- C_DECODE_TYPE : Implementation: 0=Slice based, 1=BlockRam + -- C_ELABORATION_DIR : Directory path for mif file + -- C_HAS_BPORTS : 1 indicates second decoder should be generated + -- C_HAS_CE : 1 indicates ce port is present + -- C_HAS_CE_B : 1 indicates ce_b port is present (if c_has_bports=1) + -- C_HAS_CODE_ERR : 1 indicates code_err port is present + -- C_HAS_CODE_ERR_B : 1 indicates code_err_b port is present + -- (if c_has_bports=1) + -- C_HAS_DISP_ERR : 1 indicates disp_err port is present + -- C_HAS_DISP_ERR_B : 1 indicates disp_err_b port is present + -- (if c_has_bports=1) + -- C_HAS_DISP_IN : 1 indicates disp_in port is present + -- C_HAS_DISP_IN_B : 1 indicates disp_in_b port is present + -- (if c_has_bports=1) + -- C_HAS_ND : 1 indicates nd port is present + -- C_HAS_ND_B : 1 indicates nd_b port is present (if c_has_bports=1) + -- C_HAS_RUN_DISP : 1 indicates run_disp port is present + -- C_HAS_RUN_DISP_B : 1 indicates run_disp_b port is present + -- (if c_has_bports=1) + -- C_HAS_SINIT : 1 indicates sinit port is present + -- C_HAS_SINIT_B : 1 indicates sinit_b port is present + -- (if c_has_bports=1) + -- C_HAS_SYM_DISP : 1 indicates sym_disp port is present + -- C_HAS_SYM_DISP_B : 1 indicates sym_disp_b port is present + -- (if c_has_bports=1) + -- C_SINIT_DOUT : 8-bit binary string, dout value when sinit is active + -- C_SINIT_DOUT_B : 8-bit binary string, dout_b value when sinit_b is + -- active + -- C_SINIT_KOUT : controls kout output when sinit is active + -- C_SINIT_KOUT_B : controls kout_b output when sinit_b is active + -- C_SINIT_RUN_DISP : Initializes run_disp (and disp_in) value to + -- positive(1) or negative(0) + -- C_SINIT_RUN_DISP_B : Initializes run_disp_b (and disp_in_b) value to + -- positive(1) or negative(0) +-------------------------------------------------------------------------------- + + +END xilinx; + + + + + diff --git a/rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_wrapper.vhd b/rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_wrapper.vhd new file mode 100644 index 00000000..50e45f9b --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/decode_8b10b_wrapper.vhd @@ -0,0 +1,215 @@ +------------------------------------------------------------------------------- +-- +-- Module : decode_8b10b_wrapper.vhd +-- +-- Version : 1.1 +-- +-- Last Update : 2008-10-31 +-- +-- Project : 8b/10b Decoder +-- +-- Description : Top-level core wrapper file +-- +-- Company : Xilinx, Inc. +-- +-- DISCLAIMER OF LIABILITY +-- +-- This file contains proprietary and confidential information of +-- Xilinx, Inc. ("Xilinx"), that is distributed under a license +-- from Xilinx, and may be used, copied and/or disclosed only +-- pursuant to the terms of a valid license agreement with Xilinx. +-- +-- XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION +-- ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +-- EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT +-- LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT, +-- MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx +-- does not warrant that functions included in the Materials will +-- meet the requirements of Licensee, or that the operation of the +-- Materials will be uninterrupted or error-free, or that defects +-- in the Materials will be corrected. Furthermore, Xilinx does +-- not warrant or make any representations regarding use, or the +-- results of the use, of the Materials in terms of correctness, +-- accuracy, reliability or otherwise. +-- +-- Xilinx products are not designed or intended to be fail-safe, +-- or for use in any application requiring fail-safe performance, +-- such as life-support or safety devices or systems, Class III +-- medical devices, nuclear facilities, applications related to +-- the deployment of airbags, or any other applications that could +-- lead to death, personal injury or severe property or +-- environmental damage (individually and collectively, "critical +-- applications"). Customer assumes the sole risk and liability +-- of any use of Xilinx products in critical applications, +-- subject only to applicable laws and regulations governing +-- limitations on product liability. +-- +-- Copyright 2008 Xilinx, Inc. All rights reserved. +-- +-- This disclaimer and copyright notice must be retained as part +-- of this file at all times. +-- +------------------------------------------------------------------------------- +-- +-- History +-- +-- Date Version Description +-- +-- 10/31/2008 1.1 Initial release +-- +------------------------------------------------------------------------------- + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; + + +LIBRARY decode_8b10b; + +------------------------------------------------------------------------------- +-- Entity Declaration +------------------------------------------------------------------------------- +ENTITY decode_8b10b_wrapper IS + PORT ( + + CLK : IN STD_LOGIC := '0'; + DIN : IN STD_LOGIC_VECTOR(9 DOWNTO 0) := (OTHERS => '0'); + DOUT : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) ; + KOUT : OUT STD_LOGIC ; + + CE : IN STD_LOGIC := '0'; + SINIT : IN STD_LOGIC := '0'; + CODE_ERR : OUT STD_LOGIC := '0'; + ND : OUT STD_LOGIC := '0' + + + + ); +-------------------------------------------------------------------------------- +-- Port Definitions: +-------------------------------------------------------------------------------- + -- Mandatory Pins + -- CLK : Clock Input + -- DIN : Encoded Symbol Input + -- DOUT : Data Output, decoded data byte + -- KOUT : Command Output + ------------------------------------------------------------------------- + -- Optional Pins + -- CLK_B : Clock Input (B port) + -- DIN_B : Encoded Symbol Input (B port) + -- DOUT_B : Data Output, decoded data byte (B port) + -- KOUT_B : Command Output (B port) + -- CE : Clock Enable + -- SINIT : Synchronous Initialization. Resets core to known state. + -- DISP_IN : Disparity Input (running disparity in) + -- CODE_ERR : Code Error, indicates that input symbol did not correspond + -- to a valid member of the code set. + -- DISP_ERR : Disparity Error + -- ND : New Data + -- RUN_DISP : Running Disparity + -- SYM_DISP : Symbol Disparity + -- CE_B : Clock Enable (B port) + -- SINIT_B : Synchronous Initialization. Resets core to known state. + -- (B port) + -- DISP_IN_B : Disparity Input (running disparity in) (B port) + -- CODE_ERR_B : Code Error, indicates that input symbol did not correspond + -- to a valid member of the code set. (B port) + -- DISP_ERR_B : Disparity Error (B port) + -- ND_B : New Data (B port) + -- RUN_DISP_B : Running Disparity (B port) + -- SYM_DISP_B : Symbol Disparity (B port) +---------------------------------------------------------------------------- +END decode_8b10b_wrapper; + +------------------------------------------------------------------------------- +-- Architecture +------------------------------------------------------------------------------- +ARCHITECTURE xilinx OF decode_8b10b_wrapper IS + + CONSTANT LOW : STD_LOGIC := '0'; + CONSTANT HIGH : STD_LOGIC := '1'; + CONSTANT LOWSLV : STD_LOGIC_VECTOR(9 DOWNTO 0) := (OTHERS => '0'); + +------------------------------------------------------------------------------- +-- BEGIN ARCHITECTURE +------------------------------------------------------------------------------- +BEGIN + +dec : ENTITY decode_8b10b_top + GENERIC MAP ( + C_DECODE_TYPE => 1, + C_HAS_BPORTS => 0, + C_HAS_CE => 1, + C_HAS_CODE_ERR => 1, + C_HAS_DISP_ERR => 0, + C_HAS_DISP_IN => 0, + C_HAS_ND => 1, + C_HAS_RUN_DISP => 0, + C_HAS_SINIT => 1, + C_HAS_SYM_DISP => 0, + C_SINIT_VAL => "0000000001", + C_SINIT_VAL_B => "0000000000" + ) + PORT MAP( + CLK => CLK, + DIN => DIN, + DOUT => DOUT, + KOUT => KOUT, + + CE => CE, + SINIT => SINIT, + DISP_IN => LOW, + CODE_ERR => CODE_ERR, + DISP_ERR => open, + ND => ND, + RUN_DISP => open, + SYM_DISP => open, + + CLK_B => LOW, + DIN_B => LOWSLV, + DOUT_B => open, + KOUT_B => open, + + CE_B => HIGH, + SINIT_B => LOW, + DISP_IN_B => LOW, + CODE_ERR_B => open, + DISP_ERR_B => open, + ND_B => open, + RUN_DISP_B => open, + SYM_DISP_B => open + + ); +-------------------------------------------------------------------------------- +-- Generic Definitions: +-------------------------------------------------------------------------------- + -- C_DECODE_TYPE : Implementation: 0=LUT based, 1=BRAM based + -- C_HAS_BPORTS : 1 indicates second decoder should be generated + -- C_HAS_CE : 1 indicates ce(_b) port is present + -- C_HAS_CODE_ERR : 1 indicates code_err(_b) port is present + -- C_HAS_DISP_ERR : 1 indicates disp_err(_b) port is present + -- C_HAS_DISP_IN : 1 indicates disp_in(_b) port is present + -- C_HAS_ND : 1 indicates nd(_b) port is present + -- C_HAS_RUN_DISP : 1 indicates run_disp(_b) port is present + -- C_HAS_SINIT : 1 indicates sinit(_b) port is present + -- C_HAS_SYM_DISP : 1 indicates sym_disp(_b) port is present + -- C_SINIT_VAL : 10-bit binary string, dout/kout/run_disp init value + -- C_SINIT_VAL_B : 10-bit binary string, dout_b/kout_b/run_disp_b init + -- value +-------------------------------------------------------------------------------- + +-------------------------------------------------------- +-- C_SINIT_VAL/C_SINIT_VAL_B {DOUT,KOUT,RD} +-------------------------------------------------------- + -- D.0.0 (pos) DOUT: 000_00000 KOUT: 0 RD: 1 + -- D.0.0 (neg) DOUT: 000_00000 KOUT: 0 RD: 0 + -- D.10.2 (pos) DOUT: 010_01010 KOUT: 0 RD: 1 + -- D.10.2 (neg) DOUT: 010_01010 KOUT: 0 RD: 0 + -- D.21.5 (pos) DOUT: 101_10101 KOUT: 0 RD: 1 + -- D.21.5 (neg) DOUT: 101_10101 KOUT: 0 RD: 0 +-------------------------------------------------------- + + +END xilinx; + + + diff --git a/rce/fw-hsio/modules/pixelcore/hdl/decodefei4record.vhd b/rce/fw-hsio/modules/pixelcore/hdl/decodefei4record.vhd new file mode 100644 index 00000000..15566863 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/decodefei4record.vhd @@ -0,0 +1,96 @@ +-------------------------------------------------------------- +-- Serializer for High Speed I/O board (ATLAS Pixel teststand) +-- Martin Kocian 01/2009 +-------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use work.all; + +-------------------------------------------------------------- + +entity decodefei4record is +port( clk: in std_logic; + rst: in std_logic; + enabled: in std_logic; + isrunning: out std_logic; + d_in: in std_logic_vector(7 downto 0); + k_in: in std_logic; + err_in: in std_logic; + d_out: out std_logic_vector(24 downto 0); + ldin: in std_logic; + ldout: out std_logic; + overflow: out std_logic +-- acounter: out std_logic_vector(15 downto 0) +); +end decodefei4record; + +-------------------------------------------------------------- + +architecture DECODEFEI4RECORD of decodefei4record is + +signal running: std_logic; +signal parity: natural range 0 to 2:=0; +signal wordcount: std_logic_vector(11 downto 0); +signal dint: std_logic_vector(23 downto 0):=(others => '0'); +signal nowrite: std_logic := '0'; + +begin + isrunning<=running; + process(rst, clk) + begin + if(rst='1') then + d_out<=(others => '0'); + running<='0'; + parity<=0; + ldout<='0'; + overflow<='0'; + wordcount<=(others =>'0'); + nowrite<='0'; + elsif (clk'event and clk='1') then + if(ldin='1')then + d_out(23 downto 0)<=dint; + if(running='0')then + if(enabled='1' and d_in=x"fc" and k_in='1')then -- SOF + d_out(24)<='0'; + running<='1'; + parity<=2; + ldout<='0'; + wordcount<=(others =>'0'); + nowrite<='1'; + end if; + else -- running + if(k_in='1' or err_in='1' or wordcount=x"800")then --EOF or idle or error + running<='0'; + if(wordcount=x"800")then + overflow<='1'; + end if; + ldout<='1'; + d_out(24)<='1'; + else-- data + dint(parity*8+7 downto parity*8)<=d_in; + if(parity=0)then + parity<=2; + wordcount<=unsigned(wordcount)+1; + elsif(parity=2)then + if(nowrite='0')then + ldout<='1'; + end if; + nowrite<='0'; + parity<=1; + else + parity<=0; + end if; + end if; + end if; + else + ldout<='0'; + end if; + end if; + + end process; + +end DECODEFEI4RECORD; + +-------------------------------------------------------------- diff --git a/rce/fw-hsio/modules/pixelcore/hdl/deser.vhd b/rce/fw-hsio/modules/pixelcore/hdl/deser.vhd new file mode 100644 index 00000000..c94c0bd5 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/deser.vhd @@ -0,0 +1,131 @@ +-------------------------------------------------------------- +-- Serializer for High Speed I/O board (ATLAS Pixel teststand) +-- Martin Kocian 01/2009 +-------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use work.all; + +-------------------------------------------------------------- + +entity deser is +generic( CHANNEL: std_logic_vector:="1111"); +port( clk: in std_logic; + rst: in std_logic; + d_in: in std_logic; + enabled: in std_logic; + replynow: in std_logic; + marker: in std_logic; + d_out: out std_logic_vector(15 downto 0); + ld: out std_logic; + sof: out std_logic; + eof: out std_logic +); +end deser; + +-------------------------------------------------------------- + +architecture DESER of deser is + +signal reg : std_logic_vector(15 downto 0); +signal parcounter: std_logic_vector(1 downto 0); +signal nodata: std_logic; +signal oldmarker: std_logic; +signal marked: std_logic; +signal eventmark: std_logic; + +begin + + + process(rst, clk) + + variable counter: std_logic_vector(3 downto 0); + variable zerocounter: std_logic_vector(6 downto 0); + variable headercounter: std_logic_vector(3 downto 0); + variable going: std_logic; + begin + if(rst='1') then + reg<=x"0000"; + d_out<=x"0000"; + going:='0'; + eof<='0'; + sof<='0'; + headercounter:="0000"; + ld<='0'; + parcounter<="00"; + oldmarker<='0'; + marked<='0'; + eventmark<='0'; + elsif (clk'event and clk='1') then + if (d_in='1')then + zerocounter:="0000000"; + else + zerocounter:=unsigned(zerocounter)+1; + end if; + oldmarker<=marker; + if(marker='1' and oldmarker='0')then + eventmark<='1'; + elsif(marked='1')then + eventmark<='0'; + end if; + if(going='0' and ((enabled='1' and d_in='1') or replynow='1'))then + going:='1'; + counter:="1111"; + eof<='0'; + zerocounter:="0000000"; + headercounter:="1111"; + parcounter<="00"; + nodata<=replynow; + elsif (going='1' and counter="1111") then + parcounter<=unsigned(parcounter)+1; + d_out<=reg; + if(nodata='1')then + going:='0'; + ld<='0'; + else + ld<='1'; + if(zerocounter>="0100000" and parcounter="11")then + eof<='1'; + going:='0'; + else + eof<='0'; + end if; + end if; + elsif(counter="1110" and headercounter="0000")then + ld<='0'; + end if; + if (unsigned(headercounter)>0)then -- we have to squeeze in the header + ld<='1'; -- before the first event + if(headercounter="1111")then + sof<='1'; + d_out<=(others=>'0'); + elsif(headercounter="1110")then + sof<='0'; + d_out(7 downto 0)<=(others=>'0'); + d_out(15 downto 8)<=x"0"&CHANNEL; + elsif(headercounter="1100")then + d_out<=eventmark&"000"&x"000"; + sof<='0'; + marked<='1'; + else + sof<='0'; + d_out<=(others=>'0'); + marked<='0'; + end if; + headercounter:=unsigned(headercounter)-1; + elsif(nodata='1' and headercounter="0000")then + eof<='1'; + d_out<=(others=>'0'); + end if; + reg(15 downto 1)<=reg(14 downto 0); + reg(0)<=d_in; + counter:=unsigned(counter)-1; + end if; + + end process; + +end DESER; + +-------------------------------------------------------------- diff --git a/rce/fw-hsio/modules/pixelcore/hdl/deser10b.vhd b/rce/fw-hsio/modules/pixelcore/hdl/deser10b.vhd new file mode 100644 index 00000000..ad6260b6 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/deser10b.vhd @@ -0,0 +1,64 @@ +-------------------------------------------------------------- +-- Serializer for High Speed I/O board (ATLAS Pixel teststand) +-- Martin Kocian 01/2009 +-------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use work.all; + +-------------------------------------------------------------- + +entity deser10b is +port( clk: in std_logic; + rst: in std_logic; + d_in: in std_logic; + align: in std_logic; + d_out: out std_logic_vector(9 downto 0); + ld: out std_logic +); +end deser10b; + +-------------------------------------------------------------- + +architecture DESER10B of deser10b is + +signal reg : std_logic_vector(9 downto 0); +signal index : std_logic_vector(3 downto 0); +signal aligned: std_logic; + +begin + process(rst, clk) + begin + if(rst='1') then + reg<=x"00"&"00"; + index<=x"0"; + ld<='0'; + aligned<='0'; + elsif (clk'event and clk='1') then + if(align='1' and (aligned='0' or index/=x"0"))then + index<=x"9"; + ld<='0'; + aligned<='1'; + elsif(index=x"0")then + index<=x"9"; + if(aligned='1')then + ld<='1'; + d_out<=reg; + else + ld<='0'; + end if; + else + index<=unsigned(index)-1; + ld<='0'; + end if; + reg(8 downto 0)<=reg(9 downto 1); + reg(9)<=d_in; + end if; + + end process; + +end DESER10B; + +-------------------------------------------------------------- diff --git a/rce/fw-hsio/modules/pixelcore/hdl/deser4b.vhd b/rce/fw-hsio/modules/pixelcore/hdl/deser4b.vhd new file mode 100644 index 00000000..d0056def --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/deser4b.vhd @@ -0,0 +1,64 @@ +-------------------------------------------------------------- +-- Serializer for High Speed I/O board (ATLAS Pixel teststand) +-- Martin Kocian 01/2009 +-------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use work.all; + +-------------------------------------------------------------- + +entity deser4b is +port( clk: in std_logic; + rst: in std_logic; + d_in: in std_logic; + align: in std_logic; + d_out: out std_logic_vector(3 downto 0); + ld: out std_logic +); +end deser4b; + +-------------------------------------------------------------- + +architecture DESER4B of deser4b is + +signal reg : std_logic_vector(3 downto 0); +signal index : std_logic_vector(3 downto 0); +signal aligned: std_logic; + +begin + process(rst, clk) + begin + if(rst='1') then + reg<=x"0"; + index<=x"0"; + ld<='0'; + aligned<='0'; + elsif (clk'event and clk='1') then + if(align='1' and (aligned='0' or index/=x"0"))then + index<=x"3"; + ld<='0'; + aligned<='1'; + elsif(index=x"0")then + index<=x"3"; + if(aligned='1')then + ld<='1'; + d_out<=reg; + else + ld<='0'; + end if; + else + index<=unsigned(index)-1; + ld<='0'; + end if; + reg(3 downto 1)<=reg(2 downto 0); + reg(0)<=d_in; + end if; + + end process; + +end DESER4B; + +-------------------------------------------------------------- diff --git a/rce/fw-hsio/modules/pixelcore/hdl/encodepgp.vhd b/rce/fw-hsio/modules/pixelcore/hdl/encodepgp.vhd new file mode 100644 index 00000000..16022f68 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/encodepgp.vhd @@ -0,0 +1,157 @@ +-------------------------------------------------------------- +-- Serializer for High Speed I/O board (ATLAS Pixel teststand) +-- Martin Kocian 01/2009 +-------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use work.all; + +-------------------------------------------------------------- + +entity encodepgp is +generic( CHANNEL: std_logic_vector:="1111"); +port( clk: in std_logic; + rst: in std_logic; + enabled: in std_logic; + isrunning: out std_logic; + d_in: in std_logic_vector(7 downto 0); + k_in: in std_logic; + err_in: in std_logic; + marker: in std_logic; + d_out: out std_logic_vector(17 downto 0); + ldin: in std_logic; + ldout: out std_logic; + overflow: out std_logic +-- acounter: out std_logic_vector(15 downto 0) +); +end encodepgp; + +-------------------------------------------------------------- + +architecture ENCODEPGP of encodepgp is + +signal running: std_logic; +signal headercounter: std_logic_vector(3 downto 0); +signal parity: std_logic_vector(1 downto 0); +signal trailer: std_logic; +signal msb: std_logic_vector(7 downto 0); +signal oldmarker: std_logic; +signal oldoldmarker: std_logic; +signal marked: std_logic; +signal eventmark: std_logic; +signal wordcount: std_logic_vector(11 downto 0); + +begin + isrunning<=running; + process(rst, clk) + begin + if(rst='1') then + d_out<=x"0000"&"00"; + --acounter<=x"0000"; + running<='0'; + headercounter<=x"0"; + parity<="00"; + trailer<='0'; + msb<=x"00"; + ldout<='0'; + oldmarker<='0'; + oldoldmarker<='0'; + marked<='0'; + eventmark<='0'; + overflow<='0'; + wordcount<=(others =>'0'); + elsif (clk'event and clk='1') then + oldmarker<=marker; + oldoldmarker<=oldmarker; + if(marker='1' and oldoldmarker='0')then + eventmark<='1'; + elsif(marked='1')then + eventmark<='0'; + end if; + if(ldin='1')then + if(running='0')then + if(enabled='1' and d_in=x"fc" and k_in='1')then -- SOF + headercounter<="1111"; + d_out<="01"&x"0000"; -- SOF + running<='1'; + parity<="01"; + ldout<='1'; + trailer<='0'; + wordcount<=(others =>'0'); + end if; + else -- running + if(k_in='1' or err_in='1' or wordcount=x"800")then --EOF or idle or error + --if((d_in=x"bc")and k_in='1')then --EOF or idle in case of failure + running<='0'; + if(wordcount=x"800")then + overflow<='1'; + end if; + if(headercounter/="0000")then -- sequence was SOF EOF + trailer<='1'; + ldout<='0'; + else + ldout<='1'; + if(parity(0)='0')then + d_out(15 downto 0)<=x"0000"; + else + d_out(15 downto 0)<= msb & x"00"; + end if; + if(parity(1)='0')then + trailer<='1'; + d_out(17 downto 16)<="00"; + else + trailer<='0'; + d_out(17 downto 16)<="10"; + end if; + end if; + --elsif(err_in='1' or k_in='1')then + -- acounter<=unsigned(acounter)+1; + else-- data + parity<=unsigned(parity)+1; + if(parity(0)='0')then --MSB + ldout<='0'; + msb<=d_in; + else -- LSB + wordcount<=unsigned(wordcount)+1; + ldout<='1'; + d_out(15 downto 0)<=msb & d_in; + d_out(17 downto 16)<="00"; + end if; + end if; + end if; + else + if(headercounter/="0000")then + ldout<='1'; + parity<=unsigned(parity)+1; + headercounter<=unsigned(headercounter)-1; + if(headercounter="1111")then + d_out(7 downto 0)<=(others=>'0'); + d_out(15 downto 8)<=x"0"&CHANNEL; + d_out(17 downto 16)<="00"; + elsif(headercounter="1101")then + d_out<="00"&eventmark&"000"&x"000"; + marked<='1'; + elsif(headercounter="0001" and trailer='1')then + d_out<="10"&x"0000"; --EOF + trailer<='0'; + else + d_out<=(others=>'0'); + marked<='0'; + end if; + elsif(trailer='1')then + ldout<='1'; + d_out<="10"&x"0000"; + trailer<='0'; + else + ldout<='0'; + end if; + end if; + end if; + + end process; + +end ENCODEPGP; + +-------------------------------------------------------------- diff --git a/rce/fw-hsio/modules/pixelcore/hdl/encodepgp24bit.vhd b/rce/fw-hsio/modules/pixelcore/hdl/encodepgp24bit.vhd new file mode 100644 index 00000000..e4404966 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/encodepgp24bit.vhd @@ -0,0 +1,197 @@ +-------------------------------------------------------------- +-- Serializer for High Speed I/O board (ATLAS Pixel teststand) +-- Martin Kocian 01/2009 +-------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use work.all; +use work.StdRtlPkg.all; + +-------------------------------------------------------------- + +entity encodepgp24bit is +generic( CHANNEL: std_logic_vector:="1111"); +port( clk: in std_logic; + rst: in std_logic; + enabled: in std_logic; + maxlength: in natural range 0 to 16383; + isrunning: out std_logic; + d_in: in std_logic_vector(24 downto 0); + d_next: in std_logic_vector(24 downto 0); + marker: in std_logic; + d_out: out std_logic_vector(17 downto 0); + ldin: in std_logic; + ldout: out std_logic; + dnextvalid: in std_logic; + dvalid: in std_logic; + datawaiting: in std_logic; + moredatawaiting: in std_logic; + overflow: out std_logic; + parout: out std_logic_vector(1 downto 0); + valid: out std_logic +); +end encodepgp24bit; + +-------------------------------------------------------------- + +architecture ENCODEPGP24BIT of encodepgp24bit is + +signal running: std_logic:='0'; +signal oldrunning: std_logic:='0'; +signal headercounter: std_logic_vector(3 downto 0); +signal parity: std_logic_vector(1 downto 0); +signal trailer: std_logic; +signal msb: std_logic_vector(15 downto 0); +signal oldmarker: std_logic; +signal oldoldmarker: std_logic; +signal marked: std_logic; +signal eventmark: std_logic; +signal wordcount: natural range 0 to 16383:=0; +signal enddata: std_logic := '0'; +signal skip: std_logic := '0'; +signal ldouts: std_logic := '0'; +signal nomore: std_logic := '0'; +signal init: std_logic := '0'; +signal olddatawaiting: std_logic := '0'; + +begin + isrunning<=running; + ldout<=ldouts; + parout<=parity; + ldouts<=(ldin and running and not uOr(headercounter) and (not parity(0) or skip) and not nomore) or init; + process(rst, clk) + begin + if(rst='1') then + d_out<=x"0000"&"00"; + --acounter<=x"0000"; + running<='0'; + headercounter<=x"0"; + parity<="00"; + trailer<='0'; + msb<=x"0000"; + valid<='0'; + oldmarker<='0'; + oldoldmarker<='0'; + marked<='0'; + eventmark<='0'; + overflow<='0'; + wordcount<=0; + skip<='0'; + enddata<='0'; + nomore<='0'; + init<='0'; + elsif (clk'event and clk='1') then + oldmarker<=marker; + oldoldmarker<=oldmarker; + olddatawaiting<=datawaiting; + if(marker='1' and oldoldmarker='0')then + eventmark<='1'; + elsif(marked='1')then + eventmark<='0'; + end if; + oldrunning<=running; + if(ldin='1')then + if(running='0')then + if(oldrunning='1')then + valid<='0'; + elsif(enabled='1' )then -- SOF + headercounter<="1111"; + d_out<="01"&x"0000"; -- SOF + running<='1'; + parity<="00"; + valid<='1'; + trailer<='0'; + wordcount<=0; + enddata<='0'; + skip<='0'; + nomore<='0'; + init<='1'; + end if; + else -- running + if(headercounter/="0000")then + valid<='1'; + headercounter<=unsigned(headercounter)-1; + if(headercounter="1111")then + init<='0'; + d_out(7 downto 0)<=(others=>'0'); + d_out(15 downto 8)<=x"0"&CHANNEL; + d_out(17 downto 16)<="00"; + elsif(headercounter="1101")then + d_out<="00"&eventmark&"000"&x"000"; + marked<='1'; + elsif(headercounter="0001") then + if(d_in(24)='1' and olddatawaiting='0' and (dnextvalid='0' or d_next(24)='0'))then + nomore<='1'; + end if; + else + d_out<=(others=>'0'); + marked<='0'; + end if; + elsif(trailer='1')then + valid<='1'; + d_out<="10"&x"0000"; + trailer<='0'; + running<='0'; + elsif(skip='1')then + valid<='1'; + d_out(15 downto 0)<=msb; + skip<='0'; + if(d_next(24)='1' and (moredatawaiting='0' or wordcount>MAXLENGTH))then + nomore<='1'; + end if; + elsif(enddata='1')then + valid<='1'; + if(parity(0)='1')then + d_out(15 downto 0)<= msb(7 downto 0) & x"00"; + else + d_out(15 downto 0)<=x"0000"; + end if; + if(parity="00" or parity="11")then + trailer<='1'; + d_out(17 downto 16)<="00"; + else + trailer<='0'; + d_out(17 downto 16)<="10"; + running<='0'; + end if; + else-- data + if(nomore='1')then + enddata<='1'; + elsif(moredatawaiting='0' or wordcount>MAXLENGTH)then + if(ldouts='1' and d_next(24)='1')then + nomore<='1'; + elsif(ldouts='0' and d_in(24)='1')then + nomore<='1'; + enddata<='1'; + end if; + if(wordcount>MAXLENGTH)then + overflow<='1'; + end if; + end if; + valid<='1'; + wordcount<=wordcount+1; + parity<=unsigned(parity)+1; + d_out(17 downto 16)<="00"; + if(parity(0)='0')then + msb(7 downto 0)<=d_in(7 downto 0); + d_out(15 downto 0)<=d_in(23 downto 8); + skip<='0'; + else + d_out(15 downto 0)<=msb(7 downto 0) & d_in(23 downto 16); + msb<=d_in(15 downto 0); + skip<='1'; + end if; + end if; + end if; + else + valid<='0'; + end if; + end if; + + end process; + +end ENCODEPGP24BIT; + +-------------------------------------------------------------- diff --git a/rce/fw-hsio/modules/pixelcore/hdl/eofcounter.vhd b/rce/fw-hsio/modules/pixelcore/hdl/eofcounter.vhd new file mode 100644 index 00000000..bb5d635c --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/eofcounter.vhd @@ -0,0 +1,113 @@ +-------------------------------------------------------------------------------- +-- This file is owned and controlled by Xilinx and must be used -- +-- solely for design, simulation, implementation and creation of -- +-- design files limited to Xilinx devices or technologies. Use -- +-- with non-Xilinx devices or technologies is expressly prohibited -- +-- and immediately terminates your license. -- +-- -- +-- XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" -- +-- SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR -- +-- XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION -- +-- AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION -- +-- OR STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS -- +-- IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, -- +-- AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE -- +-- FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY -- +-- WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE -- +-- IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR -- +-- REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF -- +-- INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -- +-- FOR A PARTICULAR PURPOSE. -- +-- -- +-- Xilinx products are not intended for use in life support -- +-- appliances, devices, or systems. Use in such applications are -- +-- expressly prohibited. -- +-- -- +-- (c) Copyright 1995-2007 Xilinx, Inc. -- +-- All rights reserved. -- +-------------------------------------------------------------------------------- +-- You must compile the wrapper file eofcounter.vhd when simulating +-- the core, eofcounter. When compiling the wrapper file, be sure to +-- reference the XilinxCoreLib VHDL simulation library. For detailed +-- instructions, please refer to the "CORE Generator Help". + +-- The synthesis directives "translate_off/translate_on" specified +-- below are supported by Xilinx, Mentor Graphics and Synplicity +-- synthesis tools. Ensure they are correct for your synthesis tool(s). + +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +-- synthesis translate_off +Library XilinxCoreLib; +-- synthesis translate_on +ENTITY eofcounter IS + port ( + clk: IN std_logic; + up: IN std_logic; + ce: IN std_logic; + aclr: IN std_logic; + q_thresh0: OUT std_logic; + q: OUT std_logic_VECTOR(15 downto 0)); +END eofcounter; + +ARCHITECTURE eofcounter_a OF eofcounter IS +-- synthesis translate_off +component wrapped_eofcounter + port ( + clk: IN std_logic; + up: IN std_logic; + ce: IN std_logic; + aclr: IN std_logic; + q_thresh0: OUT std_logic; + q: OUT std_logic_VECTOR(15 downto 0)); +end component; + +-- Configuration specification + for all : wrapped_eofcounter use entity XilinxCoreLib.c_counter_binary_v8_0(behavioral) + generic map( + c_count_mode => 2, + c_has_aset => 0, + c_load_enable => 0, + c_load_low => 0, + c_count_to => "1", + c_sync_priority => 1, + c_has_iv => 0, + c_has_sclr => 0, + c_restrict_count => 0, + c_width => 16, + c_has_q_thresh1 => 0, + c_enable_rlocs => 0, + c_has_q_thresh0 => 1, + c_thresh1_value => "0", + c_has_load => 0, + c_has_up => 1, + c_thresh_early => 1, + c_has_thresh1 => 0, + c_has_thresh0 => 0, + c_ainit_val => "0", + c_has_ce => 1, + c_pipe_stages => 0, + c_has_aclr => 1, + c_sync_enable => 1, + c_has_ainit => 0, + c_sinit_val => "0", + c_has_sset => 0, + c_has_sinit => 0, + c_count_by => "1", + c_has_l => 0, + c_thresh0_value => "0"); +-- synthesis translate_on +BEGIN +-- synthesis translate_off +U0 : wrapped_eofcounter + port map ( + clk => clk, + up => up, + ce => ce, + aclr => aclr, + q_thresh0 => q_thresh0, + q => q); +-- synthesis translate_on + +END eofcounter_a; + diff --git a/rce/fw-hsio/modules/pixelcore/hdl/eudaqTrigger.vhd b/rce/fw-hsio/modules/pixelcore/hdl/eudaqTrigger.vhd new file mode 100644 index 00000000..02fbb4fc --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/eudaqTrigger.vhd @@ -0,0 +1,86 @@ +------------------------------------------------------------------------------- +-- Description: +-- Core logic for BNL ASIC test FPGA. +------------------------------------------------------------------------------- +-- Copyright (c) 2008 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 07/21/2008: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity eudaqTrigger is + port ( + clk : in std_logic; + rst : in std_logic; + busyin : in std_logic; + tdcready : in std_logic; + enabled : in std_logic; + l1a : in std_logic; + trg : in std_logic; + done : out std_logic; + extbusy : out std_logic; + trgword : out std_logic_vector(14 downto 0); + trgclk : out std_logic + ); +end eudaqTrigger; + +architecture EUDAQTRIGGER of eudaqTrigger is + + signal clkcounter: std_logic_vector(7 downto 0); + signal extbusyint: std_logic; + signal trgwords: std_logic_vector(14 downto 0); + + +begin + + trgword<=trgwords; + extbusy<=extbusyint; + + process (rst,clk) + begin + if(rst='1')then + clkcounter<="00000000"; + done<='0'; + trgclk<='0'; + trgwords<=x"000"&"000"; + elsif(rising_edge(clk))then + if(clkcounter/="00000000")then + clkcounter<=unsigned(clkcounter)-1; + --if(clkcounter="10000000")then + -- trgclk<='1'; + if(clkcounter(2 downto 0)="010")then -- every 4th tick + trgwords(13 downto 0) <= trgwords(14 downto 1); + trgwords(14)<=trg; + elsif(clkcounter(2 downto 0)="000")then -- every 4th tick + if(clkcounter(7)='0' )then + trgclk<='1'; + end if; + elsif(clkcounter(2 downto 0)="100")then + trgclk<='0'; + elsif(clkcounter="00000001")then + done<='1'; + end if; + elsif(enabled='1' and l1a='1')then + clkcounter<="11000000"; + extbusyint<='1'; + else + done<='0'; + if(busyin='0' and extbusyint='1')then + extbusyint<='0'; + trgclk<='0'; + elsif(extbusyint='0' and enabled='1' and busyin='1' )then --FIFO full + trgclk<='1'; -- eudaq uses trgclk as a veto + elsif(extbusyint='0' and busyin='0')then + trgclk<='0'; + end if; + end if; + end if; + end process; + +end EUDAQTRIGGER; diff --git a/rce/fw-hsio/modules/pixelcore/hdl/framealign.vhd b/rce/fw-hsio/modules/pixelcore/hdl/framealign.vhd new file mode 100644 index 00000000..39c2a90f --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/framealign.vhd @@ -0,0 +1,56 @@ +------------------------------------------------------------------------------- +-- Description: +-- Core logic for BNL ASIC test FPGA. +------------------------------------------------------------------------------- +-- Copyright (c) 2008 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 07/21/2008: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity framealign is + port ( + clk : in std_logic; + rst : in std_logic; + d_in : in std_logic; + d_out : out std_logic; + aligned : out std_logic + ); +end framealign; + +architecture FRAMEALIGN of framealign is + + signal pipeline: std_logic_vector(19 downto 0); + +begin + + process (rst,clk) + begin + if(rst='1')then + pipeline<=(others=>'0'); + d_out<='0'; + elsif(rising_edge(clk))then + pipeline(19 downto 1)<= pipeline (18 downto 0); + pipeline(0)<=d_in; + d_out<=pipeline(19); + if(pipeline="00111110101100000111" or -- EOF SOF + pipeline="11000001010011111000" or -- EOF SOF + pipeline="00111110011100000111" or -- Idle SOF + pipeline="11000001100011111000" or -- Idle SOF + pipeline="00111110011100000110" or -- Idle Idle + pipeline="11000001100011111001" -- Idle Idle + )then + aligned<='1'; + else + aligned<='0'; + end if; + end if; + end process; + +end FRAMEALIGN; diff --git a/rce/fw-hsio/modules/pixelcore/hdl/framealignhitbus.vhd b/rce/fw-hsio/modules/pixelcore/hdl/framealignhitbus.vhd new file mode 100644 index 00000000..a84b94e8 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/framealignhitbus.vhd @@ -0,0 +1,51 @@ +------------------------------------------------------------------------------- +-- Description: +-- Core logic for BNL ASIC test FPGA. +------------------------------------------------------------------------------- +-- Copyright (c) 2008 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 07/21/2008: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity framealignhitbus is + port ( + clk : in std_logic; + rst : in std_logic; + d_in : in std_logic; + d_out : out std_logic; + aligned : out std_logic + ); +end framealignhitbus; + +architecture FRAMEALIGNHITBUS of framealignhitbus is + + signal pipeline: std_logic_vector(7 downto 0); + +begin + + process (rst,clk) + begin + if(rst='1')then + pipeline<=(others=>'0'); + d_out<='0'; + elsif(rising_edge(clk))then + pipeline(7 downto 1)<= pipeline (6 downto 0); + pipeline(0)<=d_in; + d_out<=pipeline(7); + if(pipeline="10001000" -- No triggers 1 marker bit for two cycles + )then + aligned<='1'; + else + aligned<='0'; + end if; + end if; + end process; + +end FRAMEALIGNHITBUS; diff --git a/rce/fw-hsio/modules/pixelcore/hdl/hitbuspipeline.vhd b/rce/fw-hsio/modules/pixelcore/hdl/hitbuspipeline.vhd new file mode 100644 index 00000000..b821070f --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/hitbuspipeline.vhd @@ -0,0 +1,59 @@ +------------------------------------------------------------------------------- +-- Description: +-- Core logic for BNL ASIC test FPGA. +------------------------------------------------------------------------------- +-- Copyright (c) 2008 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 07/21/2008: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; +use ieee.numeric_std.all; +use work.arraytype.all; + +entity hitbuspipeline is + port ( + rst : in std_logic; + clk : in std_logic; + ld : in std_logic; + depth : in std_logic_vector(4 downto 0); + wordin : in std_logic_vector(2 downto 0); + wordout : out std_logic_vector(31 downto 0) + ); +end hitbuspipeline; + +architecture HITBUSPIPELINE of hitbuspipeline is + + signal pp: hbpipeline; + signal index: integer; + +begin + + process (rst,clk) + begin + if(rst='1')then + for I in 0 to 40 loop + pp(I)<="000"; + end loop; + wordout(31 downto 30)<="00"; + elsif(rising_edge(clk))then + if(ld='1') then + pp(0)<=wordin; + hbset: for I in 1 to 40 loop + pp(I)<=pp(I-1); + end loop; + end if; + for I in 0 to 9 loop + wordout(I*3+2)<=pp(conv_integer(unsigned(depth))+I)(2); + wordout(I*3+1)<=pp(conv_integer(unsigned(depth))+I)(1); + wordout(I*3)<=pp(conv_integer(unsigned(depth))+I)(0); + end loop; + end if; + end process; + +end HITBUSPIPELINE; diff --git a/rce/fw-hsio/modules/pixelcore/hdl/i2c_master_bit_ctrl.vhd b/rce/fw-hsio/modules/pixelcore/hdl/i2c_master_bit_ctrl.vhd new file mode 100644 index 00000000..357535e1 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/i2c_master_bit_ctrl.vhd @@ -0,0 +1,727 @@ +--------------------------------------------------------------------- +---- ---- +---- WISHBONE revB2 I2C Master Core; bit-controller ---- +---- ---- +---- ---- +---- Author: Richard Herveille ---- +---- richard@asics.ws ---- +---- www.asics.ws ---- +---- ---- +---- Downloaded from: http://www.opencores.org/projects/i2c/ ---- +---- ---- +--------------------------------------------------------------------- +---- ---- +---- Copyright (C) 2000 Richard Herveille ---- +---- richard@asics.ws ---- +---- ---- +---- 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 ---- +---- the original copyright notice and the associated disclaimer.---- +---- ---- +---- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ---- +---- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ---- +---- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ---- +---- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ---- +---- 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. ---- +---- ---- +--------------------------------------------------------------------- + +-- CVS Log +-- +-- $Id: i2c_master_bit_ctrl.vhd,v 1.14 2006/10/11 12:10:13 rherveille Exp $ +-- +-- $Date: 2006/10/11 12:10:13 $ +-- $Revision: 1.14 $ +-- $Author: rherveille $ +-- $Locker: $ +-- $State: Exp $ +-- +-- Change History: +-- $Log: i2c_master_bit_ctrl.vhd,v $ +-- Revision 1.14 2006/10/11 12:10:13 rherveille +-- Added missing semicolons ';' on endif +-- +-- Revision 1.13 2006/10/06 10:48:24 rherveille +-- fixed short scl high pulse after clock stretch +-- +-- Revision 1.12 2004/05/07 11:53:31 rherveille +-- Fixed previous fix :) Made a variable vs signal mistake. +-- +-- Revision 1.11 2004/05/07 11:04:00 rherveille +-- Fixed a bug where the core would signal an arbitration lost (AL bit set), when another master controls the bus and the other master generates a STOP bit. +-- +-- Revision 1.10 2004/02/27 07:49:43 rherveille +-- Fixed a bug in the arbitration-lost signal generation. VHDL version only. +-- +-- Revision 1.9 2003/08/12 14:48:37 rherveille +-- Forgot an 'end if' :-/ +-- +-- Revision 1.8 2003/08/09 07:01:13 rherveille +-- Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line. +-- Fixed a potential bug in the byte controller's host-acknowledge generation. +-- +-- Revision 1.7 2003/02/05 00:06:02 rherveille +-- Fixed a bug where the core would trigger an erroneous 'arbitration lost' interrupt after being reset, when the reset pulse width < 3 clk cycles. +-- +-- Revision 1.6 2003/02/01 02:03:06 rherveille +-- Fixed a few 'arbitration lost' bugs. VHDL version only. +-- +-- Revision 1.5 2002/12/26 16:05:47 rherveille +-- Core is now a Multimaster I2C controller. +-- +-- Revision 1.4 2002/11/30 22:24:37 rherveille +-- Cleaned up code +-- +-- Revision 1.3 2002/10/30 18:09:53 rherveille +-- Fixed some reported minor start/stop generation timing issuess. +-- +-- Revision 1.2 2002/06/15 07:37:04 rherveille +-- Fixed a small timing bug in the bit controller.\nAdded verilog simulation environment. +-- +-- Revision 1.1 2001/11/05 12:02:33 rherveille +-- Split i2c_master_core.vhd into separate files for each entity; same layout as verilog version. +-- Code updated, is now up-to-date to doc. rev.0.4. +-- Added headers. +-- +-- Modified by Jan Andersson (jan@gaisler.com): +-- +-- * Added two start states to fulfill Set-up time for +-- repeated START condition. +-- * Modified synchronization of SCL and SDA. START and STOP detection +-- is now performed after a two stage synchronizer and is also +-- filtered. +-- * Changed evaluation order of 'slave_wait', 'en' and 'cnt' in +-- generation of clk_en signal to prevent clk_en assertion when +-- slave_wait is asserted. +-- * Needed to differentiate between slave clock stretching and master +-- clock synchronization. +-- * Added register s_state which contains the next state in case +-- of clock synchronization +-- * Incorporated change in wr_b state from SVN rev. 72 of +-- original OC version (delay check of SDA). +-- * Added 'filter' generic that determines length of filter. +-- Original OC core has a median filter implemented. The solution +-- implemented in this version is a plain shift register with a +-- length determined by the new generic. All samples in this +-- register must be equal, otherwise the SCL or SDA value used by +-- the core will not be changed. Every SCL/SDA transition that is +-- not stable for 'filter' system clock cycles is disregarded. +-- This solution is potentially more vulnerable against short +-- periods of relatively quick fluctuations on the line, however +-- it should do a better job of ignoring 50 ns pulses and still +-- allow us to respond quickly to events on the line - assuming +-- that the core has been correctly configured. +-- Core revision has been increased to 2 (in GRLIB PnP) +-- * Added 'dynfilt' generic to allow dynamic adjustment of the +-- filter. This component takes in a filt vector that is used to +-- reload a filter counter. The filt vector is assigned via the +-- core's APB interface. +-- Reorganized parts of the code, moving signals into blocks. +-- Core revision increased to 3. +-- +------------------------------------- +-- Bit controller section +------------------------------------ +-- +-- Translate simple commands into SCL/SDA transitions +-- Each command has 5 states, A/B/C/D/idle +-- +-- start: SCL ~~~~~~~~~~~~~~\____ +-- SDA XX/~~~~~~~\______ +-- x | A | B | C | D | i +-- +-- repstart SCL ______/~~~~~~~\___ +-- SDA __/~~~~~~~\______ +-- x | A | B | C | D | i +-- +-- stop SCL _______/~~~~~~~~~~~ +-- SDA ==\___________/~~~~~ +-- x | A | B | C | D | i +-- +--- write SCL ______/~~~~~~~\____ +-- SDA XXX===============XX +-- x | A | B | C | D | i +-- +--- read SCL ______/~~~~~~~\____ +-- SDA XXXXXXX=XXXXXXXXXXX +-- x | A | B | C | D | i +-- + +-- Timing: Normal mode Fast mode +----------------------------------------------------------------- +-- Fscl 100KHz 400KHz +-- Th_scl 4.0us 0.6us High period of SCL +-- Tl_scl 4.7us 1.3us Low period of SCL +-- Tsu:sta 4.7us 0.6us setup time for a repeated start condition +-- Tsu:sto 4.0us 0.6us setup time for a stop conditon +-- Tbuf 4.7us 1.3us Bus free time between a stop and start condition +-- + +library ieee; +use ieee.std_logic_1164.all; +--library grlib; +use work.stdlib.all; + +entity i2c_master_bit_ctrl is + generic (filter : integer; dynfilt : integer); + port ( + clk : in std_logic; + rst : in std_logic; + nReset : in std_logic; + ena : in std_logic; -- core enable signal + + clk_cnt : in std_logic_vector(15 downto 0); -- clock prescale value + + cmd : in std_logic_vector(3 downto 0); + cmd_ack : out std_logic; -- command completed + busy : out std_logic; -- i2c bus busy + al : out std_logic; -- arbitration lost + + din : in std_logic; + dout : out std_logic; + + filt : in std_logic_vector((filter-1)*dynfilt downto 0); + + -- i2c lines + scl_i : in std_logic; -- i2c clock line input + scl_o : out std_logic; -- i2c clock line output + scl_oen : out std_logic; -- i2c clock line output enable, active low + sda_i : in std_logic; -- i2c data line input + sda_o : out std_logic; -- i2c data line output + sda_oen : out std_logic -- i2c data line output enable, active low + ); +end entity i2c_master_bit_ctrl; + +architecture structural of i2c_master_bit_ctrl is + constant I2C_CMD_NOP : std_logic_vector(3 downto 0) := "0000"; + constant I2C_CMD_START : std_logic_vector(3 downto 0) := "0001"; + constant I2C_CMD_STOP : std_logic_vector(3 downto 0) := "0010"; + constant I2C_CMD_READ : std_logic_vector(3 downto 0) := "0100"; + constant I2C_CMD_WRITE : std_logic_vector(3 downto 0) := "1000"; + + type states is (idle, start_a, start_b, start_c, start_d, start_e, start_f, start_g, + stop_a, stop_b, stop_c, stop_d, rd_a, rd_b, rd_c, rd_d, wr_a, wr_b, wr_c, wr_d); + signal c_state, s_state : states; + + signal iscl_oen, isda_oen : std_logic; -- internal I2C lines + signal sda_chk : std_logic; -- check SDA status (multi-master arbitration) + signal fSCL, fSDA : std_logic_vector(1 downto 0); -- Filtered SCL and SDA inputs + signal clk_en, slave_wait : std_logic; -- clock generation signals + signal ial : std_logic; -- internal arbitration lost signal + signal cnt : std_logic_vector(15 downto 0); -- clock divider counter + signal csync : std_logic; -- Need to synchronize clock with other master + +begin + -- generate clk enable signal + gen_clken: process(clk, nReset) + begin + if (nReset = '0') then + cnt <= (others => '0'); + clk_en <= '1'; + elsif (clk'event and clk = '1') then + if (rst = '1') then + cnt <= (others => '0'); + clk_en <= '1'; + elsif (ena = '0' or csync = '1') then + cnt <= clk_cnt; + clk_en <= '1'; + elsif (slave_wait = '1') then + cnt <= cnt; + clk_en <= '0'; + elsif (cnt = X"0000") then + cnt <= clk_cnt; + clk_en <= '1'; + else + cnt <= cnt -1; + clk_en <= '0'; + end if; + end if; + end process gen_clken; + + + -- generate bus status controller + bus_status_ctrl: block + signal sta_condition : std_logic; -- start detected + signal sto_condition : std_logic; -- stop detected + signal cmd_stop : std_logic; -- STOP command + signal ibusy : std_logic; -- internal busy signal + signal slvw_dis : std_logic; -- Slave wait disable; + begin + + -- Static filter + staticfilt : if dynfilt = 0 generate + sfblock : block + constant FR : integer := filter; -- Filter range MSb + constant DR : integer := filter + 1; -- Delayed SCL/SDA range MSb + + signal sSCL, sSDA : std_logic_vector(FR downto 0); -- synchronized SCL and SDA inputs + signal discl_oen : std_logic_vector(DR downto 0); -- delayed scl_oen signal + signal disda_oen : std_logic_vector(DR downto 0); -- delayed isda_oen + begin + -- synchronize SCL and SDA inputs + synch_scl_sda: process(clk, nReset) + begin + if (nReset = '0') then + sSCL <= (others => '1'); + sSDA <= (others => '1'); + fSCL <= (others => '1'); + fSDA <= (others => '1'); + elsif (clk'event and clk = '1') then + if (rst = '1') then + sSCL <= (others => '1'); + sSDA <= (others => '1'); + fSCL <= (others => '1'); + fSDA <= (others => '1'); + else + sSCL <= sSCL(FR-1 downto 0) & scl_i; + sSDA <= sSDA(FR-1 downto 0) & sda_i; + -- Filtering + if andv(sSCL(FR downto 1)) = '1' then + fSCL <= fSCL(0) & '1'; + elsif orv(sSCL(FR downto 1)) = '0' then + fSCL <= fSCL(0) & '0'; + else + fSCL <= fSCL; + end if; + if andv(sSDA(FR downto 1)) = '1' then + fSDA <= fSDA(0) & '1'; + elsif orv(sSDA(FR downto 1)) = '0' then + fSDA <= fSDA(0) & '0'; + else + fSDA <= fSDA; + end if; + end if; + end if; + end process synch_SCL_SDA; + + -- whenever the slave is not ready it can delay the cycle by pulling SCL low + -- delay scl_oen + process (clk) + begin + if (clk'event and clk = '1') then + if rst = '1' then + discl_oen <= (others => '1'); + slvw_dis <= '0'; + else + -- Keep SCL output enable values + discl_oen <= discl_oen(DR-1 downto 0) & iscl_oen; + -- Disable slave stretch detection when other device drives SCL + -- H->L (only a master should to this). + slvw_dis <= (slvw_dis or csync) and discl_oen(0); + end if; + end if; + end process; + -- SCL forced low after master tried to assert, slave is stretching clock + slave_wait <= andv(discl_oen(DR downto 1)) and not fSCL(0) and not (slvw_dis or fSCL(1)); + -- SCL HIGH time cut short, master clock synchronization + csync <= andv(discl_oen(DR downto 1)) and not fSCL(0) and fSCL(1); + + -- generate arbitration lost signal + -- aribitration lost when: + -- 1) master drives SDA high, but the i2c bus is low + -- 2) stop detected while not requested (detect during 'idle' state) + gen_al: process(clk, nReset) + begin + if (nReset = '0') then + cmd_stop <= '0'; + ial <= '0'; + disda_oen <= (others => '1'); + elsif (clk'event and clk = '1') then + if (rst = '1') then + cmd_stop <= '0'; + ial <= '0'; + disda_oen <= (others => '1'); + else + if (clk_en = '1') then + if (cmd = I2C_CMD_STOP) then + cmd_stop <= '1'; + else + cmd_stop <= '0'; + end if; + end if; + + if (c_state = idle) then + ial <= (sda_chk and not fSDA(0) and disda_oen(DR)); + else + ial <= (sda_chk and not fSDA(0) and disda_oen(DR)) or + (sto_condition and not cmd_stop); + end if; + end if; + disda_oen <= disda_oen(DR-1 downto 0) & isda_oen; + end if; + end process gen_al; + end block sfblock; + end generate staticfilt; + + -- Dynamic filter + dynamicfilt : if dynfilt /= 0 generate + -- Fixed window + dfblock : block + signal filtcnt : std_logic_vector(filter-1 downto 0); + signal sSCL, sSDA : std_logic_vector(1 downto 0); -- synchronized SCL and SDA inputs + signal fiscl_oen : std_logic_vector(1 downto 0); -- "filtered" scl_oen signal + signal fisda_oen : std_ulogic; -- "filtered" sda_oen signal + signal fSCL_chg, fSDA_chg, fiscl_oen_chg, fisda_oen_chg : std_ulogic; + signal discl_oen : std_ulogic; -- delayed scl_oen signal + signal disda_oen : std_ulogic; -- delayed sda_oen signal + begin + -- Provides filtered signals for SCL and SDA, and corresponding + -- output enable signals. + sync_scl_sda: process(clk, nReset, fSCL_chg, fSDA_chg, fiscl_oen_chg, fisda_oen_chg) + variable scl_chg, sda_chg, iscl_oen_chg, isda_oen_chg : std_ulogic; + begin + scl_chg := fSCL_chg; sda_chg := fSDA_chg; + iscl_oen_chg := fiscl_oen_chg; isda_oen_chg := fisda_oen_chg; + if (nReset = '0') then + filtcnt <= (others => '0'); + fSCL <= (others => '1'); fSDA <= (others => '1'); + fSCL_chg <= '0'; fSDA_chg <= '0'; + fiscl_oen <= (others => '1'); fiscl_oen_chg <= '0'; + fisda_oen <= '1'; fisda_oen_chg <= '0'; + elsif (clk'event and clk = '1') then + if (rst = '1') or (ena = '0') then + filtcnt <= (others => '0'); + fSCL <= (others => '1'); fSDA <= (others => '1'); + fSCL_chg <= '0'; fSDA_chg <= '0'; + fiscl_oen <= (others => '1'); fiscl_oen_chg <= '0'; + fisda_oen <= '1'; fisda_oen_chg <= '0'; + else + if (sSCL(1) xor fSCL(0)) = '0' then scl_chg := '0'; end if; + if (sSDA(1) xor fSDA(0)) = '0' then sda_chg := '0'; end if; + if (discl_oen xor fiscl_oen(0)) = '0' then iscl_oen_chg := '0'; end if; + if (disda_oen xor fisda_oen) = '0' then isda_oen_chg := '0'; end if; + if filtcnt = zero32((filter-1)*dynfilt downto 0) then + filtcnt <= filt; + fSCL <= fSCL(0) & (fSCL(0) xor scl_chg); + fSDA <= fSDA(0) & (fSDA(0) xor sda_chg); + fSCL_chg <= '1'; fSDA_chg <= '1'; + fiscl_oen <= fiscl_oen(0) & (fiscl_oen(0) xor iscl_oen_chg); + fiscl_oen_chg <= '1'; + fisda_oen <= fisda_oen xor isda_oen_chg; + fisda_oen_chg <= '1'; + else + filtcnt <= filtcnt - 1; + fSDA <= fSDA; fSCL <= fSCL; + fSCL_chg <= scl_chg; fSDA_chg <= sda_chg; + fiscl_oen <= fiscl_oen; + fiscl_oen_chg <= iscl_oen_chg; + fisda_oen <= fisda_oen; + fisda_oen_chg <= isda_oen_chg; + end if; + end if; + sSCL <= sSCL(0) & scl_i; + sSDA <= sSDA(0) & sda_i; + end if; + end process sync_SCL_SDA; + + -- whenever the slave is not ready it can delay the cycle by pulling SCL low + -- delay scl_oen + process (clk) + begin + if (clk'event and clk = '1') then + if rst = '1' then + discl_oen <= '1'; + slvw_dis <= '0'; + else + -- Keep SCL output enable values + discl_oen <= iscl_oen; + -- Disable slave stretch detection when other device drives SCL + -- H->L (only a master should to this). + slvw_dis <= (slvw_dis or csync) and discl_oen; + end if; + end if; + end process; + -- SCL forced low after master tried to assert, slave is stretching clock + slave_wait <= andv(fiscl_oen) and not fSCL(0) and not (slvw_dis or fSCL(1)); + -- SCL HIGH time cut short, master clock synchronization + csync <= andv(fiscl_oen) and not fSCL(0) and fSCL(1); + + -- generate arbitration lost signal + -- aribitration lost when: + -- 1) master drives SDA high, but the i2c bus is low + -- 2) stop detected while not requested (detect during 'idle' state) + gen_ald: process(clk, nReset) + begin + if (nReset = '0') then + cmd_stop <= '0'; + ial <= '0'; + disda_oen <= '1'; + elsif (clk'event and clk = '1') then + if (rst = '1') then + cmd_stop <= '0'; + ial <= '0'; + disda_oen <= '1'; + else + if (clk_en = '1') then + if (cmd = I2C_CMD_STOP) then + cmd_stop <= '1'; + else + cmd_stop <= '0'; + end if; + end if; + if (c_state = idle) then + ial <= (sda_chk and not fSDA(0) and fisda_oen); + else + ial <= (sda_chk and not fSDA(0) and fisda_oen) or + (sto_condition and not cmd_stop); + end if; + disda_oen <= isda_oen; + end if; + end if; + end process gen_ald; + end block dfblock; + end generate dynamicfilt; + + al <= ial; + + -- detect start condition => detect falling edge on SDA while SCL is high + -- detect stop condition => detect rising edge on SDA while SCL is high + detect_sta_sto: process(clk, nReset) + begin + if (nReset = '0') then + sta_condition <= '0'; + sto_condition <= '0'; + elsif (clk'event and clk = '1') then + if (rst = '1') then + sta_condition <= '0'; + sto_condition <= '0'; + else + if fSCL = "11" and fSDA = "10" then + sta_condition <= '1'; + else + sta_condition <= '0'; + end if; + if fSCL = "11" and fSDA = "01" then + sto_condition <= '1'; + else + sto_condition <= '0'; + end if; + end if; + end if; + end process detect_sta_sto; + + -- generate i2c-bus busy signal + gen_busy: process(clk, nReset) + begin + if (nReset = '0') then + ibusy <= '0'; + elsif (clk'event and clk = '1') then + if (rst = '1') then + ibusy <= '0'; + else + ibusy <= (sta_condition or ibusy) and not sto_condition; + end if; + end if; + end process gen_busy; + busy <= ibusy; + + -- generate dout signal, store dout on rising edge of SCL + gen_dout: process(clk) + begin + if (clk'event and clk = '1') then + if fSCL = "01" then + dout <= fSDA(1); + end if; + end if; + end process gen_dout; + end block bus_status_ctrl; + + + -- generate statemachine + nxt_state_decoder : process (clk, nReset, c_state, cmd) + begin + if (nReset = '0') then + c_state <= idle; + s_state <= idle; + cmd_ack <= '0'; + iscl_oen <= '1'; + isda_oen <= '1'; + sda_chk <= '0'; + elsif (clk'event and clk = '1') then + if (rst = '1' or ial = '1') then + c_state <= idle; + cmd_ack <= '0'; + iscl_oen <= '1'; + isda_oen <= '1'; + sda_chk <= '0'; + elsif csync = '1' then + c_state <= s_state; + else + + cmd_ack <= '0'; -- default no acknowledge + + -- csync is always '0' here, but including it in the expression + -- appears to let some compilers optimize the design more... + if (clk_en or csync) = '1' then + + case (c_state) is + -- idle + when idle => + case cmd is + when I2C_CMD_START => c_state <= start_a; + s_state <= start_g; + when I2C_CMD_STOP => c_state <= stop_a; + s_state <= stop_d; + when I2C_CMD_WRITE => c_state <= wr_a; + s_state <= wr_d; + when I2C_CMD_READ => c_state <= rd_a; + s_state <= rd_d; + when others => c_state <= idle; -- NOP command + s_state <= idle; + end case; + + iscl_oen <= iscl_oen; -- keep SCL in same state + isda_oen <= isda_oen; -- keep SDA in same state + sda_chk <= '0'; -- don't check SDA + + -- start + when start_a => + c_state <= start_b; + iscl_oen <= iscl_oen; -- keep SCL in same state (for repeated start) + isda_oen <= '1'; -- set SDA high + sda_chk <= '0'; -- don't check SDA + + when start_b => + c_state <= start_c; + iscl_oen <= '1'; -- set SCL high + isda_oen <= '1'; -- keep SDA high + sda_chk <= '0'; -- don't check SDA + + when start_c => + c_state <= start_d; + iscl_oen <= '1'; -- set SCL high + isda_oen <= '1'; -- keep SDA high + sda_chk <= '0'; -- don't check SDA + + when start_d => + c_state <= start_e; + iscl_oen <= '1'; -- set SCL high + isda_oen <= '1'; -- keep SDA high + sda_chk <= '0'; -- don't check SDA + + when start_e => + c_state <= start_f; + iscl_oen <= '1'; -- keep SCL high + isda_oen <= '0'; -- set SDA low + sda_chk <= '0'; -- don't check SDA + + when start_f => + c_state <= start_g; + iscl_oen <= '1'; -- keep SCL high + isda_oen <= '0'; -- keep SDA low + sda_chk <= '0'; -- don't check SDA + + when start_g => + c_state <= idle; + cmd_ack <= '1'; -- command completed + iscl_oen <= '0'; -- set SCL low + isda_oen <= '0'; -- keep SDA low + sda_chk <= '0'; -- don't check SDA + s_state <= idle; + + -- stop + when stop_a => + c_state <= stop_b; + iscl_oen <= '0'; -- keep SCL low + isda_oen <= '0'; -- set SDA low + sda_chk <= '0'; -- don't check SDA + + when stop_b => + c_state <= stop_c; + iscl_oen <= '1'; -- set SCL high + isda_oen <= '0'; -- keep SDA low + sda_chk <= '0'; -- don't check SDA + + when stop_c => + c_state <= stop_d; + iscl_oen <= '1'; -- keep SCL high + isda_oen <= '0'; -- keep SDA low + sda_chk <= '0'; -- don't check SDA + + when stop_d => + c_state <= idle; + cmd_ack <= '1'; -- command completed + iscl_oen <= '1'; -- keep SCL high + isda_oen <= '1'; -- set SDA high + sda_chk <= '0'; -- don't check SDA + s_state <= idle; + + -- read + when rd_a => + c_state <= rd_b; + iscl_oen <= '0'; -- keep SCL low + isda_oen <= '1'; -- tri-state SDA + sda_chk <= '0'; -- don't check SDA + + when rd_b => + c_state <= rd_c; + iscl_oen <= '1'; -- set SCL high + isda_oen <= '1'; -- tri-state SDA + sda_chk <= '0'; -- don't check SDA + + when rd_c => + c_state <= rd_d; + iscl_oen <= '1'; -- keep SCL high + isda_oen <= '1'; -- tri-state SDA + sda_chk <= '0'; -- don't check SDA + + when rd_d => + c_state <= idle; + cmd_ack <= '1'; -- command completed + iscl_oen <= '0'; -- set SCL low + isda_oen <= '1'; -- tri-state SDA + sda_chk <= '0'; -- don't check SDA + s_state <= idle; + + -- write + when wr_a => + c_state <= wr_b; + iscl_oen <= '0'; -- keep SCL low + isda_oen <= din; -- set SDA + sda_chk <= '0'; -- don't check SDA (SCL low) + + when wr_b => + c_state <= wr_c; + iscl_oen <= '1'; -- set SCL high + isda_oen <= din; -- keep SDA + sda_chk <= '0'; -- don't check SDA (allow signals to settle) + + when wr_c => + c_state <= wr_d; + iscl_oen <= '1'; -- keep SCL high + isda_oen <= din; -- keep SDA + sda_chk <= '1'; -- check SDA + + when wr_d => + c_state <= idle; + cmd_ack <= '1'; -- command completed + iscl_oen <= '0'; -- set SCL low + isda_oen <= din; -- keep SDA + sda_chk <= '0'; -- don't check SDA (SCL low) + s_state <= idle; + + when others => + + end case; + end if; + end if; + end if; + end process nxt_state_decoder; + + + -- assign outputs + scl_o <= '0'; + scl_oen <= iscl_oen; + sda_o <= '0'; + sda_oen <= isda_oen; +end architecture structural; + diff --git a/rce/fw-hsio/modules/pixelcore/hdl/i2c_master_byte_ctrl.vhd b/rce/fw-hsio/modules/pixelcore/hdl/i2c_master_byte_ctrl.vhd new file mode 100644 index 00000000..dce9332d --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/i2c_master_byte_ctrl.vhd @@ -0,0 +1,388 @@ +--------------------------------------------------------------------- +---- ---- +---- WISHBONE revB2 compl. I2C Master Core; byte-controller ---- +---- ---- +---- ---- +---- Author: Richard Herveille ---- +---- richard@asics.ws ---- +---- www.asics.ws ---- +---- ---- +---- Downloaded from: http://www.opencores.org/projects/i2c/ ---- +---- ---- +--------------------------------------------------------------------- +---- ---- +---- Copyright (C) 2000 Richard Herveille ---- +---- richard@asics.ws ---- +---- ---- +---- 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 ---- +---- the original copyright notice and the associated disclaimer.---- +---- ---- +---- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ---- +---- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ---- +---- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ---- +---- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ---- +---- 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. ---- +---- ---- +--------------------------------------------------------------------- + +-- CVS Log +-- +-- $Id: i2c_master_byte_ctrl.vhd,v 1.5 2004/02/18 11:41:48 rherveille Exp $ +-- +-- $Date: 2004/02/18 11:41:48 $ +-- $Revision: 1.5 $ +-- $Author: rherveille $ +-- $Locker: $ +-- $State: Exp $ +-- +-- Change History: +-- $Log: i2c_master_byte_ctrl.vhd,v $ +-- Revision 1.5 2004/02/18 11:41:48 rherveille +-- Fixed a potential bug in the statemachine. During a 'stop' 2 cmd_ack signals were generated. Possibly canceling a new start command. +-- +-- Revision 1.4 2003/08/09 07:01:13 rherveille +-- Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line. +-- Fixed a potential bug in the byte controller's host-acknowledge generation. +-- +-- Revision 1.3 2002/12/26 16:05:47 rherveille +-- Core is now a Multimaster I2C controller. +-- +-- Revision 1.2 2002/11/30 22:24:37 rherveille +-- Cleaned up code +-- +-- Revision 1.1 2001/11/05 12:02:33 rherveille +-- Split i2c_master_core.vhd into separate files for each entity; same layout as verilog version. +-- Code updated, is now up-to-date to doc. rev.0.4. +-- Added headers. +-- + +-- Modified by Jan Andersson (jan@gaisler.com:. +-- Changed std_logic_arith to numeric_std. +-- Propagate filter generic + +-- +------------------------------------------ +-- Byte controller section +------------------------------------------ +-- +library ieee; +use ieee.std_logic_1164.all; +--library grlib; +use work.stdlib.all; + +entity i2c_master_byte_ctrl is + generic (filter : integer; dynfilt : integer); + port ( + clk : in std_logic; + rst : in std_logic; -- synchronous active high reset (WISHBONE compatible) + nReset : in std_logic; -- asynchornous active low reset (FPGA compatible) + ena : in std_logic; -- core enable signal + + clk_cnt : in std_logic_vector(15 downto 0); -- 4x SCL + + -- input signals + start, + stop, + read, + write, + ack_in : std_logic; + din : in std_logic_vector(7 downto 0); + filt : in std_logic_vector((filter-1)*dynfilt downto 0); + + -- output signals + cmd_ack : out std_logic; -- command done + ack_out : out std_logic; + i2c_busy : out std_logic; -- arbitration lost + i2c_al : out std_logic; -- i2c bus busy + dout : out std_logic_vector(7 downto 0); + + -- i2c lines + scl_i : in std_logic; -- i2c clock line input + scl_o : out std_logic; -- i2c clock line output + scl_oen : out std_logic; -- i2c clock line output enable, active low + sda_i : in std_logic; -- i2c data line input + sda_o : out std_logic; -- i2c data line output + sda_oen : out std_logic -- i2c data line output enable, active low + ); +end entity i2c_master_byte_ctrl; + +architecture structural of i2c_master_byte_ctrl is + component i2c_master_bit_ctrl is + generic (filter : integer; dynfilt : integer); + port ( + clk : in std_logic; + rst : in std_logic; + nReset : in std_logic; + ena : in std_logic; -- core enable signal + + clk_cnt : in std_logic_vector(15 downto 0); -- clock prescale value + + cmd : in std_logic_vector(3 downto 0); + cmd_ack : out std_logic; -- command done + busy : out std_logic; -- i2c bus busy + al : out std_logic; -- arbitration lost + + din : in std_logic; + dout : out std_logic; + + filt : in std_logic_vector((filter-1)*dynfilt downto 0); + + -- i2c lines + scl_i : in std_logic; -- i2c clock line input + scl_o : out std_logic; -- i2c clock line output + scl_oen : out std_logic; -- i2c clock line output enable, active low + sda_i : in std_logic; -- i2c data line input + sda_o : out std_logic; -- i2c data line output + sda_oen : out std_logic -- i2c data line output enable, active low + ); + end component i2c_master_bit_ctrl; + + -- commands for bit_controller block + constant I2C_CMD_NOP : std_logic_vector(3 downto 0) := "0000"; + constant I2C_CMD_START : std_logic_vector(3 downto 0) := "0001"; + constant I2C_CMD_STOP : std_logic_vector(3 downto 0) := "0010"; + constant I2C_CMD_READ : std_logic_vector(3 downto 0) := "0100"; + constant I2C_CMD_WRITE : std_logic_vector(3 downto 0) := "1000"; + + -- signals for bit_controller + signal core_cmd : std_logic_vector(3 downto 0); + signal core_ack, core_txd, core_rxd : std_logic; + signal al : std_logic; + + -- signals for shift register + signal sr : std_logic_vector(7 downto 0); -- 8bit shift register + signal shift, ld : std_logic; + + -- signals for state machine + signal go, host_ack : std_logic; + -- Added init value to dcnt to prevent simulation meta-value + -- - jan@gaisler.com + -- removed init value as it is not compatible with Formality + -- - jiri@gaisler.com + signal dcnt : std_logic_vector(2 downto 0) +-- pragma translate_off + := (others => '0') +-- pragma translate_on + ; -- data counter + signal cnt_done : std_logic; + +begin + -- hookup bit_controller + bit_ctrl: i2c_master_bit_ctrl + generic map (filter, dynfilt) + port map( + clk => clk, + rst => rst, + nReset => nReset, + ena => ena, + clk_cnt => clk_cnt, + cmd => core_cmd, + cmd_ack => core_ack, + busy => i2c_busy, + al => al, + din => core_txd, + dout => core_rxd, + filt => filt, + scl_i => scl_i, + scl_o => scl_o, + scl_oen => scl_oen, + sda_i => sda_i, + sda_o => sda_o, + sda_oen => sda_oen + ); + i2c_al <= al; + + -- generate host-command-acknowledge + cmd_ack <= host_ack; + + -- generate go-signal + go <= (read or write or stop) and not host_ack; + + -- assign Dout output to shift-register + dout <= sr; + + -- generate shift register + shift_register: process(clk, nReset) + begin + if (nReset = '0') then + sr <= (others => '0'); + elsif (clk'event and clk = '1') then + if (rst = '1') then + sr <= (others => '0'); + elsif (ld = '1') then + sr <= din; + elsif (shift = '1') then + sr <= (sr(6 downto 0) & core_rxd); + end if; + end if; + end process shift_register; + + -- generate data-counter + data_cnt: process(clk, nReset) + begin + if (nReset = '0') then + dcnt <= (others => '0'); + elsif (clk'event and clk = '1') then + if (rst = '1') then + dcnt <= (others => '0'); + elsif (ld = '1') then + dcnt <= (others => '1'); -- load counter with 7 + elsif (shift = '1') then + dcnt <= dcnt -1; + end if; + end if; + end process data_cnt; + + cnt_done <= '1' when (dcnt = "000") else '0'; + + -- + -- state machine + -- + statemachine : block + type states is (st_idle, st_start, st_read, st_write, st_ack, st_stop); + signal c_state : states; + begin + -- + -- command interpreter, translate complex commands into simpler I2C commands + -- + nxt_state_decoder: process(clk, nReset) + begin + if (nReset = '0') then + core_cmd <= I2C_CMD_NOP; + core_txd <= '0'; + shift <= '0'; + ld <= '0'; + host_ack <= '0'; + c_state <= st_idle; + ack_out <= '0'; + elsif (clk'event and clk = '1') then + if (rst = '1' or al = '1') then + core_cmd <= I2C_CMD_NOP; + core_txd <= '0'; + shift <= '0'; + ld <= '0'; + host_ack <= '0'; + c_state <= st_idle; + ack_out <= '0'; + else + -- initialy reset all signal + core_txd <= sr(7); + shift <= '0'; + ld <= '0'; + host_ack <= '0'; + + case c_state is + when st_idle => + if (go = '1') then + if (start = '1') then + c_state <= st_start; + core_cmd <= I2C_CMD_START; + elsif (read = '1') then + c_state <= st_read; + core_cmd <= I2C_CMD_READ; + elsif (write = '1') then + c_state <= st_write; + core_cmd <= I2C_CMD_WRITE; + else -- stop + c_state <= st_stop; + core_cmd <= I2C_CMD_STOP; + end if; + + ld <= '1'; + end if; + + when st_start => + if (core_ack = '1') then + if (read = '1') then + c_state <= st_read; + core_cmd <= I2C_CMD_READ; + else + c_state <= st_write; + core_cmd <= I2C_CMD_WRITE; + end if; + + ld <= '1'; + end if; + + when st_write => + if (core_ack = '1') then + if (cnt_done = '1') then + c_state <= st_ack; + core_cmd <= I2C_CMD_READ; + else + c_state <= st_write; -- stay in same state + core_cmd <= I2C_CMD_WRITE; -- write next bit + shift <= '1'; + end if; + end if; + + when st_read => + if (core_ack = '1') then + if (cnt_done = '1') then + c_state <= st_ack; + core_cmd <= I2C_CMD_WRITE; + else + c_state <= st_read; -- stay in same state + core_cmd <= I2C_CMD_READ; -- read next bit + end if; + + shift <= '1'; + core_txd <= ack_in; + end if; + + when st_ack => + if (core_ack = '1') then + -- check for stop; Should a STOP command be generated ? + if (stop = '1') then + c_state <= st_stop; + core_cmd <= I2C_CMD_STOP; + else + c_state <= st_idle; + core_cmd <= I2C_CMD_NOP; + + -- generate command acknowledge signal + host_ack <= '1'; + end if; + + -- assign ack_out output to core_rxd (contains last received bit) + ack_out <= core_rxd; + + core_txd <= '1'; + else + core_txd <= ack_in; + end if; + + when st_stop => + if (core_ack = '1') then + c_state <= st_idle; + core_cmd <= I2C_CMD_NOP; + + -- generate command acknowledge signal + host_ack <= '1'; + end if; + + when others => -- illegal states + c_state <= st_idle; + core_cmd <= I2C_CMD_NOP; + --report ("Byte controller entered illegal state."); + + end case; + + end if; + end if; + end process nxt_state_decoder; + + end block statemachine; + +end architecture structural; + diff --git a/rce/fw-hsio/modules/pixelcore/hdl/lookaheadfifo.vhd b/rce/fw-hsio/modules/pixelcore/hdl/lookaheadfifo.vhd new file mode 100644 index 00000000..87c88f4b --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/lookaheadfifo.vhd @@ -0,0 +1,136 @@ +-------------------------------------------------------------- +-- Look ahead fifo +-- Martin Kocian 01/2009 +-------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use work.StdRtlPkg.all; +use work.all; + +-------------------------------------------------------------- + +entity lookaheadfifo is + generic ( + buffersize : integer :=8192 -- FIFO size + ); +port( wr_clk: in std_logic; + rd_clk: in std_logic; + rst: in std_logic; + din: in std_logic_vector(24 downto 0); + dout: out std_logic_vector(24 downto 0):=(others =>'0'); + dnext: out std_logic_vector(24 downto 0); + wr_en: in std_logic; + rd_en: in std_logic; + dnextvalid: out std_logic; + empty: out std_logic; + full: out std_logic; + overflow: out std_logic; + prog_full: out std_logic; + underflow: out std_logic; + valid: out std_logic := '0' +); +end lookaheadfifo; + +-------------------------------------------------------------- + +architecture LOOKAHEADFIFO of lookaheadfifo is + +COMPONENT data24bitfifo4096 + PORT ( + rst : IN STD_LOGIC; + wr_clk : IN STD_LOGIC; + rd_clk : IN STD_LOGIC; + din : IN STD_LOGIC_VECTOR(24 DOWNTO 0); + wr_en : IN STD_LOGIC; + rd_en : IN STD_LOGIC; + dout : OUT STD_LOGIC_VECTOR(24 DOWNTO 0); + full : OUT STD_LOGIC; + overflow : OUT STD_LOGIC; + empty : OUT STD_LOGIC; + almost_empty : OUT STD_LOGIC; + valid : OUT STD_LOGIC; + underflow : OUT STD_LOGIC; + prog_full : OUT STD_LOGIC + ); +END COMPONENT; +COMPONENT data24bitfifo8192 + PORT ( + rst : IN STD_LOGIC; + wr_clk : IN STD_LOGIC; + rd_clk : IN STD_LOGIC; + din : IN STD_LOGIC_VECTOR(24 DOWNTO 0); + wr_en : IN STD_LOGIC; + rd_en : IN STD_LOGIC; + dout : OUT STD_LOGIC_VECTOR(24 DOWNTO 0); + full : OUT STD_LOGIC; + overflow : OUT STD_LOGIC; + empty : OUT STD_LOGIC; + almost_empty : OUT STD_LOGIC; + valid : OUT STD_LOGIC; + underflow : OUT STD_LOGIC; + prog_full : OUT STD_LOGIC + ); +END COMPONENT; + +signal frd_en: std_logic:='0'; +signal buffervalid: std_logic:='0'; +signal doutvalid: std_logic:='0'; +signal fdout: slv(24 downto 0); + +begin + dnextvalid<=buffervalid; + dnext<=fdout; + frd_en<=buffervalid and rd_en; + valid<=doutvalid; + process begin + wait until rising_edge(rd_clk); + if(frd_en='1')then + dout<=fdout; + doutvalid<='1'; + elsif(rd_en='1')then + if(doutvalid='1')then + doutvalid<='0'; + end if; + end if; + end process; + + buf_4096: if (buffersize=4096) generate + fei4fifo : data24bitfifo4096 + port map ( + din => din, + rd_clk => rd_clk, + rd_en => frd_en, + rst => rst, + wr_clk => wr_clk, + wr_en => wr_en, + dout => fdout, + empty => empty, + full => full, + overflow => overflow, + prog_full => prog_full, + valid => buffervalid, + underflow => underflow); + end generate; + buf_8192: if (buffersize=8192) generate + fei4fifo : data24bitfifo8192 + port map ( + din => din, + rd_clk => rd_clk, + rd_en => frd_en, + rst => rst, + wr_clk => wr_clk, + wr_en => wr_en, + dout => fdout, + empty => empty, + full => full, + overflow => overflow, + prog_full => prog_full, + valid => buffervalid, + underflow => underflow); + end generate; + +end LOOKAHEADFIFO; + +-------------------------------------------------------------- diff --git a/rce/fw-hsio/modules/pixelcore/hdl/multiplexdata.vhd b/rce/fw-hsio/modules/pixelcore/hdl/multiplexdata.vhd new file mode 100644 index 00000000..888f5218 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/multiplexdata.vhd @@ -0,0 +1,250 @@ +-------------------------------------------------------------- +-- Serializer for High Speed I/O board (ATLAS Pixel teststand) +-- Martin Kocian 01/2009 +-------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use work.all; +use work.arraytype.all; + +-------------------------------------------------------------- + + +entity multiplexdata is + +port( clk: in std_logic; + rst: in std_logic; + enabled: in std_logic; + channelmask: in std_logic_vector(15 downto 0); + datawaiting: in std_logic_vector(15 downto 0); + indatavalid: in std_logic_vector(15 downto 0); + datain: in dataarray; + dataout: out std_logic_vector(15 downto 0); + eofout: out std_logic; + sofout: out std_logic; + datavalid: out std_logic; + reqdata: out std_logic_vector(15 downto 0); + counter4: out std_logic_vector(31 downto 0); + counter10b: out std_logic_vector(31 downto 0); + counter10: out std_logic_vector(31 downto 0) +); +end multiplexdata; + +-------------------------------------------------------------- + +architecture MULTIPLEXDATA of multiplexdata is + signal index: integer; + signal eof: std_logic; + signal sof: std_logic; + signal pdata: dataarray; + signal pvalid: std_logic_vector(15 downto 0); + type state_type is (idle, first, sending, paused, switch, kludge1, kludge2, kludge3, mwait); + signal state: state_type; + signal wcounter: std_logic_vector(8 downto 0); + signal cdata: std_logic_vector(31 downto 0); + signal ctrig: std_logic_vector(7 downto 0); + signal ccontrol: std_logic_vector(35 downto 0); + signal dwcounter: std_logic_vector(3 downto 0); + signal eofouts: std_logic; + signal sofouts: std_logic; + signal datavalids: std_logic; + signal reqdatas: std_logic_vector(15 downto 0); +component chipscope_ila_new + PORT ( + CONTROL : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0); + CLK : IN STD_LOGIC; + DATA : IN STD_LOGIC_VECTOR(31 DOWNTO 0); + TRIG0 : IN STD_LOGIC_VECTOR(7 DOWNTO 0)); + +end component; + component chipscope_icon_new + PORT ( + CONTROL0 : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0)); + + end component; +-- attribute syn_noprune : boolean; +-- attribute syn_noprune of chipscope : label is true; +-- attribute syn_noprune of chipscopeicon : label is true; + +begin + + eofout<=eofouts; + sofout<=sofouts; + datavalid<=datavalids; + reqdata<=reqdatas; + + process (rst,clk) + begin + if(rst='1')then + index<=0; + reqdatas<=x"0000"; + eofouts<='0'; + sofouts<='0'; + dataout<=x"0000"; + pvalid<=x"0000"; + pdata(0)<="00"&x"0000"; + pdata(1)<="00"&x"0000"; + pdata(2)<="00"&x"0000"; + pdata(3)<="00"&x"0000"; + pdata(4)<="00"&x"0000"; + pdata(5)<="00"&x"0000"; + pdata(6)<="00"&x"0000"; + pdata(7)<="00"&x"0000"; + pdata(8)<="00"&x"0000"; + pdata(9)<="00"&x"0000"; + pdata(10)<="00"&x"0000"; + pdata(11)<="00"&x"0000"; + pdata(12)<="00"&x"0000"; + pdata(13)<="00"&x"0000"; + pdata(14)<="00"&x"0000"; + pdata(15)<="00"&x"0000"; + wcounter<='0'&x"00"; + counter4<=x"00000000"; + dwcounter<="0000"; + state<= idle; + elsif(rising_edge(clk))then + case state is + when kludge1 => + dataout<=x"0000"; + if(indatavalid(index)='1')then + pvalid(index)<='1'; + pdata(index)<=datain(index); + else + pvalid(index)<='0'; + end if; + state<=kludge2; + when kludge2 => + eofouts<='1'; + state<=kludge3; + when kludge3 => + eofouts<='0'; + datavalids<='0'; + sofouts<='0'; + if(index=15)then + index<=0; + else + index<=index+1; + end if; + dwcounter<="1010"; + state<=mwait; + when switch => + eofouts<='0'; + datavalids<='0'; + sofouts<='0'; + if(indatavalid(index)='1')then + pvalid(index)<='1'; + pdata(index)<=datain(index); + else + pvalid(index)<='0'; + end if; + if(index=15)then + index<=0; + else + index<=index+1; + end if; + dwcounter<="1010"; + state<=mwait; + when mwait => + if(dwcounter/="0000")then + dwcounter<=unsigned(dwcounter)-1; + state<=mwait; + else + state<=idle; + end if; + when idle => + if(enabled='1' and channelmask(index)='1' and datawaiting(index)='1')then + reqdatas(index)<='1'; + state<=first; + wcounter<='0'&x"00"; + elsif(enabled='0')then + state<=idle; + else + state<=idle; + if(index=15)then + index<=0; + else + index<=index+1; + end if; + end if; + when first => + if(pvalid(index)='1')then + sofouts<='1'; + dataout<=pdata(index)(15 downto 0); + datavalids<='1'; + wcounter<=unsigned(wcounter)+1; + pvalid(index)<='0'; + end if; + state<= sending; + when sending => + dataout <= datain(index)(15 downto 0); + datavalids<='1'; + wcounter<=unsigned(wcounter)+1; + sofouts <=datain(index)(16); + if(datain(index)(17)='1') then --EOF + reqdatas(index)<='0'; + if(wcounter(8)='1' or wcounter(7)='1')then + counter4(8 downto 0)<=wcounter; + end if; + if(wcounter(7 downto 0)=x"01")then -- pgp kludge, add an extra 2 words + state<=kludge1; + else + state<=switch; + eofouts<='1'; + end if; + elsif(enabled='0')then + reqdatas(index)<='0'; + state<=paused;-- pause transmission + else + state<=sending; + end if; + when paused => + if(indatavalid(index)='1')then + dataout <= datain(index)(15 downto 0); + wcounter<=unsigned(wcounter)+1; + if(datain(index)(17)='1') then --EOF + if(wcounter(7 downto 0)=x"01")then -- pgp kludge, add an extra 2 words + state<=kludge1; + else + state<=switch; + eofouts<='1'; + end if; + end if; + else + datavalids<='0'; + if(enabled='1')then + reqdatas(index)<='1'; + state<=first; + else + state<=paused; + end if; + end if; + end case; + end if; + + cdata(6)<=datain(index)(17); + cdata(7)<=eofouts; + cdata(8)<=datain(index)(16); + cdata(9)<=sofouts; + cdata(5)<=datavalids; + cdata(4)<=indatavalid(index); + cdata(3 downto 0)<=conv_std_logic_vector(index, 4); + cdata(17 downto 10)<=reqdatas(7 downto 0); + cdata(18)<=channelmask(index) and datawaiting(index) and enabled; + ctrig(0)<=channelmask(index) and datawaiting(index) and enabled; + + end process; + + --chipscope : chipscope_ila_new + -- port map ( + -- CONTROL => ccontrol, + -- CLK => clk, + -- DATA => cdata, + -- TRIG0 => ctrig); +-- chipscopeicon : chipscope_icon_new +-- port map ( +-- CONTROL0 => ccontrol); +-- + +end MULTIPLEXDATA; diff --git a/rce/fw-hsio/modules/pixelcore/hdl/multiplexdataopt.vhd b/rce/fw-hsio/modules/pixelcore/hdl/multiplexdataopt.vhd new file mode 100644 index 00000000..1a82bd60 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/multiplexdataopt.vhd @@ -0,0 +1,265 @@ +-------------------------------------------------------------- +-- Serializer for High Speed I/O board (ATLAS Pixel teststand) +-- Martin Kocian 01/2009 +-------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use work.all; +use work.arraytype.all; + +-------------------------------------------------------------- + + +entity multiplexdata is +generic( + maxchannel: integer:=28); +port( clk: in std_logic; + rst: in std_logic; + enabled: in std_logic; + channelmask: in std_logic_vector(31 downto 0); + datawaiting: in std_logic_vector(31 downto 0); + moredatawaiting: in std_logic_vector(31 downto 0); + indatavalid: in std_logic_vector(31 downto 0); + datain: in dataarray; + dataout: out std_logic_vector(15 downto 0); + eofout: out std_logic; + sofout: out std_logic; + datavalid: out std_logic; + reqdata: out std_logic_vector(31 downto 0); + multiplicity: in std_logic_vector(63 downto 0); + counter4: out std_logic_vector(31 downto 0); + counter10b: out std_logic_vector(31 downto 0); + counter10: out std_logic_vector(31 downto 0) +); +end multiplexdata; + +-------------------------------------------------------------- + +architecture MULTIPLEXDATA of multiplexdata is + signal index: integer; + signal eof: std_logic; + signal sof: std_logic; + signal pdata: dataarray; + signal pvalid: std_logic_vector(31 downto 0); + type state_type is (idle, first, sending, paused, switch, kludge1, kludge2, kludge3, mwait); + signal state: state_type; + signal wcounter: std_logic_vector(8 downto 0); + signal cdata: std_logic_vector(31 downto 0); + signal ctrig: std_logic_vector(7 downto 0); + signal ccontrol: std_logic_vector(35 downto 0); + signal dwcounter: std_logic_vector(3 downto 0); + signal eofouts: std_logic; + signal sofouts: std_logic; + signal datavalids: std_logic; + signal reqdatas: std_logic_vector(31 downto 0); + signal repcounter: std_logic_vector(3 downto 0); +component chipscope_ila_new + PORT ( + CONTROL : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0); + CLK : IN STD_LOGIC; + DATA : IN STD_LOGIC_VECTOR(31 DOWNTO 0); + TRIG0 : IN STD_LOGIC_VECTOR(7 DOWNTO 0)); + +end component; + component chipscope_icon_new + PORT ( + CONTROL0 : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0)); + + end component; + + function reps(w:std_logic_vector; i:integer) return std_logic_vector is + begin + if(i=30)then + return w(63 downto 60); + else + return w(i*4+3 downto i*4); + end if; + end; +-- attribute syn_noprune : boolean; +-- attribute syn_noprune of chipscope : label is true; +-- attribute syn_noprune of chipscopeicon : label is true; + +begin + + eofout<=eofouts; + sofout<=sofouts; + datavalid<=datavalids; + reqdata<=reqdatas; + + process (rst,clk) + begin + if(rst='1')then + index<=0; + reqdatas<=(others=>'0'); + eofouts<='0'; + sofouts<='0'; + dataout<=x"0000"; + pvalid<=(others=>'0'); + pdata<= (others => (others=>'0')); + wcounter<='0'&x"00"; + counter4<=x"00000000"; + dwcounter<="0000"; + state<= idle; + repcounter<=x"0"; + elsif(rising_edge(clk))then + case state is + when kludge1 => + dataout<=x"0000"; + if(indatavalid(index)='1')then + pvalid(index)<='1'; + pdata(index)<=datain(index); + else + pvalid(index)<='0'; + end if; + state<=kludge2; + when kludge2 => + eofouts<='1'; + state<=kludge3; + when kludge3 => + eofouts<='0'; + datavalids<='0'; + sofouts<='0'; + if(moredatawaiting(index)='1' and repcounter/=reps(multiplicity, index))then + repcounter<=unsigned(repcounter)+1; + else + repcounter<=x"0"; + if(index=maxchannel)then + index<=29; + elsif(index=31)then + index<=0; + else + index<=index+1; + end if; + end if; + dwcounter<="1010"; + state<=mwait; + when switch => + eofouts<='0'; + datavalids<='0'; + sofouts<='0'; + if(indatavalid(index)='1')then + pvalid(index)<='1'; + pdata(index)<=datain(index); + else + pvalid(index)<='0'; + end if; + if(moredatawaiting(index)='1' and repcounter/=reps(multiplicity, index))then + repcounter<=unsigned(repcounter)+1; + else + repcounter<=x"0"; + if(index=maxchannel)then + index<=29; + elsif(index=31)then + index<=0; + else + index<=index+1; + end if; + end if; + dwcounter<="1010"; + state<=mwait; + when mwait => + if(dwcounter/="0000")then + dwcounter<=unsigned(dwcounter)-1; + state<=mwait; + else + state<=idle; + end if; + when idle => + if(enabled='1' and channelmask(index)='1' and datawaiting(index)='1')then + reqdatas(index)<='1'; + state<=first; + wcounter<='0'&x"00"; + elsif(enabled='0')then + state<=idle; + else + if(index=maxchannel)then + index<=29; + elsif(index=31)then + index<=0; + else + index<=index+1; + end if; + state<=idle; + end if; + when first => + if(pvalid(index)='1')then + sofouts<='1'; + dataout<=pdata(index)(15 downto 0); + datavalids<='1'; + wcounter<=unsigned(wcounter)+1; + pvalid(index)<='0'; + end if; + state<= sending; + when sending => + dataout <= datain(index)(15 downto 0); + datavalids<='1'; + wcounter<=unsigned(wcounter)+1; + sofouts <=datain(index)(16); + if(datain(index)(17)='1') then --EOF + reqdatas(index)<='0'; + if(wcounter(8)='1' or wcounter(7)='1')then + counter4(8 downto 0)<=wcounter; + end if; + if(wcounter(7 downto 0)=x"01")then -- pgp kludge, add an extra 2 words + state<=kludge1; + else + state<=switch; + eofouts<='1'; + end if; + elsif(enabled='0')then + reqdatas(index)<='0'; + state<=paused;-- pause transmission + else + state<=sending; + end if; + when paused => + if(indatavalid(index)='1')then + dataout <= datain(index)(15 downto 0); + wcounter<=unsigned(wcounter)+1; + if(datain(index)(17)='1') then --EOF + if(wcounter(7 downto 0)=x"01")then -- pgp kludge, add an extra 2 words + state<=kludge1; + else + state<=switch; + eofouts<='1'; + end if; + end if; + else + datavalids<='0'; + if(enabled='1')then + reqdatas(index)<='1'; + state<=first; + else + state<=paused; + end if; + end if; + end case; + end if; + + cdata(6)<=datain(index)(17); + cdata(7)<=eofouts; + cdata(8)<=datain(index)(16); + cdata(9)<=sofouts; + cdata(5)<=datavalids; + cdata(4)<=indatavalid(index); + cdata(3 downto 0)<=conv_std_logic_vector(index, 4); + cdata(17 downto 10)<=reqdatas(7 downto 0); + cdata(18)<=channelmask(index) and datawaiting(index) and enabled; + ctrig(0)<=channelmask(index) and datawaiting(index) and enabled; + + end process; + + --chipscope : chipscope_ila_new + -- port map ( + -- CONTROL => ccontrol, + -- CLK => clk, + -- DATA => cdata, + -- TRIG0 => ctrig); +-- chipscopeicon : chipscope_icon_new +-- port map ( +-- CONTROL0 => ccontrol); +-- + +end MULTIPLEXDATA; diff --git a/rce/fw-hsio/modules/pixelcore/hdl/multiplexdatapgp2.vhd b/rce/fw-hsio/modules/pixelcore/hdl/multiplexdatapgp2.vhd new file mode 100644 index 00000000..a1f5fe8d --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/multiplexdatapgp2.vhd @@ -0,0 +1,252 @@ +-------------------------------------------------------------- +-- Serializer for High Speed I/O board (ATLAS Pixel teststand) +-- Martin Kocian 01/2009 +-------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use work.all; +use work.arraytype.all; + +-------------------------------------------------------------- + + +entity multiplexdata is +generic(maxchannel: integer:=28); +port( clk: in std_logic; + rst: in std_logic; + enabled: in std_logic; + channelmask: in std_logic_vector(31 downto 0); + datawaiting: in std_logic_vector(31 downto 0); + moredatawaiting: in std_logic_vector(31 downto 0); + indatavalid: in std_logic_vector(31 downto 0); + datain: in dataarray; + dataout: out std_logic_vector(31 downto 0); + eofout: out std_logic; + sofout: out std_logic; + datavalid: out std_logic; + reqdata: out std_logic_vector(31 downto 0); + multiplicity: in std_logic_vector(63 downto 0); + counter4: out std_logic_vector(31 downto 0); + counter10b: out std_logic_vector(31 downto 0); + counter10: out std_logic_vector(31 downto 0) +); +end multiplexdata; + +-------------------------------------------------------------- + +architecture MULTIPLEXDATA of multiplexdata is + signal index: integer; + signal eof: std_logic; + signal sof: std_logic; + signal pdata: dataarray; + signal pvalid: std_logic_vector(31 downto 0); + type state_type is (idle, first, sending, paused, switch, kludge1, kludge2, kludge3, mwait); + signal state: state_type; + signal wcounter: std_logic_vector(8 downto 0); + signal cdata: std_logic_vector(31 downto 0); + signal ctrig: std_logic_vector(7 downto 0); + signal ccontrol: std_logic_vector(35 downto 0); + signal dwcounter: std_logic_vector(3 downto 0); + signal eofouts: std_logic; + signal sofouts: std_logic; + signal datavalids: std_logic; + signal reqdatas: std_logic_vector(31 downto 0); +component chipscope_ila_new + PORT ( + CONTROL : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0); + CLK : IN STD_LOGIC; + DATA : IN STD_LOGIC_VECTOR(31 DOWNTO 0); + TRIG0 : IN STD_LOGIC_VECTOR(7 DOWNTO 0)); + +end component; + component chipscope_icon_new + PORT ( + CONTROL0 : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0)); + + end component; +-- attribute syn_noprune : boolean; +-- attribute syn_noprune of chipscope : label is true; +-- attribute syn_noprune of chipscopeicon : label is true; + +begin + + eofout<=eofouts; + sofout<=sofouts; + datavalid<=datavalids; + reqdata<=reqdatas; + + process (rst,clk) + begin + if(rst='1')then + index<=0; + reqdatas<=x"0000"; + eofouts<='0'; + sofouts<='0'; + dataout<=x"0000"; + pvalid<=x"0000"; + pdata(0)<="00"&x"0000"; + pdata(1)<="00"&x"0000"; + pdata(2)<="00"&x"0000"; + pdata(3)<="00"&x"0000"; + pdata(4)<="00"&x"0000"; + pdata(5)<="00"&x"0000"; + pdata(6)<="00"&x"0000"; + pdata(7)<="00"&x"0000"; + pdata(8)<="00"&x"0000"; + pdata(9)<="00"&x"0000"; + pdata(10)<="00"&x"0000"; + pdata(11)<="00"&x"0000"; + pdata(12)<="00"&x"0000"; + pdata(13)<="00"&x"0000"; + pdata(14)<="00"&x"0000"; + pdata(15)<="00"&x"0000"; + wcounter<='0'&x"00"; + counter4<=x"00000000"; + dwcounter<="0000"; + state<= idle; + elsif(rising_edge(clk))then + case state is + when kludge1 => + dataout<=x"0000"; + if(indatavalid(index)='1')then + pvalid(index)<='1'; + pdata(index)<=datain(index); + else + pvalid(index)<='0'; + end if; + state<=kludge2; + when kludge2 => + eofouts<='1'; + state<=kludge3; + when kludge3 => + eofouts<='0'; + datavalids<='0'; + sofouts<='0'; + if(index=15)then + index<=0; + else + index<=index+1; + end if; + dwcounter<="1010"; + state<=mwait; + when switch => + eofouts<='0'; + datavalids<='0'; + sofouts<='0'; + if(indatavalid(index)='1')then + pvalid(index)<='1'; + pdata(index)<=datain(index); + else + pvalid(index)<='0'; + end if; + if(index=15)then + index<=0; + else + index<=index+1; + end if; + dwcounter<="1010"; + state<=mwait; + when mwait => + if(dwcounter/="0000")then + dwcounter<=unsigned(dwcounter)-1; + state<=mwait; + else + state<=idle; + end if; + when idle => + if(enabled='1' and channelmask(index)='1' and datawaiting(index)='1')then + reqdatas(index)<='1'; + state<=first; + wcounter<='0'&x"00"; + elsif(enabled='0')then + state<=idle; + else + state<=idle; + if(index=15)then + index<=0; + else + index<=index+1; + end if; + end if; + when first => + if(pvalid(index)='1')then + sofouts<='1'; + dataout<=pdata(index)(15 downto 0); + datavalids<='1'; + wcounter<=unsigned(wcounter)+1; + pvalid(index)<='0'; + end if; + state<= sending; + when sending => + dataout <= datain(index)(15 downto 0); + datavalids<='1'; + wcounter<=unsigned(wcounter)+1; + sofouts <=datain(index)(16); + if(datain(index)(17)='1') then --EOF + reqdatas(index)<='0'; + if(wcounter(8)='1' or wcounter(7)='1')then + counter4(8 downto 0)<=wcounter; + end if; + if(wcounter(7 downto 0)=x"01")then -- pgp kludge, add an extra 2 words + state<=kludge1; + else + state<=kludge1; + --eofouts<='1'; + end if; + elsif(enabled='0')then + reqdatas(index)<='0'; + state<=paused;-- pause transmission + else + state<=sending; + end if; + when paused => + if(indatavalid(index)='1')then + dataout <= datain(index)(15 downto 0); + wcounter<=unsigned(wcounter)+1; + if(datain(index)(17)='1') then --EOF + if(wcounter(7 downto 0)=x"01")then -- pgp kludge, add an extra 2 words + state<=kludge1; + else + state<=kludge1; + --eofouts<='1'; + end if; + end if; + else + datavalids<='0'; + if(enabled='1')then + reqdatas(index)<='1'; + state<=first; + else + state<=paused; + end if; + end if; + end case; + end if; + + cdata(6)<=datain(index)(17); + cdata(7)<=eofouts; + cdata(8)<=datain(index)(16); + cdata(9)<=sofouts; + cdata(5)<=datavalids; + cdata(4)<=indatavalid(index); + cdata(3 downto 0)<=conv_std_logic_vector(index, 4); + cdata(17 downto 10)<=reqdatas(7 downto 0); + cdata(18)<=channelmask(index) and datawaiting(index) and enabled; + ctrig(0)<=channelmask(index) and datawaiting(index) and enabled; + + end process; + + --chipscope : chipscope_ila_new + -- port map ( + -- CONTROL => ccontrol, + -- CLK => clk, + -- DATA => cdata, + -- TRIG0 => ctrig); +-- chipscopeicon : chipscope_icon_new +-- port map ( +-- CONTROL0 => ccontrol); +-- + +end MULTIPLEXDATA; diff --git a/rce/fw-hsio/modules/pixelcore/hdl/phaseshift.vhd b/rce/fw-hsio/modules/pixelcore/hdl/phaseshift.vhd new file mode 100644 index 00000000..eac874a4 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/phaseshift.vhd @@ -0,0 +1,131 @@ +-------------------------------------------------------------------------------- +-- Copyright (c) 1995-2008 Xilinx, Inc. All rights reserved. +-------------------------------------------------------------------------------- +-- ____ ____ +-- / /\/ / +-- /___/ \ / Vendor: Xilinx +-- \ \ \/ Version : 10.1.03 +-- \ \ Application : xaw2vhdl +-- / / Filename : phaseshift.vhd +-- /___/ /\ Timestamp : 08/24/2009 10:21:32 +-- \ \ / \ +-- \___\/\___\ +-- +--Command: xaw2vhdl-st /a/sulky20/g.ee.u07/kocian/minilat/xilinx/IBL/xil_cores//phaseshift.xaw /a/sulky20/g.ee.u07/kocian/minilat/xilinx/IBL/xil_cores//phaseshift +--Design Name: phaseshift +--Device: xc4vfx60-10ff1152 +-- +-- Module phaseshift +-- Generated by Xilinx Architecture Wizard +-- Written for synthesis tool: Synplify + +library ieee; +use ieee.std_logic_1164.ALL; +use ieee.numeric_std.ALL; +library UNISIM; +use UNISIM.Vcomponents.ALL; + +entity phaseshift is + port ( CLKIN_IN : in std_logic; + DADDR_IN : in std_logic_vector (6 downto 0); + DCLK_IN : in std_logic; + DEN_IN : in std_logic; + DI_IN : in std_logic_vector (15 downto 0); + DWE_IN : in std_logic; + RST_IN : in std_logic; + CLK0_OUT : out std_logic; + CLK90_OUT : out std_logic; + CLK180_OUT : out std_logic; + CLK270_OUT : out std_logic; + CLKFX_OUT : out std_logic; + CLK2X_OUT : out std_logic; + DRDY_OUT : out std_logic; + LOCKED_OUT : out std_logic; + + pclkUnbuf : out std_logic; + pclk90Unbuf : out std_logic; + pclk180Unbuf: out std_logic; + pclk270Unbuf: out std_logic + ); + +end phaseshift; + +architecture BEHAVIORAL of phaseshift is + signal CLKFB_IN : std_logic; + signal CLK0_BUF : std_logic; + signal CLK90_BUF : std_logic; + signal CLK180_BUF : std_logic; + signal CLK270_BUF : std_logic; + signal CLKFX_BUF : std_logic; + signal CLK2X_BUF : std_logic; +begin + CLK0_OUT <= CLKFB_IN; + pclkUnbuf <= CLK0_BUF; + pclk90Unbuf <= CLK90_BUF; + pclk180Unbuf <= CLK180_BUF; + pclk270Unbuf <= CLK270_BUF; + + CLK0_BUFG_INST : BUFG + port map (I=>CLK0_BUF, + O=>CLKFB_IN); + CLKFX_BUFG_INST : BUFG + port map (I=>CLKFX_BUF, + O=>CLKFX_OUT); + CLK2X_BUFG_INST : BUFG + port map (I=>CLK2X_BUF, + O=>CLK2X_OUT); + CLK90_BUFG_INST : BUFG + port map (I=>CLK90_BUF, + O=>CLK90_OUT); + CLK180_BUFG_INST : BUFG + port map (I=>CLK180_BUF, + O=>CLK180_OUT); + CLK270_BUFG_INST : BUFG + port map (I=>CLK270_BUF, + O=>CLK270_OUT); + + DCM_ADV_INST : DCM_ADV + generic map( CLK_FEEDBACK => "1X", + CLKDV_DIVIDE => 2.0, + CLKFX_DIVIDE => 32, + CLKFX_MULTIPLY => 16, + CLKIN_DIVIDE_BY_2 => FALSE, + CLKIN_PERIOD => 6.250, + CLKOUT_PHASE_SHIFT => "DIRECT", + DCM_AUTOCALIBRATION => TRUE, + DCM_PERFORMANCE_MODE => "MAX_SPEED", + DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS", + DFS_FREQUENCY_MODE => "LOW", + DLL_FREQUENCY_MODE => "LOW", + DUTY_CYCLE_CORRECTION => TRUE, + FACTORY_JF => x"F0F0", + PHASE_SHIFT => 0, + STARTUP_WAIT => FALSE) + port map (CLKFB=>CLKFB_IN, + CLKIN=>CLKIN_IN, + DADDR(6 downto 0)=>DADDR_IN(6 downto 0), + DCLK=>DCLK_IN, + DEN=>DEN_IN, + DI(15 downto 0)=>DI_IN(15 downto 0), + DWE=>DWE_IN, + PSCLK=>'0', + PSEN=>'0', + PSINCDEC=>'0', + RST=>RST_IN, + CLKDV=>open, + CLKFX=>CLKFX_BUF, + CLKFX180=>open, + CLK0=>CLK0_BUF, + CLK2X=>CLK2X_BUF, + CLK2X180=>open, + CLK90=>CLK90_BUF, + CLK180=>CLK180_BUF, + CLK270=>CLK270_BUF, + DO=>open, + DRDY=>DRDY_OUT, + LOCKED=>LOCKED_OUT, + PSDONE=>open); + +end BEHAVIORAL; + + diff --git a/rce/fw-hsio/modules/pixelcore/hdl/ser.vhd b/rce/fw-hsio/modules/pixelcore/hdl/ser.vhd new file mode 100644 index 00000000..820fe713 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/ser.vhd @@ -0,0 +1,96 @@ +-------------------------------------------------------------- +-- Serializer for High Speed I/O board (ATLAS Pixel teststand) +-- Martin Kocian 01/2009 +-------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use work.all; + +-------------------------------------------------------------- + +entity ser is + +port( clk: in std_logic; + ld: out std_logic; + l1a: in std_logic; + go: in std_logic; + busy: out std_logic; + stop: in std_logic; + rst: in std_logic; + d_in: in std_logic_vector(15 downto 0); + d_out: out std_logic +); +end ser; + +-------------------------------------------------------------- + +architecture SER of ser is + +signal reg : std_logic_vector(15 downto 0); +signal busys: std_logic; +signal counter: std_logic_vector(3 downto 0); +signal l1acounter: std_logic_vector(2 downto 0); +signal going: std_logic; +signal oldl1a: std_logic; + +begin + + busy<=busys; + + process(rst, clk) + + begin + if(rst='1') then + reg<=x"0000"; + d_out<='0'; + going<='0'; + ld<='0'; + l1acounter<="000"; + oldl1a<='0'; + busys<='0'; + elsif (clk'event and clk='1') then + if (go='1' and stop='0' and busys='0')then + going<='1'; + counter<="0010"; + busys<='1'; + else + if (stop='1' and counter="0011") then + going<='0'; + end if; + if(counter="0010" and going='1') then -- it takes 2 cycles to + ld<='1'; -- get data from the FIFO; + elsif(counter="0001" and going='1') then + ld<='0'; -- Request is only 1 cycle long. + end if; + if (counter="0000" and going='1') then + reg<=d_in; + elsif (l1acounter="101")then + reg<=x"e800"; + else + reg(15 downto 1)<=reg(14 downto 0); + reg(0)<='0'; + end if; + if(l1acounter="010")then + busys<='0'; + elsif(going='0' and counter="0000" and l1acounter="000") then + busys<='0'; + end if; + if(l1a='1' and oldl1a='0' and busys='0')then + l1acounter<="101"; + busys<='1'; + elsif(l1acounter/="000")then + l1acounter<=unsigned(l1acounter)-1; + end if; + counter<=unsigned(counter)-1; + d_out<=reg(15); + end if; + oldl1a<=l1a; + end if; + + end process; + +end SER; + +-------------------------------------------------------------- diff --git a/rce/fw-hsio/modules/pixelcore/hdl/ser32.vhd b/rce/fw-hsio/modules/pixelcore/hdl/ser32.vhd new file mode 100644 index 00000000..af9a1e87 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/ser32.vhd @@ -0,0 +1,72 @@ +-------------------------------------------------------------- +-- Serializer for High Speed I/O board (ATLAS Pixel teststand) +-- Martin Kocian 01/2009 +-------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use work.all; + +-------------------------------------------------------------- + +entity ser32 is + +port( clk: in std_logic; + ld: out std_logic; + go: in std_logic; + busy: out std_logic; + stop: in std_logic; + rst: in std_logic; + d_in: in std_logic_vector(31 downto 0); + d_out: out std_logic +); +end ser32; + +-------------------------------------------------------------- + +architecture SER of ser32 is + +signal reg : std_logic_vector(31 downto 0); +signal counter: std_logic_vector(4 downto 0); +signal going: std_logic; + +begin + + busy<=going; + d_out<=reg(31); + process(rst, clk) + + begin + if(rst='1') then + reg<=x"00000000"; + going<='0'; + ld<='0'; + elsif (clk'event and clk='1') then + if (go='1')then + going<='1'; + counter<="00000"; + else + if (stop='1' and counter="00011") then + going<='0'; + end if; + if(counter="00010" and going='1') then -- it takes 2 cycles to + ld<='1'; -- get data from the FIFO; + elsif(counter="00001" and going='1') then + ld<='0'; -- Request is only 1 cycle long. + end if; + if (counter="00000" and going='1') then + reg<=d_in; + else + reg(31 downto 1)<=reg(30 downto 0); + reg(0)<='0'; + end if; + counter<=unsigned(counter)-1; + end if; + end if; + + end process; + +end SER; + +-------------------------------------------------------------- diff --git a/rce/fw-hsio/modules/pixelcore/hdl/stdlib.vhd b/rce/fw-hsio/modules/pixelcore/hdl/stdlib.vhd new file mode 100644 index 00000000..2e724fd7 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/stdlib.vhd @@ -0,0 +1,603 @@ +------------------------------------------------------------------------------ +-- This file is a part of the GRLIB VHDL IP LIBRARY +-- Copyright (C) 2003 - 2008, Gaisler Research +-- Copyright (C) 2008 - 2012, Aeroflex Gaisler +-- +-- This program 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 of the License, or +-- (at your option) any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +----------------------------------------------------------------------------- +-- Package: stdlib +-- File: stdlib.vhd +-- Author: Jiri Gaisler - Gaisler Research +-- Description: Package for common VHDL functions +------------------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +-- pragma translate_off +use std.textio.all; +-- pragma translate_on +--library grlib; +--use grlib.version.all; + +package stdlib is + +--constant LIBVHDL_VERSION : integer := grlib_version; +--constant LIBVHDL_BUILD : integer := grlib_build; +---- pragma translate_off +--constant LIBVHDL_DATE : string := grlib_date; +---- pragma translate_on +constant zero32 : std_logic_vector(31 downto 0) := (others => '0'); +constant zero64 : std_logic_vector(63 downto 0) := (others => '0'); +constant zero128 : std_logic_vector(127 downto 0) := (others => '0'); +constant one32 : std_logic_vector(31 downto 0) := (others => '1'); +constant one64 : std_logic_vector(63 downto 0) := (others => '1'); +constant one128 : std_logic_vector(127 downto 0) := (others => '1'); + +type log2arr is array(0 to 512) of integer; +constant log2 : log2arr := ( +0,0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + others => 9); +constant log2x : log2arr := ( +0,1,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + others => 9); + +function decode(v : std_logic_vector) return std_logic_vector; +function genmux(s,v : std_logic_vector) return std_ulogic; +function xorv(d : std_logic_vector) return std_ulogic; +function orv(d : std_logic_vector) return std_ulogic; +function andv(d : std_logic_vector) return std_ulogic; +function notx(d : std_logic_vector) return boolean; +function notx(d : std_ulogic) return boolean; +function "-" (d : std_logic_vector; i : integer) return std_logic_vector; +function "-" (i : integer; d : std_logic_vector) return std_logic_vector; +function "+" (d : std_logic_vector; i : integer) return std_logic_vector; +function "+" (i : integer; d : std_logic_vector) return std_logic_vector; +function "-" (d : std_logic_vector; i : std_ulogic) return std_logic_vector; +function "+" (d : std_logic_vector; i : std_ulogic) return std_logic_vector; +function "-" (a, b : std_logic_vector) return std_logic_vector; +function "+" (a, b : std_logic_vector) return std_logic_vector; +function "*" (a, b : std_logic_vector) return std_logic_vector; +function unsigned_mul (a, b : std_logic_vector) return std_logic_vector; +function signed_mul (a, b : std_logic_vector) return std_logic_vector; +function mixed_mul (a, b : std_logic_vector; sign : std_logic) return std_logic_vector; +--function ">" (a, b : std_logic_vector) return boolean; +function "<" (i : integer; b : std_logic_vector) return boolean; +function conv_integer(v : std_logic_vector) return integer; +function conv_integer(v : std_logic) return integer; +function conv_std_logic_vector(i : integer; w : integer) return std_logic_vector; +function conv_std_logic_vector_signed(i : integer; w : integer) return std_logic_vector; +function conv_std_logic(b : boolean) return std_ulogic; +attribute sync_set_reset : string; +attribute async_set_reset : string; + +-- Reporting and diagnostics + +-- pragma translate_off + +function tost(v:std_logic_vector) return string; +function tost(v:std_logic) return string; +function tost(i : integer) return string; +function tost_any(s: std_ulogic) return string; +function tost_bits(s: std_logic_vector) return string; +function tost(b: boolean) return string; +function tost(r: real) return string; +procedure print(s : string); + +component report_version + generic (msg1, msg2, msg3, msg4 : string := ""; mdel : integer := 4); +end component; + +-- pragma translate_on + +end; + +package body stdlib is + +function notx(d : std_logic_vector) return boolean is +variable res : boolean; +begin + res := true; +-- pragma translate_off + res := not is_x(d); +-- pragma translate_on + return (res); +end; + +function notx(d : std_ulogic) return boolean is +variable res : boolean; +begin + res := true; +-- pragma translate_off + res := not is_x(d); +-- pragma translate_on + return (res); +end; + +-- generic decoder + +function decode(v : std_logic_vector) return std_logic_vector is +variable res : std_logic_vector((2**v'length)-1 downto 0); +variable i : integer range res'range; +begin + res := (others => '0'); i := 0; + if notx(v) then i := to_integer(unsigned(v)); end if; + res(i) := '1'; + return(res); +end; + +-- generic multiplexer + +function genmux(s,v : std_logic_vector) return std_ulogic is +variable res : std_logic_vector(v'length-1 downto 0); +variable i : integer range res'range; +begin + res := v; i := 0; + if notx(s) then i := to_integer(unsigned(s)); end if; + return(res(i)); +end; + +-- vector XOR + +function xorv(d : std_logic_vector) return std_ulogic is +variable tmp : std_ulogic; +begin + tmp := '0'; + for i in d'range loop tmp := tmp xor d(i); end loop; + return(tmp); +end; + +-- vector OR + +function orv(d : std_logic_vector) return std_ulogic is +variable tmp : std_ulogic; +begin + tmp := '0'; + for i in d'range loop tmp := tmp or d(i); end loop; + return(tmp); +end; + +-- vector AND + +function andv(d : std_logic_vector) return std_ulogic is +variable tmp : std_ulogic; +begin + tmp := '1'; + for i in d'range loop tmp := tmp and d(i); end loop; + return(tmp); +end; + +-- unsigned multiplication + +function "*" (a, b : std_logic_vector) return std_logic_vector is +variable z : std_logic_vector(a'length+b'length-1 downto 0); +begin +-- pragma translate_off + if notx(a&b) then +-- pragma translate_on + return(std_logic_vector(unsigned(a) * unsigned(b))); +-- pragma translate_off + else + z := (others =>'X'); return(z); + end if; +-- pragma translate_on +end; + +-- signed multiplication + +function signed_mul (a, b : std_logic_vector) return std_logic_vector is +variable z : std_logic_vector(a'length+b'length-1 downto 0); +begin +-- pragma translate_off + if notx(a&b) then +-- pragma translate_on + return(std_logic_vector(signed(a) * signed(b))); +-- pragma translate_off + else + z := (others =>'X'); return(z); + end if; +-- pragma translate_on +end; + +-- unsigned multiplication + +function unsigned_mul (a, b : std_logic_vector) return std_logic_vector is +variable z : std_logic_vector(a'length+b'length-1 downto 0); +begin +-- pragma translate_off + if notx(a&b) then +-- pragma translate_on + return(std_logic_vector(unsigned(a) * unsigned(b))); +-- pragma translate_off + else + z := (others =>'X'); return(z); + end if; +-- pragma translate_on +end; + +-- signed/unsigned multiplication + +function mixed_mul (a, b : std_logic_vector; sign : std_logic) return std_logic_vector is +variable z : std_logic_vector(a'length+b'length-1 downto 0); +begin +-- pragma translate_off + if notx(a&b) then +-- pragma translate_on + if sign = '0' then + return(std_logic_vector(unsigned(a) * unsigned(b))); + else + return(std_logic_vector(signed(a) * signed(b))); + end if; +-- pragma translate_off + else + z := (others =>'X'); return(z); + end if; +-- pragma translate_on +end; + +-- unsigned addition + +function "+" (a, b : std_logic_vector) return std_logic_vector is +variable x : std_logic_vector(a'length-1 downto 0); +variable y : std_logic_vector(b'length-1 downto 0); +begin +-- pragma translate_off + if notx(a&b) then +-- pragma translate_on + return(std_logic_vector(unsigned(a) + unsigned(b))); +-- pragma translate_off + else + x := (others =>'X'); y := (others =>'X'); + if (x'length > y'length) then return(x); else return(y); end if; + end if; +-- pragma translate_on +end; + +function "+" (i : integer; d : std_logic_vector) return std_logic_vector is +variable x : std_logic_vector(d'length-1 downto 0); +begin +-- pragma translate_off + if notx(d) then +-- pragma translate_on + return(std_logic_vector(unsigned(d) + i)); +-- pragma translate_off + else x := (others =>'X'); return(x); + end if; +-- pragma translate_on +end; + +function "+" (d : std_logic_vector; i : integer) return std_logic_vector is +variable x : std_logic_vector(d'length-1 downto 0); +begin +-- pragma translate_off + if notx(d) then +-- pragma translate_on + return(std_logic_vector(unsigned(d) + i)); +-- pragma translate_off + else x := (others =>'X'); return(x); + end if; +-- pragma translate_on +end; + +function "+" (d : std_logic_vector; i : std_ulogic) return std_logic_vector is +variable x : std_logic_vector(d'length-1 downto 0); +variable y : std_logic_vector(0 downto 0); +begin + y(0) := i; +-- pragma translate_off + if notx(d) then +-- pragma translate_on + return(std_logic_vector(unsigned(d) + unsigned(y))); +-- pragma translate_off + else x := (others =>'X'); return(x); + end if; +-- pragma translate_on +end; + +-- unsigned subtraction + +function "-" (a, b : std_logic_vector) return std_logic_vector is +variable x : std_logic_vector(a'length-1 downto 0); +variable y : std_logic_vector(b'length-1 downto 0); +begin +-- pragma translate_off + if notx(a&b) then +-- pragma translate_on + return(std_logic_vector(unsigned(a) - unsigned(b))); +-- pragma translate_off + else + x := (others =>'X'); y := (others =>'X'); + if (x'length > y'length) then return(x); else return(y); end if; + end if; +-- pragma translate_on +end; + +function "-" (d : std_logic_vector; i : integer) return std_logic_vector is +variable x : std_logic_vector(d'length-1 downto 0); +begin +-- pragma translate_off + if notx(d) then +-- pragma translate_on + return(std_logic_vector(unsigned(d) - i)); +-- pragma translate_off + else x := (others =>'X'); return(x); + end if; +-- pragma translate_on +end; + +function "-" (i : integer; d : std_logic_vector) return std_logic_vector is +variable x : std_logic_vector(d'length-1 downto 0); +begin +-- pragma translate_off + if notx(d) then +-- pragma translate_on + return(std_logic_vector(i - unsigned(d))); +-- pragma translate_off + else x := (others =>'X'); return(x); + end if; +-- pragma translate_on +end; + +function "-" (d : std_logic_vector; i : std_ulogic) return std_logic_vector is +variable x : std_logic_vector(d'length-1 downto 0); +variable y : std_logic_vector(0 downto 0); +begin + y(0) := i; +-- pragma translate_off + if notx(d) then +-- pragma translate_on + return(std_logic_vector(unsigned(d) - unsigned(y))); +-- pragma translate_off + else x := (others =>'X'); return(x); + end if; +-- pragma translate_on +end; + +function ">=" (a, b : std_logic_vector) return boolean is +begin + return(unsigned(a) >= unsigned(b)); +end; + +function "<" (i : integer; b : std_logic_vector) return boolean is +begin + return( i < to_integer(unsigned(b))); +end; + +function ">" (a, b : std_logic_vector) return boolean is +begin + return(unsigned(a) > unsigned(b)); +end; + +function conv_integer(v : std_logic_vector) return integer is +begin + if notx(v) then return(to_integer(unsigned(v))); + else return(0); end if; +end; + +function conv_integer(v : std_logic) return integer is +begin + if notx(v) then + if v = '1' then return(1); + else return(0); end if; + else return(0); end if; +end; + +function conv_std_logic_vector(i : integer; w : integer) return std_logic_vector is +variable tmp : std_logic_vector(w-1 downto 0); +begin + tmp := std_logic_vector(to_unsigned(i, w)); + return(tmp); +end; + +function conv_std_logic_vector_signed(i : integer; w : integer) return std_logic_vector is +variable tmp : std_logic_vector(w-1 downto 0); +begin + tmp := std_logic_vector(to_signed(i, w)); + return(tmp); +end; + +function conv_std_logic(b : boolean) return std_ulogic is +begin + if b then return('1'); else return('0'); end if; +end; + +-- pragma translate_off +subtype nibble is std_logic_vector(3 downto 0); + +function todec(i:integer) return character is +begin + case i is + when 0 => return('0'); + when 1 => return('1'); + when 2 => return('2'); + when 3 => return('3'); + when 4 => return('4'); + when 5 => return('5'); + when 6 => return('6'); + when 7 => return('7'); + when 8 => return('8'); + when 9 => return('9'); + when others => return('0'); + end case; +end; + +function tohex(n:nibble) return character is +begin + case n is + when "0000" => return('0'); + when "0001" => return('1'); + when "0010" => return('2'); + when "0011" => return('3'); + when "0100" => return('4'); + when "0101" => return('5'); + when "0110" => return('6'); + when "0111" => return('7'); + when "1000" => return('8'); + when "1001" => return('9'); + when "1010" => return('a'); + when "1011" => return('b'); + when "1100" => return('c'); + when "1101" => return('d'); + when "1110" => return('e'); + when "1111" => return('f'); + when others => return('X'); + end case; +end; + +function tost(v:std_logic_vector) return string is +constant vlen : natural := v'length; --' +constant slen : natural := (vlen+3)/4; +variable vv : std_logic_vector(0 to slen*4-1) := (others => '0'); +variable s : string(1 to slen); +variable nz : boolean := false; +variable index : integer := -1; +begin + vv(slen*4-vlen to slen*4-1) := v; + for i in 0 to slen-1 loop + if (vv(i*4 to i*4+3) = "0000") and nz and (i /= (slen-1)) then + index := i; + else + nz := false; + s(i+1) := tohex(vv(i*4 to i*4+3)); + end if; + end loop; + if ((index +2) = slen) then return(s(slen to slen)); + else return(string'("0x") & s(index+2 to slen)); end if; --' +end; + +function tost(v:std_logic) return string is +begin + if to_x01(v) = '1' then return("1"); else return("0"); end if; +end; + +function tost_any(s: std_ulogic) return string is +begin + case s is + when '1' => return "1"; + when '0' => return "0"; + when '-' => return "-"; + when 'U' => return "U"; + when 'X' => return "X"; + when 'Z' => return "Z"; + when 'H' => return "H"; + when 'L' => return "L"; + when 'W' => return "W"; + end case; +end; + +function tost_bits(s: std_logic_vector) return string is + constant len: natural := s'length; + variable str: string(1 to len); + variable i: integer; +begin + i := 1; + for x in s'range loop + str(i to i) := tost_any(s(x)); + i := i+1; + end loop; + return str; +end; + +function tost(b: boolean) return string is +begin + if b then return "true"; else return "false"; end if; +end tost; + +function tost(i : integer) return string is +variable L : line; +variable s, x : string(1 to 128); +variable n, tmp : integer := 0; +begin + tmp := i; + if i < 0 then tmp := -i; end if; + loop + s(128-n) := todec(tmp mod 10); + tmp := tmp / 10; + n := n+1; + if tmp = 0 then exit; end if; + end loop; + x(1 to n) := s(129-n to 128); + if i < 0 then return "-" & x(1 to n); end if; + return(x(1 to n)); +end; + +function tost(r: real) return string is + variable x: real; + variable i,j: integer; + variable s: string(1 to 30); + variable c: character; +begin + if r = 0.0 then + return "0.0000"; + elsif r < 0.0 then + return "-" & tost(-r); + elsif r < 0.001 then + x:=r; i:=0; + while x<1.0 loop x:=x*10.0; i:=i+1; end loop; + return tost(x) & "e-" & tost(i); + elsif r >= 1000000.0 then + x:=10000000.0; i:=6; + while r>=x loop x:=x*10.0; i:=i+1; end loop; + return tost(10.0*r/x) & "e+" & tost(i); + else + i:=0; x:=r+0.00005; + while x >= 10.0 loop x:=x/10.0; i:=i+1; end loop; + j := 1; + while i > -5 loop + if x >= 9.0 then c:='9'; x:=x-9.0; + elsif x >= 8.0 then c:='8'; x:=x-8.0; + elsif x >= 7.0 then c:='7'; x:=x-7.0; + elsif x >= 6.0 then c:='6'; x:=x-6.0; + elsif x >= 5.0 then c:='5'; x:=x-5.0; + elsif x >= 4.0 then c:='4'; x:=x-4.0; + elsif x >= 3.0 then c:='3'; x:=x-3.0; + elsif x >= 2.0 then c:='2'; x:=x-2.0; + elsif x >= 1.0 then c:='1'; x:=x-1.0; + else c:='0'; + end if; + s(j) := c; + j:=j+1; + if i=0 then s(j):='.'; j:=j+1; end if; + i:=i-1; + x := x * 10.0; + end loop; + return s(1 to j-1); + end if; +end tost; + +procedure print(s : string) is + variable L : line; +begin + L := new string'(s); writeline(output, L); +end; + +-- pragma translate_on +end; + + diff --git a/rce/fw-hsio/modules/pixelcore/hdl/syncdatac.vhd b/rce/fw-hsio/modules/pixelcore/hdl/syncdatac.vhd new file mode 100644 index 00000000..ad8b9207 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/syncdatac.vhd @@ -0,0 +1,317 @@ +------------------------------------------------------------------------------ +-- +-- Xilinx, Inc. 2002 www.xilinx.com +-- +-- XAPP 225 +-- +------------------------------------------------------------------------------ +-- +-- File name : sync_master_v2.vhd +-- +-- Description : Master phase aligner module for Virtex2 (2 bits) +-- +-- Date - revision : January 6th 2009 - v 1.2 +-- +-- Author : NJS +-- +-- Disclaimer: LIMITED WARRANTY AND DISCLAMER. These designs are +-- provided to you "as is". Xilinx and its licensors make and you +-- receive no warranties or conditions, express, implied, +-- statutory or otherwise, and Xilinx specifically disclaims any +-- implied warranties of merchantability, non-infringement,or +-- fitness for a particular purpose. Xilinx does not warrant that +-- the functions contained in these designs will meet your +-- requirements, or that the operation of these designs will be +-- uninterrupted or error free, or that defects in the Designs +-- will be corrected. Furthermore, Xilinx does not warrantor +-- make any representations regarding use or the results of the +-- use of the designs in terms of correctness, accuracy, +-- reliability, or otherwise. +-- +-- LIMITATION OF LIABILITY. In no event will Xilinx or its +-- licensors be liable for any loss of data, lost profits,cost +-- or procurement of substitute goods or services, or for any +-- special, incidental, consequential, or indirect d[DX] Dependencies for CalibGui.cc +-- arising from the use or operation of the designs or +-- accompanying documentation, however caused and on any theory +-- of liability. This limitation will apply even if Xilinx +-- has been advised of the possibility of such damage. This +-- limitation shall apply not-withstanding the failure of the +-- essential purpose of any limited remedies herein. +-- +-- Copyright ยฉ 2002 Xilinx, Inc. +-- All rights reserved +-- +------------------------------------------------------------------------------ +-- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +library unisim ; +use unisim.vcomponents.all ; + +entity syncdatac is port ( + clk : in std_logic ; -- clock input + clk90 : in std_logic ; -- clock 90 input + rdatain : in std_logic; -- data input + rst : in std_logic ; -- reset input + useaout : out std_logic ; -- useA output for cascade + usebout : out std_logic ; -- useB output for cascade + usecout : out std_logic ; -- useC output for cascade + usedout : out std_logic ; -- useD output for cascade +-- useain : in std_logic ; -- useA output for cascade +-- usebin : in std_logic ; -- useB output for cascade +-- usecin : in std_logic ; -- useC output for cascade +-- usedin : in std_logic ; -- useD output for cascade + sdataout : out std_logic; -- data out + phaseConfig : in std_logic); -- Flag for calibration +end syncdatac; + +architecture arch_syncdata of syncdatac is + +-- component chipscope_ila +-- PORT ( +-- CONTROL : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0); +-- CLK : IN STD_LOGIC; +-- DATA : IN STD_LOGIC_VECTOR(15 DOWNTO 0); +-- TRIG0 : IN STD_LOGIC_VECTOR(7 DOWNTO 0)); + +-- end component; + +-- component chipscope_icon +-- PORT ( +-- CONTROL0 : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0)); +-- end component; + +-- attribute syn_noprune : boolean; +-- attribute syn_noprune of ila : label is true; +-- attribute syn_noprune of icon : label is true; + + +signal aa0 : std_logic; +signal bb0 : std_logic; +signal cc0 : std_logic; +signal dd0 : std_logic; +signal usea : std_logic; +signal useb : std_logic; +signal usec : std_logic; +signal used : std_logic; +signal useaint : std_logic; +signal usebint : std_logic; +signal usecint : std_logic; +signal usedint : std_logic; +signal ctrlint : std_logic_vector(1 downto 0); +signal sdataa : std_logic; +signal sdatab : std_logic; +signal sdatac : std_logic; +signal sdatad : std_logic; +signal az : std_logic_vector(2 downto 0) ; +signal bz : std_logic_vector(2 downto 0) ; +signal cz : std_logic_vector(2 downto 0) ; +signal dz : std_logic_vector(2 downto 0) ; +signal aap, bbp : std_logic; +signal aan, bbn : std_logic; +signal ccp, ddp : std_logic; +signal ccn, ddn : std_logic; +signal pipe_ce0 : std_logic; +signal notclk : std_logic; +signal notclk90 : std_logic; + +-- signal control : std_logic_vector(35 downto 0) ; + + +-- FS: Counters to determine most likely phase +signal countera : std_logic_vector(7 downto 0); +signal counterb : std_logic_vector(7 downto 0); +signal counterc : std_logic_vector(7 downto 0); +signal counterd : std_logic_vector(7 downto 0); + +signal useatemp : std_logic; +signal usebtemp : std_logic; +signal usectemp : std_logic; +signal usedtemp : std_logic; + +-- signal data : std_logic_vector(15 downto 0); +-- signal trigger : std_logic_vector(7 downto 0); +signal count : std_logic; +signal changed : std_logic; + + + + +attribute RLOC : string ; +attribute RLOC of ff_az0 : label is "X0Y2"; +attribute RLOC of ff_az1 : label is "X0Y2"; + +attribute RLOC of ff_bz0 : label is "X0Y1"; +attribute RLOC of ff_bz1 : label is "X1Y1"; + +attribute RLOC of ff_cz0 : label is "X1Y0"; +attribute RLOC of ff_cz1 : label is "X1Y1"; + +attribute RLOC of ff_dz0 : label is "X0Y0"; +attribute RLOC of ff_dz1 : label is "X0Y1"; + + + +begin + +notclk <= not clk ; +notclk90 <= not clk90 ; +useaout <= useaint ; +usebout <= usebint ; +usecout <= usecint ; +usedout <= usedint ; +sdataa <= (aa0 and useaint) ; +sdatab <= (bb0 and usebint) ; +sdatac <= (cc0 and usecint) ; +sdatad <= (dd0 and usedint) ; + +saa0 : srl16 port map(d => az(2), clk => clk, a0 => ctrlint(0), a1 => ctrlint(1), a2 => '0', a3 => '0', q => aa0); +sbb0 : srl16 port map(d => bz(2), clk => clk, a0 => ctrlint(0), a1 => ctrlint(1), a2 => '0', a3 => '0', q => bb0); +scc0 : srl16 port map(d => cz(2), clk => clk, a0 => ctrlint(0), a1 => ctrlint(1), a2 => '0', a3 => '0', q => cc0); +sdd0 : srl16 port map(d => dz(2), clk => clk, a0 => ctrlint(0), a1 => ctrlint(1), a2 => '0', a3 => '0', q => dd0); + + +process (clk, rst) +begin +if rst = '1' then + ctrlint <= "10" ; + useaint <= '0' ; usebint <= '0' ; usecint <= '0' ; usedint <= '0' ; + usea <= '0' ; useb <= '0' ; usec <= '0' ; used <= '0' ; + useatemp <= '0';usebtemp <= '0';usectemp <= '0';usedtemp <= '0'; + pipe_ce0 <= '0' ; sdataout <= '0' ; + aap <= '0' ; bbp <= '0' ; ccp <= '0' ; ddp <= '0' ; + aan <= '0' ; bbn <= '0' ; ccn <= '0' ; ddn <= '0' ; + az(2) <= '0' ; bz(2) <= '0' ; cz(2) <= '0' ; dz(2) <= '0' ; + countera <= "00000000"; counterb <= "00000000"; counterc <= "00000000"; counterd <= "00000000"; + count <= '0'; + changed <= '0'; +elsif clk'event and clk = '1' then + az(2) <= az(1) ; bz(2) <= bz(1) ; cz(2) <= cz(1) ; dz(2) <= dz(1) ; + aap <= (az(2) xor az(1)) and not az(1) ; -- find positive edges + bbp <= (bz(2) xor bz(1)) and not bz(1) ; + ccp <= (cz(2) xor cz(1)) and not cz(1) ; + ddp <= (dz(2) xor dz(1)) and not dz(1) ; + aan <= (az(2) xor az(1)) and az(1) ; -- find negative edges + bbn <= (bz(2) xor bz(1)) and bz(1) ; + ccn <= (cz(2) xor cz(1)) and cz(1) ; + ddn <= (dz(2) xor dz(1)) and dz(1) ; + useatemp <= (bbp and not ccp and not ddp and aap) or (bbn and not ccn and not ddn and aan) ; + usebtemp <= (ccp and not ddp and aap and bbp) or (ccn and not ddn and aan and bbn) ; + usectemp <= (ddp and aap and bbp and ccp) or (ddn and aan and bbn and ccn) ; + usedtemp <= (aap and not bbp and not ccp and not ddp) or (aan and not bbn and not ccn and not ddn) ; +-- usea<=useain; +-- useb<=usebin; +-- usec<=usecin; +-- used<=usedin; + + if phaseConfig = '1' then + count <= '1'; + end if; + + + if count = '1' then + if useatemp='1' then -- FS: Only one of the usex equal 1 + countera <= countera+1; + elsif usebtemp='1' then + counterb <= counterb+1; + elsif usectemp='1' then + counterc <= counterc+1; + elsif usedtemp='1' then + counterd <= counterd+1; + end if; + end if; +-- data(7) <= useatemp; +-- data(6) <= usebtemp; +-- data(5) <= usectemp; +-- data(4) <= usedtemp; + + if countera = "11111111" then -- FS: . . . and set the one reaching the end of the counter + usea <= '1'; + useb <= '0'; + usec <= '0'; + used <= '0'; + changed <= '1'; + + elsif counterb = "11111111" then + usea <= '0'; + useb <= '1'; + usec <= '0'; + used <= '0'; + changed <= '1'; + + elsif counterc = "11111111" then + usea <= '0'; + useb <= '0'; + usec <= '1'; + used <= '0'; + changed <= '1'; + + elsif counterd = "11111111" then + usea <= '0'; + useb <= '0'; + usec <= '0'; + used <= '1'; + changed <= '1'; + + elsif changed = '1' then + changed <= '0'; + pipe_ce0 <= '1' ; + useaint <= usea ; + usebint <= useb ; + usecint <= usec ; + usedint <= used ; + + -- data(3) <= usea; + -- data(2) <= useb; + -- data(1) <= usec; + -- data(0) <= used; + + countera <= "00000000"; -- FS: Reset all counters if one of them has reached the end + counterb <= "00000000"; + counterc <= "00000000"; + counterd <= "00000000"; + count <= '0'; + end if ; + if pipe_ce0 = '1' then + sdataout <= sdataa or sdatab or sdatac or sdatad ; + end if ; + if usedint = '1' and usea = '1' then -- 'd' going to 'a' + ctrlint <= ctrlint - 1 ; + elsif useaint = '1' and used = '1' then -- 'a' going to 'd' + ctrlint <= ctrlint + 1 ; + end if ; +end if ; +end process ; + +-- get all the samples into the same time domain + +ff_az0 : fdc port map(d => rdatain, c => clk, clr => rst, q => az(0)); +ff_az1 : fdc port map(d => az(0), c => clk, clr => rst, q => az(1)); + +ff_bz0 : fdc port map(d => rdatain, c => clk90, clr => rst, q => bz(0)); +ff_bz1 : fdc port map(d => bz(0), c => clk, clr => rst, q => bz(1)); + +ff_cz0 : fdc port map(d => rdatain, c => notclk, clr => rst, q => cz(0)); +ff_cz1 : fdc port map(d => cz(0), c => clk, clr => rst, q => cz(1)); + +ff_dz0 : fdc port map(d => rdatain, c => notclk90, clr => rst, q => dz(0)); +ff_dz1 : fdc port map(d => dz(0), c => clk90, clr => rst, q => dz(1)); + +-- trigger <= "0000000" & phaseConfig; + + +-- icon : chipscope_icon +-- port map ( +-- CONTROL0 => control); + +-- ila : chipscope_ila +-- port map ( +-- CONTROL => control, +-- CLK => clk, +-- DATA => data, +-- TRIG0 => trigger); + +end arch_syncdata; diff --git a/rce/fw-hsio/modules/pixelcore/hdl/tdc.vhd b/rce/fw-hsio/modules/pixelcore/hdl/tdc.vhd new file mode 100644 index 00000000..b916b5b1 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/tdc.vhd @@ -0,0 +1,215 @@ + +-------------------------------------------------------------- +-- Serializer for High Speed I/O board (ATLAS Pixel teststand) +-- Martin Kocian 01/2009 +-------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use work.all; + +-------------------------------------------------------------- + +entity tdc is + +port( sysclk: in std_logic; + sysrst: in std_logic; + edge1: in std_logic; + edge2: in std_logic; + start: in std_logic; + ready: out std_logic; + counter1: out std_logic_vector(31 downto 0); + counter2: out std_logic_vector(31 downto 0) +); +end tdc; + +--------------------------------------------------------------- + +architecture TDC of tdc is + component FDCPE + generic(INIT:bit:='0'); + port( + Q : out std_logic; + C : in STD_LOGIC; + CE : in STD_LOGIC; + CLR : in STD_LOGIC; + D : in STD_LOGIC; + PRE : in STD_LOGIC); + end component; + component LUT1_D + generic(INIT:bit_vector(1 downto 0)); + port( + LO: out std_logic; + O : out std_logic; + I0: in std_logic + ); + end component; + component BUFG + port ( + O: out std_logic; + I: in std_logic + ); + end component; + component BUFR + generic (BUFR_DIVIDE : string := "BYPASS"); + port ( + O: out std_logic; + CE: in std_logic; + CLR: in std_logic; + I: in std_logic + ); + end component; + constant numdel:integer:=64; + attribute LUT_MAP : string; + attribute LUT_MAP of LUT1_D : component is "lut"; + signal clear: std_logic; + signal isready: std_logic; + signal oldstart: std_logic; + signal oldoldstart: std_logic; + signal controlstop: std_logic; + signal controlstopb: std_logic; + signal controlstartb: std_logic; + signal carry: std_logic_vector(numdel downto 0); + signal result: std_logic_vector(numdel-1 downto 0); + signal localtap: std_logic_vector(numdel-1 downto 0); + signal ss: std_logic_vector(numdel-1 downto 0); + signal st: std_logic_vector(numdel-1 downto 0); + + attribute U_SET: string; + attribute RLOC: string; + attribute U_SET of startcontrol: label is "TDC"; + attribute RLOC of startcontrol : label is "X0Y-1"; + attribute U_SET of stopcontrol: label is "TDC"; + attribute RLOC of stopcontrol : label is "X0Y0"; + + --attribute U_SET of MUX: label is "TDC"; + attribute Keep: boolean; + attribute Keep of carry : signal is true; + attribute Keep of localtap : signal is true; + attribute Keep of controlstop : signal is true; + attribute Keep of ss : signal is true; + attribute Keep of st : signal is true; + attribute OPT: string; + attribute OPT of carry : signal is "KEEP"; + attribute OPT of localtap : signal is "KEEP"; + attribute OPT of controlstop : signal is "KEEP"; + attribute OPT of st : signal is "KEEP"; +begin + ready<=isready; + process (sysrst, sysclk) + begin + if(sysrst='1') then + isready<='0'; + oldstart<='0'; + oldoldstart<='0'; + clear<='1'; + elsif(rising_edge(sysclk)) then + if(start='1' and oldstart='0')then + clear<='1'; + elsif(oldstart='1' and oldoldstart='0')then + clear<='0'; + isready<='1'; + elsif(controlstop='1')then + isready<='0'; + end if; + oldstart<=start; + oldoldstart<=oldstart; + end if; + end process; + + CHAIN: + for I in 0 to numdel-1 generate + constant lfour :natural:=(I mod 8)/4; + constant sfour :natural:= 1-lfour; + constant row :natural:=sfour*((I mod 4)*2+(I/8) mod 2)+lfour*(6-(I mod 4)*2 + (I/8) mod 2); + constant column:natural:=((I/4)mod 2)*2+I/32+1; + constant rloc_str : string := "X" & natural'image(row) & "Y" & natural'image(column); + attribute RLOC of TAP: label is rloc_str; + attribute RLOC of DELAYY: label is rloc_str; + attribute U_SET of TAP: label is "TDC"; + attribute U_SET of DELAYY: label is "TDC"; + begin + TAP: FDCPE + port map ( + Q=>result(I), + C=>controlstop, + CE=>'1', + CLR=>clear, + D=>st(i), --localtap(I), + PRE=>'0' + ); + -- MUX: MUXF5_D + -- port map ( + -- LO => localtap(I), + -- O => carry(I+1), + -- I0 => ss(I), + -- I1 => carry(I), + -- S => '1' + -- ); + -- DELAYX: LUT1_D + -- generic map ( INIT => "11" ) + -- port map ( + -- LO => ss(I), + -- O => open, + -- I0 => isready + -- ); + DELAYY: LUT1_D + generic map ( INIT => "10" ) + port map ( + LO => st(I), + O => carry(I+1), + I0 => carry(I) + ); + end generate CHAIN; + + + + startcontrol: FDCPE + port map ( + Q=>carry(0), + C=>edge1, + CE=>'1', + CLR=>clear, + D=>'1', + PRE=>'0' + ); + stopcontrol: FDCPE + port map ( + Q=>controlstopb, + C=>edge2, + CE=>carry(0), + CLR=>clear, + D=>'1', + PRE=>'0' + ); + -- BUFG_stop: BUFG + -- port map( + -- O => controlstop, + -- I => controlstopb + -- ); + BUFR_stop : BUFR + generic map ( + BUFR_DIVIDE => "BYPASS") + port map ( + O => controlstop, -- Clock buffer output + CE => '1', -- Clock enable input + CLR => '0', -- Clock buffer reset input + I => controlstopb -- Clock buffer input + ); + --BUFG_start: BUFG + --port map( + --O => carry(0), + --I => controlstartb + --); + +-- ex: for i in 0 to numdel/2-1 generate +-- counter1(i)<=result(I*2); +-- end generate ex; + counter1<=result(31 downto 0); + counter2<=result(63 downto 32); +end TDC; + + + + diff --git a/rce/fw-hsio/modules/pixelcore/hdl/tdcreadout.vhd b/rce/fw-hsio/modules/pixelcore/hdl/tdcreadout.vhd new file mode 100644 index 00000000..0a72733b --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/tdcreadout.vhd @@ -0,0 +1,176 @@ +-------------------------------------------------------------- +-- Serializer for High Speed I/O board (ATLAS Pixel teststand) +-- Martin Kocian 01/2009 +-------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.all; + +-------------------------------------------------------------- + +entity tdcreadout is +generic( CHANNEL: std_logic_vector:="1111"); +port( clk: in std_logic; + rst: in std_logic; + slowclock: in std_logic; + go: in std_logic; + delay: in std_logic_vector(4 downto 0); + counter1: in std_logic_vector(31 downto 0); + counter2: in std_logic_vector(31 downto 0); + trgtime: in std_logic_vector(63 downto 0); + deadtime: in std_logic_vector(63 downto 0); + status: in std_logic_vector(14 downto 0); + marker: in std_logic; + l1count: in std_logic_vector(3 downto 0); + bxid : in std_logic_vector(7 downto 0); + d_out: out std_logic_vector(15 downto 0); + ld: out std_logic; + busy: out std_logic; + sof: out std_logic; + eof: out std_logic; + runmode: in std_logic_vector(1 downto 0); + eudaqdone: in std_logic; + eudaqtrgword: in std_logic_vector(14 downto 0); + fifothresh: in std_logic_vector(7 downto 0); + triggerword:in std_logic_vector(7 downto 0) +); +end tdcreadout; + +-------------------------------------------------------------- + +architecture TDCREADOUT of tdcreadout is + + signal headercounter: unsigned (5 downto 0); + signal busys: std_logic; + signal marked: std_logic; + signal eventmark: std_logic; + signal waitforeudaq: std_logic; + signal oldbusys: std_logic; + signal oldoldbusys: std_logic; + +begin + + busy<=oldoldbusys; + process(rst, slowclock) + begin + if(rst='1')then + oldbusys<='0'; + oldoldbusys<='0'; + elsif (rising_edge(slowclock))then + oldbusys<=busys; + oldoldbusys<=oldbusys; + end if; + end process; + + process(rst, clk) + begin + if(rst='1') then + d_out<=x"0000"; + eof<='0'; + sof<='0'; + headercounter<=(others => '0'); + ld<='0'; + busys<='0'; + marked<='0'; + eventmark<='0'; + waitforeudaq<='0'; + elsif (clk'event and clk='1') then + if(marker='1')then + eventmark<='1'; + elsif(marked='1')then + eventmark<='0'; + end if; + if(busys='0' and go='1')then + busys<='1'; + eof<='0'; + headercounter<=unsigned('0'&delay)+31; + if(delay="00000") then + sof<='1'; + ld<='1'; + end if; + d_out<=x"0000"; + elsif (headercounter/=0)then + if (headercounter=32) then + sof<='1'; + ld<='1'; + elsif (headercounter=31) then + sof<='0'; + d_out(7 downto 0)<=(others=>'0'); + d_out(15 downto 8)<=x"0"&CHANNEL; + --d_out<=tid(23 downto 8); + elsif(headercounter=30) then + d_out<=x"0000"; + elsif(headercounter=29) then + d_out<=eventmark&"000"&x"000"; + elsif(headercounter=28) then + d_out<=x"0000"; + elsif(headercounter=16) then + d_out<=x"0" & l1count & bxid; + elsif(headercounter=15) then + d_out<=eventmark&status; + elsif(headercounter=14) then + d_out<=counter1(31 downto 16); + elsif(headercounter=13) then + d_out<=counter1(15 downto 0); + elsif(headercounter=12) then + d_out<=counter2(31 downto 16); + elsif(headercounter=11) then + d_out<=counter2(15 downto 0); + elsif(headercounter=10) then + d_out<=trgtime(63 downto 48); + elsif(headercounter=9) then + d_out<=trgtime(47 downto 32); + elsif(headercounter=8) then + d_out<=trgtime(31 downto 16); + elsif(headercounter=7) then + d_out<=trgtime(15 downto 0); + elsif(headercounter=6) then + d_out<=deadtime(63 downto 48); + elsif(headercounter=5) then + d_out<=deadtime(47 downto 32); + elsif(headercounter=4) then + d_out<=deadtime(31 downto 16); + elsif(headercounter=3) then + d_out<=deadtime(15 downto 0); + marked<='1'; + elsif(headercounter=2) then + d_out<=fifothresh&triggerword; + marked<='0'; + elsif(headercounter=1) then + if (runmode(1)='1')then + ld<='0'; + waitforeudaq<='1'; + else + d_out<=(others=>'0'); + eof<='1'; + end if; + else + d_out<=(others=>'0'); + end if; + headercounter<=headercounter-1; + else + if(waitforeudaq='1')then + if(eudaqdone='1')then + ld<='1'; + eof<='1'; + d_out<='0'&eudaqtrgword; + waitforeudaq<='0'; + else + ld<='0'; + d_out<=(others=>'0'); + end if; + else + eof<='0'; + ld<='0'; + busys<='0'; + end if; + end if; + end if; + + end process; + +end TDCREADOUT; + +-------------------------------------------------------------- diff --git a/rce/fw-hsio/modules/pixelcore/hdl/tempadc.vhd b/rce/fw-hsio/modules/pixelcore/hdl/tempadc.vhd new file mode 100644 index 00000000..84edc165 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/tempadc.vhd @@ -0,0 +1,93 @@ +-------------------------------------------------------------- +-- ADC Analog Devices 7998 readout +-- Martin Kocian 12/2014 +-------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.StdRtlPkg.all; +use work.I2cPkg.all; +use work.all; + +-------------------------------------------------------------- + +entity tempadc is +generic( PRESCALE_G: integer range 0 to 65535 := 79; + MAPPING_G: NaturalArray(0 to 7) := (7,6,5,4,3,2,1,0) ); +port( clk: in std_logic; + d_out: out Slv16Array(11 downto 0):=(others => (others => '0')); + trig: in std_logic; + ld: out std_logic:= '0'; + adcAS: out std_logic; + scl: inout std_logic; + sda: inout std_logic +); +end tempadc; + +-------------------------------------------------------------- + +architecture TEMPADC of tempadc is + + type state_type is (idle, req, ack); + signal state: state_type; + signal adcI2cIn : i2c_in_type; + signal adcI2cOut : i2c_out_type; + signal i2cregmasterin: I2cRegMasterInType := I2C_REG_MASTER_IN_INIT_C; + signal i2cregmasterout: I2cRegMasterOutType; + signal index: natural range 0 to 7; +begin + sda <= adcI2cOut.sda when adcI2cOut.sdaoen = '0' else 'Z'; + adcI2cIn.sda <= to_x01z(sda); + scl <= adcI2cOut.scl when adcI2cOut.scloen = '0' else 'Z'; + adcI2cIn.scl <= to_x01z(scl); + adcAS <='0'; + + i2cregmasterin.regDataSize<="01"; + i2cregmasterin.endianness<='1'; + i2cregmasterin.i2cAddr<="0000100001"; + + chanmap: for I in 0 to 3 generate + d_out(I)<=toSlv(MAPPING_G(I*2), 8)& toSlv(MAPPING_G(I*2+1), 8); + end generate chanmap; + I2cRegMaster_Inst: entity work.I2cRegMaster + generic map( + PRESCALE_G => PRESCALE_G) + port map( + clk => clk, + regIn => i2cregmasterin, + regOut => i2cregmasterout, + i2ci => adcI2cIn, + i2co => adcI2cOut); + + process begin + wait until (rising_edge(clk)); + if(state=idle)then + ld<='0'; + if(trig='1') then + state<=req; + index<=0; + end if; + elsif (state=req)then + i2cregmasterin.regAddr <= toSlv(128+index*16, 32); + i2cregmasterin.regReq<='1'; + state<=ack; + elsif(state=ack)then + i2cregmasterin.regReq<='0'; + if(i2cregmasterout.regAck='1')then + d_out(index+4)<=i2cregmasterout.regRdData(7 downto 0) & i2cregmasterout.regRdData(15 downto 8); + if(index=7)then + ld<='1'; + state<=idle; + else + index<=index+1; + state<=req; + end if; + end if; + end if; + end process; + + +end TEMPADC; + +-------------------------------------------------------------- diff --git a/rce/fw-hsio/modules/pixelcore/hdl/triggerlogic.vhd b/rce/fw-hsio/modules/pixelcore/hdl/triggerlogic.vhd new file mode 100644 index 00000000..1dc106ec --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/triggerlogic.vhd @@ -0,0 +1,290 @@ +-------------------------------------------------------------- +-- Trigger logic for pixel HSIO firmware +-- Martin Kocian 07/2014 +-------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use work.all; +use work.arraytype.all; + +-------------------------------------------------------------- + + +entity triggerlogic is + +port( clk: in std_logic; + rst: in std_logic; + clk160: in std_logic; + rst160: in std_logic; + -- hardware inputs + discin : in std_logic_vector(3 downto 0); + hitbusin : in std_logic_vector(1 downto 0); + -- HSIO trigger + HSIObusy : out std_logic; + HSIOtrigger : in std_logic_vector(1 downto 0); + HSIObusyin : in std_logic; + hitbusout : out std_logic; + + -- eudet trigger + exttrigger : in std_logic; + extrst : in std_logic; + extbusy : out std_logic; + exttrgclk : out std_logic; + + calibmode : in std_logic_vector(1 downto 0); + startmeas : in std_logic; + eudaqdone : out std_logic; + eudaqtrgword : out std_logic_vector(14 downto 0); + tcounter1 : out std_logic_vector(31 downto 0); + tcounter2 : out std_logic_vector(31 downto 0); + + trigenabled: in std_logic; + paused: in std_logic; + fifothresh: in std_logic; + triggermask: in std_logic_vector(15 downto 0); + resetdelay: in std_logic; + incrementdelay: in std_logic_vector(4 downto 0); + discop: in std_logic_vector(15 downto 0); + telescopeop: in std_logic_vector(2 downto 0); + period : in std_logic_vector(31 downto 0); + serbusy: in std_logic; + tdcreadoutbusy: in std_logic; + phaseclksel : in std_logic; + phasebusyEn: in std_logic; + phasebusySel: in std_logic_vector(1 downto 0); + l1a: out std_logic; + triggerword: out std_logic_vector(7 downto 0); + busy: out std_logic; + coincd: out std_logic +); +end triggerlogic; + +-------------------------------------------------------------- + +architecture TRIGGERLOGIC of triggerlogic is + +component IDELAY + generic (IOBDELAY_TYPE : string := "DEFAULT"; --(DEFAULT, FIXED, VARIABLE) + IOBDELAY_VALUE : integer := 0 --(0 to 63) + ); + port ( + O : out STD_LOGIC; + I : in STD_LOGIC; + C : in STD_LOGIC; + CE : in STD_LOGIC; + INC : in STD_LOGIC; + RST : in STD_LOGIC + ); +end component; + +signal trgin: std_logic; +signal disc : std_logic_vector(4 downto 0); +signal discrim : std_logic; +signal delrst1 : std_logic; +signal delrst2 : std_logic; +signal delrstf : std_logic; +signal delayrst : std_logic; +signal exttrgclkeu : std_logic; +signal busys : std_logic; +signal l1as : std_logic; +signal cycliccounter : std_logic_vector(31 downto 0); +signal cyclic : std_logic; +signal hitbus : std_logic; +signal resettriggerword: std_logic; +signal oldtdcreadoutbusy: std_logic; +signal tdcready : std_logic; +signal starttdc : std_logic; +signal coinc : std_logic; +signal edge1 : std_logic; +signal edge2 : std_logic; +signal stdc : std_logic; +signal hsio : std_logic; +signal oldperiod : std_logic_vector(31 downto 0); +signal firstphase : std_logic; +signal oldclk : std_logic; + +begin + + HSIObusy <= busys or paused; + busy<=busys; + l1a<=l1as; + hitbusout<=hitbus; + + process(clk, rst) begin + if(rst='1')then + delrst1<='0'; + delrst2<='0'; + delrstf<='0'; + elsif(rising_edge(clk))then + if(resetdelay='1')then + delrst1<='1'; + delrst2<='1'; + delrstf<='1'; + else + delrstf<=delrst1; + delrst1<=delrst2; + delrst2<='0'; + end if; + end if; + end process; + + delayrst<= delrstf or rst; + + discdelays: for I in 0 to 3 generate + delay0 : IDELAY + generic map ( + IOBDELAY_TYPE => "VARIABLE", -- Set to DEFAULT for -- Zero Hold Time Mode + IOBDELAY_VALUE => 0 -- (0 to 63) + ) + port map ( + O => disc(I), + I => discin(I), + C => clk, + CE => incrementdelay(I), + INC => '1', + RST => delayrst + ); + end generate discdelays; + + discrim <= ((disc(0) xor discop(8)) or not discop(0)) and ((disc(1) xor discop(9)) or not discop(1)) and ((disc(2) xor discop(10)) or not discop(2)) and ((disc(3) xor discop(11)) or not discop(3)); + + with discop(15 downto 14) select + hsio <= HSIOtrigger(0) when "00", + HSIOtrigger(1) when "01", + HSIOtrigger(0) or HSIOtrigger(1) when "10", + HSIOtrigger(0) and HSIOtrigger(1) when "11", + '0' when others; + + with telescopeop select + hitbus<= hitbusin(0) when "001", + hitbusin(1) when "010", + hitbusin(0) or hitbusin(1) when "011", + hitbusin(0) and hitbusin(1) when "100", + '0' when others; + + trgin<= (triggermask(2) and exttrigger) + or (triggermask(3) and hsio) + or (triggermask(1) and cyclic) + or (triggermask(4) and hitbus) + or (triggermask(0) and discrim); + + -- Latching of trigger word + process(clk,rst) begin + if(rst='1')then + oldtdcreadoutbusy<='0'; + resettriggerword<='1'; + elsif(rising_edge(clk))then + oldtdcreadoutbusy<=tdcreadoutbusy; + if(oldtdcreadoutbusy='1' and tdcreadoutbusy='0')then + resettriggerword<='1'; + else + resettriggerword<='0'; + end if; + end if; + end process; + + process(resettriggerword, trgin) begin + if(resettriggerword='1')then + triggerword<=x"00"; + elsif(rising_edge(trgin))then + triggerword(7 downto 5)<="000"; + triggerword(4)<=triggermask(4) and hitbus; + triggerword(3)<=triggermask(3) and hsio; + triggerword(2)<=triggermask(2) and exttrigger; + triggerword(1)<=triggermask(1) and cyclic; + triggerword(0)<=triggermask(0) and discrim; + end if; + end process; + + process(clk,rst) begin + if(rst='1')then + cycliccounter<=(others=>'0'); + cyclic<='0'; + elsif(rising_edge(clk))then + oldperiod<=period; + if(period/=x"00000000" and cycliccounter=period)then + cycliccounter<=(others=>'0'); + cyclic<='1'; + elsif(period/=oldperiod)then + cycliccounter<=(others=>'0'); + cyclic<='0'; + else + cycliccounter<=unsigned(cycliccounter)+1; + cyclic<='0'; + end if; + end if; + end process; + + process(clk160, rst160) begin + if(rst160='1')then + oldclk<='0'; + elsif(rising_edge(clk160))then + if(clk=phasebusySel(0) and oldclk=phasebusySel(1))then + firstphase<='0'; + else + firstphase<=phasebusyEn; + end if; + oldclk<=clk; + end if; + end process; + + coin: entity work.coincidence + port map( + clk=>clk, + rst=>rst, + enabled=>trigenabled, + fifothresh=>fifothresh, + trgin=>trgin, + serbusy=>serbusy, + extbusy=>HSIObusyin, + firstphase=>firstphase, + tdcreadoutbusy=>tdcreadoutbusy, + tdcready=> tdcready, + starttdc=>starttdc, + l1a=> l1as, + trgdelay=>x"02", + busy=> busys, + coinc=> coinc, + coincd=> coincd + ); + + -- TDC config + with calibmode select + edge1<= clk when "01", -- tdc calib is special + coinc when others; + with calibmode select + edge2<= phaseclksel when "01", -- tdc calib + clk when others; + + stdc<= startmeas when calibmode="01" else starttdc; + thetdc: entity work.tdc + port map( + sysclk=>clk, + sysrst=>rst, + edge1=> edge1, + edge2=> edge2, + start=>stdc, + ready=>tdcready, + counter1=>tcounter1, + counter2=>tcounter2 + ); + + eudettrg: entity work.eudaqTrigger + port map( + clk => clk, + rst => rst, + busyin => busys, + tdcready => tdcready, + enabled =>calibmode(1), + l1a => l1as, + trg => exttrigger, + done => eudaqdone, + extbusy => extbusy, + trgword => eudaqtrgword, + trgclk => exttrgclkeu ); + + exttrgclk<=exttrgclkeu or paused or not trigenabled; + +end TRIGGERLOGIC; diff --git a/rce/fw-hsio/modules/pixelcore/hdl/triggerpipeline.vhd b/rce/fw-hsio/modules/pixelcore/hdl/triggerpipeline.vhd new file mode 100644 index 00000000..6f846563 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/triggerpipeline.vhd @@ -0,0 +1,125 @@ +------------------------------------------------------------------------------- +-- Description: +-- Core logic for BNL ASIC test FPGA. +------------------------------------------------------------------------------- +-- Copyright (c) 2008 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 07/21/2008: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity triggerpipeline is + port ( + rst : in std_logic; + clk : in std_logic; + L1Ain : in std_logic; + L1Aout : out std_logic; + configure : in std_logic; + delay : in std_logic_vector(7 downto 0); + busy : out std_logic; + deadtime : in std_logic_vector(15 downto 0) + ); +end triggerpipeline; + +architecture TRIGGERPIPELINE of triggerpipeline is + + component triggerfifo + port ( + clk: IN std_logic; + din: IN std_logic_VECTOR(0 downto 0); + rd_en: IN std_logic; + rst: IN std_logic; + wr_en: IN std_logic; + data_count: OUT std_logic_VECTOR(7 downto 0); + dout: OUT std_logic_VECTOR(0 downto 0); + empty: OUT std_logic; + full: OUT std_logic); + end component; + + signal oldconfigure: std_logic; + signal configuring : std_logic; + signal configured : std_logic; + signal din : std_logic_vector(0 downto 0); + signal dout : std_logic_vector(0 downto 0); + signal data_count : std_logic_vector(7 downto 0); + --signal busycounter : std_logic_vector(2 downto 0); + signal busycounter : std_logic_vector(15 downto 0); + signal rd_en : std_logic; + signal wr_en : std_logic; + signal fiforst : std_logic; + +begin + + L1Aout<=dout(0); + process (rst,clk) + begin + if(rst='1')then + oldconfigure<='0'; + configuring<='0'; + configured<='0'; + busy<='1'; + din(0)<='0'; + rd_en<='0'; + wr_en<='0'; + busycounter<=x"0000"; + elsif(rising_edge(clk))then + if(configure='1'and oldconfigure='0')then + configuring<='1'; + configured<='0'; + fiforst<='1'; + rd_en<='0'; + wr_en<='0'; + busy<='1'; + elsif(configuring='1')then + fiforst<='0'; + if(delay=data_count)then + configuring<='0'; + configured<='1'; + wr_en<='0'; + busy<='0'; + else + din(0)<='0'; + wr_en<='1'; + end if; + elsif(configured='1')then + wr_en<='1'; + rd_en<='1'; + din(0)<=L1Ain; + if(L1Ain='1')then + busy<='1'; + -- busycounter<="111"; + -- elsif (busycounter/="000")then + if(deadtime(15 downto 3)="0000000000000")then + busycounter<="0000000000000111"; --at least 7 ticks deadtime + else + busycounter<=deadtime; + end if; + elsif (busycounter/=x"0000")then + busycounter<=unsigned(busycounter)-1; + else + busy<='0'; + end if; + end if; + end if; + end process; + + + thepiepeline: triggerfifo + port map( + clk=>clk, + din=>din, + rd_en=>rd_en, + rst=>fiforst, + wr_en=>wr_en, + data_count => data_count, + dout=>dout, + empty=>open, + full=>open ); + +end TRIGGERPIPELINE; diff --git a/rce/fw-hsio/modules/pixelcore/hdl/wordswapper.vhd b/rce/fw-hsio/modules/pixelcore/hdl/wordswapper.vhd new file mode 100644 index 00000000..32e4bb11 --- /dev/null +++ b/rce/fw-hsio/modules/pixelcore/hdl/wordswapper.vhd @@ -0,0 +1,134 @@ +------------------------------------------------------------------------------- +-- Description: +-- Swaps 16-bit words in time for pgp. The number of words has to be even. +------------------------------------------------------------------------------- +-- Copyright (c) 2010 by Martin Kocian. +------------------------------------------------------------------------------- +-- Modification history: +-- 07/21/2008: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity wordswapper is + port ( + rst : in std_logic; + clk : in std_logic; + wordin : in std_logic_vector(15 downto 0); + eofin : in std_logic; + eeofin : in std_logic; + sofin : in std_logic; + validin : in std_logic; + wordout : out std_logic_vector(15 downto 0); + eofout : out std_logic; + eeofout : out std_logic; + sofout : out std_logic; + validout : out std_logic + ); +end wordswapper; + +architecture WORDSWAPPER of wordswapper is + + signal savedword : std_logic_vector(15 downto 0); + type state_type is (idle, firsteven, odd, even, lastodd); + signal state: state_type; + signal eeof: std_logic; + +begin + + process (rst,clk) + begin + if(rst='1')then + savedword<=x"0000"; + state<=idle; + eofout<='0'; + sofout<='0'; + eeofout<='0'; + validout<='0'; + wordout<=x"0000"; + elsif(rising_edge(clk))then + case state is + when idle => + if(validin='1' and sofin='1')then + eofout<='0'; + eeofout<='0'; + sofout<='0'; + validout<='0'; + wordout<=x"0000"; + savedword<=wordin; + state<=firsteven; + else + validout<='0'; + eofout<='0'; + eeofout<='0'; + sofout<='0'; + wordout<=x"0000"; + state<=idle; + end if; + when firsteven => + if(validin='1')then + sofout<='1'; + wordout<=wordin; + eofout<='0'; + eeofout<='0'; + validout<='1'; + if(eofin='1')then + eeof<=eeofin; + state<=lastodd; + else + state<=odd; + end if; + else + validout<='0'; + state<=firsteven; + end if; + when odd => + if(validin='1')then + sofout<='0'; + eofout<='0'; + eeofout<='0'; + validout<='1'; + wordout<=savedword; + savedword<=wordin; + state<=even; + else + validout<='0'; + sofout<='0'; + eofout<='0'; + eeofout<='0'; + state<=odd; + end if; + when even => + if(validin='1')then + sofout<='0'; + wordout<=wordin; + eofout<='0'; + eeofout<='0'; + validout<='1'; + if(eofin='1')then + eeof<=eeofin; + state<=lastodd; + else + state<=odd; + end if; + else + validout<='0'; + state<=even; + end if; + when lastodd => + sofout<='0'; + eofout<='1'; + eeofout<=eeof; + validout<='1'; + wordout<=savedword; + state<=idle; + end case; + end if; + end process; + + +end WORDSWAPPER; diff --git a/rce/fw-hsio/projects/HsioCosmic/Makefile b/rce/fw-hsio/projects/HsioCosmic/Makefile new file mode 100644 index 00000000..5c82cd85 --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/Makefile @@ -0,0 +1,12 @@ +# Project Name +export PROJECT = $(notdir $(PWD)) + +# List of build core directories. Relative to current directory. +CORE_DIRS = coregen ../../modules/pgp/coregen ../../modules/pgp2/coregen ../../modules/pixelcore/coregen + +# Optional ELF file to include. Relative to ./boot directory +#BOOT_ELF = udiTest.elf + +# Use top level makefile +include ../../system.mk + diff --git a/rce/fw-hsio/projects/HsioCosmic/Readme.txt b/rce/fw-hsio/projects/HsioCosmic/Readme.txt new file mode 100644 index 00000000..c0ba752b --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/Readme.txt @@ -0,0 +1,59 @@ +This is a DPM project specific Readme.txt file. + +The files in this directory are used to build +the DPM project in this directory. The project +name matches the name of the directory in which +this file is found. + +The Makefile in this directory may be used to build +this project with a simple 'gmake' command. + +The Version.vhd file in this directory is used to +generate the software readable version constant +in the build and is also used to set the name of +the files added to the images directory. + +The following sub directories exist in this project: + +boot: + This directory contains boot loader files which are + used to program the boot loader code in the DPM. The + files in this directory include: + +config: + This directory contains Xilinx configuration files for + various steps in the synthesis process. The files in this + directory include: + + bitgen_options.txt: Options for bitgen + map_options.txt: Options for map + ngdbuild_options.txt: Options for ngdbuild + par_options.txt: Options for par + trce_options.txt: Options for trce + xst_options.txt: Options for xst + sources.txt Source file list used by xst + +coregen: + This directory holds the coregen project and any modules + generated by coregen that are specific to this project. + +debug: + This directory holds any debug files for the project. + +hdl: + This directory contains the source files (.vhd and .v) for + the project and the constraints file (.ucf) for the project. + The top level module name, its source file name and the ucf + file name should match the name of the project. + +images: + + This directory contains the result of the project compile. + The resulting .mcs and .bit files for the project are + added to this directory. The name of the copied file will + be: project_version.mcs/.bit. + +sim: + + Directory for simulation Makefile and test bench. + diff --git a/rce/fw-hsio/projects/HsioCosmic/Version.vhd b/rce/fw-hsio/projects/HsioCosmic/Version.vhd new file mode 100644 index 00000000..f31cbfbb --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/Version.vhd @@ -0,0 +1,34 @@ +------------------------------------------------------------------------------- +-- Title : Version Constant File +-- Project : HSIO +------------------------------------------------------------------------------- +-- File : Version.vhd +-- Author : Martin Kocian, kocian@slac.stanford.edu +-- Created : 01/07/2013 +------------------------------------------------------------------------------- +-- Description: +-- Version Constant Module +------------------------------------------------------------------------------- +-- Copyright (c) 2012 by SLAC. All rights reserved. +------------------------------------------------------------------------------- +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; + +package Version is + +constant FpgaVersion : std_logic_vector(31 downto 0) := x"00000009"; -- MAKE_VERSION + +end Version; + +------------------------------------------------------------------------------- +-- Revision History: +-- 01/07/2013 (0x00000001): Initial XST version +-- 03/22/2013 (0x00000002): HSIO trigger/busy added to opto ucf file +-- 04/02/2013 (0x00000003): Memory buffer for triggering. +-- 06/20/2014 (0x00000004): Added hitbus readout for DBM +-- 07/24/2014 (0x00000005): Separated trigger from core. +-- 11/07/2014 (0x00000006): Set multiplicities for multiplexer +-- 12/15/2014 (0x00000007): Added Temperature ADC readout +-- 01/09/2015 (0x00000008): New readout for FEI4 +-- 01/09/2015 (0x00000009): New ADC data format, max 31 readout links. +------------------------------------------------------------------------------- diff --git a/rce/fw-hsio/projects/HsioCosmic/config/bitgen_options.txt b/rce/fw-hsio/projects/HsioCosmic/config/bitgen_options.txt new file mode 100755 index 00000000..abf29c69 --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/config/bitgen_options.txt @@ -0,0 +1,5 @@ +##----------------------------------------------------------------------------- +## Title : Xilinx bitgen options file +##----------------------------------------------------------------------------- +-intstyle silent +-w diff --git a/rce/fw-hsio/projects/HsioCosmic/config/map_options.txt b/rce/fw-hsio/projects/HsioCosmic/config/map_options.txt new file mode 100755 index 00000000..6cef41ff --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/config/map_options.txt @@ -0,0 +1,21 @@ +##----------------------------------------------------------------------------- +## Title : Xilinx map options file +##----------------------------------------------------------------------------- + +#-intstyle silent +-ol high +-xe n +-t 1 +-register_duplication on +#-global_opt off +#-equivalent_register_removal on +#-u +#-cm Area +-detail +#-ir off +#-pr off +#-lc off +#-mt 2 + + + diff --git a/rce/fw-hsio/projects/HsioCosmic/config/ngdbuild_options.txt b/rce/fw-hsio/projects/HsioCosmic/config/ngdbuild_options.txt new file mode 100755 index 00000000..95ca0eea --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/config/ngdbuild_options.txt @@ -0,0 +1,5 @@ +##----------------------------------------------------------------------------- +## Title : Xilinx ngdbuild options file +##----------------------------------------------------------------------------- +-nt timestamp + diff --git a/rce/fw-hsio/projects/HsioCosmic/config/par_options.txt b/rce/fw-hsio/projects/HsioCosmic/config/par_options.txt new file mode 100755 index 00000000..2cdd3ad0 --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/config/par_options.txt @@ -0,0 +1,9 @@ +##----------------------------------------------------------------------------- +## Title : Xilinx place and route options file +##----------------------------------------------------------------------------- +#-intstyle ise +-ol high +-xe n +#-mt 4 + + diff --git a/rce/fw-hsio/projects/HsioCosmic/config/promgen_options.txt b/rce/fw-hsio/projects/HsioCosmic/config/promgen_options.txt new file mode 100755 index 00000000..2c2257be --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/config/promgen_options.txt @@ -0,0 +1,7 @@ +##----------------------------------------------------------------------------- +## Title : Xilinx promgen options file +##----------------------------------------------------------------------------- +-x xcf32p +-w +-p mcs +-c FF diff --git a/rce/fw-hsio/projects/HsioCosmic/config/sources.txt b/rce/fw-hsio/projects/HsioCosmic/config/sources.txt new file mode 120000 index 00000000..c5dbc41e --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/config/sources.txt @@ -0,0 +1 @@ +sources_pgp1.txt \ No newline at end of file diff --git a/rce/fw-hsio/projects/HsioCosmic/config/sources_pgp1.txt b/rce/fw-hsio/projects/HsioCosmic/config/sources_pgp1.txt new file mode 100644 index 00000000..23b04f9f --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/config/sources_pgp1.txt @@ -0,0 +1,80 @@ +# Version Constant +vhdl work "_PROJ_DIR_/Version.vhd" + +# PGP + +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpVersion.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpAckRx.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpCellRx.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpCellTx.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpMgtWrap.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpPhy.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpRxTrack.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpTxSched.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpTop.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpClkGen.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpCmdSlave.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpRegSlave.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpPicRemBuff.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpDataBuffer.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpFrontEnd.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpDsBuff.vhd" + +# Pixel core +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_wrapper.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_bram.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_disp.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_lut.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_lut_base.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_pkg.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_rtl.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_top.vhd" + +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/StdRtlPkg.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/I2cPkg.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/stdlib.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/i2c_master_bit_ctrl.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/i2c_master_byte_ctrl.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/I2cMaster.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/I2cRegMaster.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/tempadc.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/adcreadout.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/arraytype.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/DisplayCharacters.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/DisplayControl.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/ser.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/ser32.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/OutputEncoder.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/tdc.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/tdcreadout.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/clock160.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/clock200.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/phaseshift.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/deser.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/dataflag.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/dataflagnew.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/dataflagff.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/eofcounter.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/multiplexdataopt.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/coincidence.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/triggerpipeline.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/hitbuspipeline.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/wordswapper.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/eudaqTrigger.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/syncdatac.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/framealign.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/framealignhitbus.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/deser10b.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/deser4b.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/encodepgp.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/encodepgp24bit.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/lookaheadfifo.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/decodefei4record.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/datafifo.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/triggerlogic.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/HsioPixelCore.vhd" + + +# Local Files +vhdl work "_PROJ_DIR_/hdl/HsioCosmic.vhd" + diff --git a/rce/fw-hsio/projects/HsioCosmic/config/sources_pgp2.txt b/rce/fw-hsio/projects/HsioCosmic/config/sources_pgp2.txt new file mode 100644 index 00000000..c9a08932 --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/config/sources_pgp2.txt @@ -0,0 +1,86 @@ +# Version Constant +vhdl work "_PROJ_DIR_/Version.vhd" + +# PGP2 + +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/core/Pgp2CorePackage.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/core/Pgp2Rx.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/core/Pgp2RxCell.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/core/Pgp2RxPhy.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/core/Pgp2Tx.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/core/Pgp2TxCell.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/core/Pgp2TxPhy.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/core/Pgp2TxSched.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/mgt/Pgp2MgtPackage.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/mgt/Pgp2Mgt16.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/mgt/PgpClkGen.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/mgt/Pgp2MgtRxRst.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/mgt/Pgp2MgtTxRst.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/applications/Pgp2AppPackage.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/applications/Pgp2CmdSlave.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/applications/Pgp2DsBuff.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/applications/Pgp2RegSlave.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/applications/Pgp2UsBuff.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/applications/PgpDsBuff.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/applications/PgpFrontEnd.vhd" + + +# Pixel core +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_wrapper.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_bram.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_disp.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_lut.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_lut_base.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_pkg.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_rtl.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_top.vhd" + +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/StdRtlPkg.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/I2cPkg.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/stdlib.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/i2c_master_bit_ctrl.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/i2c_master_byte_ctrl.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/I2cMaster.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/I2cRegMaster.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/tempadc.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/adcreadout.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/arraytype.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/DisplayCharacters.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/DisplayControl.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/ser.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/ser32.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/OutputEncoder.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/tdc.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/tdcreadout.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/clock160.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/clock200.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/phaseshift.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/deser.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/dataflag.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/dataflagnew.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/dataflagff.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/eofcounter.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/multiplexdataopt.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/coincidence.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/triggerpipeline.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/wordswapper.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/eudaqTrigger.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/syncdatac.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/framealign.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/deser10b.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/encodepgp.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/encodepgp24bit.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/lookaheadfifo.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/decodefei4record.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/datafifo.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/hitbuspipeline.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/framealignhitbus.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/deser4b.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/triggerlogic.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/HsioPixelCore.vhd" + + + +# Local Files +vhdl work "_PROJ_DIR_/hdl/HsioCosmic.vhd" + diff --git a/rce/fw-hsio/projects/HsioCosmic/config/trce_options.txt b/rce/fw-hsio/projects/HsioCosmic/config/trce_options.txt new file mode 100755 index 00000000..2656ff46 --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/config/trce_options.txt @@ -0,0 +1,7 @@ +##----------------------------------------------------------------------------- +## Title : Xilinx trace options file +##----------------------------------------------------------------------------- +-intstyle silent +-l 30 +-v 30 +-tsi DpmTest.tsi diff --git a/rce/fw-hsio/projects/HsioCosmic/config/xst_options.txt b/rce/fw-hsio/projects/HsioCosmic/config/xst_options.txt new file mode 100644 index 00000000..50864e04 --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/config/xst_options.txt @@ -0,0 +1,50 @@ +run +-ofn HsioCosmic +-top HsioCosmic +-p XC4VFX60-11-FF1152 +-ifn "sources.txt" +-opt_mode Speed +-opt_level 2 +-power NO +-iuc NO +-keep_hierarchy No +-netlist_hierarchy As_Optimized +-rtlview Yes +-glob_opt AllClockNets +-write_timing_constraints No +-cross_clock_analysis NO +-hierarchy_separator / +-bus_delimiter <> +-case Maintain +-slice_utilization_ratio 100 +-bram_utilization_ratio 100 +-dsp_utilization_ratio 100 +-verilog2001 YES +-fsm_extract YES -fsm_encoding Auto +-safe_implementation No +-fsm_style LUT +-ram_extract Yes +-ram_style Auto +-rom_extract Yes +-mux_style Auto +-decoder_extract YES +-priority_extract Yes +-shreg_extract YES +-shift_extract YES +-xor_collapse YES +-resource_sharing Yes +-use_dsp48 Auto +-async_to_sync No +-iobuf Yes +-max_fanout 100000 +-bufg 32 +-register_duplication YES +-equivalent_register_removal Yes +-register_balancing No +-iob Auto +-slice_packing YES +-use_clock_enable Auto +-use_sync_set Auto +-use_sync_reset Auto +-optimize_primitives No + diff --git a/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf new file mode 120000 index 00000000..84bd04b7 --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf @@ -0,0 +1 @@ +HsioCosmic.ucf.4core \ No newline at end of file diff --git a/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf.2core b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf.2core new file mode 100644 index 00000000..4393b339 --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf.2core @@ -0,0 +1,408 @@ + +#----------------------------------------------------------------------------- +# Title : LCLS BNL ASIC Test FPGA, Constraints File +# Project : LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# File : HsioCosmic.ucf +# Author : Ryan Herbst, rherbst@slac.stanford.edu +# Created : 07/21/2008 +#----------------------------------------------------------------------------- +# Description: +# This file contains all of the user constraints required to implement the +# LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# Copyright (c) 2008 by Ryan Herbst. All rights reserved. +#----------------------------------------------------------------------------- +# Modification history +# 07/21/2008: created. +#----------------------------------------------------------------------------- + + +#----------------------------------------------------------------------------- +#-------------------------- Timing Constraints ------------------------------- +#----------------------------------------------------------------------------- +# This section contains the timing constraints for the FPGA +#----------------------------------------------------------------------------- + +# Define system clocks +NET pgpClk TNM_NET = FFS pgpClk; +NET sysClk125 TNM_NET = FFS sysClk125; +#NET clk320 TNM_NET = FFS clk320; +#NET sysClk250 TNM_NET = FFS sysClk250; +#NET mainClk TNM_NET = FFS mainClk; +INST "U_triggerlogic/thetdc/stopcontrol" RLOC_ORIGIN="X44Y117"; + +# Define system clocks +TIMESPEC TS_pgpClk = PERIOD pgpClk 6.4 ns HIGH 50%; +TIMESPEC TS_sysClk125 = PERIOD sysClk125 25.6 ns HIGH 50%; +#TIMESPEC TS_clk320 = PERIOD clk320 3.2 ns HIGH 50%; +#TIMESPEC TS_sysClk250 = PERIOD sysClk250 12.8 ns HIGH 50%; +#TIMESPEC TS_mainClk = PERIOD mainClk 6.4 ns HIGH 50%; + +# Define time groups for inter-clock constraints +TIMEGRP TG_pgpClk_r = RISING pgpClk; +TIMEGRP TG_sysClk125_r = RISING sysClk125; +#TIMEGRP TG_sysClk250_r = RISING sysClk250; +#TIMEGRP TG_mainClk_r = RISING mainClk; + +# Inter Domain Constraints +# TIMESPEC TS_pgpClk_r_sysClk125_r = FROM TG_pgpClk_r TO TG_sysClk125_r 6.4ns; +TIMESPEC TS_sysClk125_r_pgpClk_r = FROM TG_sysClk125_r TO TG_pgpClk_r 6.4ns; +#TIMESPEC TS_sysClk125_r_sysClk250_r = FROM TG_sysClk125_r TO TG_sysClk250_r 8ns; +# NET U_HsioFei4Core/go TIG; +NET U_HsioCosmicCore*/channelmask(*) TIG; +NET U_HsioCosmicCore*/channeloutmask(*) TIG; + +timespec ts_02 = from ffs(*bz(0):*cz(0):*dz(0):*dz(1)) to ffs 640 MHz; +#timespec ts_03 = from ffs(*fei4fifo*) to ffs(*fei4dataflag*) 6.4ns; +#timespec ts_04 = from rams(*fei4fifo*) to ffs(*fei4dataflag*) 6.4ns; + +# Nets to ignore for timing +NET "iResetInL" TIG; + +NET serialinb(?) maxskew = 250 ps ; +#NET U_HsioCosmicCore/deldata maxskew = 250 ps ; + +INST "U_HsioCosmicCore*/*receivedata/ff_*" IOB=FALSE; + + +# Nets to ignore for timing +NET "iResetInL" TIG; + + +#----------------------------------------------------------------------------- +#-------------------------- Pin Location Constraints ------------------------- +#----------------------------------------------------------------------------- +# This section contains the pin location constraints for the design +#----------------------------------------------------------------------------- +# Old P5 = New P5 +# Old P4 = New P4 +# Old P9 = New P3 +# Old P3 = New P2 + + +NET "iPgpRefClkP" LOC = "J1"; +NET "iPgpRefClkM" LOC = "K1"; +#NET "iMainClkP" LOC = "H17"; +#NET "iMainClkN" LOC = "J17"; +# fiber 1 +NET "iMgtRxN" LOC = "N1"; +NET "iMgtRxP" LOC = "M1"; +NET "oMgtTxN" LOC = "T1"; +NET "oMgtTxP" LOC = "R1"; +# fiber 2 +#NET "iMgtRxN2" LOC = "AA1"; +#NET "iMgtRxP2" LOC = "Y1"; +#NET "oMgtTxN2" LOC = "V1"; +#NET "oMgtTxP2" LOC = "U1"; + +NET "iMgtRxN2" LOC = "AD1"; +NET "iMgtRxP2" LOC = "AC1"; +NET "oMgtTxN2" LOC = "AG1"; +NET "oMgtTxP2" LOC = "AF1"; + +NET "oReload" LOC = "G16"; +NET "iResetInL" LOC = "AJ19"; +NET "oDispClk" LOC = "AG22"; +NET "oDispDat" LOC = "AJ22"; +NET "oDispLoadL(1)" LOC = "AK17"; +NET "oDispLoadL(0)" LOC = "Ak18"; +NET "oDispRstL" LOC = "AH22"; +#NET "rclk" LOC = "AM21"; +# fiber 1 +NET "transDis1" LOC = "AH4"; +NET "transDis1" IOSTANDARD="LVCMOS33"; +# fiber 2 +#NET "transDis2" LOC = "AK4"; +#NET "transDis2" IOSTANDARD="LVCMOS33"; +NET "transDis2" LOC = "Y4"; +NET "transDis2" IOSTANDARD="LVCMOS33"; + +NET "iExtreload" LOC = "G15"; +NET "iExtreload" IOSTANDARD="LVCMOS25"; +NET "iExtreload" PULLUP; + +NET "refclk_p" LOC = "J25"; +NET "refclk_p" IOSTANDARD="LVDS_25"; +NET "refclk_n" LOC = "H25"; +NET "refclk_n" IOSTANDARD="LVDS_25"; + +NET "xclk_p" LOC = "E24"; +NET "xclk_p" IOSTANDARD="LVDS_25"; +NET "xclk_n" LOC = "F24"; +NET "xclk_n" IOSTANDARD="LVDS_25"; + +NET "clkout40" LOC = "AJ29"; +NET "clkout40" IOSTANDARD="LVCMOS33"; +NET "clkout40" SLEW="FAST"; + +NET "RD2" LOC = "AJ24"; +NET "RD2" IOSTANDARD="LVCMOS33"; +NET "RD2" SLEW="FAST"; + +NET "AuxClk" LOC = "AK29"; +NET "AuxClk" IOSTANDARD="LVCMOS33"; +NET "AuxClk" SLEW="FAST"; + +NET "RA" LOC = "AM30"; +NET "RA" IOSTANDARD="LVCMOS33"; +NET "RA" SLEW="FAST"; + +NET "RD1" LOC = "AH24"; +NET "RD1" IOSTANDARD="LVCMOS33"; +NET "RD1" SLEW="FAST"; + +NET "IOMXIN(3)" LOC = "AG3"; +NET "IOMXIN(3)" IOSTANDARD="LVCMOS33"; + +NET "IOMXIN(2)" LOC = "AF3"; +NET "IOMXIN(2)" IOSTANDARD="LVCMOS33"; + +NET "IOMXIN(1)" LOC = "W9"; +NET "IOMXIN(1)" IOSTANDARD="LVCMOS33"; + +NET "IOMXIN(0)" LOC = "Y9"; +NET "IOMXIN(0)" IOSTANDARD="LVCMOS33"; + +NET "IOMXSEL(2)" LOC = "AB6"; +NET "IOMXSEL(2)" IOSTANDARD="LVCMOS33"; +NET "IOMXSEL(2)" SLEW="FAST"; + +NET "IOMXSEL(1)" LOC = "AA6"; +NET "IOMXSEL(1)" IOSTANDARD="LVCMOS33"; +NET "IOMXSEL(1)" SLEW="FAST"; + +NET "IOMXSEL(0)" LOC = "Y6"; +NET "IOMXSEL(0)" IOSTANDARD="LVCMOS33"; +NET "IOMXSEL(0)" SLEW="FAST"; + +NET "HITOR" LOC = "AL29"; +NET "HITOR" IOSTANDARD="LVCMOS33"; + +NET "IOMXOUT(0)" LOC = "AC4"; +NET "IOMXOUT(0)" IOSTANDARD="LVCMOS33"; + +NET "IOMXOUT(1)" LOC = "AA8"; +NET "IOMXOUT(1)" IOSTANDARD="LVCMOS33"; + +NET "IOMXOUT(2)" LOC = "AA9"; +NET "IOMXOUT(2)" IOSTANDARD="LVCMOS33"; + +NET "SELALTBUS" LOC = "AK6"; +NET "SELALTBUS" IOSTANDARD="LVCMOS33"; +NET "SELALTBUS" SLEW="FAST"; + +NET "REGABDACLD" LOC = "AD5"; +NET "REGABDACLD" IOSTANDARD="LVCMOS33"; +NET "REGABDACLD" SLEW="FAST"; + +NET "REGABSTBLD" LOC = "AD4"; +NET "REGABSTBLD" IOSTANDARD="LVCMOS33"; +NET "REGABSTBLD" SLEW="FAST"; + +NET "SELCMD" LOC = "AE6"; +NET "SELCMD" IOSTANDARD="LVCMOS33"; +NET "SELCMD" SLEW="FAST"; + +NET "CMDEXTTRIGGER" LOC = "AF6"; +NET "CMDEXTTRIGGER" IOSTANDARD="LVCMOS33"; +NET "CMDEXTTRIGGER" SLEW="FAST"; + +NET "CMDALTPLS" LOC = "AC3"; +NET "CMDALTPLS" IOSTANDARD="LVCMOS33"; +NET "CMDALTPLS" SLEW="FAST"; + +NET "iHSIOtrigger(0)" LOC="J14"; +NET "iHSIOtrigger(0)" IOSTANDARD="LVTTL"; +NET "iHSIOtrigger(0)" SLEW=FAST; + +NET "iHSIOtrigger(1)" LOC="L14"; +NET "iHSIOtrigger(1)" IOSTANDARD="LVTTL"; +NET "iHSIOtrigger(1)" SLEW=FAST; + +#NET "oHSIObusy" LOC="H19"; +#NET "oHSIObusy" IOSTANDARD="LVTTL"; +#NET "oHSIObusy" SLEW=FAST; + +NET "oHSIOtrigger" LOC="L15"; +NET "oHSIOtrigger" IOSTANDARD="LVTTL"; +NET "oHSIOtrigger" SLEW=FAST; + +NET "iHSIObusy" LOC="H19"; +NET "iHSIObusy" IOSTANDARD="LVTTL"; +NET "iHSIObusy" SLEW=FAST; +NET "iHSIObusy" PULLDOWN; + +# Temperature ADC MAX145 +#NET "ADC_Data_in_p" LOC = "L4"; +#NET "ADC_Data_in_n" LOC = "L3"; +#NET "ADC_Clk_p" LOC = "T9"; +#NET "ADC_Clk_n" LOC = "R9"; +#NET "ADC_nCS_p" LOC = "U3"; +#NET "ADC_nCS_n" LOC = "T3"; + +# DI1 +NET "oExttrgclkP" LOC = "AH15"; +NET "oExttrgclkN" LOC = "AJ15"; +# DI3 +NET "oExtbusyP" LOC = "AD14"; +NET "oExtbusyN" LOC = "AC13"; +#DTO1 +NET "iExttriggerP" LOC = "J31"; +NET "iExttriggerN" LOC = "J30"; +# DTO3 +NET "iExtrstP" LOC = "G30"; +NET "iExtrstN" LOC = "F30"; + +NET "serialout_p(0)" LOC = "AG12"; +NET "serialout_n(0)" LOC = "AH12"; +NET "serialout_p(1)" LOC = "AF10"; +NET "serialout_n(1)" LOC = "AG10"; +NET "serialout_p(3)" LOC = "AH14"; +NET "serialout_n(3)" LOC = "AJ14"; +NET "serialout_p(2)" LOC = "AH10"; +NET "serialout_n(2)" LOC = "AJ10"; +NET "serialout_p(4)" LOC = "AJ12"; +NET "serialout_n(4)" LOC = "AK12"; +NET "serialout_p(5)" LOC = "AH8"; +NET "serialout_n(5)" LOC = "AH7"; +NET "serialout_p(6)" LOC = "AF11"; +NET "serialout_n(6)" LOC = "AG11"; +NET "serialout_p(7)" LOC = "AJ9"; +NET "serialout_n(7)" LOC = "AH9"; +#NET "oExttrgclkP" LOC = "AJ9"; +#NET "oExttrgclkN" LOC = "AH9"; + + +NET "serialout_p(11)" LOC = "AF15"; +NET "serialout_n(11)" LOC = "AG15"; +NET "serialout_p(12)" LOC = "AB13"; +NET "serialout_n(12)" LOC = "AA13"; +NET "serialout_p(13)" LOC = "AD10"; +NET "serialout_n(13)" LOC = "AD9"; +NET "serialout_p(14)" LOC = "AB11"; +NET "serialout_n(14)" LOC = "AA11"; +#NET "serialout_p(15)" LOC = "AD14"; +#NET "serialout_n(15)" LOC = "AC13"; +#NET "oExtbusyP" LOC = "AD14"; +#NET "oExtbusyN" LOC = "AC13"; + +NET "serialout(8)" LOC = "AL21"; + +NET "serialin_p(0)" LOC = "AK7"; +NET "serialin_n(0)" LOC = "AJ7"; +NET "serialin_p(1)" LOC = "AF9"; +NET "serialin_n(1)" LOC = "AE9"; +NET "serialin_p(3)" LOC = "AL10"; +NET "serialin_n(3)" LOC = "AM10"; +NET "serialin_p(2)" LOC = "AL9"; +NET "serialin_n(2)" LOC = "AK9"; +NET "serialin_p(4)" LOC = "AL11"; +NET "serialin_n(4)" LOC = "AM11"; +NET "serialin_p(5)" LOC = "AK13"; +NET "serialin_n(5)" LOC = "AL13"; +NET "serialin_p(6)" LOC = "AK14"; +NET "serialin_n(6)" LOC = "AL14"; +NET "serialin_p(7)" LOC = "AM8"; +NET "serialin_n(7)" LOC = "AM7"; +#NET "iExttriggerP" LOC = "AM8"; +#NET "iExttriggerN" LOC = "AM7"; +NET "serialin_p(8)" LOC = "AM13"; +NET "serialin_n(8)" LOC = "AM12"; + +NET "serialin_p(11)" LOC = "K28"; +NET "serialin_n(11)" LOC = "J27"; +NET "serialin_p(12)" LOC = "H30"; +NET "serialin_n(12)" LOC = "H29"; +NET "serialin_p(13)" LOC = "C23"; +NET "serialin_n(13)" LOC = "C22"; +NET "serialin_p(14)" LOC = "E23"; +NET "serialin_n(14)" LOC = "F23"; +#NET "serialin_p(15)" LOC = "G30"; +#NET "serialin_n(15)" LOC = "F30"; +#NET "iExtrstP" LOC = "G30"; +#NET "iExtrstN" LOC = "F30"; + + +NET "discinP(0)" LOC = "AD7"; +NET "discinP(1)" LOC = "AD6"; +NET "discinP(2)" LOC = "AM6"; +NET "discinP(3)" LOC = "AL6"; + +NET "discinP(0)" IOSTANDARD = "LVCMOS33"; +NET "discinP(1)" IOSTANDARD = "LVCMOS33"; +NET "discinP(2)" IOSTANDARD = "LVCMOS33"; +NET "discinP(3)" IOSTANDARD = "LVCMOS33"; + +#-------------------------- IO Standard Constraints -------------------------- +#----------------------------------------------------------------------------- +# This section defines the IO types, IO delays and other IO parameters +#----------------------------------------------------------------------------- + +NET "iResetInL" IOSTANDARD = "LVCMOS33"; +NET "oDispClk" IOSTANDARD = "LVCMOS33"; +NET "oDispDat" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(1)" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(0)" IOSTANDARD = "LVCMOS33"; +NET "oDispRstL" IOSTANDARD = "LVCMOS33"; + +NET "serialin_p(0)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(0)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(1)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(1)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(2)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(2)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(3)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(3)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(4)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(4)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(5)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(5)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(6)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(6)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(7)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(7)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(8)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(8)" IOSTANDARD = "LVDS_25"; + +NET "serialin_p(11)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(11)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(12)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(12)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(13)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(13)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(14)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(14)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(15)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(15)" IOSTANDARD = "LVDS_25"; + +NET "serialout_p(0)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(0)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(1)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(1)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(2)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(2)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(3)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(3)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(4)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(4)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(5)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(5)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(6)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(6)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(7)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(7)" IOSTANDARD = "LVDS_25"; +NET "serialout(8)" IOSTANDARD = "LVCMOS33"; + +NET "serialout(8)" SLEW = "FAST"; + +NET "serialout_p(11)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(11)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(12)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(12)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(13)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(13)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(14)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(14)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(15)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(15)" IOSTANDARD = "LVDS_25"; diff --git a/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf.4core b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf.4core new file mode 100644 index 00000000..d1cc689d --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf.4core @@ -0,0 +1,438 @@ + +#----------------------------------------------------------------------------- +# Title : LCLS BNL ASIC Test FPGA, Constraints File +# Project : LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# File : HsioCosmic.ucf +# Author : Ryan Herbst, rherbst@slac.stanford.edu +# Created : 07/21/2008 +#----------------------------------------------------------------------------- +# Description: +# This file contains all of the user constraints required to implement the +# LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# Copyright (c) 2008 by Ryan Herbst. All rights reserved. +#----------------------------------------------------------------------------- +# Modification history +# 07/21/2008: created. +#----------------------------------------------------------------------------- + + +#----------------------------------------------------------------------------- +#-------------------------- Timing Constraints ------------------------------- +#----------------------------------------------------------------------------- +# This section contains the timing constraints for the FPGA +#----------------------------------------------------------------------------- + +# Define system clocks +NET pgpClk TNM_NET = FFS pgpClk; +NET sysClk125 TNM_NET = FFS sysClk125; +#NET clk320 TNM_NET = FFS clk320; +#NET sysClk250 TNM_NET = FFS sysClk250; +#NET mainClk TNM_NET = FFS mainClk; +INST "U_triggerlogic/thetdc/stopcontrol" RLOC_ORIGIN="X44Y117"; + +# Define system clocks +TIMESPEC TS_pgpClk = PERIOD pgpClk 6.4 ns HIGH 50%; +TIMESPEC TS_sysClk125 = PERIOD sysClk125 25.6 ns HIGH 50%; +#TIMESPEC TS_clk320 = PERIOD clk320 3.2 ns HIGH 50%; +#TIMESPEC TS_sysClk250 = PERIOD sysClk250 12.8 ns HIGH 50%; +#TIMESPEC TS_mainClk = PERIOD mainClk 6.4 ns HIGH 50%; + +# Define time groups for inter-clock constraints +TIMEGRP TG_pgpClk_r = RISING pgpClk; +TIMEGRP TG_sysClk125_r = RISING sysClk125; +#TIMEGRP TG_sysClk250_r = RISING sysClk250; +#TIMEGRP TG_mainClk_r = RISING mainClk; + +# Inter Domain Constraints +# TIMESPEC TS_pgpClk_r_sysClk125_r = FROM TG_pgpClk_r TO TG_sysClk125_r 6.4ns; +TIMESPEC TS_sysClk125_r_pgpClk_r = FROM TG_sysClk125_r TO TG_pgpClk_r 6.4ns; +#TIMESPEC TS_sysClk125_r_sysClk250_r = FROM TG_sysClk125_r TO TG_sysClk250_r 8ns; +# NET U_HsioFei4Core/go TIG; +NET U_HsioCosmicCore*/channelmask(*) TIG; +NET U_HsioCosmicCore*/channeloutmask(*) TIG; +#NET U_HsioCosmicCore*/dispDigitC(*) TIG; + +timespec ts_02 = from ffs(*bz(0):*cz(0):*dz(0):*dz(1)) to ffs 640 MHz; +#timespec ts_03 = from ffs(*fei4fifo*) to ffs(*fei4dataflag*) 6.4ns; +#timespec ts_04 = from rams(*fei4fifo*) to ffs(*fei4dataflag*) 6.4ns; + +# Nets to ignore for timing +NET "iResetInL" TIG; + +NET serialinb(?) maxskew = 250 ps ; +#NET U_HsioCosmicCore/deldata maxskew = 250 ps ; + +INST "U_HsioCosmicCore*/*receivedata/ff_*" IOB=FALSE; + + +# Nets to ignore for timing +NET "iResetInL" TIG; + + +#----------------------------------------------------------------------------- +#-------------------------- Pin Location Constraints ------------------------- +#----------------------------------------------------------------------------- +# This section contains the pin location constraints for the design +#----------------------------------------------------------------------------- +# Old P5 = New P5 +# Old P4 = New P4 +# Old P9 = New P3 +# Old P3 = New P2 + + +NET "iPgpRefClkP" LOC = "J1"; +NET "iPgpRefClkM" LOC = "K1"; +#NET "iMainClkP" LOC = "H17"; +#NET "iMainClkN" LOC = "J17"; +# fiber 1 +NET "iMgtRxN(0)" LOC = "N1"; +NET "iMgtRxP(0)" LOC = "M1"; +NET "oMgtTxN(0)" LOC = "T1"; +NET "oMgtTxP(0)" LOC = "R1"; +# fiber 2 +NET "iMgtRxN(1)" LOC = "AA1"; +NET "iMgtRxP(1)" LOC = "Y1"; +NET "oMgtTxN(1)" LOC = "V1"; +NET "oMgtTxP(1)" LOC = "U1"; +#fiber 3 +NET "iMgtRxN(2)" LOC = "AD1"; +NET "iMgtRxP(2)" LOC = "AC1"; +NET "oMgtTxN(2)" LOC = "AG1"; +NET "oMgtTxP(2)" LOC = "AF1"; +#fiber 4 +NET "iMgtRxN(3)" LOC = "AM1"; +NET "iMgtRxP(3)" LOC = "AL1"; +NET "oMgtTxN(3)" LOC = "AJ1"; +NET "oMgtTxP(3)" LOC = "AH1"; + + +NET "oReload" LOC = "G16"; +NET "iResetInL" LOC = "AJ19"; +NET "oDispClk" LOC = "AG22"; +NET "oDispDat" LOC = "AJ22"; +NET "oDispLoadL(1)" LOC = "AK17"; +NET "oDispLoadL(0)" LOC = "Ak18"; +NET "oDispRstL" LOC = "AH22"; +#NET "rclk" LOC = "AM21"; +# fiber 1 +NET "transDis(0)" LOC = "AH4"; +NET "transDis(0)" IOSTANDARD="LVCMOS33"; +# fiber 2 +NET "transDis(1)" LOC = "AK4"; +NET "transDis(1)" IOSTANDARD="LVCMOS33"; +# fiber 3 +NET "transDis(2)" LOC = "Y4"; +NET "transDis(2)" IOSTANDARD="LVCMOS33"; +# fiber 4 +NET "transDis(3)" LOC = "V8"; +NET "transDis(3)" IOSTANDARD="LVCMOS33"; + +NET "iExtreload" LOC = "G15"; +NET "iExtreload" IOSTANDARD="LVCMOS25"; +NET "iExtreload" PULLUP; + +NET "refclk_p" LOC = "J25"; +NET "refclk_p" IOSTANDARD="LVDS_25"; +NET "refclk_n" LOC = "H25"; +NET "refclk_n" IOSTANDARD="LVDS_25"; + +NET "xclk_p" LOC = "E24"; +NET "xclk_p" IOSTANDARD="LVDS_25"; +NET "xclk_n" LOC = "F24"; +NET "xclk_n" IOSTANDARD="LVDS_25"; + +NET "clkout40" LOC = "AJ29"; +NET "clkout40" IOSTANDARD="LVCMOS33"; +NET "clkout40" SLEW="FAST"; + +NET "RD2" LOC = "AJ24"; +NET "RD2" IOSTANDARD="LVCMOS33"; +NET "RD2" SLEW="FAST"; + +NET "AuxClk" LOC = "AK29"; +NET "AuxClk" IOSTANDARD="LVCMOS33"; +NET "AuxClk" SLEW="FAST"; + +NET "RA" LOC = "AM30"; +NET "RA" IOSTANDARD="LVCMOS33"; +NET "RA" SLEW="FAST"; + +NET "RD1" LOC = "AH24"; +NET "RD1" IOSTANDARD="LVCMOS33"; +NET "RD1" SLEW="FAST"; + +NET "IOMXIN(3)" LOC = "AG3"; +NET "IOMXIN(3)" IOSTANDARD="LVCMOS33"; + +NET "IOMXIN(2)" LOC = "AF3"; +NET "IOMXIN(2)" IOSTANDARD="LVCMOS33"; + +NET "IOMXIN(1)" LOC = "W9"; +NET "IOMXIN(1)" IOSTANDARD="LVCMOS33"; + +NET "IOMXIN(0)" LOC = "Y9"; +NET "IOMXIN(0)" IOSTANDARD="LVCMOS33"; + +NET "IOMXSEL(2)" LOC = "AB6"; +NET "IOMXSEL(2)" IOSTANDARD="LVCMOS33"; +NET "IOMXSEL(2)" SLEW="FAST"; + +NET "IOMXSEL(1)" LOC = "AA6"; +NET "IOMXSEL(1)" IOSTANDARD="LVCMOS33"; +NET "IOMXSEL(1)" SLEW="FAST"; + +NET "IOMXSEL(0)" LOC = "Y6"; +NET "IOMXSEL(0)" IOSTANDARD="LVCMOS33"; +NET "IOMXSEL(0)" SLEW="FAST"; + +NET "HITOR" LOC = "AL29"; +NET "HITOR" IOSTANDARD="LVCMOS33"; + +NET "IOMXOUT(0)" LOC = "AC4"; +NET "IOMXOUT(0)" IOSTANDARD="LVCMOS33"; + +NET "IOMXOUT(1)" LOC = "AA8"; +NET "IOMXOUT(1)" IOSTANDARD="LVCMOS33"; + +NET "IOMXOUT(2)" LOC = "AA9"; +NET "IOMXOUT(2)" IOSTANDARD="LVCMOS33"; + +NET "SELALTBUS" LOC = "AK6"; +NET "SELALTBUS" IOSTANDARD="LVCMOS33"; +NET "SELALTBUS" SLEW="FAST"; + +NET "REGABDACLD" LOC = "AD5"; +NET "REGABDACLD" IOSTANDARD="LVCMOS33"; +NET "REGABDACLD" SLEW="FAST"; + +NET "REGABSTBLD" LOC = "AD4"; +NET "REGABSTBLD" IOSTANDARD="LVCMOS33"; +NET "REGABSTBLD" SLEW="FAST"; + +NET "SELCMD" LOC = "AE6"; +NET "SELCMD" IOSTANDARD="LVCMOS33"; +NET "SELCMD" SLEW="FAST"; + +NET "CMDEXTTRIGGER" LOC = "AF6"; +NET "CMDEXTTRIGGER" IOSTANDARD="LVCMOS33"; +NET "CMDEXTTRIGGER" SLEW="FAST"; + +NET "CMDALTPLS" LOC = "AC3"; +NET "CMDALTPLS" IOSTANDARD="LVCMOS33"; +NET "CMDALTPLS" SLEW="FAST"; + +NET "iHSIOtrigger(0)" LOC="J14"; +NET "iHSIOtrigger(0)" IOSTANDARD="LVTTL"; +NET "iHSIOtrigger(0)" SLEW=FAST; + +NET "iHSIOtrigger(1)" LOC="L14"; +NET "iHSIOtrigger(1)" IOSTANDARD="LVTTL"; +NET "iHSIOtrigger(1)" SLEW=FAST; + +#NET "oHSIObusy" LOC="H19"; +#NET "oHSIObusy" LOC="L15"; +#NET "oHSIObusy" IOSTANDARD="LVTTL"; +#NET "oHSIObusy" SLEW=FAST; + +NET "oHSIOtrigger" LOC="L15"; +NET "oHSIOtrigger" IOSTANDARD="LVTTL"; +NET "oHSIOtrigger" SLEW=FAST; + +NET "iHSIObusy" LOC="H19"; +NET "iHSIObusy" IOSTANDARD="LVTTL"; +NET "iHSIObusy" SLEW=FAST; +NET "iHSIObusy" PULLDOWN; + +# Temperature ADC MAX145 +#NET "ADC_Data_in_p" LOC = "L4"; +#NET "ADC_Data_in_n" LOC = "L3"; +#NET "ADC_Clk_p" LOC = "T9"; +#NET "ADC_Clk_n" LOC = "R9"; +#NET "ADC_nCS_p" LOC = "U3"; +#NET "ADC_nCS_n" LOC = "T3"; + +# DI1 +NET "oExttrgclkP" LOC = "AH15"; +NET "oExttrgclkN" LOC = "AJ15"; +# DI3 +NET "oExtbusyP" LOC = "AD14"; +NET "oExtbusyN" LOC = "AC13"; +#DTO1 +NET "iExttriggerP" LOC = "J31"; +NET "iExttriggerN" LOC = "J30"; +# DTO3 +NET "iExtrstP" LOC = "G30"; +NET "iExtrstN" LOC = "F30"; + +NET "serialout_p(0)" LOC = "AG12"; +NET "serialout_n(0)" LOC = "AH12"; +NET "serialout_p(1)" LOC = "AF10"; +NET "serialout_n(1)" LOC = "AG10"; +NET "serialout_p(3)" LOC = "AH14"; +NET "serialout_n(3)" LOC = "AJ14"; +NET "serialout_p(2)" LOC = "AH10"; +NET "serialout_n(2)" LOC = "AJ10"; +NET "serialout_p(4)" LOC = "AJ12"; +NET "serialout_n(4)" LOC = "AK12"; +NET "serialout_p(5)" LOC = "AH8"; +NET "serialout_n(5)" LOC = "AH7"; +NET "serialout_p(6)" LOC = "AF11"; +NET "serialout_n(6)" LOC = "AG11"; +# LVDS drivers broken, use header instead +NET "serialout_p(7)" LOC = "AJ9"; +NET "serialout_n(7)" LOC = "AH9"; +#NET "serialout_p(7)" LOC = "AF15"; +#NET "serialout_n(7)" LOC = "AG15"; +#NET "oExttrgclkP" LOC = "AJ9"; +#NET "oExttrgclkN" LOC = "AH9"; + + +#NET "serialout_p(11)" LOC = "AF15"; +#NET "serialout_n(11)" LOC = "AG15"; +#NET "serialout_p(12)" LOC = "AB13"; +#NET "serialout_n(12)" LOC = "AA13"; +#NET "serialout_p(13)" LOC = "AD10"; +#NET "serialout_n(13)" LOC = "AD9"; +#NET "serialout_p(14)" LOC = "AB11"; +#NET "serialout_n(14)" LOC = "AA11"; +#NET "serialout_p(15)" LOC = "AD14"; +#NET "serialout_n(15)" LOC = "AC13"; +#NET "oExtbusyP" LOC = "AD14"; +#NET "oExtbusyN" LOC = "AC13"; + +NET "serialout(8)" LOC = "AL21"; + +NET "serialin_p(0)" LOC = "AK7"; +NET "serialin_n(0)" LOC = "AJ7"; +NET "serialin_p(1)" LOC = "AF9"; +NET "serialin_n(1)" LOC = "AE9"; +NET "serialin_p(3)" LOC = "AL10"; +NET "serialin_n(3)" LOC = "AM10"; +NET "serialin_p(2)" LOC = "AL9"; +NET "serialin_n(2)" LOC = "AK9"; +NET "serialin_p(4)" LOC = "AL11"; +NET "serialin_n(4)" LOC = "AM11"; +NET "serialin_p(5)" LOC = "AK13"; +NET "serialin_n(5)" LOC = "AL13"; +NET "serialin_p(6)" LOC = "AK14"; +NET "serialin_n(6)" LOC = "AL14"; +# LVDS drivers broken, use header instead +NET "serialin_p(7)" LOC = "AM8"; +NET "serialin_n(7)" LOC = "AM7"; +#NET "serialin_p(7)" LOC = "K28"; +#NET "serialin_n(7)" LOC = "J27"; +#NET "iExttriggerP" LOC = "AM8"; +#NET "iExttriggerN" LOC = "AM7"; +NET "serialin_p(8)" LOC = "AM13"; +NET "serialin_n(8)" LOC = "AM12"; + +#NET "serialin_p(11)" LOC = "K28"; +#NET "serialin_n(11)" LOC = "J27"; +#NET "serialin_p(12)" LOC = "H30"; +#NET "serialin_n(12)" LOC = "H29"; +#NET "serialin_p(13)" LOC = "C23"; +#NET "serialin_n(13)" LOC = "C22"; +#NET "serialin_p(14)" LOC = "E23"; +#NET "serialin_n(14)" LOC = "F23"; +#NET "serialin_p(15)" LOC = "G30"; +#NET "serialin_n(15)" LOC = "F30"; +#NET "iExtrstP" LOC = "G30"; +#NET "iExtrstN" LOC = "F30"; + + +NET "discinP(0)" LOC = "AD7"; +NET "discinP(1)" LOC = "AD6"; +NET "discinP(2)" LOC = "AM6"; +NET "discinP(3)" LOC = "AL6"; + +NET "discinP(0)" IOSTANDARD = "LVCMOS33"; +NET "discinP(1)" IOSTANDARD = "LVCMOS33"; +NET "discinP(2)" IOSTANDARD = "LVCMOS33"; +NET "discinP(3)" IOSTANDARD = "LVCMOS33"; + +# ADC I2C +NET "adcI2cScl" LOC = "AM3"; +NET "adcI2cSda" LOC = "AL3"; +NET "adcAS" LOC = "AJ6"; + +NET "adcI2cScl" IOSTANDARD = "LVCMOS33"; +NET "adcI2cSda" IOSTANDARD = "LVCMOS33"; +NET "adcAS" IOSTANDARD = "LVCMOS33"; + +NET "adcI2cScl" PULLUP; +NET "adcI2cSda" PULLUP; + +#-------------------------- IO Standard Constraints -------------------------- +#----------------------------------------------------------------------------- +# This section defines the IO types, IO delays and other IO parameters +#----------------------------------------------------------------------------- + +NET "iResetInL" IOSTANDARD = "LVCMOS33"; +NET "oDispClk" IOSTANDARD = "LVCMOS33"; +NET "oDispDat" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(1)" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(0)" IOSTANDARD = "LVCMOS33"; +NET "oDispRstL" IOSTANDARD = "LVCMOS33"; + +NET "serialin_p(0)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(0)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(1)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(1)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(2)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(2)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(3)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(3)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(4)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(4)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(5)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(5)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(6)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(6)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(7)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(7)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(8)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(8)" IOSTANDARD = "LVDS_25"; + +NET "serialin_p(11)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(11)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(12)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(12)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(13)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(13)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(14)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(14)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(15)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(15)" IOSTANDARD = "LVDS_25"; +# +NET "serialout_p(0)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(0)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(1)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(1)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(2)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(2)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(3)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(3)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(4)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(4)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(5)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(5)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(6)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(6)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(7)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(7)" IOSTANDARD = "LVDS_25"; +NET "serialout(8)" IOSTANDARD = "LVCMOS33"; + +NET "serialout(8)" SLEW = "FAST"; + +NET "serialout_p(11)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(11)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(12)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(12)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(13)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(13)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(14)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(14)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(15)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(15)" IOSTANDARD = "LVDS_25"; diff --git a/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf.RJ45.oldHSIO b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf.RJ45.oldHSIO new file mode 100644 index 00000000..d9f802b9 --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf.RJ45.oldHSIO @@ -0,0 +1,370 @@ + +#----------------------------------------------------------------------------- +# Title : LCLS BNL ASIC Test FPGA, Constraints File +# Project : LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# File : HsioCosmic.ucf +# Author : Ryan Herbst, rherbst@slac.stanford.edu +# Created : 07/21/2008 +#----------------------------------------------------------------------------- +# Description: +# This file contains all of the user constraints required to implement the +# LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# Copyright (c) 2008 by Ryan Herbst. All rights reserved. +#----------------------------------------------------------------------------- +# Modification history +# 07/21/2008: created. +#----------------------------------------------------------------------------- + + +#----------------------------------------------------------------------------- +#-------------------------- Timing Constraints ------------------------------- +#----------------------------------------------------------------------------- +# This section contains the timing constraints for the FPGA +#----------------------------------------------------------------------------- + +# Define system clocks +NET pgpClk TNM_NET = FFS pgpClk; +NET sysClk125 TNM_NET = FFS sysClk125; +#NET clk320 TNM_NET = FFS clk320; +#NET sysClk250 TNM_NET = FFS sysClk250; +#NET mainClk TNM_NET = FFS mainClk; +INST "U_HsioCosmicCore/thetdc/stopcontrol" RLOC_ORIGIN="X44Y117"; + +# Define system clocks +TIMESPEC TS_pgpClk = PERIOD pgpClk 6.4 ns HIGH 50%; +TIMESPEC TS_sysClk125 = PERIOD sysClk125 25.6 ns HIGH 50%; +#TIMESPEC TS_clk320 = PERIOD clk320 3.2 ns HIGH 50%; +#TIMESPEC TS_sysClk250 = PERIOD sysClk250 12.8 ns HIGH 50%; +#TIMESPEC TS_mainClk = PERIOD mainClk 6.4 ns HIGH 50%; + +# Define time groups for inter-clock constraints +TIMEGRP TG_pgpClk_r = RISING pgpClk; +TIMEGRP TG_sysClk125_r = RISING sysClk125; +#TIMEGRP TG_sysClk250_r = RISING sysClk250; +#TIMEGRP TG_mainClk_r = RISING mainClk; + +# Inter Domain Constraints +# TIMESPEC TS_pgpClk_r_sysClk125_r = FROM TG_pgpClk_r TO TG_sysClk125_r 6.4ns; +TIMESPEC TS_sysClk125_r_pgpClk_r = FROM TG_sysClk125_r TO TG_pgpClk_r 6.4ns; +#TIMESPEC TS_sysClk125_r_sysClk250_r = FROM TG_sysClk125_r TO TG_sysClk250_r 8ns; +# NET U_HsioFei4Core/go TIG; +NET U_HsioCosmicCore/channelmask(*) TIG; +NET U_HsioCosmicCore/channeloutmask(*) TIG; + +timespec ts_02 = from ffs(*bz(0):*cz(0):*dz(0):*dz(1)) to ffs 640 MHz; +timespec ts_03 = from ffs(*fei4fifo*) to ffs(*fei4dataflag*) 6.4ns; +timespec ts_04 = from rams(*fei4fifo*) to ffs(*fei4dataflag*) 6.4ns; + +# Nets to ignore for timing +NET "iResetInL" TIG; + +NET serialinb(?) maxskew = 250 ps ; +#NET U_HsioCosmicCore/deldata maxskew = 250 ps ; + +INST "U_HsioCosmicCore/*receivedata/ff_*" IOB=FALSE; + + +# Nets to ignore for timing +NET "iResetInL" TIG; + + +#----------------------------------------------------------------------------- +#-------------------------- Pin Location Constraints ------------------------- +#----------------------------------------------------------------------------- +# This section contains the pin location constraints for the design +#----------------------------------------------------------------------------- +# Old P5 = New P5 +# Old P4 = New P4 +# Old P9 = New P3 +# Old P3 = New P2 + + +NET "iPgpRefClkP" LOC = "AP29"; +NET "iPgpRefClkM" LOC = "AP28"; +#NET "iMainClkP" LOC = "H17"; +#NET "iMainClkN" LOC = "J17"; +# fiber 1 +NET "iMgtRxN" LOC = "AP25"; +NET "iMgtRxP" LOC = "AP26"; +NET "oMgtTxN" LOC = "AP22"; +NET "oMgtTxP" LOC = "AP23"; +# fiber 2 +#NET "iMgtRxN" LOC = "AA1"; +#NET "iMgtRxP" LOC = "Y1"; +#NET "oMgtTxN" LOC = "V1"; +#NET "oMgtTxP" LOC = "U1"; +NET "oReload" LOC = "G16"; +NET "iResetInL" LOC = "AJ19"; +NET "oDispClk" LOC = "AG22"; +NET "oDispDat" LOC = "AJ22"; +NET "oDispLoadL(1)" LOC = "AK17"; +NET "oDispLoadL(0)" LOC = "Ak18"; +NET "oDispRstL" LOC = "AH22"; +#NET "rclk" LOC = "AM21"; +# fiber 1 +NET "transDis1" LOC = "AE27"; +# fiber 2 +#NET "transDis1" LOC = "AK4"; +NET "transDis1" IOSTANDARD="LVCMOS33"; + +NET "refclk_p" LOC = "T9"; +NET "refclk_p" IOSTANDARD="LVDS_25"; +NET "refclk_n" LOC = "R9"; +NET "refclk_n" IOSTANDARD="LVDS_25"; + +#NET "xclk_p" LOC = "E24"; +#NET "xclk_p" IOSTANDARD="LVDS_25"; +#NET "xclk_n" LOC = "F24"; +#NET "xclk_n" IOSTANDARD="LVDS_25"; + +#NET "clkout40" LOC = "AJ29"; +#NET "clkout40" IOSTANDARD="LVCMOS33"; +#NET "clkout40" SLEW="FAST"; + +#NET "RD2" LOC = "AJ24"; +#NET "RD2" IOSTANDARD="LVCMOS33"; +#NET "RD2" SLEW="FAST"; + +#NET "AuxClk" LOC = "AK29"; +#NET "AuxClk" IOSTANDARD="LVCMOS33"; +#NET "AuxClk" SLEW="FAST"; + +#NET "RA" LOC = "AM30"; +#NET "RA" IOSTANDARD="LVCMOS33"; +#NET "RA" SLEW="FAST"; + +#NET "RD1" LOC = "AH24"; +#NET "RD1" IOSTANDARD="LVCMOS33"; +#NET "RD1" SLEW="FAST"; + +#NET "IOMXIN(3)" LOC = "AG3"; +#NET "IOMXIN(3)" IOSTANDARD="LVCMOS33"; + +#NET "IOMXIN(2)" LOC = "AF3"; +#NET "IOMXIN(2)" IOSTANDARD="LVCMOS33"; + +#NET "IOMXIN(1)" LOC = "W9"; +#NET "IOMXIN(1)" IOSTANDARD="LVCMOS33"; + +#NET "IOMXIN(0)" LOC = "Y9"; +#NET "IOMXIN(0)" IOSTANDARD="LVCMOS33"; + +#NET "IOMXSEL(2)" LOC = "AB6"; +#NET "IOMXSEL(2)" IOSTANDARD="LVCMOS33"; +#NET "IOMXSEL(2)" SLEW="FAST"; + +#NET "IOMXSEL(1)" LOC = "AA6"; +#NET "IOMXSEL(1)" IOSTANDARD="LVCMOS33"; +#NET "IOMXSEL(1)" SLEW="FAST"; + +#NET "IOMXSEL(0)" LOC = "Y6"; +#NET "IOMXSEL(0)" IOSTANDARD="LVCMOS33"; +#NET "IOMXSEL(0)" SLEW="FAST"; + +#NET "HITOR" LOC = "T8"; #auxclk +#NET "HITOR" LOC = "AL29"; +#NET "HITOR" IOSTANDARD="LVCMOS33"; + +#NET "IOMXOUT(0)" LOC = "AC4"; +#NET "IOMXOUT(0)" IOSTANDARD="LVCMOS33"; + +#NET "IOMXOUT(1)" LOC = "AA8"; +#NET "IOMXOUT(1)" IOSTANDARD="LVCMOS33"; + +#NET "IOMXOUT(2)" LOC = "AA9"; +#NET "IOMXOUT(2)" IOSTANDARD="LVCMOS33"; + +#NET "SELALTBUS" LOC = "AK6"; +#NET "SELALTBUS" IOSTANDARD="LVCMOS33"; +#NET "SELALTBUS" SLEW="FAST"; + +#NET "REGABDACLD" LOC = "AD5"; +#NET "REGABDACLD" IOSTANDARD="LVCMOS33"; +#NET "REGABDACLD" SLEW="FAST"; + +#NET "REGABSTBLD" LOC = "AD4"; +#NET "REGABSTBLD" IOSTANDARD="LVCMOS33"; +#NET "REGABSTBLD" SLEW="FAST"; + +#NET "SELCMD" LOC = "AE6"; +#NET "SELCMD" IOSTANDARD="LVCMOS33"; +#NET "SELCMD" SLEW="FAST"; + +#NET "CMDEXTTRIGGER" LOC = "AF6"; +#NET "CMDEXTTRIGGER" IOSTANDARD="LVCMOS33"; +#NET "CMDEXTTRIGGER" SLEW="FAST"; + +#NET "CMDALTPLS" LOC = "AC3"; +#NET "CMDALTPLS" IOSTANDARD="LVCMOS33"; +#NET "CMDALTPLS" SLEW="FAST"; + +#NET "iHSIOtrigger" LOC="J14"; +#NET "iHSIOtrigger" IOSTANDARD="LVTTL"; +#NET "iHSIOtrigger" SLEW=FAST; + +#NET "oHSIObusy" LOC="H19"; +#NET "oHSIObusy" IOSTANDARD="LVTTL"; +#NET "oHSIObusy" SLEW=FAST; + +# Temperature ADC MAX145 +#NET "ADC_Data_in_p" LOC = "L4"; +#NET "ADC_Data_in_n" LOC = "L3"; +#NET "ADC_Clk_p" LOC = "T9"; +#NET "ADC_Clk_n" LOC = "R9"; +#NET "ADC_nCS_p" LOC = "U3"; +#NET "ADC_nCS_n" LOC = "T3"; + +NET "serialout_p(0)" LOC = "U3"; +NET "serialout_n(0)" LOC = "T3"; +#NET "serialout_p(1)" LOC = "AF10"; +#NET "serialout_n(1)" LOC = "AG10"; +#NET "serialout_p(3)" LOC = "AH14"; +#NET "serialout_n(3)" LOC = "AJ14"; +#NET "serialout_p(2)" LOC = "AH10"; +#NET "serialout_n(2)" LOC = "AJ10"; +#NET "serialout_p(4)" LOC = "AJ12"; +#NET "serialout_n(4)" LOC = "AK12"; +#NET "serialout_p(5)" LOC = "AH8"; +#NET "serialout_n(5)" LOC = "AH7"; +#NET "serialout_p(6)" LOC = "AF11"; +#NET "serialout_n(6)" LOC = "AG11"; +#NET "serialout_p(7)" LOC = "AJ9"; +#NET "serialout_n(7)" LOC = "AH9"; +#NET "oExttrgclkP" LOC = "AJ9"; +#NET "oExttrgclkN" LOC = "AH9"; + + +#NET "serialout_p(11)" LOC = "AF15"; +#NET "serialout_n(11)" LOC = "AG15"; +#NET "serialout_p(12)" LOC = "AB13"; +#NET "serialout_n(12)" LOC = "AA13"; +#NET "serialout_p(13)" LOC = "AD10"; +#NET "serialout_n(13)" LOC = "AD9"; +#NET "serialout_p(14)" LOC = "AB11"; +#NET "serialout_n(14)" LOC = "AA11"; +#NET "serialout_p(15)" LOC = "AD14"; +#NET "serialout_n(15)" LOC = "AC13"; +#NET "oExtbusyP" LOC = "AD14"; +#NET "oExtbusyN" LOC = "AC13"; + +#NET "serialout(8)" LOC = "AL21"; + +NET "serialin_p(0)" LOC = "M3"; +NET "serialin_n(0)" LOC = "N3"; +#NET "serialin_p(1)" LOC = "AF9"; +#NET "serialin_n(1)" LOC = "AE9"; +#NET "serialin_p(3)" LOC = "AL10"; +#NET "serialin_n(3)" LOC = "AM10"; +#NET "serialin_p(2)" LOC = "AL9"; +#NET "serialin_n(2)" LOC = "AK9"; +#NET "serialin_p(4)" LOC = "AL11"; +#NET "serialin_n(4)" LOC = "AM11"; +#NET "serialin_p(5)" LOC = "AK13"; +#NET "serialin_n(5)" LOC = "AL13"; +#NET "serialin_p(6)" LOC = "AK14"; +#NET "serialin_n(6)" LOC = "AL14"; +##NET "serialin_p(7)" LOC = "AM8"; +##NET "serialin_n(7)" LOC = "AM7"; +#NET "iExttriggerP" LOC = "AM8"; +#NET "iExttriggerN" LOC = "AM7"; +#NET "serialin_p(8)" LOC = "AM13"; +#NET "serialin_n(8)" LOC = "AM12"; + +#NET "serialin_p(11)" LOC = "K28"; +#NET "serialin_n(11)" LOC = "J27"; +#NET "serialin_p(12)" LOC = "H30"; +#NET "serialin_n(12)" LOC = "H29"; +#NET "serialin_p(13)" LOC = "C23"; +#NET "serialin_n(13)" LOC = "C22"; +#NET "serialin_p(14)" LOC = "E23"; +#NET "serialin_n(14)" LOC = "F23"; +#NET "serialin_p(15)" LOC = "G30"; +#NET "serialin_n(15)" LOC = "F30"; +#NET "iExtrstP" LOC = "G30"; +#NET "iExtrstN" LOC = "F30"; + + +#NET "discinP(0)" LOC = "AD7"; +#NET "discinP(1)" LOC = "AD6"; +#NET "discinP(2)" LOC = "AM6"; +#NET "discinP(3)" LOC = "AL6"; + +#NET "discinP(0)" IOSTANDARD = "LVCMOS33"; +#NET "discinP(1)" IOSTANDARD = "LVCMOS33"; +#NET "discinP(2)" IOSTANDARD = "LVCMOS33"; +#NET "discinP(3)" IOSTANDARD = "LVCMOS33"; + +#-------------------------- IO Standard Constraints -------------------------- +#----------------------------------------------------------------------------- +# This section defines the IO types, IO delays and other IO parameters +#----------------------------------------------------------------------------- + +NET "iResetInL" IOSTANDARD = "LVCMOS33"; +NET "oDispClk" IOSTANDARD = "LVCMOS33"; +NET "oDispDat" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(1)" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(0)" IOSTANDARD = "LVCMOS33"; +NET "oDispRstL" IOSTANDARD = "LVCMOS33"; + +NET "serialin_p(0)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(0)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(1)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(1)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(2)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(2)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(3)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(3)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(4)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(4)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(5)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(5)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(6)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(6)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(7)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(7)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(8)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(8)" IOSTANDARD = "LVDS_25"; + +NET "serialin_p(11)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(11)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(12)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(12)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(13)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(13)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(14)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(14)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(15)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(15)" IOSTANDARD = "LVDS_25"; + +NET "serialout_p(0)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(0)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(1)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(1)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(2)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(2)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(3)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(3)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(4)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(4)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(5)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(5)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(6)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(6)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(7)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(7)" IOSTANDARD = "LVDS_25"; +NET "serialout(8)" IOSTANDARD = "LVCMOS33"; + +NET "serialout(8)" SLEW = "FAST"; + +NET "serialout_p(11)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(11)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(12)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(12)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(13)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(13)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(14)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(14)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(15)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(15)" IOSTANDARD = "LVDS_25"; diff --git a/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf.fei3 b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf.fei3 new file mode 100644 index 00000000..6d214340 --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf.fei3 @@ -0,0 +1,161 @@ + +#----------------------------------------------------------------------------- +# Title : LCLS BNL ASIC Test FPGA, Constraints File +# Project : LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# File : HsioCosmic.ucf +# Author : Ryan Herbst, rherbst@slac.stanford.edu +# Created : 07/21/2008 +#----------------------------------------------------------------------------- +# Description: +# This file contains all of the user constraints required to implement the +# LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# Copyright (c) 2008 by Ryan Herbst. All rights reserved. +#----------------------------------------------------------------------------- +# Modification history +# 07/21/2008: created. +#----------------------------------------------------------------------------- + + +#----------------------------------------------------------------------------- +#-------------------------- Timing Constraints ------------------------------- +#----------------------------------------------------------------------------- +# This section contains the timing constraints for the FPGA +#----------------------------------------------------------------------------- + +# Define system clocks +NET pgpClk TNM_NET = FFS pgpClk; +NET sysClk125 TNM_NET = FFS sysClk125; +#NET clk320 TNM_NET = FFS clk320; +#NET sysClk250 TNM_NET = FFS sysClk250; +#NET mainClk TNM_NET = FFS mainClk; +INST "U_HsioCosmicCore/thetdc/stopcontrol" RLOC_ORIGIN="X44Y117"; + +# Define system clocks +TIMESPEC TS_pgpClk = PERIOD pgpClk 6.4 ns HIGH 50%; +TIMESPEC TS_sysClk125 = PERIOD sysClk125 25.6 ns HIGH 50%; +#TIMESPEC TS_clk320 = PERIOD clk320 3.2 ns HIGH 50%; +#TIMESPEC TS_sysClk250 = PERIOD sysClk250 12.8 ns HIGH 50%; +#TIMESPEC TS_mainClk = PERIOD mainClk 6.4 ns HIGH 50%; + +# Define time groups for inter-clock constraints +TIMEGRP TG_pgpClk_r = RISING pgpClk; +TIMEGRP TG_sysClk125_r = RISING sysClk125; +#TIMEGRP TG_sysClk250_r = RISING sysClk250; +#TIMEGRP TG_mainClk_r = RISING mainClk; + +# Inter Domain Constraints +# TIMESPEC TS_pgpClk_r_sysClk125_r = FROM TG_pgpClk_r TO TG_sysClk125_r 6.4ns; +TIMESPEC TS_sysClk125_r_pgpClk_r = FROM TG_sysClk125_r TO TG_pgpClk_r 6.4ns; +#TIMESPEC TS_sysClk125_r_sysClk250_r = FROM TG_sysClk125_r TO TG_sysClk250_r 8ns; +# NET U_HsioFei4Core/go TIG; +NET U_HsioCosmicCore/channelmask(*) TIG; +NET U_HsioCosmicCore/channeloutmask(*) TIG; + +#timespec ts_03 = from ffs(*fei4fifo*) to ffs(*fei4dataflag*) 6.4ns; +#timespec ts_04 = from rams(*fei4fifo*) to ffs(*fei4dataflag*) 6.4ns; + +# Nets to ignore for timing +NET "iResetInL" TIG; + + + + +# Nets to ignore for timing +NET "iResetInL" TIG; + + +#----------------------------------------------------------------------------- +#-------------------------- Pin Location Constraints ------------------------- +#----------------------------------------------------------------------------- +# This section contains the pin location constraints for the design +#----------------------------------------------------------------------------- +# Old P5 = New P5 +# Old P4 = New P4 +# Old P9 = New P3 +# Old P3 = New P2 + + +NET "iPgpRefClkP" LOC = "J1"; +NET "iPgpRefClkM" LOC = "K1"; +#NET "iMainClkP" LOC = "H17"; +#NET "iMainClkN" LOC = "J17"; +# fiber 1 +NET "iMgtRxN" LOC = "N1"; +NET "iMgtRxP" LOC = "M1"; +NET "oMgtTxN" LOC = "T1"; +NET "oMgtTxP" LOC = "R1"; +# fiber 2 +#NET "iMgtRxN" LOC = "AA1"; +#NET "iMgtRxP" LOC = "Y1"; +#NET "oMgtTxN" LOC = "V1"; +#NET "oMgtTxP" LOC = "U1"; +NET "oReload" LOC = "G16"; +NET "iResetInL" LOC = "AJ19"; +NET "oDispClk" LOC = "AG22"; +NET "oDispDat" LOC = "AJ22"; +NET "oDispLoadL(1)" LOC = "AK17"; +NET "oDispLoadL(0)" LOC = "Ak18"; +NET "oDispRstL" LOC = "AH22"; +#NET "rclk" LOC = "AM21"; +# fiber 1 +NET "transDis1" LOC = "AH4"; +# fiber 2 +#NET "transDis1" LOC = "AK4"; +NET "transDis1" IOSTANDARD="LVCMOS33"; + +NET "refclk_p" LOC = "J25"; +NET "refclk_p" IOSTANDARD="LVDS_25"; +NET "refclk_n" LOC = "H25"; +NET "refclk_n" IOSTANDARD="LVDS_25"; + +NET "xclk_p" LOC = "E24"; +NET "xclk_p" IOSTANDARD="LVDS_25"; +NET "xclk_n" LOC = "F24"; +NET "xclk_n" IOSTANDARD="LVDS_25"; + +NET "clkout40" LOC = "AF16"; +NET "clkout40" IOSTANDARD="LVCMOS25"; +NET "clkout40" SLEW="FAST"; + +NET "iHSIOtrigger" LOC="J14"; +NET "iHSIOtrigger" IOSTANDARD="LVTTL"; +NET "iHSIOtrigger" SLEW=FAST; + +NET "oHSIObusy" LOC="H19"; +NET "oHSIObusy" IOSTANDARD="LVTTL"; +NET "oHSIObusy" SLEW=FAST; + +NET "serialout(0)" LOC = "AE16"; +NET "serialout(0)" SLEW = "FAST"; +NET "serialout(0)" IOSTANDARD = "LVCMOS25"; + +NET "serialin(0)" LOC = "AE18"; +NET "serialout(0)" IOSTANDARD = "LVCMOS25"; + + +#NET "discinP(0)" LOC = "AD7"; +#NET "discinP(1)" LOC = "AD6"; +#NET "discinP(2)" LOC = "AM6"; +#NET "discinP(3)" LOC = "AL6"; + +#NET "discinP(0)" IOSTANDARD = "LVCMOS33"; +#NET "discinP(1)" IOSTANDARD = "LVCMOS33"; +#NET "discinP(2)" IOSTANDARD = "LVCMOS33"; +#NET "discinP(3)" IOSTANDARD = "LVCMOS33"; + +#-------------------------- IO Standard Constraints -------------------------- +#----------------------------------------------------------------------------- +# This section defines the IO types, IO delays and other IO parameters +#----------------------------------------------------------------------------- + +NET "iResetInL" IOSTANDARD = "LVCMOS33"; +NET "oDispClk" IOSTANDARD = "LVCMOS33"; +NET "oDispDat" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(1)" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(0)" IOSTANDARD = "LVCMOS33"; +NET "oDispRstL" IOSTANDARD = "LVCMOS33"; + + + diff --git a/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf.full b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf.full new file mode 100644 index 00000000..75a17a88 --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf.full @@ -0,0 +1,412 @@ + +#----------------------------------------------------------------------------- +# Title : LCLS BNL ASIC Test FPGA, Constraints File +# Project : LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# File : HsioCosmic.ucf +# Author : Ryan Herbst, rherbst@slac.stanford.edu +# Created : 07/21/2008 +#----------------------------------------------------------------------------- +# Description: +# This file contains all of the user constraints required to implement the +# LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# Copyright (c) 2008 by Ryan Herbst. All rights reserved. +#----------------------------------------------------------------------------- +# Modification history +# 07/21/2008: created. +#----------------------------------------------------------------------------- + + +#----------------------------------------------------------------------------- +#-------------------------- Timing Constraints ------------------------------- +#----------------------------------------------------------------------------- +# This section contains the timing constraints for the FPGA +#----------------------------------------------------------------------------- + +# Define system clocks +NET pgpClk TNM_NET = FFS pgpClk; +NET sysClk125 TNM_NET = FFS sysClk125; +#NET clk320 TNM_NET = FFS clk320; +#NET sysClk250 TNM_NET = FFS sysClk250; +#NET mainClk TNM_NET = FFS mainClk; +INST "U_triggerlogic/thetdc/stopcontrol" RLOC_ORIGIN="X44Y117"; + +# Define system clocks +TIMESPEC TS_pgpClk = PERIOD pgpClk 6.4 ns HIGH 50%; +TIMESPEC TS_sysClk125 = PERIOD sysClk125 25.6 ns HIGH 50%; +#TIMESPEC TS_clk320 = PERIOD clk320 3.2 ns HIGH 50%; +#TIMESPEC TS_sysClk250 = PERIOD sysClk250 12.8 ns HIGH 50%; +#TIMESPEC TS_mainClk = PERIOD mainClk 6.4 ns HIGH 50%; + +# Define time groups for inter-clock constraints +TIMEGRP TG_pgpClk_r = RISING pgpClk; +TIMEGRP TG_sysClk125_r = RISING sysClk125; +#TIMEGRP TG_sysClk250_r = RISING sysClk250; +#TIMEGRP TG_mainClk_r = RISING mainClk; + +# Inter Domain Constraints +# TIMESPEC TS_pgpClk_r_sysClk125_r = FROM TG_pgpClk_r TO TG_sysClk125_r 6.4ns; +TIMESPEC TS_sysClk125_r_pgpClk_r = FROM TG_sysClk125_r TO TG_pgpClk_r 6.4ns; +#TIMESPEC TS_sysClk125_r_sysClk250_r = FROM TG_sysClk125_r TO TG_sysClk250_r 8ns; +# NET U_HsioFei4Core/go TIG; +NET U_HsioCosmicCore*/channelmask(*) TIG; +NET U_HsioCosmicCore*/channeloutmask(*) TIG; + +timespec ts_02 = from ffs(*bz(0):*cz(0):*dz(0):*dz(1)) to ffs 640 MHz; +#timespec ts_03 = from ffs(*fei4fifo*) to ffs(*fei4dataflag*) 6.4ns; +#timespec ts_04 = from rams(*fei4fifo*) to ffs(*fei4dataflag*) 6.4ns; + +# Nets to ignore for timing +NET "iResetInL" TIG; + +NET serialinb(?) maxskew = 250 ps ; +#NET U_HsioCosmicCore/deldata maxskew = 250 ps ; + +INST "U_HsioCosmicCore*/*receivedata/ff_*" IOB=FALSE; + + +# Nets to ignore for timing +NET "iResetInL" TIG; + + +#----------------------------------------------------------------------------- +#-------------------------- Pin Location Constraints ------------------------- +#----------------------------------------------------------------------------- +# This section contains the pin location constraints for the design +#----------------------------------------------------------------------------- +# Old P5 = New P5 +# Old P4 = New P4 +# Old P9 = New P3 +# Old P3 = New P2 + + +NET "iPgpRefClkP" LOC = "J1"; +NET "iPgpRefClkM" LOC = "K1"; +#NET "iMainClkP" LOC = "H17"; +#NET "iMainClkN" LOC = "J17"; +# fiber 1 +NET "iMgtRxN" LOC = "N1"; +NET "iMgtRxP" LOC = "M1"; +NET "oMgtTxN" LOC = "T1"; +NET "oMgtTxP" LOC = "R1"; +# fiber 2 +#NET "iMgtRxN2" LOC = "AA1"; +#NET "iMgtRxP2" LOC = "Y1"; +#NET "oMgtTxN2" LOC = "V1"; +#NET "oMgtTxP2" LOC = "U1"; +NET "oReload" LOC = "G16"; +NET "iResetInL" LOC = "AJ19"; +NET "oDispClk" LOC = "AG22"; +NET "oDispDat" LOC = "AJ22"; +NET "oDispLoadL(1)" LOC = "AK17"; +NET "oDispLoadL(0)" LOC = "Ak18"; +NET "oDispRstL" LOC = "AH22"; +#NET "rclk" LOC = "AM21"; +# fiber 1 +NET "transDis1" LOC = "AH4"; +NET "transDis1" IOSTANDARD="LVCMOS33"; +# fiber 2 +#NET "transDis2" LOC = "AK4"; +#NET "transDis2" IOSTANDARD="LVCMOS33"; + +NET "iExtreload" LOC = "G15"; +NET "iExtreload" IOSTANDARD="LVCMOS25"; +NET "iExtreload" PULLUP; + +NET "refclk_p" LOC = "J25"; +NET "refclk_p" IOSTANDARD="LVDS_25"; +NET "refclk_n" LOC = "H25"; +NET "refclk_n" IOSTANDARD="LVDS_25"; + +NET "xclk_p" LOC = "E24"; +NET "xclk_p" IOSTANDARD="LVDS_25"; +NET "xclk_n" LOC = "F24"; +NET "xclk_n" IOSTANDARD="LVDS_25"; + +NET "clkout40" LOC = "AJ29"; +NET "clkout40" IOSTANDARD="LVCMOS33"; +NET "clkout40" SLEW="FAST"; + +NET "RD2" LOC = "AJ24"; +NET "RD2" IOSTANDARD="LVCMOS33"; +NET "RD2" SLEW="FAST"; + +NET "AuxClk" LOC = "AK29"; +NET "AuxClk" IOSTANDARD="LVCMOS33"; +NET "AuxClk" SLEW="FAST"; + +NET "RA" LOC = "AM30"; +NET "RA" IOSTANDARD="LVCMOS33"; +NET "RA" SLEW="FAST"; + +NET "RD1" LOC = "AH24"; +NET "RD1" IOSTANDARD="LVCMOS33"; +NET "RD1" SLEW="FAST"; + +NET "IOMXIN(3)" LOC = "AG3"; +NET "IOMXIN(3)" IOSTANDARD="LVCMOS33"; + +NET "IOMXIN(2)" LOC = "AF3"; +NET "IOMXIN(2)" IOSTANDARD="LVCMOS33"; + +NET "IOMXIN(1)" LOC = "W9"; +NET "IOMXIN(1)" IOSTANDARD="LVCMOS33"; + +NET "IOMXIN(0)" LOC = "Y9"; +NET "IOMXIN(0)" IOSTANDARD="LVCMOS33"; + +NET "IOMXSEL(2)" LOC = "AB6"; +NET "IOMXSEL(2)" IOSTANDARD="LVCMOS33"; +NET "IOMXSEL(2)" SLEW="FAST"; + +NET "IOMXSEL(1)" LOC = "AA6"; +NET "IOMXSEL(1)" IOSTANDARD="LVCMOS33"; +NET "IOMXSEL(1)" SLEW="FAST"; + +NET "IOMXSEL(0)" LOC = "Y6"; +NET "IOMXSEL(0)" IOSTANDARD="LVCMOS33"; +NET "IOMXSEL(0)" SLEW="FAST"; + +NET "HITOR" LOC = "AL29"; +NET "HITOR" IOSTANDARD="LVCMOS33"; + +NET "IOMXOUT(0)" LOC = "AC4"; +NET "IOMXOUT(0)" IOSTANDARD="LVCMOS33"; + +NET "IOMXOUT(1)" LOC = "AA8"; +NET "IOMXOUT(1)" IOSTANDARD="LVCMOS33"; + +NET "IOMXOUT(2)" LOC = "AA9"; +NET "IOMXOUT(2)" IOSTANDARD="LVCMOS33"; + +NET "SELALTBUS" LOC = "AK6"; +NET "SELALTBUS" IOSTANDARD="LVCMOS33"; +NET "SELALTBUS" SLEW="FAST"; + +NET "REGABDACLD" LOC = "AD5"; +NET "REGABDACLD" IOSTANDARD="LVCMOS33"; +NET "REGABDACLD" SLEW="FAST"; + +NET "REGABSTBLD" LOC = "AD4"; +NET "REGABSTBLD" IOSTANDARD="LVCMOS33"; +NET "REGABSTBLD" SLEW="FAST"; + +NET "SELCMD" LOC = "AE6"; +NET "SELCMD" IOSTANDARD="LVCMOS33"; +NET "SELCMD" SLEW="FAST"; + +NET "CMDEXTTRIGGER" LOC = "AF6"; +NET "CMDEXTTRIGGER" IOSTANDARD="LVCMOS33"; +NET "CMDEXTTRIGGER" SLEW="FAST"; + +NET "CMDALTPLS" LOC = "AC3"; +NET "CMDALTPLS" IOSTANDARD="LVCMOS33"; +NET "CMDALTPLS" SLEW="FAST"; + +NET "iHSIOtrigger(0)" LOC="J14"; +NET "iHSIOtrigger(0)" IOSTANDARD="LVTTL"; +NET "iHSIOtrigger(0)" SLEW=FAST; + +NET "iHSIOtrigger(1)" LOC="L14"; +NET "iHSIOtrigger(1)" IOSTANDARD="LVTTL"; +NET "iHSIOtrigger(1)" SLEW=FAST; + +#NET "oHSIObusy" LOC="H19"; +#NET "oHSIObusy" IOSTANDARD="LVTTL"; +#NET "oHSIObusy" SLEW=FAST; + +NET "oHSIOtrigger" LOC="L15"; +NET "oHSIOtrigger" IOSTANDARD="LVTTL"; +NET "oHSIOtrigger" SLEW=FAST; + +NET "iHSIObusy" LOC="H19"; +NET "iHSIObusy" IOSTANDARD="LVTTL"; +NET "iHSIObusy" SLEW=FAST; +NET "iHSIObusy" PULLDOWN; + +# Temperature ADC MAX145 +#NET "ADC_Data_in_p" LOC = "L4"; +#NET "ADC_Data_in_n" LOC = "L3"; +#NET "ADC_Clk_p" LOC = "T9"; +#NET "ADC_Clk_n" LOC = "R9"; +#NET "ADC_nCS_p" LOC = "U3"; +#NET "ADC_nCS_n" LOC = "T3"; + +# DI1 +NET "oExttrgclkP" LOC = "AH15"; +NET "oExttrgclkN" LOC = "AJ15"; +# DI3 +NET "oExtbusyP" LOC = "AD14"; +NET "oExtbusyN" LOC = "AC13"; +#DTO1 +NET "iExttriggerP" LOC = "J31"; +NET "iExttriggerN" LOC = "J30"; +# DTO3 +NET "iExtrstP" LOC = "G30"; +NET "iExtrstN" LOC = "F30"; + +NET "serialout_p(0)" LOC = "AG12"; +NET "serialout_n(0)" LOC = "AH12"; +NET "serialout_p(1)" LOC = "AF10"; +NET "serialout_n(1)" LOC = "AG10"; +NET "serialout_p(3)" LOC = "AH14"; +NET "serialout_n(3)" LOC = "AJ14"; +NET "serialout_p(2)" LOC = "AH10"; +NET "serialout_n(2)" LOC = "AJ10"; +NET "serialout_p(4)" LOC = "AJ12"; +NET "serialout_n(4)" LOC = "AK12"; +NET "serialout_p(5)" LOC = "AH8"; +NET "serialout_n(5)" LOC = "AH7"; +NET "serialout_p(6)" LOC = "AF11"; +NET "serialout_n(6)" LOC = "AG11"; +NET "serialout_p(7)" LOC = "AJ9"; +NET "serialout_n(7)" LOC = "AH9"; +#NET "oExttrgclkP" LOC = "AJ9"; +#NET "oExttrgclkN" LOC = "AH9"; + + +NET "serialout_p(11)" LOC = "AF15"; +NET "serialout_n(11)" LOC = "AG15"; +NET "serialout_p(12)" LOC = "AB13"; +NET "serialout_n(12)" LOC = "AA13"; +NET "serialout_p(13)" LOC = "AD10"; +NET "serialout_n(13)" LOC = "AD9"; +NET "serialout_p(14)" LOC = "AB11"; +NET "serialout_n(14)" LOC = "AA11"; +#NET "serialout_p(15)" LOC = "AD14"; +#NET "serialout_n(15)" LOC = "AC13"; +#NET "oExtbusyP" LOC = "AD14"; +#NET "oExtbusyN" LOC = "AC13"; + +NET "serialout(8)" LOC = "AL21"; + +NET "serialin_p(0)" LOC = "AK7"; +NET "serialin_n(0)" LOC = "AJ7"; +NET "serialin_p(1)" LOC = "AF9"; +NET "serialin_n(1)" LOC = "AE9"; +NET "serialin_p(3)" LOC = "AL10"; +NET "serialin_n(3)" LOC = "AM10"; +NET "serialin_p(2)" LOC = "AL9"; +NET "serialin_n(2)" LOC = "AK9"; +NET "serialin_p(4)" LOC = "AL11"; +NET "serialin_n(4)" LOC = "AM11"; +NET "serialin_p(5)" LOC = "AK13"; +NET "serialin_n(5)" LOC = "AL13"; +NET "serialin_p(6)" LOC = "AK14"; +NET "serialin_n(6)" LOC = "AL14"; +NET "serialin_p(7)" LOC = "AM8"; +NET "serialin_n(7)" LOC = "AM7"; +#NET "iExttriggerP" LOC = "AM8"; +#NET "iExttriggerN" LOC = "AM7"; +NET "serialin_p(8)" LOC = "AM13"; +NET "serialin_n(8)" LOC = "AM12"; + +NET "serialin_p(11)" LOC = "K28"; +NET "serialin_n(11)" LOC = "J27"; +NET "serialin_p(12)" LOC = "H30"; +NET "serialin_n(12)" LOC = "H29"; +NET "serialin_p(13)" LOC = "C23"; +NET "serialin_n(13)" LOC = "C22"; +NET "serialin_p(14)" LOC = "E23"; +NET "serialin_n(14)" LOC = "F23"; +#NET "serialin_p(15)" LOC = "G30"; +#NET "serialin_n(15)" LOC = "F30"; +#NET "iExtrstP" LOC = "G30"; +#NET "iExtrstN" LOC = "F30"; + + +NET "discinP(0)" LOC = "AD7"; +NET "discinP(1)" LOC = "AD6"; +NET "discinP(2)" LOC = "AM6"; +NET "discinP(3)" LOC = "AL6"; + +NET "discinP(0)" IOSTANDARD = "LVCMOS33"; +NET "discinP(1)" IOSTANDARD = "LVCMOS33"; +NET "discinP(2)" IOSTANDARD = "LVCMOS33"; +NET "discinP(3)" IOSTANDARD = "LVCMOS33"; + +# ADC I2C +NET "adcI2cScl" LOC = "AM3"; +NET "adcI2cSda" LOC = "AL3"; +NET "adcAS" LOC = "AJ6"; + +NET "adcI2cScl" IOSTANDARD = "LVCMOS33"; +NET "adcI2cSda" IOSTANDARD = "LVCMOS33"; +NET "adcAS" IOSTANDARD = "LVCMOS33"; + +NET "adcI2cScl" PULLUP; +NET "adcI2cSda" PULLUP; + +#-------------------------- IO Standard Constraints -------------------------- +#----------------------------------------------------------------------------- +# This section defines the IO types, IO delays and other IO parameters +#----------------------------------------------------------------------------- + +NET "iResetInL" IOSTANDARD = "LVCMOS33"; +NET "oDispClk" IOSTANDARD = "LVCMOS33"; +NET "oDispDat" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(1)" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(0)" IOSTANDARD = "LVCMOS33"; +NET "oDispRstL" IOSTANDARD = "LVCMOS33"; + +NET "serialin_p(0)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(0)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(1)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(1)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(2)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(2)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(3)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(3)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(4)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(4)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(5)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(5)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(6)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(6)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(7)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(7)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(8)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(8)" IOSTANDARD = "LVDS_25"; + +NET "serialin_p(11)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(11)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(12)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(12)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(13)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(13)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(14)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(14)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(15)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(15)" IOSTANDARD = "LVDS_25"; + +NET "serialout_p(0)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(0)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(1)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(1)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(2)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(2)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(3)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(3)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(4)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(4)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(5)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(5)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(6)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(6)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(7)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(7)" IOSTANDARD = "LVDS_25"; +NET "serialout(8)" IOSTANDARD = "LVCMOS33"; + +NET "serialout(8)" SLEW = "FAST"; + +NET "serialout_p(11)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(11)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(12)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(12)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(13)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(13)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(14)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(14)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(15)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(15)" IOSTANDARD = "LVDS_25"; diff --git a/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf.oldCosmic b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf.oldCosmic new file mode 100644 index 00000000..e7412378 --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.ucf.oldCosmic @@ -0,0 +1,219 @@ + +#----------------------------------------------------------------------------- +# Title : LCLS BNL ASIC Test FPGA, Constraints File +# Project : LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# File : HsioCosmic.ucf +# Author : Ryan Herbst, rherbst@slac.stanford.edu +# Created : 07/21/2008 +#----------------------------------------------------------------------------- +# Description: +# This file contains all of the user constraints required to implement the +# LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# Copyright (c) 2008 by Ryan Herbst. All rights reserved. +#----------------------------------------------------------------------------- +# Modification history +# 07/21/2008: created. +#----------------------------------------------------------------------------- + + +#----------------------------------------------------------------------------- +#-------------------------- Timing Constraints ------------------------------- +#----------------------------------------------------------------------------- +# This section contains the timing constraints for the FPGA +#----------------------------------------------------------------------------- + +# Define system clocks +NET pgpClk TNM_NET = FFS pgpClk; +NET sysClk125 TNM_NET = FFS sysClk125; +#NET clk320 TNM_NET = FFS clk320; +#NET sysClk250 TNM_NET = FFS sysClk250; +#NET mainClk TNM_NET = FFS mainClk; +INST "U_triggerlogic/thetdc/stopcontrol" RLOC_ORIGIN="X44Y117"; + +# Define system clocks +TIMESPEC TS_pgpClk = PERIOD pgpClk 6.4 ns HIGH 50%; +TIMESPEC TS_sysClk125 = PERIOD sysClk125 25.6 ns HIGH 50%; +#TIMESPEC TS_clk320 = PERIOD clk320 3.2 ns HIGH 50%; +#TIMESPEC TS_sysClk250 = PERIOD sysClk250 12.8 ns HIGH 50%; +#TIMESPEC TS_mainClk = PERIOD mainClk 6.4 ns HIGH 50%; + +# Define time groups for inter-clock constraints +TIMEGRP TG_pgpClk_r = RISING pgpClk; +TIMEGRP TG_sysClk125_r = RISING sysClk125; +#TIMEGRP TG_sysClk250_r = RISING sysClk250; +#TIMEGRP TG_mainClk_r = RISING mainClk; + +# Inter Domain Constraints +# TIMESPEC TS_pgpClk_r_sysClk125_r = FROM TG_pgpClk_r TO TG_sysClk125_r 6.4ns; +TIMESPEC TS_sysClk125_r_pgpClk_r = FROM TG_sysClk125_r TO TG_pgpClk_r 6.4ns; +#TIMESPEC TS_sysClk125_r_sysClk250_r = FROM TG_sysClk125_r TO TG_sysClk250_r 8ns; +# NET U_HsioFei4Core/go TIG; +NET U_HsioCosmicCore*/channelmask(*) TIG; +NET U_HsioCosmicCore*/channeloutmask(*) TIG; + +timespec ts_02 = from ffs(*bz(0):*cz(0):*dz(0):*dz(1)) to ffs 640 MHz; +#timespec ts_03 = from ffs(*fei4fifo*) to ffs(*fei4dataflag*) 6.4ns; +#timespec ts_04 = from rams(*fei4fifo*) to ffs(*fei4dataflag*) 6.4ns; + +# Nets to ignore for timing +NET "iResetInL" TIG; + +NET serialinb(?) maxskew = 250 ps ; +#NET U_HsioCosmicCore/deldata maxskew = 250 ps ; + +INST "U_HsioCosmicCore*/*receivedata/ff_*" IOB=FALSE; + + +# Nets to ignore for timing +NET "iResetInL" TIG; + + +#----------------------------------------------------------------------------- +#-------------------------- Pin Location Constraints ------------------------- +#----------------------------------------------------------------------------- +# This section contains the pin location constraints for the design +#----------------------------------------------------------------------------- +# Old P5 = New P5 +# Old P4 = New P4 +# Old P9 = New P3 +# Old P3 = New P2 + + +#NET "iPgpRefClkP" LOC = "J1"; +#NET "iPgpRefClkM" LOC = "K1"; +NET "iPgpRefClkP" LOC = "AP29"; +NET "iPgpRefClkM" LOC = "AP28"; +#NET "iMainClkP" LOC = "H17"; +#NET "iMainClkN" LOC = "J17"; +# fiber 1 +#NET "iMgtRxN" LOC = "N1"; +#NET "iMgtRxP" LOC = "M1"; +#NET "oMgtTxN" LOC = "T1"; +#NET "oMgtTxP" LOC = "R1"; +# fiber 2 +#NET "iMgtRxN2" LOC = "AA1"; +#NET "iMgtRxP2" LOC = "Y1"; +#NET "oMgtTxN2" LOC = "V1"; +#NET "oMgtTxP2" LOC = "U1"; +# fiber RTM 1 +#NET "iMgtRxN" LOC = "AP25"; +#NET "iMgtRxP" LOC = "AP26"; +#NET "oMgtTxN" LOC = "AP22"; +#NET "oMgtTxP" LOC = "AP23"; +# fiber RTM 2 +NET "iMgtRxN" LOC = "AP17"; +NET "iMgtRxP" LOC = "AP18"; +NET "oMgtTxN" LOC = "AP20"; +NET "oMgtTxP" LOC = "AP21"; +NET "oReload" LOC = "G16"; +NET "iResetInL" LOC = "AJ19"; +NET "oDispClk" LOC = "AG22"; +NET "oDispDat" LOC = "AJ22"; +NET "oDispLoadL(1)" LOC = "AK17"; +NET "oDispLoadL(0)" LOC = "Ak18"; +NET "oDispRstL" LOC = "AH22"; +#NET "rclk" LOC = "AM21"; +# fiber 1 +NET "transDis1" LOC = "AH4"; +NET "transDis1" IOSTANDARD="LVCMOS33"; +# fiber 2 +#NET "transDis2" LOC = "AK4"; +#NET "transDis2" IOSTANDARD="LVCMOS33"; + +NET "iExtreload" LOC = "L15"; +NET "iExtreload" IOSTANDARD="LVCMOS33"; +NET "iExtreload" PULLUP; + +#NET "refclk_p" LOC = "J25"; +#NET "refclk_p" IOSTANDARD="LVDS_25"; +#NET "refclk_n" LOC = "H25"; +#NET "refclk_n" IOSTANDARD="LVDS_25"; + +#NET "xclk_p" LOC = "E24"; +#NET "xclk_p" IOSTANDARD="LVDS_25"; +#NET "xclk_n" LOC = "F24"; +#NET "xclk_n" IOSTANDARD="LVDS_25"; + +#NET "clkout40" LOC = "AF21"; +NET "clkout40" LOC = "AF16"; +NET "clkout40" IOSTANDARD="LVCMOS33"; +NET "clkout40" SLEW="FAST"; + +NET "HITOR" LOC = "AL29"; +NET "HITOR" IOSTANDARD="LVCMOS33"; + + +NET "iHSIOtrigger(0)" LOC="J14"; +NET "iHSIOtrigger(0)" IOSTANDARD="LVTTL"; +NET "iHSIOtrigger(0)" SLEW=FAST; + +NET "iHSIOtrigger(1)" LOC="L14"; +NET "iHSIOtrigger(1)" IOSTANDARD="LVTTL"; +NET "iHSIOtrigger(1)" SLEW=FAST; + +NET "oHSIObusy" LOC="H19"; +NET "oHSIObusy" IOSTANDARD="LVTTL"; +NET "oHSIObusy" SLEW=FAST; + +#NET "oHSIOtrigger" LOC="L14"; +#NET "oHSIOtrigger" IOSTANDARD="LVTTL"; +#NET "oHSIOtrigger" SLEW=FAST; + +# Temperature ADC MAX145 +#NET "ADC_Data_in_p" LOC = "L4"; +#NET "ADC_Data_in_n" LOC = "L3"; +#NET "ADC_Clk_p" LOC = "T9"; +#NET "ADC_Clk_n" LOC = "R9"; +#NET "ADC_nCS_p" LOC = "U3"; +#NET "ADC_nCS_n" LOC = "T3"; + +# DI1 +#NET "oExttrgclkP" LOC = "AH15"; +#NET "oExttrgclkN" LOC = "AJ15"; +# DI3 +#NET "oExtbusyP" LOC = "AD14"; +#NET "oExtbusyN" LOC = "AC13"; +#DTO1 +#NET "iExttriggerP" LOC = "J31"; +#NET "iExttriggerN" LOC = "J30"; +# DTO3 +#NET "iExtrstP" LOC = "G30"; +#NET "iExtrstN" LOC = "F30"; + +NET "serialout(0)" LOC = "AE16"; +#NET "serialout(0)" LOC = "AL21"; + + +#NET "serialin(0)" LOC = "AK21"; +NET "serialin(0)" LOC = "AE18"; + +NET "discinP(0)" LOC = "AD7"; +NET "discinP(1)" LOC = "AD6"; +NET "discinP(2)" LOC = "AM6"; +NET "discinP(3)" LOC = "AG6"; + +NET "discinP(0)" IOSTANDARD = "LVCMOS33"; +NET "discinP(1)" IOSTANDARD = "LVCMOS33"; +NET "discinP(2)" IOSTANDARD = "LVCMOS33"; +NET "discinP(3)" IOSTANDARD = "LVCMOS33"; + +#-------------------------- IO Standard Constraints -------------------------- +#----------------------------------------------------------------------------- +# This section defines the IO types, IO delays and other IO parameters +#----------------------------------------------------------------------------- + +NET "iResetInL" IOSTANDARD = "LVCMOS33"; +NET "oDispClk" IOSTANDARD = "LVCMOS33"; +NET "oDispDat" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(1)" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(0)" IOSTANDARD = "LVCMOS33"; +NET "oDispRstL" IOSTANDARD = "LVCMOS33"; + +NET "serialin(0)" IOSTANDARD = "LVCMOS33"; + +NET "serialout(0)" IOSTANDARD = "LVCMOS33"; + +NET "serialout(0)" SLEW = "FAST"; + diff --git a/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd new file mode 120000 index 00000000..ead52a63 --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd @@ -0,0 +1 @@ +HsioCosmic.vhd.4core \ No newline at end of file diff --git a/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd.2core b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd.2core new file mode 100755 index 00000000..266f2a26 --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd.2core @@ -0,0 +1,786 @@ +------------------------------------------------------------------------------- +-- Title : BNL ASIC Test FGPA, Top Level +-- Project : LCLS Detector, BNL ASIC +------------------------------------------------------------------------------- +-- File : HsioCosmic.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 07/21/2008 +------------------------------------------------------------------------------- +-- Description: +-- Top level logic for BNL ASIC test FPGA. +------------------------------------------------------------------------------- +-- Copyright (c) 2008 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 07/21/2008: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +Library Unisim; +USE ieee. std_logic_1164.ALL; +use ieee. std_logic_arith.all; +use ieee. std_logic_unsigned.all; +USE work.ALL; + +entity HsioCosmic is + port ( + + -- PGP Crystal Clock Input, 156.25Mhz + iPgpRefClkP : in std_logic; + iPgpRefClkM : in std_logic; + + -- System clock 125 MHz clock input + iMainClkP : in std_logic; + iMainClkN : in std_logic; + + -- PGP Rx/Tx Lines + iMgtRxN : in std_logic; + iMgtRxP : in std_logic; + oMgtTxN : out std_logic; + oMgtTxP : out std_logic; + iMgtRxN2 : in std_logic; + iMgtRxP2 : in std_logic; + oMgtTxN2 : out std_logic; + oMgtTxP2 : out std_logic; + + -- ATLAS Pixel module pins + serialin : in std_logic_vector(15 downto 0); + serialout : out std_logic_vector(15 downto 0); + serialout_p : out std_logic_vector(15 downto 0); + serialout_n : out std_logic_vector(15 downto 0); + serialin_p : in std_logic_vector(15 downto 0); + serialin_n : in std_logic_vector(15 downto 0); + discinP : in std_logic_vector(3 downto 0); +-- discinN : in std_logic_vector(1 downto 0); + clkout40 : out std_logic; + refclk_p : out std_logic; + refclk_n : out std_logic; + xclk_p : out std_logic; + xclk_n : out std_logic; + + -- Reset button + iResetInL : in std_logic; + -- Reload firmware + oReload : out std_logic; + iExtreload : in std_logic; + -- LED Display + oDispClk : out std_logic; + oDispDat : out std_logic; + oDispLoadL : out std_logic_vector(1 downto 0); + oDispRstL : out std_logic; + + -- Debug + oDebug : out std_logic_vector(7 downto 0); + + -- Eudet trigger + iExttriggerP : in std_logic; + iExttriggerN : in std_logic; + iExtrstP : in std_logic; + iExtrstN : in std_logic; + oExtbusyP : out std_logic; + oExtbusyN : out std_logic; + oExttrgclkP : out std_logic; + oExttrgclkN : out std_logic; + + --HSIO trigger IF + iHSIOtrigger : in std_logic_vector(1 downto 0); + oHSIOtrigger : out std_logic; + oHSIObusy : out std_logic; + iHSIObusy : in std_logic; + + -- Eudet test + oExtrstP : out std_logic; + oExtrstN : out std_logic; + oExttriggerP : out std_logic; + oExttriggerN : out std_logic; + + + -- Misc Signals + oPdBuff0 : out std_logic; + oPdBuff1 : out std_logic; + oPdBuff3 : out std_logic; + oPdBuff4 : out std_logic; + oLemoA : out std_logic; + iLemoB : in std_logic; + + -- Transmitter enable + transDis1 : out std_logic; + transDis2 : out std_logic; + -- CMOS chip I/O + RD2 : out std_logic; + AuxClk : out std_logic; + RA : out std_logic; + RD1 : out std_logic; + IOMXIN : out std_logic_vector(3 downto 0); + IOMXSEL : out std_logic_vector(2 downto 0); + HITOR : in std_logic; + IOMXOUT : in std_logic_vector(2 downto 0); + SELALTBUS : out std_logic; + REGABDACLD : out std_logic; + REGABSTBLD : out std_logic; + SELCMD : out std_logic; + CMDEXTTRIGGER : out std_logic; + CMDALTPLS : out std_logic + ); +end HsioCosmic; + + +-- Define architecture for top level module +architecture HsioCosmic of HsioCosmic is + + -- Synthesis control attributes + attribute syn_useioff : boolean; + attribute syn_useioff of HsioCosmic : architecture is true; + attribute xc_fast_auto : boolean; + attribute xc_fast_auto of HsioCosmic : architecture is false; + attribute syn_noclockbuf : boolean; + attribute syn_noclockbuf of HsioCosmic : architecture is true; + + -- IO Pad components + component IBUF port ( O : out std_logic; I : in std_logic ); end component; + component OBUF port ( O : out std_logic; I : in std_logic ); end component; + component OBUFDS + generic( IOSTANDARD: STRING:= "LVDS_25"; + SLEW: STRING:="FAST"); + port ( O : out std_logic; OB : out std_logic; I : in std_logic ); + end component; + + -- Input LVDS with termination + component IBUFDS + generic ( DIFF_TERM : boolean := TRUE; + IOSTANDARD: STRING := "LVDS_25"); + port ( O : out std_logic; I : in std_logic; IB : in std_logic ); + end component; + + -- Xilinx global clock buffer component + component BUFGMUX + port ( + O : out std_logic; + I0 : in std_logic; + I1 : in std_logic; + S : in std_logic + ); + end component; + + component IDELAYCTRL + port ( RDY : out std_logic; + REFCLK : in std_logic; + RST : in std_logic + ); + end component; + +component IDELAY + generic (IOBDELAY_TYPE : string := "DEFAULT"; --(DEFAULT, FIXED, VARIABLE) + IOBDELAY_VALUE : integer := 0 --(0 to 63) + ); + port ( + O : out STD_LOGIC; + I : in STD_LOGIC; + C : in STD_LOGIC; + CE : in STD_LOGIC; + INC : in STD_LOGIC; + RST : in STD_LOGIC + ); +end component; + + + -- Local signals + signal resetInL : std_logic; + signal tmpClk250 : std_logic; + signal sysClk125 : std_logic; + signal sysRst125 : std_logic; + signal sysRst250 : std_logic; + signal sysClk250 : std_logic; + signal refClock : std_logic; + signal pgpClk : std_logic; + signal pgpClk90 : std_logic; + signal pgpReset : std_logic; + signal clk320 : std_logic; + signal reload : std_logic; + signal reload1 : std_logic; + signal reload2 : std_logic; + signal extreload : std_logic; + signal resetOut : std_logic; + signal resetOut1 : std_logic; + signal resetOut2 : std_logic; + signal mgtRxN : std_logic; + signal mgtRxP : std_logic; + signal mgtTxN : std_logic; + signal mgtTxP : std_logic; + signal mgtRxN2 : std_logic; + signal mgtRxP2 : std_logic; + signal mgtTxN2 : std_logic; + signal mgtTxP2 : std_logic; + signal dispClk : std_logic; + signal dispDat : std_logic; + signal dispLoadL : std_logic_vector(1 downto 0); + signal dispRstL : std_logic; + signal debug : std_logic_vector(7 downto 0); + signal sysClk125i : std_logic; + signal mainClk : std_logic; + signal clk0 : std_logic; + signal clkin : std_logic; + signal halfclock : std_logic; + signal quarterclock : std_logic; + signal clockidctrl : std_logic; + signal idctrlrst : std_logic; + signal RD2b : std_logic; + signal AuxClkb : std_logic; + signal RAb : std_logic; + signal RD1b : std_logic; + signal IOMXINb : std_logic_vector(3 downto 0); + signal IOMXSELb : std_logic_vector(2 downto 0); + signal HITORb : std_logic; + signal HITORout : std_logic; + signal IOMXOUTb : std_logic_vector(2 downto 0); + signal SELALTBUSb : std_logic; + signal REGABDACLDb : std_logic; + signal REGABSTBLDb : std_logic; + signal SELCMDb : std_logic; + signal CMDEXTTRIGGERb : std_logic; + signal CMDALTPLSb : std_logic; + signal exttrigger : std_logic; + signal exttriggerinv : std_logic; + signal extrst : std_logic; + signal extrstinv : std_logic; + signal exttriggero : std_logic; + signal extrsto : std_logic; + signal extbusy : std_logic; + signal extbusyinv : std_logic; + signal exttrgclk : std_logic; + signal exttrgclkinv : std_logic; + signal hsiobusyb : std_logic; + signal hsiobusyinb : std_logic; + signal hsiotriggerb : std_logic_vector(1 downto 0); + signal serialoutb : std_logic_vector(15 downto 0); + signal serialoutm1 : std_logic_vector(15 downto 0); + signal serialoutm2 : std_logic_vector(15 downto 0); + signal serialinb : std_logic_vector(15 downto 0); + signal serialinm1 : std_logic_vector(15 downto 0); + signal serialinm2 : std_logic_vector(15 downto 0); + signal discinb : std_logic_vector(3 downto 0); + signal ccontrol : std_logic_vector(35 downto 0); + signal cdata : std_logic_vector(31 downto 0); + signal ctrig : std_logic_vector(0 downto 0); + signal opgpClk : std_logic; + signal dispDatA : std_logic; + signal dispDatB : std_logic; + signal pgpDispA : std_logic_vector(7 downto 0); + signal pgpDispB : std_logic_vector(7 downto 0); + signal dispDigitA : std_logic_vector(7 downto 0); + signal dispDigitB : std_logic_vector(7 downto 0); + signal dispDigitC : std_logic_vector(7 downto 0); + signal dispDigitD : std_logic_vector(7 downto 0); + signal dispDigitE : std_logic_vector(7 downto 0); + signal dispDigitF : std_logic_vector(7 downto 0); + signal dispDigitG : std_logic_vector(7 downto 0); + signal dispDigitH : std_logic_vector(7 downto 0); + signal dispStrobe : std_logic; + signal dispUpdateA : std_logic; + signal dispUpdateB : std_logic; + signal sysClkCnt : std_logic_vector(15 downto 0); + signal lockedid : std_logic; + signal oldlockedid : std_logic; + signal holdrst : std_logic; + signal holdctr : std_logic_vector(24 downto 0); + signal idcounter : std_logic_vector(2 downto 0); + + signal pgpClkUnbuf : std_logic; + signal pgpClk90Unbuf : std_logic; + signal sysClkUnbuf : std_logic; + signal disc : std_logic_vector(4 downto 0); + + signal calibmode1 : std_logic_vector(1 downto 0); + signal calibmode2 : std_logic_vector(1 downto 0); + signal calibmode : std_logic_vector(1 downto 0); + signal eudaqdone : std_logic; + signal eudaqtrgword : std_logic_vector(14 downto 0); + signal trigenabled1 : std_logic; + signal trigenabled2 : std_logic; + signal trigenabled : std_logic; + signal paused1 : std_logic; + signal paused2 : std_logic; + signal paused : std_logic; + signal triggermask1 : std_logic_vector(15 downto 0); + signal triggermask2 : std_logic_vector(15 downto 0); + signal triggermask : std_logic_vector(15 downto 0); + signal resetdelay1 : std_logic; + signal resetdelay2 : std_logic; + signal resetdelay : std_logic; + signal incrementdelay1: std_logic_vector(4 downto 0); + signal incrementdelay2: std_logic_vector(4 downto 0); + signal incrementdelay: std_logic_vector(4 downto 0); + signal discop1 : std_logic_vector(15 downto 0); + signal discop2 : std_logic_vector(15 downto 0); + signal discop : std_logic_vector(15 downto 0); + signal telescopeop1 : std_logic_vector(2 downto 0); + signal telescopeop2 : std_logic_vector(2 downto 0); + signal telescopeop : std_logic_vector(2 downto 0); + signal period1 : std_logic_vector(31 downto 0); + signal period2 : std_logic_vector(31 downto 0); + signal period : std_logic_vector(31 downto 0); + signal fifothresh : std_logic; + signal fifothresh1 : std_logic; + signal fifothresh2 : std_logic; + signal serbusy1 : std_logic; + signal serbusy2 : std_logic; + signal serbusy : std_logic; + signal tdcreadoutbusy1: std_logic; + signal tdcreadoutbusy2: std_logic; + signal tdcreadoutbusy: std_logic; + signal tcounter1 : std_logic_vector(31 downto 0); + signal tcounter2 : std_logic_vector(31 downto 0); + signal l1a1 : std_logic; + signal l1a2 : std_logic; + signal l1a : std_logic; + signal triggerword : std_logic_vector(7 downto 0); + signal busy : std_logic; + signal rstFromCore1 : std_logic; + signal rstFromCore2 : std_logic; + signal rstFromCore : std_logic; + signal hitbus : std_logic_vector(1 downto 0); + signal present : std_logic_vector(1 downto 0); + signal phaseclksel : std_logic; + signal phaseclksel1 : std_logic; + signal phaseclksel2 : std_logic; + signal startmeas : std_logic; + signal startmeas1 : std_logic; + signal startmeas2 : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Reset input + U_ResetIn: IBUF port map ( I => iResetInL, O => resetInL ); + + -- PGP Clock Generator + U_PgpClkGen: entity work.PgpClkGen generic map ( + RefClkEn1 => "ENABLE", + RefClkEn2 => "DISABLE", + DcmClkSrc => "RefClk1", + UserFxDiv => 4, + UserFxMult => 2 + ) port map ( + pgpRefClkInP => iPgpRefClkP, + pgpRefClkInN => iPgpRefClkM, + ponResetL => resetInL, + locReset => resetOut, + pgpRefClk1 => refClock, + pgpRefClk2 => open, + pgpClk => pgpClk, + pgpClk90 => pgpClk90, + pgpReset => pgpReset, + clk320 => clk320, + pgpClkIn => pgpClk, + userClk => sysClk125, + userReset => sysRst125, + userClkIn => sysClk125, + pgpClkUnbuf => pgpClkUnbuf, + pgpClk90Unbuf => pgpClk90Unbuf, + locClkUnbuf => sysClkUnbuf + + + ); + + -- Generate Divided Clock, sample reset + process ( pgpClk ) begin + if rising_edge(pgpClk) then + tmpClk250 <= not tmpClk250 after tpd; + sysRst250 <= sysRst125 after tpd; + end if; + end process; + + -- Global Buffer For 125Mhz Clock + U_CLK125: BUFGMUX port map ( + O => sysClk250, + I0 => tmpClk250, + I1 => '0', + S => '0' + ); + + -- No Pads for MGT Lines + mgtRxN <= iMgtRxN; + mgtRxP <= iMgtRxP; + oMgtTxN <= mgtTxN; + oMgtTxP <= mgtTxP; + mgtRxN2 <= iMgtRxN2; + mgtRxP2 <= iMgtRxP2; + oMgtTxN2 <= mgtTxN2; + oMgtTxP2 <= mgtTxP2; + + -- LED Display + U_DispClk : OBUF port map ( I => dispClk , O => oDispClk ); + U_DispDat : OBUF port map ( I => dispDat , O => oDispDat ); + U_DispLoadL1 : OBUF port map ( I => dispLoadL(1) , O => oDispLoadL(1) ); + U_DispLoadL0 : OBUF port map ( I => dispLoadL(0) , O => oDispLoadL(0) ); + U_DispRstL : OBUF port map ( I => dispRstL , O => oDispRstL ); + U_reload : OBUF port map ( I => reload , O => oReload ); + U_clkout40 : OBUF port map ( I => sysClk125i , O => clkout40 ); + U_refclk : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => sysClk125i , O => refclk_p , OB => refclk_n ); + U_xclk : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => sysClk125i , O => xclk_p , OB => xclk_n ); + + U_transdis : OBUF port map ( I => '0' , O => transDis1 ); + U_transdis2 : OBUF port map ( I => '0' , O => transDis2 ); + + U_rd2 : OBUF port map ( I => RD2b , O => RD2); + U_auxclk : OBUF port map ( I => AuxClkb , O => AuxClk); + U_RA : OBUF port map ( I => RAb , O => RA ); + U_rd1 : OBUF port map ( I => RD1b , O => RD1 ); + U_IOMXIN3 : OBUF port map ( I => IOMXINb(3) , O => IOMXIN(3) ); + U_IOMXIN2 : OBUF port map ( I => IOMXINb(2) , O => IOMXIN(2) ); + U_IOMXIN1 : OBUF port map ( I => IOMXINb(1) , O => IOMXIN(1) ); + U_IOMXIN0 : OBUF port map ( I => IOMXINb(0) , O => IOMXIN(0) ); + U_IOMXSEL2 : OBUF port map ( I => IOMXSELb(2) , O => IOMXSEL(2) ); + U_IOMXSEL1 : OBUF port map ( I => IOMXSELb(1) , O => IOMXSEL(1) ); + U_IOMXSEL0 : OBUF port map ( I => IOMXSELb(0) , O => IOMXSEL(0) ); + U_HITOR : IBUF port map ( O => HITORb , I => HITOR); + U_IOMXOUT2 : IBUF port map ( O => IOMXOUTb(2) , I => IOMXOUT(2) ); + U_IOMXOUT1 : IBUF port map ( O => IOMXOUTb(1) , I => IOMXOUT(1) ); + U_IOMXOUT0 : IBUF port map ( O => IOMXOUTb(0) , I => IOMXOUT(0) ); + U_SELALTBUS : OBUF port map ( I => SELALTBUSb , O => SELALTBUS); + U_REGABDACLD : OBUF port map ( I => REGABDACLDb , O => REGABDACLD); + U_REGABSTBLD : OBUF port map ( I => REGABSTBLDb , O => REGABSTBLD); + U_SELCMD : OBUF port map ( I => SELCMDb , O => SELCMD ); + U_CMDEXTTRIGGER : OBUF port map ( I => CMDEXTTRIGGERb , O => CMDEXTTRIGGER ); + U_CMDALTPLS : OBUF port map ( I => CMDALTPLSb , O => CMDALTPLS ); + U_exttrgclk : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => exttrgclkinv , O => oExttrgclkP , OB => oExttrgclkN ); + exttrgclkinv<= not exttrgclk; + U_extbusy : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => extbusyinv , O => oExtBusyP , OB => oExtbusyN ); + extbusyinv<= not extbusy; + U_exttrigger : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => iExttriggerP , IB=>iExttriggerN , O => exttriggerinv ); + exttrigger<= not exttriggerinv; + U_extrst : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => iExtrstP , IB=>iExtrstN , O => extrstinv ); + extrst<= not extrstinv; + U_exttriggero : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => exttriggero , O => oExttriggerP , OB => oExttriggerN ); + + U_extrsto : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => extrsto , O => oExtrstP , OB => oExtrstN ); + + U_HSIObusy : OBUF port map ( I => hsiobusyb , O => oHSIObusy); + U_HSIOtriggero : OBUF port map ( I => l1a , O => oHSIOtrigger); + U_HSIOtrigger : IBUF port map ( O => hsiotriggerb(0) , I => iHSIOtrigger(0) ); + U_HSIOtrigger2 : IBUF port map ( O => hsiotriggerb(1) , I => iHSIOtrigger(1) ); + U_hsiobusyin : IBUF port map ( O => hsiobusyinb , I => iHSIObusy ); + U_extreload : IBUF port map ( O => extreload , I => iExtreload ); + + SERIAL_IO_DATA: + for I in 0 to 7 generate +-- U_serialin : IBUF port map ( I => serialin(I) , O => serialinb(I) ); + U_serialout_pn :OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => serialoutb(I) , O => serialout_p(I) , OB => serialout_n(I) ); + + U_serialin_pn : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => serialin_p(I) , IB=>serialin_n(I) , O => serialinb(I) ); + + end generate SERIAL_IO_DATA; + + U_serialout : OBUF port map ( I => serialoutb(8) , O => serialout(8) ); + U_serialin_pn_8 : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => serialin_p(8) , IB=>serialin_n(8) , O => serialinb(8) ); + +-- U_serialout11 : OBUF port map ( I => serialoutb(11) , O => serialout(11) ); +-- U_serialin11 : IBUF port map ( I => serialin(11) , O => serialinb(11) ); + SERIAL_IO_DATA_FEI3: + for I in 11 to 14 generate + U_serialout_pn :OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => serialoutb(I) , O => serialout_p(I) , OB => serialout_n(I) ); + + U_serialin_pn : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => serialin_p(I) , IB=>serialin_n(I) , O => serialinb(I) ); + + end generate SERIAL_IO_DATA_FEI3; + --DISC_1: IBUFDS port map ( O => discinb(0), I => discinP(0) , IB => discinN(0) ); + --DISC_2: IBUFDS port map ( O => discinb(1), I => discinP(1) , IB => discinN(1) ); + DISC_1: IBUF port map ( O => discinb(0), I => discinP(0) ); + DISC_2: IBUF port map ( O => discinb(1), I => discinP(1) ); + DISC_3: IBUF port map ( O => discinb(2), I => discinP(2) ); + DISC_4: IBUF port map ( O => discinb(3), I => discinP(3) ); + -- Display Controller A + U_DispCntrlA: entity work.DisplayControl port map ( + sysClk => sysClk125, sysRst => sysRst125, + dispStrobe => dispStrobe, dispUpdate => dispUpdateA, + dispRotate => "01", dispDigitA => dispDigitA, + dispDigitB => dispDigitB, dispDigitC => dispDigitC, + dispDigitD => dispDigitD, dispClk => dispClk, + dispDat => dispDatA, dispLoadL => dispLoadL(0), + dispRstL => dispRstL + ); + + -- Display Controller B + U_DispCntrlB: entity work.DisplayControl port map ( + sysClk => sysClk125, sysRst => sysRst125, + dispStrobe => dispStrobe, dispUpdate => dispUpdateB, + dispRotate => "01", dispDigitA => dispDigitE, + dispDigitB => dispDigitF, dispDigitC => dispDigitG, + dispDigitD => dispDigitH, dispClk => open, + dispDat => dispDatB, dispLoadL => dispLoadL(1), + dispRstL => open + ); + -- Output LED Data + dispDat <= dispDatA or dispDatB; + -- Generate display strobe (200ns) and update control + process ( sysClk125, sysRst125 ) begin + if sysRst125 = '1' then + sysClkCnt <= (others=>'0') after tpd; + dispStrobe <= '0' after tpd; + dispUpdateA <= '0' after tpd; + dispUpdateB <= '0' after tpd; + elsif rising_edge(sysClk125) then + + -- Display strobe, 320ns + dispStrobe <= sysClkCnt(4) after tpd; + + -- Update Display 0 + if sysClkCnt(15 downto 0) = x"8000" then + dispUpdateA <= '1' after tpd; + else + dispUpdateA <= '0' after tpd; + end if; + + -- Update Display B + if sysClkCnt(15 downto 0) = x"0000" then + dispUpdateB <= '1' after tpd; + else + dispUpdateB <= '0' after tpd; + end if; + + -- Update counter + sysClkCnt <= sysClkCnt + 1 after tpd; + + + end if; + end process; + + paused <= paused1 or paused2; + resetdelay <= resetdelay1 or resetdelay2; + incrementdelay <= incrementdelay1 or incrementdelay2; + serbusy <= (serbusy1 and present(0)) or (serbusy2 and present(1)); + tdcreadoutbusy<= tdcreadoutbusy1 or tdcreadoutbusy2; + rstFromCore <= rstFromCore1 or rstFromCore2; + + fifothresh <= (fifothresh1 and present(0)) or (fifothresh2 and present(1)); + trigenabled <= (trigenabled1 or not present(0)) and (trigenabled2 or not present(1)) and (present(0) or present(1)); + l1a1 <= l1a and present(0); + l1a2 <= l1a and present(1); + + serialinm1 <= x"000"&serialinb(3 downto 0); + serialinm2 <= x"000"&serialinb(7 downto 4); + serialoutb <= x"00" & serialoutm2(3 downto 0) & serialoutm1(3 downto 0); + + with present select discop <= discop2 when "10", discop1 when others; + with present select calibmode <= calibmode2 when "10", calibmode1 when others; + with present select triggermask <= triggermask2 when "10", triggermask1 when others; + with present select period <= period2 when "10", period1 when others; + with present select telescopeop <= telescopeop2 when "10", telescopeop1 when others; + with present select phaseclksel <= phaseclksel2 when "10", phaseclksel1 when others; + with present select startmeas <= startmeas2 when "10", startmeas1 when others; + + + U_triggerlogic: entity work.triggerlogic + port map( + clk => sysClk125, + rst => rstFromCore, + -- hardware inputs + discin => discinb, + hitbusin => hitbus, + -- HSIO trigger + HSIObusy => hsiobusyb, + HSIOtrigger => hsiotriggerb, + HSIObusyin => hsiobusyinb, + hitbusout => open, + + -- eudet trigger + exttrigger => exttrigger, + extrst => extrst, + extbusy => extbusy, + exttrgclk => exttrgclk, + + calibmode => calibmode, + startmeas => startmeas, + eudaqdone => eudaqdone, + eudaqtrgword => eudaqtrgword, + tcounter1 => tcounter1, + tcounter2 => tcounter2, + + trigenabled => trigenabled, + paused => paused, + triggermask => triggermask, + resetdelay => resetdelay, + incrementdelay => incrementdelay, + discop => discop, + telescopeop => telescopeop, + period => period, + fifothresh => fifothresh, + serbusy => serbusy, + tdcreadoutbusy => tdcreadoutbusy, + phaseclksel => phaseclksel, + l1a => l1a, + triggerword => triggerword, + busy =>busy, + coincd =>open +); + + reload <= reload1 and reload2 and extreload; -- active low + resetOut <= resetOut1 or resetOut2; + -- FPGA Core + U_HsioCosmicCore1: entity work.HsioPixelCore + generic map( framedFirstChannel=> 0, + framedLastChannel=> 3, + rawFirstChannel => 11, + rawLastChannel => 10, + buffersize => 16384, + bpmDefault => '0', + hitbusreadout => '0') + port map ( + sysClk250 => sysClk250, sysRst250 => sysRst250, + sysClk125 => sysClk125, sysRst125 => sysRst125, + refClock => refClock, pgpClk => pgpClk, + pgpClk90 => pgpClk90, pgpReset => pgpReset, + clk320 => clk320, reload => reload1, + mgtRxN => mgtRxN, + mgtRxP => mgtRxP, mgtTxN => mgtTxN, + mgtTxP => mgtTxP, serialin => serialinm1, + serialout => serialoutm1, clock160 => pgpClk, + clock80 => halfclock, clock40 => quarterclock, + resetOut => resetOut1, l1a => l1a1, + latchtriggerword => triggerword, tcounter1=>tcounter1, + tcounter2 => tcounter2, busy =>busy, + eudaqdone => eudaqdone, eudaqtrgword => eudaqtrgword, + calibmodeout => calibmode1, startmeas => startmeas1, + pausedout => paused1, present => present(0), + trgenabledout => trigenabled1, rstFromCore => rstFromCore1, + fifothresh => fifothresh1, triggermask => triggermask1, + discop => discop1, period => period1, + telescopeop => telescopeop1, resetdelay => resetdelay1, + incrementdelay => incrementdelay1, + sbusy => serbusy1, tdcbusy => tdcreadoutbusy1, + phaseclksel => phaseclksel1 , hitbus => hitbus(0), + debug => debug, + exttriggero => exttriggero, extrsto => extrsto, + doricreset => open, + dispDigitA => dispDigitE, dispDigitB => dispDigitF, + dispDigitC => dispDigitG, dispDigitD => dispDigitH, + dispDigitE => open, dispDigitF => open, + dispDigitG => open, dispDigitH => open, + pgpClkUnbuf => pgpClkUnbuf, pgpClk90Unbuf => pgpClk90Unbuf, + sysClkUnbuf => sysClkUnbuf + ); + U_HsioCosmicCore2: entity work.HsioPixelCore + generic map( framedFirstChannel=> 0, + framedLastChannel=> 3, + rawFirstChannel => 11, + rawLastChannel => 10, + buffersize => 16384, + bpmDefault => '0', + hitbusreadout => '0') + port map ( + sysClk250 => sysClk250, sysRst250 => sysRst250, + sysClk125 => sysClk125, sysRst125 => sysRst125, + refClock => refClock, pgpClk => pgpClk, + pgpClk90 => pgpClk90, pgpReset => pgpReset, + clk320 => clk320, reload => reload2, + mgtRxN => mgtRxN2, + mgtRxP => mgtRxP2, mgtTxN => mgtTxN2, + mgtTxP => mgtTxP2, serialin => serialinm2, + serialout => serialoutm2, clock160 => pgpClk, + clock80 => halfclock, clock40 => quarterclock, + resetOut => resetOut2, + l1a => l1a2, latchtriggerword => triggerword, + tcounter1=>tcounter1, tcounter2=>tcounter2, + busy =>busy, + eudaqdone => eudaqdone, eudaqtrgword => eudaqtrgword, + calibmodeout => calibmode2, startmeas => startmeas2, + pausedout => paused2, present => present(1), + trgenabledout => trigenabled2, rstFromCore => rstFromCore2, + fifothresh => fifothresh2, triggermask => triggermask2, + discop => discop2, period => period2, + telescopeop => telescopeop2, resetdelay => resetdelay2, + incrementdelay => incrementdelay2, + sbusy => serbusy2, tdcbusy => tdcreadoutbusy2, + phaseclksel=>phaseclksel2, hitbus => hitbus(1), + debug => open, + exttriggero => open, extrsto => open, + doricreset => open, + dispDigitA => dispDigitA, dispDigitB => dispDigitB, + dispDigitC => dispDigitC, dispDigitD => dispDigitD, + dispDigitE => open, dispDigitF => open, + dispDigitG => open, dispDigitH => open, + pgpClkUnbuf => pgpClkUnbuf, pgpClk90Unbuf => pgpClk90Unbuf, + sysClkUnbuf => sysClkUnbuf + ); + sysClk125i <= not sysClk125; + --sysClk125i<=debug(0); + U_clock160: entity work.clock160 port map( + CLKIN_N_IN => iMainClkN, + CLKIN_P_IN => iMainClkP, + RST_IN => sysRst125, + CLKFX_OUT => mainClk, + CLKIN_IBUFGDS_OUT => clkin, + CLK0_OUT => clk0, + LOCKED_OUT => open); + + process(mainClk) + begin + if(mainClk'event and mainClk='1') then + halfclock<= not halfclock; + end if; + end process; + process(halfclock) + begin + if(halfclock'event and halfclock='1') then + quarterclock<= not quarterclock; + end if; + end process; + U_idelctrlclk: entity work.clock200 port map( + CLKIN_IN => mainClk, + RST_IN => holdrst, + CLKFX_OUT => clockidctrl, + CLK0_OUT => open, + LOCKED_OUT => lockedid); + U_idelayctrl: IDELAYCTRL port map( + RDY => open, + REFCLK => clockidctrl, + RST => idctrlrst); + + process(sysRst125, sysClk125) -- clock interface + begin + if (sysRst125='1') then + holdctr<=(others=>'1'); + holdrst<='1'; + elsif(sysClk125'event and sysClk125='1') then + if (holdctr(24)='0') then + holdrst<='0'; + end if; + holdctr<=unsigned(holdctr)-1; + end if; + end process; + + process(sysClk125, sysRst125) -- reset logic for IDELAYCTRL + begin + if(sysRst125='1') then + idctrlrst<='0'; + idcounter<="000"; + oldlockedid<='0'; + elsif(sysClk125'event and sysClk125='1') then + if(lockedid='1' and oldlockedid='0')then + idcounter<="111"; + idctrlrst<='1'; + elsif(unsigned(idcounter)>0)then + idcounter<=unsigned(idcounter)-1; + else + idctrlrst<='0'; + end if; + oldlockedid<=lockedid; + end if; + end process; + +end HsioCosmic; diff --git a/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd.4core b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd.4core new file mode 100755 index 00000000..7ec9f154 --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd.4core @@ -0,0 +1,986 @@ +------------------------------------------------------------------------------- +-- Title : HsioCosmic, Top Level +-- Project : ATLAS Pixel Detector +------------------------------------------------------------------------------- +-- File : HsioCosmic.vhd +-- Author : Martin Kocian, kocian@slac.stanford.edu +-- Created : 2009 +------------------------------------------------------------------------------- +-- Description: +-- Top level logic for cosmic interface board +------------------------------------------------------------------------------- +-- Copyright (c) 2009 by Martin Kocian. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 07/21/2008: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +Library Unisim; +USE ieee. std_logic_1164.ALL; +use ieee. std_logic_arith.all; +use ieee. std_logic_unsigned.all; +USE work.ALL; +use work.StdRtlPkg.all; + +entity HsioCosmic is + port ( + + -- PGP Crystal Clock Input, 156.25Mhz + iPgpRefClkP : in std_logic; + iPgpRefClkM : in std_logic; + + -- System clock 125 MHz clock input + iMainClkP : in std_logic; + iMainClkN : in std_logic; + + -- PGP Rx/Tx Lines + iMgtRxN : in std_logic_vector(3 downto 0); + iMgtRxP : in std_logic_vector(3 downto 0); + oMgtTxN : out std_logic_vector(3 downto 0); + oMgtTxP : out std_logic_vector(3 downto 0); + + -- ATLAS Pixel module pins + serialin : in std_logic_vector(15 downto 0); + serialout : out std_logic_vector(15 downto 0); + serialout_p : out std_logic_vector(15 downto 0); + serialout_n : out std_logic_vector(15 downto 0); + serialin_p : in std_logic_vector(15 downto 0); + serialin_n : in std_logic_vector(15 downto 0); + discinP : in std_logic_vector(3 downto 0); +-- discinN : in std_logic_vector(1 downto 0); + clkout40 : out std_logic; + refclk_p : out std_logic; + refclk_n : out std_logic; + xclk_p : out std_logic; + xclk_n : out std_logic; + + -- Reset button + iResetInL : in std_logic; + -- Reload firmware + oReload : out std_logic; + iExtreload : in std_logic; + -- LED Display + oDispClk : out std_logic; + oDispDat : out std_logic; + oDispLoadL : out std_logic_vector(1 downto 0); + oDispRstL : out std_logic; + + -- Temperature ADC + adcI2cScl: inout std_logic; + adcI2cSda: inout std_logic; + adcAS: out std_logic; + + -- Debug + oDebug : out std_logic_vector(7 downto 0); + + -- Eudet trigger + iExttriggerP : in std_logic; + iExttriggerN : in std_logic; + iExtrstP : in std_logic; + iExtrstN : in std_logic; + oExtbusyP : out std_logic; + oExtbusyN : out std_logic; + oExttrgclkP : out std_logic; + oExttrgclkN : out std_logic; + + --HSIO trigger IF + iHSIOtrigger : in std_logic_vector(1 downto 0); + oHSIOtrigger : out std_logic; + oHSIObusy : out std_logic; + iHSIObusy : in std_logic; + + -- Eudet test + oExtrstP : out std_logic; + oExtrstN : out std_logic; + oExttriggerP : out std_logic; + oExttriggerN : out std_logic; + + + -- Misc Signals + oPdBuff0 : out std_logic; + oPdBuff1 : out std_logic; + oPdBuff3 : out std_logic; + oPdBuff4 : out std_logic; + oLemoA : out std_logic; + iLemoB : in std_logic; + + -- Transmitter enable + transDis : out std_logic_vector(3 downto 0); + -- CMOS chip I/O + RD2 : out std_logic; + AuxClk : out std_logic; + RA : out std_logic; + RD1 : out std_logic; + IOMXIN : out std_logic_vector(3 downto 0); + IOMXSEL : out std_logic_vector(2 downto 0); + HITOR : in std_logic; + IOMXOUT : in std_logic_vector(2 downto 0); + SELALTBUS : out std_logic; + REGABDACLD : out std_logic; + REGABSTBLD : out std_logic; + SELCMD : out std_logic; + CMDEXTTRIGGER : out std_logic; + CMDALTPLS : out std_logic + ); +end HsioCosmic; + + +-- Define architecture for top level module +architecture HsioCosmic of HsioCosmic is + + -- Synthesis control attributes + attribute syn_useioff : boolean; + attribute syn_useioff of HsioCosmic : architecture is true; + attribute xc_fast_auto : boolean; + attribute xc_fast_auto of HsioCosmic : architecture is false; + attribute syn_noclockbuf : boolean; + attribute syn_noclockbuf of HsioCosmic : architecture is true; + + -- IO Pad components + component IBUF port ( O : out std_logic; I : in std_logic ); end component; + component OBUF port ( O : out std_logic; I : in std_logic ); end component; + component OBUFDS + generic( IOSTANDARD: STRING:= "LVDS_25"; + SLEW: STRING:="FAST"); + port ( O : out std_logic; OB : out std_logic; I : in std_logic ); + end component; + + -- Input LVDS with termination + component IBUFDS + generic ( DIFF_TERM : boolean := TRUE; + IOSTANDARD: STRING := "LVDS_25"); + port ( O : out std_logic; I : in std_logic; IB : in std_logic ); + end component; + + -- Xilinx global clock buffer component + component BUFGMUX + port ( + O : out std_logic; + I0 : in std_logic; + I1 : in std_logic; + S : in std_logic + ); + end component; + + component IDELAYCTRL + port ( RDY : out std_logic; + REFCLK : in std_logic; + RST : in std_logic + ); + end component; + +component IDELAY + generic (IOBDELAY_TYPE : string := "DEFAULT"; --(DEFAULT, FIXED, VARIABLE) + IOBDELAY_VALUE : integer := 0 --(0 to 63) + ); + port ( + O : out STD_LOGIC; + I : in STD_LOGIC; + C : in STD_LOGIC; + CE : in STD_LOGIC; + INC : in STD_LOGIC; + RST : in STD_LOGIC + ); +end component; + + + -- Local signals + signal resetInL : std_logic; + signal tmpClk250 : std_logic; + signal sysClk125 : std_logic; + signal sysRst125 : std_logic; + signal sysRst250 : std_logic; + signal sysClk250 : std_logic; + signal refClock : std_logic; + signal pgpClk : std_logic; + signal pgpClk90 : std_logic; + signal pgpReset : std_logic; + signal clk320 : std_logic; + signal reload : std_logic; + signal reloadc : std_logic_vector(3 downto 0); + signal extreload : std_logic; + signal resetOut : std_logic; + signal resetOutc : std_logic_vector(3 downto 0); + signal dispClk : std_logic; + signal dispDat : std_logic; + signal dispLoadL : std_logic_vector(1 downto 0); + signal dispRstL : std_logic; + signal debug : std_logic_vector(7 downto 0); + signal sysClk125i : std_logic; + signal mainClk : std_logic; + signal clk0 : std_logic; + signal clkin : std_logic; + signal halfclock : std_logic; + signal quarterclock : std_logic; + signal clockidctrl : std_logic; + signal idctrlrst : std_logic; + signal RD2b : std_logic; + signal AuxClkb : std_logic; + signal RAb : std_logic; + signal RD1b : std_logic; + signal IOMXINb : std_logic_vector(3 downto 0); + signal IOMXSELb : std_logic_vector(2 downto 0); + signal HITORb : std_logic; + signal HITORout : std_logic; + signal IOMXOUTb : std_logic_vector(2 downto 0); + signal SELALTBUSb : std_logic; + signal REGABDACLDb : std_logic; + signal REGABSTBLDb : std_logic; + signal SELCMDb : std_logic; + signal CMDEXTTRIGGERb : std_logic; + signal CMDALTPLSb : std_logic; + signal exttrigger : std_logic; + signal exttriggerinv : std_logic; + signal extrst : std_logic; + signal extrstinv : std_logic; + signal exttriggero : std_logic; + signal extrsto : std_logic; + signal extbusy : std_logic; + signal extbusyinv : std_logic; + signal exttrgclk : std_logic; + signal exttrgclkinv : std_logic; + signal hsiobusyb : std_logic; + signal hsiobusyinb : std_logic; + signal hsiotriggerb : std_logic_vector(1 downto 0); + signal serialoutb : std_logic_vector(15 downto 0); + signal serialoutm1 : std_logic_vector(15 downto 0); + signal serialoutm2 : std_logic_vector(15 downto 0); + signal serialinb : std_logic_vector(15 downto 0); + signal serialinm1 : std_logic_vector(15 downto 0); + signal serialinm2 : std_logic_vector(15 downto 0); + signal discinb : std_logic_vector(3 downto 0); + signal ccontrol : std_logic_vector(35 downto 0); + signal cdata : std_logic_vector(31 downto 0); + signal ctrig : std_logic_vector(0 downto 0); + signal opgpClk : std_logic; + signal dispDatA : std_logic; + signal dispDatB : std_logic; + signal pgpDispA : std_logic_vector(7 downto 0); + signal pgpDispB : std_logic_vector(7 downto 0); + signal dispDigitA : std_logic_vector(7 downto 0); + signal dispDigitB : std_logic_vector(7 downto 0); + signal dispDigitC : std_logic_vector(7 downto 0); + signal dispDigitD : std_logic_vector(7 downto 0); + signal dispDigitE : std_logic_vector(7 downto 0); + signal dispDigitF : std_logic_vector(7 downto 0); + signal dispDigitG : std_logic_vector(7 downto 0); + signal dispDigitH : std_logic_vector(7 downto 0); + signal dispStrobe : std_logic; + signal dispUpdateA : std_logic; + signal dispUpdateB : std_logic; + signal sysClkCnt : std_logic_vector(15 downto 0); + signal lockedid : std_logic; + signal oldlockedid : std_logic; + signal holdrst : std_logic; + signal holdctr : std_logic_vector(24 downto 0); + signal idcounter : std_logic_vector(2 downto 0); + + signal pgpClkUnbuf : std_logic; + signal pgpClk90Unbuf : std_logic; + signal sysClkUnbuf : std_logic; + signal disc : std_logic_vector(4 downto 0); + + signal calibmodec : Slv2Array(0 to 3); + signal calibmode : std_logic_vector(1 downto 0); + signal eudaqdone : std_logic; + signal eudaqtrgword : std_logic_vector(14 downto 0); + signal trigenabledc : std_logic_vector(3 downto 0); + signal trigenabled : std_logic; + signal pausedc : std_logic_vector(3 downto 0); + signal paused : std_logic; + signal triggermaskc : Slv16Array(0 to 3); + signal triggermask : std_logic_vector(15 downto 0); + signal resetdelayc : std_logic_vector(3 downto 0); + signal resetdelay : std_logic; + signal incrementdelayc: Slv5Array(0 to 3); + signal incrementdelay: std_logic_vector(4 downto 0); + signal discopc : Slv16Array(0 to 3); + signal discop : std_logic_vector(15 downto 0); + signal telescopeopc : Slv3Array(0 to 3); + signal telescopeop : std_logic_vector(2 downto 0); + signal periodc : Slv32Array(0 to 3); + signal period : std_logic_vector(31 downto 0); + signal fifothreshc : std_logic_vector(3 downto 0); + signal fifothresh : std_logic; + signal serbusyc : std_logic_vector(3 downto 0); + signal serbusy : std_logic; + signal tdcreadoutbusyc: std_logic_vector(3 downto 0); + signal tdcreadoutbusy: std_logic; + signal tcounter1 : std_logic_vector(31 downto 0); + signal tcounter2 : std_logic_vector(31 downto 0); + signal l1ac : std_logic_vector(3 downto 0); + signal l1a : std_logic; + signal triggerword : std_logic_vector(7 downto 0); + signal busy : std_logic; + signal rstFromCorec : std_logic_vector(3 downto 0); + signal rstFromCore : std_logic; + signal hitbus : std_logic_vector(3 downto 0); + signal present : std_logic_vector(3 downto 0); + signal phaseclkselc : std_logic_vector(3 downto 0); + signal phaseclksel : std_logic; + signal startmeasc : std_logic_vector(3 downto 0); + signal startmeas : std_logic; + signal dispDigitAA : Slv8Array(0 to 3); + signal dispDigitBB : Slv8Array(0 to 3); + signal dispDigitCC : Slv8Array(0 to 3); + signal dispDigitDD : Slv8Array(0 to 3); + signal transdissig : std_logic_vector(3 downto 0); + signal trigAdc : sl; + signal trigAdcc : slv(3 downto 0); + signal sendAdcData : sl; + type adcarray is array(3 downto 0) of Slv16Array(11 downto 0); + signal adcDatachan : adcarray; + signal adcData : Slv16Array(11 downto 0); + signal phasebusySelc : Slv2Array(3 downto 0); + signal phasebusySel : slv(1 downto 0); + signal phasebusyEnc : slv(3 downto 0); + signal phasebusyEn : sl; + + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Reset input + U_ResetIn: IBUF port map ( I => iResetInL, O => resetInL ); + + -- PGP Clock Generator + U_PgpClkGen: entity work.PgpClkGen generic map ( + RefClkEn1 => "ENABLE", + RefClkEn2 => "DISABLE", + DcmClkSrc => "RefClk1", + UserFxDiv => 4, + UserFxMult => 2 + ) port map ( + pgpRefClkInP => iPgpRefClkP, + pgpRefClkInN => iPgpRefClkM, + ponResetL => resetInL, + locReset => resetOut, + pgpRefClk1 => refClock, + pgpRefClk2 => open, + pgpClk => pgpClk, + pgpClk90 => pgpClk90, + pgpReset => pgpReset, + clk320 => clk320, + pgpClkIn => pgpClk, + userClk => sysClk125, + userReset => sysRst125, + userClkIn => sysClk125, + pgpClkUnbuf => pgpClkUnbuf, + pgpClk90Unbuf => pgpClk90Unbuf, + locClkUnbuf => sysClkUnbuf + + + ); + + -- Generate Divided Clock, sample reset + process ( pgpClk ) begin + if rising_edge(pgpClk) then + tmpClk250 <= not tmpClk250 after tpd; + sysRst250 <= sysRst125 after tpd; + end if; + end process; + + -- Global Buffer For 125Mhz Clock + U_CLK125: BUFGMUX port map ( + O => sysClk250, + I0 => tmpClk250, + I1 => '0', + S => '0' + ); + + -- LED Display + U_DispClk : OBUF port map ( I => dispClk , O => oDispClk ); + U_DispDat : OBUF port map ( I => dispDat , O => oDispDat ); + U_DispLoadL1 : OBUF port map ( I => dispLoadL(1) , O => oDispLoadL(1) ); + U_DispLoadL0 : OBUF port map ( I => dispLoadL(0) , O => oDispLoadL(0) ); + U_DispRstL : OBUF port map ( I => dispRstL , O => oDispRstL ); + U_reload : OBUF port map ( I => reload , O => oReload ); + U_clkout40 : OBUF port map ( I => sysClk125i , O => clkout40 ); + U_refclk : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => sysClk125i , O => refclk_p , OB => refclk_n ); + U_xclk : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => sysClk125i , O => xclk_p , OB => xclk_n ); + + TRANSDISGEN: + for I in 0 to 3 generate + U_transdis : OBUF port map ( I => transdissig(I) , O => transDis(I) ); + end generate TRANSDISGEN; + + U_rd2 : OBUF port map ( I => RD2b , O => RD2); + U_auxclk : OBUF port map ( I => AuxClkb , O => AuxClk); + U_RA : OBUF port map ( I => RAb , O => RA ); + U_rd1 : OBUF port map ( I => RD1b , O => RD1 ); + U_IOMXIN3 : OBUF port map ( I => IOMXINb(3) , O => IOMXIN(3) ); + U_IOMXIN2 : OBUF port map ( I => IOMXINb(2) , O => IOMXIN(2) ); + U_IOMXIN1 : OBUF port map ( I => IOMXINb(1) , O => IOMXIN(1) ); + U_IOMXIN0 : OBUF port map ( I => IOMXINb(0) , O => IOMXIN(0) ); + U_IOMXSEL2 : OBUF port map ( I => IOMXSELb(2) , O => IOMXSEL(2) ); + U_IOMXSEL1 : OBUF port map ( I => IOMXSELb(1) , O => IOMXSEL(1) ); + U_IOMXSEL0 : OBUF port map ( I => IOMXSELb(0) , O => IOMXSEL(0) ); + U_HITOR : IBUF port map ( O => HITORb , I => HITOR); + U_IOMXOUT2 : IBUF port map ( O => IOMXOUTb(2) , I => IOMXOUT(2) ); + U_IOMXOUT1 : IBUF port map ( O => IOMXOUTb(1) , I => IOMXOUT(1) ); + U_IOMXOUT0 : IBUF port map ( O => IOMXOUTb(0) , I => IOMXOUT(0) ); + U_SELALTBUS : OBUF port map ( I => SELALTBUSb , O => SELALTBUS); + U_REGABDACLD : OBUF port map ( I => REGABDACLDb , O => REGABDACLD); + U_REGABSTBLD : OBUF port map ( I => REGABSTBLDb , O => REGABSTBLD); + U_SELCMD : OBUF port map ( I => SELCMDb , O => SELCMD ); + U_CMDEXTTRIGGER : OBUF port map ( I => CMDEXTTRIGGERb , O => CMDEXTTRIGGER ); + U_CMDALTPLS : OBUF port map ( I => CMDALTPLSb , O => CMDALTPLS ); + U_exttrgclk : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => exttrgclkinv , O => oExttrgclkP , OB => oExttrgclkN ); + exttrgclkinv<= not exttrgclk; + U_extbusy : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => extbusyinv , O => oExtBusyP , OB => oExtbusyN ); + extbusyinv<= not extbusy; + U_exttrigger : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => iExttriggerP , IB=>iExttriggerN , O => exttriggerinv ); + exttrigger<= not exttriggerinv; + U_extrst : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => iExtrstP , IB=>iExtrstN , O => extrstinv ); + extrst<= not extrstinv; + U_exttriggero : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => exttriggero , O => oExttriggerP , OB => oExttriggerN ); + + U_extrsto : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => extrsto , O => oExtrstP , OB => oExtrstN ); + + U_HSIObusy : OBUF port map ( I => hsiobusyb , O => oHSIObusy); + U_HSIOtriggero : OBUF port map ( I => l1a , O => oHSIOtrigger); + U_HSIOtrigger : IBUF port map ( O => hsiotriggerb(0) , I => iHSIOtrigger(0) ); + U_HSIOtrigger2 : IBUF port map ( O => hsiotriggerb(1) , I => iHSIOtrigger(1) ); + U_hsiobusyin : IBUF port map ( O => hsiobusyinb , I => iHSIObusy ); + U_extreload : IBUF port map ( O => extreload , I => iExtreload ); + + SERIAL_IO_DATA: + for I in 0 to 7 generate +-- U_serialin : IBUF port map ( I => serialin(I) , O => serialinb(I) ); + U_serialout_pn :OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => serialoutb(I) , O => serialout_p(I) , OB => serialout_n(I) ); + + U_serialin_pn : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => serialin_p(I) , IB=>serialin_n(I) , O => serialinb(I) ); + + end generate SERIAL_IO_DATA; + + U_serialout : OBUF port map ( I => serialoutb(8) , O => serialout(8) ); + U_serialin_pn_8 : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => serialin_p(8) , IB=>serialin_n(8) , O => serialinb(8) ); + +-- U_serialout11 : OBUF port map ( I => serialoutb(11) , O => serialout(11) ); +-- U_serialin11 : IBUF port map ( I => serialin(11) , O => serialinb(11) ); + SERIAL_IO_DATA_FEI3: + for I in 11 to 14 generate + U_serialout_pn :OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => serialoutb(I) , O => serialout_p(I) , OB => serialout_n(I) ); + + U_serialin_pn : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => serialin_p(I) , IB=>serialin_n(I) , O => serialinb(I) ); + + end generate SERIAL_IO_DATA_FEI3; + --DISC_1: IBUFDS port map ( O => discinb(0), I => discinP(0) , IB => discinN(0) ); + --DISC_2: IBUFDS port map ( O => discinb(1), I => discinP(1) , IB => discinN(1) ); + DISC_1: IBUF port map ( O => discinb(0), I => discinP(0) ); + DISC_2: IBUF port map ( O => discinb(1), I => discinP(1) ); + DISC_3: IBUF port map ( O => discinb(2), I => discinP(2) ); + DISC_4: IBUF port map ( O => discinb(3), I => discinP(3) ); + -- Display Controller A + U_DispCntrlA: entity work.DisplayControl port map ( + sysClk => sysClk125, sysRst => sysRst125, + dispStrobe => dispStrobe, dispUpdate => dispUpdateA, + dispRotate => "01", dispDigitA => dispDigitA, + dispDigitB => dispDigitB, dispDigitC => dispDigitC, + dispDigitD => dispDigitD, dispClk => dispClk, + dispDat => dispDatA, dispLoadL => dispLoadL(0), + dispRstL => dispRstL + ); + + -- Display Controller B + U_DispCntrlB: entity work.DisplayControl port map ( + sysClk => sysClk125, sysRst => sysRst125, + dispStrobe => dispStrobe, dispUpdate => dispUpdateB, + dispRotate => "01", dispDigitA => dispDigitE, + dispDigitB => dispDigitF, dispDigitC => dispDigitG, + dispDigitD => dispDigitH, dispClk => open, + dispDat => dispDatB, dispLoadL => dispLoadL(1), + dispRstL => open + ); + -- Output LED Data + dispDat <= dispDatA or dispDatB; + -- Generate display strobe (200ns) and update control + process ( sysClk125, sysRst125 ) begin + if sysRst125 = '1' then + sysClkCnt <= (others=>'0') after tpd; + dispStrobe <= '0' after tpd; + dispUpdateA <= '0' after tpd; + dispUpdateB <= '0' after tpd; + elsif rising_edge(sysClk125) then + + -- Display strobe, 320ns + dispStrobe <= sysClkCnt(4) after tpd; + + -- Update Display 0 + if sysClkCnt(15 downto 0) = x"8000" then + dispUpdateA <= '1' after tpd; + else + dispUpdateA <= '0' after tpd; + end if; + + -- Update Display B + if sysClkCnt(15 downto 0) = x"0000" then + dispUpdateB <= '1' after tpd; + else + dispUpdateB <= '0' after tpd; + end if; + + -- Update counter + sysClkCnt <= sysClkCnt + 1 after tpd; + + + end if; + end process; + + paused <= uOr(pausedc); + resetdelay <= uOr(resetdelayc); + incrementdelay <= incrementdelayc(0) or incrementdelayc(1) or incrementdelayc (2) or incrementdelayc(3); + serbusy <= uOr(serbusyc and present); + tdcreadoutbusy<= uOr(tdcreadoutbusyc); + rstFromCore <= uOr(rstFromCorec); + + fifothresh <= uOr(fifothreshc and present); + trigenabled <= uAnd(trigenabledc or not present) and uOr(present); + trigAdc <= uOr(trigAdcc and present); + + reload <= uAnd(reloadc) and extreload; -- active low + resetOut <= uOr(resetOutc); + phasebusyEn <= uOr(phasebusyEnc); + phasebusySel <= phasebusySelc(0) or phasebusySelc(1) or phasebusySelc(2) or phasebusySelc(3); + + process(present, discopc) begin + if(present(0)='1')then discop<=discopc(0); + elsif(present(1)='1')then discop<=discopc(1); + elsif(present(2)='1')then discop<=discopc(2); + else discop<=discopc(3); + end if; + end process; + + process(present, calibmodec) begin + if(present(0)='1')then calibmode<=calibmodec(0); + elsif(present(1)='1')then calibmode<=calibmodec(1); + elsif(present(2)='1')then calibmode<=calibmodec(2); + else calibmode<=calibmodec(3); + end if; + end process; + + process(present, triggermaskc) begin + if(present(0)='1')then triggermask<=triggermaskc(0); + elsif(present(1)='1')then triggermask<=triggermaskc(1); + elsif(present(2)='1')then triggermask<=triggermaskc(2); + else triggermask<=triggermaskc(3); + end if; + end process; + + process(present, periodc) begin + if(present(0)='1')then period<=periodc(0); + elsif(present(1)='1')then period<=periodc(1); + elsif(present(2)='1')then period<=periodc(2); + else period<=periodc(3); + end if; + end process; + + process(present, telescopeopc) begin + if(present(0)='1')then telescopeop<=telescopeopc(0); + elsif(present(1)='1')then telescopeop<=telescopeopc(1); + elsif(present(2)='1')then telescopeop<=telescopeopc(2); + else telescopeop<=telescopeopc(3); + end if; + end process; + + process(present, phaseclkselc) begin + if(present(0)='1')then phaseclksel<=phaseclkselc(0); + elsif(present(1)='1')then phaseclksel<=phaseclkselc(1); + elsif(present(2)='1')then phaseclksel<=phaseclkselc(2); + else phaseclksel<=phaseclkselc(3); + end if; + end process; + + process(present, startmeasc) begin + if(present(0)='1')then startmeas<=startmeasc(0); + elsif(present(1)='1')then startmeas<=startmeasc(1); + elsif(present(2)='1')then startmeas<=startmeasc(2); + else startmeas<=startmeasc(3); + end if; + end process; + + U_triggerlogic: entity work.triggerlogic + port map( + clk => sysClk125, + rst => rstFromCore, + clk160 => pgpClk, + rst160 => pgpReset, + -- hardware inputs + discin => discinb, + hitbusin => hitbus(1 downto 0), + -- HSIO trigger + HSIObusy => hsiobusyb, + HSIOtrigger => hsiotriggerb, + HSIObusyin => hsiobusyinb, + hitbusout => open, + + -- eudet trigger + exttrigger => exttrigger, + extrst => extrst, + extbusy => extbusy, + exttrgclk => exttrgclk, + + calibmode => calibmode, + startmeas => startmeas, + eudaqdone => eudaqdone, + eudaqtrgword => eudaqtrgword, + tcounter1 => tcounter1, + tcounter2 => tcounter2, + + trigenabled => trigenabled, + paused => paused, + triggermask => triggermask, + resetdelay => resetdelay, + incrementdelay => incrementdelay, + discop => discop, + telescopeop => telescopeop, + period => period, + fifothresh => fifothresh, + serbusy => serbusy, + tdcreadoutbusy => tdcreadoutbusy, + phaseclksel => phaseclksel, + phasebusyEn => phasebusyEn, + phasebusySel => phasebusySel, + l1a => l1a, + triggerword => triggerword, + busy =>busy, + coincd =>open +); + + -- FPGA Cores + -- Telescope 1 + U_HsioCosmicCore0: entity work.HsioPixelCore + generic map( framedFirstChannel=> 0, + framedLastChannel=> 2, + rawFirstChannel => 11, + rawLastChannel => 10, + buffersizefe => 4096, + buffersizetdc => 16384, + fixed160 => '1', + encodingDefault => "00", + hitbusreadout => '0') + port map ( + sysClk250 => sysClk250, sysRst250 => sysRst250, + sysClk125 => sysClk125, sysRst125 => sysRst125, + refClock => refClock, pgpClk => pgpClk, + pgpClk90 => pgpClk90, pgpReset => pgpReset, + clk320 => clk320, reload => reloadc(0), + mgtRxN => iMgtRxN(0), + mgtRxP => iMgtRxP(0), mgtTxN => oMgtTxN(0), + mgtTxP => oMgtTxP(0), + serialin(2 downto 0) => serialinb(2 downto 0), + serialin(15 downto 3) => "0000000000000", + serialout(2 downto 0) => serialoutb(2 downto 0), + serialout(15 downto 3) => open, + clock160 => pgpClk, + clock80 => halfclock, clock40 => quarterclock, + resetOut => resetOutc(0), l1a => l1ac(0), + latchtriggerword => triggerword, tcounter1=>tcounter1, + tcounter2 => tcounter2, busy =>busy, + eudaqdone => eudaqdone, eudaqtrgword => eudaqtrgword, + calibmodeout => calibmodec(0), startmeas => startmeasc(0), + pausedout => pausedc(0), present => present(0), + trgenabledout => trigenabledc(0), rstFromCore => rstFromCorec(0), + fifothresh => fifothreshc(0), triggermask => triggermaskc(0), + discop => discopc(0), period => periodc(0), + telescopeop => telescopeopc(0), resetdelay => resetdelayc(0), + incrementdelay => incrementdelayc(0), + sbusy => serbusyc(0), tdcbusy => tdcreadoutbusyc(0), + phaseclksel => phaseclkselc(0) , hitbus => hitbus(0), + debug => open, + exttriggero => open, extrsto => open, + doricreset => open, + phasebusyEn => phasebusyEnc(0), phasebusySel => phasebusySelc(0), + dispDigitA => dispDigitAA(0), dispDigitB => dispDigitBB(0), + dispDigitC => dispDigitCC(0), dispDigitD => dispDigitDD(0), + dispDigitE => open, dispDigitF => open, + dispDigitG => open, dispDigitH => open, + pgpClkUnbuf => pgpClkUnbuf, pgpClk90Unbuf => pgpClk90Unbuf, + sysClkUnbuf => sysClkUnbuf, trigAdc => trigAdcc(0), + sendAdcData => sendAdcData, adcData => adcDataChan(0) + ); + --Remap ADC channels. Unused channel is f. + adcDataChan(0)(0)<=x"000f"; + adcDataChan(0)(1)<=x"0f0f"; + adcDataChan(0)(2)<=x"0f0f"; + adcDataChan(0)(3)<=x"0f0f"; + adcDataChan(0)(11 downto 4)<=adcData(11 downto 4); + -- Telescope 2 + U_HsioCosmicCore1: entity work.HsioPixelCore + generic map( framedFirstChannel=> 0, + framedLastChannel=> 2, + rawFirstChannel => 11, + rawLastChannel => 10, + buffersizefe => 4096, + buffersizetdc => 16384, + fixed160 => '1', + encodingDefault => "00", + hitbusreadout => '0') + port map ( + sysClk250 => sysClk250, sysRst250 => sysRst250, + sysClk125 => sysClk125, sysRst125 => sysRst125, + refClock => refClock, pgpClk => pgpClk, + pgpClk90 => pgpClk90, pgpReset => pgpReset, + clk320 => clk320, reload => reloadc(1), + mgtRxN => iMgtRxN(1), + mgtRxP => iMgtRxP(1), mgtTxN => oMgtTxN(1), + mgtTxP => oMgtTxP(1), + serialin(2 downto 0) => serialinb(5 downto 3), + serialin(15 downto 3) => "0000000000000", + serialout(2 downto 0) => serialoutb(5 downto 3), + serialout(15 downto 3) => open, + clock160 => pgpClk, + clock80 => halfclock, clock40 => quarterclock, + resetOut => resetOutc(1), l1a => l1ac(1), + latchtriggerword => triggerword, tcounter1=>tcounter1, + tcounter2 => tcounter2, busy =>busy, + eudaqdone => eudaqdone, eudaqtrgword => eudaqtrgword, + calibmodeout => calibmodec(1), startmeas => startmeasc(1), + pausedout => pausedc(1), present => present(1), + trgenabledout => trigenabledc(1), rstFromCore => rstFromCorec(1), + fifothresh => fifothreshc(1), triggermask => triggermaskc(1), + discop => discopc(1), period => periodc(1), + telescopeop => telescopeopc(1), resetdelay => resetdelayc(1), + incrementdelay => incrementdelayc(1), + sbusy => serbusyc(1), tdcbusy => tdcreadoutbusyc(1), + phaseclksel => phaseclkselc(1) , hitbus => hitbus(1), + debug => open, + exttriggero => open, extrsto => open, + doricreset => open, + phasebusyEn => phasebusyEnc(1), phasebusySel => phasebusySelc(1), + dispDigitA => dispDigitAA(1), dispDigitB => dispDigitBB(1), + dispDigitC => dispDigitCC(1), dispDigitD => dispDigitDD(1), + dispDigitE => open, dispDigitF => open, + dispDigitG => open, dispDigitH => open, + pgpClkUnbuf => pgpClkUnbuf, pgpClk90Unbuf => pgpClk90Unbuf, + sysClkUnbuf => sysClkUnbuf, trigAdc => trigAdcc(1), + sendAdcData => sendAdcData, adcData => adcDataChan(1) + ); + adcDataChan(1)(0)<=x"0f00"; + adcDataChan(1)(1)<=x"0f0f"; + adcDataChan(1)(2)<=x"0f0f"; + adcDataChan(1)(3)<=x"0f0f"; + adcDataChan(1)(11 downto 4)<=adcData(11 downto 4); + -- Telescope 3 + U_HsioCosmicCore2: entity work.HsioPixelCore + generic map( framedFirstChannel=> 0, + framedLastChannel=> 0, + rawFirstChannel => 11, + rawLastChannel => 10, + buffersizefe => 8192, + buffersizetdc => 16384, + fixed160 => '0', + encodingDefault => "00", + hitbusreadout => '0') + port map ( + sysClk250 => sysClk250, sysRst250 => sysRst250, + sysClk125 => sysClk125, sysRst125 => sysRst125, + refClock => refClock, pgpClk => pgpClk, + pgpClk90 => pgpClk90, pgpReset => pgpReset, + clk320 => clk320, reload => reloadc(2), + mgtRxN => iMgtRxN(2), + mgtRxP => iMgtRxP(2), mgtTxN => oMgtTxN(2), + mgtTxP => oMgtTxP(2), + serialin(0) => serialinb(6), + serialin(15 downto 1) => "000000000000000", + serialout(0) => serialoutb(6), + serialout(15 downto 1) => open, + clock160 => pgpClk, + clock80 => halfclock, clock40 => quarterclock, + resetOut => resetOutc(2), l1a => l1ac(2), + latchtriggerword => triggerword, tcounter1=>tcounter1, + tcounter2 => tcounter2, busy =>busy, + eudaqdone => eudaqdone, eudaqtrgword => eudaqtrgword, + calibmodeout => calibmodec(2), startmeas => startmeasc(2), + pausedout => pausedc(2), present => present(2), + trgenabledout => trigenabledc(2), rstFromCore => rstFromCorec(2), + fifothresh => fifothreshc(2), triggermask => triggermaskc(2), + discop => discopc(2), period => periodc(2), + telescopeop => telescopeopc(2), resetdelay => resetdelayc(2), + incrementdelay => incrementdelayc(2), + sbusy => serbusyc(2), tdcbusy => tdcreadoutbusyc(2), + phaseclksel => phaseclkselc(2) , hitbus => hitbus(2), + debug => open, + exttriggero => open, extrsto => open, + doricreset => open, + phasebusyEn => phasebusyEnc(2), phasebusySel => phasebusySelc(2), + dispDigitA => dispDigitAA(2), dispDigitB => dispDigitBB(2), + dispDigitC => dispDigitCC(2), dispDigitD => dispDigitDD(2), + dispDigitE => open, dispDigitF => open, + dispDigitG => open, dispDigitH => open, + pgpClkUnbuf => pgpClkUnbuf, pgpClk90Unbuf => pgpClk90Unbuf, + sysClkUnbuf => sysClkUnbuf, trigAdc=>trigAdcc(2), + sendAdcData => sendAdcData, adcData => adcDataChan(2) + ); + adcDataChan(2)(0)<=x"0f0f"; + adcDataChan(2)(1)<=x"0201"; + adcDataChan(2)(2)<=x"0f00"; + adcDataChan(2)(3)<=x"0f0f"; + adcDataChan(2)(11 downto 4)<=adcData(11 downto 4); + -- DUT + U_HsioCosmicCore3: entity work.HsioPixelCore + generic map( framedFirstChannel=> 0, + framedLastChannel=> 0, + rawFirstChannel => 11, + rawLastChannel => 10, + buffersizefe => 8192, + buffersizetdc => 16384, + fixed160 => '0', + encodingDefault => "00", + hitbusreadout => '0') + port map ( + sysClk250 => sysClk250, sysRst250 => sysRst250, + sysClk125 => sysClk125, sysRst125 => sysRst125, + refClock => refClock, pgpClk => pgpClk, + pgpClk90 => pgpClk90, pgpReset => pgpReset, + clk320 => clk320, reload => reloadc(3), + mgtRxN => iMgtRxN(3), + mgtRxP => iMgtRxP(3), mgtTxN => oMgtTxN(3), + mgtTxP => oMgtTxP(3), + serialin(0) => serialinb(7), + serialin(15 downto 1) => "000000000000000", + serialout(0) => serialoutb(7), + serialout(15 downto 1) => open, + clock160 => pgpClk, + clock80 => halfclock, clock40 => quarterclock, + resetOut => resetOutc(3), l1a => l1ac(3), + latchtriggerword => triggerword, tcounter1=>tcounter1, + tcounter2 => tcounter2, busy =>busy, + eudaqdone => eudaqdone, eudaqtrgword => eudaqtrgword, + calibmodeout => calibmodec(3), startmeas => startmeasc(3), + pausedout => pausedc(3), present => present(3), + trgenabledout => trigenabledc(3), rstFromCore => rstFromCorec(3), + fifothresh => fifothreshc(3), triggermask => triggermaskc(3), + discop => discopc(3), period => periodc(3), + telescopeop => telescopeopc(3), resetdelay => resetdelayc(3), + incrementdelay => incrementdelayc(3), + sbusy => serbusyc(3), tdcbusy => tdcreadoutbusyc(3), + phaseclksel => phaseclkselc(3) , hitbus => hitbus(3), + debug => open, + exttriggero => open, extrsto => open, + doricreset => open, + phasebusyEn => phasebusyEnc(3), phasebusySel => phasebusySelc(3), + dispDigitA => dispDigitAA(3), dispDigitB => dispDigitBB(3), + dispDigitC => dispDigitCC(3), dispDigitD => dispDigitDD(3), + dispDigitE => open, dispDigitF => open, + dispDigitG => open, dispDigitH => open, + pgpClkUnbuf => pgpClkUnbuf, pgpClk90Unbuf => pgpClk90Unbuf, + sysClkUnbuf => sysClkUnbuf, trigAdc => trigAdcc(3), + sendAdcData => sendAdcData, adcData => adcDataChan(3) + ); + adcDataChan(3)(0)<=x"0f0f"; + adcDataChan(3)(1)<=x"0f0f"; + adcDataChan(3)(2)<=x"020f"; + adcDataChan(3)(3)<=x"0100"; + adcDataChan(3)(11 downto 4)<=adcData(11 downto 4); + tempadc_inst: entity work.tempadc + generic map( + PRESCALE_G => 79, + MAPPING_G => (0, 1, 2, 3, 5, 4, 6, 7) ) + port map( + clk => sysClk125, + d_out => adcData, + trig => trigAdc, + ld => sendAdcData, + adcAS => adcAs, + scl => adcI2cScl, + sda => adcI2cSda + ); + HSIOCORES: + for I in 0 to 3 generate + l1ac(I) <= l1a and present(I); + transdissig(I)<='0'; + end generate HSIOCORES; + + dispDigitE<=dispDigitAA(0); + dispDigitF<=dispDigitAA(1); + dispDigitG<=dispDigitAA(2); + dispDigitH<=dispDigitAA(3); + dispDigitA<=dispDigitBB(0); + dispDigitB<=dispDigitBB(1); + dispDigitC<="0000"&dispDigitCC(0)(0)&dispDigitCC(1)(0)&dispDigitCC(2)(0)&dispDigitCC(3)(0); + dispDigitD<=dispDigitDD(3); + + sysClk125i <= not sysClk125; + --sysClk125i<=debug(0); + U_clock160: entity work.clock160 port map( + CLKIN_N_IN => iMainClkN, + CLKIN_P_IN => iMainClkP, + RST_IN => sysRst125, + CLKFX_OUT => mainClk, + CLKIN_IBUFGDS_OUT => clkin, + CLK0_OUT => clk0, + LOCKED_OUT => open); + + process(mainClk) + begin + if(mainClk'event and mainClk='1') then + halfclock<= not halfclock; + end if; + end process; + process(halfclock) + begin + if(halfclock'event and halfclock='1') then + quarterclock<= not quarterclock; + end if; + end process; + U_idelctrlclk: entity work.clock200 port map( + CLKIN_IN => mainClk, + RST_IN => holdrst, + CLKFX_OUT => clockidctrl, + CLK0_OUT => open, + LOCKED_OUT => lockedid); + U_idelayctrl: IDELAYCTRL port map( + RDY => open, + REFCLK => clockidctrl, + RST => idctrlrst); + + process(sysRst125, sysClk125) -- clock interface + begin + if (sysRst125='1') then + holdctr<=(others=>'1'); + holdrst<='1'; + elsif(sysClk125'event and sysClk125='1') then + if (holdctr(24)='0') then + holdrst<='0'; + end if; + holdctr<=unsigned(holdctr)-1; + end if; + end process; + + process(sysClk125, sysRst125) -- reset logic for IDELAYCTRL + begin + if(sysRst125='1') then + idctrlrst<='0'; + idcounter<="000"; + oldlockedid<='0'; + elsif(sysClk125'event and sysClk125='1') then + if(lockedid='1' and oldlockedid='0')then + idcounter<="111"; + idctrlrst<='1'; + elsif(unsigned(idcounter)>0)then + idcounter<=unsigned(idcounter)-1; + else + idctrlrst<='0'; + end if; + oldlockedid<=lockedid; + end if; + end process; + +end HsioCosmic; diff --git a/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd.fei3 b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd.fei3 new file mode 100755 index 00000000..d76e8ffa --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd.fei3 @@ -0,0 +1,770 @@ +------------------------------------------------------------------------------- +-- Title : BNL ASIC Test FGPA, Top Level +-- Project : LCLS Detector, BNL ASIC +------------------------------------------------------------------------------- +-- File : HsioCosmic.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 07/21/2008 +------------------------------------------------------------------------------- +-- Description: +-- Top level logic for BNL ASIC test FPGA. +------------------------------------------------------------------------------- +-- Copyright (c) 2008 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 07/21/2008: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +Library Unisim; +USE ieee. std_logic_1164.ALL; +use ieee. std_logic_arith.all; +use ieee. std_logic_unsigned.all; +USE work.ALL; + +entity HsioCosmic is + port ( + + -- PGP Crystal Clock Input, 156.25Mhz + iPgpRefClkP : in std_logic; + iPgpRefClkM : in std_logic; + + -- System clock 125 MHz clock input + iMainClkP : in std_logic; + iMainClkN : in std_logic; + + -- PGP Rx/Tx Lines + iMgtRxN : in std_logic; + iMgtRxP : in std_logic; + oMgtTxN : out std_logic; + oMgtTxP : out std_logic; + + -- ATLAS Pixel module pins + serialin : in std_logic_vector(15 downto 0); + serialout : out std_logic_vector(15 downto 0); + serialout_p : out std_logic_vector(15 downto 0); + serialout_n : out std_logic_vector(15 downto 0); + serialin_p : in std_logic_vector(15 downto 0); + serialin_n : in std_logic_vector(15 downto 0); + discinP : in std_logic_vector(3 downto 0); +-- discinN : in std_logic_vector(1 downto 0); + clkout40 : out std_logic; + refclk_p : out std_logic; + refclk_n : out std_logic; + xclk_p : out std_logic; + xclk_n : out std_logic; + + -- Reset button + iResetInL : in std_logic; + -- Reload firmware + oReload : out std_logic; + -- LED Display + oDispClk : out std_logic; + oDispDat : out std_logic; + oDispLoadL : out std_logic_vector(1 downto 0); + oDispRstL : out std_logic; + + -- Debug + oDebug : out std_logic_vector(7 downto 0); + + -- Eudet trigger + iExttriggerP : in std_logic; + iExttriggerN : in std_logic; + iExtrstP : in std_logic; + iExtrstN : in std_logic; + oExtbusyP : out std_logic; + oExtbusyN : out std_logic; + oExttrgclkP : out std_logic; + oExttrgclkN : out std_logic; + + --HSIO trigger IF + iHSIOtrigger : in std_logic; + oHSIObusy : out std_logic; + + -- Eudet test + oExtrstP : out std_logic; + oExtrstN : out std_logic; + oExttriggerP : out std_logic; + oExttriggerN : out std_logic; + + + -- Misc Signals + oPdBuff0 : out std_logic; + oPdBuff1 : out std_logic; + oPdBuff3 : out std_logic; + oPdBuff4 : out std_logic; + oLemoA : out std_logic; + iLemoB : in std_logic; + + -- Transmitter enable + transDis1 : out std_logic; + -- CMOS chip I/O + RD2 : out std_logic; + AuxClk : out std_logic; + RA : out std_logic; + RD1 : out std_logic; + IOMXIN : out std_logic_vector(3 downto 0); + IOMXSEL : out std_logic_vector(2 downto 0); + HITOR : in std_logic; + IOMXOUT : in std_logic_vector(2 downto 0); + SELALTBUS : out std_logic; + REGABDACLD : out std_logic; + REGABSTBLD : out std_logic; + SELCMD : out std_logic; + CMDEXTTRIGGER : out std_logic; + CMDALTPLS : out std_logic + ); +end HsioCosmic; + + +-- Define architecture for top level module +architecture HsioCosmic of HsioCosmic is + + -- Synthesis control attributes + attribute syn_useioff : boolean; + attribute syn_useioff of HsioCosmic : architecture is true; + attribute xc_fast_auto : boolean; + attribute xc_fast_auto of HsioCosmic : architecture is false; + attribute syn_noclockbuf : boolean; + attribute syn_noclockbuf of HsioCosmic : architecture is true; + + -- IO Pad components + component IBUF port ( O : out std_logic; I : in std_logic ); end component; + component OBUF port ( O : out std_logic; I : in std_logic ); end component; + component OBUFDS + generic( IOSTANDARD: STRING:= "LVDS_25"; + SLEW: STRING:="FAST"); + port ( O : out std_logic; OB : out std_logic; I : in std_logic ); + end component; + + -- Input LVDS with termination + component IBUFDS + generic ( DIFF_TERM : boolean := TRUE; + IOSTANDARD: STRING := "LVDS_25"); + port ( O : out std_logic; I : in std_logic; IB : in std_logic ); + end component; + + -- Xilinx global clock buffer component + component BUFGMUX + port ( + O : out std_logic; + I0 : in std_logic; + I1 : in std_logic; + S : in std_logic + ); + end component; + + + -- PGP Clock Generator + component PgpClkGen + generic ( + RefClkEn1 : string := "ENABLE"; -- ENABLE or DISABLE + RefClkEn2 : string := "DISABLE"; -- ENABLE or DISABLE + DcmClkSrc : string := "RefClk1"; -- RefClk1 or RefClk2 + UserFxDiv : integer := 5; -- DCM FX Output Divide + UserFxMult : integer := 4 -- DCM FX Output Divide, 4/5 * 156.25 = 125Mhz + ); + port ( + + -- Reference Clock Pad Inputs + pgpRefClkInP : in std_logic; + pgpRefClkInN : in std_logic; + + -- Power On Reset Input + ponResetL : in std_logic; + + -- Locally Generated Reset + locReset : in std_logic; + + -- Reference Clock To PGP MGT + -- Use one, See RefClkEn1 & RefClkEn2 Generics + pgpRefClk1 : out std_logic; + pgpRefClk2 : out std_logic; + + -- Global Clock & Reset For PGP Logic, 156.25Mhz + pgpClk : out std_logic; + pgpClk90 : out std_logic; + pgpReset : out std_logic; + + clk320 : out std_logic; + -- Global Clock & Reset For User Logic, 125Mhz + userClk : out std_logic; + userReset : out std_logic; + + -- Inputs clocks for reset generation connect + -- to pgpClk and userClk + pgpClkIn : in std_logic; + userClkIn : in std_logic; + + pgpClkUnbuf : out std_logic; + pgpClk90Unbuf : out std_logic; + locClkUnbuf : out std_logic + + ); + end component; + + + -- Core Logic + component HsioPixelCore + generic ( + framedFirstChannel : integer := 0; --First framed channel + framedLastChannel : integer := 7; --Last framed channel + rawFirstChannel : integer := 11; --First raw channel + rawLastChannel : integer := 14; --Last raw channel + buffersize : integer := 8192; --FIFO size + bpmDefault : std_logic := '0' --BPM on startup + ); + port ( + sysClk250 : in std_logic; + sysClk125 : in std_logic; + sysRst125 : in std_logic; + sysRst250 : in std_logic; + refClock : in std_logic; + pgpClk : in std_logic; + pgpClk90 : in std_logic; + pgpReset : in std_logic; + + pgpClkUnbuf : in std_logic; + pgpClk90Unbuf: in std_logic; + sysClkUnbuf : in std_logic; + + clk320 : in std_logic; + reload : out std_logic; + mgtRxN : in std_logic; + mgtRxP : in std_logic; + mgtTxN : out std_logic; + mgtTxP : out std_logic; + serialin : in std_logic_vector(15 downto 0); + serialout : out std_logic_vector(15 downto 0); + discin : in std_logic_vector(3 downto 0); + clock160 : in std_logic; + clock80 : in std_logic; + clock40 : in std_logic; + resetOut : out std_logic; + debug : out std_logic_vector(7 downto 0); + exttrigger : in std_logic; + extrst : in std_logic; + extbusy : out std_logic; + exttrgclk : out std_logic; + exttriggero : out std_logic; + extrsto : out std_logic; + doricreset : out std_logic; + dispDigitA : out std_logic_vector(7 downto 0); + dispDigitB : out std_logic_vector(7 downto 0); + dispDigitC : out std_logic_vector(7 downto 0); + dispDigitD : out std_logic_vector(7 downto 0); + dispDigitE : out std_logic_vector(7 downto 0); + dispDigitF : out std_logic_vector(7 downto 0); + dispDigitG : out std_logic_vector(7 downto 0); + dispDigitH : out std_logic_vector(7 downto 0); + HSIObusy : out std_logic; + HSIOtrigger : in std_logic + ); + end component; + + component clock160 + port ( + CLKIN_N_IN : in std_logic; + CLKIN_P_IN : in std_logic; + RST_IN : in std_logic; + CLKFX_OUT : out std_logic; + CLKIN_IBUFGDS_OUT : out std_logic; + CLK0_OUT : out std_logic; + LOCKED_OUT : out std_logic); + end component; + component clock200 + port( CLKIN_IN : in std_logic; + RST_IN : in std_logic; + CLKFX_OUT : out std_logic; + CLK0_OUT : out std_logic; + LOCKED_OUT : out std_logic); + end component; + component IDELAYCTRL + port ( RDY : out std_logic; + REFCLK : in std_logic; + RST : in std_logic + ); + end component; + +component IDELAY + generic (IOBDELAY_TYPE : string := "DEFAULT"; --(DEFAULT, FIXED, VARIABLE) + IOBDELAY_VALUE : integer := 0 --(0 to 63) + ); + port ( + O : out STD_LOGIC; + I : in STD_LOGIC; + C : in STD_LOGIC; + CE : in STD_LOGIC; + INC : in STD_LOGIC; + RST : in STD_LOGIC + ); +end component; + component DisplayControl + port ( + sysClk : in std_logic; + sysRst : in std_logic; + dispStrobe : in std_logic; + dispUpdate : in std_logic; + dispRotate : in std_logic_vector(1 downto 0); + dispDigitA : in std_logic_vector(7 downto 0); + dispDigitB : in std_logic_vector(7 downto 0); + dispDigitC : in std_logic_vector(7 downto 0); + dispDigitD : in std_logic_vector(7 downto 0); + dispClk : out std_logic; + dispDat : out std_logic; + dispLoadL : out std_logic; + dispRstL : out std_logic + ); + end component; + + + component ODDR port ( + Q : out std_logic; + CE : in std_logic; + C : in std_logic; + D1 : in std_logic; + D2 : in std_logic; + R : in std_logic; + S : in std_logic + ); + end component; + + + -- Local signals + signal resetInL : std_logic; + signal tmpClk250 : std_logic; + signal sysClk125 : std_logic; + signal sysRst125 : std_logic; + signal sysRst250 : std_logic; + signal sysClk250 : std_logic; + signal refClock : std_logic; + signal pgpClk : std_logic; + signal pgpClk90 : std_logic; + signal pgpReset : std_logic; + signal clk320 : std_logic; + signal reload : std_logic; + signal resetOut : std_logic; + signal mgtRxN : std_logic; + signal mgtRxP : std_logic; + signal mgtTxN : std_logic; + signal mgtTxP : std_logic; + signal dispClk : std_logic; + signal dispDat : std_logic; + signal dispLoadL : std_logic_vector(1 downto 0); + signal dispRstL : std_logic; + signal debug : std_logic_vector(7 downto 0); + signal sysClk125i : std_logic; + signal mainClk : std_logic; + signal clk0 : std_logic; + signal clkin : std_logic; + signal halfclock : std_logic; + signal quarterclock : std_logic; + signal clockidctrl : std_logic; + signal idctrlrst : std_logic; + signal RD2b : std_logic; + signal AuxClkb : std_logic; + signal RAb : std_logic; + signal RD1b : std_logic; + signal IOMXINb : std_logic_vector(3 downto 0); + signal IOMXSELb : std_logic_vector(2 downto 0); + signal HITORb : std_logic; + signal IOMXOUTb : std_logic_vector(2 downto 0); + signal SELALTBUSb : std_logic; + signal REGABDACLDb : std_logic; + signal REGABSTBLDb : std_logic; + signal SELCMDb : std_logic; + signal CMDEXTTRIGGERb : std_logic; + signal CMDALTPLSb : std_logic; + signal exttrigger : std_logic; + signal exttriggerinv : std_logic; + signal extrst : std_logic; + signal extrstinv : std_logic; + signal exttriggero : std_logic; + signal extrsto : std_logic; + signal extbusy : std_logic; + signal extbusyinv : std_logic; + signal exttrgclk : std_logic; + signal exttrgclkinv : std_logic; + signal hsiobusyb : std_logic; + signal hsiotriggerb : std_logic; + signal serialoutb : std_logic_vector(15 downto 0); + signal serialinb : std_logic_vector(15 downto 0); + signal discinb : std_logic_vector(3 downto 0); + signal ccontrol : std_logic_vector(35 downto 0); + signal cdata : std_logic_vector(31 downto 0); + signal ctrig : std_logic_vector(0 downto 0); + signal opgpClk : std_logic; + signal dispDatA : std_logic; + signal dispDatB : std_logic; + signal pgpDispA : std_logic_vector(7 downto 0); + signal pgpDispB : std_logic_vector(7 downto 0); + signal dispDigitA : std_logic_vector(7 downto 0); + signal dispDigitB : std_logic_vector(7 downto 0); + signal dispDigitC : std_logic_vector(7 downto 0); + signal dispDigitD : std_logic_vector(7 downto 0); + signal dispDigitE : std_logic_vector(7 downto 0); + signal dispDigitF : std_logic_vector(7 downto 0); + signal dispDigitG : std_logic_vector(7 downto 0); + signal dispDigitH : std_logic_vector(7 downto 0); + signal dispStrobe : std_logic; + signal dispUpdateA : std_logic; + signal dispUpdateB : std_logic; + signal sysClkCnt : std_logic_vector(15 downto 0); + signal lockedid : std_logic; + signal oldlockedid : std_logic; + signal holdrst : std_logic; + signal holdctr : std_logic_vector(24 downto 0); + signal idcounter : std_logic_vector(2 downto 0); + + signal pgpClkUnbuf : std_logic; + signal pgpClk90Unbuf : std_logic; + signal sysClkUnbuf : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + + -- Black Box Attributes +-- attribute syn_noprune : boolean; +-- attribute syn_noprune of chipscope : label is true; +-- attribute syn_noprune of chipscopeicon : label is true; + attribute syn_black_box : boolean; + attribute syn_noprune : boolean; + attribute syn_black_box of IBUF : component is TRUE; + attribute syn_noprune of IBUF : component is TRUE; + attribute syn_black_box of OBUF : component is TRUE; + attribute syn_noprune of OBUF : component is TRUE; + attribute syn_black_box of IBUFDS : component is TRUE; + attribute syn_noprune of IBUFDS : component is TRUE; + attribute syn_black_box of OBUFDS : component is TRUE; + attribute syn_noprune of OBUFDS : component is TRUE; + attribute syn_black_box of BUFGMUX : component is TRUE; + attribute syn_noprune of BUFGMUX : component is TRUE; + attribute syn_hier: string; + attribute syn_hier of HsioCosmic: architecture is "hard"; + attribute xc_props : string; + attribute xc_props of HsioCosmic : architecture is "KEEP_HIERARCHY=TRUE"; +begin + + -- Reset input + U_ResetIn: IBUF port map ( I => iResetInL, O => resetInL ); + + -- PGP Clock Generator + U_PgpClkGen: PgpClkGen generic map ( + RefClkEn1 => "ENABLE", + RefClkEn2 => "DISABLE", + DcmClkSrc => "RefClk1", + UserFxDiv => 4, + UserFxMult => 2 + ) port map ( + pgpRefClkInP => iPgpRefClkP, + pgpRefClkInN => iPgpRefClkM, + ponResetL => resetInL, + locReset => resetOut, + pgpRefClk1 => refClock, + pgpRefClk2 => open, + pgpClk => pgpClk, + pgpClk90 => pgpClk90, + pgpReset => pgpReset, + clk320 => clk320, + pgpClkIn => pgpClk, + userClk => sysClk125, + userReset => sysRst125, + userClkIn => sysClk125, + pgpClkUnbuf => pgpClkUnbuf, + pgpClk90Unbuf => pgpClk90Unbuf, + locClkUnbuf => sysClkUnbuf + + + ); + + -- Generate Divided Clock, sample reset + process ( pgpClk ) begin + if rising_edge(pgpClk) then + tmpClk250 <= not tmpClk250 after tpd; + sysRst250 <= sysRst125 after tpd; + end if; + end process; + + -- Global Buffer For 125Mhz Clock + U_CLK125: BUFGMUX port map ( + O => sysClk250, + I0 => tmpClk250, + I1 => '0', + S => '0' + ); + + -- No Pads for MGT Lines + mgtRxN <= iMgtRxN; + mgtRxP <= iMgtRxP; + oMgtTxN <= mgtTxN; + oMgtTxP <= mgtTxP; + + -- LED Display + U_DispClk : OBUF port map ( I => dispClk , O => oDispClk ); + U_DispDat : OBUF port map ( I => dispDat , O => oDispDat ); + U_DispLoadL1 : OBUF port map ( I => dispLoadL(1) , O => oDispLoadL(1) ); + U_DispLoadL0 : OBUF port map ( I => dispLoadL(0) , O => oDispLoadL(0) ); + U_DispRstL : OBUF port map ( I => dispRstL , O => oDispRstL ); + U_reload : OBUF port map ( I => reload , O => oReload ); + U_clkout40 : OBUF port map ( I => sysClk125i , O => clkout40 ); + U_refclk : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => sysClk125i , O => refclk_p , OB => refclk_n ); + U_xclk : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => sysClk125i , O => xclk_p , OB => xclk_n ); + +-- U_pgpClk : ODDR port map ( +-- Q => opgpClk, +-- CE => '1', +-- C => pgpClk, +-- D1 => '0', +-- D2 => '1', +-- R => '0', +-- S => '0' +-- ); + + + + -- Debug + -- U_Debug0 : OBUF port map ( I => debug(0) , O => oDebug(0) ); + -- U_Debug1 : OBUF port map ( I => debug(1) , O => oDebug(1) ); + -- U_Debug2 : OBUF port map ( I => debug(2) , O => oDebug(2) ); + -- U_Debug3 : OBUF port map ( I => debug(3) , O => oDebug(3) ); + -- U_Debug4 : OBUF port map ( I => debug(4) , O => oDebug(4) ); + -- U_Debug5 : OBUF port map ( I => debug(5) , O => oDebug(5) ); + -- U_Debug6 : OBUF port map ( I => debug(6) , O => oDebug(6) ); + -- U_Debug7 : OBUF port map ( I => debug(7) , O => oDebug(7) ); + + U_transdis : OBUF port map ( I => '0' , O => transDis1 ); + + U_rd2 : OBUF port map ( I => RD2b , O => RD2); + U_auxclk : OBUF port map ( I => AuxClkb , O => AuxClk); + U_RA : OBUF port map ( I => RAb , O => RA ); + U_rd1 : OBUF port map ( I => RD1b , O => RD1 ); + U_IOMXIN3 : OBUF port map ( I => IOMXINb(3) , O => IOMXIN(3) ); + U_IOMXIN2 : OBUF port map ( I => IOMXINb(2) , O => IOMXIN(2) ); + U_IOMXIN1 : OBUF port map ( I => IOMXINb(1) , O => IOMXIN(1) ); + U_IOMXIN0 : OBUF port map ( I => IOMXINb(0) , O => IOMXIN(0) ); + U_IOMXSEL2 : OBUF port map ( I => IOMXSELb(2) , O => IOMXSEL(2) ); + U_IOMXSEL1 : OBUF port map ( I => IOMXSELb(1) , O => IOMXSEL(1) ); + U_IOMXSEL0 : OBUF port map ( I => IOMXSELb(0) , O => IOMXSEL(0) ); + U_HITOR : IBUF port map ( O => HITORb , I => HITOR); + U_IOMXOUT2 : IBUF port map ( O => IOMXOUTb(2) , I => IOMXOUT(2) ); + U_IOMXOUT1 : IBUF port map ( O => IOMXOUTb(1) , I => IOMXOUT(1) ); + U_IOMXOUT0 : IBUF port map ( O => IOMXOUTb(0) , I => IOMXOUT(0) ); + U_SELALTBUS : OBUF port map ( I => SELALTBUSb , O => SELALTBUS); + U_REGABDACLD : OBUF port map ( I => REGABDACLDb , O => REGABDACLD); + U_REGABSTBLD : OBUF port map ( I => REGABSTBLDb , O => REGABSTBLD); + U_SELCMD : OBUF port map ( I => SELCMDb , O => SELCMD ); + U_CMDEXTTRIGGER : OBUF port map ( I => CMDEXTTRIGGERb , O => CMDEXTTRIGGER ); + U_CMDALTPLS : OBUF port map ( I => CMDALTPLSb , O => CMDALTPLS ); + U_exttrgclk : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => extrgclkinv , O => oExttrgclkP , OB => oExttrgclkN ); + exttrgclkinv<= not exttrgclk; + U_extbusy : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => extbusyinv , O => oExtBusyP , OB => oExtbusyN ); + extbusyinv<= not extbusy; + U_exttrigger : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => iExttriggerP , IB=>iExttriggerN , O => exttriggerinv ); + exttrigger<= not exttriggerinv; + U_extrst : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => iExtrstP , IB=>iExtrstN , O => extrstinv ); + extrst<= not extrstinv; + U_exttriggero : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => exttriggero , O => oExttriggerP , OB => oExttriggerN ); + + U_extrsto : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => extrsto , O => oExtrstP , OB => oExtrstN ); + + U_HSIObusy : OBUF port map ( I => hsiobusyb , O => oHSIObusy); + U_HSIOtrigger : IBUF port map ( O => hsiotriggerb , I => iHSIOtrigger ); + + SERIAL_IO_DATA: + for I in 0 to 0 generate + U_serialin : IBUF port map ( I => serialin(I) , O => serialinb(I) ); + U_serialout : OBUF port map ( I => serialoutb(I) , O => serialout(I) ); + --U_serialout_pn :OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + -- port map ( I => serialoutb(I) , O => serialout_p(I) , OB => serialout_n(I) ); + + --U_serialin_pn : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + -- port map ( I => serialin_p(I) , IB=>serialin_n(I) , O => serialinb(I) ); + + end generate SERIAL_IO_DATA; + + --U_serialout : OBUF port map ( I => serialoutb(8) , O => serialout(8) ); + --U_serialin_pn_8 : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + --port map ( I => serialin_p(8) , IB=>serialin_n(8) , O => serialinb(8) ); + +-- U_serialout11 : OBUF port map ( I => serialoutb(11) , O => serialout(11) ); +-- U_serialin11 : IBUF port map ( I => serialin(11) , O => serialinb(11) ); + SERIAL_IO_DATA_FEI3: + for I in 11 to 14 generate + U_serialout_pn :OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => serialoutb(I) , O => serialout_p(I) , OB => serialout_n(I) ); + + U_serialin_pn : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => serialin_p(I) , IB=>serialin_n(I) , O => serialinb(I) ); + + end generate SERIAL_IO_DATA_FEI3; + --DISC_1: IBUFDS port map ( O => discinb(0), I => discinP(0) , IB => discinN(0) ); + --DISC_2: IBUFDS port map ( O => discinb(1), I => discinP(1) , IB => discinN(1) ); + DISC_1: IBUF port map ( O => discinb(0), I => discinP(0) ); + DISC_2: IBUF port map ( O => discinb(1), I => discinP(1) ); + DISC_3: IBUF port map ( O => discinb(2), I => discinP(2) ); + DISC_4: IBUF port map ( O => discinb(3), I => discinP(3) ); + -- Display Controller A + U_DispCntrlA: DisplayControl port map ( + sysClk => sysClk125, sysRst => sysRst125, + dispStrobe => dispStrobe, dispUpdate => dispUpdateA, + dispRotate => "01", dispDigitA => dispDigitA, + dispDigitB => dispDigitB, dispDigitC => dispDigitC, + dispDigitD => dispDigitD, dispClk => dispClk, + dispDat => dispDatA, dispLoadL => dispLoadL(0), + dispRstL => dispRstL + ); + + -- Display Controller B + U_DispCntrlB: DisplayControl port map ( + sysClk => sysClk125, sysRst => sysRst125, + dispStrobe => dispStrobe, dispUpdate => dispUpdateB, + dispRotate => "01", dispDigitA => dispDigitE, + dispDigitB => dispDigitF, dispDigitC => dispDigitG, + dispDigitD => dispDigitH, dispClk => open, + dispDat => dispDatB, dispLoadL => dispLoadL(1), + dispRstL => open + ); + -- Output LED Data + dispDat <= dispDatA or dispDatB; + -- Generate display strobe (200ns) and update control + process ( sysClk125, sysRst125 ) begin + if sysRst125 = '1' then + sysClkCnt <= (others=>'0') after tpd; + dispStrobe <= '0' after tpd; + dispUpdateA <= '0' after tpd; + dispUpdateB <= '0' after tpd; + elsif rising_edge(sysClk125) then + + -- Display strobe, 320ns + dispStrobe <= sysClkCnt(4) after tpd; + + -- Update Display 0 + if sysClkCnt(15 downto 0) = x"8000" then + dispUpdateA <= '1' after tpd; + else + dispUpdateA <= '0' after tpd; + end if; + + -- Update Display B + if sysClkCnt(15 downto 0) = x"0000" then + dispUpdateB <= '1' after tpd; + else + dispUpdateB <= '0' after tpd; + end if; + + -- Update counter + sysClkCnt <= sysClkCnt + 1 after tpd; + + + end if; + end process; + + + -- FPGA Core + U_HsioCosmicCore: HsioPixelCore + generic map( framedFirstChannel=> 1, + framedLastChannel=> 0, + rawFirstChannel => 0, + rawLastChannel => 0, + buffersize => 16384, + bpmDefault => '0') + port map ( + sysClk250 => sysClk250, sysRst250 => sysRst250, + sysClk125 => sysClk125, sysRst125 => sysRst125, + refClock => refClock, pgpClk => pgpClk, + pgpClk90 => pgpClk90, pgpReset => pgpReset, + clk320 => clk320, reload => reload, + mgtRxN => mgtRxN, + mgtRxP => mgtRxP, mgtTxN => mgtTxN, + mgtTxP => mgtTxP, serialin => serialinb, + serialout => serialoutb, discin => discinb, + clock160 => pgpClk, + clock80 => halfclock, clock40 => quarterclock, + resetOut => resetOut, + debug => debug, exttrigger => exttrigger, + extrst => extrst, extbusy => extbusy, exttrgclk => exttrgclk, + exttriggero => exttriggero, extrsto => extrsto, + doricreset => open, + dispDigitA => dispDigitA, dispDigitB => dispDigitB, + dispDigitC => dispDigitC, dispDigitD => dispDigitD, + dispDigitE => dispDigitE, dispDigitF => dispDigitF, + dispDigitG => dispDigitF, dispDigitH => dispDigitH, + pgpClkUnbuf => pgpClkUnbuf, pgpClk90Unbuf => pgpClk90Unbuf, + sysClkUnbuf => sysClkUnbuf, HSIObusy => hsiobusyb, + HSIOtrigger => hsiotriggerb + ); + sysClk125i <= not sysClk125; + --sysClk125i<=debug(0); + U_clock160: clock160 port map( + CLKIN_N_IN => iMainClkN, + CLKIN_P_IN => iMainClkP, + RST_IN => sysRst125, + CLKFX_OUT => mainClk, + CLKIN_IBUFGDS_OUT => clkin, + CLK0_OUT => clk0, + LOCKED_OUT => open); + + process(mainClk) + begin + if(mainClk'event and mainClk='1') then + halfclock<= not halfclock; + end if; + end process; + process(halfclock) + begin + if(halfclock'event and halfclock='1') then + quarterclock<= not quarterclock; + end if; + end process; + U_idelctrlclk: clock200 port map( + CLKIN_IN => mainClk, + RST_IN => holdrst, + CLKFX_OUT => clockidctrl, + CLK0_OUT => open, + LOCKED_OUT => lockedid); + U_idelayctrl: IDELAYCTRL port map( + RDY => open, + REFCLK => clockidctrl, + RST => idctrlrst); + + process(sysRst125, sysClk125) -- clock interface + begin + if (sysRst125='1') then + holdctr<=(others=>'1'); + holdrst<='1'; + elsif(sysClk125'event and sysClk125='1') then + if (holdctr(24)='0') then + holdrst<='0'; + end if; + holdctr<=unsigned(holdctr)-1; + end if; + end process; + + process(sysClk125, sysRst125) -- reset logic for IDELAYCTRL + begin + if(sysRst125='1') then + idctrlrst<='0'; + idcounter<="000"; + oldlockedid<='0'; + elsif(sysClk125'event and sysClk125='1') then + if(lockedid='1' and oldlockedid='0')then + idcounter<="111"; + idctrlrst<='1'; + elsif(unsigned(idcounter)>0)then + idcounter<=unsigned(idcounter)-1; + else + idctrlrst<='0'; + end if; + oldlockedid<=lockedid; + end if; + end process; + +end HsioCosmic; diff --git a/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd.multicore b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd.multicore new file mode 100755 index 00000000..4cdb8055 --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd.multicore @@ -0,0 +1,800 @@ +------------------------------------------------------------------------------- +-- Title : BNL ASIC Test FGPA, Top Level +-- Project : LCLS Detector, BNL ASIC +------------------------------------------------------------------------------- +-- File : HsioCosmic.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 07/21/2008 +------------------------------------------------------------------------------- +-- Description: +-- Top level logic for BNL ASIC test FPGA. +------------------------------------------------------------------------------- +-- Copyright (c) 2008 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 07/21/2008: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +Library Unisim; +USE ieee. std_logic_1164.ALL; +use ieee. std_logic_arith.all; +use ieee. std_logic_unsigned.all; +USE work.ALL; +use work.StdRtlPkg.all; + +entity HsioCosmic is + port ( + + -- PGP Crystal Clock Input, 156.25Mhz + iPgpRefClkP : in std_logic; + iPgpRefClkM : in std_logic; + + -- System clock 125 MHz clock input + iMainClkP : in std_logic; + iMainClkN : in std_logic; + + -- PGP Rx/Tx Lines + iMgtRxN : in std_logic_vector(3 downto 0); + iMgtRxP : in std_logic_vector(3 downto 0); + oMgtTxN : out std_logic_vector(3 downto 0); + oMgtTxP : out std_logic_vector(3 downto 0); + + -- ATLAS Pixel module pins + serialin : in std_logic_vector(15 downto 0); + serialout : out std_logic_vector(15 downto 0); + serialout_p : out std_logic_vector(15 downto 0); + serialout_n : out std_logic_vector(15 downto 0); + serialin_p : in std_logic_vector(15 downto 0); + serialin_n : in std_logic_vector(15 downto 0); + discinP : in std_logic_vector(3 downto 0); +-- discinN : in std_logic_vector(1 downto 0); + clkout40 : out std_logic; + refclk_p : out std_logic; + refclk_n : out std_logic; + xclk_p : out std_logic; + xclk_n : out std_logic; + + -- Reset button + iResetInL : in std_logic; + -- Reload firmware + oReload : out std_logic; + iExtreload : in std_logic; + -- LED Display + oDispClk : out std_logic; + oDispDat : out std_logic; + oDispLoadL : out std_logic_vector(1 downto 0); + oDispRstL : out std_logic; + + -- Debug + oDebug : out std_logic_vector(7 downto 0); + + -- Eudet trigger + iExttriggerP : in std_logic; + iExttriggerN : in std_logic; + iExtrstP : in std_logic; + iExtrstN : in std_logic; + oExtbusyP : out std_logic; + oExtbusyN : out std_logic; + oExttrgclkP : out std_logic; + oExttrgclkN : out std_logic; + + --HSIO trigger IF + iHSIOtrigger : in std_logic_vector(1 downto 0); + oHSIOtrigger : out std_logic; + oHSIObusy : out std_logic; + iHSIObusy : in std_logic; + + -- Eudet test + oExtrstP : out std_logic; + oExtrstN : out std_logic; + oExttriggerP : out std_logic; + oExttriggerN : out std_logic; + + + -- Misc Signals + oPdBuff0 : out std_logic; + oPdBuff1 : out std_logic; + oPdBuff3 : out std_logic; + oPdBuff4 : out std_logic; + oLemoA : out std_logic; + iLemoB : in std_logic; + + -- Transmitter enable + transDis : out std_logic_vector(3 downto 0); + -- CMOS chip I/O + RD2 : out std_logic; + AuxClk : out std_logic; + RA : out std_logic; + RD1 : out std_logic; + IOMXIN : out std_logic_vector(3 downto 0); + IOMXSEL : out std_logic_vector(2 downto 0); + HITOR : in std_logic; + IOMXOUT : in std_logic_vector(2 downto 0); + SELALTBUS : out std_logic; + REGABDACLD : out std_logic; + REGABSTBLD : out std_logic; + SELCMD : out std_logic; + CMDEXTTRIGGER : out std_logic; + CMDALTPLS : out std_logic + ); +end HsioCosmic; + + +-- Define architecture for top level module +architecture HsioCosmic of HsioCosmic is + + -- Synthesis control attributes + attribute syn_useioff : boolean; + attribute syn_useioff of HsioCosmic : architecture is true; + attribute xc_fast_auto : boolean; + attribute xc_fast_auto of HsioCosmic : architecture is false; + attribute syn_noclockbuf : boolean; + attribute syn_noclockbuf of HsioCosmic : architecture is true; + + -- IO Pad components + component IBUF port ( O : out std_logic; I : in std_logic ); end component; + component OBUF port ( O : out std_logic; I : in std_logic ); end component; + component OBUFDS + generic( IOSTANDARD: STRING:= "LVDS_25"; + SLEW: STRING:="FAST"); + port ( O : out std_logic; OB : out std_logic; I : in std_logic ); + end component; + + -- Input LVDS with termination + component IBUFDS + generic ( DIFF_TERM : boolean := TRUE; + IOSTANDARD: STRING := "LVDS_25"); + port ( O : out std_logic; I : in std_logic; IB : in std_logic ); + end component; + + -- Xilinx global clock buffer component + component BUFGMUX + port ( + O : out std_logic; + I0 : in std_logic; + I1 : in std_logic; + S : in std_logic + ); + end component; + + component IDELAYCTRL + port ( RDY : out std_logic; + REFCLK : in std_logic; + RST : in std_logic + ); + end component; + +component IDELAY + generic (IOBDELAY_TYPE : string := "DEFAULT"; --(DEFAULT, FIXED, VARIABLE) + IOBDELAY_VALUE : integer := 0 --(0 to 63) + ); + port ( + O : out STD_LOGIC; + I : in STD_LOGIC; + C : in STD_LOGIC; + CE : in STD_LOGIC; + INC : in STD_LOGIC; + RST : in STD_LOGIC + ); +end component; + + + -- Local signals + signal resetInL : std_logic; + signal tmpClk250 : std_logic; + signal sysClk125 : std_logic; + signal sysRst125 : std_logic; + signal sysRst250 : std_logic; + signal sysClk250 : std_logic; + signal refClock : std_logic; + signal pgpClk : std_logic; + signal pgpClk90 : std_logic; + signal pgpReset : std_logic; + signal clk320 : std_logic; + signal reload : std_logic; + signal reloadc : std_logic_vector(3 downto 0); + signal extreload : std_logic; + signal resetOut : std_logic; + signal resetOutc : std_logic_vector(3 downto 0); + signal dispClk : std_logic; + signal dispDat : std_logic; + signal dispLoadL : std_logic_vector(1 downto 0); + signal dispRstL : std_logic; + signal debug : std_logic_vector(7 downto 0); + signal sysClk125i : std_logic; + signal mainClk : std_logic; + signal clk0 : std_logic; + signal clkin : std_logic; + signal halfclock : std_logic; + signal quarterclock : std_logic; + signal clockidctrl : std_logic; + signal idctrlrst : std_logic; + signal RD2b : std_logic; + signal AuxClkb : std_logic; + signal RAb : std_logic; + signal RD1b : std_logic; + signal IOMXINb : std_logic_vector(3 downto 0); + signal IOMXSELb : std_logic_vector(2 downto 0); + signal HITORb : std_logic; + signal HITORout : std_logic; + signal IOMXOUTb : std_logic_vector(2 downto 0); + signal SELALTBUSb : std_logic; + signal REGABDACLDb : std_logic; + signal REGABSTBLDb : std_logic; + signal SELCMDb : std_logic; + signal CMDEXTTRIGGERb : std_logic; + signal CMDALTPLSb : std_logic; + signal exttrigger : std_logic; + signal exttriggerinv : std_logic; + signal extrst : std_logic; + signal extrstinv : std_logic; + signal exttriggero : std_logic; + signal extrsto : std_logic; + signal extbusy : std_logic; + signal extbusyinv : std_logic; + signal exttrgclk : std_logic; + signal exttrgclkinv : std_logic; + signal hsiobusyb : std_logic; + signal hsiobusyinb : std_logic; + signal hsiotriggerb : std_logic_vector(1 downto 0); + signal serialoutb : std_logic_vector(15 downto 0); + signal serialoutm1 : std_logic_vector(15 downto 0); + signal serialoutm2 : std_logic_vector(15 downto 0); + signal serialinb : std_logic_vector(15 downto 0); + signal serialinm1 : std_logic_vector(15 downto 0); + signal serialinm2 : std_logic_vector(15 downto 0); + signal discinb : std_logic_vector(3 downto 0); + signal ccontrol : std_logic_vector(35 downto 0); + signal cdata : std_logic_vector(31 downto 0); + signal ctrig : std_logic_vector(0 downto 0); + signal opgpClk : std_logic; + signal dispDatA : std_logic; + signal dispDatB : std_logic; + signal pgpDispA : std_logic_vector(7 downto 0); + signal pgpDispB : std_logic_vector(7 downto 0); + signal dispDigitA : std_logic_vector(7 downto 0); + signal dispDigitB : std_logic_vector(7 downto 0); + signal dispDigitC : std_logic_vector(7 downto 0); + signal dispDigitD : std_logic_vector(7 downto 0); + signal dispDigitE : std_logic_vector(7 downto 0); + signal dispDigitF : std_logic_vector(7 downto 0); + signal dispDigitG : std_logic_vector(7 downto 0); + signal dispDigitH : std_logic_vector(7 downto 0); + signal dispStrobe : std_logic; + signal dispUpdateA : std_logic; + signal dispUpdateB : std_logic; + signal sysClkCnt : std_logic_vector(15 downto 0); + signal lockedid : std_logic; + signal oldlockedid : std_logic; + signal holdrst : std_logic; + signal holdctr : std_logic_vector(24 downto 0); + signal idcounter : std_logic_vector(2 downto 0); + + signal pgpClkUnbuf : std_logic; + signal pgpClk90Unbuf : std_logic; + signal sysClkUnbuf : std_logic; + signal disc : std_logic_vector(4 downto 0); + + signal calibmodec : Slv2Array(0 to 3); + signal calibmode : std_logic_vector(1 downto 0); + signal eudaqdone : std_logic; + signal eudaqtrgword : std_logic_vector(14 downto 0); + signal trigenabledc : std_logic_vector(3 downto 0); + signal trigenabled : std_logic; + signal pausedc : std_logic_vector(3 downto 0); + signal paused : std_logic; + signal triggermaskc : Slv16Array(0 to 3); + signal triggermask : std_logic_vector(15 downto 0); + signal resetdelayc : std_logic_vector(3 downto 0); + signal resetdelay : std_logic; + signal incrementdelayc: Slv5Array(0 to 3); + signal incrementdelay: std_logic_vector(4 downto 0); + signal discopc : Slv16Array(0 to 3); + signal discop : std_logic_vector(15 downto 0); + signal telescopeopc : Slv3Array(0 to 3); + signal telescopeop : std_logic_vector(2 downto 0); + signal periodc : Slv32Array(0 to 3); + signal period : std_logic_vector(31 downto 0); + signal fifothreshc : std_logic_vector(3 downto 0); + signal fifothresh : std_logic; + signal serbusyc : std_logic_vector(3 downto 0); + signal serbusy : std_logic; + signal tdcreadoutbusyc: std_logic_vector(3 downto 0); + signal tdcreadoutbusy: std_logic; + signal tcounter1 : std_logic_vector(31 downto 0); + signal tcounter2 : std_logic_vector(31 downto 0); + signal l1ac : std_logic_vector(3 downto 0); + signal l1a : std_logic; + signal triggerword : std_logic_vector(7 downto 0); + signal busy : std_logic; + signal rstFromCorec : std_logic_vector(3 downto 0); + signal rstFromCore : std_logic; + signal hitbus : std_logic_vector(3 downto 0); + signal present : std_logic_vector(3 downto 0); + signal phaseclkselc : std_logic_vector(3 downto 0); + signal phaseclksel : std_logic; + signal startmeasc : std_logic_vector(3 downto 0); + signal startmeas : std_logic; + signal dispDigitAA : Slv8Array(0 to 3); + signal dispDigitBB : Slv8Array(0 to 3); + signal dispDigitCC : Slv8Array(0 to 3); + signal dispDigitDD : Slv8Array(0 to 3); + signal transdissig : std_logic_vector(3 downto 0); + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + constant N_CORES: integer := 4; + constant N_CHANS: integer := 2; + +begin + + -- Reset input + U_ResetIn: IBUF port map ( I => iResetInL, O => resetInL ); + + -- PGP Clock Generator + U_PgpClkGen: entity work.PgpClkGen generic map ( + RefClkEn1 => "ENABLE", + RefClkEn2 => "DISABLE", + DcmClkSrc => "RefClk1", + UserFxDiv => 4, + UserFxMult => 2 + ) port map ( + pgpRefClkInP => iPgpRefClkP, + pgpRefClkInN => iPgpRefClkM, + ponResetL => resetInL, + locReset => resetOut, + pgpRefClk1 => refClock, + pgpRefClk2 => open, + pgpClk => pgpClk, + pgpClk90 => pgpClk90, + pgpReset => pgpReset, + clk320 => clk320, + pgpClkIn => pgpClk, + userClk => sysClk125, + userReset => sysRst125, + userClkIn => sysClk125, + pgpClkUnbuf => pgpClkUnbuf, + pgpClk90Unbuf => pgpClk90Unbuf, + locClkUnbuf => sysClkUnbuf + + + ); + + -- Generate Divided Clock, sample reset + process ( pgpClk ) begin + if rising_edge(pgpClk) then + tmpClk250 <= not tmpClk250 after tpd; + sysRst250 <= sysRst125 after tpd; + end if; + end process; + + -- Global Buffer For 125Mhz Clock + U_CLK125: BUFGMUX port map ( + O => sysClk250, + I0 => tmpClk250, + I1 => '0', + S => '0' + ); + + -- LED Display + U_DispClk : OBUF port map ( I => dispClk , O => oDispClk ); + U_DispDat : OBUF port map ( I => dispDat , O => oDispDat ); + U_DispLoadL1 : OBUF port map ( I => dispLoadL(1) , O => oDispLoadL(1) ); + U_DispLoadL0 : OBUF port map ( I => dispLoadL(0) , O => oDispLoadL(0) ); + U_DispRstL : OBUF port map ( I => dispRstL , O => oDispRstL ); + U_reload : OBUF port map ( I => reload , O => oReload ); + U_clkout40 : OBUF port map ( I => sysClk125i , O => clkout40 ); + U_refclk : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => sysClk125i , O => refclk_p , OB => refclk_n ); + U_xclk : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => sysClk125i , O => xclk_p , OB => xclk_n ); + + TRANSDISGEN: + for I in 0 to 3 generate + U_transdis : OBUF port map ( I => transdissig(I) , O => transDis(I) ); + end generate TRANSDISGEN; + + U_rd2 : OBUF port map ( I => RD2b , O => RD2); + U_auxclk : OBUF port map ( I => AuxClkb , O => AuxClk); + U_RA : OBUF port map ( I => RAb , O => RA ); + U_rd1 : OBUF port map ( I => RD1b , O => RD1 ); + U_IOMXIN3 : OBUF port map ( I => IOMXINb(3) , O => IOMXIN(3) ); + U_IOMXIN2 : OBUF port map ( I => IOMXINb(2) , O => IOMXIN(2) ); + U_IOMXIN1 : OBUF port map ( I => IOMXINb(1) , O => IOMXIN(1) ); + U_IOMXIN0 : OBUF port map ( I => IOMXINb(0) , O => IOMXIN(0) ); + U_IOMXSEL2 : OBUF port map ( I => IOMXSELb(2) , O => IOMXSEL(2) ); + U_IOMXSEL1 : OBUF port map ( I => IOMXSELb(1) , O => IOMXSEL(1) ); + U_IOMXSEL0 : OBUF port map ( I => IOMXSELb(0) , O => IOMXSEL(0) ); + U_HITOR : IBUF port map ( O => HITORb , I => HITOR); + U_IOMXOUT2 : IBUF port map ( O => IOMXOUTb(2) , I => IOMXOUT(2) ); + U_IOMXOUT1 : IBUF port map ( O => IOMXOUTb(1) , I => IOMXOUT(1) ); + U_IOMXOUT0 : IBUF port map ( O => IOMXOUTb(0) , I => IOMXOUT(0) ); + U_SELALTBUS : OBUF port map ( I => SELALTBUSb , O => SELALTBUS); + U_REGABDACLD : OBUF port map ( I => REGABDACLDb , O => REGABDACLD); + U_REGABSTBLD : OBUF port map ( I => REGABSTBLDb , O => REGABSTBLD); + U_SELCMD : OBUF port map ( I => SELCMDb , O => SELCMD ); + U_CMDEXTTRIGGER : OBUF port map ( I => CMDEXTTRIGGERb , O => CMDEXTTRIGGER ); + U_CMDALTPLS : OBUF port map ( I => CMDALTPLSb , O => CMDALTPLS ); + U_exttrgclk : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => exttrgclkinv , O => oExttrgclkP , OB => oExttrgclkN ); + exttrgclkinv<= not exttrgclk; + U_extbusy : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => extbusyinv , O => oExtBusyP , OB => oExtbusyN ); + extbusyinv<= not extbusy; + U_exttrigger : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => iExttriggerP , IB=>iExttriggerN , O => exttriggerinv ); + exttrigger<= not exttriggerinv; + U_extrst : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => iExtrstP , IB=>iExtrstN , O => extrstinv ); + extrst<= not extrstinv; + U_exttriggero : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => exttriggero , O => oExttriggerP , OB => oExttriggerN ); + + U_extrsto : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => extrsto , O => oExtrstP , OB => oExtrstN ); + + U_HSIObusy : OBUF port map ( I => hsiobusyb , O => oHSIObusy); + U_HSIOtriggero : OBUF port map ( I => l1a , O => oHSIOtrigger); + U_HSIOtrigger : IBUF port map ( O => hsiotriggerb(0) , I => iHSIOtrigger(0) ); + U_HSIOtrigger2 : IBUF port map ( O => hsiotriggerb(1) , I => iHSIOtrigger(1) ); + U_hsiobusyin : IBUF port map ( O => hsiobusyinb , I => iHSIObusy ); + U_extreload : IBUF port map ( O => extreload , I => iExtreload ); + + SERIAL_IO_DATA: + for I in 0 to 7 generate +-- U_serialin : IBUF port map ( I => serialin(I) , O => serialinb(I) ); + U_serialout_pn :OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => serialoutb(I) , O => serialout_p(I) , OB => serialout_n(I) ); + + U_serialin_pn : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => serialin_p(I) , IB=>serialin_n(I) , O => serialinb(I) ); + + end generate SERIAL_IO_DATA; + + U_serialout : OBUF port map ( I => serialoutb(8) , O => serialout(8) ); + U_serialin_pn_8 : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => serialin_p(8) , IB=>serialin_n(8) , O => serialinb(8) ); + +-- U_serialout11 : OBUF port map ( I => serialoutb(11) , O => serialout(11) ); +-- U_serialin11 : IBUF port map ( I => serialin(11) , O => serialinb(11) ); + SERIAL_IO_DATA_FEI3: + for I in 11 to 14 generate + U_serialout_pn :OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => serialoutb(I) , O => serialout_p(I) , OB => serialout_n(I) ); + + U_serialin_pn : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => serialin_p(I) , IB=>serialin_n(I) , O => serialinb(I) ); + + end generate SERIAL_IO_DATA_FEI3; + --DISC_1: IBUFDS port map ( O => discinb(0), I => discinP(0) , IB => discinN(0) ); + --DISC_2: IBUFDS port map ( O => discinb(1), I => discinP(1) , IB => discinN(1) ); + DISC_1: IBUF port map ( O => discinb(0), I => discinP(0) ); + DISC_2: IBUF port map ( O => discinb(1), I => discinP(1) ); + DISC_3: IBUF port map ( O => discinb(2), I => discinP(2) ); + DISC_4: IBUF port map ( O => discinb(3), I => discinP(3) ); + disc<= hitorb & discinb; + -- Display Controller A + U_DispCntrlA: entity work.DisplayControl port map ( + sysClk => sysClk125, sysRst => sysRst125, + dispStrobe => dispStrobe, dispUpdate => dispUpdateA, + dispRotate => "01", dispDigitA => dispDigitA, + dispDigitB => dispDigitB, dispDigitC => dispDigitC, + dispDigitD => dispDigitD, dispClk => dispClk, + dispDat => dispDatA, dispLoadL => dispLoadL(0), + dispRstL => dispRstL + ); + + -- Display Controller B + U_DispCntrlB: entity work.DisplayControl port map ( + sysClk => sysClk125, sysRst => sysRst125, + dispStrobe => dispStrobe, dispUpdate => dispUpdateB, + dispRotate => "01", dispDigitA => dispDigitE, + dispDigitB => dispDigitF, dispDigitC => dispDigitG, + dispDigitD => dispDigitH, dispClk => open, + dispDat => dispDatB, dispLoadL => dispLoadL(1), + dispRstL => open + ); + -- Output LED Data + dispDat <= dispDatA or dispDatB; + -- Generate display strobe (200ns) and update control + process ( sysClk125, sysRst125 ) begin + if sysRst125 = '1' then + sysClkCnt <= (others=>'0') after tpd; + dispStrobe <= '0' after tpd; + dispUpdateA <= '0' after tpd; + dispUpdateB <= '0' after tpd; + elsif rising_edge(sysClk125) then + + -- Display strobe, 320ns + dispStrobe <= sysClkCnt(4) after tpd; + + -- Update Display 0 + if sysClkCnt(15 downto 0) = x"8000" then + dispUpdateA <= '1' after tpd; + else + dispUpdateA <= '0' after tpd; + end if; + + -- Update Display B + if sysClkCnt(15 downto 0) = x"0000" then + dispUpdateB <= '1' after tpd; + else + dispUpdateB <= '0' after tpd; + end if; + + -- Update counter + sysClkCnt <= sysClkCnt + 1 after tpd; + + + end if; + end process; + + paused <= uOr(pausedc); + resetdelay <= uOr(resetdelayc); + incrementdelay <= incrementdelayc(0) or incrementdelayc(1) or incrementdelayc (2) or incrementdelayc(3); + serbusy <= uOr(serbusyc and present); + tdcreadoutbusy<= uOr(tdcreadoutbusyc); + rstFromCore <= uOr(rstFromCorec); + + fifothresh <= uOr(fifothreshc and present); + trigenabled <= uAnd(trigenabledc or not present) and uOr(present); + + reload <= uAnd(reloadc) and extreload; -- active low + resetOut <= uOr(resetOutc); + + process(present, discopc) begin + if(present(0)='1')then discop<=discopc(0); + elsif(present(1)='1')then discop<=discopc(1); + elsif(present(2)='1')then discop<=discopc(2); + else discop<=discopc(3); + end if; + end process; + + process(present, calibmodec) begin + if(present(0)='1')then calibmode<=calibmodec(0); + elsif(present(1)='1')then calibmode<=calibmodec(1); + elsif(present(2)='1')then calibmode<=calibmodec(2); + else calibmode<=calibmodec(3); + end if; + end process; + + process(present, triggermaskc) begin + if(present(0)='1')then triggermask<=triggermaskc(0); + elsif(present(1)='1')then triggermask<=triggermaskc(1); + elsif(present(2)='1')then triggermask<=triggermaskc(2); + else triggermask<=triggermaskc(3); + end if; + end process; + + process(present, periodc) begin + if(present(0)='1')then period<=periodc(0); + elsif(present(1)='1')then period<=periodc(1); + elsif(present(2)='1')then period<=periodc(2); + else period<=periodc(3); + end if; + end process; + + process(present, telescopeopc) begin + if(present(0)='1')then telescopeop<=telescopeopc(0); + elsif(present(1)='1')then telescopeop<=telescopeopc(1); + elsif(present(2)='1')then telescopeop<=telescopeopc(2); + else telescopeop<=telescopeopc(3); + end if; + end process; + + process(present, phaseclkselc) begin + if(present(0)='1')then phaseclksel<=phaseclkselc(0); + elsif(present(1)='1')then phaseclksel<=phaseclkselc(1); + elsif(present(2)='1')then phaseclksel<=phaseclkselc(2); + else phaseclksel<=phaseclkselc(3); + end if; + end process; + + process(present, startmeasc) begin + if(present(0)='1')then startmeas<=startmeasc(0); + elsif(present(1)='1')then startmeas<=startmeasc(1); + elsif(present(2)='1')then startmeas<=startmeasc(2); + else startmeas<=startmeasc(3); + end if; + end process; + + U_triggerlogic: entity work.triggerlogic + port map( + clk => sysClk125, + rst => rstFromCore, + -- hardware inputs + discin => disc, + hitbusin => hitbus(1 downto 0), + -- HSIO trigger + HSIObusy => hsiobusyb, + HSIOtrigger => hsiotriggerb, + HSIObusyin => hsiobusyinb, + hitbusout => open, + + -- eudet trigger + exttrigger => exttrigger, + extrst => extrst, + extbusy => extbusy, + exttrgclk => exttrgclk, + + calibmode => calibmode, + startmeas => startmeas, + eudaqdone => eudaqdone, + eudaqtrgword => eudaqtrgword, + tcounter1 => tcounter1, + tcounter2 => tcounter2, + + trigenabled => trigenabled, + paused => paused, + triggermask => triggermask, + resetdelay => resetdelay, + incrementdelay => incrementdelay, + discop => discop, + telescopeop => telescopeop, + period => period, + fifothresh => fifothresh, + serbusy => serbusy, + tdcreadoutbusy => tdcreadoutbusy, + phaseclksel => phaseclksel, + l1a => l1a, + triggerword => triggerword, + busy =>busy, + coincd =>open +); + + -- FPGA Core + HSIOCORES: + for I in 0 to N_CORES-1 generate + U_HsioCosmicCorex: entity work.HsioPixelCore + generic map( framedFirstChannel=> 0, + framedLastChannel=> N_CHANS-1, + rawFirstChannel => 11, + rawLastChannel => 10, + buffersize => 8192, + bpmDefault => '0', + hitbusreadout => '0') + port map ( + sysClk250 => sysClk250, sysRst250 => sysRst250, + sysClk125 => sysClk125, sysRst125 => sysRst125, + refClock => refClock, pgpClk => pgpClk, + pgpClk90 => pgpClk90, pgpReset => pgpReset, + clk320 => clk320, reload => reloadc(I), + mgtRxN => iMgtRxN(I), + mgtRxP => iMgtRxP(I), mgtTxN => oMgtTxN(I), + mgtTxP => oMgtTxP(I), + serialin(N_CHANS-1 downto 0) => serialinb(N_CHANS*(I+1)-1 downto I*N_CHANS), + serialin(15 downto N_CHANS) => (others => '0'), + serialout(N_CHANS-1 downto 0) => serialoutb(N_CHANS*(I+1)-1 downto I*N_CHANS), + serialout(15 downto N_CHANS) => open, + clock160 => pgpClk, + clock80 => halfclock, clock40 => quarterclock, + resetOut => resetOutc(I), l1a => l1ac(I), + latchtriggerword => triggerword, tcounter1=>tcounter1, + tcounter2 => tcounter2, busy =>busy, + eudaqdone => eudaqdone, eudaqtrgword => eudaqtrgword, + calibmodeout => calibmodec(I), startmeas => startmeasc(I), + pausedout => pausedc(I), present => present(I), + trgenabledout => trigenabledc(I), rstFromCore => rstFromCorec(I), + fifothresh => fifothreshc(I), triggermask => triggermaskc(I), + discop => discopc(I), period => periodc(I), + telescopeop => telescopeopc(I), resetdelay => resetdelayc(I), + incrementdelay => incrementdelayc(I), + sbusy => serbusyc(I), tdcbusy => tdcreadoutbusyc(I), + phaseclksel => phaseclkselc(I) , hitbus => hitbus(I), + debug => open, + exttriggero => open, extrsto => open, + doricreset => open, + dispDigitA => dispDigitAA(I), dispDigitB => dispDigitBB(I), + dispDigitC => dispDigitCC(I), dispDigitD => dispDigitDD(I), + dispDigitE => open, dispDigitF => open, + dispDigitG => open, dispDigitH => open, + pgpClkUnbuf => pgpClkUnbuf, pgpClk90Unbuf => pgpClk90Unbuf, + sysClkUnbuf => sysClkUnbuf + ); + l1ac(I) <= l1a and present(I); + transdissig(I)<='0'; + end generate HSIOCORES; + FILLVECTORS: + for I in N_CORES to 3 generate + dispDigitAA(I)<=x"00"; + dispDigitBB(I)<=x"00"; + dispDigitCC(I)<=x"00"; + dispDigitDD(I)<=x"00"; + transdissig(I)<='1'; -- disable fiber + present(I)<='0'; + hitbus(I)<='0'; + pausedc(I)<='0'; + resetdelayc(I)<='0'; + incrementdelayc(I)<="00000"; + serbusyc(I)<='0'; + tdcreadoutbusyc(I)<='0'; + rstFromCorec(I)<='0'; + fifothreshc(I)<='0'; + trigenabledc(I)<='0'; + l1ac(I)<='0'; + reloadc(I)<='1'; -- inverted logic + discopc(I)<=(others =>'0'); + calibmodec(I)<=(others =>'0'); + triggermaskc(I)<=(others =>'0'); + periodc(I)<=(others =>'0'); + telescopeopc(I)<=(others =>'0'); + phaseclkselc(I)<='0'; + startmeasc(I)<='0'; + end generate FILLVECTORS; + dispDigitE<=dispDigitAA(0); + dispDigitF<=dispDigitAA(1); + dispDigitG<=dispDigitAA(2); + dispDigitH<=dispDigitAA(3); + dispDigitA<=dispDigitBB(0); + dispDigitB<=dispDigitBB(1); + dispDigitC<=dispDigitBB(2); + dispDigitD<=dispDigitDD(0); + + sysClk125i <= not sysClk125; + --sysClk125i<=debug(0); + U_clock160: entity work.clock160 port map( + CLKIN_N_IN => iMainClkN, + CLKIN_P_IN => iMainClkP, + RST_IN => sysRst125, + CLKFX_OUT => mainClk, + CLKIN_IBUFGDS_OUT => clkin, + CLK0_OUT => clk0, + LOCKED_OUT => open); + + process(mainClk) + begin + if(mainClk'event and mainClk='1') then + halfclock<= not halfclock; + end if; + end process; + process(halfclock) + begin + if(halfclock'event and halfclock='1') then + quarterclock<= not quarterclock; + end if; + end process; + U_idelctrlclk: entity work.clock200 port map( + CLKIN_IN => mainClk, + RST_IN => holdrst, + CLKFX_OUT => clockidctrl, + CLK0_OUT => open, + LOCKED_OUT => lockedid); + U_idelayctrl: IDELAYCTRL port map( + RDY => open, + REFCLK => clockidctrl, + RST => idctrlrst); + + process(sysRst125, sysClk125) -- clock interface + begin + if (sysRst125='1') then + holdctr<=(others=>'1'); + holdrst<='1'; + elsif(sysClk125'event and sysClk125='1') then + if (holdctr(24)='0') then + holdrst<='0'; + end if; + holdctr<=unsigned(holdctr)-1; + end if; + end process; + + process(sysClk125, sysRst125) -- reset logic for IDELAYCTRL + begin + if(sysRst125='1') then + idctrlrst<='0'; + idcounter<="000"; + oldlockedid<='0'; + elsif(sysClk125'event and sysClk125='1') then + if(lockedid='1' and oldlockedid='0')then + idcounter<="111"; + idctrlrst<='1'; + elsif(unsigned(idcounter)>0)then + idcounter<=unsigned(idcounter)-1; + else + idctrlrst<='0'; + end if; + oldlockedid<=lockedid; + end if; + end process; + +end HsioCosmic; diff --git a/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd.oldCosmic b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd.oldCosmic new file mode 100644 index 00000000..ca724008 --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd.oldCosmic @@ -0,0 +1,668 @@ +------------------------------------------------------------------------------- +-- Title : BNL ASIC Test FGPA, Top Level +-- Project : LCLS Detector, BNL ASIC +------------------------------------------------------------------------------- +-- File : HsioCosmic.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 07/21/2008 +------------------------------------------------------------------------------- +-- Description: +-- Top level logic for BNL ASIC test FPGA. +------------------------------------------------------------------------------- +-- Copyright (c) 2008 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 07/21/2008: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +Library Unisim; +USE ieee. std_logic_1164.ALL; +use ieee. std_logic_arith.all; +use ieee. std_logic_unsigned.all; +USE work.ALL; + +entity HsioCosmic is + port ( + + -- PGP Crystal Clock Input, 156.25Mhz + iPgpRefClkP : in std_logic; + iPgpRefClkM : in std_logic; + + -- System clock 125 MHz clock input + iMainClkP : in std_logic; + iMainClkN : in std_logic; + + -- PGP Rx/Tx Lines + iMgtRxN : in std_logic; + iMgtRxP : in std_logic; + oMgtTxN : out std_logic; + oMgtTxP : out std_logic; + + -- ATLAS Pixel module pins + serialin : in std_logic_vector(15 downto 0); + serialout : out std_logic_vector(15 downto 0); + serialout_p : out std_logic_vector(15 downto 0); + serialout_n : out std_logic_vector(15 downto 0); + serialin_p : in std_logic_vector(15 downto 0); + serialin_n : in std_logic_vector(15 downto 0); + discinP : in std_logic_vector(3 downto 0); +-- discinN : in std_logic_vector(1 downto 0); + clkout40 : out std_logic; + refclk_p : out std_logic; + refclk_n : out std_logic; + xclk_p : out std_logic; + xclk_n : out std_logic; + + -- Reset button + iResetInL : in std_logic; + -- Reload firmware + oReload : out std_logic; + iExtreload : in std_logic; + -- LED Display + oDispClk : out std_logic; + oDispDat : out std_logic; + oDispLoadL : out std_logic_vector(1 downto 0); + oDispRstL : out std_logic; + + -- Debug + oDebug : out std_logic_vector(7 downto 0); + + -- Eudet trigger + iExttriggerP : in std_logic; + iExttriggerN : in std_logic; + iExtrstP : in std_logic; + iExtrstN : in std_logic; + oExtbusyP : out std_logic; + oExtbusyN : out std_logic; + oExttrgclkP : out std_logic; + oExttrgclkN : out std_logic; + + --HSIO trigger IF + iHSIOtrigger : in std_logic_vector(1 downto 0); + oHSIOtrigger : out std_logic; + oHSIObusy : out std_logic; + iHSIObusy : in std_logic; + + -- Eudet test + oExtrstP : out std_logic; + oExtrstN : out std_logic; + oExttriggerP : out std_logic; + oExttriggerN : out std_logic; + + + -- Misc Signals + oPdBuff0 : out std_logic; + oPdBuff1 : out std_logic; + oPdBuff3 : out std_logic; + oPdBuff4 : out std_logic; + oLemoA : out std_logic; + iLemoB : in std_logic; + + -- Transmitter enable + transDis1 : out std_logic; + -- CMOS chip I/O + RD2 : out std_logic; + AuxClk : out std_logic; + RA : out std_logic; + RD1 : out std_logic; + IOMXIN : out std_logic_vector(3 downto 0); + IOMXSEL : out std_logic_vector(2 downto 0); + HITOR : in std_logic; + IOMXOUT : in std_logic_vector(2 downto 0); + SELALTBUS : out std_logic; + REGABDACLD : out std_logic; + REGABSTBLD : out std_logic; + SELCMD : out std_logic; + CMDEXTTRIGGER : out std_logic; + CMDALTPLS : out std_logic + ); +end HsioCosmic; + + +-- Define architecture for top level module +architecture HsioCosmic of HsioCosmic is + + -- Synthesis control attributes + attribute syn_useioff : boolean; + attribute syn_useioff of HsioCosmic : architecture is true; + attribute xc_fast_auto : boolean; + attribute xc_fast_auto of HsioCosmic : architecture is false; + attribute syn_noclockbuf : boolean; + attribute syn_noclockbuf of HsioCosmic : architecture is true; + + -- IO Pad components + component IBUF port ( O : out std_logic; I : in std_logic ); end component; + component OBUF port ( O : out std_logic; I : in std_logic ); end component; + component OBUFDS + generic( IOSTANDARD: STRING:= "LVDS_25"; + SLEW: STRING:="FAST"); + port ( O : out std_logic; OB : out std_logic; I : in std_logic ); + end component; + + -- Input LVDS with termination + component IBUFDS + generic ( DIFF_TERM : boolean := TRUE; + IOSTANDARD: STRING := "LVDS_25"); + port ( O : out std_logic; I : in std_logic; IB : in std_logic ); + end component; + + -- Xilinx global clock buffer component + component BUFGMUX + port ( + O : out std_logic; + I0 : in std_logic; + I1 : in std_logic; + S : in std_logic + ); + end component; + + component IDELAYCTRL + port ( RDY : out std_logic; + REFCLK : in std_logic; + RST : in std_logic + ); + end component; + +component IDELAY + generic (IOBDELAY_TYPE : string := "DEFAULT"; --(DEFAULT, FIXED, VARIABLE) + IOBDELAY_VALUE : integer := 0 --(0 to 63) + ); + port ( + O : out STD_LOGIC; + I : in STD_LOGIC; + C : in STD_LOGIC; + CE : in STD_LOGIC; + INC : in STD_LOGIC; + RST : in STD_LOGIC + ); +end component; + + + -- Local signals + signal resetInL : std_logic; + signal tmpClk250 : std_logic; + signal sysClk125 : std_logic; + signal sysRst125 : std_logic; + signal sysRst250 : std_logic; + signal sysClk250 : std_logic; + signal refClock : std_logic; + signal pgpClk : std_logic; + signal pgpClk90 : std_logic; + signal pgpReset : std_logic; + signal clk320 : std_logic; + signal reload : std_logic; + signal reload1 : std_logic; + signal extreload : std_logic; + signal resetOut : std_logic; + signal mgtRxN : std_logic; + signal mgtRxP : std_logic; + signal mgtTxN : std_logic; + signal mgtTxP : std_logic; + signal dispClk : std_logic; + signal dispDat : std_logic; + signal dispLoadL : std_logic_vector(1 downto 0); + signal dispRstL : std_logic; + signal debug : std_logic_vector(7 downto 0); + signal sysClk125i : std_logic; + signal mainClk : std_logic; + signal clk0 : std_logic; + signal clkin : std_logic; + signal halfclock : std_logic; + signal quarterclock : std_logic; + signal clockidctrl : std_logic; + signal idctrlrst : std_logic; + signal RD2b : std_logic; + signal AuxClkb : std_logic; + signal RAb : std_logic; + signal RD1b : std_logic; + signal IOMXINb : std_logic_vector(3 downto 0); + signal IOMXSELb : std_logic_vector(2 downto 0); + signal HITORb : std_logic; + signal IOMXOUTb : std_logic_vector(2 downto 0); + signal SELALTBUSb : std_logic; + signal REGABDACLDb : std_logic; + signal REGABSTBLDb : std_logic; + signal SELCMDb : std_logic; + signal CMDEXTTRIGGERb : std_logic; + signal CMDALTPLSb : std_logic; + signal exttrigger : std_logic; + signal exttriggerinv : std_logic; + signal extrst : std_logic; + signal extrstinv : std_logic; + signal exttriggero : std_logic; + signal extrsto : std_logic; + signal extbusy : std_logic; + signal extbusyinv : std_logic; + signal exttrgclk : std_logic; + signal exttrgclkinv : std_logic; + signal hsiobusyb : std_logic; + signal hsiobusyinb : std_logic; + signal hsiotriggerb : std_logic_vector(1 downto 0); + signal serialoutb : std_logic_vector(15 downto 0); + signal serialinb : std_logic_vector(15 downto 0); + signal discinb : std_logic_vector(3 downto 0); + signal ccontrol : std_logic_vector(35 downto 0); + signal cdata : std_logic_vector(31 downto 0); + signal ctrig : std_logic_vector(0 downto 0); + signal opgpClk : std_logic; + signal dispDatA : std_logic; + signal dispDatB : std_logic; + signal pgpDispA : std_logic_vector(7 downto 0); + signal pgpDispB : std_logic_vector(7 downto 0); + signal dispDigitA : std_logic_vector(7 downto 0); + signal dispDigitB : std_logic_vector(7 downto 0); + signal dispDigitC : std_logic_vector(7 downto 0); + signal dispDigitD : std_logic_vector(7 downto 0); + signal dispDigitE : std_logic_vector(7 downto 0); + signal dispDigitF : std_logic_vector(7 downto 0); + signal dispDigitG : std_logic_vector(7 downto 0); + signal dispDigitH : std_logic_vector(7 downto 0); + signal dispStrobe : std_logic; + signal dispUpdateA : std_logic; + signal dispUpdateB : std_logic; + signal sysClkCnt : std_logic_vector(15 downto 0); + signal lockedid : std_logic; + signal oldlockedid : std_logic; + signal holdrst : std_logic; + signal holdctr : std_logic_vector(24 downto 0); + signal idcounter : std_logic_vector(2 downto 0); + + signal pgpClkUnbuf : std_logic; + signal pgpClk90Unbuf : std_logic; + signal sysClkUnbuf : std_logic; + signal disc : std_logic_vector(4 downto 0); + + signal calibmode1 : std_logic_vector(1 downto 0); + signal calibmode2 : std_logic_vector(1 downto 0); + signal calibmode : std_logic_vector(1 downto 0); + signal eudaqdone : std_logic; + signal eudaqtrgword : std_logic_vector(14 downto 0); + signal trigenabled : std_logic; + signal paused : std_logic; + signal triggermask : std_logic_vector(15 downto 0); + signal resetdelay : std_logic; + signal incrementdelay: std_logic_vector(4 downto 0); + signal discop : std_logic_vector(15 downto 0); + signal telescopeop : std_logic_vector(2 downto 0); + signal period : std_logic_vector(31 downto 0); + signal fifothresh : std_logic; + signal serbusy : std_logic; + signal tdcreadoutbusy: std_logic; + signal tcounter1 : std_logic_vector(31 downto 0); + signal tcounter2 : std_logic_vector(31 downto 0); + signal l1a : std_logic; + signal triggerword : std_logic_vector(7 downto 0); + signal busy : std_logic; + signal rstFromCore : std_logic; + signal phaseclksel : std_logic; + signal hitbus : std_logic_vector(1 downto 0); + signal startmeas : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Reset input + U_ResetIn: IBUF port map ( I => iResetInL, O => resetInL ); + + -- PGP Clock Generator + U_PgpClkGen: entity work.PgpClkGen generic map ( + RefClkEn1 => "ENABLE", + RefClkEn2 => "DISABLE", + DcmClkSrc => "RefClk1", + UserFxDiv => 4, + UserFxMult => 2 + ) port map ( + pgpRefClkInP => iPgpRefClkP, + pgpRefClkInN => iPgpRefClkM, + ponResetL => resetInL, + locReset => resetOut, + pgpRefClk1 => refClock, + pgpRefClk2 => open, + pgpClk => pgpClk, + pgpClk90 => pgpClk90, + pgpReset => pgpReset, + clk320 => clk320, + pgpClkIn => pgpClk, + userClk => sysClk125, + userReset => sysRst125, + userClkIn => sysClk125, + pgpClkUnbuf => pgpClkUnbuf, + pgpClk90Unbuf => pgpClk90Unbuf, + locClkUnbuf => sysClkUnbuf + + + ); + + -- Generate Divided Clock, sample reset + process ( pgpClk ) begin + if rising_edge(pgpClk) then + tmpClk250 <= not tmpClk250 after tpd; + sysRst250 <= sysRst125 after tpd; + end if; + end process; + + -- Global Buffer For 125Mhz Clock + U_CLK125: BUFGMUX port map ( + O => sysClk250, + I0 => tmpClk250, + I1 => '0', + S => '0' + ); + + -- No Pads for MGT Lines + mgtRxN <= iMgtRxN; + mgtRxP <= iMgtRxP; + oMgtTxN <= mgtTxN; + oMgtTxP <= mgtTxP; + + -- LED Display + U_DispClk : OBUF port map ( I => dispClk , O => oDispClk ); + U_DispDat : OBUF port map ( I => dispDat , O => oDispDat ); + U_DispLoadL1 : OBUF port map ( I => dispLoadL(1) , O => oDispLoadL(1) ); + U_DispLoadL0 : OBUF port map ( I => dispLoadL(0) , O => oDispLoadL(0) ); + U_DispRstL : OBUF port map ( I => dispRstL , O => oDispRstL ); + U_reload : OBUF port map ( I => reload , O => oReload ); + U_clkout40 : OBUF port map ( I => sysClk125i , O => clkout40 ); + U_refclk : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => sysClk125i , O => refclk_p , OB => refclk_n ); + U_xclk : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => sysClk125i , O => xclk_p , OB => xclk_n ); + + U_transdis : OBUF port map ( I => '0' , O => transDis1 ); + + U_rd2 : OBUF port map ( I => RD2b , O => RD2); + U_auxclk : OBUF port map ( I => AuxClkb , O => AuxClk); + U_RA : OBUF port map ( I => RAb , O => RA ); + U_rd1 : OBUF port map ( I => RD1b , O => RD1 ); + U_IOMXIN3 : OBUF port map ( I => IOMXINb(3) , O => IOMXIN(3) ); + U_IOMXIN2 : OBUF port map ( I => IOMXINb(2) , O => IOMXIN(2) ); + U_IOMXIN1 : OBUF port map ( I => IOMXINb(1) , O => IOMXIN(1) ); + U_IOMXIN0 : OBUF port map ( I => IOMXINb(0) , O => IOMXIN(0) ); + U_IOMXSEL2 : OBUF port map ( I => IOMXSELb(2) , O => IOMXSEL(2) ); + U_IOMXSEL1 : OBUF port map ( I => IOMXSELb(1) , O => IOMXSEL(1) ); + U_IOMXSEL0 : OBUF port map ( I => IOMXSELb(0) , O => IOMXSEL(0) ); + U_HITOR : IBUF port map ( O => HITORb , I => HITOR); + U_IOMXOUT2 : IBUF port map ( O => IOMXOUTb(2) , I => IOMXOUT(2) ); + U_IOMXOUT1 : IBUF port map ( O => IOMXOUTb(1) , I => IOMXOUT(1) ); + U_IOMXOUT0 : IBUF port map ( O => IOMXOUTb(0) , I => IOMXOUT(0) ); + U_SELALTBUS : OBUF port map ( I => SELALTBUSb , O => SELALTBUS); + U_REGABDACLD : OBUF port map ( I => REGABDACLDb , O => REGABDACLD); + U_REGABSTBLD : OBUF port map ( I => REGABSTBLDb , O => REGABSTBLD); + U_SELCMD : OBUF port map ( I => SELCMDb , O => SELCMD ); + U_CMDEXTTRIGGER : OBUF port map ( I => CMDEXTTRIGGERb , O => CMDEXTTRIGGER ); + U_CMDALTPLS : OBUF port map ( I => CMDALTPLSb , O => CMDALTPLS ); + U_exttrgclk : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => exttrgclkinv , O => oExttrgclkP , OB => oExttrgclkN ); + exttrgclkinv<= not exttrgclk; + U_extbusy : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => extbusyinv , O => oExtBusyP , OB => oExtbusyN ); + extbusyinv<= not extbusy; + U_exttrigger : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => iExttriggerP , IB=>iExttriggerN , O => exttriggerinv ); + exttrigger<= not exttriggerinv; + U_extrst : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => iExtrstP , IB=>iExtrstN , O => extrstinv ); + extrst<= not extrstinv; + U_exttriggero : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => exttriggero , O => oExttriggerP , OB => oExttriggerN ); + + U_extrsto : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => extrsto , O => oExtrstP , OB => oExtrstN ); + + U_HSIObusy : OBUF port map ( I => hsiobusyb , O => oHSIObusy); + U_HSIOtrigger : IBUF port map ( O => hsiotriggerb(0) , I => iHSIOtrigger(0) ); + U_HSIOtrigger2 : IBUF port map ( O => hsiotriggerb(1) , I => iHSIOtrigger(1) ); + U_hsiobusyin : IBUF port map ( O => hsiobusyinb , I => iHSIObusy ); + U_extreload : IBUF port map ( O => extreload , I => iExtreload ); + U_HSIOtriggero : OBUF port map ( O => oHSIOtrigger , I => l1a ); + +-- SERIAL_IO_DATA: +-- for I in 0 to 7 generate +-- U_serialin : IBUF port map ( I => serialin(I) , O => serialinb(I) ); +-- U_serialout_pn :OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") +-- port map ( I => serialoutb(I) , O => serialout_p(I) , OB => serialout_n(I) ); +-- +-- U_serialin_pn : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") +-- port map ( I => serialin_p(I) , IB=>serialin_n(I) , O => serialinb(I) ); +-- +-- end generate SERIAL_IO_DATA; + + U_serialout : OBUF port map ( I => serialoutb(0) , O => serialout(0) ); + U_serialin1 : IBUF port map ( I => serialin(0) , O => serialinb(0) ); + U_serialin_pn_0 : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => serialin_p(8) , IB=>serialin_n(8) , O => serialinb(8) ); + +-- U_serialout11 : OBUF port map ( I => serialoutb(11) , O => serialout(11) ); +-- U_serialin11 : IBUF port map ( I => serialin(11) , O => serialinb(11) ); + SERIAL_IO_DATA_FEI3: + for I in 11 to 14 generate + U_serialout_pn :OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => serialoutb(I) , O => serialout_p(I) , OB => serialout_n(I) ); + + U_serialin_pn : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => serialin_p(I) , IB=>serialin_n(I) , O => serialinb(I) ); + + end generate SERIAL_IO_DATA_FEI3; + --DISC_1: IBUFDS port map ( O => discinb(0), I => discinP(0) , IB => discinN(0) ); + --DISC_2: IBUFDS port map ( O => discinb(1), I => discinP(1) , IB => discinN(1) ); + DISC_1: IBUF port map ( O => discinb(0), I => discinP(0) ); + DISC_2: IBUF port map ( O => discinb(1), I => discinP(1) ); + DISC_3: IBUF port map ( O => discinb(2), I => discinP(2) ); + DISC_4: IBUF port map ( O => discinb(3), I => discinP(3) ); + -- Display Controller A + U_DispCntrlA: entity work.DisplayControl port map ( + sysClk => sysClk125, sysRst => sysRst125, + dispStrobe => dispStrobe, dispUpdate => dispUpdateA, + dispRotate => "01", dispDigitA => dispDigitA, + dispDigitB => dispDigitB, dispDigitC => dispDigitC, + dispDigitD => dispDigitD, dispClk => dispClk, + dispDat => dispDatA, dispLoadL => dispLoadL(0), + dispRstL => dispRstL + ); + + -- Display Controller B + U_DispCntrlB: entity work.DisplayControl port map ( + sysClk => sysClk125, sysRst => sysRst125, + dispStrobe => dispStrobe, dispUpdate => dispUpdateB, + dispRotate => "01", dispDigitA => dispDigitE, + dispDigitB => dispDigitF, dispDigitC => dispDigitG, + dispDigitD => dispDigitH, dispClk => open, + dispDat => dispDatB, dispLoadL => dispLoadL(1), + dispRstL => open + ); + -- Output LED Data + dispDat <= dispDatA or dispDatB; + -- Generate display strobe (200ns) and update control + process ( sysClk125, sysRst125 ) begin + if sysRst125 = '1' then + sysClkCnt <= (others=>'0') after tpd; + dispStrobe <= '0' after tpd; + dispUpdateA <= '0' after tpd; + dispUpdateB <= '0' after tpd; + elsif rising_edge(sysClk125) then + + -- Display strobe, 320ns + dispStrobe <= sysClkCnt(4) after tpd; + + -- Update Display 0 + if sysClkCnt(15 downto 0) = x"8000" then + dispUpdateA <= '1' after tpd; + else + dispUpdateA <= '0' after tpd; + end if; + + -- Update Display B + if sysClkCnt(15 downto 0) = x"0000" then + dispUpdateB <= '1' after tpd; + else + dispUpdateB <= '0' after tpd; + end if; + + -- Update counter + sysClkCnt <= sysClkCnt + 1 after tpd; + + + end if; + end process; + + + U_triggerlogic: entity work.triggerlogic + port map( + clk => sysClk125, + rst => rstFromCore, + -- hardware inputs + discin => discinb, + hitbusin => hitbus, + -- HSIO trigger + HSIObusy => hsiobusyb, + HSIOtrigger => hsiotriggerb, + HSIObusyin => hsiobusyinb, + hitbusout => open, + + -- eudet trigger + exttrigger => exttrigger, + extrst => extrst, + extbusy => extbusy, + exttrgclk => exttrgclk, + + calibmode => calibmode, + startmeas => startmeas, + eudaqdone => eudaqdone, + eudaqtrgword => eudaqtrgword, + tcounter1 => tcounter1, + tcounter2 => tcounter2, + + trigenabled => trigenabled, + paused => paused, + triggermask => triggermask, + resetdelay => resetdelay, + incrementdelay => incrementdelay, + discop => discop, + telescopeop => telescopeop, + period => period, + fifothresh => fifothresh, + serbusy => serbusy, + tdcreadoutbusy => tdcreadoutbusy, + phaseclksel => phaseclksel, + l1a => l1a, + triggerword => triggerword, + busy =>busy, + coincd =>open +); + + -- FPGA Core + U_HsioCosmicCore1: entity work.HsioPixelCore + generic map( framedFirstChannel=> 0, + framedLastChannel=> 0, + rawFirstChannel => 11, + rawLastChannel => 10, + buffersizefe => 16384, + buffersizetdc => 4096, + fixed160 => '0', + bpmDefault => '0', + hitbusreadout => '0') + port map ( + sysClk250 => sysClk250, sysRst250 => sysRst250, + sysClk125 => sysClk125, sysRst125 => sysRst125, + refClock => refClock, pgpClk => pgpClk, + pgpClk90 => pgpClk90, pgpReset => pgpReset, + clk320 => clk320, reload => reload1, + mgtRxN => mgtRxN, + mgtRxP => mgtRxP, mgtTxN => mgtTxN, + mgtTxP => mgtTxP, serialin => serialinb, + serialout => serialoutb, clock160 => pgpClk, + clock80 => halfclock, clock40 => quarterclock, + resetOut => resetOut, l1a => l1a, + latchtriggerword => triggerword, tcounter1=>tcounter1, + tcounter2 => tcounter2, busy =>busy, + eudaqdone => eudaqdone, eudaqtrgword => eudaqtrgword, + calibmodeout => calibmode, startmeas => startmeas, + pausedout => paused, present =>open, + trgenabledout => trigenabled, rstFromCore => rstFromCore, + fifothresh => fifothresh, triggermask => triggermask, + discop => discop, period => period, + telescopeop => telescopeop, resetdelay => resetdelay, + incrementdelay => incrementdelay, + sbusy => serbusy, tdcbusy => tdcreadoutbusy, + phaseclksel => phaseclksel, hitbus => hitbus(0), + debug => debug, + exttriggero => exttriggero, extrsto => extrsto, + doricreset => open, + dispDigitA => dispDigitA, dispDigitB => dispDigitB, + dispDigitC => dispDigitC, dispDigitD => dispDigitD, + dispDigitE => dispDigitE, dispDigitF => dispDigitF, + dispDigitG => dispDigitF, dispDigitH => dispDigitH, + pgpClkUnbuf => pgpClkUnbuf, pgpClk90Unbuf => pgpClk90Unbuf, + sysClkUnbuf => sysClkUnbuf + ); + sysClk125i <= not sysClk125; + reload <= reload1 and extreload; -- active low + --sysClk125i<=debug(0); + U_clock160: entity work.clock160 port map( + CLKIN_N_IN => iMainClkN, + CLKIN_P_IN => iMainClkP, + RST_IN => sysRst125, + CLKFX_OUT => mainClk, + CLKIN_IBUFGDS_OUT => clkin, + CLK0_OUT => clk0, + LOCKED_OUT => open); + + process(mainClk) + begin + if(mainClk'event and mainClk='1') then + halfclock<= not halfclock; + end if; + end process; + process(halfclock) + begin + if(halfclock'event and halfclock='1') then + quarterclock<= not quarterclock; + end if; + end process; + U_idelctrlclk: entity work.clock200 port map( + CLKIN_IN => mainClk, + RST_IN => holdrst, + CLKFX_OUT => clockidctrl, + CLK0_OUT => open, + LOCKED_OUT => lockedid); + U_idelayctrl: IDELAYCTRL port map( + RDY => open, + REFCLK => clockidctrl, + RST => idctrlrst); + + process(sysRst125, sysClk125) -- clock interface + begin + if (sysRst125='1') then + holdctr<=(others=>'1'); + holdrst<='1'; + elsif(sysClk125'event and sysClk125='1') then + if (holdctr(24)='0') then + holdrst<='0'; + end if; + holdctr<=unsigned(holdctr)-1; + end if; + end process; + + process(sysClk125, sysRst125) -- reset logic for IDELAYCTRL + begin + if(sysRst125='1') then + idctrlrst<='0'; + idcounter<="000"; + oldlockedid<='0'; + elsif(sysClk125'event and sysClk125='1') then + if(lockedid='1' and oldlockedid='0')then + idcounter<="111"; + idctrlrst<='1'; + elsif(unsigned(idcounter)>0)then + idcounter<=unsigned(idcounter)-1; + else + idctrlrst<='0'; + end if; + oldlockedid<=lockedid; + end if; + end process; + +end HsioCosmic; diff --git a/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd.regular b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd.regular new file mode 100755 index 00000000..9a363fd0 --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/hdl/HsioCosmic.vhd.regular @@ -0,0 +1,697 @@ +------------------------------------------------------------------------------- +-- Title : BNL ASIC Test FGPA, Top Level +-- Project : LCLS Detector, BNL ASIC +------------------------------------------------------------------------------- +-- File : HsioCosmic.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 07/21/2008 +------------------------------------------------------------------------------- +-- Description: +-- Top level logic for BNL ASIC test FPGA. +------------------------------------------------------------------------------- +-- Copyright (c) 2008 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 07/21/2008: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +Library Unisim; +USE ieee. std_logic_1164.ALL; +use ieee. std_logic_arith.all; +use ieee. std_logic_unsigned.all; +use work.StdRtlPkg.all; +USE work.ALL; + +entity HsioCosmic is + port ( + + -- PGP Crystal Clock Input, 156.25Mhz + iPgpRefClkP : in std_logic; + iPgpRefClkM : in std_logic; + + -- System clock 125 MHz clock input + iMainClkP : in std_logic; + iMainClkN : in std_logic; + + -- PGP Rx/Tx Lines + iMgtRxN : in std_logic; + iMgtRxP : in std_logic; + oMgtTxN : out std_logic; + oMgtTxP : out std_logic; + + -- ATLAS Pixel module pins + serialin : in std_logic_vector(15 downto 0); + serialout : out std_logic_vector(15 downto 0); + serialout_p : out std_logic_vector(15 downto 0); + serialout_n : out std_logic_vector(15 downto 0); + serialin_p : in std_logic_vector(15 downto 0); + serialin_n : in std_logic_vector(15 downto 0); + discinP : in std_logic_vector(3 downto 0); +-- discinN : in std_logic_vector(1 downto 0); + clkout40 : out std_logic; + refclk_p : out std_logic; + refclk_n : out std_logic; + xclk_p : out std_logic; + xclk_n : out std_logic; + + -- Reset button + iResetInL : in std_logic; + -- Reload firmware + oReload : out std_logic; + iExtreload : in std_logic; + -- LED Display + oDispClk : out std_logic; + oDispDat : out std_logic; + oDispLoadL : out std_logic_vector(1 downto 0); + oDispRstL : out std_logic; + + -- Temperature ADC + adcI2cScl: inout std_logic; + adcI2cSda: inout std_logic; + adcAS: out std_logic; + + -- Debug + oDebug : out std_logic_vector(7 downto 0); + + -- Eudet trigger + iExttriggerP : in std_logic; + iExttriggerN : in std_logic; + iExtrstP : in std_logic; + iExtrstN : in std_logic; + oExtbusyP : out std_logic; + oExtbusyN : out std_logic; + oExttrgclkP : out std_logic; + oExttrgclkN : out std_logic; + + --HSIO trigger IF + iHSIOtrigger : in std_logic_vector(1 downto 0); + oHSIOtrigger : out std_logic; + oHSIObusy : out std_logic; + iHSIObusy : in std_logic; + + -- Eudet test + oExtrstP : out std_logic; + oExtrstN : out std_logic; + oExttriggerP : out std_logic; + oExttriggerN : out std_logic; + + + -- Misc Signals + oPdBuff0 : out std_logic; + oPdBuff1 : out std_logic; + oPdBuff3 : out std_logic; + oPdBuff4 : out std_logic; + oLemoA : out std_logic; + iLemoB : in std_logic; + + -- Transmitter enable + transDis1 : out std_logic; + -- CMOS chip I/O + RD2 : out std_logic; + AuxClk : out std_logic; + RA : out std_logic; + RD1 : out std_logic; + IOMXIN : out std_logic_vector(3 downto 0); + IOMXSEL : out std_logic_vector(2 downto 0); + HITOR : in std_logic; + IOMXOUT : in std_logic_vector(2 downto 0); + SELALTBUS : out std_logic; + REGABDACLD : out std_logic; + REGABSTBLD : out std_logic; + SELCMD : out std_logic; + CMDEXTTRIGGER : out std_logic; + CMDALTPLS : out std_logic + ); +end HsioCosmic; + + +-- Define architecture for top level module +architecture HsioCosmic of HsioCosmic is + + -- Synthesis control attributes + attribute syn_useioff : boolean; + attribute syn_useioff of HsioCosmic : architecture is true; + attribute xc_fast_auto : boolean; + attribute xc_fast_auto of HsioCosmic : architecture is false; + attribute syn_noclockbuf : boolean; + attribute syn_noclockbuf of HsioCosmic : architecture is true; + + -- IO Pad components + component IBUF port ( O : out std_logic; I : in std_logic ); end component; + component OBUF port ( O : out std_logic; I : in std_logic ); end component; + component OBUFDS + generic( IOSTANDARD: STRING:= "LVDS_25"; + SLEW: STRING:="FAST"); + port ( O : out std_logic; OB : out std_logic; I : in std_logic ); + end component; + + -- Input LVDS with termination + component IBUFDS + generic ( DIFF_TERM : boolean := TRUE; + IOSTANDARD: STRING := "LVDS_25"); + port ( O : out std_logic; I : in std_logic; IB : in std_logic ); + end component; + + -- Xilinx global clock buffer component + component BUFGMUX + port ( + O : out std_logic; + I0 : in std_logic; + I1 : in std_logic; + S : in std_logic + ); + end component; + + component IDELAYCTRL + port ( RDY : out std_logic; + REFCLK : in std_logic; + RST : in std_logic + ); + end component; + +component IDELAY + generic (IOBDELAY_TYPE : string := "DEFAULT"; --(DEFAULT, FIXED, VARIABLE) + IOBDELAY_VALUE : integer := 0 --(0 to 63) + ); + port ( + O : out STD_LOGIC; + I : in STD_LOGIC; + C : in STD_LOGIC; + CE : in STD_LOGIC; + INC : in STD_LOGIC; + RST : in STD_LOGIC + ); +end component; + + + -- Local signals + signal resetInL : std_logic; + signal tmpClk250 : std_logic; + signal sysClk125 : std_logic; + signal sysRst125 : std_logic; + signal sysRst250 : std_logic; + signal sysClk250 : std_logic; + signal refClock : std_logic; + signal pgpClk : std_logic; + signal pgpClk90 : std_logic; + signal pgpReset : std_logic; + signal clk320 : std_logic; + signal reload : std_logic; + signal reload1 : std_logic; + signal extreload : std_logic; + signal resetOut : std_logic; + signal mgtRxN : std_logic; + signal mgtRxP : std_logic; + signal mgtTxN : std_logic; + signal mgtTxP : std_logic; + signal dispClk : std_logic; + signal dispDat : std_logic; + signal dispLoadL : std_logic_vector(1 downto 0); + signal dispRstL : std_logic; + signal debug : std_logic_vector(7 downto 0); + signal sysClk125i : std_logic; + signal mainClk : std_logic; + signal clk0 : std_logic; + signal clkin : std_logic; + signal halfclock : std_logic; + signal quarterclock : std_logic; + signal clockidctrl : std_logic; + signal idctrlrst : std_logic; + signal RD2b : std_logic; + signal AuxClkb : std_logic; + signal RAb : std_logic; + signal RD1b : std_logic; + signal IOMXINb : std_logic_vector(3 downto 0); + signal IOMXSELb : std_logic_vector(2 downto 0); + signal HITORb : std_logic; + signal IOMXOUTb : std_logic_vector(2 downto 0); + signal SELALTBUSb : std_logic; + signal REGABDACLDb : std_logic; + signal REGABSTBLDb : std_logic; + signal SELCMDb : std_logic; + signal CMDEXTTRIGGERb : std_logic; + signal CMDALTPLSb : std_logic; + signal exttrigger : std_logic; + signal exttriggerinv : std_logic; + signal extrst : std_logic; + signal extrstinv : std_logic; + signal exttriggero : std_logic; + signal extrsto : std_logic; + signal extbusy : std_logic; + signal extbusyinv : std_logic; + signal exttrgclk : std_logic; + signal exttrgclkinv : std_logic; + signal hsiobusyb : std_logic; + signal hsiobusyinb : std_logic; + signal hsiotriggerb : std_logic_vector(1 downto 0); + signal serialoutb : std_logic_vector(15 downto 0); + signal serialinb : std_logic_vector(15 downto 0); + signal discinb : std_logic_vector(3 downto 0); + signal ccontrol : std_logic_vector(35 downto 0); + signal cdata : std_logic_vector(31 downto 0); + signal ctrig : std_logic_vector(0 downto 0); + signal opgpClk : std_logic; + signal dispDatA : std_logic; + signal dispDatB : std_logic; + signal pgpDispA : std_logic_vector(7 downto 0); + signal pgpDispB : std_logic_vector(7 downto 0); + signal dispDigitA : std_logic_vector(7 downto 0); + signal dispDigitB : std_logic_vector(7 downto 0); + signal dispDigitC : std_logic_vector(7 downto 0); + signal dispDigitD : std_logic_vector(7 downto 0); + signal dispDigitE : std_logic_vector(7 downto 0); + signal dispDigitF : std_logic_vector(7 downto 0); + signal dispDigitG : std_logic_vector(7 downto 0); + signal dispDigitH : std_logic_vector(7 downto 0); + signal dispStrobe : std_logic; + signal dispUpdateA : std_logic; + signal dispUpdateB : std_logic; + signal sysClkCnt : std_logic_vector(15 downto 0); + signal lockedid : std_logic; + signal oldlockedid : std_logic; + signal holdrst : std_logic; + signal holdctr : std_logic_vector(24 downto 0); + signal idcounter : std_logic_vector(2 downto 0); + + signal pgpClkUnbuf : std_logic; + signal pgpClk90Unbuf : std_logic; + signal sysClkUnbuf : std_logic; + signal disc : std_logic_vector(4 downto 0); + + signal calibmode1 : std_logic_vector(1 downto 0); + signal calibmode2 : std_logic_vector(1 downto 0); + signal calibmode : std_logic_vector(1 downto 0); + signal eudaqdone : std_logic; + signal eudaqtrgword : std_logic_vector(14 downto 0); + signal trigenabled : std_logic; + signal paused : std_logic; + signal triggermask : std_logic_vector(15 downto 0); + signal resetdelay : std_logic; + signal incrementdelay: std_logic_vector(4 downto 0); + signal discop : std_logic_vector(15 downto 0); + signal telescopeop : std_logic_vector(2 downto 0); + signal period : std_logic_vector(31 downto 0); + signal fifothresh : std_logic; + signal serbusy : std_logic; + signal tdcreadoutbusy: std_logic; + signal tcounter1 : std_logic_vector(31 downto 0); + signal tcounter2 : std_logic_vector(31 downto 0); + signal l1a : std_logic; + signal triggerword : std_logic_vector(7 downto 0); + signal busy : std_logic; + signal rstFromCore : std_logic; + signal phaseclksel : std_logic; + signal hitbus : std_logic_vector(1 downto 0); + signal startmeas : std_logic; + signal phasebusySel : std_logic_vector(1 downto 0); + signal phasebusyEn : std_logic; + + signal trigAdc : sl; + signal sendAdcData : sl; + signal adcData : Slv16Array(11 downto 0); + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + +begin + + -- Reset input + U_ResetIn: IBUF port map ( I => iResetInL, O => resetInL ); + + -- PGP Clock Generator + U_PgpClkGen: entity work.PgpClkGen generic map ( + RefClkEn1 => "ENABLE", + RefClkEn2 => "DISABLE", + DcmClkSrc => "RefClk1", + UserFxDiv => 4, + UserFxMult => 2 + ) port map ( + pgpRefClkInP => iPgpRefClkP, + pgpRefClkInN => iPgpRefClkM, + ponResetL => resetInL, + locReset => resetOut, + pgpRefClk1 => refClock, + pgpRefClk2 => open, + pgpClk => pgpClk, + pgpClk90 => pgpClk90, + pgpReset => pgpReset, + clk320 => clk320, + pgpClkIn => pgpClk, + userClk => sysClk125, + userReset => sysRst125, + userClkIn => sysClk125, + pgpClkUnbuf => pgpClkUnbuf, + pgpClk90Unbuf => pgpClk90Unbuf, + locClkUnbuf => sysClkUnbuf + + + ); + + -- Generate Divided Clock, sample reset + process ( pgpClk ) begin + if rising_edge(pgpClk) then + tmpClk250 <= not tmpClk250 after tpd; + sysRst250 <= sysRst125 after tpd; + end if; + end process; + + -- Global Buffer For 125Mhz Clock + U_CLK125: BUFGMUX port map ( + O => sysClk250, + I0 => tmpClk250, + I1 => '0', + S => '0' + ); + + -- No Pads for MGT Lines + mgtRxN <= iMgtRxN; + mgtRxP <= iMgtRxP; + oMgtTxN <= mgtTxN; + oMgtTxP <= mgtTxP; + + -- LED Display + U_DispClk : OBUF port map ( I => dispClk , O => oDispClk ); + U_DispDat : OBUF port map ( I => dispDat , O => oDispDat ); + U_DispLoadL1 : OBUF port map ( I => dispLoadL(1) , O => oDispLoadL(1) ); + U_DispLoadL0 : OBUF port map ( I => dispLoadL(0) , O => oDispLoadL(0) ); + U_DispRstL : OBUF port map ( I => dispRstL , O => oDispRstL ); + U_reload : OBUF port map ( I => reload , O => oReload ); + U_clkout40 : OBUF port map ( I => sysClk125i , O => clkout40 ); + U_refclk : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => sysClk125i , O => refclk_p , OB => refclk_n ); + U_xclk : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => sysClk125i , O => xclk_p , OB => xclk_n ); + + U_transdis : OBUF port map ( I => '0' , O => transDis1 ); + + U_rd2 : OBUF port map ( I => RD2b , O => RD2); + U_auxclk : OBUF port map ( I => AuxClkb , O => AuxClk); + U_RA : OBUF port map ( I => RAb , O => RA ); + U_rd1 : OBUF port map ( I => RD1b , O => RD1 ); + U_IOMXIN3 : OBUF port map ( I => IOMXINb(3) , O => IOMXIN(3) ); + U_IOMXIN2 : OBUF port map ( I => IOMXINb(2) , O => IOMXIN(2) ); + U_IOMXIN1 : OBUF port map ( I => IOMXINb(1) , O => IOMXIN(1) ); + U_IOMXIN0 : OBUF port map ( I => IOMXINb(0) , O => IOMXIN(0) ); + U_IOMXSEL2 : OBUF port map ( I => IOMXSELb(2) , O => IOMXSEL(2) ); + U_IOMXSEL1 : OBUF port map ( I => IOMXSELb(1) , O => IOMXSEL(1) ); + U_IOMXSEL0 : OBUF port map ( I => IOMXSELb(0) , O => IOMXSEL(0) ); + U_HITOR : IBUF port map ( O => HITORb , I => HITOR); + U_IOMXOUT2 : IBUF port map ( O => IOMXOUTb(2) , I => IOMXOUT(2) ); + U_IOMXOUT1 : IBUF port map ( O => IOMXOUTb(1) , I => IOMXOUT(1) ); + U_IOMXOUT0 : IBUF port map ( O => IOMXOUTb(0) , I => IOMXOUT(0) ); + U_SELALTBUS : OBUF port map ( I => SELALTBUSb , O => SELALTBUS); + U_REGABDACLD : OBUF port map ( I => REGABDACLDb , O => REGABDACLD); + U_REGABSTBLD : OBUF port map ( I => REGABSTBLDb , O => REGABSTBLD); + U_SELCMD : OBUF port map ( I => SELCMDb , O => SELCMD ); + U_CMDEXTTRIGGER : OBUF port map ( I => CMDEXTTRIGGERb , O => CMDEXTTRIGGER ); + U_CMDALTPLS : OBUF port map ( I => CMDALTPLSb , O => CMDALTPLS ); + U_exttrgclk : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => exttrgclkinv , O => oExttrgclkP , OB => oExttrgclkN ); + exttrgclkinv<= not exttrgclk; + U_extbusy : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => extbusyinv , O => oExtBusyP , OB => oExtbusyN ); + extbusyinv<= not extbusy; + U_exttrigger : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => iExttriggerP , IB=>iExttriggerN , O => exttriggerinv ); + exttrigger<= not exttriggerinv; + U_extrst : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => iExtrstP , IB=>iExtrstN , O => extrstinv ); + extrst<= not extrstinv; + U_exttriggero : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => exttriggero , O => oExttriggerP , OB => oExttriggerN ); + + U_extrsto : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => extrsto , O => oExtrstP , OB => oExtrstN ); + + U_HSIObusy : OBUF port map ( I => hsiobusyb , O => oHSIObusy); + U_HSIOtrigger : IBUF port map ( O => hsiotriggerb(0) , I => iHSIOtrigger(0) ); + U_HSIOtrigger2 : IBUF port map ( O => hsiotriggerb(1) , I => iHSIOtrigger(1) ); + U_hsiobusyin : IBUF port map ( O => hsiobusyinb , I => iHSIObusy ); + U_extreload : IBUF port map ( O => extreload , I => iExtreload ); + U_HSIOtriggero : OBUF port map ( O => oHSIOtrigger , I => l1a ); + + SERIAL_IO_DATA: + for I in 0 to 7 generate +-- U_serialin : IBUF port map ( I => serialin(I) , O => serialinb(I) ); + U_serialout_pn :OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => serialoutb(I) , O => serialout_p(I) , OB => serialout_n(I) ); + + U_serialin_pn : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => serialin_p(I) , IB=>serialin_n(I) , O => serialinb(I) ); + + end generate SERIAL_IO_DATA; + + U_serialout : OBUF port map ( I => serialoutb(8) , O => serialout(8) ); + U_serialin_pn_8 : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => serialin_p(8) , IB=>serialin_n(8) , O => serialinb(8) ); + +-- U_serialout11 : OBUF port map ( I => serialoutb(11) , O => serialout(11) ); +-- U_serialin11 : IBUF port map ( I => serialin(11) , O => serialinb(11) ); + SERIAL_IO_DATA_FEI3: + for I in 11 to 14 generate + U_serialout_pn :OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => serialoutb(I) , O => serialout_p(I) , OB => serialout_n(I) ); + + U_serialin_pn : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => serialin_p(I) , IB=>serialin_n(I) , O => serialinb(I) ); + + end generate SERIAL_IO_DATA_FEI3; + --DISC_1: IBUFDS port map ( O => discinb(0), I => discinP(0) , IB => discinN(0) ); + --DISC_2: IBUFDS port map ( O => discinb(1), I => discinP(1) , IB => discinN(1) ); + DISC_1: IBUF port map ( O => discinb(0), I => discinP(0) ); + DISC_2: IBUF port map ( O => discinb(1), I => discinP(1) ); + DISC_3: IBUF port map ( O => discinb(2), I => discinP(2) ); + DISC_4: IBUF port map ( O => discinb(3), I => discinP(3) ); + -- Display Controller A + U_DispCntrlA: entity work.DisplayControl port map ( + sysClk => sysClk125, sysRst => sysRst125, + dispStrobe => dispStrobe, dispUpdate => dispUpdateA, + dispRotate => "01", dispDigitA => dispDigitA, + dispDigitB => dispDigitB, dispDigitC => dispDigitC, + dispDigitD => dispDigitD, dispClk => dispClk, + dispDat => dispDatA, dispLoadL => dispLoadL(0), + dispRstL => dispRstL + ); + + -- Display Controller B + U_DispCntrlB: entity work.DisplayControl port map ( + sysClk => sysClk125, sysRst => sysRst125, + dispStrobe => dispStrobe, dispUpdate => dispUpdateB, + dispRotate => "01", dispDigitA => dispDigitE, + dispDigitB => dispDigitF, dispDigitC => dispDigitG, + dispDigitD => dispDigitH, dispClk => open, + dispDat => dispDatB, dispLoadL => dispLoadL(1), + dispRstL => open + ); + -- Output LED Data + dispDat <= dispDatA or dispDatB; + -- Generate display strobe (200ns) and update control + process ( sysClk125, sysRst125 ) begin + if sysRst125 = '1' then + sysClkCnt <= (others=>'0') after tpd; + dispStrobe <= '0' after tpd; + dispUpdateA <= '0' after tpd; + dispUpdateB <= '0' after tpd; + elsif rising_edge(sysClk125) then + + -- Display strobe, 320ns + dispStrobe <= sysClkCnt(4) after tpd; + + -- Update Display 0 + if sysClkCnt(15 downto 0) = x"8000" then + dispUpdateA <= '1' after tpd; + else + dispUpdateA <= '0' after tpd; + end if; + + -- Update Display B + if sysClkCnt(15 downto 0) = x"0000" then + dispUpdateB <= '1' after tpd; + else + dispUpdateB <= '0' after tpd; + end if; + + -- Update counter + sysClkCnt <= sysClkCnt + 1 after tpd; + + + end if; + end process; + + + U_triggerlogic: entity work.triggerlogic + port map( + clk => sysClk125, + rst => rstFromCore, + clk160 => pgpClk, + rst160 => pgpReset, + -- hardware inputs + discin => discinb, + hitbusin => hitbus, + -- HSIO trigger + HSIObusy => hsiobusyb, + HSIOtrigger => hsiotriggerb, + HSIObusyin => hsiobusyinb, + hitbusout => open, + + -- eudet trigger + exttrigger => exttrigger, + extrst => extrst, + extbusy => extbusy, + exttrgclk => exttrgclk, + + calibmode => calibmode, + startmeas => startmeas, + eudaqdone => eudaqdone, + eudaqtrgword => eudaqtrgword, + tcounter1 => tcounter1, + tcounter2 => tcounter2, + + trigenabled => trigenabled, + paused => paused, + triggermask => triggermask, + resetdelay => resetdelay, + incrementdelay => incrementdelay, + discop => discop, + telescopeop => telescopeop, + period => period, + fifothresh => fifothresh, + serbusy => serbusy, + tdcreadoutbusy => tdcreadoutbusy, + phaseclksel => phaseclksel, + phasebusyEn => phasebusyEn, + phasebusySel => phasebusySel, + l1a => l1a, + triggerword => triggerword, + busy =>busy, + coincd =>open +); + + -- FPGA Core + U_HsioCosmicCore1: entity work.HsioPixelCore + generic map( framedFirstChannel=> 0, + framedLastChannel=> 7, + rawFirstChannel => 11, + rawLastChannel => 10, + buffersizefe => 8192, + buffersizetdc => 16384, + encodingDefault => "00", + hitbusreadout => '0') + port map ( + sysClk250 => sysClk250, sysRst250 => sysRst250, + sysClk125 => sysClk125, sysRst125 => sysRst125, + refClock => refClock, pgpClk => pgpClk, + pgpClk90 => pgpClk90, pgpReset => pgpReset, + clk320 => clk320, reload => reload1, + mgtRxN => mgtRxN, + mgtRxP => mgtRxP, mgtTxN => mgtTxN, + mgtTxP => mgtTxP, serialin => serialinb, + serialout => serialoutb, clock160 => pgpClk, + clock80 => halfclock, clock40 => quarterclock, + resetOut => resetOut, l1a => l1a, + latchtriggerword => triggerword, tcounter1=>tcounter1, + tcounter2 => tcounter2, busy =>busy, + eudaqdone => eudaqdone, eudaqtrgword => eudaqtrgword, + calibmodeout => calibmode, startmeas => startmeas, + pausedout => paused, present =>open, + trgenabledout => trigenabled, rstFromCore => rstFromCore, + fifothresh => fifothresh, triggermask => triggermask, + discop => discop, period => period, + telescopeop => telescopeop, resetdelay => resetdelay, + incrementdelay => incrementdelay, + sbusy => serbusy, tdcbusy => tdcreadoutbusy, + phaseclksel => phaseclksel, hitbus => hitbus(0), + debug => debug, + exttriggero => exttriggero, extrsto => extrsto, + doricreset => open, + phasebusyEn => phasebusyEn, phasebusySel => phasebusySel, + dispDigitA => dispDigitA, dispDigitB => dispDigitB, + dispDigitC => dispDigitC, dispDigitD => dispDigitD, + dispDigitE => dispDigitE, dispDigitF => dispDigitF, + dispDigitG => dispDigitF, dispDigitH => dispDigitH, + pgpClkUnbuf => pgpClkUnbuf, pgpClk90Unbuf => pgpClk90Unbuf, + sysClkUnbuf => sysClkUnbuf, trigAdc => trigAdc, + sendAdcData => sendAdcData, adcData => adcData + ); + sysClk125i <= not sysClk125; + reload <= reload1 and extreload; -- active low + --sysClk125i<=debug(0); + tempadc_inst: entity work.tempadc + generic map( + PRESCALE_G => 79, + MAPPING_G => (7, 6, 4, 5, 3, 2, 1, 0) ) + port map( + clk => sysClk125, + d_out => adcData, + trig => trigAdc, + ld => sendAdcData, + adcAS => adcAs, + scl => adcI2cScl, + sda => adcI2cSda + ); + U_clock160: entity work.clock160 port map( + CLKIN_N_IN => iMainClkN, + CLKIN_P_IN => iMainClkP, + RST_IN => sysRst125, + CLKFX_OUT => mainClk, + CLKIN_IBUFGDS_OUT => clkin, + CLK0_OUT => clk0, + LOCKED_OUT => open); + + process(mainClk) + begin + if(mainClk'event and mainClk='1') then + halfclock<= not halfclock; + end if; + end process; + process(halfclock) + begin + if(halfclock'event and halfclock='1') then + quarterclock<= not quarterclock; + end if; + end process; + U_idelctrlclk: entity work.clock200 port map( + CLKIN_IN => mainClk, + RST_IN => holdrst, + CLKFX_OUT => clockidctrl, + CLK0_OUT => open, + LOCKED_OUT => lockedid); + U_idelayctrl: IDELAYCTRL port map( + RDY => open, + REFCLK => clockidctrl, + RST => idctrlrst); + + process(sysRst125, sysClk125) -- clock interface + begin + if (sysRst125='1') then + holdctr<=(others=>'1'); + holdrst<='1'; + elsif(sysClk125'event and sysClk125='1') then + if (holdctr(24)='0') then + holdrst<='0'; + end if; + holdctr<=unsigned(holdctr)-1; + end if; + end process; + + process(sysClk125, sysRst125) -- reset logic for IDELAYCTRL + begin + if(sysRst125='1') then + idctrlrst<='0'; + idcounter<="000"; + oldlockedid<='0'; + elsif(sysClk125'event and sysClk125='1') then + if(lockedid='1' and oldlockedid='0')then + idcounter<="111"; + idctrlrst<='1'; + elsif(unsigned(idcounter)>0)then + idcounter<=unsigned(idcounter)-1; + else + idctrlrst<='0'; + end if; + oldlockedid<=lockedid; + end if; + end process; + +end HsioCosmic; diff --git a/rce/fw-hsio/projects/HsioCosmic/images/.gitignore b/rce/fw-hsio/projects/HsioCosmic/images/.gitignore new file mode 100644 index 00000000..d6b7ef32 --- /dev/null +++ b/rce/fw-hsio/projects/HsioCosmic/images/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/rce/fw-hsio/projects/HsioStave0/Makefile b/rce/fw-hsio/projects/HsioStave0/Makefile new file mode 100644 index 00000000..5c82cd85 --- /dev/null +++ b/rce/fw-hsio/projects/HsioStave0/Makefile @@ -0,0 +1,12 @@ +# Project Name +export PROJECT = $(notdir $(PWD)) + +# List of build core directories. Relative to current directory. +CORE_DIRS = coregen ../../modules/pgp/coregen ../../modules/pgp2/coregen ../../modules/pixelcore/coregen + +# Optional ELF file to include. Relative to ./boot directory +#BOOT_ELF = udiTest.elf + +# Use top level makefile +include ../../system.mk + diff --git a/rce/fw-hsio/projects/HsioStave0/Readme.txt b/rce/fw-hsio/projects/HsioStave0/Readme.txt new file mode 100644 index 00000000..c0ba752b --- /dev/null +++ b/rce/fw-hsio/projects/HsioStave0/Readme.txt @@ -0,0 +1,59 @@ +This is a DPM project specific Readme.txt file. + +The files in this directory are used to build +the DPM project in this directory. The project +name matches the name of the directory in which +this file is found. + +The Makefile in this directory may be used to build +this project with a simple 'gmake' command. + +The Version.vhd file in this directory is used to +generate the software readable version constant +in the build and is also used to set the name of +the files added to the images directory. + +The following sub directories exist in this project: + +boot: + This directory contains boot loader files which are + used to program the boot loader code in the DPM. The + files in this directory include: + +config: + This directory contains Xilinx configuration files for + various steps in the synthesis process. The files in this + directory include: + + bitgen_options.txt: Options for bitgen + map_options.txt: Options for map + ngdbuild_options.txt: Options for ngdbuild + par_options.txt: Options for par + trce_options.txt: Options for trce + xst_options.txt: Options for xst + sources.txt Source file list used by xst + +coregen: + This directory holds the coregen project and any modules + generated by coregen that are specific to this project. + +debug: + This directory holds any debug files for the project. + +hdl: + This directory contains the source files (.vhd and .v) for + the project and the constraints file (.ucf) for the project. + The top level module name, its source file name and the ucf + file name should match the name of the project. + +images: + + This directory contains the result of the project compile. + The resulting .mcs and .bit files for the project are + added to this directory. The name of the copied file will + be: project_version.mcs/.bit. + +sim: + + Directory for simulation Makefile and test bench. + diff --git a/rce/fw-hsio/projects/HsioStave0/Version.vhd b/rce/fw-hsio/projects/HsioStave0/Version.vhd new file mode 100644 index 00000000..ce6867c7 --- /dev/null +++ b/rce/fw-hsio/projects/HsioStave0/Version.vhd @@ -0,0 +1,32 @@ +------------------------------------------------------------------------------- +-- Title : Version Constant File +-- Project : HSIO +------------------------------------------------------------------------------- +-- File : Version.vhd +-- Author : Martin Kocian, kocian@slac.stanford.edu +-- Created : 01/07/2013 +------------------------------------------------------------------------------- +-- Description: +-- Version Constant Module +------------------------------------------------------------------------------- +-- Copyright (c) 2012 by SLAC. All rights reserved. +------------------------------------------------------------------------------- +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; + +package Version is + +constant FpgaVersion : std_logic_vector(31 downto 0) := x"00000009"; -- MAKE_VERSION + +end Version; + +------------------------------------------------------------------------------- +-- Revision History: +-- 01/07/2013 (0x00000001): Initial XST version +-- 03/22/2013 (0x00000002): HSIO trigger/busy added to opto ucf file +-- 04/02/2013 (0x00000003): Memory buffer for triggering. +-- 06/20/2014 (0x00000004): Added hitbus readout for DBM +-- 07/24/2014 (0x00000005): Separated trigger from core. +-- 01/26/2015 (0x00000008): New fei4 readout +-- 01/09/2015 (0x00000009): New ADC data format, max 31 readout links. +------------------------------------------------------------------------------- diff --git a/rce/fw-hsio/projects/HsioStave0/config/bitgen_options.txt b/rce/fw-hsio/projects/HsioStave0/config/bitgen_options.txt new file mode 100755 index 00000000..abf29c69 --- /dev/null +++ b/rce/fw-hsio/projects/HsioStave0/config/bitgen_options.txt @@ -0,0 +1,5 @@ +##----------------------------------------------------------------------------- +## Title : Xilinx bitgen options file +##----------------------------------------------------------------------------- +-intstyle silent +-w diff --git a/rce/fw-hsio/projects/HsioStave0/config/map_options.txt b/rce/fw-hsio/projects/HsioStave0/config/map_options.txt new file mode 100755 index 00000000..6cef41ff --- /dev/null +++ b/rce/fw-hsio/projects/HsioStave0/config/map_options.txt @@ -0,0 +1,21 @@ +##----------------------------------------------------------------------------- +## Title : Xilinx map options file +##----------------------------------------------------------------------------- + +#-intstyle silent +-ol high +-xe n +-t 1 +-register_duplication on +#-global_opt off +#-equivalent_register_removal on +#-u +#-cm Area +-detail +#-ir off +#-pr off +#-lc off +#-mt 2 + + + diff --git a/rce/fw-hsio/projects/HsioStave0/config/ngdbuild_options.txt b/rce/fw-hsio/projects/HsioStave0/config/ngdbuild_options.txt new file mode 100755 index 00000000..95ca0eea --- /dev/null +++ b/rce/fw-hsio/projects/HsioStave0/config/ngdbuild_options.txt @@ -0,0 +1,5 @@ +##----------------------------------------------------------------------------- +## Title : Xilinx ngdbuild options file +##----------------------------------------------------------------------------- +-nt timestamp + diff --git a/rce/fw-hsio/projects/HsioStave0/config/par_options.txt b/rce/fw-hsio/projects/HsioStave0/config/par_options.txt new file mode 100755 index 00000000..2cdd3ad0 --- /dev/null +++ b/rce/fw-hsio/projects/HsioStave0/config/par_options.txt @@ -0,0 +1,9 @@ +##----------------------------------------------------------------------------- +## Title : Xilinx place and route options file +##----------------------------------------------------------------------------- +#-intstyle ise +-ol high +-xe n +#-mt 4 + + diff --git a/rce/fw-hsio/projects/HsioStave0/config/promgen_options.txt b/rce/fw-hsio/projects/HsioStave0/config/promgen_options.txt new file mode 100755 index 00000000..2c2257be --- /dev/null +++ b/rce/fw-hsio/projects/HsioStave0/config/promgen_options.txt @@ -0,0 +1,7 @@ +##----------------------------------------------------------------------------- +## Title : Xilinx promgen options file +##----------------------------------------------------------------------------- +-x xcf32p +-w +-p mcs +-c FF diff --git a/rce/fw-hsio/projects/HsioStave0/config/sources.txt b/rce/fw-hsio/projects/HsioStave0/config/sources.txt new file mode 120000 index 00000000..c5dbc41e --- /dev/null +++ b/rce/fw-hsio/projects/HsioStave0/config/sources.txt @@ -0,0 +1 @@ +sources_pgp1.txt \ No newline at end of file diff --git a/rce/fw-hsio/projects/HsioStave0/config/sources_pgp1.txt b/rce/fw-hsio/projects/HsioStave0/config/sources_pgp1.txt new file mode 100644 index 00000000..40eabc71 --- /dev/null +++ b/rce/fw-hsio/projects/HsioStave0/config/sources_pgp1.txt @@ -0,0 +1,73 @@ +# Version Constant +vhdl work "_PROJ_DIR_/Version.vhd" + +# PGP + +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpVersion.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpAckRx.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpCellRx.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpCellTx.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpMgtWrap.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpPhy.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpRxTrack.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpTxSched.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpTop.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpClkGen.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpCmdSlave.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpRegSlave.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpPicRemBuff.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpDataBuffer.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpFrontEnd.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpDsBuff.vhd" + +# Pixel core +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/StdRtlPkg.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/adcreadout.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/arraytype.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/DisplayCharacters.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/DisplayControl.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/ser.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/ser32.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/OutputEncoder.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/tdc.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/tdcreadout.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/clock160.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/clock200.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/phaseshift.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/deser.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/dataflag.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/dataflagnew.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/dataflagff.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/eofcounter.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/multiplexdataopt.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/coincidence.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/triggerpipeline.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/hitbuspipeline.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/wordswapper.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/eudaqTrigger.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/syncdatac.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/framealign.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/framealignhitbus.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/deser10b.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/deser4b.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/encodepgp.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/encodepgp24bit.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/lookaheadfifo.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/decodefei4record.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/datafifo.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/triggerlogic.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/HsioPixelCore.vhd" + +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_wrapper.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_bram.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_disp.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_lut.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_lut_base.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_pkg.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_rtl.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_top.vhd" + + +# Local Files +vhdl work "_PROJ_DIR_/hdl/HsioStave0.vhd" + diff --git a/rce/fw-hsio/projects/HsioStave0/config/sources_pgp2.txt b/rce/fw-hsio/projects/HsioStave0/config/sources_pgp2.txt new file mode 100644 index 00000000..d7ff5dd1 --- /dev/null +++ b/rce/fw-hsio/projects/HsioStave0/config/sources_pgp2.txt @@ -0,0 +1,67 @@ +# Version Constant +vhdl work "_PROJ_DIR_/Version.vhd" + +# PGP2 + +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/core/Pgp2CorePackage.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/core/Pgp2Rx.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/core/Pgp2RxCell.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/core/Pgp2RxPhy.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/core/Pgp2Tx.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/core/Pgp2TxCell.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/core/Pgp2TxPhy.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/core/Pgp2TxSched.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/mgt/Pgp2MgtPackage.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/mgt/Pgp2Mgt16.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/mgt/PgpClkGen.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/mgt/Pgp2MgtRxRst.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/mgt/Pgp2MgtTxRst.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/applications/Pgp2AppPackage.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/applications/Pgp2CmdSlave.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/applications/Pgp2DsBuff.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/applications/Pgp2RegSlave.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/applications/Pgp2UsBuff.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/applications/PgpDsBuff.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp2/hdl/applications/PgpFrontEnd.vhd" + + +# Pixel core +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/arraytype.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/DisplayCharacters.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/DisplayControl.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/ser32.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/BiphaseMarkEncoder.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/tdc.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/tdcreadout.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/clock160.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/clock200.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/phaseshift.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/deser.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/dataflag.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/dataflagnew.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/eofcounter.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/multiplexdatapgp2.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/coincidence.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/triggerpipeline.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/wordswapper.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/eudaqTrigger.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/syncdatac.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/framealign.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/deser10b.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/encodepgp.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/datafifo.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/HsioPixelCore.vhd" + +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_wrapper.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_bram.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_disp.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_lut.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_lut_base.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_pkg.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_rtl.vhd" +vhdl decode_8b10b "_PROJ_DIR_/../../modules/pixelcore/hdl/decode_8b10b_top.vhd" + + +# Local Files +vhdl work "_PROJ_DIR_/hdl/HsioStave0.vhd" + diff --git a/rce/fw-hsio/projects/HsioStave0/config/trce_options.txt b/rce/fw-hsio/projects/HsioStave0/config/trce_options.txt new file mode 100755 index 00000000..2656ff46 --- /dev/null +++ b/rce/fw-hsio/projects/HsioStave0/config/trce_options.txt @@ -0,0 +1,7 @@ +##----------------------------------------------------------------------------- +## Title : Xilinx trace options file +##----------------------------------------------------------------------------- +-intstyle silent +-l 30 +-v 30 +-tsi DpmTest.tsi diff --git a/rce/fw-hsio/projects/HsioStave0/config/xst_options.txt b/rce/fw-hsio/projects/HsioStave0/config/xst_options.txt new file mode 100644 index 00000000..268629be --- /dev/null +++ b/rce/fw-hsio/projects/HsioStave0/config/xst_options.txt @@ -0,0 +1,50 @@ +run +-ofn HsioStave0 +-top HsioStave0 +-p XC4VFX60-11-FF1152 +-ifn "sources.txt" +-opt_mode Speed +-opt_level 2 +-power NO +-iuc NO +-keep_hierarchy No +-netlist_hierarchy As_Optimized +-rtlview Yes +-glob_opt AllClockNets +-write_timing_constraints No +-cross_clock_analysis NO +-hierarchy_separator / +-bus_delimiter <> +-case Maintain +-slice_utilization_ratio 100 +-bram_utilization_ratio 100 +-dsp_utilization_ratio 100 +-verilog2001 YES +-fsm_extract YES -fsm_encoding Auto +-safe_implementation No +-fsm_style LUT +-ram_extract Yes +-ram_style Auto +-rom_extract Yes +-mux_style Auto +-decoder_extract YES +-priority_extract Yes +-shreg_extract YES +-shift_extract YES +-xor_collapse YES +-resource_sharing Yes +-use_dsp48 Auto +-async_to_sync No +-iobuf Yes +-max_fanout 100000 +-bufg 32 +-register_duplication YES +-equivalent_register_removal Yes +-register_balancing No +-iob Auto +-slice_packing YES +-use_clock_enable Auto +-use_sync_set Auto +-use_sync_reset Auto +-optimize_primitives No + diff --git a/rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.ucf b/rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.ucf new file mode 120000 index 00000000..461f5981 --- /dev/null +++ b/rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.ucf @@ -0,0 +1 @@ +HsioStave0.ucf.rotated \ No newline at end of file diff --git a/rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.ucf.dbm_nonrotated b/rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.ucf.dbm_nonrotated new file mode 100644 index 00000000..ace28b72 --- /dev/null +++ b/rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.ucf.dbm_nonrotated @@ -0,0 +1,333 @@ + +#----------------------------------------------------------------------------- +# Title : LCLS BNL ASIC Test FPGA, Constraints File +# Project : LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# File : HsioStave0.ucf +# Author : Ryan Herbst, rherbst@slac.stanford.edu +# Created : 07/21/2008 +#----------------------------------------------------------------------------- +# Description: +# This file contains all of the user constraints required to implement the +# LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# Copyright (c) 2008 by Ryan Herbst. All rights reserved. +#----------------------------------------------------------------------------- +# Modification history +# 07/21/2008: created. +#----------------------------------------------------------------------------- + + +#----------------------------------------------------------------------------- +#-------------------------- Timing Constraints ------------------------------- +#----------------------------------------------------------------------------- +# This section contains the timing constraints for the FPGA +#----------------------------------------------------------------------------- + +# Define system clocks +NET pgpClk TNM_NET = FFS pgpClk; +#NET clk320 TNM_NET = FFS clk320; +NET sysClk125 TNM_NET = FFS sysClk125; +NET sysClk250 TNM_NET = FFS sysClk250; +NET mainClk TNM_NET = FFS mainClk; +INST "U_HsioStave0Core1/thetdc/stopcontrol" RLOC_ORIGIN="X44Y117"; +INST "U_HsioStave0Core2/thetdc/stopcontrol" RLOC_ORIGIN="X44Y89"; + +# Define system clocks +TIMESPEC TS_pgpClk = PERIOD pgpClk 6.4 ns HIGH 50%; +TIMESPEC TS_sysClk125 = PERIOD sysClk125 25.6 ns HIGH 50%; +TIMESPEC TS_sysClk250 = PERIOD sysClk250 12.8 ns HIGH 50%; +#TIMESPEC TS_clk320 = PERIOD clk320 TS_pgpClk / 2; +TIMESPEC TS_mainClk = PERIOD mainClk 6.4 ns HIGH 50%; + +# Define time groups for inter-clock constraints +TIMEGRP TG_pgpClk_r = RISING pgpClk; +TIMEGRP TG_sysClk125_r = RISING sysClk125; +TIMEGRP TG_sysClk250_r = RISING sysClk250; +TIMEGRP TG_mainClk_r = RISING mainClk; + +# Inter Domain Constraints +# TIMESPEC TS_pgpClk_r_sysClk125_r = FROM TG_pgpClk_r TO TG_sysClk125_r 6.4ns; +TIMESPEC TS_sysClk125_r_pgpClk_r = FROM TG_sysClk125_r TO TG_pgpClk_r 6.4ns; +#TIMESPEC TS_sysClk125_r_sysClk250_r = FROM TG_sysClk125_r TO TG_sysClk250_r 8ns; +# NET U_HsioFei4Core/go TIG; +NET U_HsioStave0Core*/channelmask(*) TIG; +NET U_HsioStave0Core*/dfifothresh(*) TIG; +#NET U_HsioStave0Core*/enablereadout(*) TIG; + +timespec ts_02 = from ffs(*bz(0):*cz(0):*dz(0):*dz(1)) to ffs 640 MHz; +#timespec ts_03 = from ffs(*fei4fifo*) to ffs(*fei4dataflag*) 6.4ns; +#timespec ts_04 = from rams(*fei4fifo*) to ffs(*fei4dataflag*) 6.4ns; + +# Nets to ignore for timing +NET "iResetInL" TIG; + +NET serialin(*) maxskew = 250 ps ; + +INST "U_HsioStave0Core*/*receivedata/ff_*" IOB=FALSE; + + +# Nets to ignore for timing +NET "iResetInL" TIG; + + +#----------------------------------------------------------------------------- +#-------------------------- Pin Location Constraints ------------------------- +#----------------------------------------------------------------------------- +# This section contains the pin location constraints for the design +#----------------------------------------------------------------------------- +# Old P5 = New P5 +# Old P4 = New P4 +# Old P9 = New P3 +# Old P3 = New P2 + + +NET "iPgpRefClkP" LOC = "J1"; +NET "iPgpRefClkM" LOC = "K1"; +#NET "iMainClkP" LOC = "H17"; +#NET "iMainClkN" LOC = "J17"; +# fiber 1 +NET "iMgtRxN" LOC = "N1"; +NET "iMgtRxP" LOC = "M1"; +NET "oMgtTxN" LOC = "T1"; +NET "oMgtTxP" LOC = "R1"; +# fiber 2 +NET "iMgtRxN2" LOC = "AA1"; +NET "iMgtRxP2" LOC = "Y1"; +NET "oMgtTxN2" LOC = "V1"; +NET "oMgtTxP2" LOC = "U1"; +NET "oReload" LOC = "G16"; +NET "iResetInL" LOC = "AJ19"; +NET "oDispClk" LOC = "AG22"; +NET "oDispDat" LOC = "AJ22"; +NET "oDispLoadL(1)" LOC = "AK17"; +NET "oDispLoadL(0)" LOC = "Ak18"; +NET "oDispRstL" LOC = "AH22"; +#NET "rclk" LOC = "AM21"; +# fiber 1 +NET "transDis1" LOC = "AH4"; +# fiber 2 +NET "transDis2" LOC = "AK4"; +NET "transDis1" IOSTANDARD="LVCMOS33"; +NET "transDis2" IOSTANDARD="LVCMOS33"; + +#NET "refclk_p" LOC = "J25"; +#NET "refclk_p" IOSTANDARD="LVDS_25"; +#NET "refclk_n" LOC = "H25"; +#NET "refclk_n" IOSTANDARD="LVDS_25"; + +#NET "xclk_p" LOC = "E24"; +#NET "xclk_p" IOSTANDARD="LVDS_25"; +#NET "xclk_n" LOC = "F24"; +#NET "xclk_n" IOSTANDARD="LVDS_25"; + +#NET "clkout40" LOC = "AJ29"; +#NET "clkout40" IOSTANDARD="LVCMOS33"; +#NET "oDebug(7)" LOC = "N9"; +#NET "oDebug(7)" IOSTANDARD="LVDS_25"; +#NET "oDebug(6)" LOC = "N10"; +#NET "oDebug(6)" IOSTANDARD="LVDS_25"; +#NET "oDebug(4)" LOC = "N8"; +#NET "oDebug(4)" IOSTANDARD="LVDS_25"; +#NET "oDebug(5)" LOC = "N7"; +#NET "oDebug(5)" IOSTANDARD="LVDS_25"; + +# Temperature ADC MAX145 +#NET "ADC_Data_in_p" LOC = "L4"; +#NET "ADC_Data_in_n" LOC = "L3"; +#NET "ADC_Clk_p" LOC = "T9"; +#NET "ADC_Clk_n" LOC = "R9"; +#NET "ADC_nCS_p" LOC = "U3"; +#NET "ADC_nCS_n" LOC = "T3"; + +NET "iHSIOtrigger" LOC="J14"; +NET "iHSIOtrigger" IOSTANDARD="LVTTL"; +NET "iHSIOtrigger" SLEW=FAST; + +NET "oHSIObusy" LOC="H19"; +NET "oHSIObusy" IOSTANDARD="LVTTL"; +NET "oHSIObusy" SLEW=FAST; + +NET "oExttriggerP" LOC="L15"; +NET "oExttriggerP" IOSTANDARD="LVCMOS33"; +NET "oExttriggerP" SLEW=FAST; + +NET "doricreset1" LOC = "AJ11"; +NET "doricreset1" IOSTANDARD="LVCMOS25"; +NET "doricreset2" LOC = "AK11"; +NET "doricreset2" IOSTANDARD="LVCMOS25"; + +NET "iExtrst" LOC = "K18"; +NET "iExtrst" IOSTANDARD="LVCMOS33"; +NET "iExtrst" SLEW=FAST; +NET "iExttrigger" LOC = "K19"; +NET "iExttrigger" IOSTANDARD="LVCMOS33"; +NET "iExttrigger" SLEW=FAST; +NET "oExttrgclk" LOC = "K16"; +NET "oExttrgclk" IOSTANDARD="LVCMOS33"; +NET "oExttrgclk" SLEW=FAST; +NET "oExtBusy" LOC = "J16"; +NET "oExtBusy" IOSTANDARD="LVCMOS33"; +NET "oExtBusy" SLEW=FAST; + + +NET "serialout_p(0)" LOC = "AM13"; +NET "serialout_n(0)" LOC = "AM12"; +NET "serialout_p(1)" LOC = "AM8"; +NET "serialout_n(1)" LOC = "AM7"; +NET "serialout_p(2)" LOC = "AK14"; +NET "serialout_n(2)" LOC = "AL14"; +NET "serialout_p(3)" LOC = "AK13"; +NET "serialout_n(3)" LOC = "AL13"; +NET "serialout_p(4)" LOC = "AL11"; +NET "serialout_n(4)" LOC = "AM11"; +NET "serialout_p(5)" LOC = "AL9"; +NET "serialout_n(5)" LOC = "AK9"; +NET "serialout_p(6)" LOC = "AL10"; +NET "serialout_n(6)" LOC = "AM10"; +NET "serialout_p(7)" LOC = "AF9"; +NET "serialout_n(7)" LOC = "AE9"; + +NET "serialout_p(8)" LOC = "AK7"; +NET "serialout_n(8)" LOC = "AJ7"; +NET "serialout_p(9)" LOC = "AJ9"; +NET "serialout_n(9)" LOC = "AH9"; +NET "serialout_p(10)" LOC = "AF11"; +NET "serialout_n(10)" LOC = "AG11"; +NET "serialout_p(11)" LOC = "AH8"; +NET "serialout_n(11)" LOC = "AH7"; +NET "serialout_p(12)" LOC = "AJ12"; +NET "serialout_n(12)" LOC = "AK12"; +NET "serialout_p(13)" LOC = "AH10"; +NET "serialout_n(13)" LOC = "AJ10"; +NET "serialout_p(14)" LOC = "AH14"; +NET "serialout_n(14)" LOC = "AJ14"; +NET "serialout_p(15)" LOC = "AF10"; +NET "serialout_n(15)" LOC = "AG10"; + + +NET "serialin_p(8)" LOC = "AC12"; +NET "serialin_n(8)" LOC = "AB12"; +NET "serialin_p(9)" LOC = "AG13"; +NET "serialin_n(9)" LOC = "AH13"; +NET "serialin_p(10)" LOC = "AD11"; +NET "serialin_n(10)" LOC = "AE11"; +NET "serialin_p(11)" LOC = "AD10"; +NET "serialin_n(11)" LOC = "AD9"; +NET "serialin_p(12)" LOC = "AE14"; +NET "serialin_n(12)" LOC = "AF14"; +NET "serialin_p(13)" LOC = "AB11"; +NET "serialin_n(13)" LOC = "AA11"; +NET "serialin_p(14)" LOC = "AD14"; +NET "serialin_n(14)" LOC = "AC13"; +NET "serialin_p(15)" LOC = "AB13"; +NET "serialin_n(15)" LOC = "AA13"; + +NET "serialin_p(1)" LOC = "AH15"; +NET "serialin_n(1)" LOC = "AJ15"; +NET "serialin_p(6)" LOC = "AF15"; +NET "serialin_n(6)" LOC = "AG15"; +NET "serialin_p(4)" LOC = "AE13"; +NET "serialin_n(4)" LOC = "AF13"; +NET "serialin_p(7)" LOC = "AJ16"; +NET "serialin_n(7)" LOC = "AK16"; +NET "serialin_p(0)" LOC = "H24"; +NET "serialin_n(0)" LOC = "J24"; +NET "serialin_p(2)" LOC = "G22"; +NET "serialin_n(2)" LOC = "H22"; +NET "serialin_p(3)" LOC = "E24"; +NET "serialin_n(3)" LOC = "F24"; +NET "serialin_p(5)" LOC = "J25"; +NET "serialin_n(5)" LOC = "H25"; + + +#NET "discinP(0)" LOC = "AD7"; +#NET "discinP(1)" LOC = "AD6"; +#NET "discinP(2)" LOC = "AM6"; +#NET "discinP(3)" LOC = "AL6"; + +#NET "discinP(0)" IOSTANDARD= "LVCMOS33"; +#NET "discinP(1)" IOSTANDARD = "LVCMOS33"; +#NET "discinP(2)" IOSTANDARD= "LVCMOS33"; +#NET "discinP(3)" IOSTANDARD = "LVCMOS33"; + +#-------------------------- IO Standard Constraints -------------------------- +#----------------------------------------------------------------------------- +# This section defines the IO types, IO delays and other IO parameters +#----------------------------------------------------------------------------- + +NET "iResetInL" IOSTANDARD = "LVCMOS33"; +NET "oDispClk" IOSTANDARD = "LVCMOS33"; +NET "oDispDat" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(1)" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(0)" IOSTANDARD = "LVCMOS33"; +NET "oDispRstL" IOSTANDARD = "LVCMOS33"; + +NET "serialin_p(0)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(0)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(1)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(1)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(2)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(2)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(3)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(3)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(4)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(4)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(5)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(5)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(6)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(6)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(7)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(7)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(8)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(8)" IOSTANDARD = "LVDS_25"; + +NET "serialin_p(8)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(8)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(9)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(9)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(10)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(10)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(11)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(11)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(12)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(12)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(13)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(13)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(14)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(14)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(15)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(15)" IOSTANDARD = "LVDS_25"; + +NET "serialout_p(0)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(0)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(1)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(1)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(2)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(2)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(3)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(3)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(4)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(4)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(5)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(5)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(6)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(6)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(7)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(7)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(8)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(8)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(9)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(9)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(10)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(10)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(11)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(11)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(12)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(12)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(13)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(13)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(14)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(14)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(15)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(15)" IOSTANDARD = "LVDS_25"; diff --git a/rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.ucf.full b/rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.ucf.full new file mode 100644 index 00000000..7f222433 --- /dev/null +++ b/rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.ucf.full @@ -0,0 +1,348 @@ + +#----------------------------------------------------------------------------- +# Title : LCLS BNL ASIC Test FPGA, Constraints File +# Project : LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# File : HsioStave0.ucf +# Author : Ryan Herbst, rherbst@slac.stanford.edu +# Created : 07/21/2008 +#----------------------------------------------------------------------------- +# Description: +# This file contains all of the user constraints required to implement the +# LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# Copyright (c) 2008 by Ryan Herbst. All rights reserved. +#----------------------------------------------------------------------------- +# Modification history +# 07/21/2008: created. +#----------------------------------------------------------------------------- + + +#----------------------------------------------------------------------------- +#-------------------------- Timing Constraints ------------------------------- +#----------------------------------------------------------------------------- +# This section contains the timing constraints for the FPGA +#----------------------------------------------------------------------------- + +# Define system clocks +NET pgpClk TNM_NET = FFS pgpClk; +#NET clk320 TNM_NET = FFS clk320; +NET sysClk125 TNM_NET = FFS sysClk125; +NET sysClk250 TNM_NET = FFS sysClk250; +NET mainClk TNM_NET = FFS mainClk; + +INST "U_triggerlogic/thetdc/CHAIN[*].TAP" U_SET="TDC1"; +INST "U_triggerlogic/thetdc/CHAIN[*].DELAYY" U_SET="TDC1"; +INST "U_triggerlogic/thetdc/startcontrol" U_SET="TDC1"; +INST "U_triggerlogic/thetdc/stopcontrol" U_SET="TDC1"; +#INST "U_HsioStave0Core2/thetdc/CHAIN[*].TAP" U_SET="TDC2"; +#INST "U_HsioStave0Core2/thetdc/CHAIN[*].DELAYY" U_SET="TDC2"; +#INST "U_HsioStave0Core2/thetdc/startcontrol" U_SET="TDC2"; +#INST "U_HsioStave0Core2/thetdc/stopcontrol" U_SET="TDC2"; + +INST "U_triggerlogic/thetdc/stopcontrol" RLOC_ORIGIN="X44Y117"; +#INST "U_HsioStave0Core2/thetdc/stopcontrol" RLOC_ORIGIN="X44Y89"; + +# Define system clocks +TIMESPEC TS_pgpClk = PERIOD pgpClk 6.4 ns HIGH 50%; +TIMESPEC TS_sysClk125 = PERIOD sysClk125 25.6 ns HIGH 50%; +TIMESPEC TS_sysClk250 = PERIOD sysClk250 12.8 ns HIGH 50%; +#TIMESPEC TS_clk320 = PERIOD clk320 TS_pgpClk / 2; +TIMESPEC TS_mainClk = PERIOD mainClk 6.4 ns HIGH 50%; + +# Define time groups for inter-clock constraints +TIMEGRP TG_pgpClk_r = RISING pgpClk; +TIMEGRP TG_sysClk125_r = RISING sysClk125; +TIMEGRP TG_sysClk250_r = RISING sysClk250; +TIMEGRP TG_mainClk_r = RISING mainClk; + +# Inter Domain Constraints +# TIMESPEC TS_pgpClk_r_sysClk125_r = FROM TG_pgpClk_r TO TG_sysClk125_r 6.4ns; +TIMESPEC TS_sysClk125_r_pgpClk_r = FROM TG_sysClk125_r TO TG_pgpClk_r 6.4ns; +#TIMESPEC TS_sysClk125_r_sysClk250_r = FROM TG_sysClk125_r TO TG_sysClk250_r 8ns; +# NET U_HsioFei4Core/go TIG; +NET U_HsioStave0Core*/channelmask(*) TIG; +NET U_HsioStave0Core*/dfifothresh(*) TIG; +#NET U_HsioStave0Core*/enablereadout(*) TIG; + +timespec ts_02 = from ffs(*bz(0):*cz(0):*dz(0):*dz(1)) to ffs 640 MHz; +#timespec ts_03 = from ffs(*fei4fifo*) to ffs(*fei4dataflag*) 6.4ns; +#timespec ts_04 = from rams(*fei4fifo*) to ffs(*fei4dataflag*) 6.4ns; + +# Nets to ignore for timing +NET "iResetInL" TIG; + +NET serialinb(*) maxskew = 250 ps ; + +INST "U_HsioStave0Core*/*receivedata/ff_*" IOB=FALSE; + + +# Nets to ignore for timing +NET "iResetInL" TIG; + + +#----------------------------------------------------------------------------- +#-------------------------- Pin Location Constraints ------------------------- +#----------------------------------------------------------------------------- +# This section contains the pin location constraints for the design +#----------------------------------------------------------------------------- +# Old P5 = New P5 +# Old P4 = New P4 +# Old P9 = New P3 +# Old P3 = New P2 + + +NET "iPgpRefClkP" LOC = "J1"; +NET "iPgpRefClkM" LOC = "K1"; +#NET "iMainClkP" LOC = "H17"; +#NET "iMainClkN" LOC = "J17"; +# fiber 1 +NET "iMgtRxN" LOC = "N1"; +NET "iMgtRxP" LOC = "M1"; +NET "oMgtTxN" LOC = "T1"; +NET "oMgtTxP" LOC = "R1"; +# fiber 2 +NET "iMgtRxN2" LOC = "AA1"; +NET "iMgtRxP2" LOC = "Y1"; +NET "oMgtTxN2" LOC = "V1"; +NET "oMgtTxP2" LOC = "U1"; +NET "oReload" LOC = "G16"; +NET "iResetInL" LOC = "AJ19"; +NET "oDispClk" LOC = "AG22"; +NET "oDispDat" LOC = "AJ22"; +NET "oDispLoadL(1)" LOC = "AK17"; +NET "oDispLoadL(0)" LOC = "Ak18"; +NET "oDispRstL" LOC = "AH22"; +#NET "rclk" LOC = "AM21"; +# fiber 1 +NET "transDis1" LOC = "AH4"; +# fiber 2 +NET "transDis2" LOC = "AK4"; +NET "transDis1" IOSTANDARD="LVCMOS33"; +NET "transDis2" IOSTANDARD="LVCMOS33"; + +NET "iExtreload" LOC = "L15"; +NET "iExtreload" IOSTANDARD="LVCMOS33"; +NET "iExtreload" PULLUP; + +#NET "refclk_p" LOC = "J25"; +#NET "refclk_p" IOSTANDARD="LVDS_25"; +#NET "refclk_n" LOC = "H25"; +#NET "refclk_n" IOSTANDARD="LVDS_25"; + +#NET "xclk_p" LOC = "E24"; +#NET "xclk_p" IOSTANDARD="LVDS_25"; +#NET "xclk_n" LOC = "F24"; +#NET "xclk_n" IOSTANDARD="LVDS_25"; + +#NET "clkout40" LOC = "AJ29"; +#NET "clkout40" IOSTANDARD="LVCMOS33"; +#NET "oDebug(7)" LOC = "N9"; +#NET "oDebug(7)" IOSTANDARD="LVDS_25"; +#NET "oDebug(6)" LOC = "N10"; +#NET "oDebug(6)" IOSTANDARD="LVDS_25"; +#NET "oDebug(4)" LOC = "N8"; +#NET "oDebug(4)" IOSTANDARD="LVDS_25"; +#NET "oDebug(5)" LOC = "N7"; +#NET "oDebug(5)" IOSTANDARD="LVDS_25"; + +# Temperature ADC MAX145 +#NET "ADC_Data_in_p" LOC = "L4"; +#NET "ADC_Data_in_n" LOC = "L3"; +#NET "ADC_Clk_p" LOC = "T9"; +#NET "ADC_Clk_n" LOC = "R9"; +#NET "ADC_nCS_p" LOC = "U3"; +#NET "ADC_nCS_n" LOC = "T3"; + +NET "iHSIOtrigger(0)" LOC="J14"; +NET "iHSIOtrigger(0)" IOSTANDARD="LVTTL"; +NET "iHSIOtrigger(0)" SLEW=FAST; + +NET "iHSIOtrigger(1)" LOC="L14"; +NET "iHSIOtrigger(1)" IOSTANDARD="LVTTL"; +NET "iHSIOtrigger(1)" SLEW=FAST; + + +NET "oHSIObusy" LOC="H19"; +NET "oHSIObusy" IOSTANDARD="LVTTL"; +NET "oHSIObusy" SLEW=FAST; + + +NET "doricreset1" LOC = "AJ11"; +NET "doricreset1" IOSTANDARD="LVCMOS25"; +NET "doricreset2" LOC = "AK11"; +NET "doricreset2" IOSTANDARD="LVCMOS25"; + +NET "iExtrst" LOC = "K18"; +NET "iExtrst" IOSTANDARD="LVCMOS33"; +NET "iExtrst" SLEW=FAST; +NET "iExttrigger" LOC = "K19"; +NET "iExttrigger" IOSTANDARD="LVCMOS33"; +NET "iExttrigger" SLEW=FAST; +NET "oExttrgclk" LOC = "K16"; +NET "oExttrgclk" IOSTANDARD="LVCMOS33"; +NET "oExttrgclk" SLEW=FAST; +NET "oExtBusy" LOC = "J16"; +NET "oExtBusy" IOSTANDARD="LVCMOS33"; +NET "oExtBusy" SLEW=FAST; + +NET "serialout_p(0)" LOC = "AM13"; +NET "serialout_n(0)" LOC = "AM12"; +NET "serialout_p(1)" LOC = "AM8"; +NET "serialout_n(1)" LOC = "AM7"; +NET "serialout_p(2)" LOC = "AK14"; +NET "serialout_n(2)" LOC = "AL14"; +NET "serialout_p(3)" LOC = "AK13"; +NET "serialout_n(3)" LOC = "AL13"; +NET "serialout_p(4)" LOC = "AL11"; +NET "serialout_n(4)" LOC = "AM11"; +NET "serialout_p(5)" LOC = "AL9"; +NET "serialout_n(5)" LOC = "AK9"; +NET "serialout_p(6)" LOC = "AL10"; +NET "serialout_n(6)" LOC = "AM10"; +NET "serialout_p(7)" LOC = "AF9"; +NET "serialout_n(7)" LOC = "AE9"; + +NET "serialout_p(8)" LOC = "AK7"; +NET "serialout_n(8)" LOC = "AJ7"; +NET "serialout_p(9)" LOC = "AJ9"; +NET "serialout_n(9)" LOC = "AH9"; +NET "serialout_p(10)" LOC = "AF11"; +NET "serialout_n(10)" LOC = "AG11"; +NET "serialout_p(11)" LOC = "AH8"; +NET "serialout_n(11)" LOC = "AH7"; +NET "serialout_p(12)" LOC = "AJ12"; +NET "serialout_n(12)" LOC = "AK12"; +NET "serialout_p(13)" LOC = "AH10"; +NET "serialout_n(13)" LOC = "AJ10"; +NET "serialout_p(14)" LOC = "AH14"; +NET "serialout_n(14)" LOC = "AJ14"; +NET "serialout_p(15)" LOC = "AF10"; +NET "serialout_n(15)" LOC = "AG10"; + + +NET "serialin_p(0)" LOC = "AC12"; +NET "serialin_n(0)" LOC = "AB12"; +NET "serialin_p(1)" LOC = "AG13"; +NET "serialin_n(1)" LOC = "AH13"; +NET "serialin_p(2)" LOC = "AD11"; +NET "serialin_n(2)" LOC = "AE11"; +NET "serialin_p(3)" LOC = "AD10"; +NET "serialin_n(3)" LOC = "AD9"; +NET "serialin_p(4)" LOC = "AE14"; +NET "serialin_n(4)" LOC = "AF14"; +NET "serialin_p(5)" LOC = "AB11"; +NET "serialin_n(5)" LOC = "AA11"; +NET "serialin_p(6)" LOC = "AD14"; +NET "serialin_n(6)" LOC = "AC13"; +NET "serialin_p(7)" LOC = "AB13"; +NET "serialin_n(7)" LOC = "AA13"; + +NET "serialin_p(8)" LOC = "AH15"; +NET "serialin_n(8)" LOC = "AJ15"; +NET "serialin_p(9)" LOC = "AF15"; +NET "serialin_n(9)" LOC = "AG15"; +NET "serialin_p(10)" LOC = "AE13"; +NET "serialin_n(10)" LOC = "AF13"; +NET "serialin_p(11)" LOC = "AJ16"; +NET "serialin_n(11)" LOC = "AK16"; +NET "serialin_p(12)" LOC = "H24"; +NET "serialin_n(12)" LOC = "J24"; +NET "serialin_p(13)" LOC = "G22"; +NET "serialin_n(13)" LOC = "H22"; +NET "serialin_p(14)" LOC = "E24"; +NET "serialin_n(14)" LOC = "F24"; +NET "serialin_p(15)" LOC = "J25"; +NET "serialin_n(15)" LOC = "H25"; + + +#NET "discinP(0)" LOC = "AD7"; +#NET "discinP(1)" LOC = "AD6"; +#NET "discinP(2)" LOC = "AM6"; +#NET "discinP(3)" LOC = "AL6"; + +#NET "discinP(0)" IOSTANDARD= "LVCMOS33"; +#NET "discinP(1)" IOSTANDARD = "LVCMOS33"; +#NET "discinP(2)" IOSTANDARD= "LVCMOS33"; +#NET "discinP(3)" IOSTANDARD = "LVCMOS33"; + +#-------------------------- IO Standard Constraints -------------------------- +#----------------------------------------------------------------------------- +# This section defines the IO types, IO delays and other IO parameters +#----------------------------------------------------------------------------- + +NET "iResetInL" IOSTANDARD = "LVCMOS33"; +NET "oDispClk" IOSTANDARD = "LVCMOS33"; +NET "oDispDat" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(1)" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(0)" IOSTANDARD = "LVCMOS33"; +NET "oDispRstL" IOSTANDARD = "LVCMOS33"; + +NET "serialin_p(0)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(0)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(1)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(1)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(2)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(2)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(3)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(3)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(4)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(4)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(5)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(5)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(6)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(6)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(7)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(7)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(8)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(8)" IOSTANDARD = "LVDS_25"; + +NET "serialin_p(8)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(8)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(9)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(9)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(10)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(10)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(11)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(11)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(12)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(12)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(13)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(13)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(14)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(14)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(15)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(15)" IOSTANDARD = "LVDS_25"; + +NET "serialout_p(0)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(0)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(1)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(1)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(2)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(2)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(3)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(3)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(4)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(4)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(5)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(5)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(6)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(6)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(7)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(7)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(8)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(8)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(9)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(9)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(10)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(10)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(11)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(11)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(12)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(12)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(13)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(13)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(14)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(14)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(15)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(15)" IOSTANDARD = "LVDS_25"; diff --git a/rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.ucf.opto.ibl b/rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.ucf.opto.ibl new file mode 100644 index 00000000..beda4562 --- /dev/null +++ b/rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.ucf.opto.ibl @@ -0,0 +1,396 @@ + +#----------------------------------------------------------------------------- +# Title : LCLS BNL ASIC Test FPGA, Constraints File +# Project : LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# File : HsioStave0.ucf +# Author : Ryan Herbst, rherbst@slac.stanford.edu +# Created : 07/21/2008 +#----------------------------------------------------------------------------- +# Description: +# This file contains all of the user constraints required to implement the +# LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# Copyright (c) 2008 by Ryan Herbst. All rights reserved. +#----------------------------------------------------------------------------- +# Modification history +# 07/21/2008: created. +#----------------------------------------------------------------------------- + + +#----------------------------------------------------------------------------- +#-------------------------- Timing Constraints ------------------------------- +#----------------------------------------------------------------------------- +# This section contains the timing constraints for the FPGA +#----------------------------------------------------------------------------- + +# Define system clocks +NET pgpClk TNM_NET = FFS pgpClk; +#NET clk320 TNM_NET = FFS clk320; +NET sysClk125 TNM_NET = FFS sysClk125; +NET sysClk250 TNM_NET = FFS sysClk250; +NET mainClk TNM_NET = FFS mainClk; +INST "U_triggerlogic/thetdc/stopcontrol" RLOC_ORIGIN="X44Y117"; +#INST "U_HsioStave0Core2/thetdc/stopcontrol" RLOC_ORIGIN="X44Y89"; + +# Define system clocks +TIMESPEC TS_pgpClk = PERIOD pgpClk 6.4 ns HIGH 50%; +TIMESPEC TS_sysClk125 = PERIOD sysClk125 25.6 ns HIGH 50%; +TIMESPEC TS_sysClk250 = PERIOD sysClk250 12.8 ns HIGH 50%; +#TIMESPEC TS_clk320 = PERIOD clk320 TS_pgpClk / 2; +TIMESPEC TS_mainClk = PERIOD mainClk 6.4 ns HIGH 50%; + +# Define time groups for inter-clock constraints +TIMEGRP TG_pgpClk_r = RISING pgpClk; +TIMEGRP TG_sysClk125_r = RISING sysClk125; +TIMEGRP TG_sysClk250_r = RISING sysClk250; +TIMEGRP TG_mainClk_r = RISING mainClk; + +# Inter Domain Constraints +# TIMESPEC TS_pgpClk_r_sysClk125_r = FROM TG_pgpClk_r TO TG_sysClk125_r 6.4ns; +TIMESPEC TS_sysClk125_r_pgpClk_r = FROM TG_sysClk125_r TO TG_pgpClk_r 6.4ns; +#TIMESPEC TS_sysClk125_r_sysClk250_r = FROM TG_sysClk125_r TO TG_sysClk250_r 8ns; +# NET U_HsioFei4Core/go TIG; +NET U_HsioStave0Core*/channelmask(*) TIG; +NET U_HsioStave0Core*/dfifothresh(*) TIG; +#NET U_HsioStave0Core*/enablereadout(*) TIG; + +timespec ts_02 = from ffs(*bz(0):*cz(0):*dz(0):*dz(1)) to ffs 640 MHz; +#timespec ts_03 = from ffs(*fei4fifo*) to ffs(*fei4dataflag*) 6.4ns; +#timespec ts_04 = from rams(*fei4fifo*) to ffs(*fei4dataflag*) 6.4ns; + +# Nets to ignore for timing +NET "iResetInL" TIG; + +NET serialinb(*) maxskew = 250 ps ; + +INST "U_HsioStave0Core*/*receivedata/ff_*" IOB=FALSE; + + +# Nets to ignore for timing +NET "iResetInL" TIG; + + +#----------------------------------------------------------------------------- +#-------------------------- Pin Location Constraints ------------------------- +#----------------------------------------------------------------------------- +# This section contains the pin location constraints for the design +#----------------------------------------------------------------------------- +# Old P5 = New P5 +# Old P4 = New P4 +# Old P9 = New P3 +# Old P3 = New P2 + + +NET "iPgpRefClkP" LOC = "J1"; +NET "iPgpRefClkM" LOC = "K1"; +#NET "iMainClkP" LOC = "H17"; +#NET "iMainClkN" LOC = "J17"; +# fiber 1 +NET "iMgtRxN" LOC = "N1"; +NET "iMgtRxP" LOC = "M1"; +NET "oMgtTxN" LOC = "T1"; +NET "oMgtTxP" LOC = "R1"; +# fiber 2 +NET "iMgtRxN2" LOC = "AA1"; +NET "iMgtRxP2" LOC = "Y1"; +NET "oMgtTxN2" LOC = "V1"; +NET "oMgtTxP2" LOC = "U1"; +NET "oReload" LOC = "G16"; +NET "iResetInL" LOC = "AJ19"; +NET "oDispClk" LOC = "AG22"; +NET "oDispDat" LOC = "AJ22"; +NET "oDispLoadL(1)" LOC = "AK17"; +NET "oDispLoadL(0)" LOC = "Ak18"; +NET "oDispRstL" LOC = "AH22"; +#NET "rclk" LOC = "AM21"; +# fiber 1 +NET "transDis1" LOC = "AH4"; +# fiber 2 +NET "transDis2" LOC = "AK4"; +NET "transDis1" IOSTANDARD="LVCMOS33"; +NET "transDis2" IOSTANDARD="LVCMOS33"; + +NET "iExtreload" LOC = "L15"; +NET "iExtreload" IOSTANDARD="LVCMOS33"; +NET "iExtreload" PULLUP; + +#NET "refclk_p" LOC = "J25"; +#NET "refclk_p" IOSTANDARD="LVDS_25"; +#NET "refclk_n" LOC = "H25"; +#NET "refclk_n" IOSTANDARD="LVDS_25"; + +#NET "xclk_p" LOC = "E24"; +#NET "xclk_p" IOSTANDARD="LVDS_25"; +#NET "xclk_n" LOC = "F24"; +#NET "xclk_n" IOSTANDARD="LVDS_25"; + +#NET "clkout40" LOC = "AJ29"; +#NET "clkout40" IOSTANDARD="LVCMOS33"; +NET "oDebug(0)" LOC = "N10"; +NET "oDebug(1)" LOC = "N9"; +NET "oDebug(2)" LOC = "N8"; +NET "oDebug(3)" LOC = "N7"; +NET "oDebug(4)" LOC = "U8"; +NET "oDebug(5)" LOC = "T8"; +NET "oDebug(6)" LOC = "L6"; +NET "oDebug(7)" LOC = "L5"; +NET "oDebug(0)" IOSTANDARD="LVCMOS25"; +NET "oDebug(1)" IOSTANDARD="LVCMOS25"; +NET "oDebug(2)" IOSTANDARD="LVCMOS25"; +NET "oDebug(3)" IOSTANDARD="LVCMOS25"; +NET "oDebug(4)" IOSTANDARD="LVCMOS25"; +NET "oDebug(5)" IOSTANDARD="LVCMOS25"; +NET "oDebug(6)" IOSTANDARD="LVCMOS25"; +NET "oDebug(7)" IOSTANDARD="LVCMOS25"; +NET "oDebug(0)" SLEW="FAST"; +NET "oDebug(1)" SLEW="FAST"; +NET "oDebug(2)" SLEW="FAST"; +NET "oDebug(3)" SLEW="FAST"; +NET "oDebug(4)" SLEW="FAST"; +NET "oDebug(5)" SLEW="FAST"; +NET "oDebug(6)" SLEW="FAST"; +NET "oDebug(7)" SLEW="FAST"; + +# Temperature ADC MAX145 +#NET "ADC_Data_in_p" LOC = "L4"; +#NET "ADC_Data_in_n" LOC = "L3"; +#NET "ADC_Clk_p" LOC = "T9"; +#NET "ADC_Clk_n" LOC = "R9"; +#NET "ADC_nCS_p" LOC = "U3"; +#NET "ADC_nCS_n" LOC = "T3"; + +NET "iHSIOtrigger(0)" LOC="J14"; +NET "iHSIOtrigger(0)" IOSTANDARD="LVTTL"; +NET "iHSIOtrigger(0)" SLEW=FAST; + +NET "iHSIOtrigger(1)" LOC="L14"; +NET "iHSIOtrigger(1)" IOSTANDARD="LVTTL"; +NET "iHSIOtrigger(1)" SLEW=FAST; + +NET "oHSIOtrigger" LOC="L15"; +NET "oHSIOtrigger" IOSTANDARD="LVTTL"; +NET "oHSIOtrigger" SLEW=FAST; + +NET "iHSIObusy" LOC="H19"; +NET "iHSIObusy" IOSTANDARD="LVTTL"; +NET "iHSIObusy" SLEW=FAST; +NET "iHSIObusy" PULLDOWN; + +NET "iExtreload" LOC = "G15"; +NET "iExtreload" IOSTANDARD="LVCMOS25"; +NET "iExtreload" PULLUP; + + +NET "doricreset1" LOC = "AJ11"; +NET "doricreset1" IOSTANDARD="LVCMOS25"; +NET "doricreset2" LOC = "AK11"; +NET "doricreset2" IOSTANDARD="LVCMOS25"; + +#NET "oExtrstP" LOC = "N10"; +#NET "oExtrstN" LOC = "N9"; +#NET "oExtrstP" IOSTANDARD="LVDS_25"; +#NET "oExtrstN" IOSTANDARD="LVDS_25"; + +#NET "unused_p(0)" LOC="AM13"; +#NET "unused_n(0)" LOC="AM12"; +#NET "unused_p(1)" LOC="AM8"; +#NET "unused_n(1)" LOC="AM7"; +#NET "unused_p(2)" LOC="AH8"; +#NET "unused_n(2)" LOC="AH7"; +#NET "unused_p(3)" LOC="AF11"; +#NET "unused_n(3)" LOC="AG11"; +NET "serialout_p(0)" LOC = "AJ9"; +NET "serialout_n(0)" LOC = "AH9"; +#NET "serialout_p(1)" LOC = "AJ9"; +#NET "serialout_n(1)" LOC = "AH9"; +NET "serialout_p(2)" LOC = "AK7"; +NET "serialout_n(2)" LOC = "AJ7"; +#NET "serialout_p(3)" LOC = "AF9"; +#NET "serialout_n(3)" LOC = "AE9"; +NET "serialout_p(4)" LOC = "AF9"; +NET "serialout_n(4)" LOC = "AE9"; +#NET "serialout_p(5)" LOC = "AL9"; +#NET "serialout_n(5)" LOC = "AK9"; +NET "serialout_p(6)" LOC = "AL10"; +NET "serialout_n(6)" LOC = "AM10"; +#NET "serialout_p(7)" LOC = "AL10"; +#NET "serialout_n(7)" LOC = "AM10"; + +NET "serialout_p(8)" LOC = "AL9"; +NET "serialout_n(8)" LOC = "AK9"; +#NET "serialout_p(9)" LOC = "J31"; +#NET "serialout_n(9)" LOC = "J30"; +NET "serialout_p(10)" LOC = "AL11"; +NET "serialout_n(10)" LOC = "AM11"; +#NET "serialout_p(11)" LOC = "T31"; +#NET "serialout_n(11)" LOC = "T30"; +NET "serialout_p(12)" LOC = "AK13"; +NET "serialout_n(12)" LOC = "AL13"; +#NET "serialout_p(13)" LOC = "M32"; +#NET "serialout_n(13)" LOC = "M31"; +NET "serialout_p(14)" LOC = "AK14"; +NET "serialout_n(14)" LOC = "AL14"; +#NET "serialout_p(15)" LOC = "H28"; +#NET "serialout_n(15)" LOC = "H27"; + + +NET "serialin_p(0)" LOC = "N29"; +NET "serialin_n(0)" LOC = "N28"; +NET "serialin_p(1)" LOC = "P32"; +NET "serialin_n(1)" LOC = "N32"; +NET "serialin_p(2)" LOC = "K32"; +NET "serialin_n(2)" LOC = "K31"; +NET "serialin_p(3)" LOC = "N27"; +NET "serialin_n(3)" LOC = "M28"; +NET "serialin_p(4)" LOC = "L31"; +NET "serialin_n(4)" LOC = "L30"; +NET "serialin_p(5)" LOC = "M32"; +NET "serialin_n(5)" LOC = "M31"; +NET "serialin_p(6)" LOC = "E32"; +NET "serialin_n(6)" LOC = "F31"; +NET "serialin_p(7)" LOC = "G32"; +NET "serialin_n(7)" LOC = "G31"; + +NET "serialin_p(8)" LOC = "H28"; +NET "serialin_n(8)" LOC = "H27"; +NET "serialin_p(9)" LOC = "G30"; +NET "serialin_n(9)" LOC = "F30"; +NET "serialin_p(10)" LOC = "H30"; +NET "serialin_n(10)" LOC = "H29"; +NET "serialin_p(11)" LOC = "J31"; +NET "serialin_n(11)" LOC = "J30"; +NET "serialin_p(12)" LOC = "K28"; +NET "serialin_n(12)" LOC = "J27"; +NET "serialin_p(13)" LOC = "T26"; +NET "serialin_n(13)" LOC = "R26"; +NET "serialin_p(14)" LOC = "U28"; +NET "serialin_n(14)" LOC = "U27"; +NET "serialin_p(15)" LOC = "T31"; +NET "serialin_n(15)" LOC = "T30"; + + +#NET "discinP(0)" LOC = "AD7"; +#NET "discinP(1)" LOC = "AD6"; +#NET "discinP(2)" LOC = "AM6"; +#NET "discinP(3)" LOC = "AL6"; + +#NET "discinP(0)" IOSTANDARD= "LVCMOS33"; +#NET "discinP(1)" IOSTANDARD = "LVCMOS33"; +#NET "discinP(2)" IOSTANDARD= "LVCMOS33"; +#NET "discinP(3)" IOSTANDARD = "LVCMOS33"; + +NET "TX_EN" LOC="AJ6"; +NET "TX_DIS" LOC="AM3"; +NET "TX_RESET" LOC="AL3"; +NET "TX_FAULT" LOC="AG7"; +NET "RX0_RX_EN" LOC="AM6"; +NET "RX0_EN_SD" LOC="AL6"; +NET "RX0_SD" LOC="AG6"; +NET "RX0_SQ_EN" LOC="AG5"; +NET "RX1_RX_EN" LOC="AJ5"; +NET "RX1_EN_SD" LOC="AH5"; +NET "RX1_SD" LOC="AD21"; +NET "RX1_SQ_EN" LOC="AD20"; + +NET "TX_EN" IOSTANDARD= "LVCMOS33"; +NET "TX_DIS" IOSTANDARD= "LVCMOS33"; +NET "TX_RESET" IOSTANDARD= "LVCMOS33"; +NET "TX_FAULT" IOSTANDARD= "LVTTL"; +NET "RX0_RX_EN" IOSTANDARD= "LVCMOS33"; +NET "RX0_EN_SD" IOSTANDARD= "LVCMOS33"; +NET "RX0_SD" IOSTANDARD= "LVTTL"; +NET "RX0_SQ_EN" IOSTANDARD= "LVCMOS33"; +NET "RX1_RX_EN" IOSTANDARD= "LVCMOS33"; +NET "RX1_EN_SD" IOSTANDARD= "LVCMOS33"; +NET "RX1_SD" IOSTANDARD= "LVTTL"; +NET "RX1_SQ_EN" IOSTANDARD= "LVCMOS33"; + +#-------------------------- IO Standard Constraints -------------------------- +#----------------------------------------------------------------------------- +# This section defines the IO types, IO delays and other IO parameters +#----------------------------------------------------------------------------- + +NET "iResetInL" IOSTANDARD = "LVCMOS33"; +NET "oDispClk" IOSTANDARD = "LVCMOS33"; +NET "oDispDat" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(1)" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(0)" IOSTANDARD = "LVCMOS33"; +NET "oDispRstL" IOSTANDARD = "LVCMOS33"; + +NET "serialin_p(0)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(0)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(1)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(1)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(2)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(2)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(3)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(3)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(4)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(4)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(5)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(5)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(6)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(6)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(7)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(7)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(8)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(8)" IOSTANDARD = "LVDS_25"; + +NET "serialin_p(8)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(8)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(9)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(9)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(10)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(10)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(11)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(11)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(12)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(12)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(13)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(13)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(14)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(14)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(15)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(15)" IOSTANDARD = "LVDS_25"; + +NET "serialout_p(0)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(0)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(1)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(1)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(2)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(2)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(3)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(3)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(4)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(4)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(5)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(5)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(6)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(6)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(7)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(7)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(8)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(8)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(9)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(9)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(10)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(10)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(11)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(11)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(12)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(12)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(13)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(13)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(14)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(14)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(15)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(15)" IOSTANDARD = "LVDS_25"; +#NET "unused_p(0)" IOSTANDARD = "LVDS_25"; +#NET "unused_n(0)" IOSTANDARD = "LVDS_25"; +#NET "unused_p(1)" IOSTANDARD = "LVDS_25"; +#NET "unused_n(1)" IOSTANDARD = "LVDS_25"; +#NET "unused_p(2)" IOSTANDARD = "LVDS_25"; +#NET "unused_n(2)" IOSTANDARD = "LVDS_25"; +#NET "unused_p(3)" IOSTANDARD = "LVDS_25"; +#NET "unused_n(3)" IOSTANDARD = "LVDS_25"; diff --git a/rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.ucf.opto.nsqp.flipped b/rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.ucf.opto.nsqp.flipped new file mode 100644 index 00000000..db1b3068 --- /dev/null +++ b/rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.ucf.opto.nsqp.flipped @@ -0,0 +1,354 @@ + +#----------------------------------------------------------------------------- +# Title : LCLS BNL ASIC Test FPGA, Constraints File +# Project : LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# File : HsioStave0.ucf +# Author : Ryan Herbst, rherbst@slac.stanford.edu +# Created : 07/21/2008 +#----------------------------------------------------------------------------- +# Description: +# This file contains all of the user constraints required to implement the +# LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# Copyright (c) 2008 by Ryan Herbst. All rights reserved. +#----------------------------------------------------------------------------- +# Modification history +# 07/21/2008: created. +#----------------------------------------------------------------------------- + + +#----------------------------------------------------------------------------- +#-------------------------- Timing Constraints ------------------------------- +#----------------------------------------------------------------------------- +# This section contains the timing constraints for the FPGA +#----------------------------------------------------------------------------- + +# Define system clocks +NET pgpClk TNM_NET = FFS pgpClk; +#NET clk320 TNM_NET = FFS clk320; +NET sysClk125 TNM_NET = FFS sysClk125; +NET sysClk250 TNM_NET = FFS sysClk250; +NET mainClk TNM_NET = FFS mainClk; +INST "U_HsioStave0Core1/thetdc/stopcontrol" RLOC_ORIGIN="X44Y117"; +INST "U_HsioStave0Core2/thetdc/stopcontrol" RLOC_ORIGIN="X44Y89"; + +# Define system clocks +TIMESPEC TS_pgpClk = PERIOD pgpClk 6.4 ns HIGH 50%; +TIMESPEC TS_sysClk125 = PERIOD sysClk125 25.6 ns HIGH 50%; +TIMESPEC TS_sysClk250 = PERIOD sysClk250 12.8 ns HIGH 50%; +#TIMESPEC TS_clk320 = PERIOD clk320 TS_pgpClk / 2; +TIMESPEC TS_mainClk = PERIOD mainClk 6.4 ns HIGH 50%; + +# Define time groups for inter-clock constraints +TIMEGRP TG_pgpClk_r = RISING pgpClk; +TIMEGRP TG_sysClk125_r = RISING sysClk125; +TIMEGRP TG_sysClk250_r = RISING sysClk250; +TIMEGRP TG_mainClk_r = RISING mainClk; + +# Inter Domain Constraints +# TIMESPEC TS_pgpClk_r_sysClk125_r = FROM TG_pgpClk_r TO TG_sysClk125_r 6.4ns; +TIMESPEC TS_sysClk125_r_pgpClk_r = FROM TG_sysClk125_r TO TG_pgpClk_r 6.4ns; +#TIMESPEC TS_sysClk125_r_sysClk250_r = FROM TG_sysClk125_r TO TG_sysClk250_r 8ns; +# NET U_HsioFei4Core/go TIG; +NET U_HsioStave0Core*/channelmask(*) TIG; +NET U_HsioStave0Core*/dfifothresh(*) TIG; +#NET U_HsioStave0Core*/enablereadout(*) TIG; + +timespec ts_02 = from ffs(*bz(0):*cz(0):*dz(0):*dz(1)) to ffs 640 MHz; +#timespec ts_03 = from ffs(*fei4fifo*) to ffs(*fei4dataflag*) 6.4ns; +#timespec ts_04 = from rams(*fei4fifo*) to ffs(*fei4dataflag*) 6.4ns; + +# Nets to ignore for timing +NET "iResetInL" TIG; + +NET serialinb(*) maxskew = 250 ps ; + +INST "U_HsioStave0Core*/*receivedata/ff_*" IOB=FALSE; + + +# Nets to ignore for timing +NET "iResetInL" TIG; + + +#----------------------------------------------------------------------------- +#-------------------------- Pin Location Constraints ------------------------- +#----------------------------------------------------------------------------- +# This section contains the pin location constraints for the design +#----------------------------------------------------------------------------- +# Old P5 = New P5 +# Old P4 = New P4 +# Old P9 = New P3 +# Old P3 = New P2 + + +NET "iPgpRefClkP" LOC = "J1"; +NET "iPgpRefClkM" LOC = "K1"; +NET "iMainClkP" LOC = "H17"; +NET "iMainClkN" LOC = "J17"; +# fiber 1 +NET "iMgtRxN" LOC = "N1"; +NET "iMgtRxP" LOC = "M1"; +NET "oMgtTxN" LOC = "T1"; +NET "oMgtTxP" LOC = "R1"; +# fiber 2 +NET "iMgtRxN2" LOC = "AA1"; +NET "iMgtRxP2" LOC = "Y1"; +NET "oMgtTxN2" LOC = "V1"; +NET "oMgtTxP2" LOC = "U1"; +NET "oReload" LOC = "G16"; +NET "iResetInL" LOC = "AJ19"; +NET "oDispClk" LOC = "AG22"; +NET "oDispDat" LOC = "AJ22"; +NET "oDispLoadL(1)" LOC = "AK17"; +NET "oDispLoadL(0)" LOC = "Ak18"; +NET "oDispRstL" LOC = "AH22"; +#NET "rclk" LOC = "AM21"; +# fiber 1 +NET "transDis1" LOC = "AH4"; +# fiber 2 +NET "transDis2" LOC = "AK4"; +NET "transDis1" IOSTANDARD="LVCMOS33"; +NET "transDis2" IOSTANDARD="LVCMOS33"; + +#NET "refclk_p" LOC = "J25"; +#NET "refclk_p" IOSTANDARD="LVDS_25"; +#NET "refclk_n" LOC = "H25"; +#NET "refclk_n" IOSTANDARD="LVDS_25"; + +#NET "xclk_p" LOC = "E24"; +#NET "xclk_p" IOSTANDARD="LVDS_25"; +#NET "xclk_n" LOC = "F24"; +#NET "xclk_n" IOSTANDARD="LVDS_25"; + +#NET "clkout40" LOC = "AJ29"; +#NET "clkout40" IOSTANDARD="LVCMOS33"; +NET "oDebug(0)" LOC = "N10"; +NET "oDebug(1)" LOC = "N9"; +NET "oDebug(2)" LOC = "N8"; +NET "oDebug(3)" LOC = "N7"; +NET "oDebug(4)" LOC = "U8"; +NET "oDebug(5)" LOC = "T8"; +NET "oDebug(6)" LOC = "L6"; +NET "oDebug(7)" LOC = "L5"; +NET "oDebug(0)" IOSTANDARD="LVCMOS25"; +NET "oDebug(1)" IOSTANDARD="LVCMOS25"; +NET "oDebug(2)" IOSTANDARD="LVCMOS25"; +NET "oDebug(3)" IOSTANDARD="LVCMOS25"; +NET "oDebug(4)" IOSTANDARD="LVCMOS25"; +NET "oDebug(5)" IOSTANDARD="LVCMOS25"; +NET "oDebug(6)" IOSTANDARD="LVCMOS25"; +NET "oDebug(7)" IOSTANDARD="LVCMOS25"; +NET "oDebug(0)" SLEW="FAST"; +NET "oDebug(1)" SLEW="FAST"; +NET "oDebug(2)" SLEW="FAST"; +NET "oDebug(3)" SLEW="FAST"; +NET "oDebug(4)" SLEW="FAST"; +NET "oDebug(5)" SLEW="FAST"; +NET "oDebug(6)" SLEW="FAST"; +NET "oDebug(7)" SLEW="FAST"; + +# Temperature ADC MAX145 +#NET "ADC_Data_in_p" LOC = "L4"; +#NET "ADC_Data_in_n" LOC = "L3"; +#NET "ADC_Clk_p" LOC = "T9"; +#NET "ADC_Clk_n" LOC = "R9"; +#NET "ADC_nCS_p" LOC = "U3"; +#NET "ADC_nCS_n" LOC = "T3"; + +NET "doricreset1" LOC = "AJ11"; +NET "doricreset1" IOSTANDARD="LVCMOS25"; +NET "doricreset2" LOC = "AK11"; +NET "doricreset2" IOSTANDARD="LVCMOS25"; + +#NET "oExtrstP" LOC = "N10"; +#NET "oExtrstN" LOC = "N9"; +#NET "oExtrstP" IOSTANDARD="LVDS_25"; +#NET "oExtrstN" IOSTANDARD="LVDS_25"; + +NET "serialout_p(0)" LOC = "AJ9"; +NET "serialout_n(0)" LOC = "AH9"; +#NET "serialout_p(1)" LOC = "AJ9"; +#NET "serialout_n(1)" LOC = "AH9"; +NET "serialout_p(2)" LOC = "AL10"; +NET "serialout_n(2)" LOC = "AM10"; +#NET "serialout_p(3)" LOC = "AF9"; +#NET "serialout_n(3)" LOC = "AE9"; +NET "serialout_p(4)" LOC = "AF9"; +NET "serialout_n(4)" LOC = "AE9"; +#NET "serialout_p(5)" LOC = "AL9"; +#NET "serialout_n(5)" LOC = "AK9"; +NET "serialout_p(6)" LOC = "AL11"; +NET "serialout_n(6)" LOC = "AM11"; +#NET "serialout_p(7)" LOC = "AL10"; +#NET "serialout_n(7)" LOC = "AM10"; + +#NET "serialout_p(8)" LOC = "G30"; +#NET "serialout_n(8)" LOC = "F30"; +#NET "serialout_p(9)" LOC = "J31"; +#NET "serialout_n(9)" LOC = "J30"; +#NET "serialout_p(10)" LOC = "T26"; +#NET "serialout_n(10)" LOC = "R26"; +#NET "serialout_p(11)" LOC = "T31"; +#NET "serialout_n(11)" LOC = "T30"; +#NET "serialout_p(12)" LOC = "N27"; +#NET "serialout_n(12)" LOC = "M28"; +#NET "serialout_p(13)" LOC = "M32"; +#NET "serialout_n(13)" LOC = "M31"; +#NET "serialout_p(14)" LOC = "G32"; +#NET "serialout_n(14)" LOC = "G31"; +#NET "serialout_p(15)" LOC = "H28"; +#NET "serialout_n(15)" LOC = "H27"; + + +NET "serialin_p(0)" LOC = "G30"; +NET "serialin_n(0)" LOC = "F30"; +NET "serialin_p(1)" LOC = "J31"; +NET "serialin_n(1)" LOC = "J30"; +NET "serialin_p(2)" LOC = "T26"; +NET "serialin_n(2)" LOC = "R26"; +NET "serialin_p(3)" LOC = "T31"; +NET "serialin_n(3)" LOC = "T30"; +NET "serialin_p(4)" LOC = "N27"; +NET "serialin_n(4)" LOC = "M28"; +NET "serialin_p(5)" LOC = "M32"; +NET "serialin_n(5)" LOC = "M31"; +NET "serialin_p(6)" LOC = "G32"; +NET "serialin_n(6)" LOC = "G31"; +NET "serialin_p(7)" LOC = "H28"; +NET "serialin_n(7)" LOC = "H27"; + +#NET "serialin_p(8)" LOC = "AH15"; +#NET "serialin_n(8)" LOC = "AJ15"; +#NET "serialin_p(9)" LOC = "AF15"; +#NET "serialin_n(9)" LOC = "AG15"; +#NET "serialin_p(10)" LOC = "AE13"; +#NET "serialin_n(10)" LOC = "AF13"; +#NET "serialin_p(11)" LOC = "AJ16"; +#NET "serialin_n(11)" LOC = "AK16"; +#NET "serialin_p(12)" LOC = "H24"; +#NET "serialin_n(12)" LOC = "J24"; +#NET "serialin_p(13)" LOC = "G22"; +#NET "serialin_n(13)" LOC = "H22"; +#NET "serialin_p(14)" LOC = "E24"; +#NET "serialin_n(14)" LOC = "F24"; +#NET "serialin_p(15)" LOC = "J25"; +#NET "serialin_n(15)" LOC = "H25"; + + +#NET "discinP(0)" LOC = "AD7"; +#NET "discinP(1)" LOC = "AD6"; +#NET "discinP(2)" LOC = "AM6"; +#NET "discinP(3)" LOC = "AL6"; + +#NET "discinP(0)" IOSTANDARD= "LVCMOS33"; +#NET "discinP(1)" IOSTANDARD = "LVCMOS33"; +#NET "discinP(2)" IOSTANDARD= "LVCMOS33"; +#NET "discinP(3)" IOSTANDARD = "LVCMOS33"; + +NET "TX_EN" LOC="AJ6"; +NET "TX_DIS" LOC="AM3"; +NET "TX_RESET" LOC="AL3"; +NET "TX_FAULT" LOC="AG7"; +NET "RX0_RX_EN" LOC="AM6"; +NET "RX0_EN_SD" LOC="AL6"; +NET "RX0_SD" LOC="AG6"; +NET "RX0_SQ_EN" LOC="AG5"; +NET "RX1_RX_EN" LOC="AJ5"; +NET "RX1_EN_SD" LOC="AH5"; +NET "RX1_SD" LOC="AD21"; +NET "RX1_SQ_EN" LOC="AD20"; + +NET "TX_EN" IOSTANDARD= "LVCMOS33"; +NET "TX_DIS" IOSTANDARD= "LVCMOS33"; +NET "TX_RESET" IOSTANDARD= "LVCMOS33"; +NET "TX_FAULT" IOSTANDARD= "LVTTL"; +NET "RX0_RX_EN" IOSTANDARD= "LVCMOS33"; +NET "RX0_EN_SD" IOSTANDARD= "LVCMOS33"; +NET "RX0_SD" IOSTANDARD= "LVTTL"; +NET "RX0_SQ_EN" IOSTANDARD= "LVCMOS33"; +NET "RX1_RX_EN" IOSTANDARD= "LVCMOS33"; +NET "RX1_EN_SD" IOSTANDARD= "LVCMOS33"; +NET "RX1_SD" IOSTANDARD= "LVTTL"; +NET "RX1_SQ_EN" IOSTANDARD= "LVCMOS33"; + +#-------------------------- IO Standard Constraints -------------------------- +#----------------------------------------------------------------------------- +# This section defines the IO types, IO delays and other IO parameters +#----------------------------------------------------------------------------- + +NET "iResetInL" IOSTANDARD = "LVCMOS33"; +NET "oDispClk" IOSTANDARD = "LVCMOS33"; +NET "oDispDat" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(1)" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(0)" IOSTANDARD = "LVCMOS33"; +NET "oDispRstL" IOSTANDARD = "LVCMOS33"; + +NET "serialin_p(0)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(0)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(1)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(1)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(2)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(2)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(3)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(3)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(4)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(4)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(5)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(5)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(6)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(6)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(7)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(7)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(8)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(8)" IOSTANDARD = "LVDS_25"; + +NET "serialin_p(8)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(8)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(9)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(9)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(10)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(10)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(11)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(11)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(12)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(12)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(13)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(13)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(14)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(14)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(15)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(15)" IOSTANDARD = "LVDS_25"; + +NET "serialout_p(0)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(0)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(1)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(1)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(2)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(2)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(3)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(3)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(4)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(4)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(5)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(5)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(6)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(6)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(7)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(7)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(8)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(8)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(9)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(9)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(10)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(10)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(11)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(11)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(12)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(12)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(13)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(13)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(14)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(14)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(15)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(15)" IOSTANDARD = "LVDS_25"; diff --git a/rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.ucf.rotated b/rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.ucf.rotated new file mode 100644 index 00000000..da051433 --- /dev/null +++ b/rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.ucf.rotated @@ -0,0 +1,368 @@ + +#----------------------------------------------------------------------------- +# Title : LCLS BNL ASIC Test FPGA, Constraints File +# Project : LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# File : HsioStave0.ucf +# Author : Ryan Herbst, rherbst@slac.stanford.edu +# Created : 07/21/2008 +#----------------------------------------------------------------------------- +# Description: +# This file contains all of the user constraints required to implement the +# LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# Copyright (c) 2008 by Ryan Herbst. All rights reserved. +#----------------------------------------------------------------------------- +# Modification history +# 07/21/2008: created. +#----------------------------------------------------------------------------- + + +#----------------------------------------------------------------------------- +#-------------------------- Timing Constraints ------------------------------- +#----------------------------------------------------------------------------- +# This section contains the timing constraints for the FPGA +#----------------------------------------------------------------------------- + +# Define system clocks +NET pgpClk TNM_NET = FFS pgpClk; +#NET clk320 TNM_NET = FFS clk320; +NET sysClk125 TNM_NET = FFS sysClk125; +NET sysClk250 TNM_NET = FFS sysClk250; +NET mainClk TNM_NET = FFS mainClk; + +INST "U_triggerlogic/thetdc/CHAIN[*].TAP" U_SET="TDC1"; +INST "U_triggerlogic/thetdc/CHAIN[*].DELAYY" U_SET="TDC1"; +INST "U_triggerlogic/thetdc/startcontrol" U_SET="TDC1"; +INST "U_triggerlogic/thetdc/stopcontrol" U_SET="TDC1"; +#INST "U_HsioStave0Core2/thetdc/CHAIN[*].TAP" U_SET="TDC2"; +#INST "U_HsioStave0Core2/thetdc/CHAIN[*].DELAYY" U_SET="TDC2"; +#INST "U_HsioStave0Core2/thetdc/startcontrol" U_SET="TDC2"; +#IINST "U_HsioStave0Core2/thetdc/stopcontrol" U_SET="TDC2"; + +INST "U_triggerlogic/thetdc/stopcontrol" RLOC_ORIGIN="X44Y117"; +#INST "U_HsioStave0Core2/thetdc/stopcontrol" RLOC_ORIGIN="X44Y89"; + +# Define system clocks +TIMESPEC TS_pgpClk = PERIOD pgpClk 6.4 ns HIGH 50%; +TIMESPEC TS_sysClk125 = PERIOD sysClk125 25.6 ns HIGH 50%; +TIMESPEC TS_sysClk250 = PERIOD sysClk250 12.8 ns HIGH 50%; +#TIMESPEC TS_clk320 = PERIOD clk320 TS_pgpClk / 2; +TIMESPEC TS_mainClk = PERIOD mainClk 6.4 ns HIGH 50%; + +# Define time groups for inter-clock constraints +TIMEGRP TG_pgpClk_r = RISING pgpClk; +TIMEGRP TG_sysClk125_r = RISING sysClk125; +TIMEGRP TG_sysClk250_r = RISING sysClk250; +TIMEGRP TG_mainClk_r = RISING mainClk; + +# Inter Domain Constraints +# TIMESPEC TS_pgpClk_r_sysClk125_r = FROM TG_pgpClk_r TO TG_sysClk125_r 6.4ns; +TIMESPEC TS_sysClk125_r_pgpClk_r = FROM TG_sysClk125_r TO TG_pgpClk_r 6.4ns; +#TIMESPEC TS_sysClk125_r_sysClk250_r = FROM TG_sysClk125_r TO TG_sysClk250_r 8ns; +# NET U_HsioFei4Core/go TIG; +NET U_HsioStave0Core*/channelmask(*) TIG; +NET U_HsioStave0Core*/dfifothresh(*) TIG; +#NET U_HsioStave0Core*/enablereadout(*) TIG; + +timespec ts_02 = from ffs(*bz(0):*cz(0):*dz(0):*dz(1)) to ffs 640 MHz; +#timespec ts_03 = from ffs(*fei4fifo*) to ffs(*fei4dataflag*) 6.4ns; +#timespec ts_04 = from rams(*fei4fifo*) to ffs(*fei4dataflag*) 6.4ns; + +# Nets to ignore for timing +NET "iResetInL" TIG; + +NET serialinb(*) maxskew = 250 ps ; + +INST "U_HsioStave0Core*/*receivedata/ff_*" IOB=FALSE; + + +# Nets to ignore for timing +NET "iResetInL" TIG; + + +#----------------------------------------------------------------------------- +#-------------------------- Pin Location Constraints ------------------------- +#----------------------------------------------------------------------------- +# This section contains the pin location constraints for the design +#----------------------------------------------------------------------------- +# Old P5 = New P5 +# Old P4 = New P4 +# Old P9 = New P3 +# Old P3 = New P2 + + +NET "iPgpRefClkP" LOC = "J1"; +NET "iPgpRefClkM" LOC = "K1"; +#NET "iMainClkP" LOC = "H17"; +#NET "iMainClkN" LOC = "J17"; +# fiber 1 +NET "iMgtRxN" LOC = "N1"; +NET "iMgtRxP" LOC = "M1"; +NET "oMgtTxN" LOC = "T1"; +NET "oMgtTxP" LOC = "R1"; +# fiber 2 +NET "iMgtRxN2" LOC = "AA1"; +NET "iMgtRxP2" LOC = "Y1"; +NET "oMgtTxN2" LOC = "V1"; +NET "oMgtTxP2" LOC = "U1"; +NET "oReload" LOC = "G16"; +NET "iResetInL" LOC = "AJ19"; +NET "oDispClk" LOC = "AG22"; +NET "oDispDat" LOC = "AJ22"; +NET "oDispLoadL(1)" LOC = "AK17"; +NET "oDispLoadL(0)" LOC = "Ak18"; +NET "oDispRstL" LOC = "AH22"; +#NET "rclk" LOC = "AM21"; +# fiber 1 +NET "transDis1" LOC = "AH4"; +# fiber 2 +NET "transDis2" LOC = "AK4"; +NET "transDis1" IOSTANDARD="LVCMOS33"; +NET "transDis2" IOSTANDARD="LVCMOS33"; + + +#NET "refclk_p" LOC = "J25"; +#NET "refclk_p" IOSTANDARD="LVDS_25"; +#NET "refclk_n" LOC = "H25"; +#NET "refclk_n" IOSTANDARD="LVDS_25"; + +#NET "xclk_p" LOC = "E24"; +#NET "xclk_p" IOSTANDARD="LVDS_25"; +#NET "xclk_n" LOC = "F24"; +#NET "xclk_n" IOSTANDARD="LVDS_25"; + +#NET "clkout40" LOC = "AJ29"; +#NET "clkout40" IOSTANDARD="LVCMOS33"; +NET "oDebug(0)" LOC = "N10"; +NET "oDebug(0)" IOSTANDARD="LVCMOS25"; +NET "oDebug(0)" SLEW=FAST; +NET "oDebug(1)" LOC = "N9"; +NET "oDebug(1)" IOSTANDARD="LVCMOS25"; +NET "oDebug(1)" SLEW=FAST; +NET "oDebug(2)" LOC = "N8"; +NET "oDebug(2)" IOSTANDARD="LVCMOS25"; +NET "oDebug(2)" SLEW=FAST; +NET "oDebug(3)" LOC = "N7"; +NET "oDebug(3)" IOSTANDARD="LVCMOS25"; +NET "oDebug(3)" SLEW=FAST; +NET "oDebug(4)" LOC = "U8"; +NET "oDebug(4)" IOSTANDARD="LVCMOS25"; +NET "oDebug(4)" SLEW=FAST; +NET "oDebug(5)" LOC = "T8"; +NET "oDebug(5)" IOSTANDARD="LVCMOS25"; +NET "oDebug(5)" SLEW=FAST; +NET "oDebug(6)" LOC = "L6"; +NET "oDebug(6)" IOSTANDARD="LVCMOS25"; +NET "oDebug(6)" SLEW=FAST; +NET "oDebug(7)" LOC = "L5"; +NET "oDebug(7)" IOSTANDARD="LVCMOS25"; +NET "oDebug(7)" SLEW=FAST; + +# Temperature ADC MAX145 +#NET "ADC_Data_in_p" LOC = "L4"; +#NET "ADC_Data_in_n" LOC = "L3"; +#NET "ADC_Clk_p" LOC = "T9"; +#NET "ADC_Clk_n" LOC = "R9"; +#NET "ADC_nCS_p" LOC = "U3"; +#NET "ADC_nCS_n" LOC = "T3"; + +NET "iHSIOtrigger(0)" LOC="J14"; +NET "iHSIOtrigger(0)" IOSTANDARD="LVTTL"; +NET "iHSIOtrigger(0)" SLEW=FAST; + +NET "iHSIOtrigger(1)" LOC="L14"; +NET "iHSIOtrigger(1)" IOSTANDARD="LVTTL"; +NET "iHSIOtrigger(1)" SLEW=FAST; + +NET "oHSIOtrigger" LOC="L15"; +NET "oHSIOtrigger" IOSTANDARD="LVTTL"; +NET "oHSIOtrigger" SLEW=FAST; + +NET "iHSIObusy" LOC="H19"; +NET "iHSIObusy" IOSTANDARD="LVTTL"; +NET "iHSIObusy" SLEW=FAST; +NET "iHSIObusy" PULLDOWN; + +NET "iExtreload" LOC = "G15"; +NET "iExtreload" IOSTANDARD="LVCMOS25"; +NET "iExtreload" PULLUP; + +NET "doricreset1" LOC = "AJ11"; +NET "doricreset1" IOSTANDARD="LVCMOS25"; +NET "doricreset2" LOC = "AK11"; +NET "doricreset2" IOSTANDARD="LVCMOS25"; + +NET "iExtrst" LOC = "K18"; +NET "iExtrst" IOSTANDARD="LVCMOS33"; +NET "iExtrst" SLEW=FAST; +NET "iExttrigger" LOC = "K19"; +NET "iExttrigger" IOSTANDARD="LVCMOS33"; +NET "iExttrigger" SLEW=FAST; +NET "oExttrgclk" LOC = "K16"; +NET "oExttrgclk" IOSTANDARD="LVCMOS33"; +NET "oExttrgclk" SLEW=FAST; +NET "oExtBusy" LOC = "J16"; +NET "oExtBusy" IOSTANDARD="LVCMOS33"; +NET "oExtBusy" SLEW=FAST; + + +NET "serialout_p(1)" LOC = "AM13"; +NET "serialout_n(1)" LOC = "AM12"; +NET "serialout_p(0)" LOC = "AM8"; +NET "serialout_n(0)" LOC = "AM7"; +NET "serialout_p(3)" LOC = "AK14"; +NET "serialout_n(3)" LOC = "AL14"; +NET "serialout_p(2)" LOC = "AK13"; +NET "serialout_n(2)" LOC = "AL13"; +NET "serialout_p(5)" LOC = "AL11"; +NET "serialout_n(5)" LOC = "AM11"; +NET "serialout_p(4)" LOC = "AL9"; +NET "serialout_n(4)" LOC = "AK9"; +NET "serialout_p(7)" LOC = "AL10"; +NET "serialout_n(7)" LOC = "AM10"; +NET "serialout_p(6)" LOC = "AF9"; +NET "serialout_n(6)" LOC = "AE9"; + +NET "serialout_p(9)" LOC = "AK7"; +NET "serialout_n(9)" LOC = "AJ7"; +NET "serialout_p(8)" LOC = "AJ9"; +NET "serialout_n(8)" LOC = "AH9"; +NET "serialout_p(11)" LOC = "AF11"; +NET "serialout_n(11)" LOC = "AG11"; +NET "serialout_p(10)" LOC = "AH8"; +NET "serialout_n(10)" LOC = "AH7"; +NET "serialout_p(13)" LOC = "AJ12"; +NET "serialout_n(13)" LOC = "AK12"; +NET "serialout_p(12)" LOC = "AH10"; +NET "serialout_n(12)" LOC = "AJ10"; +NET "serialout_p(15)" LOC = "AH14"; +NET "serialout_n(15)" LOC = "AJ14"; +NET "serialout_p(14)" LOC = "AF10"; +NET "serialout_n(14)" LOC = "AG10"; + +NET "serialin_p(8)" LOC = "AC12"; +NET "serialin_n(8)" LOC = "AB12"; +NET "serialin_p(10)" LOC = "AG13"; +NET "serialin_n(10)" LOC = "AH13"; +NET "serialin_p(12)" LOC = "AD11"; +NET "serialin_n(12)" LOC = "AE11"; +NET "serialin_p(14)" LOC = "AD10"; +NET "serialin_n(14)" LOC = "AD9"; +NET "serialin_p(9)" LOC = "AE14"; +NET "serialin_n(9)" LOC = "AF14"; +NET "serialin_p(11)" LOC = "AB11"; +NET "serialin_n(11)" LOC = "AA11"; +NET "serialin_p(13)" LOC = "AD14"; +NET "serialin_n(13)" LOC = "AC13"; +NET "serialin_p(15)" LOC = "AB13"; +NET "serialin_n(15)" LOC = "AA13"; + +NET "serialin_p(0)" LOC = "AH15"; +NET "serialin_n(0)" LOC = "AJ15"; +NET "serialin_p(2)" LOC = "AF15"; +NET "serialin_n(2)" LOC = "AG15"; +NET "serialin_p(4)" LOC = "AE13"; +NET "serialin_n(4)" LOC = "AF13"; +NET "serialin_p(6)" LOC = "AJ16"; +NET "serialin_n(6)" LOC = "AK16"; +NET "serialin_p(1)" LOC = "H24"; +NET "serialin_n(1)" LOC = "J24"; +NET "serialin_p(3)" LOC = "G22"; +NET "serialin_n(3)" LOC = "H22"; +NET "serialin_p(5)" LOC = "E24"; +NET "serialin_n(5)" LOC = "F24"; +NET "serialin_p(7)" LOC = "J25"; +NET "serialin_n(7)" LOC = "H25"; + + +#NET "discinP(0)" LOC = "AD7"; +#NET "discinP(1)" LOC = "AD6"; +#NET "discinP(2)" LOC = "AM6"; +#NET "discinP(3)" LOC = "AL6"; + +#NET "discinP(0)" IOSTANDARD= "LVCMOS33"; +#NET "discinP(1)" IOSTANDARD = "LVCMOS33"; +#NET "discinP(2)" IOSTANDARD= "LVCMOS33"; +#NET "discinP(3)" IOSTANDARD = "LVCMOS33"; + +#-------------------------- IO Standard Constraints -------------------------- +#----------------------------------------------------------------------------- +# This section defines the IO types, IO delays and other IO parameters +#----------------------------------------------------------------------------- + +NET "iResetInL" IOSTANDARD = "LVCMOS33"; +NET "oDispClk" IOSTANDARD = "LVCMOS33"; +NET "oDispDat" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(1)" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(0)" IOSTANDARD = "LVCMOS33"; +NET "oDispRstL" IOSTANDARD = "LVCMOS33"; + +NET "serialin_p(0)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(0)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(1)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(1)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(2)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(2)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(3)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(3)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(4)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(4)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(5)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(5)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(6)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(6)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(7)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(7)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(8)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(8)" IOSTANDARD = "LVDS_25"; + +NET "serialin_p(8)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(8)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(9)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(9)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(10)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(10)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(11)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(11)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(12)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(12)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(13)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(13)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(14)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(14)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(15)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(15)" IOSTANDARD = "LVDS_25"; + +NET "serialout_p(0)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(0)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(1)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(1)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(2)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(2)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(3)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(3)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(4)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(4)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(5)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(5)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(6)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(6)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(7)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(7)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(8)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(8)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(9)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(9)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(10)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(10)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(11)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(11)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(12)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(12)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(13)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(13)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(14)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(14)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(15)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(15)" IOSTANDARD = "LVDS_25"; diff --git a/rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.vhd b/rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.vhd new file mode 100755 index 00000000..1a369aed --- /dev/null +++ b/rce/fw-hsio/projects/HsioStave0/hdl/HsioStave0.vhd @@ -0,0 +1,886 @@ +------------------------------------------------------------------------------- +-- Title : BNL ASIC Test FGPA, Top Level +-- Project : LCLS Detector, BNL ASIC +------------------------------------------------------------------------------- +-- File : HsioCosmic.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 07/21/2008 +------------------------------------------------------------------------------- +-- Description: +-- Top level logic for BNL ASIC test FPGA. +------------------------------------------------------------------------------- +-- Copyright (c) 2008 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 07/21/2008: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +Library Unisim; +USE ieee. std_logic_1164.ALL; +use ieee. std_logic_arith.all; +use ieee. std_logic_unsigned.all; +USE work.ALL; + +entity HsioStave0 is + port ( + + -- PGP Crystal Clock Input, 156.25Mhz + iPgpRefClkP : in std_logic; + iPgpRefClkM : in std_logic; + + -- System clock 125 MHz clock input + iMainClkP : in std_logic; + iMainClkN : in std_logic; + + -- PGP Rx/Tx Lines + iMgtRxN : in std_logic; + iMgtRxP : in std_logic; + oMgtTxN : out std_logic; + oMgtTxP : out std_logic; + iMgtRxN2 : in std_logic; + iMgtRxP2 : in std_logic; + oMgtTxN2 : out std_logic; + oMgtTxP2 : out std_logic; + + -- ATLAS Pixel module pins + serialin : in std_logic_vector(15 downto 0); + serialout : out std_logic_vector(15 downto 0); + serialout_p : out std_logic_vector(15 downto 0); + serialout_n : out std_logic_vector(15 downto 0); + serialin_p : in std_logic_vector(15 downto 0); + serialin_n : in std_logic_vector(15 downto 0); + discinP : in std_logic_vector(3 downto 0); + HITOR : in std_logic; +-- discinN : in std_logic_vector(1 downto 0); + clkout40 : out std_logic; + refclk_p : out std_logic; + refclk_n : out std_logic; + xclk_p : out std_logic; + xclk_n : out std_logic; + + -- Reset button + iResetInL : in std_logic; + -- Reload firmware + oReload : out std_logic; + iExtreload : in std_logic; + -- LED Display + oDispClk : out std_logic; + oDispDat : out std_logic; + oDispLoadL : out std_logic_vector(1 downto 0); + oDispRstL : out std_logic; + + -- Debug + oDebug : out std_logic_vector(7 downto 0); + + -- Eudet trigger + iExttrigger : in std_logic; + iExtrst : in std_logic; + oExtbusy : out std_logic; + oExttrgclk : out std_logic; + + --HSIO trigger IF + iHSIOtrigger : in std_logic_vector(1 downto 0); + oHSIOtrigger : out std_logic; + oHSIObusy : out std_logic; + iHSIObusy : in std_logic; + + oExtrstP : out std_logic; + oExtrstN : out std_logic; + oExttriggerP : out std_logic; + oExttriggerN : out std_logic; + + + -- Misc Signals + oPdBuff0 : out std_logic; + oPdBuff1 : out std_logic; + oPdBuff3 : out std_logic; + oPdBuff4 : out std_logic; + oLemoA : out std_logic; + iLemoB : in std_logic; + + -- Transmitter enable + transDis1 : out std_logic; + transDis2 : out std_logic; + + -- Doric resets + doricreset1: out std_logic; + doricreset2: out std_logic; + --unused_p : out std_logic_vector(3 downto 0); + --unused_n : out std_logic_vector(3 downto 0); + + -- Fiber modules + TX_EN : out std_logic; + TX_DIS : out std_logic; + TX_RESET : out std_logic; + TX_FAULT : in std_logic; + RX0_RX_EN : out std_logic; + RX0_EN_SD : out std_logic; + RX0_SD : in std_logic; + RX0_SQ_EN : out std_logic; + RX1_RX_EN : out std_logic; + RX1_EN_SD : out std_logic; + RX1_SD : in std_logic; + RX1_SQ_EN : out std_logic + ); +end HsioStave0; + + +-- Define architecture for top level module +architecture HsioStave0 of HsioStave0 is + + -- Synthesis control attributes + attribute syn_useioff : boolean; + attribute syn_useioff of HsioStave0 : architecture is true; + attribute xc_fast_auto : boolean; + attribute xc_fast_auto of HsioStave0 : architecture is false; + attribute syn_noclockbuf : boolean; + attribute syn_noclockbuf of HsioStave0 : architecture is true; + + -- IO Pad components + component IBUF port ( O : out std_logic; I : in std_logic ); end component; + component OBUF port ( O : out std_logic; I : in std_logic ); end component; + component OBUFDS + generic( IOSTANDARD: STRING:= "LVDS_25"; + SLEW: STRING:="FAST"); + port ( O : out std_logic; OB : out std_logic; I : in std_logic ); + end component; + + -- Input LVDS with termination + component IBUFDS + generic ( DIFF_TERM : boolean := TRUE; + IOSTANDARD: STRING := "LVDS_25"); + port ( O : out std_logic; I : in std_logic; IB : in std_logic ); + end component; + + -- Xilinx global clock buffer component + component BUFGMUX + port ( + O : out std_logic; + I0 : in std_logic; + I1 : in std_logic; + S : in std_logic + ); + end component; + + component IDELAYCTRL + port ( RDY : out std_logic; + REFCLK : in std_logic; + RST : in std_logic + ); + end component; + +component IDELAY + generic (IOBDELAY_TYPE : string := "DEFAULT"; --(DEFAULT, FIXED, VARIABLE) + IOBDELAY_VALUE : integer := 0 --(0 to 63) + ); + port ( + O : out STD_LOGIC; + I : in STD_LOGIC; + C : in STD_LOGIC; + CE : in STD_LOGIC; + INC : in STD_LOGIC; + RST : in STD_LOGIC + ); +end component; +--component ila + --PORT ( + --CONTROL : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0); + --CLK : IN STD_LOGIC; + --DATA : IN STD_LOGIC_VECTOR(31 DOWNTO 0); + --TRIG0 : IN STD_LOGIC_VECTOR(0 DOWNTO 0)); +-- +--end component; + --component icon + --PORT ( + --CONTROL0 : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0)); +-- + --end component; + + + -- Local signals + signal resetInL : std_logic; + signal tmpClk250 : std_logic; + signal sysClk125 : std_logic; + signal sysRst125 : std_logic; + signal sysRst250 : std_logic; + signal sysClk250 : std_logic; + signal refClock : std_logic; + signal pgpClk : std_logic; + signal pgpClk90 : std_logic; + signal pgpReset : std_logic; + signal clk320 : std_logic; + signal oClk320 : std_logic; + signal reload1 : std_logic; + signal reload2 : std_logic; + signal reload : std_logic; + signal resetOut : std_logic; + signal resetOut1 : std_logic; + signal resetOut2 : std_logic; + signal mgtRxN : std_logic; + signal mgtRxP : std_logic; + signal mgtTxN : std_logic; + signal mgtTxP : std_logic; + signal mgtRxN2 : std_logic; + signal mgtRxP2 : std_logic; + signal mgtTxN2 : std_logic; + signal mgtTxP2 : std_logic; + signal dispClk : std_logic; + signal dispDat : std_logic; + signal dispLoadL : std_logic_vector(1 downto 0); + signal dispRstL : std_logic; + signal debug : std_logic_vector(7 downto 0); + signal sysClk125i : std_logic; + signal mainClk : std_logic; + signal clk0 : std_logic; + signal clkin : std_logic; + signal halfclock : std_logic; + signal quarterclock : std_logic; + signal exttrigger : std_logic; + signal extrst : std_logic; + signal exttriggero : std_logic; + signal extrsto : std_logic; + signal extbusy : std_logic; + signal exttrgclk : std_logic; + signal hsiobusyb : std_logic; + signal hsiobusyinb : std_logic; + signal hsiobusyb1 : std_logic; + signal hsiobusyb2 : std_logic; + signal hsiotriggerb : std_logic_vector(1 downto 0); + signal doricresetb1 : std_logic; + signal doricresetb2 : std_logic; + signal serialoutb : std_logic_vector(7 downto 0); + signal serialoutb1 : std_logic_vector(15 downto 0); + signal serialoutb2 : std_logic_vector(15 downto 0); + signal serialinb : std_logic_vector(15 downto 0); + signal serialinb1 : std_logic_vector(15 downto 0); + signal serialinb2 : std_logic_vector(15 downto 0); + signal serialininv : std_logic_vector(15 downto 0); + signal discinb : std_logic_vector(3 downto 0); + signal ccontrol: std_logic_vector(35 downto 0); + signal cdata: std_logic_vector(31 downto 0); + signal ctrig: std_logic_vector(0 downto 0); + signal clockb : std_logic_vector(7 downto 0); + signal extreload : std_logic; + signal dispDatA : std_logic; + signal dispDatB : std_logic; + signal pgpDispA : std_logic_vector(7 downto 0); + signal pgpDispB : std_logic_vector(7 downto 0); + signal dispDigitA : std_logic_vector(7 downto 0); + signal dispDigitB : std_logic_vector(7 downto 0); + signal dispDigitC : std_logic_vector(7 downto 0); + signal dispDigitD : std_logic_vector(7 downto 0); + signal dispDigitE : std_logic_vector(7 downto 0); + signal dispDigitF : std_logic_vector(7 downto 0); + signal dispDigitG : std_logic_vector(7 downto 0); + signal dispDigitH : std_logic_vector(7 downto 0); + signal dispStrobe : std_logic; + signal dispUpdateA : std_logic; + signal dispUpdateB : std_logic; + signal sysClkCnt : std_logic_vector(15 downto 0); + signal lockedid : std_logic; + signal oldlockedid : std_logic; + signal holdrst : std_logic; + signal hitorb : std_logic; + + signal txfault : std_logic; + signal rx0sd : std_logic; + signal rx1sd : std_logic; + + signal pgpClkUnbuf : std_logic; + signal pgpClk90Unbuf : std_logic; + signal sysClkUnbuf : std_logic; + signal disc : std_logic_vector(4 downto 0); + + signal calibmode1 : std_logic_vector(1 downto 0); + signal calibmode2 : std_logic_vector(1 downto 0); + signal calibmode : std_logic_vector(1 downto 0); + signal eudaqdone : std_logic; + signal eudaqtrgword : std_logic_vector(14 downto 0); + signal trigenabled1 : std_logic; + signal trigenabled2 : std_logic; + signal trigenabled : std_logic; + signal paused1 : std_logic; + signal paused2 : std_logic; + signal paused : std_logic; + signal triggermask1 : std_logic_vector(15 downto 0); + signal triggermask2 : std_logic_vector(15 downto 0); + signal triggermask : std_logic_vector(15 downto 0); + signal resetdelay1 : std_logic; + signal resetdelay2 : std_logic; + signal resetdelay : std_logic; + signal incrementdelay1: std_logic_vector(4 downto 0); + signal incrementdelay2: std_logic_vector(4 downto 0); + signal incrementdelay: std_logic_vector(4 downto 0); + signal discop1 : std_logic_vector(15 downto 0); + signal discop2 : std_logic_vector(15 downto 0); + signal discop : std_logic_vector(15 downto 0); + signal telescopeop1 : std_logic_vector(2 downto 0); + signal telescopeop2 : std_logic_vector(2 downto 0); + signal telescopeop : std_logic_vector(2 downto 0); + signal period1 : std_logic_vector(31 downto 0); + signal period2 : std_logic_vector(31 downto 0); + signal period : std_logic_vector(31 downto 0); + signal fifothresh : std_logic; + signal fifothresh1 : std_logic; + signal fifothresh2 : std_logic; + signal serbusy1 : std_logic; + signal serbusy2 : std_logic; + signal serbusy : std_logic; + signal tdcreadoutbusy1: std_logic; + signal tdcreadoutbusy2: std_logic; + signal tdcreadoutbusy: std_logic; + signal tcounter1 : std_logic_vector(31 downto 0); + signal tcounter2 : std_logic_vector(31 downto 0); + signal l1a1 : std_logic; + signal l1a2 : std_logic; + signal l1a : std_logic; + signal triggerword : std_logic_vector(7 downto 0); + signal busy : std_logic; + signal rstFromCore1 : std_logic; + signal rstFromCore2 : std_logic; + signal rstFromCore : std_logic; + signal hitbus : std_logic_vector(1 downto 0); + signal present : std_logic_vector(1 downto 0); + signal phaseclksel : std_logic; + signal phaseclksel1 : std_logic; + signal phaseclksel2 : std_logic; + signal startmeas : std_logic; + signal startmeas1 : std_logic; + signal startmeas2 : std_logic; + signal hitbusout : std_logic; + signal hitbusoutgated: std_logic; + signal phasebusySelc : is array (1 downto 0) of std_logic_vector(1 downto 0); + signal phasebusySel : std_logic_vector(1 downto 0); + signal phasebusyEnc : std_logic_vector(1 downto 0); + signal phasebusyEn : std_logic; + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + signal holdctr : std_logic_vector(24 downto 0); + signal clockidctrl : std_logic; + signal idctrlrst : std_logic; + signal idcounter : std_logic_vector(2 downto 0); + component ODDR port ( + Q : out std_logic; + CE : in std_logic; + C : in std_logic; + D1 : in std_logic; + D2 : in std_logic; + R : in std_logic; + S : in std_logic + ); + end component; + + -- Black Box Attributes +-- attribute syn_noprune : boolean; +-- attribute syn_noprune of chipscope : label is true; +-- attribute syn_noprune of chipscopeicon : label is true; + attribute syn_black_box : boolean; + attribute syn_noprune : boolean; + attribute syn_black_box of IBUF : component is TRUE; + attribute syn_noprune of IBUF : component is TRUE; + attribute syn_black_box of OBUF : component is TRUE; + attribute syn_noprune of OBUF : component is TRUE; + attribute syn_black_box of IBUFDS : component is TRUE; + attribute syn_noprune of IBUFDS : component is TRUE; + attribute syn_black_box of OBUFDS : component is TRUE; + attribute syn_noprune of OBUFDS : component is TRUE; + attribute syn_black_box of BUFGMUX : component is TRUE; + attribute syn_noprune of BUFGMUX : component is TRUE; + attribute syn_hier: string; + attribute syn_hier of HsioStave0: architecture is "hard"; + attribute xc_props : string; + attribute xc_props of HsioStave0 : architecture is "KEEP_HIERARCHY=TRUE"; + attribute syn_noprune of U_idelayctrl: label is true; +begin + + -- Reset input + U_ResetIn: IBUF port map ( I => iResetInL, O => resetInL ); + + -- PGP Clock Generator + U_PgpClkGen: entity work.PgpClkGen generic map ( + RefClkEn1 => "ENABLE", + RefClkEn2 => "DISABLE", + DcmClkSrc => "RefClk1", + UserFxDiv => 4, + UserFxMult => 2 + ) port map ( + pgpRefClkInP => iPgpRefClkP, + pgpRefClkInN => iPgpRefClkM, + ponResetL => resetInL, + locReset => resetOut, + pgpRefClk1 => refClock, + pgpRefClk2 => open, + pgpClk => pgpClk, + pgpClk90 => pgpClk90, + pgpReset => pgpReset, + clk320 => clk320, + pgpClkIn => pgpClk, + userClk => sysClk125, + userReset => sysRst125, + userClkIn => sysClk125, + pgpClkUnbuf => pgpClkUnbuf, + pgpClk90Unbuf => pgpClk90Unbuf, + locClkUnbuf => sysClkUnbuf + + ); + + -- Generate Divided Clock, sample reset + process ( pgpClk ) begin + if rising_edge(pgpClk) then + tmpClk250 <= not tmpClk250 after tpd; + sysRst250 <= sysRst125 after tpd; + end if; + end process; + + -- Global Buffer For 125Mhz Clock + U_CLK125: BUFGMUX port map ( + O => sysClk250, + I0 => tmpClk250, + I1 => '0', + S => '0' + ); + + -- No Pads for MGT Lines + mgtRxN <= iMgtRxN; + mgtRxP <= iMgtRxP; + oMgtTxN <= mgtTxN; + oMgtTxP <= mgtTxP; + mgtRxN2 <= iMgtRxN2; + mgtRxP2 <= iMgtRxP2; + oMgtTxN2 <= mgtTxN2; + oMgtTxP2 <= mgtTxP2; + + -- fiber modules + U_TX_EN : OBUF port map ( I => '1' , O => TX_EN ); + U_TX_DIS : OBUF port map ( I => '0' , O => TX_DIS ); + U_TX_RESET : OBUF port map ( I => '1' , O => TX_RESET ); + U_RX0_RX_EN: OBUF port map ( I => '1' , O => RX0_RX_EN ); + U_RX0_EN_SD: OBUF port map ( I => '0' , O => RX0_EN_SD ); + U_RX0_SQ_EN: OBUF port map ( I => '0' , O => RX0_SQ_EN ); + U_RX1_RX_EN: OBUF port map ( I => '1' , O => RX1_RX_EN ); + U_RX1_EN_SD: OBUF port map ( I => '0' , O => RX1_EN_SD ); + U_RX1_SQ_EN: OBUF port map ( I => '0' , O => RX1_SQ_EN ); + U_TX_FAULT: IBUF port map ( O => txfault , I => TX_FAULT ); + U_RX0_SD: IBUF port map ( O => rx0sd , I => RX0_SD ); + U_RX1_SD: IBUF port map ( O => rx1sd , I => RX1_SD ); + -- LED Display + U_DispClk : OBUF port map ( I => dispClk , O => oDispClk ); + U_DispDat : OBUF port map ( I => dispDat , O => oDispDat ); + U_DispLoadL1 : OBUF port map ( I => dispLoadL(1) , O => oDispLoadL(1) ); + U_DispLoadL0 : OBUF port map ( I => dispLoadL(0) , O => oDispLoadL(0) ); + U_DispRstL : OBUF port map ( I => dispRstL , O => oDispRstL ); + U_reload : OBUF port map ( I => reload , O => oReload ); + U_clkout40 : OBUF port map ( I => sysClk125i , O => clkout40 ); + U_refclk : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => sysClk125i , O => refclk_p , OB => refclk_n ); + U_xclk : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => sysClk125i , O => xclk_p , OB => xclk_n ); + +-- U_Clk320 : ODDR port map ( +-- Q => oClk320, +-- CE => '1', +-- C => clk320, +-- D1 => '0', +-- D2 => '1', +-- R => '0', +-- S => '0' +-- ); +-- U_clk320buf : OBUFDS generic map ( IOSTANDARD=>"LVDS_25") +-- port map ( I => oClk320 , O => oDebug(4) , OB => oDebug(5) ); + +-- U_bit0out : OBUFDS generic map ( IOSTANDARD=>"LVDS_25") +-- port map ( I => debug(7) , O => oDebug(6) , OB => oDebug(7) ); + + --UNUSED_IO_DATA: + --for I in 0 to 3 generate + --U_unused : OBUFDS generic map ( IOSTANDARD=>"LVDS_25") + -- port map ( I => '0' , O => unused_p(I) , OB => unused_n(I) ); + --end generate UNUSED_IO_DATA; + -- Debug + U_Debug0 : OBUF port map ( I => debug(0) , O => oDebug(0) ); + U_Debug1 : OBUF port map ( I => debug(1) , O => oDebug(1) ); + U_Debug2 : OBUF port map ( I => debug(2) , O => oDebug(2) ); + U_Debug3 : OBUF port map ( I => debug(3) , O => oDebug(3) ); + U_Debug4 : OBUF port map ( I => debug(4) , O => oDebug(4) ); + U_Debug5 : OBUF port map ( I => debug(5) , O => oDebug(5) ); + U_Debug6 : OBUF port map ( I => debug(6) , O => oDebug(6) ); + U_Debug7 : OBUF port map ( I => debug(7) , O => oDebug(7) ); + + U_transdis : OBUF port map ( I => '0' , O => transDis1 ); + U_transdis2 : OBUF port map ( I => '0' , O => transDis2 ); + + U_rstb_1 : OBUF port map ( I => doricresetb1 , O => doricreset1 ); + U_rstb_2 : OBUF port map ( I => doricresetb2 , O => doricreset2 ); + + U_exttrgclk : OBUF port map ( I => exttrgclk , O => oExttrgclk ); + + U_extbusy : OBUF port map ( I => extbusy , O => oExtBusy ); + + U_exttrigger : IBUF port map ( O => exttrigger , I => iExttrigger ); + + U_extrst : IBUF port map ( O => extrst , I => iExtrst ); + + --U_exttriggero : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + -- port map ( I => exttriggero , O => oExttriggerP , OB => oExttriggerN ); + U_exttriggero : OBUF port map ( I => exttriggero , O => oExttriggerP ); + + U_extrsto : OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => extrsto , O => oExtrstP , OB => oExtrstN ); + + U_HSIObusy : OBUF port map ( I => hsiobusyb , O => oHSIObusy); + hitbusoutgated <= hitbusout and trigenabled and not paused; + U_HSIOtriggero : OBUF port map ( I => hitbusoutgated , O => oHSIOtrigger); + U_HSIOtrigger : IBUF port map ( O => hsiotriggerb(0) , I => iHSIOtrigger(0) ); + U_HSIOtrigger2 : IBUF port map ( O => hsiotriggerb(1) , I => iHSIOtrigger(1) ); + U_hsiobusyin : IBUF port map ( O => hsiobusyinb , I => iHSIObusy ); + U_extreload : IBUF port map ( O => extreload , I => iExtreload ); + + SERIALOUT_IO_DATA: + for I in 0 to 7 generate + U_serialout_pn :OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => serialoutb(I) , O => serialout_p(I*2) , OB => serialout_n(I*2) ); + U_Clk320 : ODDR port map ( + Q => clockb(I), + CE => '1', + C => sysClk125, + D1 => '0', + D2 => '1', + R => '0', + S => '0' + ); + U_serialoutclock_pn :OBUFDS generic map ( IOSTANDARD=>"LVDS_25", SLEW=>"FAST") + port map ( I => clockb(I) , O => serialout_p(I*2+1) , OB => serialout_n(I*2+1) ); + end generate SERIALOUT_IO_DATA; + + SERIALIN_IO_DATA: + for I in 0 to 15 generate + U_serialin_pn : IBUFDS generic map ( DIFF_TERM=>TRUE, IOSTANDARD=>"LVDS_25") + port map ( I => serialin_p(I) , IB=>serialin_n(I) , O => serialininv(I) ); + serialinb(I)<=not serialininv(I); + + end generate SERIALIN_IO_DATA; + + + --DISC_1: IBUFDS port map ( O => discinb(0), I => discinP(0) , IB => discinN(0) ); + --DISC_2: IBUFDS port map ( O => discinb(1), I => discinP(1) , IB => discinN(1) ); + DISC_1: IBUF port map ( O => discinb(0), I => discinP(0) ); + DISC_2: IBUF port map ( O => discinb(1), I => discinP(1) ); + DISC_3: IBUF port map ( O => discinb(2), I => discinP(2) ); + DISC_4: IBUF port map ( O => discinb(3), I => discinP(3) ); + DISC_5: IBUF port map ( O => hitorb, I => HITOR); + + -- Display Controller A + U_DispCntrlA: entity work.DisplayControl port map ( + sysClk => sysClk125, sysRst => sysRst125, + dispStrobe => dispStrobe, dispUpdate => dispUpdateA, + dispRotate => "01", dispDigitA => dispDigitA, + dispDigitB => dispDigitB, dispDigitC => dispDigitC, + dispDigitD => dispDigitD, dispClk => dispClk, + dispDat => dispDatA, dispLoadL => dispLoadL(0), + dispRstL => dispRstL + ); + + -- Display Controller B + U_DispCntrlB: entity work.DisplayControl port map ( + sysClk => sysClk125, sysRst => sysRst125, + dispStrobe => dispStrobe, dispUpdate => dispUpdateB, + dispRotate => "01", dispDigitA => dispDigitE, + dispDigitB => dispDigitF, dispDigitC => dispDigitG, + dispDigitD => dispDigitH, dispClk => open, + dispDat => dispDatB, dispLoadL => dispLoadL(1), + dispRstL => open + ); + + -- Output LED Data + dispDat <= dispDatA or dispDatB; + -- Generate display strobe (200ns) and update control + process ( sysClk125, sysRst125 ) begin + if sysRst125 = '1' then + sysClkCnt <= (others=>'0') after tpd; + dispStrobe <= '0' after tpd; + dispUpdateA <= '0' after tpd; + dispUpdateB <= '0' after tpd; + elsif rising_edge(sysClk125) then + + -- Display strobe, 320ns + dispStrobe <= sysClkCnt(4) after tpd; + + -- Update Display 0 + if sysClkCnt(15 downto 0) = x"8000" then + dispUpdateA <= '1' after tpd; + else + dispUpdateA <= '0' after tpd; + end if; + + -- Update Display B + if sysClkCnt(15 downto 0) = x"0000" then + dispUpdateB <= '1' after tpd; + else + dispUpdateB <= '0' after tpd; + end if; + + -- Update counter + sysClkCnt <= sysClkCnt + 1 after tpd; + + + end if; + end process; + + + --debug(7 downto 0)<=serialinb(7 downto 0); + paused <= paused1 or paused2; + resetdelay <= resetdelay1 or resetdelay2; + incrementdelay <= incrementdelay1 or incrementdelay2; + serbusy <= (serbusy1 and present(0)) or (serbusy2 and present(1)); + tdcreadoutbusy<= tdcreadoutbusy1 or tdcreadoutbusy2; + rstFromCore <= rstFromCore1 or rstFromCore2; + + phasebusyEn <= phasebusyEnc(0) or phasebusyEnc(1); + phasebusySel <= phasebusySelc(0) or phasebusySelc(1); + + fifothresh <= (fifothresh1 and present(0)) or (fifothresh2 and present(1)); + trigenabled <= (trigenabled1 or not present(0)) and (trigenabled2 or not present(1)) and (present(0) or present(1)); + l1a1 <= l1a and present(0); + l1a2 <= l1a and present(1); + + with present select discop <= discop2 when "10", discop1 when others; + with present select calibmode <= calibmode2 when "10", calibmode1 when others; + with present select triggermask <= triggermask2 when "10", triggermask1 when others; + with present select period <= period2 when "10", period1 when others; + with present select telescopeop <= telescopeop2 when "10", telescopeop1 when others; + with present select phaseclksel <= phaseclksel2 when "10", phaseclksel1 when others; + with present select startmeas <= startmeas2 when "10", startmeas1 when others; + + + U_triggerlogic: entity work.triggerlogic + port map( + clk => sysClk125, + rst => rstFromCore, + clk160 => pgpClk, + rst160 => pgpReset, + -- hardware inputs + discin => discinb, + hitbusin => hitbus, + -- HSIO trigger + HSIObusy => hsiobusyb, + HSIOtrigger => hsiotriggerb, + HSIObusyin => hsiobusyinb, + hitbusout => hitbusout, + + -- eudet trigger + exttrigger => exttrigger, + extrst => extrst, + extbusy => extbusy, + exttrgclk => exttrgclk, + + calibmode => calibmode, + startmeas => startmeas, + eudaqdone => eudaqdone, + eudaqtrgword => eudaqtrgword, + tcounter1 => tcounter1, + tcounter2 => tcounter2, + + trigenabled => trigenabled, + paused => paused, + triggermask => triggermask, + resetdelay => resetdelay, + incrementdelay => incrementdelay, + discop => discop, + telescopeop => telescopeop, + period => period, + fifothresh => fifothresh, + serbusy => serbusy, + tdcreadoutbusy => tdcreadoutbusy, + phaseclksel => phaseclksel, + phasebusyEn => phasebusyEn, + phasebusySel => phasebusySel, + l1a => l1a, + triggerword => triggerword, + busy =>busy, + coincd =>open +); + -- FPGA Core + U_HsioStave0Core1: entity work.HsioPixelCore + generic map( framedFirstChannel=> 0, + framedLastChannel=> 7, + rawFirstChannel => 11, + rawLastChannel => 10, + buffersizefe => 4096, + buffersizetdc => 16384, + encodingDefault => "00", + hitbusreadout => '1') + port map ( + sysClk250 => sysClk250, sysRst250 => sysRst250, + sysClk125 => sysClk125, sysRst125 => sysRst125, + refClock => refClock, pgpClk => pgpClk, + pgpClk90 => pgpClk90, pgpReset => pgpReset, + clk320 => clk320, reload => reload1, + mgtRxN => mgtRxN, + mgtRxP => mgtRxP, mgtTxN => mgtTxN, + mgtTxP => mgtTxP, serialin => serialinb1, + serialout => serialoutb1, clock160 => mainClk, + clock80 => halfclock, clock40 => quarterclock, + resetOut => resetOut1, l1a => l1a1, + latchtriggerword => triggerword, tcounter1 => tcounter1, + tcounter2 => tcounter2, busy => busy, + eudaqdone => eudaqdone, eudaqtrgword => eudaqtrgword, + calibmodeout => calibmode1, startmeas => startmeas1, + pausedout => paused1, present => present(0), + trgenabledout => trigenabled1, rstFromCore => rstFromCore1, + fifothresh => fifothresh1, triggermask => triggermask1, + discop => discop1, period => period1, + telescopeop => telescopeop1, resetdelay => resetdelay1, + incrementdelay => incrementdelay1, + sbusy => serbusy1, tdcbusy => tdcreadoutbusy1, + phaseclksel => phaseclksel1 , hitbus => hitbus(0), + debug => debug, + exttriggero => exttriggero, extrsto => extrsto, + doricreset => doricresetb1, + phasebusyEn => phasebusyEnc(0), phasebusySel => phasebusySelc(0), + dispDigitA => dispDigitE, dispDigitB => dispDigitF, + dispDigitC => open, dispDigitD => dispDigitH, + dispDigitE => open, dispDigitF => open, + dispDigitG => open, dispDigitH => open, + pgpClkUnbuf => pgpClkUnbuf, pgpClk90Unbuf => pgpClk90Unbuf, + sysClkUnbuf => sysClkUnbuf, trigAdc => open, + sendAdcData => '0', adcData => (others => (others => '0')) + ); + dispDigitC<="0000000"&present(0); + dispDigitG<="0000000"&present(1); + U_HsioStave0Core2: entity work.HsioPixelCore + generic map( framedFirstChannel=> 0, + framedLastChannel=> 7, + rawFirstChannel => 11, + rawLastChannel => 10, + buffersizefe => 4096, + buffersizetdc => 16384, + encodingDefault => "00", + hitbusreadout => '1') + port map ( + sysClk250 => sysClk250, sysRst250 => sysRst250, + sysClk125 => sysClk125, sysRst125 => sysRst125, + refClock => refClock, pgpClk => pgpClk, + pgpClk90 => pgpClk90, pgpReset => pgpReset, + clk320 => clk320, reload => reload2, + mgtRxN => mgtRxN2, + mgtRxP => mgtRxP2, mgtTxN => mgtTxN2, + mgtTxP => mgtTxP2, serialin => serialinb2, + serialout => serialoutb2, clock160 => mainClk, + clock80 => halfclock, clock40 => quarterclock, + resetOut => resetOut2, l1a => l1a2, + latchtriggerword => triggerword, tcounter1=>tcounter1, + tcounter2=>tcounter2, busy =>busy, + eudaqdone => eudaqdone, eudaqtrgword => eudaqtrgword, + calibmodeout => calibmode2, startmeas => startmeas2, + pausedout => paused2, present => present(1), + trgenabledout => trigenabled2, rstFromCore => rstFromCore2, + fifothresh => fifothresh2, triggermask => triggermask2, + discop => discop2, period => period2, + telescopeop => telescopeop2, resetdelay => resetdelay2, + incrementdelay => incrementdelay2, + sbusy => serbusy2, tdcbusy => tdcreadoutbusy2, + phaseclksel=>phaseclksel2, hitbus => hitbus(1), + debug => open, + exttriggero => open, extrsto => open, + doricreset => doricresetb2, + phasebusyEn => phasebusyEnc(1), phasebusySel => phasebusySelc(1), + dispDigitA => dispDigitA, dispDigitB => dispDigitB, + dispDigitC => open, dispDigitD => dispDigitD, + dispDigitE => open, dispDigitF => open, + dispDigitG => open, dispDigitH => open, + pgpClkUnbuf => pgpClkUnbuf, pgpClk90Unbuf => pgpClk90Unbuf, + sysClkUnbuf => sysClkUnbuf, trigAdc => open, + sendAdcData => '0', adcData => (others => (others => '0')) + ); + serialoutb<= serialoutb2(3 downto 0) & serialoutb1(3 downto 0); + serialinb1(7 downto 0)<=serialinb(7 downto 0); + serialinb2(7 downto 0)<=serialinb(15 downto 8); + --dispDigitC<="0000000"&txfault; +-- serialout(15 downto 8) <= "00000000"; + + --dispDigitD<=x"02"; + + sysClk125i <= not sysClk125; + reload <= reload1 and reload2 and extreload; -- active low + resetOut <= resetOut1 or resetOut2; + --sysClk125i<=debug(0); + U_clock160: entity work.clock160 port map( + CLKIN_N_IN => iMainClkN, + CLKIN_P_IN => iMainClkP, + RST_IN => sysRst125, + CLKFX_OUT => mainClk, + CLKIN_IBUFGDS_OUT => clkin, + CLK0_OUT => clk0, + LOCKED_OUT => open); + + process(mainClk) + begin + if(mainClk'event and mainClk='1') then + halfclock<= not halfclock; + end if; + end process; + process(halfclock) + begin + if(halfclock'event and halfclock='1') then + quarterclock<= not quarterclock; + end if; + end process; + --cdata(7 downto 0)<=serialinb(7 downto 0); + --cdata(31 downto 8) <=(others=>'0'); + --ctrig(0)<='0'; + --chipscope : ila + --port map ( + --CONTROL => ccontrol, + --CLK => mainClk, + --DATA => cdata, + --TRIG0 => ctrig); + --chipscopeicon : icon + --port map ( + --CONTROL0 => ccontrol); + U_idelctrlclk: entity work.clock200 port map( + CLKIN_IN => mainClk, + RST_IN => holdrst, + CLKFX_OUT => clockidctrl, + CLK0_OUT => open, + LOCKED_OUT => lockedid); + U_idelayctrl: IDELAYCTRL port map( + RDY => open, + REFCLK => clockidctrl, + RST => idctrlrst); + + process(sysRst125, sysClk125) -- clock interface + begin + if (sysRst125='1') then + holdctr<=(others=>'1'); + holdrst<='1'; + elsif(sysClk125'event and sysClk125='1') then + if (holdctr(24)='0') then + holdrst<='0'; + end if; + holdctr<=unsigned(holdctr)-1; + end if; + end process; + + process(sysClk125, sysRst125) -- reset logic for IDELAYCTRL + begin + if(sysRst125='1') then + idctrlrst<='0'; + idcounter<="000"; + oldlockedid<='0'; + elsif(sysClk125'event and sysClk125='1') then + if(lockedid='1' and oldlockedid='0')then + idcounter<="111"; + idctrlrst<='1'; + elsif(unsigned(idcounter)>0)then + idcounter<=unsigned(idcounter)-1; + else + idctrlrst<='0'; + end if; + oldlockedid<=lockedid; + end if; + end process; + + +end HsioStave0; diff --git a/rce/fw-hsio/projects/HsioStave0/images/.gitignore b/rce/fw-hsio/projects/HsioStave0/images/.gitignore new file mode 100644 index 00000000..d6b7ef32 --- /dev/null +++ b/rce/fw-hsio/projects/HsioStave0/images/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/rce/fw-hsio/projects/IBLcableTester/Makefile b/rce/fw-hsio/projects/IBLcableTester/Makefile new file mode 100644 index 00000000..5c82cd85 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/Makefile @@ -0,0 +1,12 @@ +# Project Name +export PROJECT = $(notdir $(PWD)) + +# List of build core directories. Relative to current directory. +CORE_DIRS = coregen ../../modules/pgp/coregen ../../modules/pgp2/coregen ../../modules/pixelcore/coregen + +# Optional ELF file to include. Relative to ./boot directory +#BOOT_ELF = udiTest.elf + +# Use top level makefile +include ../../system.mk + diff --git a/rce/fw-hsio/projects/IBLcableTester/Readme.txt b/rce/fw-hsio/projects/IBLcableTester/Readme.txt new file mode 100644 index 00000000..c0ba752b --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/Readme.txt @@ -0,0 +1,59 @@ +This is a DPM project specific Readme.txt file. + +The files in this directory are used to build +the DPM project in this directory. The project +name matches the name of the directory in which +this file is found. + +The Makefile in this directory may be used to build +this project with a simple 'gmake' command. + +The Version.vhd file in this directory is used to +generate the software readable version constant +in the build and is also used to set the name of +the files added to the images directory. + +The following sub directories exist in this project: + +boot: + This directory contains boot loader files which are + used to program the boot loader code in the DPM. The + files in this directory include: + +config: + This directory contains Xilinx configuration files for + various steps in the synthesis process. The files in this + directory include: + + bitgen_options.txt: Options for bitgen + map_options.txt: Options for map + ngdbuild_options.txt: Options for ngdbuild + par_options.txt: Options for par + trce_options.txt: Options for trce + xst_options.txt: Options for xst + sources.txt Source file list used by xst + +coregen: + This directory holds the coregen project and any modules + generated by coregen that are specific to this project. + +debug: + This directory holds any debug files for the project. + +hdl: + This directory contains the source files (.vhd and .v) for + the project and the constraints file (.ucf) for the project. + The top level module name, its source file name and the ucf + file name should match the name of the project. + +images: + + This directory contains the result of the project compile. + The resulting .mcs and .bit files for the project are + added to this directory. The name of the copied file will + be: project_version.mcs/.bit. + +sim: + + Directory for simulation Makefile and test bench. + diff --git a/rce/fw-hsio/projects/IBLcableTester/Version.vhd b/rce/fw-hsio/projects/IBLcableTester/Version.vhd new file mode 100644 index 00000000..449ef270 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/Version.vhd @@ -0,0 +1,26 @@ +------------------------------------------------------------------------------- +-- Title : Version Constant File +-- Project : HSIO +------------------------------------------------------------------------------- +-- File : Version.vhd +-- Author : Martin Kocian, kocian@slac.stanford.edu +-- Created : 01/07/2013 +------------------------------------------------------------------------------- +-- Description: +-- Version Constant Module +------------------------------------------------------------------------------- +-- Copyright (c) 2012 by SLAC. All rights reserved. +------------------------------------------------------------------------------- +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; + +package Version is + +constant FpgaVersion : std_logic_vector(31 downto 0) := x"00000001"; -- MAKE_VERSION + +end Version; + +------------------------------------------------------------------------------- +-- Revision History: +-- 01/07/2013 (0x00000001): Initial XST version +------------------------------------------------------------------------------- diff --git a/rce/fw-hsio/projects/IBLcableTester/config/bitgen_options.txt b/rce/fw-hsio/projects/IBLcableTester/config/bitgen_options.txt new file mode 100755 index 00000000..abf29c69 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/config/bitgen_options.txt @@ -0,0 +1,5 @@ +##----------------------------------------------------------------------------- +## Title : Xilinx bitgen options file +##----------------------------------------------------------------------------- +-intstyle silent +-w diff --git a/rce/fw-hsio/projects/IBLcableTester/config/map_options.txt b/rce/fw-hsio/projects/IBLcableTester/config/map_options.txt new file mode 100755 index 00000000..6cef41ff --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/config/map_options.txt @@ -0,0 +1,21 @@ +##----------------------------------------------------------------------------- +## Title : Xilinx map options file +##----------------------------------------------------------------------------- + +#-intstyle silent +-ol high +-xe n +-t 1 +-register_duplication on +#-global_opt off +#-equivalent_register_removal on +#-u +#-cm Area +-detail +#-ir off +#-pr off +#-lc off +#-mt 2 + + + diff --git a/rce/fw-hsio/projects/IBLcableTester/config/ngdbuild_options.txt b/rce/fw-hsio/projects/IBLcableTester/config/ngdbuild_options.txt new file mode 100755 index 00000000..95ca0eea --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/config/ngdbuild_options.txt @@ -0,0 +1,5 @@ +##----------------------------------------------------------------------------- +## Title : Xilinx ngdbuild options file +##----------------------------------------------------------------------------- +-nt timestamp + diff --git a/rce/fw-hsio/projects/IBLcableTester/config/par_options.txt b/rce/fw-hsio/projects/IBLcableTester/config/par_options.txt new file mode 100755 index 00000000..2cdd3ad0 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/config/par_options.txt @@ -0,0 +1,9 @@ +##----------------------------------------------------------------------------- +## Title : Xilinx place and route options file +##----------------------------------------------------------------------------- +#-intstyle ise +-ol high +-xe n +#-mt 4 + + diff --git a/rce/fw-hsio/projects/IBLcableTester/config/promgen_options.txt b/rce/fw-hsio/projects/IBLcableTester/config/promgen_options.txt new file mode 100755 index 00000000..2c2257be --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/config/promgen_options.txt @@ -0,0 +1,7 @@ +##----------------------------------------------------------------------------- +## Title : Xilinx promgen options file +##----------------------------------------------------------------------------- +-x xcf32p +-w +-p mcs +-c FF diff --git a/rce/fw-hsio/projects/IBLcableTester/config/sources.txt b/rce/fw-hsio/projects/IBLcableTester/config/sources.txt new file mode 100644 index 00000000..f8a33f5d --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/config/sources.txt @@ -0,0 +1,40 @@ +# Version Constant +vhdl work "_PROJ_DIR_/Version.vhd" + +# PGP + +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpVersion.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpAckRx.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpCellRx.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpCellTx.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpMgtWrap.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpPhy.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpRxTrack.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpTxSched.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpTop.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpClkGen.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpCmdSlave.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpRegSlave.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpPicRemBuff.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpDataBuffer.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpFrontEnd.vhd" +vhdl work "_PROJ_DIR_/../../modules/pgp/hdl/PgpDsBuff.vhd" + +# Pixel core +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/DisplayCharacters.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/DisplayControl.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/clock160.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/clock200.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/syncdatac.vhd" +vhdl work "_PROJ_DIR_/../../modules/pixelcore/hdl/phaseshift.vhd" + + +# Local Files +vhdl work "_PROJ_DIR_/hdl/serbiphase.vhd" +vhdl work "_PROJ_DIR_/hdl/deser16.vhd" +vhdl work "_PROJ_DIR_/hdl/pattern_mem.vhd" +vhdl work "_PROJ_DIR_/hdl/pattern_cmd.vhd" +vhdl work "_PROJ_DIR_/hdl/ser.vhd" +vhdl work "_PROJ_DIR_/hdl/deser.vhd" +vhdl work "_PROJ_DIR_/hdl/IBLcableTesterCore.vhd" +vhdl work "_PROJ_DIR_/hdl/IBLcableTester.vhd" diff --git a/rce/fw-hsio/projects/IBLcableTester/config/trce_options.txt b/rce/fw-hsio/projects/IBLcableTester/config/trce_options.txt new file mode 100755 index 00000000..2656ff46 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/config/trce_options.txt @@ -0,0 +1,7 @@ +##----------------------------------------------------------------------------- +## Title : Xilinx trace options file +##----------------------------------------------------------------------------- +-intstyle silent +-l 30 +-v 30 +-tsi DpmTest.tsi diff --git a/rce/fw-hsio/projects/IBLcableTester/config/xst_options.txt b/rce/fw-hsio/projects/IBLcableTester/config/xst_options.txt new file mode 100644 index 00000000..65969499 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/config/xst_options.txt @@ -0,0 +1,50 @@ +run +-ofn IBLcableTester +-top IBLcableTester +-p XC4VFX60-11-FF1152 +-ifn "sources.txt" +-opt_mode Speed +-opt_level 2 +-power NO +-iuc NO +-keep_hierarchy No +-netlist_hierarchy As_Optimized +-rtlview Yes +-glob_opt AllClockNets +-write_timing_constraints No +-cross_clock_analysis NO +-hierarchy_separator / +-bus_delimiter <> +-case Maintain +-slice_utilization_ratio 100 +-bram_utilization_ratio 100 +-dsp_utilization_ratio 100 +-verilog2001 YES +-fsm_extract YES -fsm_encoding Auto +-safe_implementation No +-fsm_style LUT +-ram_extract Yes +-ram_style Auto +-rom_extract Yes +-mux_style Auto +-decoder_extract YES +-priority_extract Yes +-shreg_extract YES +-shift_extract YES +-xor_collapse YES +-resource_sharing Yes +-use_dsp48 Auto +-async_to_sync No +-iobuf Yes +-max_fanout 100000 +-bufg 32 +-register_duplication YES +-equivalent_register_removal Yes +-register_balancing No +-iob Auto +-slice_packing YES +-use_clock_enable Auto +-use_sync_set Auto +-use_sync_reset Auto +-optimize_primitives No + diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/counter30.xco b/rce/fw-hsio/projects/IBLcableTester/coregen/counter30.xco new file mode 100644 index 00000000..68de958d --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/counter30.xco @@ -0,0 +1,64 @@ +############################################################## +# +# Xilinx Core Generator version K.39 +# Date: Wed Sep 9 21:20:06 2009 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# BEGIN Project Options +SET addpads = False +SET asysymbol = False +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = False +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = False +SET foundationsym = False +SET implementationfiletype = Ngc +SET package = ff1152 +SET removerpms = False +SET simulationfiles = Behavioral +SET speedgrade = -10 +SET verilogsim = False +SET vhdlsim = True +# END Project Options +# BEGIN Select +SELECT Binary_Counter family Xilinx,_Inc. 8.0 +# END Select +# BEGIN Parameters +CSET aclr=true +CSET ainit=false +CSET ainit_value=0 +CSET aset=false +CSET async_threshold_output=false +CSET ce=true +CSET component_name=counter30 +CSET count_mode=UP +CSET cycle_early_threshold_output=false +CSET final_count_value=1 +CSET increment_value=1 +CSET load=false +CSET load_ce_priority=CE_Overrides_Load +CSET output_width=30 +CSET restrict_count=false +CSET sclr=false +CSET sinit=false +CSET sinit_value=0 +CSET sset=false +CSET sync_ce_priority=Sync_Overrides_CE +CSET sync_threshold_output=true +CSET syncctrlpriority=Reset_Overrides_Set +CSET threshold_value=3ffffffe +# END Parameters +GENERATE +# CRC: d766a50a + diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/counter30_c_counter_binary_v8_0_xst_1.ngc_xst.xrpt b/rce/fw-hsio/projects/IBLcableTester/coregen/counter30_c_counter_binary_v8_0_xst_1.ngc_xst.xrpt new file mode 100644 index 00000000..85312325 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/counter30_c_counter_binary_v8_0_xst_1.ngc_xst.xrpt @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<document OS="lin" product="ISE" version="10.1.03"> + + <!--The data in this file is primarily intended for consumption by Xilinx tools. + The structure and the elements are likely to change over the next few releases. + This means code written to parse this file will need to be revisited each subsequent release.--> + + <application stringID="Xst" timeStamp="Wed Sep 9 14:19:27 2009"> + <section stringID="XST_HDL_SYNTHESIS_REPORT"> + <item dataType="int" stringID="XST_REGISTERS" value="2"> + <item dataType="int" stringID="XST_1BIT_REGISTER" value="1"/> + <item dataType="int" stringID="XST_30BIT_REGISTER" value="1"/> + </item> + </section> + <section stringID="XST_ADVANCED_HDL_SYNTHESIS_REPORT"> + <item dataType="int" stringID="XST_REGISTERS" value="31"> + <item dataType="int" stringID="XST_FLIPFLOPS" value="31"/> + </item> + </section> + <section stringID="XST_FINAL_REGISTER_REPORT"> + <item dataType="int" stringID="XST_REGISTERS" value="31"> + <item dataType="int" stringID="XST_FLIPFLOPS" value="31"/> + </item> + </section> + <section stringID="XST_PARTITION_REPORT"> + <section stringID="XST_PARTITION_IMPLEMENTATION_STATUS"> + <section stringID="XST_NO_PARTITIONS_WERE_FOUND_IN_THIS_DESIGN"/> + </section> + </section> + <section stringID="XST_FINAL_REPORT"> + <section stringID="XST_FINAL_RESULTS"> + <item stringID="XST_TOP_LEVEL_OUTPUT_FILE_NAME" value="/afs/slac/u/ec/kocian/minilat/xilinx/xil_cores/tmp/_cg/counter30_c_counter_binary_v8_0_xst_1.ngc"/> + <item stringID="XST_OUTPUT_FORMAT" value="NGC"/> + <item stringID="XST_OPTIMIZATION_GOAL" value="SPEED"/> + <item stringID="XST_KEEP_HIERARCHY" value="no"/> + </section> + <section stringID="XST_DESIGN_STATISTICS"> + <item stringID="XST_IOS" value="104"/> + </section> + <section stringID="XST_CELL_USAGE"> + <item dataType="int" stringID="XST_BELS" value="107"> + <item dataType="int" stringID="XST_GND" value="1"/> + <item dataType="int" stringID="XST_INV" value="1"/> + <item dataType="int" stringID="XST_LUT1" value="29"/> + <item dataType="int" stringID="XST_LUT2" value="1"/> + <item dataType="int" stringID="XST_LUT4" value="7"/> + <item dataType="int" stringID="XST_MUXCY" value="37"/> + <item dataType="int" stringID="XST_VCC" value="1"/> + <item dataType="int" stringID="XST_XORCY" value="30"/> + </item> + <item dataType="int" stringID="XST_FLIPFLOPSLATCHES" value="31"> + <item dataType="int" stringID="XST_FDCE" value="31"/> + </item> + </section> + </section> + <section stringID="XST_DEVICE_UTILIZATION_SUMMARY"> + <item stringID="XST_SELECTED_DEVICE" value="4vfx60ff672-12"/> + <item AVAILABLE="25280" dataType="int" stringID="XST_NUMBER_OF_SLICES" value="20"/> + <item AVAILABLE="50560" dataType="int" stringID="XST_NUMBER_OF_SLICE_FLIP_FLOPS" value="31"/> + <item AVAILABLE="50560" dataType="int" stringID="XST_NUMBER_OF_4_INPUT_LUTS" value="38"/> + <item dataType="int" stringID="XST_NUMBER_OF_IOS" value="104"/> + <item AVAILABLE="352" dataType="int" stringID="XST_NUMBER_OF_BONDED_IOBS" value="0"/> + </section> + <section stringID="XST_PARTITION_RESOURCE_SUMMARY"> + <section stringID="XST_NO_PARTITIONS_WERE_FOUND_IN_THIS_DESIGN"/> + </section> + <section stringID="XST_ERRORS_STATISTICS"> + <item dataType="int" filtered="0" stringID="XST_NUMBER_OF_ERRORS" value="0"/> + <item dataType="int" filtered="0" stringID="XST_NUMBER_OF_WARNINGS" value="87"/> + <item dataType="int" filtered="0" stringID="XST_NUMBER_OF_INFOS" value="2"/> + </section> + </application> + +</document> diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/counter30_xmdf.tcl b/rce/fw-hsio/projects/IBLcableTester/coregen/counter30_xmdf.tcl new file mode 100644 index 00000000..3717db15 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/counter30_xmdf.tcl @@ -0,0 +1,68 @@ +# The package naming convention is <core_name>_xmdf +package provide counter30_xmdf 1.0 + +# This includes some utilities that support common XMDF operations +package require utilities_xmdf + +# Define a namespace for this package. The name of the name space +# is <core_name>_xmdf +namespace eval ::counter30_xmdf { +# Use this to define any statics +} + +# Function called by client to rebuild the params and port arrays +# Optional when the use context does not require the param or ports +# arrays to be available. +proc ::counter30_xmdf::xmdfInit { instance } { +# Variable containg name of library into which module is compiled +# Recommendation: <module_name> +# Required +utilities_xmdf::xmdfSetData $instance Module Attributes Name counter30 +} +# ::counter30_xmdf::xmdfInit + +# Function called by client to fill in all the xmdf* data variables +# based on the current settings of the parameters +proc ::counter30_xmdf::xmdfApplyParams { instance } { + +set fcount 0 +# Array containing libraries that are assumed to exist +# Examples include unisim and xilinxcorelib +# Optional +# In this example, we assume that the unisim library will +# be magically +# available to the simulation and synthesis tool +utilities_xmdf::xmdfSetData $instance FileSet $fcount type logical_library +utilities_xmdf::xmdfSetData $instance FileSet $fcount logical_library unisim +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path counter30.ngc +utilities_xmdf::xmdfSetData $instance FileSet $fcount type ngc +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path counter30.vhd +utilities_xmdf::xmdfSetData $instance FileSet $fcount type vhdl +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path counter30.vho +utilities_xmdf::xmdfSetData $instance FileSet $fcount type vhdl_template +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path counter30.xco +utilities_xmdf::xmdfSetData $instance FileSet $fcount type coregen_ip +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path counter30_c_counter_binary_v8_0_xst_1.ngc_xst.xrpt +utilities_xmdf::xmdfSetData $instance FileSet $fcount type AnyView +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path counter30_xmdf.tcl +utilities_xmdf::xmdfSetData $instance FileSet $fcount type AnyView +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount associated_module counter30 +incr fcount + +} + +# ::gen_comp_name_xmdf::xmdfApplyParams diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo.xco b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo.xco new file mode 100644 index 00000000..0d9adf03 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo.xco @@ -0,0 +1,217 @@ +############################################################## +# +# Xilinx Core Generator version 13.2 +# Date: Thu Oct 6 00:36:33 2011 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# Generated from component: xilinx.com:ip:fifo_generator:8.2 +# +############################################################## +# +# BEGIN Project Options +SET addpads = false +SET asysymbol = false +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = false +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = false +SET foundationsym = false +SET implementationfiletype = Ngc +SET package = ff1152 +SET removerpms = false +SET simulationfiles = Behavioral +SET speedgrade = -10 +SET verilogsim = false +SET vhdlsim = true +# END Project Options +# BEGIN Select +SELECT Fifo_Generator xilinx.com:ip:fifo_generator:8.2 +# END Select +# BEGIN Parameters +CSET add_ngc_constraint_axi=false +CSET almost_empty_flag=false +CSET almost_full_flag=false +CSET aruser_width=1 +CSET awuser_width=1 +CSET axi_address_width=32 +CSET axi_data_width=64 +CSET axi_type=AXI4_Stream +CSET axis_type=FIFO +CSET buser_width=1 +CSET clock_enable_type=Slave_Interface_Clock_Enable +CSET clock_type_axi=Common_Clock +CSET component_name=iblfifo +CSET data_count=false +CSET data_count_width=9 +CSET disable_timing_violations=false +CSET disable_timing_violations_axi=false +CSET dout_reset_value=0 +CSET empty_threshold_assert_value=19 +CSET empty_threshold_assert_value_axis=1022 +CSET empty_threshold_assert_value_rach=1022 +CSET empty_threshold_assert_value_rdch=1022 +CSET empty_threshold_assert_value_wach=1022 +CSET empty_threshold_assert_value_wdch=1022 +CSET empty_threshold_assert_value_wrch=1022 +CSET empty_threshold_negate_value=20 +CSET enable_aruser=false +CSET enable_awuser=false +CSET enable_buser=false +CSET enable_common_overflow=false +CSET enable_common_underflow=false +CSET enable_data_counts_axis=false +CSET enable_data_counts_rach=false +CSET enable_data_counts_rdch=false +CSET enable_data_counts_wach=false +CSET enable_data_counts_wdch=false +CSET enable_data_counts_wrch=false +CSET enable_ecc=false +CSET enable_ecc_axis=false +CSET enable_ecc_rach=false +CSET enable_ecc_rdch=false +CSET enable_ecc_wach=false +CSET enable_ecc_wdch=false +CSET enable_ecc_wrch=false +CSET enable_handshake_flag_options_axis=false +CSET enable_handshake_flag_options_rach=false +CSET enable_handshake_flag_options_rdch=false +CSET enable_handshake_flag_options_wach=false +CSET enable_handshake_flag_options_wdch=false +CSET enable_handshake_flag_options_wrch=false +CSET enable_read_channel=false +CSET enable_read_pointer_increment_by2=false +CSET enable_reset_synchronization=true +CSET enable_ruser=false +CSET enable_tdata=false +CSET enable_tdest=false +CSET enable_tid=false +CSET enable_tkeep=false +CSET enable_tlast=false +CSET enable_tready=true +CSET enable_tstrobe=false +CSET enable_tuser=false +CSET enable_write_channel=false +CSET enable_wuser=false +CSET fifo_application_type_axis=Data_FIFO +CSET fifo_application_type_rach=Data_FIFO +CSET fifo_application_type_rdch=Data_FIFO +CSET fifo_application_type_wach=Data_FIFO +CSET fifo_application_type_wdch=Data_FIFO +CSET fifo_application_type_wrch=Data_FIFO +CSET fifo_implementation=Independent_Clocks_Builtin_FIFO +CSET fifo_implementation_axis=Common_Clock_Block_RAM +CSET fifo_implementation_rach=Common_Clock_Block_RAM +CSET fifo_implementation_rdch=Common_Clock_Block_RAM +CSET fifo_implementation_wach=Common_Clock_Block_RAM +CSET fifo_implementation_wdch=Common_Clock_Block_RAM +CSET fifo_implementation_wrch=Common_Clock_Block_RAM +CSET full_flags_reset_value=0 +CSET full_threshold_assert_value=523 +CSET full_threshold_assert_value_axis=1023 +CSET full_threshold_assert_value_rach=1023 +CSET full_threshold_assert_value_rdch=1023 +CSET full_threshold_assert_value_wach=1023 +CSET full_threshold_assert_value_wdch=1023 +CSET full_threshold_assert_value_wrch=1023 +CSET full_threshold_negate_value=522 +CSET id_width=4 +CSET inject_dbit_error=false +CSET inject_dbit_error_axis=false +CSET inject_dbit_error_rach=false +CSET inject_dbit_error_rdch=false +CSET inject_dbit_error_wach=false +CSET inject_dbit_error_wdch=false +CSET inject_dbit_error_wrch=false +CSET inject_sbit_error=false +CSET inject_sbit_error_axis=false +CSET inject_sbit_error_rach=false +CSET inject_sbit_error_rdch=false +CSET inject_sbit_error_wach=false +CSET inject_sbit_error_wdch=false +CSET inject_sbit_error_wrch=false +CSET input_data_width=36 +CSET input_depth=512 +CSET input_depth_axis=1024 +CSET input_depth_rach=16 +CSET input_depth_rdch=1024 +CSET input_depth_wach=16 +CSET input_depth_wdch=1024 +CSET input_depth_wrch=16 +CSET interface_type=Native +CSET output_data_width=36 +CSET output_depth=512 +CSET overflow_flag=false +CSET overflow_flag_axi=false +CSET overflow_sense=Active_High +CSET overflow_sense_axi=Active_High +CSET performance_options=Standard_FIFO +CSET programmable_empty_type=No_Programmable_Empty_Threshold +CSET programmable_empty_type_axis=Empty +CSET programmable_empty_type_rach=Empty +CSET programmable_empty_type_rdch=Empty +CSET programmable_empty_type_wach=Empty +CSET programmable_empty_type_wdch=Empty +CSET programmable_empty_type_wrch=Empty +CSET programmable_full_type=No_Programmable_Full_Threshold +CSET programmable_full_type_axis=Full +CSET programmable_full_type_rach=Full +CSET programmable_full_type_rdch=Full +CSET programmable_full_type_wach=Full +CSET programmable_full_type_wdch=Full +CSET programmable_full_type_wrch=Full +CSET rach_type=FIFO +CSET rdch_type=FIFO +CSET read_clock_frequency=160 +CSET read_data_count=false +CSET read_data_count_width=9 +CSET register_slice_mode_axis=Fully_Registered +CSET register_slice_mode_rach=Fully_Registered +CSET register_slice_mode_rdch=Fully_Registered +CSET register_slice_mode_wach=Fully_Registered +CSET register_slice_mode_wdch=Fully_Registered +CSET register_slice_mode_wrch=Fully_Registered +CSET reset_pin=true +CSET reset_type=Asynchronous_Reset +CSET ruser_width=1 +CSET tdata_width=64 +CSET tdest_width=4 +CSET tid_width=8 +CSET tkeep_width=4 +CSET tstrb_width=4 +CSET tuser_width=4 +CSET underflow_flag=false +CSET underflow_flag_axi=false +CSET underflow_sense=Active_High +CSET underflow_sense_axi=Active_High +CSET use_clock_enable=false +CSET use_dout_reset=false +CSET use_embedded_registers=false +CSET use_extra_logic=false +CSET valid_flag=false +CSET valid_sense=Active_High +CSET wach_type=FIFO +CSET wdch_type=FIFO +CSET wrch_type=FIFO +CSET write_acknowledge_flag=false +CSET write_acknowledge_sense=Active_High +CSET write_clock_frequency=160 +CSET write_data_count=false +CSET write_data_count_width=9 +CSET wuser_width=1 +# END Parameters +# BEGIN Extra information +MISC pkg_timestamp=2011-03-14T07:12:32.000Z +# END Extra information +GENERATE +# CRC: 1619f87d diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_fifo_generator_v4_4_xst_1.ngc_xst.xrpt b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_fifo_generator_v4_4_xst_1.ngc_xst.xrpt new file mode 100644 index 00000000..cedd25e8 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_fifo_generator_v4_4_xst_1.ngc_xst.xrpt @@ -0,0 +1,101 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<document OS="lin" product="ISE" version="10.1.03"> + + <!--The data in this file is primarily intended for consumption by Xilinx tools. + The structure and the elements are likely to change over the next few releases. + This means code written to parse this file will need to be revisited each subsequent release.--> + + <application stringID="Xst" timeStamp="Sat Aug 22 13:49:02 2009"> + <section stringID="XST_HDL_SYNTHESIS_REPORT"> + <item dataType="int" stringID="XST_RAMS" value="1"></item> + <item dataType="int" stringID="XST_COUNTERS" value="2"> + <item dataType="int" stringID="XST_4BIT_UP_COUNTER" value="2"/> + </item> + <item dataType="int" stringID="XST_REGISTERS" value="38"> + <item dataType="int" stringID="XST_1BIT_REGISTER" value="23"/> + <item dataType="int" stringID="XST_2BIT_REGISTER" value="1"/> + <item dataType="int" stringID="XST_3BIT_REGISTER" value="1"/> + <item dataType="int" stringID="XST_36BIT_REGISTER" value="1"/> + <item dataType="int" stringID="XST_4BIT_REGISTER" value="12"/> + </item> + <item dataType="int" stringID="XST_XORS" value="32"> + <item dataType="int" stringID="XST_1BIT_XOR2" value="32"/> + </item> + </section> + <section stringID="XST_ADVANCED_HDL_SYNTHESIS_REPORT"> + <item dataType="int" stringID="XST_RAMS" value="1"></item> + <item dataType="int" stringID="XST_COUNTERS" value="2"> + <item dataType="int" stringID="XST_4BIT_UP_COUNTER" value="2"/> + </item> + <item dataType="int" stringID="XST_REGISTERS" value="112"> + <item dataType="int" stringID="XST_FLIPFLOPS" value="112"/> + </item> + <item dataType="int" stringID="XST_XORS" value="32"> + <item dataType="int" stringID="XST_1BIT_XOR2" value="32"/> + </item> + </section> + <section stringID="XST_FINAL_REGISTER_REPORT"> + <item dataType="int" stringID="XST_REGISTERS" value="115"> + <item dataType="int" stringID="XST_FLIPFLOPS" value="115"/> + </item> + </section> + <section stringID="XST_PARTITION_REPORT"> + <section stringID="XST_PARTITION_IMPLEMENTATION_STATUS"> + <section stringID="XST_NO_PARTITIONS_WERE_FOUND_IN_THIS_DESIGN"/> + </section> + </section> + <section stringID="XST_FINAL_REPORT"> + <section stringID="XST_FINAL_RESULTS"> + <item stringID="XST_TOP_LEVEL_OUTPUT_FILE_NAME" value="/afs/slac/u/ec/kocian/minilat/xilinx/BnlAsic/xil_cores/tmp/_cg/iblfifo_fifo_generator_v4_4_xst_1.ngc"/> + <item stringID="XST_OUTPUT_FORMAT" value="NGC"/> + <item stringID="XST_OPTIMIZATION_GOAL" value="SPEED"/> + <item stringID="XST_KEEP_HIERARCHY" value="no"/> + </section> + <section stringID="XST_DESIGN_STATISTICS"> + <item stringID="XST_IOS" value="177"/> + </section> + <section stringID="XST_CELL_USAGE"> + <item dataType="int" stringID="XST_BELS" value="51"> + <item dataType="int" stringID="XST_GND" value="1"/> + <item dataType="int" stringID="XST_INV" value="3"/> + <item dataType="int" stringID="XST_LUT2" value="22"/> + <item dataType="int" stringID="XST_LUT3" value="5"/> + <item dataType="int" stringID="XST_LUT3L" value="1"/> + <item dataType="int" stringID="XST_LUT4" value="16"/> + <item dataType="int" stringID="XST_LUT4D" value="1"/> + <item dataType="int" stringID="XST_LUT4L" value="2"/> + </item> + <item dataType="int" stringID="XST_FLIPFLOPSLATCHES" value="115"> + <item dataType="int" stringID="XST_FD" value="4"/> + <item dataType="int" stringID="XST_FDC" value="35"/> + <item dataType="int" stringID="XST_FDCE" value="19"/> + <item dataType="int" stringID="XST_FDE" value="36"/> + <item dataType="int" stringID="XST_FDP" value="11"/> + <item dataType="int" stringID="XST_FDPE" value="10"/> + </item> + <item dataType="int" stringID="XST_RAMS" value="37"> + <item dataType="int" stringID="XST_RAM16X1D" value="36"/> + </item> + </section> + </section> + <section stringID="XST_DEVICE_UTILIZATION_SUMMARY"> + <item stringID="XST_SELECTED_DEVICE" value="4vfx60ff672-12"/> + <item AVAILABLE="25280" dataType="int" stringID="XST_NUMBER_OF_SLICES" value="123"/> + <item AVAILABLE="50560" dataType="int" stringID="XST_NUMBER_OF_SLICE_FLIP_FLOPS" value="115"/> + <item AVAILABLE="50560" dataType="int" stringID="XST_NUMBER_OF_4_INPUT_LUTS" value="122"/> + <item dataType="int" stringID="XST_NUMBER_USED_AS_LOGIC" value="50"/> + <item dataType="int" stringID="XST_NUMBER_USED_AS_RAMS" value="72"/> + <item dataType="int" stringID="XST_NUMBER_OF_IOS" value="177"/> + <item AVAILABLE="352" dataType="int" stringID="XST_NUMBER_OF_BONDED_IOBS" value="0"/> + </section> + <section stringID="XST_PARTITION_RESOURCE_SUMMARY"> + <section stringID="XST_NO_PARTITIONS_WERE_FOUND_IN_THIS_DESIGN"/> + </section> + <section stringID="XST_ERRORS_STATISTICS"> + <item dataType="int" filtered="0" stringID="XST_NUMBER_OF_ERRORS" value="0"/> + <item dataType="int" filtered="0" stringID="XST_NUMBER_OF_WARNINGS" value="158"/> + <item dataType="int" filtered="0" stringID="XST_NUMBER_OF_INFOS" value="5"/> + </section> + </application> + +</document> diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/example_design/iblfifo_top.ucf b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/example_design/iblfifo_top.ucf new file mode 100755 index 00000000..33471d1c --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/example_design/iblfifo_top.ucf @@ -0,0 +1,59 @@ +################################################################################ +# (c) Copyright 2009 - 2010 Xilinx, Inc. All rights reserved. +# +# This file contains confidential and proprietary information +# of Xilinx, Inc. and is protected under U.S. and +# international copyright and other intellectual property +# laws. +# +# DISCLAIMER +# This disclaimer is not a license and does not grant any +# rights to the materials distributed herewith. Except as +# otherwise provided in a valid license issued to you by +# Xilinx, and to the maximum extent permitted by applicable +# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND +# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES +# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING +# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- +# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and +# (2) Xilinx shall not be liable (whether in contract or tort, +# including negligence, or under any other theory of +# liability) for any loss or damage of any kind or nature +# related to, arising under or in connection with these +# materials, including for any direct, or any indirect, +# special, incidental, or consequential loss or damage +# (including loss of data, profits, goodwill, or any type of +# loss or damage suffered as a result of any action brought +# by a third party) even if such damage or loss was +# reasonably foreseeable or Xilinx had been advised of the +# possibility of the same. +# +# CRITICAL APPLICATIONS +# Xilinx products are not designed or intended to be fail- +# safe, or for use in any application requiring fail-safe +# performance, such as life-support or safety devices or +# systems, Class III medical devices, nuclear facilities, +# applications related to the deployment of airbags, or any +# other applications that could lead to death, personal +# injury, or severe property or environmental damage +# (individually and collectively, "Critical +# Applications"). Customer assumes the sole risk and +# liability of any use of Xilinx products in Critical +# Applications, subject only to applicable laws and +# regulations governing limitations on product liability. +# +# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS +# PART OF THIS FILE AT ALL TIMES. +# +################################################################################ + +# Core Period Constraint. This constraint can be modified, and is +# valid as long as it is met after place and route. + NET "RD_CLK" TNM_NET = "RD_CLK"; + NET "WR_CLK" TNM_NET = "WR_CLK"; + TIMESPEC "TS_RD_CLK" = PERIOD "RD_CLK" 50 MHZ; + TIMESPEC "TS_WR_CLK" = PERIOD "WR_CLK" 50 MHZ; + + + +################################################################################ diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/example_design/iblfifo_top.vhd b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/example_design/iblfifo_top.vhd new file mode 100755 index 00000000..3062b60e --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/example_design/iblfifo_top.vhd @@ -0,0 +1,358 @@ +-------------------------------------------------------------------------------- +-- +-- FIFO Generator v8.2 Core - Top-level core wrapper +-- +-------------------------------------------------------------------------------- +-- +-- (c) Copyright 2009 - 2010 Xilinx, Inc. All rights reserved. +-- +-- This file contains confidential and proprietary information +-- of Xilinx, Inc. and is protected under U.S. and +-- international copyright and other intellectual property +-- laws. +-- +-- DISCLAIMER +-- This disclaimer is not a license and does not grant any +-- rights to the materials distributed herewith. Except as +-- otherwise provided in a valid license issued to you by +-- Xilinx, and to the maximum extent permitted by applicable +-- law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND +-- WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES +-- AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING +-- BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- +-- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and +-- (2) Xilinx shall not be liable (whether in contract or tort, +-- including negligence, or under any other theory of +-- liability) for any loss or damage of any kind or nature +-- related to, arising under or in connection with these +-- materials, including for any direct, or any indirect, +-- special, incidental, or consequential loss or damage +-- (including loss of data, profits, goodwill, or any type of +-- loss or damage suffered as a result of any action brought +-- by a third party) even if such damage or loss was +-- reasonably foreseeable or Xilinx had been advised of the +-- possibility of the same. +-- +-- CRITICAL APPLICATIONS +-- Xilinx products are not designed or intended to be fail- +-- safe, or for use in any application requiring fail-safe +-- performance, such as life-support or safety devices or +-- systems, Class III medical devices, nuclear facilities, +-- applications related to the deployment of airbags, or any +-- other applications that could lead to death, personal +-- injury, or severe property or environmental damage +-- (individually and collectively, "Critical +-- Applications"). Customer assumes the sole risk and +-- liability of any use of Xilinx products in Critical +-- Applications, subject only to applicable laws and +-- regulations governing limitations on product liability. +-- +-- THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS +-- PART OF THIS FILE AT ALL TIMES. +-------------------------------------------------------------------------------- +-- +-- Filename: <componenet name>_top.vhd +-- +-- Description: +-- This is the actual FIFO core wrapper. +-- +-------------------------------------------------------------------------------- +-- Library Declarations +-------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +library unisim; +use unisim.vcomponents.all; + +-------------------------------------------------------------------------------- +-- Entity Declaration +-------------------------------------------------------------------------------- +entity iblfifo_top is + PORT ( + CLK : IN STD_LOGIC; + BACKUP : IN STD_LOGIC; + BACKUP_MARKER : IN STD_LOGIC; + DIN : IN STD_LOGIC_VECTOR(36-1 downto 0); + PROG_EMPTY_THRESH : IN STD_LOGIC_VECTOR(9-1 downto 0); + PROG_EMPTY_THRESH_ASSERT : IN STD_LOGIC_VECTOR(9-1 downto 0); + PROG_EMPTY_THRESH_NEGATE : IN STD_LOGIC_VECTOR(9-1 downto 0); + PROG_FULL_THRESH : IN STD_LOGIC_VECTOR(9-1 downto 0); + PROG_FULL_THRESH_ASSERT : IN STD_LOGIC_VECTOR(9-1 downto 0); + PROG_FULL_THRESH_NEGATE : IN STD_LOGIC_VECTOR(9-1 downto 0); + RD_CLK : IN STD_LOGIC; + RD_EN : IN STD_LOGIC; + RD_RST : IN STD_LOGIC; + RST : IN STD_LOGIC; + SRST : IN STD_LOGIC; + WR_CLK : IN STD_LOGIC; + WR_EN : IN STD_LOGIC; + WR_RST : IN STD_LOGIC; + INJECTDBITERR : IN STD_LOGIC; + INJECTSBITERR : IN STD_LOGIC; + ALMOST_EMPTY : OUT STD_LOGIC; + ALMOST_FULL : OUT STD_LOGIC; + DATA_COUNT : OUT STD_LOGIC_VECTOR(9-1 downto 0); + DOUT : OUT STD_LOGIC_VECTOR(36-1 downto 0); + EMPTY : OUT STD_LOGIC; + FULL : OUT STD_LOGIC; + OVERFLOW : OUT STD_LOGIC; + PROG_EMPTY : OUT STD_LOGIC; + PROG_FULL : OUT STD_LOGIC; + VALID : OUT STD_LOGIC; + RD_DATA_COUNT : OUT STD_LOGIC_VECTOR(9-1 downto 0); + UNDERFLOW : OUT STD_LOGIC; + WR_ACK : OUT STD_LOGIC; + WR_DATA_COUNT : OUT STD_LOGIC_VECTOR(9-1 downto 0); + SBITERR : OUT STD_LOGIC; + DBITERR : OUT STD_LOGIC; + -- AXI Global Signal + M_ACLK : IN std_logic; + S_ACLK : IN std_logic; + S_ARESETN : IN std_logic; + M_ACLK_EN : IN std_logic; + S_ACLK_EN : IN std_logic; + -- AXI Full/Lite Slave Write Channel (write side) + S_AXI_AWID : IN std_logic_vector(4-1 DOWNTO 0); + S_AXI_AWADDR : IN std_logic_vector(32-1 DOWNTO 0); + S_AXI_AWLEN : IN std_logic_vector(8-1 DOWNTO 0); + S_AXI_AWSIZE : IN std_logic_vector(3-1 DOWNTO 0); + S_AXI_AWBURST : IN std_logic_vector(2-1 DOWNTO 0); + S_AXI_AWLOCK : IN std_logic_vector(2-1 DOWNTO 0); + S_AXI_AWCACHE : IN std_logic_vector(4-1 DOWNTO 0); + S_AXI_AWPROT : IN std_logic_vector(3-1 DOWNTO 0); + S_AXI_AWQOS : IN std_logic_vector(4-1 DOWNTO 0); + S_AXI_AWREGION : IN std_logic_vector(4-1 DOWNTO 0); + S_AXI_AWUSER : IN std_logic_vector(1-1 DOWNTO 0); + S_AXI_AWVALID : IN std_logic; + S_AXI_AWREADY : OUT std_logic; + S_AXI_WID : IN std_logic_vector(4-1 DOWNTO 0); + S_AXI_WDATA : IN std_logic_vector(64-1 DOWNTO 0); + S_AXI_WSTRB : IN std_logic_vector(8-1 DOWNTO 0); + S_AXI_WLAST : IN std_logic; + S_AXI_WUSER : IN std_logic_vector(1-1 DOWNTO 0); + S_AXI_WVALID : IN std_logic; + S_AXI_WREADY : OUT std_logic; + S_AXI_BID : OUT std_logic_vector(4-1 DOWNTO 0); + S_AXI_BRESP : OUT std_logic_vector(2-1 DOWNTO 0); + S_AXI_BUSER : OUT std_logic_vector(1-1 DOWNTO 0); + S_AXI_BVALID : OUT std_logic; + S_AXI_BREADY : IN std_logic; + -- AXI Full/Lite Master Write Channel (Read side) + M_AXI_AWID : OUT std_logic_vector(4-1 DOWNTO 0); + M_AXI_AWADDR : OUT std_logic_vector(32-1 DOWNTO 0); + M_AXI_AWLEN : OUT std_logic_vector(8-1 DOWNTO 0); + M_AXI_AWSIZE : OUT std_logic_vector(3-1 DOWNTO 0); + M_AXI_AWBURST : OUT std_logic_vector(2-1 DOWNTO 0); + M_AXI_AWLOCK : OUT std_logic_vector(2-1 DOWNTO 0); + M_AXI_AWCACHE : OUT std_logic_vector(4-1 DOWNTO 0); + M_AXI_AWPROT : OUT std_logic_vector(3-1 DOWNTO 0); + M_AXI_AWQOS : OUT std_logic_vector(4-1 DOWNTO 0); + M_AXI_AWREGION : OUT std_logic_vector(4-1 DOWNTO 0); + M_AXI_AWUSER : OUT std_logic_vector(1-1 DOWNTO 0); + M_AXI_AWVALID : OUT std_logic; + M_AXI_AWREADY : IN std_logic; + M_AXI_WID : OUT std_logic_vector(4-1 DOWNTO 0); + M_AXI_WDATA : OUT std_logic_vector(64-1 DOWNTO 0); + M_AXI_WSTRB : OUT std_logic_vector(8-1 DOWNTO 0); + M_AXI_WLAST : OUT std_logic; + M_AXI_WUSER : OUT std_logic_vector(1-1 DOWNTO 0); + M_AXI_WVALID : OUT std_logic; + M_AXI_WREADY : IN std_logic; + M_AXI_BID : IN std_logic_vector(4-1 DOWNTO 0); + M_AXI_BRESP : IN std_logic_vector(2-1 DOWNTO 0); + M_AXI_BUSER : IN std_logic_vector(1-1 DOWNTO 0); + M_AXI_BVALID : IN std_logic; + M_AXI_BREADY : OUT std_logic; + -- AXI Full/Lite Slave Read Channel (Write side) + S_AXI_ARID : IN std_logic_vector(4-1 DOWNTO 0); + S_AXI_ARADDR : IN std_logic_vector(32-1 DOWNTO 0); + S_AXI_ARLEN : IN std_logic_vector(8-1 DOWNTO 0); + S_AXI_ARSIZE : IN std_logic_vector(3-1 DOWNTO 0); + S_AXI_ARBURST : IN std_logic_vector(2-1 DOWNTO 0); + S_AXI_ARLOCK : IN std_logic_vector(2-1 DOWNTO 0); + S_AXI_ARCACHE : IN std_logic_vector(4-1 DOWNTO 0); + S_AXI_ARPROT : IN std_logic_vector(3-1 DOWNTO 0); + S_AXI_ARQOS : IN std_logic_vector(4-1 DOWNTO 0); + S_AXI_ARREGION : IN std_logic_vector(4-1 DOWNTO 0); + S_AXI_ARUSER : IN std_logic_vector(1-1 DOWNTO 0); + S_AXI_ARVALID : IN std_logic; + S_AXI_ARREADY : OUT std_logic; + S_AXI_RID : OUT std_logic_vector(4-1 DOWNTO 0); + S_AXI_RDATA : OUT std_logic_vector(64-1 DOWNTO 0); + S_AXI_RRESP : OUT std_logic_vector(2-1 DOWNTO 0); + S_AXI_RLAST : OUT std_logic; + S_AXI_RUSER : OUT std_logic_vector(1-1 DOWNTO 0); + S_AXI_RVALID : OUT std_logic; + S_AXI_RREADY : IN std_logic; + -- AXI Full/Lite Master Read Channel (Read side) + M_AXI_ARID : OUT std_logic_vector(4-1 DOWNTO 0); + M_AXI_ARADDR : OUT std_logic_vector(32-1 DOWNTO 0); + M_AXI_ARLEN : OUT std_logic_vector(8-1 DOWNTO 0); + M_AXI_ARSIZE : OUT std_logic_vector(3-1 DOWNTO 0); + M_AXI_ARBURST : OUT std_logic_vector(2-1 DOWNTO 0); + M_AXI_ARLOCK : OUT std_logic_vector(2-1 DOWNTO 0); + M_AXI_ARCACHE : OUT std_logic_vector(4-1 DOWNTO 0); + M_AXI_ARPROT : OUT std_logic_vector(3-1 DOWNTO 0); + M_AXI_ARQOS : OUT std_logic_vector(4-1 DOWNTO 0); + M_AXI_ARREGION : OUT std_logic_vector(4-1 DOWNTO 0); + M_AXI_ARUSER : OUT std_logic_vector(1-1 DOWNTO 0); + M_AXI_ARVALID : OUT std_logic; + M_AXI_ARREADY : IN std_logic; + M_AXI_RID : IN std_logic_vector(4-1 DOWNTO 0); + M_AXI_RDATA : IN std_logic_vector(64-1 DOWNTO 0); + M_AXI_RRESP : IN std_logic_vector(2-1 DOWNTO 0); + M_AXI_RLAST : IN std_logic; + M_AXI_RUSER : IN std_logic_vector(1-1 DOWNTO 0); + M_AXI_RVALID : IN std_logic; + M_AXI_RREADY : OUT std_logic; + -- AXI Streaming Slave Signals (Write side) + S_AXIS_TVALID : IN std_logic; + S_AXIS_TREADY : OUT std_logic; + S_AXIS_TDATA : IN std_logic_vector(64-1 DOWNTO 0); + S_AXIS_TSTRB : IN std_logic_vector(4-1 DOWNTO 0); + S_AXIS_TKEEP : IN std_logic_vector(4-1 DOWNTO 0); + S_AXIS_TLAST : IN std_logic; + S_AXIS_TID : IN std_logic_vector(8-1 DOWNTO 0); + S_AXIS_TDEST : IN std_logic_vector(4-1 DOWNTO 0); + S_AXIS_TUSER : IN std_logic_vector(4-1 DOWNTO 0); + -- AXI Streaming Master Signals (Read side) + M_AXIS_TVALID : OUT std_logic; + M_AXIS_TREADY : IN std_logic; + M_AXIS_TDATA : OUT std_logic_vector(64-1 DOWNTO 0); + M_AXIS_TSTRB : OUT std_logic_vector(4-1 DOWNTO 0); + M_AXIS_TKEEP : OUT std_logic_vector(4-1 DOWNTO 0); + M_AXIS_TLAST : OUT std_logic; + M_AXIS_TID : OUT std_logic_vector(8-1 DOWNTO 0); + M_AXIS_TDEST : OUT std_logic_vector(4-1 DOWNTO 0); + M_AXIS_TUSER : OUT std_logic_vector(4-1 DOWNTO 0); + -- AXI Full/Lite Write Address Channel Signals + AXI_AW_INJECTSBITERR : IN std_logic; + AXI_AW_INJECTDBITERR : IN std_logic; + AXI_AW_PROG_FULL_THRESH : IN std_logic_vector(4-1 DOWNTO 0); + AXI_AW_PROG_EMPTY_THRESH : IN std_logic_vector(4-1 DOWNTO 0); + AXI_AW_DATA_COUNT : OUT std_logic_vector(4 DOWNTO 0); + AXI_AW_WR_DATA_COUNT : OUT std_logic_vector(4 DOWNTO 0); + AXI_AW_RD_DATA_COUNT : OUT std_logic_vector(4 DOWNTO 0); + AXI_AW_SBITERR : OUT std_logic; + AXI_AW_DBITERR : OUT std_logic; + AXI_AW_OVERFLOW : OUT std_logic; + AXI_AW_UNDERFLOW : OUT std_logic; + -- AXI Full/Lite Write Data Channel Signals + AXI_W_INJECTSBITERR : IN std_logic; + AXI_W_INJECTDBITERR : IN std_logic; + AXI_W_PROG_FULL_THRESH : IN std_logic_vector(10-1 DOWNTO 0); + AXI_W_PROG_EMPTY_THRESH : IN std_logic_vector(10-1 DOWNTO 0); + AXI_W_DATA_COUNT : OUT std_logic_vector(10 DOWNTO 0); + AXI_W_WR_DATA_COUNT : OUT std_logic_vector(10 DOWNTO 0); + AXI_W_RD_DATA_COUNT : OUT std_logic_vector(10 DOWNTO 0); + AXI_W_SBITERR : OUT std_logic; + AXI_W_DBITERR : OUT std_logic; + AXI_W_OVERFLOW : OUT std_logic; + AXI_W_UNDERFLOW : OUT std_logic; + -- AXI Full/Lite Write Response Channel Signals + AXI_B_INJECTSBITERR : IN std_logic; + AXI_B_INJECTDBITERR : IN std_logic; + AXI_B_PROG_FULL_THRESH : IN std_logic_vector(4-1 DOWNTO 0); + AXI_B_PROG_EMPTY_THRESH : IN std_logic_vector(4-1 DOWNTO 0); + AXI_B_DATA_COUNT : OUT std_logic_vector(4 DOWNTO 0); + AXI_B_WR_DATA_COUNT : OUT std_logic_vector(4 DOWNTO 0); + AXI_B_RD_DATA_COUNT : OUT std_logic_vector(4 DOWNTO 0); + AXI_B_SBITERR : OUT std_logic; + AXI_B_DBITERR : OUT std_logic; + AXI_B_OVERFLOW : OUT std_logic; + AXI_B_UNDERFLOW : OUT std_logic; + -- AXI Full/Lite Read Address Channel Signals + AXI_AR_INJECTSBITERR : IN std_logic; + AXI_AR_INJECTDBITERR : IN std_logic; + AXI_AR_PROG_FULL_THRESH : IN std_logic_vector(4-1 DOWNTO 0); + AXI_AR_PROG_EMPTY_THRESH : IN std_logic_vector(4-1 DOWNTO 0); + AXI_AR_DATA_COUNT : OUT std_logic_vector(4 DOWNTO 0); + AXI_AR_WR_DATA_COUNT : OUT std_logic_vector(4 DOWNTO 0); + AXI_AR_RD_DATA_COUNT : OUT std_logic_vector(4 DOWNTO 0); + AXI_AR_SBITERR : OUT std_logic; + AXI_AR_DBITERR : OUT std_logic; + AXI_AR_OVERFLOW : OUT std_logic; + AXI_AR_UNDERFLOW : OUT std_logic; + -- AXI Full/Lite Read Data Channel Signals + AXI_R_INJECTSBITERR : IN std_logic; + AXI_R_INJECTDBITERR : IN std_logic; + AXI_R_PROG_FULL_THRESH : IN std_logic_vector(10-1 DOWNTO 0); + AXI_R_PROG_EMPTY_THRESH : IN std_logic_vector(10-1 DOWNTO 0); + AXI_R_DATA_COUNT : OUT std_logic_vector(10 DOWNTO 0); + AXI_R_WR_DATA_COUNT : OUT std_logic_vector(10 DOWNTO 0); + AXI_R_RD_DATA_COUNT : OUT std_logic_vector(10 DOWNTO 0); + AXI_R_SBITERR : OUT std_logic; + AXI_R_DBITERR : OUT std_logic; + AXI_R_OVERFLOW : OUT std_logic; + AXI_R_UNDERFLOW : OUT std_logic; + -- AXI Streaming FIFO Related Signals + AXIS_INJECTSBITERR : IN std_logic; + AXIS_INJECTDBITERR : IN std_logic; + AXIS_PROG_FULL_THRESH : IN std_logic_vector(10-1 DOWNTO 0); + AXIS_PROG_EMPTY_THRESH : IN std_logic_vector(10-1 DOWNTO 0); + AXIS_DATA_COUNT : OUT std_logic_vector(10 DOWNTO 0); + AXIS_WR_DATA_COUNT : OUT std_logic_vector(10 DOWNTO 0); + AXIS_RD_DATA_COUNT : OUT std_logic_vector(10 DOWNTO 0); + AXIS_SBITERR : OUT std_logic; + AXIS_DBITERR : OUT std_logic; + AXIS_OVERFLOW : OUT std_logic; + AXIS_UNDERFLOW : OUT std_logic); + +end iblfifo_top; + + + +architecture xilinx of iblfifo_top is + + SIGNAL WR_CLK_i : std_logic; + SIGNAL RD_CLK_i : std_logic; + + + + component iblfifo is + PORT ( + WR_CLK : IN std_logic; + RD_CLK : IN std_logic; + RST : IN std_logic; + WR_EN : IN std_logic; + RD_EN : IN std_logic; + DIN : IN std_logic_vector(36-1 DOWNTO 0); + DOUT : OUT std_logic_vector(36-1 DOWNTO 0); + FULL : OUT std_logic; + EMPTY : OUT std_logic); + end component; + + +begin + + fg0 : iblfifo + port map ( + WR_CLK => WR_CLK_i, + RD_CLK => RD_CLK_i, + RST => RST, + WR_EN => WR_EN, + RD_EN => RD_EN, + DIN => DIN, + DOUT => DOUT, + FULL => FULL, + EMPTY => EMPTY); + + +wr_clk_buf: bufg + PORT map( + i => WR_CLK, + o => WR_CLK_i + ); + +rd_clk_buf: bufg + PORT map( + i => RD_CLK, + o => RD_CLK_i + ); + + +end xilinx; diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/example_design/iblfifo_top.xdc b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/example_design/iblfifo_top.xdc new file mode 100755 index 00000000..d0bafcd3 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/example_design/iblfifo_top.xdc @@ -0,0 +1,57 @@ +################################################################################ +# (c) Copyright 2009 - 2010 Xilinx, Inc. All rights reserved. +# +# This file contains confidential and proprietary information +# of Xilinx, Inc. and is protected under U.S. and +# international copyright and other intellectual property +# laws. +# +# DISCLAIMER +# This disclaimer is not a license and does not grant any +# rights to the materials distributed herewith. Except as +# otherwise provided in a valid license issued to you by +# Xilinx, and to the maximum extent permitted by applicable +# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND +# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES +# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING +# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- +# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and +# (2) Xilinx shall not be liable (whether in contract or tort, +# including negligence, or under any other theory of +# liability) for any loss or damage of any kind or nature +# related to, arising under or in connection with these +# materials, including for any direct, or any indirect, +# special, incidental, or consequential loss or damage +# (including loss of data, profits, goodwill, or any type of +# loss or damage suffered as a result of any action brought +# by a third party) even if such damage or loss was +# reasonably foreseeable or Xilinx had been advised of the +# possibility of the same. +# +# CRITICAL APPLICATIONS +# Xilinx products are not designed or intended to be fail- +# safe, or for use in any application requiring fail-safe +# performance, such as life-support or safety devices or +# systems, Class III medical devices, nuclear facilities, +# applications related to the deployment of airbags, or any +# other applications that could lead to death, personal +# injury, or severe property or environmental damage +# (individually and collectively, "Critical +# Applications"). Customer assumes the sole risk and +# liability of any use of Xilinx products in Critical +# Applications, subject only to applicable laws and +# regulations governing limitations on product liability. +# +# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS +# PART OF THIS FILE AT ALL TIMES. +# +################################################################################ + +# Core Period Constraint. This constraint can be modified, and is +# valid as long as it is met after place and route. +create_clock -name "TS_RD_CLK" -period 20.0 [ get_ports RD_CLK ] +create_clock -name "TS_WR_CLK" -period 20.0 [ get_ports WR_CLK ] + + + +################################################################################ diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/implement.bat b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/implement.bat new file mode 100755 index 00000000..903e453b --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/implement.bat @@ -0,0 +1,88 @@ +rem (c) Copyright 2009 - 2010 Xilinx, Inc. All rights reserved. +rem +rem This file contains confidential and proprietary information +rem of Xilinx, Inc. and is protected under U.S. and +rem international copyright and other intellectual property +rem laws. +rem +rem DISCLAIMER +rem This disclaimer is not a license and does not grant any +rem rights to the materials distributed herewith. Except as +rem otherwise provided in a valid license issued to you by +rem Xilinx, and to the maximum extent permitted by applicable +rem law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND +rem WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES +rem AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING +rem BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- +rem INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and +rem (2) Xilinx shall not be liable (whether in contract or tort, +rem including negligence, or under any other theory of +rem liability) for any loss or damage of any kind or nature +rem related to, arising under or in connection with these +rem materials, including for any direct, or any indirect, +rem special, incidental, or consequential loss or damage +rem (including loss of data, profits, goodwill, or any type of +rem loss or damage suffered as a result of any action brought +rem by a third party) even if such damage or loss was +rem reasonably foreseeable or Xilinx had been advised of the +rem possibility of the same. +rem +rem CRITICAL APPLICATIONS +rem Xilinx products are not designed or intended to be fail- +rem safe, or for use in any application requiring fail-safe +rem performance, such as life-support or safety devices or +rem systems, Class III medical devices, nuclear facilities, +rem applications related to the deployment of airbags, or any +rem other applications that could lead to death, personal +rem injury, or severe property or environmental damage +rem (individually and collectively, "Critical +rem Applications"). Customer assumes the sole risk and +rem liability of any use of Xilinx products in Critical +rem Applications, subject only to applicable laws and +rem regulations governing limitations on product liability. +rem +rem THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS +rem PART OF THIS FILE AT ALL TIMES. + +rem Clean up the results directory +rmdir /S /Q results +mkdir results + +rem Synthesize the VHDL Wrapper Files + +#Synthesize the Wrapper Files + +echo 'Synthesizing example design with XST'; +xst -ifn xst.scr +copy iblfifo_top.ngc .\results\ + + +rem Copy the netlist generated by Coregen +echo 'Copying files from the netlist directory to the results directory' +copy ..\..\iblfifo.ngc results\ + + +rem Copy the constraints files generated by Coregen +echo 'Copying files from constraints directory to results directory' +copy ..\example_design\iblfifo_top.ucf results\ + +cd results + +echo 'Running ngdbuild' + +ngdbuild -p xc4vlx200-ff1513-10 -sd ../../../ iblfifo_top + +echo 'Running map' +map iblfifo_top -o mapped.ncd + +echo 'Running par' +par mapped.ncd routed.ncd + +echo 'Running trce' +trce -e 10 routed.ncd mapped.pcf -o routed + +echo 'Running design through bitgen' +bitgen -w routed + +echo 'Running netgen to create gate level VHDL model' +netgen -ofmt vhdl -sim -tm iblfifo_top -pcf mapped.pcf -w routed.ncd routed.vhd diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/implement.sh b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/implement.sh new file mode 100755 index 00000000..a4b86aaf --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/implement.sh @@ -0,0 +1,87 @@ +#!/bin/sh +# (c) Copyright 2009 - 2010 Xilinx, Inc. All rights reserved. +# +# This file contains confidential and proprietary information +# of Xilinx, Inc. and is protected under U.S. and +# international copyright and other intellectual property +# laws. +# +# DISCLAIMER +# This disclaimer is not a license and does not grant any +# rights to the materials distributed herewith. Except as +# otherwise provided in a valid license issued to you by +# Xilinx, and to the maximum extent permitted by applicable +# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND +# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES +# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING +# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- +# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and +# (2) Xilinx shall not be liable (whether in contract or tort, +# including negligence, or under any other theory of +# liability) for any loss or damage of any kind or nature +# related to, arising under or in connection with these +# materials, including for any direct, or any indirect, +# special, incidental, or consequential loss or damage +# (including loss of data, profits, goodwill, or any type of +# loss or damage suffered as a result of any action brought +# by a third party) even if such damage or loss was +# reasonably foreseeable or Xilinx had been advised of the +# possibility of the same. +# +# CRITICAL APPLICATIONS +# Xilinx products are not designed or intended to be fail- +# safe, or for use in any application requiring fail-safe +# performance, such as life-support or safety devices or +# systems, Class III medical devices, nuclear facilities, +# applications related to the deployment of airbags, or any +# other applications that could lead to death, personal +# injury, or severe property or environmental damage +# (individually and collectively, "Critical +# Applications"). Customer assumes the sole risk and +# liability of any use of Xilinx products in Critical +# Applications, subject only to applicable laws and +# regulations governing limitations on product liability. +# +# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS +# PART OF THIS FILE AT ALL TIMES. + +# Clean up the results directory +rm -rf results +mkdir results + +#Synthesize the Wrapper Files + +echo 'Synthesizing example design with XST'; +xst -ifn xst.scr +cp iblfifo_top.ngc ./results/ + + +# Copy the netlist generated by Coregen +echo 'Copying files from the netlist directory to the results directory' +cp ../../iblfifo.ngc results/ + +# Copy the constraints files generated by Coregen +echo 'Copying files from constraints directory to results directory' +cp ../example_design/iblfifo_top.ucf results/ + +cd results + +echo 'Running ngdbuild' + +ngdbuild -p xc4vlx200-ff1513-10 -sd ../../../ iblfifo_top + +echo 'Running map' +map iblfifo_top -o mapped.ncd + +echo 'Running par' +par mapped.ncd routed.ncd + +echo 'Running trce' +trce -e 10 routed.ncd mapped.pcf -o routed + +echo 'Running design through bitgen' +bitgen -w routed + +echo 'Running netgen to create gate level VHDL model' +netgen -ofmt vhdl -sim -tm iblfifo_top -pcf mapped.pcf -w routed.ncd routed.vhd + diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/planAhead_rdn.bat b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/planAhead_rdn.bat new file mode 100755 index 00000000..85210855 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/planAhead_rdn.bat @@ -0,0 +1,55 @@ +#!/bin/sh +rem (c) Copyright 2009 - 2010 Xilinx, Inc. All rights reserved. +rem +rem This file contains confidential and proprietary information +rem of Xilinx, Inc. and is protected under U.S. and +rem international copyright and other intellectual property +rem laws. +rem +rem DISCLAIMER +rem This disclaimer is not a license and does not grant any +rem rights to the materials distributed herewith. Except as +rem otherwise provided in a valid license issued to you by +rem Xilinx, and to the maximum extent permitted by applicable +rem law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND +rem WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES +rem AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING +rem BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- +rem INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and +rem (2) Xilinx shall not be liable (whether in contract or tort, +rem including negligence, or under any other theory of +rem liability) for any loss or damage of any kind or nature +rem related to, arising under or in connection with these +rem materials, including for any direct, or any indirect, +rem special, incidental, or consequential loss or damage +rem (including loss of data, profits, goodwill, or any type of +rem loss or damage suffered as a result of any action brought +rem by a third party) even if such damage or loss was +rem reasonably foreseeable or Xilinx had been advised of the +rem possibility of the same. +rem +rem CRITICAL APPLICATIONS +rem Xilinx products are not designed or intended to be fail- +rem safe, or for use in any application requiring fail-safe +rem performance, such as life-support or safety devices or +rem systems, Class III medical devices, nuclear facilities, +rem applications related to the deployment of airbags, or any +rem other applications that could lead to death, personal +rem injury, or severe property or environmental damage +rem (individually and collectively, "Critical +rem Applications"). Customer assumes the sole risk and +rem liability of any use of Xilinx products in Critical +rem Applications, subject only to applicable laws and +rem regulations governing limitations on product liability. +rem +rem THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS +rem PART OF THIS FILE AT ALL TIMES. + +rem ----------------------------------------------------------------------------- +rem Script to synthesize and implement the Coregen FIFO Generator +rem ----------------------------------------------------------------------------- +rmdir /S /Q results +mkdir results +cd results +copy ..\..\..\tmp\iblfifo.edf . +planAhead -mode batch -source ..\planAhead_rdn.tcl diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/planAhead_rdn.sh b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/planAhead_rdn.sh new file mode 100755 index 00000000..9c19db71 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/planAhead_rdn.sh @@ -0,0 +1,55 @@ +#!/bin/sh +# (c) Copyright 2009 - 2010 Xilinx, Inc. All rights reserved. +# +# This file contains confidential and proprietary information +# of Xilinx, Inc. and is protected under U.S. and +# international copyright and other intellectual property +# laws. +# +# DISCLAIMER +# This disclaimer is not a license and does not grant any +# rights to the materials distributed herewith. Except as +# otherwise provided in a valid license issued to you by +# Xilinx, and to the maximum extent permitted by applicable +# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND +# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES +# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING +# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- +# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and +# (2) Xilinx shall not be liable (whether in contract or tort, +# including negligence, or under any other theory of +# liability) for any loss or damage of any kind or nature +# related to, arising under or in connection with these +# materials, including for any direct, or any indirect, +# special, incidental, or consequential loss or damage +# (including loss of data, profits, goodwill, or any type of +# loss or damage suffered as a result of any action brought +# by a third party) even if such damage or loss was +# reasonably foreseeable or Xilinx had been advised of the +# possibility of the same. +# +# CRITICAL APPLICATIONS +# Xilinx products are not designed or intended to be fail- +# safe, or for use in any application requiring fail-safe +# performance, such as life-support or safety devices or +# systems, Class III medical devices, nuclear facilities, +# applications related to the deployment of airbags, or any +# other applications that could lead to death, personal +# injury, or severe property or environmental damage +# (individually and collectively, "Critical +# Applications"). Customer assumes the sole risk and +# liability of any use of Xilinx products in Critical +# Applications, subject only to applicable laws and +# regulations governing limitations on product liability. +# +# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS +# PART OF THIS FILE AT ALL TIMES. + +#----------------------------------------------------------------------------- +# Script to synthesize and implement the Coregen FIFO Generator +#----------------------------------------------------------------------------- +rm -rf results +mkdir results +cd results +cp ../../../tmp/iblfifo.edf . +planAhead -mode batch -source ../planAhead_rdn.tcl diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/planAhead_rdn.tcl b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/planAhead_rdn.tcl new file mode 100755 index 00000000..b97647dd --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/planAhead_rdn.tcl @@ -0,0 +1,67 @@ +# (c) Copyright 2009 - 2010 Xilinx, Inc. All rights reserved. +# +# This file contains confidential and proprietary information +# of Xilinx, Inc. and is protected under U.S. and +# international copyright and other intellectual property +# laws. +# +# DISCLAIMER +# This disclaimer is not a license and does not grant any +# rights to the materials distributed herewith. Except as +# otherwise provided in a valid license issued to you by +# Xilinx, and to the maximum extent permitted by applicable +# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND +# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES +# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING +# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- +# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and +# (2) Xilinx shall not be liable (whether in contract or tort, +# including negligence, or under any other theory of +# liability) for any loss or damage of any kind or nature +# related to, arising under or in connection with these +# materials, including for any direct, or any indirect, +# special, incidental, or consequential loss or damage +# (including loss of data, profits, goodwill, or any type of +# loss or damage suffered as a result of any action brought +# by a third party) even if such damage or loss was +# reasonably foreseeable or Xilinx had been advised of the +# possibility of the same. +# +# CRITICAL APPLICATIONS +# Xilinx products are not designed or intended to be fail- +# safe, or for use in any application requiring fail-safe +# performance, such as life-support or safety devices or +# systems, Class III medical devices, nuclear facilities, +# applications related to the deployment of airbags, or any +# other applications that could lead to death, personal +# injury, or severe property or environmental damage +# (individually and collectively, "Critical +# Applications"). Customer assumes the sole risk and +# liability of any use of Xilinx products in Critical +# Applications, subject only to applicable laws and +# regulations governing limitations on product liability. +# +# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS +# PART OF THIS FILE AT ALL TIMES. + + +set device xc4vfx60ff1152-10 +set projName iblfifo +set design iblfifo +set projDir [file dirname [info script]] +create_project $projName $projDir/results/$projName -part $device -force +set_property design_mode RTL [current_fileset -srcset] +set top_module iblfifo_top +add_files -norecurse {../../example_design/iblfifo_top.vhd} +add_files -norecurse {./iblfifo.edf} +import_files -fileset [get_filesets constrs_1] -force -norecurse {../../example_design/iblfifo_top.xdc} +set_property top iblfifo_top [get_property srcset [current_run]] +synth_design +opt_design +place_design +route_design +write_sdf -rename_top_module iblfifo_top -file routed.sdf +write_verilog -nolib -mode sim -sdf_anno false -rename_top_module iblfifo_top routed.vhd +report_timing -nworst 30 -path_type full -file routed.twr +report_drc +#write_bitstream diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/xst.prj b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/xst.prj new file mode 100755 index 00000000..59db9f66 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/xst.prj @@ -0,0 +1 @@ +work ../example_design/iblfifo_top.vhd diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/xst.scr b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/xst.scr new file mode 100755 index 00000000..acf6372c --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_ste/implement/xst.scr @@ -0,0 +1,13 @@ +run +-ifmt VHDL +-ent iblfifo_top +-p xc4vlx200-ff1513-10 +-ifn xst.prj +-write_timing_constraints No +-iobuf YES +-max_fanout 100 +-ofn iblfifo_top +-ofmt NGC +-bus_delimiter () +-hierarchy_separator / +-case Maintain diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_upgrade.txt b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_upgrade.txt new file mode 100644 index 00000000..0612390f --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_upgrade.txt @@ -0,0 +1,129 @@ +Thu Oct 6 00:36:20 2011 + +Upgraded iblfifo from Fifo Generator 4.4 to Fifo Generator 8.2 + +Added parameter enable_reset_synchronization with value true +Added parameter inject_dbit_error with value false +Added parameter inject_sbit_error with value false +Removed parameter enable_int_clk +Added parameter add_ngc_constraint_axi with value false +Added parameter aruser_width with value 1 +Added parameter awuser_width with value 1 +Added parameter axi_address_width with value 32 +Added parameter axi_data_width with value 64 +Added parameter axi_type with value AXI4_Stream +Added parameter axis_type with value FIFO +Added parameter buser_width with value 1 +Added parameter clock_enable_type with value Slave_Interface_Clock_Enable +Added parameter clock_type_axi with value Common_Clock +Added parameter disable_timing_violations_axi with value false +Added parameter empty_threshold_assert_value_axis with value 1022 +Added parameter empty_threshold_assert_value_rach with value 1022 +Added parameter empty_threshold_assert_value_rdch with value 1022 +Added parameter empty_threshold_assert_value_wach with value 1022 +Added parameter empty_threshold_assert_value_wdch with value 1022 +Added parameter empty_threshold_assert_value_wrch with value 1022 +Added parameter enable_aruser with value false +Added parameter enable_awuser with value false +Added parameter enable_buser with value false +Added parameter enable_common_overflow with value false +Added parameter enable_common_underflow with value false +Added parameter enable_data_counts_axis with value false +Added parameter enable_data_counts_rach with value false +Added parameter enable_data_counts_rdch with value false +Added parameter enable_data_counts_wach with value false +Added parameter enable_data_counts_wdch with value false +Added parameter enable_data_counts_wrch with value false +Added parameter enable_ecc_axis with value false +Added parameter enable_ecc_rach with value false +Added parameter enable_ecc_rdch with value false +Added parameter enable_ecc_wach with value false +Added parameter enable_ecc_wdch with value false +Added parameter enable_ecc_wrch with value false +Added parameter enable_handshake_flag_options_axis with value false +Added parameter enable_handshake_flag_options_rach with value false +Added parameter enable_handshake_flag_options_rdch with value false +Added parameter enable_handshake_flag_options_wach with value false +Added parameter enable_handshake_flag_options_wdch with value false +Added parameter enable_handshake_flag_options_wrch with value false +Added parameter enable_read_channel with value false +Added parameter enable_ruser with value false +Added parameter enable_tdata with value false +Added parameter enable_tdest with value false +Added parameter enable_tid with value false +Added parameter enable_tkeep with value false +Added parameter enable_tlast with value false +Added parameter enable_tready with value true +Added parameter enable_tstrobe with value false +Added parameter enable_tuser with value false +Added parameter enable_write_channel with value false +Added parameter enable_wuser with value false +Added parameter fifo_application_type_axis with value Data_FIFO +Added parameter fifo_application_type_rach with value Data_FIFO +Added parameter fifo_application_type_rdch with value Data_FIFO +Added parameter fifo_application_type_wach with value Data_FIFO +Added parameter fifo_application_type_wdch with value Data_FIFO +Added parameter fifo_application_type_wrch with value Data_FIFO +Added parameter fifo_implementation_axis with value Common_Clock_Block_RAM +Added parameter fifo_implementation_rach with value Common_Clock_Block_RAM +Added parameter fifo_implementation_rdch with value Common_Clock_Block_RAM +Added parameter fifo_implementation_wach with value Common_Clock_Block_RAM +Added parameter fifo_implementation_wdch with value Common_Clock_Block_RAM +Added parameter fifo_implementation_wrch with value Common_Clock_Block_RAM +Added parameter full_threshold_assert_value_axis with value 1023 +Added parameter full_threshold_assert_value_rach with value 1023 +Added parameter full_threshold_assert_value_rdch with value 1023 +Added parameter full_threshold_assert_value_wach with value 1023 +Added parameter full_threshold_assert_value_wdch with value 1023 +Added parameter full_threshold_assert_value_wrch with value 1023 +Added parameter id_width with value 4 +Added parameter inject_dbit_error_axis with value false +Added parameter inject_dbit_error_rach with value false +Added parameter inject_dbit_error_rdch with value false +Added parameter inject_dbit_error_wach with value false +Added parameter inject_dbit_error_wdch with value false +Added parameter inject_dbit_error_wrch with value false +Added parameter inject_sbit_error_axis with value false +Added parameter inject_sbit_error_rach with value false +Added parameter inject_sbit_error_rdch with value false +Added parameter inject_sbit_error_wach with value false +Added parameter inject_sbit_error_wdch with value false +Added parameter inject_sbit_error_wrch with value false +Added parameter input_depth_axis with value 1024 +Added parameter input_depth_rach with value 16 +Added parameter input_depth_rdch with value 1024 +Added parameter input_depth_wach with value 16 +Added parameter input_depth_wdch with value 1024 +Added parameter input_depth_wrch with value 16 +Added parameter interface_type with value Native +Added parameter overflow_flag_axi with value false +Added parameter overflow_sense_axi with value Active_High +Added parameter programmable_empty_type_axis with value Empty +Added parameter programmable_empty_type_rach with value Empty +Added parameter programmable_empty_type_rdch with value Empty +Added parameter programmable_empty_type_wach with value Empty +Added parameter programmable_empty_type_wdch with value Empty +Added parameter programmable_empty_type_wrch with value Empty +Added parameter programmable_full_type_axis with value Full +Added parameter programmable_full_type_rach with value Full +Added parameter programmable_full_type_rdch with value Full +Added parameter programmable_full_type_wach with value Full +Added parameter programmable_full_type_wdch with value Full +Added parameter programmable_full_type_wrch with value Full +Added parameter rach_type with value FIFO +Added parameter rdch_type with value FIFO +Added parameter ruser_width with value 1 +Added parameter tdata_width with value 64 +Added parameter tdest_width with value 4 +Added parameter tid_width with value 8 +Added parameter tkeep_width with value 4 +Added parameter tstrb_width with value 4 +Added parameter tuser_width with value 4 +Added parameter underflow_flag_axi with value false +Added parameter underflow_sense_axi with value Active_High +Added parameter use_clock_enable with value false +Added parameter wach_type with value FIFO +Added parameter wdch_type with value FIFO +Added parameter wrch_type with value FIFO +Added parameter wuser_width with value 1 + diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_xmdf.tcl b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_xmdf.tcl new file mode 100644 index 00000000..71e51b1d --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/iblfifo_xmdf.tcl @@ -0,0 +1,115 @@ +# The package naming convention is <core_name>_xmdf +package provide iblfifo_xmdf 1.0 + +# This includes some utilities that support common XMDF operations +package require utilities_xmdf + +# Define a namespace for this package. The name of the name space +# is <core_name>_xmdf +namespace eval ::iblfifo_xmdf { +# Use this to define any statics +} + +# Function called by client to rebuild the params and port arrays +# Optional when the use context does not require the param or ports +# arrays to be available. +proc ::iblfifo_xmdf::xmdfInit { instance } { +# Variable containing name of library into which module is compiled +# Recommendation: <module_name> +# Required +utilities_xmdf::xmdfSetData $instance Module Attributes Name iblfifo +} +# ::iblfifo_xmdf::xmdfInit + +# Function called by client to fill in all the xmdf* data variables +# based on the current settings of the parameters +proc ::iblfifo_xmdf::xmdfApplyParams { instance } { + +set fcount 0 +# Array containing libraries that are assumed to exist +# Examples include unisim and xilinxcorelib +# Optional +# In this example, we assume that the unisim library will +# be available to the simulation and synthesis tool +utilities_xmdf::xmdfSetData $instance FileSet $fcount type logical_library +utilities_xmdf::xmdfSetData $instance FileSet $fcount logical_library unisim +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path fifo_generator_ug175.pdf +utilities_xmdf::xmdfSetData $instance FileSet $fcount type AnyView +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path fifo_generator_v8_2_readme.txt +utilities_xmdf::xmdfSetData $instance FileSet $fcount type text +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path iblfifo.ngc +utilities_xmdf::xmdfSetData $instance FileSet $fcount type ngc +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path iblfifo.vhd +utilities_xmdf::xmdfSetData $instance FileSet $fcount type vhdl +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path iblfifo.vho +utilities_xmdf::xmdfSetData $instance FileSet $fcount type vhdl_template +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path iblfifo.xco +utilities_xmdf::xmdfSetData $instance FileSet $fcount type coregen_ip +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path iblfifo_ste/example_design/iblfifo_top.ucf +utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path iblfifo_ste/example_design/iblfifo_top.vhd +utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path iblfifo_ste/example_design/iblfifo_top.xdc +utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path iblfifo_ste/implement/implement.bat +utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path iblfifo_ste/implement/implement.sh +utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path iblfifo_ste/implement/planAhead_rdn.bat +utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path iblfifo_ste/implement/planAhead_rdn.sh +utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path iblfifo_ste/implement/planAhead_rdn.tcl +utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path iblfifo_ste/implement/xst.prj +utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path iblfifo_ste/implement/xst.scr +utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path iblfifo_upgrade.txt +utilities_xmdf::xmdfSetData $instance FileSet $fcount type text +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path iblfifo_xmdf.tcl +utilities_xmdf::xmdfSetData $instance FileSet $fcount type AnyView +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount associated_module iblfifo +incr fcount + +} + +# ::gen_comp_name_xmdf::xmdfApplyParams diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem.ngc b/rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem.ngc new file mode 100644 index 00000000..78b1bc8c --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem.ngc @@ -0,0 +1,3 @@ +XILINX-XDB 0.1 STUB 0.1 ASCII +XILINX-XDM V1.4e +$26b4g<,[o}e~g`n;"2*413&;$>"9 > %71?*ga{&ygmn!z/da,ojenig%fecgcau-{mioip&He`L}fc.zjhZehzly$x`~ _be,tdrsm{dTnaePmdo-jbi>39:;<=>?0163?56789:;<=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?012346=6&9;87<>5IORVP?gcl{k757>112924?OIX\^1mij}b=;94;7338?1EC^ZT;CG@WG;9=0;2<:4148JJUSS2HNO^O2>4;2=55=62@D[YY4xe`>3>58682;1EC^ZT;uff96=87;97><5IORVP?BNI59:6=0>2:11>LHW]]0OEO2<1;2=56=4:3CE\XZ5dhlb867=87;87><5IORVP?bnfk68=7>112906?IR\Y__6IAN<2394;743:81CXZ_UU8GKG:493:5=85<2;MVPUSS2me~xl2<1;2=50=4:3E^X][[:emvpg:493:5=<5;:HLSQQ<CAYK7?7>11097>LHW]]0OE]L33;2=55=32@D[YY4XE@>0>58682>1EC^ZT;UFF95=87;9794@UURVP?BHXH686=0>2:69KPRW]]0OC]L33;2=b>2qnq<;jk?>53/24==FLMXJ0=06;@FGVD:68730MIJ]A=32:<=FLMXJ0<<19:CG@WG;9:4i7LJKR@>20?6912KOH_O315<;?DBCZH6:255NDEPB878?3HNO^L2<>99B@ATF4=437LJKR@>6:==FLMXJ0;07;@FGVD:0611JHI\N<9<;?DBCZH62255NDEPA858>3HNO^O2>0?;8EABUJ5;:245NDEPA844912KOH_L312<a?DBCZK6:87>19:CG@WD;9=437LJKRC>2:==FLMXI0?07;@FGVG:4611JHI\M<5<;?DBCZK6>255NDEPA838?3HNO^O28>99B@ATE41437LJKRC>::6=FDE90NX<7;CWP[LHAGh1HM^MNDDKMEd=DIZIJHHGABc9@EVEFLLE^XLl4C@Q@EACH]]H:>6MGEBI\HLEBFZOTXT^J4:AOOD2<KEAI56M@MLKWP@B6<2ID^HQHEOGQEQOHFVCEJB94CSGBP@B13MCJ0=08;EKB8469?2NBM1?>>69GMD:6:7=0HDO312<4?AOF48>5;6JFA=36:2=CAH6::394DHC?52803MCJ0<617:FJE97>6?1OEL2>>69GMD:587=0HDO320<4?AOF4;85;6JFA=00:2=CAH698394DHC?60803MCJ0?817:FJE9406>1OEL2=8?58@LG;:04=7IGN<3<4?AOF4::556JFA=12>5803MCJ0>?16:FJE959>2NBM1:16:FJE939>2NBM1816:FJE919>2NBM1616:FJE9?9>2NBN1>17:FJF9776>1OEO2>1?58@LD;9;4<7IGM<01=3>BNJ5;?2:5KIC>21;1<L@H7=;08;EKA8419?2NBN1?7>69GMG:617<0HDL31?58@LD;:94<7IGM<33=3>BNJ5892:5KIC>17;1<L@H7>908;EKA8739?2NBN1<9>69GMG:5?7=0HDL329<4?AOE4;35:6JFB=0=3>BNJ59;245KIC>05?69?2NBN1=>>79GMG:46?1OEO2;>79GMG:26?1OEO29>79GMG:06?1OEO27>79GMG:>6>1OE]O30?58@LVF484<7IG_A=0==>BNXH686=08;EKSE959?2NB\O2?>69GMUD;97=0HD^M<3<:?AOWJ591<394DHRA86813MEJ0=08;EMB8469?2NDM1?>>69GKD:6:7=0HBO312<4?AIF48>5;6J@A=36:2=CGH6::394DNC?52803MEJ0<617:FLE97>6?1OCL2>>69GKD:587=0HBO320<4?AIF4;85;6J@A=00:2=CGH698394DNC?60803MEJ0?817:FLE9406>1OCL2=8?58@JG;:04=7IAN<3<4?AIF4::556J@A=12>5803MEJ0>?16:FLE959>2NDM1:16:FLE939>2NDM1816:FLE919>2NDM1616:FLE9?9?2NDMR\JG79GKG:76>1OCO2>0?58@JD;984<7IAM<00=3>BHJ5;82:5KOC>20;1<LFH7=808;EMA8409?2NDN1?8>69GKG:607=0HBL318<5?AIE484<7IAM<32=3>BHJ58:2:5KOC>16;1<LFH7>>08;EMA8729?2NDN1<:>69GKG:5>7=0HBL326<4?AIE4;25;6J@B=0::3=CGK692:5KOC>04;?<LFH7?<4?>69GKG:497<0HBL33?48@JD;<7<0HBL35?48@JD;>7<0HBL37?48@JD;07<0HBL39?58@JDXZLM<7IA_A=2=3>BHXH6:2:5KOQC?6;?<LFZJ0>4?>69GKUG;;7=0HB^M<1<4?AIWJ5;5;6J@PC>1:<=CGYH7?7>17:FLTG:46:1NBL=4EO@6?CGK[L;0K>5HNE:8MKOSXV:;46GAIUR\44><AGC_\R>=8:KMMQVX8:20ECG[P^27<>OIA]ZT<864IOKWTZ6102CEEY^P0658MKOSW9:<7D@FT^223>OIA]U;>:5FNHV\461<AGC_S=:8;HLJPZ62?2CEEYQ?669JJLRX8>=0ECG[_1:4?LHN\V:2;6GAIU]3E2=NF@^T<O94IOKW[5E03@DBXR>K7:KMMQY7M>1BBDZP0G58MKOSW8:<7D@FT^323>OIA]U:>:5FNHV\561<AGC_S<:8;HLJPZ72?2CEEYQ>669JJLRX9>=0ECG[_0:4?LHN\V;2;6GAIU]2E2=NF@^T=O94IOKW[4E03@DBXR?K7:KMMQY6M>1BBDZP1G58MKOSW;:<7D@FT^023>OIA]U9>:5FNHV\661<AGC_S?:8;HLJPZ42?2CEEYQ=669JJLRX:>=0ECG[_3:4?LHN\V82;6GAIU]1E2=NF@^T>O94IOKW[7E03@DBXR<K7:KMMQY5M>1BBDZP2G58MKOSW::<7D@FT^123>OIA]U8>:5FNHV\761<AGC_S>:8;HLJPZ52?2CEEYQ<669JJLRX;>=0ECG[_2:4?LHN\V92;6GAIU]0E2=NF@^T?O94IOKW[6E03@DBXR=K7:KMMQY4M>1BBDZP3G48MKOSWH<0ECG[_C;8MKOSWOCGI<<4IOTFVQYDDBUOCLQ]EF31?LHQM[^TOAEPDN@\V@A13EEJHHJ8;MMDMFGKk2Gjfb|Yesqjkke<E`dd~[k}shmm7>H68=1E==>;;O3351=I998?7C??359M55233G;;995A1147?K77?=1E==6;;O33=6=I98>0B<??4:L2542<F8;986@>1268J473<2D:=8:4N0350>H69>>0B<?74:L25<5<F88?7C?=059M57733G;9>95A1317?K75<=1E=?8;;O31<1=I9;387C?<4:L2752<F89:86@>3368J454<2D:?9:4N0160>H6;?>0B<=84:L27=2<F892?6@>459M51633G;?=95A1507?K73;=1E=9:;;O3711=I9=<?7C?;759M51>33G;?5>5A1468J437<2D:9<:4N0710>H6=:>0B<;;4:L2102<F8?=86@>5668J43?<2D:94=4N040?K70;2D:4>5A1808J75<F;:87C<>3:L166=I::90B?:<;O067>H5>:1E>:=4N3:0?K4>:2D8?6@<029M745<F:887C=<3:L006=I;<90B>8<;O147>H40:1E?4<4N518J1643G>:?6@;229M065<F=>87C::3:L736=I<080B8=4N420?K36;2D>>>5A5218J0243G?>?6@:629M125<F<287C;62:L57>H18:1E:<=4N700?K04;2D=8>5A6418J3043G<<?6@9829M2<4<F>90B:><;O527>H0::1E;>=4N660?K12;2D<:>5A7618J2>43G=2>6@73:L;46=I0890B5<<;O:07>H?<:1E48=4N940?K>0;2D34>5A8808J<5<F0:87C7>3:L:66=I1:90B4:<;O;67>H>>:1E5:=4N8:0?K?>n2DISO[\PHL\TWIW[>1EIYY@RJ68JJHB12DDSNFNNFG1?JM63Y>0\L\[a:RJJZDR[@NSn6^FN^@VWKGJM?1YM@L>6g9QEHYBP]OE_DAA_@d8VDKXMQ^NB^G@N^@`?WCFLV]BHYFPAb9QADBX_@N_DRL9;SGDG@G13[OLOHL7;RCUAAGSI890_DCPCNNOMVOHFVICINE9;RMVVFC03ZX]MAQN7:QQRDJXJ=1X__O;;RQQF1=SQYO>86[?/cnh[hcjWnoeio{os-ueioc&jy~"|nmmmlt^6Z&{kf"!y4^kmmq(uid%_^XKPDQ,PMKAKMVZYE@ [DQ77?P6(jeaTahcPgdlfvdrhz&|j`dj!crvq+wgjdfe{W<S!r`o-v*p3W`dbx#|nm.VQQ@YCX'YBBJBJ_QPJI+RCXh1^_H\PAMKBWf=R[LXTZD]FBMG0?SED12\BIZQ[YQG5?RCF494=7ZKN<0<5?RCF4;437ZKN<283:3=PMH682;5XEC>3:3=PMK6:2;5XEC>1:==PMK686=09;VGA868d3^XBXHQBOEG\Ef=PZ@^NS@AKE^@g?RTN\LU\EIZG_@f8SWOSMV]BHYFPB0f8\LJNFQ'SHO.?.0"PPPD'8';+M^MFI79[WQJNJ>1S_YQHNE`8\ZEHZLUBBKA9;Yfa[Lba3QncS]|fmWgqwlii991Sh`QBakmqR`ttafd:<6Vkm^OjjjtQm{ybcc64aefqe-6.02koho'1(:8eabui!8"46okdsc+7,><imnym%:&8:cg`wg/= 20mij}a)4*<>gcl{k#;$64aefqe->.02koho'9(:8eabui5:546okdsc?5;><imnym1<18:cg`wg;;720mij}a=6=<>gcl{k79364aefqe90902koho37?:8eabui525m6okdsc?=?6902koho39?:8eabuj!:"46okds`+5,><imnyn%<&8:cg`wd/; 20mij}b)6*<>gcl{h#9$64aefqf-0.02kohl'7(:8eabuj!2"46okds`+=,><imnyn1>18:cg`wd;9720mij}b=0=<>gcl{h7?364aefqf92902kohl35?:8eabuj5<546okds`?3;><imnyn161a:cg`wd;13:546okds`?=;543kf`S`kb_fgm[s4X0%*Seagax!ALV@&@mgoymya} 02-5+64W`z886mck`68gime?2nieyk}r69gmkg/8 =0hd`n(0+;?aoii!;;%55kioc+54/?3mcem%?=)99gmkg/9:#37igaa)37-==cagk#=8'7;ekme-71!11oeco'16+;?aoii!;3%55kioc+5</03mcem%<&8:fjjd.58 20hd`n(33*<>bnfh"9>$64dhlb,75.02nbbl&=4(:8`lhf ;?"46jfn`*12,><l`dj$?9&8:fjjd.50 20hd`n(3;*3>bnfh"8%55kioc+75/?3mcem%=>)69gmkg/< =0hd`n(4+4?aoii!<";6jfn`*4-2=cagk#4$94dhlb,</03mcem1>18:fjjd:68720hd`n<03=<>bnfh6:>364dhlb845902nbbl2>4?:8`lhf48?546jfn`>22;><l`dj0<918:fjjd:60720hd`n<0;=3>bnfh6:255kioc?658?3mcem1<>>99gmkg;:;437igaa=00:==cagk7>907;ekme942611oeco327<;?aoii58<255kioc?6=8?3mcem1<6>69gmkg;:720hd`n<22=e>bnfh68=7>18:fjjd:497=0hd`n<2<4?aoii5>5;6jfn`>6:2=cagk7:394dhlb82803mcem1617:fjjd:>6>1oecl'0(58`lhe 8#37igab)33-==cagh#=<'7;ekmf-75!11oecl'12+;?aoij!;?%55kio`+50/?3mcen%?9)99gmkd/9>#37igab)3;-==cagh#=4'8;ekmf-4.02nbbo&=0(:8`lhe ;;"46jfnc*16,><l`di$?=&8:fjjg.5< 20hd`m(37*<>bnfk"9:$64dhla,71.02nbbo&=8(:8`lhe ;3";6jfnc*0-==cagh#?='7;ekmf-56!>1oecl'4(58`lhe <#<7igab)4*3>bnfk"<%:5kio`+<,1<l`di$4'8;ekmf96902nbbo2>0?:8`lhe48;546jfnc>26;><l`di0<=18:fjjg:6<720hd`m<07=<>bnfk6::364dhla841902nbbo2>8?:8`lhe4835;6jfnc>2:==cagh7>=07;ekmf946611oecl323<;?aoij588255kio`?618?3mcen1<:>99gmkd;:?437igab=04:==cagh7>507;ekmf94>6>1oecl32?:8`lhe4::5m6jfnc>05?6902nbbo2<1?58`lhe4:4<7igab=6=3>bnfk6>2:5kio`?2;1<l`di0:08;ekmf9>9?2nbbo26>99gkprf 9#37iazt`*2-<=cg|~j$<>&9:flqqg/98#27iazt`*26,?<lfm%?<)89gkprf 8>"56j`uuc+50/>3me~xl&>6(;8`jssi!;<%45kotvb,4>.12ndyyo'18+;?air|h"9%45kotvb,76.12ndyyo'20+:?air|h"9>$74dnwwe-44!01ocxzn(36*=>bh}}k#>8'6;emvpd.5> 30hb{{a)04-<=cg|~j$?6&9:flqqg/:0#37iazt`*0-<=cg|~j$>>&9:flqqg/;8#37iazt`*7-==cg|~j$8'7;emvpd.1!11ocxzn(6+;?air|h"3%55kotvb,</?3me~xl2?>89gkprf48:556j`uuc?548>3me~xl2>2?;8`jssi5;8245kotvb842912ndyyo314<:?air|h6::374dnwwe970601ocxzn<0:==>bh}}k7=407;emvpd:6601ocxzn<32==>bh}}k7><06;emvpd:5:730hb{{a=00:<=cg|~j0?:19:flqqg;:<427iazt`>12;?<lfm1<8>89gkprf4;2556j`uuc?6<8?3me~xl2=>89gkprf4::5n6j`uuc?74<7601ocxzn<23=<>bh}}k7?364dnwwe92902ndyyo35?:8`jssi5<546j`uuc?3;><lfm1618:flqqg;1720hb{{b)2*<>bh}}h#=$74dnwwf-77!01ocxzm(03*=>bh}}h#=?'6;emvpg.6; 30hb{{b)37-<=cg|~i$<;&9:flqqd/9?#27iaztc*23,?<lfn%?7)89gkpre 83"46j`uu`+6,?<lfn%<?)89gkpre ;;"56j`uu`+67/>3me~xo&=3(;8`jssj!8?%45kotva,73.12ndyyl'27+:?air|k"9;$74dnwwf-4?!01ocxzm(3;*<>bh}}h#?$74dnwwf-57!01ocxzm(23*<>bh}}h#8$64dnwwf-3.02ndyyl'6(:8`jssj!="46j`uu`+<,><lfn%7&8:flqqd;8730hb{{b=33:<=cg|~i0<?19:flqqd;9;427iaztc>27;?<lfn1?;>89gkpre48?556j`uu`?538>3me~xo2>7?;8`jssj5;3245kotva84?902ndyyl31?;8`jssj58;245kotva877912ndyyl323<:?air|k69?374dnwwf943601ocxzm<37==>bh}}h7>;06;emvpg:5?730hb{{b=0;:<=cg|~i0?718:flqqd;:730hb{{b=13:g=cg|~i0>?50?;8`jssj59:255kotva868?3me~xo2;>99gkpre4<437iaztc>5:==cg|~i0:07;emvpg:?611ocxzm<8<;?`bnn;dlh>5jn`18akd?3gmhnxgcdg9seqrbzgUi`fQbel0b?ugs|lxeSobd_lgn(gjlWdofSjka_w0\<)HHFL&ECCK<769seqrbzgUi`fQbel.ahnYjmdUlicQy2^:/fYoizUyijmjb<2/gZnf{Vxnknkn=1.`[hcjW}s{i0<#c^rqmhYsqyo6=!mPshljpdYqie7; nQ}e`f\slbs`Vh6??"l_sgb`Zqnl}bTm0==,b]gmvgedlU|m`Pbit\gjjk59&hSd`ft^djh`Yiido6bbQlod]emicXdfkoii"l_vpjp`YjgmoTn0@@_BJBJBC+kV}yeykPmnff[d;IGVICMCIJ,b]nq}YwayogeckPsucdav;7$jUcm~Qbel]lqqvr|Vxnk~Qm=1.`[iiflVceeyQiimg>4)eX`hyTahcPotvsqqYumnyTm0>#c^uqmqcXllzdRl21107(fYpz`~nSikti]b9465<%iTdl}Psrpa95*dWakxS`{w_nwwtprXzlmxSo3?,b]kevYt{{k6<!mPh`q\ip~Xg|~{yyQ}efq\e86+kVkohoPwhfwl877$jUjhi|m_vkgpm;68%iThhhnumv\`drf59&hSx}j_da`95*dWhflcg{hl?2(fYcazki`hQxasl\fmpXzhdli0>#c^uqmqcX`ndRl233.`[rtn|lU|eizg_`?06)eXzlkoSikti]a9465<%iT~hok_egspmYf58:98!mPbxvf[vo}m43'oR}fm^alhiotafdToeklk<COH)eXkfgfccQllj?3(fYr{lUym`l>6cufvZtt|Vhcz0>#c^ufeZqnl}b6=!mPh`q\akd:9%iTdl}Peoc>5)eXlhT{dj{h<3/gZunf`~iS{oc=1.`khvhfldScobe<rbpqcufVhggRcjm-a\qvcXjp~nSzkm=1.`[pubWksiRyja<2/gZstmVnnjl{ct^fbpd;6$t8=7}o{tdpm[gjlWdofSobd_lgn[bciW8T4Rv|t^35?wc`klk=7khcd`4?vdn|lxy86}|r`68wvte>2}nm%>&8:ufe96=87<0{ho30?48s`d/8 20{hl30;2=2>qbj5:5qMN4`08DE~62O0?6<u\478072<328994km>:23`76}i:991=6`=0587?!4793;mh6s\458072<328994km>:23`76=T9:91?>o50;306=`d939:o>=4S56976g=83;8>5hl1;12g60<l:9i6=4>:0yP03<4;>0?6<==8ga2>67d;:1}X<k<:182>4<>jrY?:7=<7;69564?nj;1?<m<3:&2a`<6;=1]>=<52zw270<63|;8:7>4}%3g3?7>3k98n7>59`80><g|@8oh7W=l:9y:>d<22?0:=7?=:e8f>x"6m108?o5+212967`<a:936=44i21:>5<<a:>?6=4+1e;9713<f8n36=54i264>5<#9m31?964n0f;>5=<a;:n6=4+1e;964><f8n36=54i32g>5<#9m31><64n0f;>4=<a;:h6=4+1e;964><f8n36?54i32a>5<#9m31><64n0f;>6=<a;:j6=4+1e;964><f8n36954i32:>5<#9m31><64n0f;>0=<a;:36=4+1e;964><f8n36;54i324>5<#9m31><64n0f;>2=<a;:=6=4+1e;964><f8n36554i326>5<#9m31><64n0f;><=<a;886=4+1e;967b<f8n36=54i301>5<#9m31>?j4n0f;>4=<a;8:6=4+1e;967b<f8n36?54i303>5<#9m31>?j4n0f;>6=<a;;m6=4+1e;967b<f8n36954i33f>5<#9m31>?j4n0f;>0=<a;;o6=4+1e;967b<f8n36;54i33`>5<#9m31>?j4n0f;>2=<a;;i6=4+1e;967b<f8n36554i33b>5<#9m31>?j4n0f;><=<g;in6=4+1e;96`b<f8n36=54o3ag>5<#9m31>hj4n0f;>4=<g;ii6=4+1e;96`b<f8n36?54o3ab>5<#9m31>hj4n0f;>6=<g;i26=4+1e;96`b<f8n36954o3a;>5<#9m31>hj4n0f;>0=<g;i<6=4+1e;96`b<f8n36;54o3a5>5<#9m31>hj4n0f;>2=<g;i>6=4+1e;96`b<f8n36554o3a7>5<#9m31>hj4n0f;><=<g;i86=4+1e;96`b<f8n36l54o3a1>5<#9m31>hj4n0f;>g=<g;i;6=4+1e;96`b<f8n36n54o3`e>5<#9m31>hj4n0f;>a=<g;hn6=4+1e;96`b<f8n36h54o3`g>5<#9m31>hj4n0f;>c=<g;hh6=4+1e;96`b<f8n36<>4;n0af?6=,8n26?kk;o3g<?7632e9nl4?:%3g=?4bl2d:h54>2:9l6g?=83.:h44=ee9m5a>=9:10c?l7:18'5a?=:ln0b<j7:068?j4e?3:1(<j6:3gg?k7c03;>76a=d583>!7c138nh6`>d9822>=h:m91<7*>d881aa=i9m21=:54o3f1>5<#9m31>hj4n0f;>4><3f8o=7>5$0f:>7cc3g;o47?6;:m1`5<72-;o57<jd:l2`=<6i21d>nh50;&2`<<5mm1e=i651c98k7ed290/=i752df8j4b?28i07b<l1;29 4b>2;oo7c?k8;3g?>i5j?0;6)?k9;0f`>h6l10:i65`2c794?"6l009ii5a1e:95c=<g::m6=4+1e;977c<f8n36=54o22f>5<#9m31??k4n0f;>4=<g::h6=4+1e;977c<f8n36?54o22a>5<#9m31??k4n0f;>6=<g::j6=4+1e;977c<f8n36954o22:>5<#9m31??k4n0f;>0=<g::36=4+1e;977c<f8n36;54o224>5<#9m31??k4n0f;>2=<g::=6=4+1e;977c<f8n36554o226>5<#9m31??k4n0f;><=<g::?6=4+1e;977c<f8n36l54o220>5<#9m31??k4n0f;>g=<g:::6=4+1e;977c<f8n36n54o223>5<#9m31??k4n0f;>a=<g;lm6=4+1e;977c<f8n36h54o3df>5<#9m31??k4n0f;>c=<g;lo6=4+1e;977c<f8n36<>4;n0eg?6=,8n26><j;o3g<?7632e9jo4?:%3g=?55m2d:h54>2:9l6cg=83.:h44<2d9m5a>=9:10c?h6:18'5a?=;;o0b<j7:068?j4a03:1(<j6:20f?k7c03;>76a<1483>!7c1399i6`>d9822>=h;8>1<7*>d8806`=i9m21=:54o230>5<#9m31??k4n0f;>4><3f9:>7>5$0f:>64b3g;o47?6;:m054<72-;o57==e:l2`=<6i21d?<>50;&2`<<4:l1e=i651c98k66c290/=i7533g8j4b?28i07b=?2;29 4b>2:8n7c?k8;3g?>i5n>0;6)?k9;11a>h6l10:i65`2g494?"6l008>h5a1e:95c=<a;9;6=44i312>5<<a;>h6=4+1e;963d<f8n36=54i36a>5<#9m31>;l4n0f;>4=<a;>26=4+1e;963d<f8n36?54i36;>5<#9m31>;l4n0f;>6=<a;><6=4+1e;963d<f8n36954i365>5<#9m31>;l4n0f;>0=<a;>>6=4+1e;963d<f8n36;54i367>5<#9m31>;l4n0f;>2=<a;>86=4+1e;963d<f8n36554i361>5<#9m31>;l4n0f;><=<a;>:6=4+1e;963d<f8n36l54i363>5<#9m31>;l4n0f;>g=<a;9n6=4+1e;963d<f8n36n54i31g>5<#9m31>;l4n0f;>a=<a;9h6=4+1e;963d<f8n36h54i31a>5<#9m31>;l4n0f;>c=<a;9j6=4+1e;963d<f8n36<>4;h00=?6=,8n26?8m;o3g<?7632c9?54?:%3g=?41j2d:h54>2:9j661=83.:h44=6c9m5a>=9:10e?=9:18'5a?=:?h0b<j7:068?l44=3:1(<j6:34a?k7c03;>76g=5383>!7c138=n6`>d9822>=n:<;1<7*>d8812g=i9m21=:54i373>5<#9m31>;l4n0f;>4><3`8?j7>5$0f:>70e3g;o47?6;:k10`<72-;o57<9b:l2`=<6i21b>9j50;&2`<<5>k1e=i651c98m72f290/=i7527`8j4b?28i07d<<f;29 4b>2;<i7c?k8;3g?>o5;=0;6)?k9;05f>h6l10:i65f22194?"6l009:o5a1e:95c=<a;2o6=4+1e;96de<f8n36=54i3:`>5<#9m31>lm4n0f;>4=<a;2j6=4+1e;96de<f8n36?54i3::>5<#9m31>lm4n0f;>6=<a;236=4+1e;96de<f8n36954i3:4>5<#9m31>lm4n0f;>0=<a;2=6=4+1e;96de<f8n36;54i3:6>5<#9m31>lm4n0f;>2=<a;2?6=4+1e;96de<f8n36554i3:0>5<#9m31>lm4n0f;><=<a;296=4+1e;96de<f8n36l54i3:2>5<#9m31>lm4n0f;>g=<a;=m6=4+1e;96de<f8n36n54i35f>5<#9m31>lm4n0f;>a=<a;=o6=4+1e;96de<f8n36h54i35`>5<#9m31>lm4n0f;>c=<a;=i6=4+1e;96de<f8n36<>4;h04e?6=,8n26?ol;o3g<?7632c9;44?:%3g=?4fk2d:h54>2:9j62>=83.:h44=ab9m5a>=9:10e?98:18'5a?=:hi0b<j7:068?l40>3:1(<j6:3c`?k7c03;>76g=9283>!7c138jo6`>d9822>=n:081<7*>d881ef=i9m21=:54i3;2>5<#9m31>lm4n0f;>4><3`82<7>5$0f:>7gd3g;o47?6;:k1<c<72-;o57<nc:l2`=<6i21b>5k50;&2`<<5ij1e=i651c98m7>e290/=i752`a8j4b?28i07d<70;29 4b>2;kh7c?k8;3g?>o5?<0;6)?k9;0bg>h6l10:i65f26694?"6l009mn5a1e:95c=<j8oo6=4>:183M7bk2.:i54>ee9l5a0=831vnh;50;394?6|@8oh7)?j8;g6?jc32900qo=m:18b4?5=1kqC=hm4Z2a955}>2h0>6;4>1;31>a<b28;1=?46:`86>3<c2l0v(<k7:21f?!262:9h7):::21g?!7c93;o96g<3983>>o4;00;66g<4383>>o4<:0;66g<3g83>>o4<90;66g<4583>!7c139?96`>d983?>o4<>0;6)?k9;17<>h6l10;76g=0d83>!7c138:46`>d983?>o58m0;6)?k9;02<>h6l10:76g=0b83>!7c138:46`>d981?>o58k0;6)?k9;02<>h6l10876g=0`83>!7c138:46`>d987?>o5800;6)?k9;02<>h6l10>76g=0983>!7c138:46`>d985?>o58>0;6)?k9;02<>h6l10<76g=0783>!7c138:46`>d98;?>o58<0;6)?k9;02<>h6l10276g=2283>!7c1389h6`>d983?>o5:;0;6)?k9;01`>h6l10:76g=2083>!7c1389h6`>d981?>o5:90;6)?k9;01`>h6l10876g=1g83>!7c1389h6`>d987?>o59l0;6)?k9;01`>h6l10>76g=1e83>!7c1389h6`>d985?>o59j0;6)?k9;01`>h6l10<76g=1c83>!7c1389h6`>d98;?>o59h0;6)?k9;01`>h6l10276a<4083>>i5kl0;6)?k9;0f`>h6l10;76a=ce83>!7c138nh6`>d982?>i5kk0;6)?k9;0f`>h6l10976a=c`83>!7c138nh6`>d980?>i5k00;6)?k9;0f`>h6l10?76a=c983>!7c138nh6`>d986?>i5k>0;6)?k9;0f`>h6l10=76a=c783>!7c138nh6`>d984?>i5k<0;6)?k9;0f`>h6l10376a=c583>!7c138nh6`>d98:?>i5k:0;6)?k9;0f`>h6l10j76a=c383>!7c138nh6`>d98a?>i5k90;6)?k9;0f`>h6l10h76a=bg83>!7c138nh6`>d98g?>i5jl0;6)?k9;0f`>h6l10n76a=be83>!7c138nh6`>d98e?>i5jj0;6)?k9;0f`>h6l10:<65`2c`94?"6l009ii5a1e:954=<g;hj6=4+1e;96`b<f8n36<<4;n0a=?6=,8n26?kk;o3g<?7432e9n54?:%3g=?4bl2d:h54>4:9l6g1=83.:h44=ee9m5a>=9<10c?j;:18'5a?=:ln0b<j7:048?j4c;3:1(<j6:3gg?k7c03;<76a=d383>!7c138nh6`>d982<>=h:m;1<7*>d881aa=i9m21=454o3f3>5<#9m31>hj4n0f;>4g<3f8hj7>5$0f:>7cc3g;o47?m;:m1gf<72-;o57<jd:l2`=<6k21d>n?50;&2`<<5mm1e=i651e98k7d1290/=i752df8j4b?28o07b<m5;29 4b>2;oo7c?k8;3e?>i48o0;6)?k9;11a>h6l10;76a<0d83>!7c1399i6`>d982?>i48j0;6)?k9;11a>h6l10976a<0c83>!7c1399i6`>d980?>i48h0;6)?k9;11a>h6l10?76a<0883>!7c1399i6`>d986?>i4810;6)?k9;11a>h6l10=76a<0683>!7c1399i6`>d984?>i48?0;6)?k9;11a>h6l10376a<0483>!7c1399i6`>d98:?>i48=0;6)?k9;11a>h6l10j76a<0283>!7c1399i6`>d98a?>i4880;6)?k9;11a>h6l10h76a<0183>!7c1399i6`>d98g?>i5no0;6)?k9;11a>h6l10n76a=fd83>!7c1399i6`>d98e?>i5nm0;6)?k9;11a>h6l10:<65`2ga94?"6l008>h5a1e:954=<g;li6=4+1e;977c<f8n36<<4;n0ee?6=,8n26><j;o3g<?7432e9j44?:%3g=?55m2d:h54>4:9l6c>=83.:h44<2d9m5a>=9<10c>?::18'5a?=;;o0b<j7:048?j56<3:1(<j6:20f?k7c03;<76a<1283>!7c1399i6`>d982<>=h;881<7*>d8806`=i9m21=454o232>5<#9m31??k4n0f;>4g<3f9:<7>5$0f:>64b3g;o47?m;:m04a<72-;o57==e:l2`=<6k21d?=<50;&2`<<4:l1e=i651e98k7`0290/=i7533g8j4b?28o07b<i6;29 4b>2:8n7c?k8;3e?>o5;90;66g=3083>>o5<j0;6)?k9;05f>h6l10;76g=4c83>!7c138=n6`>d982?>o5<00;6)?k9;05f>h6l10976g=4983>!7c138=n6`>d980?>o5<>0;6)?k9;05f>h6l10?76g=4783>!7c138=n6`>d986?>o5<<0;6)?k9;05f>h6l10=76g=4583>!7c138=n6`>d984?>o5<:0;6)?k9;05f>h6l10376g=4383>!7c138=n6`>d98:?>o5<80;6)?k9;05f>h6l10j76g=4183>!7c138=n6`>d98a?>o5;l0;6)?k9;05f>h6l10h76g=3e83>!7c138=n6`>d98g?>o5;j0;6)?k9;05f>h6l10n76g=3c83>!7c138=n6`>d98e?>o5;h0;6)?k9;05f>h6l10:<65f22;94?"6l009:o5a1e:954=<a;936=4+1e;963d<f8n36<<4;h003?6=,8n26?8m;o3g<?7432c9?;4?:%3g=?41j2d:h54>4:9j663=83.:h44=6c9m5a>=9<10e?;=:18'5a?=:?h0b<j7:048?l4293:1(<j6:34a?k7c03;<76g=5183>!7c138=n6`>d982<>=n:=l1<7*>d8812g=i9m21=454i36f>5<#9m31>;l4n0f;>4g<3`8?h7>5$0f:>70e3g;o47?m;:k10d<72-;o57<9b:l2`=<6k21b>>h50;&2`<<5>k1e=i651e98m753290/=i7527`8j4b?28o07d<<3;29 4b>2;<i7c?k8;3e?>o50m0;6)?k9;0bg>h6l10;76g=8b83>!7c138jo6`>d982?>o50h0;6)?k9;0bg>h6l10976g=8883>!7c138jo6`>d980?>o5010;6)?k9;0bg>h6l10?76g=8683>!7c138jo6`>d986?>o50?0;6)?k9;0bg>h6l10=76g=8483>!7c138jo6`>d984?>o50=0;6)?k9;0bg>h6l10376g=8283>!7c138jo6`>d98:?>o50;0;6)?k9;0bg>h6l10j76g=8083>!7c138jo6`>d98a?>o5?o0;6)?k9;0bg>h6l10h76g=7d83>!7c138jo6`>d98g?>o5?m0;6)?k9;0bg>h6l10n76g=7b83>!7c138jo6`>d98e?>o5?k0;6)?k9;0bg>h6l10:<65f26c94?"6l009mn5a1e:954=<a;=26=4+1e;96de<f8n36<<4;h04<?6=,8n26?ol;o3g<?7432c9;:4?:%3g=?4fk2d:h54>4:9j620=83.:h44=ab9m5a>=9<10e?7<:18'5a?=:hi0b<j7:048?l4>:3:1(<j6:3c`?k7c03;<76g=9083>!7c138jo6`>d982<>=n:0:1<7*>d881ef=i9m21=454i3:e>5<#9m31>lm4n0f;>4g<3`83i7>5$0f:>7gd3g;o47?m;:k1<g<72-;o57<nc:l2`=<6k21b>5>50;&2`<<5ij1e=i651e98m712290/=i752`a8j4b?28o07d<84;29 4b>2;kh7c?k8;3e?>i5;;0;66l>fg83>4<729q/=h65e49K5cc<@8oh7bk;:188yg7bi3:1o?4?:1y'5`>=9mk0D<hj;I3fg>\4k3ip;765b;a956<6<3;>6<85f;33>41=910vbo:50:lg2?6<,88n6?5+13d96>"b>390(h953:&f<?5<,l31?6*ja;18 `d=;2.:i<4j3:&2a1<53-on6>5+eg80?!`72:1/j<4<;%d1>6=#n:087)h;:29'b0<43-l=6>5+f680?!`?2:1/j44<;%db>6=#nk087)hl:29'ba<43-ln6>5+fg80?!778390(<>>:29'554=;2.:<>4<;%330?5<,8:>6>5+11497>"68>087)??8;18 46>2:1/==o53:&24g<43-;;o7=4$02g>6=#99o1?6*>0g80?!768390(<?>:29'544=;2.:=>4<;%320?5<,8;>6>5+10497>"69>087)?>8;18 47>2:1/=<o53:&25g<43-;:o7=4$03g>6=#98o1?6*>1g80?!758390(<<>:29'574=;2.:>>4<;%310?5<,88>6>5+13497>"6:>087)?=8;18 44>2:1/=?o53:&26g<43-;9o7=4$00g>6=#9::1=i=4$012>`5<,8996h=4$0fa>4b43-;oo7?k3:l2`a<6:2d:hh4>2:&2a7<4i2.no7=4$df97>"6n00:h95+1gc95a2<f8li6<<4n0d`>44<,8o>6?5f3e83>>o4m3:17d:=:188m15=831bi<4?::k2`c<722c:i=4?::kf6?6=3`;n:7>5;h3f3?6=3f9m6=44o5294?=n:90;6)?k9;3e?k7c03:07d?j:18'5a?=9o1e=i651:9j5a<72-;o57?i;o3g<?4<3`;h6=4+1e;95c=i9m21?65f1c83>!7c13;m7c?k8;68?l4>290/=i751g9m5a>==21b>54?:%3g=?7a3g;o4784;h04>5<#9m31=k5a1e:93>=n:?0;6)?k9;3e?k7c03207d<::18'5a?=9o1e=i659:9j61<72-;o57?i;o3g<?g<3`886=4+1e;95c=i9m21n65f2383>!7c13;m7c?k8;a8?l46290/=i751g9m5a>=l21b=l4?:%3g=?7a3g;o47k4;h13>5<#9m31>k5a1e:94>=n:l0;6)?k9;0e?k7c03;07d<k:18'5a?=:o1e=i652:9j6f<72-;o57<i;o3g<?5<3`8i6=4+1e;96c=i9m21865f3883>!7c138m7c?k8;78?l5?290/=i752g9m5a>=>21b?:4?:%3g=?4a3g;o4794;h15>5<#9m31>k5a1e:9<>=n;<0;6)?k9;0e?k7c03307d=;:18'5a?=:o1e=i65a:9j76<72-;o57<i;o3g<?d<3`996=4+1e;96c=i9m21o65f3083>!7c138m7c?k8;f8?l4f290/=i752g9m5a>=m21b:=4?:%3g=?3a3g;o47>4;h7f>5<#9m319k5a1e:95>=n=j0;6)?k9;7e?k7c03807d;m:18'5a?==o1e=i653:9j1d<72-;o57;i;o3g<?2<3`?26=4+1e;91c=i9m21965f5983>!7c13?m7c?k8;48?l30290/=i755g9m5a>=?21b9;4?:%3g=?3a3g;o4764;h76>5<#9m319k5a1e:9=>=n==0;6)?k9;7e?k7c03k07d;<:18'5a?==o1e=i65b:9j14<72-;o57;i;o3g<?e<3`?;6=4+1e;91c=i9m21h65f4g83>!7c13?m7c?k8;g8?l2b290/=i755g9m5a>=n21b8i4?:%3g=?3a3g;o47??;:k7g?6=,8n268h4n0f;>47<3`>i6=4+1e;91c=i9m21=?54i5c94?"6l00>j6`>d9827>=n<00;6)?k9;7e?k7c03;?76g;8;29 4b>2<l0b<j7:078?l00290/=i755g9m5a>=9?10e;850;&2`<<2n2d:h54>7:9j20<72-;o57;i;o3g<?7?32c=87>5$0f:>0`<f8n36<74;h40>5<#9m319k5a1e:95d=<a?81<7*>d886b>h6l10:n65f6083>!7c13?m7c?k8;3`?>o2l3:1(<j6:4d8j4b?28n07d;=:18'5a?==o1e=i651d98m11=83.:h44:f:l2`=<6n21b4<4?:%3g=?>73g;o47>4;h5e>5<#9m314=5a1e:95>=n?m0;6)?k9;:3?k7c03807d9l:18'5a?=091e=i653:9j3g<72-;o576?;o3g<?2<3`=j6=4+1e;9<5=i9m21965f7883>!7c132;7c?k8;48?l1?290/=i75819m5a>=?21b;:4?:%3g=?>73g;o4764;h55>5<#9m314=5a1e:9=>=n?<0;6)?k9;:3?k7c03k07d9;:18'5a?=091e=i65b:9j37<72-;o576?;o3g<?e<3`=:6=4+1e;9<5=i9m21h65f7183>!7c132;7c?k8;g8?l0a290/=i75819m5a>=n21b:h4?:%3g=?>73g;o47??;:k5`?6=,8n265>4n0f;>47<3`<h6=4+1e;9<5=i9m21=?54i7`94?"6l003<6`>d9827>=n>h0;6)?k9;:3?k7c03;?76g99;29 4b>21:0b<j7:078?l>?290/=i75819m5a>=9?10e5950;&2`<<?82d:h54>7:9j<3<72-;o576?;o3g<?7?32c397>5$0f:>=6<f8n36<74;h:7>5<#9m314=5a1e:95d=<a191<7*>d88;4>h6l10:n65f8383>!7c132;7c?k8;3`?>o0m3:1(<j6:928j4b?28n07d9<:18'5a?=091e=i651d98m3>=83.:h4470:l2`=<6n21b4i4?:%3g=?>d3g;o47>4;h:a>5<#9m314n5a1e:95>=n0h0;6)?k9;:`?k7c03807d66:18'5a?=0j1e=i653:9j=7<72-;o577>;o3g<?6<3`3;6=4+1e;9=4=i9m21=65f8g83>!7c133:7c?k8;08?l>b290/=i75909m5a>=;21b=k=50;&2`<<6n;1e=i650:9j5c7=83.:h44>f39m5a>=921b=k>50;&2`<<6n;1e=i652:9j5``=83.:h44>f39m5a>=;21b=k650;&2`<<6n>1e=i650:9j5c0=83.:h44>f69m5a>=921b=k;50;&2`<<6n>1e=i652:9j5c2=83.:h44>f69m5a>=;21dmn4?:%3g=?ge3g;o47>4;ncb>5<#9m31mo5a1e:95>=hi10;6)?k9;ca?k7c03807bo8:18'5a?=ik1e=i653:9le3<72-;o57om;o3g<?2<3fk>6=4+1e;9eg=i9m21965`a583>!7c13ki7c?k8;48?jg4290/=i75ac9m5a>=?21dm?4?:%3g=?ge3g;o4764;nc2>5<#9m31mo5a1e:9=>=hi90;6)?k9;ca?k7c03k07b7i:18'5a?=ik1e=i65b:9l=a<72-;o57om;o3g<?e<3f3h6=4+1e;9eg=i9m21h65`9c83>!7c13ki7c?k8;g8?j?f290/=i75ac9m5a>=n21d544?:%3g=?ge3g;o47??;:m:<?6=,8n26ll4n0f;>47<3f3<6=4+1e;9eg=i9m21=?54o8494?"6l00jn6`>d9827>=h1<0;6)?k9;ca?k7c03;?76a64;29 4b>2hh0b<j7:078?jd4290/=i75ac9m5a>=9?10co<50;&2`<<fj2d:h54>7:9lf4<72-;o57om;o3g<?7?32ei<7>5$0f:>dd<f8n36<74;nce>5<#9m31mo5a1e:95d=<gho1<7*>d88bf>h6l10:n65`ae83>!7c13ki7c?k8;3`?>if13:1(<j6:``8j4b?28n07b7j:18'5a?=ik1e=i651d98k<5=83.:h44nb:l2`=<6n21doh4?:%3g=?ec3g;o47>4;na`>5<#9m31oi5a1e:95>=hkh0;6)?k9;ag?k7c03807bm6:18'5a?=km1e=i653:9lg=<72-;o57mk;o3g<?2<3fi<6=4+1e;9ga=i9m21965`c783>!7c13io7c?k8;48?je2290/=i75ce9m5a>=?21do94?:%3g=?ec3g;o4764;na0>5<#9m31oi5a1e:9=>=hk;0;6)?k9;ag?k7c03k07bm>:18'5a?=km1e=i65b:9lfc<72-;o57mk;o3g<?e<3fhn6=4+1e;9ga=i9m21h65`be83>!7c13io7c?k8;g8?jdd290/=i75ce9m5a>=n21dno4?:%3g=?ec3g;o47??;:mae?6=,8n26nj4n0f;>47<3fh26=4+1e;9ga=i9m21=?54oc:94?"6l00hh6`>d9827>=hj>0;6)?k9;ag?k7c03;?76am6;29 4b>2jn0b<j7:078?jb2290/=i75ce9m5a>=9?10ci:50;&2`<<dl2d:h54>7:9l`6<72-;o57mk;o3g<?7?32eo>7>5$0f:>fb<f8n36<74;nf2>5<#9m31oi5a1e:95d=<gm:1<7*>d88``>h6l10:n65`cg83>!7c13io7c?k8;3`?>idj3:1(<j6:bf8j4b?28n07bm?:18'5a?=km1e=i651d98kg3=83.:h44ld:l2`=<6n21dho4?:%3g=?bf3g;o47>4;nf:>5<#9m31hl5a1e:95>=hl10;6)?k9;fb?k7c03807bj8:18'5a?=lh1e=i653:9la5<72-;o57ji;o3g<?6<3fnn6=4+1e;9`c=i9m21=65`de83>!7c13nm7c?k8;08?jbd290/=i75dg9m5a>=;21vn<k6:18`6?6=8r.:i54>d`9K5cc<@8oh7W=l:by4>=<e2j0:?7?;:07953<a28:1=:4>8;mf1<73gn=6=5+13g96>"6:o097)k9:29'a2<43-o36>5+e880?!cf2:1/io4<;%3f5?c43-;n87<4$dg97>"bn390(k>53:&e5?5<,o81?6*i3;18 c2=;2.m97=4$g497>"a?390(k653:&e=?5<,ok1?6*ib;18 ce=;2.mh7=4$gg97>"an390(<>?:29'557=;2.:<?4<;%337?5<,8:?6>5+11797>"68?087)??7;18 46?2:1/==753:&24d<43-;;n7=4$02`>6=#99n1?6*>0d80?!77n390(<??:29'547=;2.:=?4<;%327?5<,8;?6>5+10797>"69?087)?>7;18 47?2:1/=<753:&25d<43-;:n7=4$03`>6=#98n1?6*>1d80?!76n390(<<?:29'577=;2.:>?4<;%317?5<,88?6>5+13797>"6:?087)?=7;18 44?2:1/=?753:&26d<43-;9n7=4$00`>6=#9;n1?6*>3182`6=#9:;1i>5+1209a6=#9mh1=i=4$0f`>4b43g;oh7?=;o3ga?753-;n>7=n;%g`>6=#mm087)?i9;3g0>"6nh0:h95a1g`957=i9oi1=?5+1d796>o4l3:17d=j:188m14=831b8>4?::kf5?6=3`;oj7>5;h3f4?6=3`o96=44i0g5>5<<a8o<6=44o2d94?=h<90;66g=0;29 4b>28l0b<j7:198m4c=83.:h44>f:l2`=<632c:h7>5$0f:>4`<f8n36?54i0a94?"6l00:j6`>d980?>o6j3:1(<j6:0d8j4b?2=10e?750;&2`<<6n2d:h54:;:k1<?6=,8n26<h4n0f;>3=<a;=1<7*>d882b>h6l10<76g=6;29 4b>28l0b<j7:998m73=83.:h44>f:l2`=<>32c987>5$0f:>4`<f8n36l54i3194?"6l00:j6`>d98a?>o5:3:1(<j6:0d8j4b?2j10e??50;&2`<<6n2d:h54k;:k2e?6=,8n26<h4n0f;>`=<a::1<7*>d881b>h6l10;76g=e;29 4b>2;l0b<j7:098m7b=83.:h44=f:l2`=<532c9o7>5$0f:>7`<f8n36>54i3`94?"6l009j6`>d987?>o413:1(<j6:3d8j4b?2<10e>650;&2`<<5n2d:h549;:k03?6=,8n26?h4n0f;>2=<a:<1<7*>d881b>h6l10376g<5;29 4b>2;l0b<j7:898m62=83.:h44=f:l2`=<f32c8?7>5$0f:>7`<f8n36o54i2094?"6l009j6`>d98`?>o493:1(<j6:3d8j4b?2m10e?o50;&2`<<5n2d:h54j;:k54?6=,8n268h4n0f;>5=<a<o1<7*>d886b>h6l10:76g:c;29 4b>2<l0b<j7:398m0d=83.:h44:f:l2`=<432c>m7>5$0f:>0`<f8n36954i4;94?"6l00>j6`>d986?>o203:1(<j6:4d8j4b?2?10e8950;&2`<<2n2d:h548;:k62?6=,8n268h4n0f;>==<a<?1<7*>d886b>h6l10276g:4;29 4b>2<l0b<j7:`98m05=83.:h44:f:l2`=<e32c>=7>5$0f:>0`<f8n36n54i4294?"6l00>j6`>d98g?>o3n3:1(<j6:4d8j4b?2l10e9k50;&2`<<2n2d:h54i;:k7`?6=,8n268h4n0f;>46<3`>h6=4+1e;91c=i9m21=<54i5`94?"6l00>j6`>d9826>=n<h0;6)?k9;7e?k7c03;876g;9;29 4b>2<l0b<j7:068?l2?290/=i755g9m5a>=9<10e;950;&2`<<2n2d:h54>6:9j23<72-;o57;i;o3g<?7032c=97>5$0f:>0`<f8n36<64;h47>5<#9m319k5a1e:95<=<a?91<7*>d886b>h6l10:m65f6383>!7c13?m7c?k8;3a?>o193:1(<j6:4d8j4b?28i07d;k:18'5a?==o1e=i651e98m04=83.:h44:f:l2`=<6m21b8:4?:%3g=?3a3g;o47?i;:k;5?6=,8n265>4n0f;>5=<a>l1<7*>d88;4>h6l10:76g8d;29 4b>21:0b<j7:398m2e=83.:h4470:l2`=<432c<n7>5$0f:>=6<f8n36954i6c94?"6l003<6`>d986?>o013:1(<j6:928j4b?2?10e:650;&2`<<?82d:h548;:k43?6=,8n265>4n0f;>==<a><1<7*>d88;4>h6l10276g85;29 4b>21:0b<j7:`98m22=83.:h4470:l2`=<e32c<>7>5$0f:>=6<f8n36n54i6394?"6l003<6`>d98g?>o083:1(<j6:928j4b?2l10e;h50;&2`<<?82d:h54i;:k5a?6=,8n265>4n0f;>46<3`<o6=4+1e;9<5=i9m21=<54i7a94?"6l003<6`>d9826>=n>k0;6)?k9;:3?k7c03;876g9a;29 4b>21:0b<j7:068?l0>290/=i75819m5a>=9<10e5650;&2`<<?82d:h54>6:9j<2<72-;o576?;o3g<?7032c3:7>5$0f:>=6<f8n36<64;h:6>5<#9m314=5a1e:95<=<a1>1<7*>d88;4>h6l10:m65f8283>!7c132;7c?k8;3a?>o?:3:1(<j6:928j4b?28i07d9j:18'5a?=091e=i651e98m25=83.:h4470:l2`=<6m21b:54?:%3g=?>73g;o47?i;:k;`?6=,8n265m4n0f;>5=<a1h1<7*>d88;g>h6l10:76g7a;29 4b>21i0b<j7:398m=?=83.:h447c:l2`=<432c2>7>5$0f:><7<f8n36=54i8294?"6l002=6`>d982?>o?n3:1(<j6:838j4b?2;10e5k50;&2`<<>92d:h54<;:k2b6<72-;o57?i2:l2`=<732c:j<4?:%3g=?7a:2d:h54>;:k2b5<72-;o57?i2:l2`=<532c:ik4?:%3g=?7a:2d:h54<;:k2b=<72-;o57?i7:l2`=<732c:j;4?:%3g=?7a?2d:h54>;:k2b0<72-;o57?i7:l2`=<532c:j94?:%3g=?7a?2d:h54<;:mbg?6=,8n26ll4n0f;>5=<ghk1<7*>d88bf>h6l10:76an8;29 4b>2hh0b<j7:398kd1=83.:h44nb:l2`=<432ej:7>5$0f:>dd<f8n36954o`794?"6l00jn6`>d986?>if<3:1(<j6:``8j4b?2?10cl=50;&2`<<fj2d:h548;:mb6?6=,8n26ll4n0f;>==<gh;1<7*>d88bf>h6l10276an0;29 4b>2hh0b<j7:`98k<`=83.:h44nb:l2`=<e32e2h7>5$0f:>dd<f8n36n54o8a94?"6l00jn6`>d98g?>i>j3:1(<j6:``8j4b?2l10c4o50;&2`<<fj2d:h54i;:m:=?6=,8n26ll4n0f;>46<3f336=4+1e;9eg=i9m21=<54o8594?"6l00jn6`>d9826>=h1?0;6)?k9;ca?k7c03;876a65;29 4b>2hh0b<j7:068?j?3290/=i75ac9m5a>=9<10co=50;&2`<<fj2d:h54>6:9lf7<72-;o57om;o3g<?7032ei=7>5$0f:>dd<f8n36<64;n`3>5<#9m31mo5a1e:95<=<ghl1<7*>d88bf>h6l10:m65`ad83>!7c13ki7c?k8;3a?>ifl3:1(<j6:``8j4b?28i07bo6:18'5a?=ik1e=i651e98k<c=83.:h44nb:l2`=<6m21d5>4?:%3g=?ge3g;o47?i;:m`a?6=,8n26nj4n0f;>5=<gji1<7*>d88``>h6l10:76ala;29 4b>2jn0b<j7:398kf?=83.:h44ld:l2`=<432eh47>5$0f:>fb<f8n36954ob594?"6l00hh6`>d986?>id>3:1(<j6:bf8j4b?2?10cn;50;&2`<<dl2d:h548;:m`0?6=,8n26nj4n0f;>==<gj91<7*>d88``>h6l10276al2;29 4b>2jn0b<j7:`98kf7=83.:h44ld:l2`=<e32eij7>5$0f:>fb<f8n36n54ocg94?"6l00hh6`>d98g?>iel3:1(<j6:bf8j4b?2l10com50;&2`<<dl2d:h54i;:maf?6=,8n26nj4n0f;>46<3fhj6=4+1e;9ga=i9m21=<54oc;94?"6l00hh6`>d9826>=hj10;6)?k9;ag?k7c03;876am7;29 4b>2jn0b<j7:068?jd1290/=i75ce9m5a>=9<10ci;50;&2`<<dl2d:h54>6:9l`1<72-;o57mk;o3g<?7032eo?7>5$0f:>fb<f8n36<64;nf1>5<#9m31oi5a1e:95<=<gm;1<7*>d88``>h6l10:m65`d183>!7c13io7c?k8;3a?>idn3:1(<j6:bf8j4b?28i07bmm:18'5a?=km1e=i651e98kf6=83.:h44ld:l2`=<6m21dn84?:%3g=?ec3g;o47?i;:mgf?6=,8n26io4n0f;>5=<gm31<7*>d88ge>h6l10:76ak8;29 4b>2mk0b<j7:398ka1=83.:h44ka:l2`=<432en<7>5$0f:>a`<f8n36=54oeg94?"6l00oj6`>d982?>icl3:1(<j6:ed8j4b?2;10cim50;&2`<<cn2d:h54<;:p717=83=8wS<<2:\004=:9ol1i9521dc97a=:9lk1?h521dc95a`<58oj6<k?;<3fe?7b>27:il4>e69>5`g=:916=ho5229>5`g=:;16=ho5209>5`g=9h16=ho5319>5`g=;:16=ho5339>5`g=;816=ho52`9>5`g=>916=ho55d9>5`g==j16=ho55c9>5`g==h16=ho5589>5`g==116=ho5569>5`g==?16=ho5549>5`g===16=ho5529>5`g==816=ho5519>5`g=<o16=ho54d9>5`g=<m16=ho5649>5`g=0816=ho57g9>5`g=?m16=ho57b9>5`g=?k16=ho57`9>5`g=?016=ho5799>5`g=?>16=ho5779>5`g=?<16=ho5759>5`g=?;16=ho5709>5`g=?916=ho56g9>5`g=>l16=ho5879>5`g=0m16=ho58c9>5`g=0h16=ho5889>5`g=1;16=ho5919>5`g=0o16=ho58d9>5`?=;m16=h753d9>5`?=9ml01<k6:0g3?87b13;n:63>e882a2=:9l31>=521d;966=:9l31>?521d;964=:9l31=l521d;975=:9l31?>521d;977=:9l31?<521d;96d=:9l31:=521d;91`=:9l319n521d;91g=:9l319l521d;91<=:9l3195521d;912=:9l319;521d;910=:9l3199521d;916=:9l319<521d;915=:9l318k521d;90`=:9l314<521d;93c=:9l31;i521d;93f=:9l31;o521d;93d=:9l31;4521d;93==:9l31;:521d;933=:9l31;8521d;931=:9l31;?521d;934=:9l31;=521d;92c=:9l314i521d;9<g=:9l315?521d;9=5=z{:936=4<{_10<>;6mh0n=63>e88f5>{t;:31<7=t^21:?87bi3o970?j9;g1?xu5;90;6>uQ222894cf2=801<k6:508yv4493:1?vP=309>5`g=<:16=h75429~w7cb2909wS<le:?2ad<>02wx>hm50;0xZ7ec34;nm778;|q1ad<72;qU>nl4=0gb><0<uz8n57>52z\1gd=:9lk1585rs3g;>5<5sW8h563>e`8:0>{t:l=1<7<t^3a;?87bi3h87p}=e783>7}Y:j=01<kn:c08yv4b=3:1>vP=c79>5`g=j91v?k;:181[4d=27:il4nf:p6`5=838pR?m;;<3fe?gb3ty9i?4?:3y]6f5<58oj6lj4}r0f5?6=:rT9o?521dc9e<=z{;nm6=4={_0`4>;6mh02i6s|2eg94?4|V;hm70?ja;;0?xu5lm0;6?uQ2cg894c>2m20q~<kc;296~X5jm16=h75989~w7be2909wS<mc:?2a<<>02wx>io50;0xZ7de34;n5778;|q1`<<72;qU>oo4=0g:><0<uz8o47>52z\1f<=:9l31585rs3f4>5<5sW8i463>e88:0>{t:m<1<7<t^3`4?87b13h87p}=f483>7}Y:m>01<k6:c08yv4a<3:1>vP=d29>5`?=l>1v?h<:181[4c:27:i44m1:p6c4=838pR?j>;<3f=?d73ty9j<4?:3y]6a6<58o26lh4}r0e4?6=:rT9ok521d;9e`=z{;om6=4={_0`g>;6m00jh6s|2d`94?4|V;i:70?j9;c:?xu5m90;6?uQ2c4894c>20o0q~<k5;296~X5j<16=h75929~w64a2909wS=?f:?2ad<ei2wx??j50;0xZ66b34;nm7l6;|q06g<72;qU?=m4=0gb>g><uz99m7>52z\04g=:9lk1n:5rs20:>5<5sW9;m63>e`8a2>{t;;21<7<t^22:?87bi3n>7p}<2683>7}Y;9201<kn:e68yv55>3:1>vP<069>5`g=l;1v><::181[57>27:il4k1:p772=838pR>>:;<3fe?b73ty8>>4?:3y]752<58oj6nh4}r116?6=:rT8<>521dc9gg=z{:8;6=4={_135>;6mh0h<6s|30d94?4|V::;70?ja;`6?xu49l0;6?uQ2gd894c>2mn0q~=>d;296~X5nl16=h75bc9~w67d2909wS<id:?2a<<ei2wx?<l50;0xZ7`d34;n57l6;|q05d<72;qU>kl4=0g:>g><uz9:57>52z\1bd=:9l31n:5rs23;>5<5sW8m563>e88a2>{t;8=1<7<t^3d;?87b13n>7p}<3783>7}Y;8?01<k6:e68yv54=3:1>vP<159>5`?=lj1v>=;:181[56;27:i44k3:p765=838pR>?=;<3f=?b53ty8??4?:3y]747<58o26i?4}r105?6=:rT8==521d;9`5=z{:9;6=4={_13`>;6m00hj6s|33a94?4|V::970?j9;aa?xu4:80;6?uQ2g5894c>2j:0q~=>6;296~X5n?16=h75b49~w6212902wS=;4:?2ad<6n:16=ho51g3894cf28l;70?ja;3fb>;6m00:j>521d;95c7<58o26<h?;<3f=?7bn2wx?9750;;xZ62034;nm7?i8:?2ad<6n?16=ho51g7894cf28l?70?j9;3e<>;6m00:j;521d;95c3<58o26<h;;|q15<<72:qU>=k4=0gb>4c<58o26<k4}r023?6=;rT9<i521dc95a=:9l31=i5rs335>5<4sW8;o63>e`82g>;6m00:o6s|20794?5|V;:i70?ja;3a?87b13;i7p}=1583>6}Y:9k01<kn:3;894c>2;30q~<>3;297~X58016=ho5299>5`?=:11v??=:180[47027:il4=7:?2a<<5?2wx><?50;1xZ76034;nm7<9;<3f=?413ty9==4?:2y]650<58oj6?;4=0g:>73<uz8;j7>53z\140=:9lk1>9521d;961=z{;8n6=4<{_017>;6mh09i63>e881a>{t:;i1<7=t^301?87bi38o70?j9;0g?xu5:k0;6>uQ233894cf2;i01<k6:3a8yv45i3:1?vP=219>5`g=:k16=h752c9~w74>2908wS<>f:?2ad<4127:i44<9:p67>=839pR??j;<3fe?5?34;n57=7;|q162<72:qU><j4=0gb>61<58o26>94}r012?6=;rT9=n521dc973=:9l31?;5rs306>5<4sW8:n63>e`801>;6m00896s|23694?5|V;;j70?ja;17?87b139?7p}=6b83>7}Y:=i01<kn:5a8yv41i3:1>vP=4c9>5`g=<k1v?87:181[43127:il4;a:p631=838pR?:7;<3fe?2>3ty9:;4?:3y]611<58oj6964}r051?6=:rT98;521dc922=z{;<?6=4={_071>;6mh0=:6s|27194?4|V;>?70?ja;47?xu5>;0;6?uQ251894cf2?90q~<91;296~X5<;16=ho5639~w7072909wS<;1:?2ad<192wx>8h50;0xZ72734;nm7;k;|q11a<72;qU>>k4=0gb>04<uz8>o7>52z\17a=:9lk18:5rs37a>5<5sW88o63>e88;e>{t:<k1<7<t^31a?87b13>o7p}=5883>7}Y::k01<k6:5a8yv4203:1>vP=389>5`?=<k1v?;8:181[44027:i44;a:p600=838pR?=8;<3f=?2>3ty9984?:3y]660<58o26964}r060?6=:rT9?8521d;922=z{;=86=4={_066>;6m00=:6s|26094?4|V;?:70?j9;::?xu5?80;6?uQ242894c>2??0q~<80;296~X5<o16=h75659~w70a2909wS<;e:?2a<<1;2wx>;k50;0xZ72c34;n578=;|q12a<72;qU>9o4=0g:>37<uz8=57>52z\17c=:9l319i5rs37f>5<5sW88863>e8866>{t:<91<7<t^310?87b13><7p}=ae83>7}Y:1n01<kn:7f8yv4fj3:1>vP=8b9>5`g=>j1v?o6:181[4?i27:il49b:p6d>=838pR?66;<3fe?0f3ty9m:4?:3y]6=><58oj6;74}r0b2?6=:rT94:521dc9<==z{;k>6=4={_0;2>;6mh03;6s|2`694?4|V;2>70?ja;:6?xu5i:0;6?uQ296894cf21>0q~<n2;296~X50:16=ho5829~w7g62909wS<72:?2ad<?:2wx>l>50;0xZ7>634;nm79j;|q1=`<72;qU>:h4=0gb>25<uz82h7>52z\13`=:9lk1:55rs3;`>5<5sW8<h63>e88;b>{t:0h1<7<t^35`?87b13<n7p}=9`83>7}Y:>h01<k6:7f8yv4>13:1>vP=7`9>5`?=>j1v?77:181[40127:i449b:p6<1=838pR?97;<3f=?0f3ty95;4?:3y]621<58o26;74}r0:1?6=:rT9;;521d;9<==z{;h?6=4={_0:7>;6m003;6s|2c194?4|V;3970?j9;:f?xu5j;0;6?uQ283894c>21<0q~<m1;296~X51916=h75849~w7d72909wS<7f:?2a<<?<2wx>lh50;0xZ7>b34;n576<;|q1e`<72;qU>5l4=0g:>=4<uz8jm7>52z\1<5=:9l31;h5rs3;e>5<5sW8<963>e8847>{t:0>1<7<t^357?87b13<37ps|22294?4|V;9;70=m:313?!7bj3;<n6s|27a94?4|V;>h70=m:36`?!7bj3;3:6s|27c94?4|V;>i70=m:36a?!7bj3;2=6s|27:94?4|V;>270=m:36:?!7bj3;2m6s|27594?4|V;>370=m:36;?!7bj3;j96s|27494?4|V;><70=m:364?!7bj3;i<6s|27794?4|V;>=70=m:365?!7bj3;in6s|27694?4|V;>>70=m:366?!7bj3;h:6s|27194?4|V;>?70=m:367?!7bj3;8;6s|27094?4|V;>870=m:360?!7bj3;?>6s|27394?4|V;>970=m:361?!7bj3;?h6s|27294?4|V;>:70=m:362?!7bj3;>:6s|24d94?4|V;>;70=m:363?!7bj3;==6s|24f94?4|V;9n70=m:31f?!7bj3;=o6s|24a94?4|V;9o70=m:31g?!7bj3;<;6s|24`94?4|V;9h70=m:31`?!7bj3;<46s|24c94?4|V;9i70=m:31a?!7bj3;<56s|24;94?4|V;9j70=m:31b?!7bj3;<m6s|24:94?4|V;9270=m:31:?!7bj3;<o6s|24594?4|V;9370=m:31;?!7bj3;<h6s|24494?4|V;9<70=m:314?!7bj3;<i6s|24794?4|V;9=70=m:315?!7bj3;<j6s|24694?4|V;9>70=m:316?!7bj3;3<6s|26194?4|V;?970=m:371?!7bj3;3=6s|26094?4|V;?:70=m:372?!7bj3;3>6s|26394?4|V;?;70=m:373?!7bj3;3?6s|26294?4|V;>m70=m:36e?!7bj3;386s|27d94?4|V;>n70=m:36f?!7bj3;396s|27g94?4|V;>o70=m:36g?!7bj3;3;6s|27f94?4|V;>j70=m:36b?!7bj3;346s|27;94?4|V;9m70=m:31e?!7bj3;356s|24g94?4|V;9?70=m:317?!7bj3;3m6s|24194?4|V;9870=m:310?!7bj3;3n6s|20;94?4|V;:n70=m:32f?!7bj3;3o6s|20594?4|V;:o70=m:32g?!7bj3;3h6s|20494?4|V;:h70=m:32`?!7bj3;3i6s|20794?4|V;:i70=m:32a?!7bj3;3j6s|20694?4|V;:j70=m:32b?!7bj3;2<6s|20194?4|V;:270=m:32:?!7bj3;2>6s|20094?4|V;:370=m:32;?!7bj3;2?6s|20394?4|V;:<70=m:324?!7bj3;286s|20294?4|V;:=70=m:325?!7bj3;296s|21d94?4|V;:>70=m:326?!7bj3;2:6s|32:94?4|V:9370=m:21;?!7bj3;2;6s|35494?4|V:>?70=m:267?!7bj3;246s|2dg94?4|V;in70=m:3af?!7bj3;256s|2da94?4|V;io70=m:3ag?!7bj3;2n6s|2dc94?4|V;ii70=m:3aa?!7bj3;2o6s|2d;94?4|V;ij70=m:3ab?!7bj3;2h6s|2d:94?4|V;i270=m:3a:?!7bj3;2i6s|2d594?4|V;i370=m:3a;?!7bj3;2j6s|2d494?4|V;i<70=m:3a4?!7bj3;j<6s|2d794?4|V;i=70=m:3a5?!7bj3;j=6s|2d694?4|V;i>70=m:3a6?!7bj3;j>6s|2d194?4|V;i?70=m:3a7?!7bj3;j?6s|2d094?4|V;i870=m:3a0?!7bj3;j86s|2d394?4|V;i970=m:3a1?!7bj3;j:6s|2ed94?4|V;i;70=m:3a3?!7bj3;j;6s|2eg94?4|V;hm70=m:3`e?!7bj3;j46s|2ef94?4|V;hn70=m:3`f?!7bj3;j56s|2ea94?4|V;ho70=m:3`g?!7bj3;jm6s|2e`94?4|V;hh70=m:3``?!7bj3;jn6s|2ec94?4|V;hi70=m:3`a?!7bj3;jo6s|2e;94?4|V;hj70=m:3`b?!7bj3;jh6s|2e:94?4|V;h270=m:3`:?!7bj3;ji6s|2e594?4|V;h370=m:3`;?!7bj3;jj6s|2e494?4|V;h<70=m:3`4?!7bj3;i=6s|2g794?4|V;n?70=m:3f7?!7bj3;i>6s|2g694?4|V;n870=m:3f0?!7bj3;i?6s|2g194?4|V;n970=m:3f1?!7bj3;i86s|2g094?4|V;n:70=m:3f2?!7bj3;i96s|2g394?4|V;n;70=m:3f3?!7bj3;i:6s|2g294?4|V;im70=m:3ae?!7bj3;i;6s|2dd94?4|V;ih70=m:3a`?!7bj3;i46s|2d`94?4|V;i:70=m:3a2?!7bj3;i56s|2d294?4|V;h=70=m:3`5?!7bj3;im6s|2e794?4|V;h>70=m:3`6?!7bj3;io6s|22394?4|V;9:70=m:312?!7bj3;ih6s|2`f94?4|V;2o70=m:3:g?!7bj3;ii6s|2``94?4|V;2h70=m:3:`?!7bj3;ij6s|2`;94?4|V;2j70=m:3:b?!7bj3;h<6s|2`:94?4|V;2270=m:3::?!7bj3;h=6s|2`594?4|V;2370=m:3:;?!7bj3;h>6s|2`494?4|V;2<70=m:3:4?!7bj3;h?6s|2`794?4|V;2=70=m:3:5?!7bj3;h86s|2`694?4|V;2>70=m:3:6?!7bj3;h96s|2`194?4|V;2?70=m:3:7?!7bj3;h;6s|2`094?4|V;2870=m:3:0?!7bj3;h46s|2`394?4|V;2970=m:3:1?!7bj3;h56s|2`294?4|V;2:70=m:3:2?!7bj3;hm6s|28g94?4|V;=m70=m:35e?!7bj3;hn6s|28f94?4|V;=n70=m:35f?!7bj3;ho6s|28a94?4|V;=o70=m:35g?!7bj3;hh6s|28`94?4|V;=h70=m:35`?!7bj3;hi6s|28c94?4|V;=i70=m:35a?!7bj3;hj6s|28;94?4|V;=j70=m:35b?!7bj3;o<6s|28:94?4|V;=270=m:35:?!7bj3;846s|28594?4|V;=370=m:35;?!7bj3;856s|28494?4|V;=<70=m:354?!7bj3;8m6s|28794?4|V;==70=m:355?!7bj3;8n6s|2c694?4|V;3870=m:3;0?!7bj3;8o6s|2c194?4|V;3970=m:3;1?!7bj3;8h6s|2c094?4|V;3:70=m:3;2?!7bj3;8i6s|2c394?4|V;3;70=m:3;3?!7bj3;8j6s|2c294?4|V;2m70=m:3:e?!7bj3;?<6s|2`d94?4|V;2n70=m:3:f?!7bj3;?=6s|2`g94?4|V;2i70=m:3:a?!7bj3;??6s|2`c94?4|V;2;70=m:3:3?!7bj3;?86s|28d94?4|V;=>70=m:356?!7bj3;?96s|28694?4|V;=?70=m:357?!7bj3;?:6s|23g94?4|V;8870=m:300?!7bj3;?;6s|23a94?4|V;8970=m:301?!7bj3;?46s|23`94?4|V;8:70=m:302?!7bj3;?56s|23c94?4|V;8;70=m:303?!7bj3;?m6s|23;94?4|V;;m70=m:33e?!7bj3;?n6s|23:94?4|V;;n70=m:33f?!7bj3;?o6s|23594?4|V;;o70=m:33g?!7bj3;?i6s|23494?4|V;;h70=m:33`?!7bj3;?j6s|23794?4|V;;i70=m:33a?!7bj3;><6s|23694?4|V;;j70=m:33b?!7bj3;>=6s|32;94?4|V:9270=m:21:?!7bj3;>>6s|35;94?4|V:><70=m:264?!7bj3;>?6s|33d94?4|V::m70=m:22e?!7bj3;>86s|33f94?4|V::n70=m:22f?!7bj3;>96s|33`94?4|V::h70=m:22`?!7bj3;>;6s|33c94?4|V::i70=m:22a?!7bj3;>46s|33;94?4|V::j70=m:22b?!7bj3;>56s|33:94?4|V::270=m:22:?!7bj3;>m6s|33594?4|V::370=m:22;?!7bj3;>n6s|33494?4|V::<70=m:224?!7bj3;>o6s|33794?4|V::=70=m:225?!7bj3;>h6s|33694?4|V::>70=m:226?!7bj3;>i6s|33194?4|V::?70=m:227?!7bj3;>j6s|33094?4|V::870=m:220?!7bj3;=<6s|33294?4|V:::70=m:222?!7bj3;=>6s|30d94?4|V::;70=m:223?!7bj3;=?6s|30g94?4|V;lm70=m:3de?!7bj3;=86s|30f94?4|V;ln70=m:3df?!7bj3;=96s|30a94?4|V;lo70=m:3dg?!7bj3;=:6s|30`94?4|V;lh70=m:3d`?!7bj3;=;6s|30c94?4|V;li70=m:3da?!7bj3;=46s|30;94?4|V;lj70=m:3db?!7bj3;=56s|30:94?4|V;l270=m:3d:?!7bj3;=m6s|30594?4|V;l370=m:3d;?!7bj3;=n6s|32494?4|V:;>70=m:236?!7bj3;=h6s|32794?4|V:;?70=m:237?!7bj3;=i6s|32694?4|V:;870=m:230?!7bj3;=j6s|32194?4|V:;970=m:231?!7bj3;<<6s|32094?4|V:;:70=m:232?!7bj3;<=6s|32394?4|V:;;70=m:233?!7bj3;<>6s|32294?4|V::o70=m:22g?!7bj3;<?6s|33a94?4|V::970=m:221?!7bj3;<86s|33394?4|V;l<70=m:3d4?!7bj3;<96s|30494?4|V;l=70=m:3d5?!7bj3;<:6srn24g>5<5sA;no6sa37g94?4|@8oh7p`<6g83>7}O9li0qc=80;296~N6mj1vb>9>:181M7bk2we?:<50;0xL4cd3td8;>4?:3yK5`e<ug9<87>52zJ2af=zf:=>6=4={I3fg>{i;><1<7<tH0g`?xh4?>0;6?uG1da8yk5003:1>vF>eb9~j61>2909wE?jc:m72g=838pD<kl;|l03g<72;qC=hm4}o14g?6=:rB:in5rn25g>5<5sA;no6sa36g94?4|@8oh7p`<7g83>7}O9li0qc=70;296~N6mj1vb>6>:181M7bk2we?5<50;0xL4cd3td84>4?:3yK5`e<ug9387>52zJ2af=zf:2>6=4={I3fg>{i;1<1<7<tH0g`?xh40>0;6?uG1da8yk5?03:1>vF>eb9~j6>>2909wE?jc:m7=g=838pD<kl;|l0<g<72;qC=hm4}o1;g?6=:rB:in5rn2:g>5<5sA;no6sa39g94?4|@8oh7p`<8g83>7}O9li0qc=60;296~N6mj1vb>7>:181M7bk2we?4<50;0xL4cd3td85>4?:3yK5`e<ug9287>52zJ2af=zf:3>6=4={I3fg>{i;0<1<7<tH0g`?xh41>0;6?uG1da8yk5>03:1>vF>eb9~j6?>2909wE?jc:m7<g=838pD<kl;|l0=g<72;qC=hm4}o1:g?6=:rB:in5rn2;g>5<5sA;no6sa38g94?4|@8oh7p`<9g83>7}O9li0qc=n0;296~N6mj1vb>o>:181M7bk2we?l<50;0xL4cd3td8m>4?:3yK5`e<ug9j87>52zJ2af=zf:k>6=4={I3fg>{i;h<1<7<tH0g`?xh4i>0;6?uG1da8yk5f03:1>vF>eb9~j6g>2909wE?jc:m7dg=838pD<kl;|l0eg<72;qC=hm4}o1bg?6=:rB:in5rn2cg>5<5sA;no6sa3`g94?4|@8oh7p`<ag83>7}O9li0qc=m0;296~N6mj1vb>l>:181M7bk2we?o<50;0xL4cd3td8n>4?:3yK5`e<ug9i87>52zJ2af=zf:h>6=4={I3fg>{i;k<1<7<tH0g`?xh4j>0;6?uG1da8yk5e03:1>vF>eb9~j6d>2909wE?jc:m7gg=838pD<kl;|l0fg<72;qC=hm4}o1ag?6=:rB:in5rn2`g>5<5sA;no6sa3cg94?4|@8oh7p`<bg83>7}O9li0qc=l0;296~N6mj1vb>m>:181M7bk2we?n<50;0xL4cd3td8o>4?:3yK5`e<ug9h87>52zJ2af=zf:i>6=4={I3fg>{i;j<1<7<tH0g`?xh4k>0;6?uG1da8yk5d03:1>vF>eb9~j6e>2909wE?jc:m7fg=838pD<kl;|l0gg<72;qC=hm4}o1`g?6=:rB:in5rn2ag>5<5sA;no6sa3bg94?4|@8oh7p`<cg83>7}O9li0qc=k0;296~N6mj1vb>j>:181M7bk2we?i<50;0xL4cd3td8h>4?:3yK5`e<ug9o87>52zJ2af=zf:n>6=4={I3fg>{i;m<1<7<tH0g`?xh4l>0;6?uG1da8yk5c03:1>vF>eb9~j6b>2909wE?jc:m7ag=838pD<kl;|l0`g<72;qC=hm4}o1gg?6=:rB:in5rn2fg>5<5sA;no6sa3eg94?4|@8oh7p`<dg83>7}O9li0qc=j0;296~N6mj1vb>k>:181M7bk2we?h<50;0xL4cd3td8i>4?:3yK5`e<ug9n87>52zJ2af=zf:o>6=4={I3fg>{i;l<1<7<tH0g`?xh4m>0;6?uG1da8yk5b03:1>vF>eb9~j6c>2909wE?jc:m7`g=838pD<kl;|l0ag<72;qC=hm4}o1fg?6=:rB:in5rn2gg>5<5sA;no6sa3dg94?4|@8oh7p`<eg83>7}O9li0qc=i0;296~N6mj1vb>h>:181M7bk2we?k<50;0xL4cd3td8j>4?:3yK5`e<ug9m87>52zJ2af=zf:l>6=4={I3fg>{i;o<1<7<tH0g`?xh4n>0;6?uG1da8yk5a03:1>vF>eb9~j6`>2909wE?jc:m7cg=838pD<kl;|l0bg<72;qC=hm4}o1eg?6=:rB:in5rn2dg>5<5sA;no6sa3gg94?4|@8oh7p`<fg83>7}O9li0qc:?0;296~N6mj1vb9>>:181M7bk2we8=<50;0xL4cd3td?<>4?:3yK5`e<ug>;87>52zJ2af=zf=:>6=4={I3fg>{i<9<1<7<tH0g`?xh5l;0;6<uG1da8yx{zHIIp8l<5a76;e5c4uIJIw=sO@Qy~DE \ No newline at end of file diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem.vhd b/rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem.vhd new file mode 100644 index 00000000..80684cd1 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem.vhd @@ -0,0 +1,145 @@ +-------------------------------------------------------------------------------- +-- This file is owned and controlled by Xilinx and must be used -- +-- solely for design, simulation, implementation and creation of -- +-- design files limited to Xilinx devices or technologies. Use -- +-- with non-Xilinx devices or technologies is expressly prohibited -- +-- and immediately terminates your license. -- +-- -- +-- XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" -- +-- SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR -- +-- XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION -- +-- AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION -- +-- OR STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS -- +-- IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, -- +-- AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE -- +-- FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY -- +-- WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE -- +-- IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR -- +-- REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF -- +-- INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -- +-- FOR A PARTICULAR PURPOSE. -- +-- -- +-- Xilinx products are not intended for use in life support -- +-- appliances, devices, or systems. Use in such applications are -- +-- expressly prohibited. -- +-- -- +-- (c) Copyright 1995-2007 Xilinx, Inc. -- +-- All rights reserved. -- +-------------------------------------------------------------------------------- +-- You must compile the wrapper file pattern_blk_mem.vhd when simulating +-- the core, pattern_blk_mem. When compiling the wrapper file, be sure to +-- reference the XilinxCoreLib VHDL simulation library. For detailed +-- instructions, please refer to the "CORE Generator Help". + +-- The synthesis directives "translate_off/translate_on" specified +-- below are supported by Xilinx, Mentor Graphics and Synplicity +-- synthesis tools. Ensure they are correct for your synthesis tool(s). + +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +-- synthesis translate_off +Library XilinxCoreLib; +-- synthesis translate_on +ENTITY pattern_blk_mem IS + port ( + clka: IN std_logic; + dina: IN std_logic_VECTOR(31 downto 0); + addra: IN std_logic_VECTOR(9 downto 0); + ena: IN std_logic; + wea: IN std_logic_VECTOR(0 downto 0); + douta: OUT std_logic_VECTOR(31 downto 0); + clkb: IN std_logic; + dinb: IN std_logic_VECTOR(31 downto 0); + addrb: IN std_logic_VECTOR(9 downto 0); + enb: IN std_logic; + web: IN std_logic_VECTOR(0 downto 0); + doutb: OUT std_logic_VECTOR(31 downto 0)); +END pattern_blk_mem; + +ARCHITECTURE pattern_blk_mem_a OF pattern_blk_mem IS +-- synthesis translate_off +component wrapped_pattern_blk_mem + port ( + clka: IN std_logic; + dina: IN std_logic_VECTOR(31 downto 0); + addra: IN std_logic_VECTOR(9 downto 0); + ena: IN std_logic; + wea: IN std_logic_VECTOR(0 downto 0); + douta: OUT std_logic_VECTOR(31 downto 0); + clkb: IN std_logic; + dinb: IN std_logic_VECTOR(31 downto 0); + addrb: IN std_logic_VECTOR(9 downto 0); + enb: IN std_logic; + web: IN std_logic_VECTOR(0 downto 0); + doutb: OUT std_logic_VECTOR(31 downto 0)); +end component; + +-- Configuration specification + for all : wrapped_pattern_blk_mem use entity XilinxCoreLib.blk_mem_gen_v2_8(behavioral) + generic map( + c_has_regceb => 0, + c_has_regcea => 0, + c_mem_type => 2, + c_prim_type => 1, + c_sinita_val => "0", + c_read_width_b => 32, + c_family => "virtex4", + c_read_width_a => 32, + c_disable_warn_bhv_coll => 0, + c_write_mode_b => "NO_CHANGE", + c_init_file_name => "no_coe_file_loaded", + c_write_mode_a => "NO_CHANGE", + c_mux_pipeline_stages => 0, + c_has_mem_output_regs_b => 0, + c_load_init_file => 0, + c_xdevicefamily => "virtex4", + c_has_mem_output_regs_a => 0, + c_write_depth_b => 1024, + c_write_depth_a => 1024, + c_has_ssrb => 0, + c_has_mux_output_regs_b => 0, + c_has_ssra => 0, + c_has_mux_output_regs_a => 0, + c_addra_width => 10, + c_addrb_width => 10, + c_default_data => "0", + c_use_ecc => 0, + c_algorithm => 1, + c_disable_warn_bhv_range => 0, + c_write_width_b => 32, + c_write_width_a => 32, + c_read_depth_b => 1024, + c_read_depth_a => 1024, + c_byte_size => 9, + c_sim_collision_check => "ALL", + c_use_ramb16bwer_rst_bhv => 0, + c_common_clk => 0, + c_wea_width => 1, + c_has_enb => 1, + c_web_width => 1, + c_has_ena => 1, + c_sinitb_val => "0", + c_use_byte_web => 0, + c_use_byte_wea => 0, + c_use_default_data => 1); +-- synthesis translate_on +BEGIN +-- synthesis translate_off +U0 : wrapped_pattern_blk_mem + port map ( + clka => clka, + dina => dina, + addra => addra, + ena => ena, + wea => wea, + douta => douta, + clkb => clkb, + dinb => dinb, + addrb => addrb, + enb => enb, + web => web, + doutb => doutb); +-- synthesis translate_on + +END pattern_blk_mem_a; + diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem.vho b/rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem.vho new file mode 100644 index 00000000..6c359283 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem.vho @@ -0,0 +1,74 @@ +-------------------------------------------------------------------------------- +-- This file is owned and controlled by Xilinx and must be used -- +-- solely for design, simulation, implementation and creation of -- +-- design files limited to Xilinx devices or technologies. Use -- +-- with non-Xilinx devices or technologies is expressly prohibited -- +-- and immediately terminates your license. -- +-- -- +-- XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" -- +-- SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR -- +-- XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION -- +-- AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION -- +-- OR STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS -- +-- IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, -- +-- AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE -- +-- FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY -- +-- WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE -- +-- IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR -- +-- REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF -- +-- INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -- +-- FOR A PARTICULAR PURPOSE. -- +-- -- +-- Xilinx products are not intended for use in life support -- +-- appliances, devices, or systems. Use in such applications are -- +-- expressly prohibited. -- +-- -- +-- (c) Copyright 1995-2007 Xilinx, Inc. -- +-- All rights reserved. -- +-------------------------------------------------------------------------------- +-- The following code must appear in the VHDL architecture header: + +------------- Begin Cut here for COMPONENT Declaration ------ COMP_TAG +component pattern_blk_mem + port ( + clka: IN std_logic; + dina: IN std_logic_VECTOR(31 downto 0); + addra: IN std_logic_VECTOR(9 downto 0); + ena: IN std_logic; + wea: IN std_logic_VECTOR(0 downto 0); + douta: OUT std_logic_VECTOR(31 downto 0); + clkb: IN std_logic; + dinb: IN std_logic_VECTOR(31 downto 0); + addrb: IN std_logic_VECTOR(9 downto 0); + enb: IN std_logic; + web: IN std_logic_VECTOR(0 downto 0); + doutb: OUT std_logic_VECTOR(31 downto 0)); +end component; + +-- COMP_TAG_END ------ End COMPONENT Declaration ------------ + +-- The following code must appear in the VHDL architecture +-- body. Substitute your own instance name and net names. + +------------- Begin Cut here for INSTANTIATION Template ----- INST_TAG +your_instance_name : pattern_blk_mem + port map ( + clka => clka, + dina => dina, + addra => addra, + ena => ena, + wea => wea, + douta => douta, + clkb => clkb, + dinb => dinb, + addrb => addrb, + enb => enb, + web => web, + doutb => doutb); +-- INST_TAG_END ------ End INSTANTIATION Template ------------ + +-- You must compile the wrapper file pattern_blk_mem.vhd when simulating +-- the core, pattern_blk_mem. When compiling the wrapper file, be sure to +-- reference the XilinxCoreLib VHDL simulation library. For detailed +-- instructions, please refer to the "CORE Generator Help". + diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem.xco b/rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem.xco new file mode 100644 index 00000000..ef82ce5d --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem.xco @@ -0,0 +1,78 @@ +############################################################## +# +# Xilinx Core Generator version K.39 +# Date: Mon Aug 17 20:38:30 2009 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# BEGIN Project Options +SET addpads = False +SET asysymbol = False +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = False +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = False +SET foundationsym = False +SET implementationfiletype = Ngc +SET package = ff1152 +SET removerpms = False +SET simulationfiles = Behavioral +SET speedgrade = -10 +SET verilogsim = False +SET vhdlsim = True +# END Project Options +# BEGIN Select +SELECT Block_Memory_Generator family Xilinx,_Inc. 2.8 +# END Select +# BEGIN Parameters +CSET algorithm=Minimum_Area +CSET assume_synchronous_clk=false +CSET byte_size=9 +CSET coe_file=no_coe_file_loaded +CSET collision_warnings=ALL +CSET component_name=pattern_blk_mem +CSET disable_collision_warnings=false +CSET disable_out_of_range_warnings=false +CSET ecc=false +CSET enable_a=Use_ENA_Pin +CSET enable_b=Use_ENB_Pin +CSET fill_remaining_memory_locations=true +CSET load_init_file=false +CSET memory_type=True_Dual_Port_RAM +CSET operating_mode_a=NO_CHANGE +CSET operating_mode_b=NO_CHANGE +CSET output_reset_value_a=0 +CSET output_reset_value_b=0 +CSET pipeline_stages=0 +CSET primitive=8kx2 +CSET read_width_a=32 +CSET read_width_b=32 +CSET register_porta_output_of_memory_core=false +CSET register_porta_output_of_memory_primitives=false +CSET register_portb_output_of_memory_core=false +CSET register_portb_output_of_memory_primitives=false +CSET remaining_memory_locations=0 +CSET single_bit_ecc=false +CSET use_byte_write_enable=false +CSET use_ramb16bwer_reset_behavior=false +CSET use_regcea_pin=false +CSET use_regceb_pin=false +CSET use_ssra_pin=false +CSET use_ssrb_pin=false +CSET write_depth_a=1024 +CSET write_width_a=32 +CSET write_width_b=32 +# END Parameters +GENERATE +# CRC: d212e058 + diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem_blk_mem_gen_v2_8_xst_1.ngc_xst.xrpt b/rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem_blk_mem_gen_v2_8_xst_1.ngc_xst.xrpt new file mode 100644 index 00000000..b4dcf62f --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem_blk_mem_gen_v2_8_xst_1.ngc_xst.xrpt @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<document OS="lin" product="ISE" version="10.1.03"> + + <!--The data in this file is primarily intended for consumption by Xilinx tools. + The structure and the elements are likely to change over the next few releases. + This means code written to parse this file will need to be revisited each subsequent release.--> + + <application stringID="Xst" timeStamp="Mon Aug 17 13:37:53 2009"> + <section stringID="XST_ADVANCED_HDL_SYNTHESIS_REPORTFOUND_NO_MACRO"/> + <section stringID="XST_FINAL_REGISTER_REPORTFOUND_NO_MACRO"/> + <section stringID="XST_PARTITION_REPORT"> + <section stringID="XST_PARTITION_IMPLEMENTATION_STATUS"> + <section stringID="XST_NO_PARTITIONS_WERE_FOUND_IN_THIS_DESIGN"/> + </section> + </section> + <section stringID="XST_FINAL_REPORT"> + <section stringID="XST_FINAL_RESULTS"> + <item stringID="XST_TOP_LEVEL_OUTPUT_FILE_NAME" value="/afs/slac/u/ec/kocian/minilat/xilinx/BnlAsic/xil_cores/tmp/_cg/pattern_blk_mem_blk_mem_gen_v2_8_xst_1.ngc"/> + <item stringID="XST_OUTPUT_FORMAT" value="NGC"/> + <item stringID="XST_OPTIMIZATION_GOAL" value="SPEED"/> + <item stringID="XST_KEEP_HIERARCHY" value="no"/> + </section> + <section stringID="XST_DESIGN_STATISTICS"> + <item stringID="XST_IOS" value="160"/> + </section> + <section stringID="XST_CELL_USAGE"> + <item dataType="int" stringID="XST_BELS" value="1"> + <item dataType="int" stringID="XST_GND" value="1"/> + </item> + <item dataType="int" stringID="XST_RAMS" value="2"></item> + </section> + </section> + <section stringID="XST_DEVICE_UTILIZATION_SUMMARY"> + <item stringID="XST_SELECTED_DEVICE" value="4vfx60ff672-12"/> + <item AVAILABLE="25280" dataType="int" stringID="XST_NUMBER_OF_SLICES" value="0"/> + <item dataType="int" stringID="XST_NUMBER_OF_IOS" value="160"/> + <item AVAILABLE="352" dataType="int" stringID="XST_NUMBER_OF_BONDED_IOBS" value="0"/> + </section> + <section stringID="XST_PARTITION_RESOURCE_SUMMARY"> + <section stringID="XST_NO_PARTITIONS_WERE_FOUND_IN_THIS_DESIGN"/> + </section> + <section stringID="XST_ERRORS_STATISTICS"> + <item dataType="int" filtered="0" stringID="XST_NUMBER_OF_ERRORS" value="0"/> + <item dataType="int" filtered="0" stringID="XST_NUMBER_OF_WARNINGS" value="112"/> + <item dataType="int" filtered="0" stringID="XST_NUMBER_OF_INFOS" value="15"/> + </section> + </application> + +</document> diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem_flist.txt b/rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem_flist.txt new file mode 100644 index 00000000..6bfdd435 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem_flist.txt @@ -0,0 +1,8 @@ +# Output products list for <pattern_blk_mem> +pattern_blk_mem.ngc +pattern_blk_mem.vhd +pattern_blk_mem.vho +pattern_blk_mem.xco +pattern_blk_mem_blk_mem_gen_v2_8_xst_1.ngc_xst.xrpt +pattern_blk_mem_flist.txt +pattern_blk_mem_xmdf.tcl diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem_readme.txt b/rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem_readme.txt new file mode 100644 index 00000000..e4f5cebb --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem_readme.txt @@ -0,0 +1,39 @@ +The following files were generated for 'pattern_blk_mem' in directory +/a/sulky20/g.ee.u07/kocian/minilat/xilinx/IBL/xil_cores/: + +pattern_blk_mem.ngc: + Binary Xilinx implementation netlist file containing the information + required to implement the module in a Xilinx (R) FPGA. + +pattern_blk_mem.vhd: + VHDL wrapper file provided to support functional simulation. This + file contains simulation model customization data that is passed to + a parameterized simulation model for the core. + +pattern_blk_mem.vho: + VHO template file containing code that can be used as a model for + instantiating a CORE Generator module in a VHDL design. + +pattern_blk_mem.xco: + CORE Generator input file containing the parameters used to + regenerate a core. + +pattern_blk_mem_blk_mem_gen_v2_8_xst_1.ngc_xst.xrpt: + Please see the core data sheet. + +pattern_blk_mem_flist.txt: + Text file listing all of the output files produced when a customized + core was generated in the CORE Generator. + +pattern_blk_mem_readme.txt: + Text file indicating the files generated and how they are used. + +pattern_blk_mem_xmdf.tcl: + ISE Project Navigator interface file. ISE uses this file to determine + how the files output by CORE Generator for the core can be integrated + into your ISE project. + + +Please see the Xilinx CORE Generator online help for further details on +generated files and how to use them. + diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem_xmdf.tcl b/rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem_xmdf.tcl new file mode 100644 index 00000000..d1919217 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/pattern_blk_mem_xmdf.tcl @@ -0,0 +1,68 @@ +# The package naming convention is <core_name>_xmdf +package provide pattern_blk_mem_xmdf 1.0 + +# This includes some utilities that support common XMDF operations +package require utilities_xmdf + +# Define a namespace for this package. The name of the name space +# is <core_name>_xmdf +namespace eval ::pattern_blk_mem_xmdf { +# Use this to define any statics +} + +# Function called by client to rebuild the params and port arrays +# Optional when the use context does not require the param or ports +# arrays to be available. +proc ::pattern_blk_mem_xmdf::xmdfInit { instance } { +# Variable containg name of library into which module is compiled +# Recommendation: <module_name> +# Required +utilities_xmdf::xmdfSetData $instance Module Attributes Name pattern_blk_mem +} +# ::pattern_blk_mem_xmdf::xmdfInit + +# Function called by client to fill in all the xmdf* data variables +# based on the current settings of the parameters +proc ::pattern_blk_mem_xmdf::xmdfApplyParams { instance } { + +set fcount 0 +# Array containing libraries that are assumed to exist +# Examples include unisim and xilinxcorelib +# Optional +# In this example, we assume that the unisim library will +# be magically +# available to the simulation and synthesis tool +utilities_xmdf::xmdfSetData $instance FileSet $fcount type logical_library +utilities_xmdf::xmdfSetData $instance FileSet $fcount logical_library unisim +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path pattern_blk_mem.ngc +utilities_xmdf::xmdfSetData $instance FileSet $fcount type ngc +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path pattern_blk_mem.vhd +utilities_xmdf::xmdfSetData $instance FileSet $fcount type vhdl +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path pattern_blk_mem.vho +utilities_xmdf::xmdfSetData $instance FileSet $fcount type vhdl_template +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path pattern_blk_mem.xco +utilities_xmdf::xmdfSetData $instance FileSet $fcount type coregen_ip +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path pattern_blk_mem_blk_mem_gen_v2_8_xst_1.ngc_xst.xrpt +utilities_xmdf::xmdfSetData $instance FileSet $fcount type AnyView +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path pattern_blk_mem_xmdf.tcl +utilities_xmdf::xmdfSetData $instance FileSet $fcount type AnyView +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount associated_module pattern_blk_mem +incr fcount + +} + +# ::gen_comp_name_xmdf::xmdfApplyParams diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/wordcounter.xco b/rce/fw-hsio/projects/IBLcableTester/coregen/wordcounter.xco new file mode 100644 index 00000000..19b7548f --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/wordcounter.xco @@ -0,0 +1,78 @@ +############################################################## +# +# Xilinx Core Generator version K.39 +# Date: Tue Sep 1 16:45:51 2009 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# BEGIN Project Options +SET addpads = False +SET asysymbol = False +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = False +SET designentry = VHDL +SET device = xc4vfx60 +SET devicefamily = virtex4 +SET flowvendor = Other +SET formalverification = False +SET foundationsym = False +SET implementationfiletype = Ngc +SET package = ff1152 +SET removerpms = False +SET simulationfiles = Behavioral +SET speedgrade = -10 +SET verilogsim = False +SET vhdlsim = True +# END Project Options +# BEGIN Select +SELECT Block_Memory_Generator family Xilinx,_Inc. 2.8 +# END Select +# BEGIN Parameters +CSET algorithm=Minimum_Area +CSET assume_synchronous_clk=false +CSET byte_size=9 +CSET coe_file=no_coe_file_loaded +CSET collision_warnings=ALL +CSET component_name=wordcounter +CSET disable_collision_warnings=false +CSET disable_out_of_range_warnings=false +CSET ecc=false +CSET enable_a=Always_Enabled +CSET enable_b=Always_Enabled +CSET fill_remaining_memory_locations=false +CSET load_init_file=false +CSET memory_type=Simple_Dual_Port_RAM +CSET operating_mode_a=READ_FIRST +CSET operating_mode_b=READ_FIRST +CSET output_reset_value_a=0 +CSET output_reset_value_b=0 +CSET pipeline_stages=0 +CSET primitive=8kx2 +CSET read_width_a=64 +CSET read_width_b=64 +CSET register_porta_output_of_memory_core=false +CSET register_porta_output_of_memory_primitives=false +CSET register_portb_output_of_memory_core=false +CSET register_portb_output_of_memory_primitives=false +CSET remaining_memory_locations=0 +CSET single_bit_ecc=false +CSET use_byte_write_enable=false +CSET use_ramb16bwer_reset_behavior=false +CSET use_regcea_pin=false +CSET use_regceb_pin=false +CSET use_ssra_pin=false +CSET use_ssrb_pin=false +CSET write_depth_a=2 +CSET write_width_a=64 +CSET write_width_b=64 +# END Parameters +GENERATE +# CRC: 2d2b874a + diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/wordcounter_blk_mem_gen_v2_8_xst_1.ngc_xst.xrpt b/rce/fw-hsio/projects/IBLcableTester/coregen/wordcounter_blk_mem_gen_v2_8_xst_1.ngc_xst.xrpt new file mode 100644 index 00000000..0468ac4c --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/wordcounter_blk_mem_gen_v2_8_xst_1.ngc_xst.xrpt @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<document OS="lin" product="ISE" version="10.1.03"> + + <!--The data in this file is primarily intended for consumption by Xilinx tools. + The structure and the elements are likely to change over the next few releases. + This means code written to parse this file will need to be revisited each subsequent release.--> + + <application stringID="Xst" timeStamp="Tue Sep 1 09:45:16 2009"> + <section stringID="XST_ADVANCED_HDL_SYNTHESIS_REPORTFOUND_NO_MACRO"/> + <section stringID="XST_FINAL_REGISTER_REPORTFOUND_NO_MACRO"/> + <section stringID="XST_PARTITION_REPORT"> + <section stringID="XST_PARTITION_IMPLEMENTATION_STATUS"> + <section stringID="XST_NO_PARTITIONS_WERE_FOUND_IN_THIS_DESIGN"/> + </section> + </section> + <section stringID="XST_FINAL_REPORT"> + <section stringID="XST_FINAL_RESULTS"> + <item stringID="XST_TOP_LEVEL_OUTPUT_FILE_NAME" value="/afs/slac/u/ec/kocian/minilat/xilinx/BnlAsic/xil_cores/tmp/_cg/wordcounter_blk_mem_gen_v2_8_xst_1.ngc"/> + <item stringID="XST_OUTPUT_FORMAT" value="NGC"/> + <item stringID="XST_OPTIMIZATION_GOAL" value="SPEED"/> + <item stringID="XST_KEEP_HIERARCHY" value="no"/> + </section> + <section stringID="XST_DESIGN_STATISTICS"> + <item stringID="XST_IOS" value="270"/> + </section> + <section stringID="XST_CELL_USAGE"> + <item dataType="int" stringID="XST_BELS" value="2"> + <item dataType="int" stringID="XST_GND" value="1"/> + <item dataType="int" stringID="XST_VCC" value="1"/> + </item> + <item dataType="int" stringID="XST_RAMS" value="2"></item> + </section> + </section> + <section stringID="XST_DEVICE_UTILIZATION_SUMMARY"> + <item stringID="XST_SELECTED_DEVICE" value="4vfx60ff672-12"/> + <item AVAILABLE="25280" dataType="int" stringID="XST_NUMBER_OF_SLICES" value="0"/> + <item dataType="int" stringID="XST_NUMBER_OF_IOS" value="270"/> + <item AVAILABLE="352" dataType="int" stringID="XST_NUMBER_OF_BONDED_IOBS" value="0"/> + </section> + <section stringID="XST_PARTITION_RESOURCE_SUMMARY"> + <section stringID="XST_NO_PARTITIONS_WERE_FOUND_IN_THIS_DESIGN"/> + </section> + <section stringID="XST_ERRORS_STATISTICS"> + <item dataType="int" filtered="0" stringID="XST_NUMBER_OF_ERRORS" value="0"/> + <item dataType="int" filtered="0" stringID="XST_NUMBER_OF_WARNINGS" value="137"/> + <item dataType="int" filtered="0" stringID="XST_NUMBER_OF_INFOS" value="13"/> + </section> + </application> + +</document> diff --git a/rce/fw-hsio/projects/IBLcableTester/coregen/wordcounter_xmdf.tcl b/rce/fw-hsio/projects/IBLcableTester/coregen/wordcounter_xmdf.tcl new file mode 100644 index 00000000..ecab7919 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/coregen/wordcounter_xmdf.tcl @@ -0,0 +1,68 @@ +# The package naming convention is <core_name>_xmdf +package provide wordcounter_xmdf 1.0 + +# This includes some utilities that support common XMDF operations +package require utilities_xmdf + +# Define a namespace for this package. The name of the name space +# is <core_name>_xmdf +namespace eval ::wordcounter_xmdf { +# Use this to define any statics +} + +# Function called by client to rebuild the params and port arrays +# Optional when the use context does not require the param or ports +# arrays to be available. +proc ::wordcounter_xmdf::xmdfInit { instance } { +# Variable containg name of library into which module is compiled +# Recommendation: <module_name> +# Required +utilities_xmdf::xmdfSetData $instance Module Attributes Name wordcounter +} +# ::wordcounter_xmdf::xmdfInit + +# Function called by client to fill in all the xmdf* data variables +# based on the current settings of the parameters +proc ::wordcounter_xmdf::xmdfApplyParams { instance } { + +set fcount 0 +# Array containing libraries that are assumed to exist +# Examples include unisim and xilinxcorelib +# Optional +# In this example, we assume that the unisim library will +# be magically +# available to the simulation and synthesis tool +utilities_xmdf::xmdfSetData $instance FileSet $fcount type logical_library +utilities_xmdf::xmdfSetData $instance FileSet $fcount logical_library unisim +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path wordcounter.ngc +utilities_xmdf::xmdfSetData $instance FileSet $fcount type ngc +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path wordcounter.vhd +utilities_xmdf::xmdfSetData $instance FileSet $fcount type vhdl +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path wordcounter.vho +utilities_xmdf::xmdfSetData $instance FileSet $fcount type vhdl_template +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path wordcounter.xco +utilities_xmdf::xmdfSetData $instance FileSet $fcount type coregen_ip +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path wordcounter_blk_mem_gen_v2_8_xst_1.ngc_xst.xrpt +utilities_xmdf::xmdfSetData $instance FileSet $fcount type AnyView +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path wordcounter_xmdf.tcl +utilities_xmdf::xmdfSetData $instance FileSet $fcount type AnyView +incr fcount + +utilities_xmdf::xmdfSetData $instance FileSet $fcount associated_module wordcounter +incr fcount + +} + +# ::gen_comp_name_xmdf::xmdfApplyParams diff --git a/rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTester.ucf b/rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTester.ucf new file mode 120000 index 00000000..36290050 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTester.ucf @@ -0,0 +1 @@ +IBLcableTester.ucf.cable.newHSIO \ No newline at end of file diff --git a/rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTester.ucf.cable.newHSIO b/rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTester.ucf.cable.newHSIO new file mode 100644 index 00000000..0eb4ae2e --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTester.ucf.cable.newHSIO @@ -0,0 +1,460 @@ +#----------------------------------------------------------------------------- +# Title : LCLS BNL ASIC Test FPGA, Constraints File +# Project : LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# File : BnlAsic.ucf +# Author : Ryan Herbst, rherbst@slac.stanford.edu +# Created : 07/21/2008 +#----------------------------------------------------------------------------- +# Description: +# This file contains all of the user constraints required to implement the +# LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# Copyright (c) 2008 by Ryan Herbst. All rights reserved. +#----------------------------------------------------------------------------- +# Modification history +# 07/21/2008: created. +#----------------------------------------------------------------------------- + + +#----------------------------------------------------------------------------- +#-------------------------- Timing Constraints ------------------------------- +#----------------------------------------------------------------------------- +# This section contains the timing constraints for the FPGA +#----------------------------------------------------------------------------- + +# Define system clocks +NET pgpClk TNM_NET = FFS pgpClk; +NET sysClk125 TNM_NET = FFS sysClk125; +NET clk80 TNM_NET = FFS clk80; +NET clk40 TNM_NET = FFS clk40; +NET "U_IBLcableTesterCore/phaseclk" TNM_NET = "U_BnlAsicCore_phaseclk"; + +# Define system clocks +TIMESPEC TS_pgpClk = PERIOD pgpClk 156.25 Mhz HIGH 50%; +TIMESPEC TS_sysClk125 = PERIOD sysClk125 39.0625 Mhz HIGH 50%; +TIMESPEC TS_clk80 = PERIOD clk80 78.125 Mhz HIGH 50%; +TIMESPEC TS_clk40 = PERIOD clk40 39.0625 Mhz HIGH 50%; +TIMESPEC TS_phaseclk = PERIOD "U_BnlAsicCore_phaseclk" 78.125 Mhz HIGH 50%; + +# Define time groups for inter-clock constraints +TIMEGRP TG_pgpClk_r = RISING pgpClk; +TIMEGRP TG_sysClk125_r = RISING sysClk125; +TIMEGRP TG_clk80_r = RISING clk80; +TIMEGRP TG_clk40_r = RISING clk40; + +# Inter Domain Constraints +TIMESPEC TS_pgpClk_r_sysClk125_r = FROM TG_pgpClk_r TO TG_sysClk125_r 6.4ns; +TIMESPEC TS_sysClk125_r_pgpClk_r = FROM TG_sysClk125_r TO TG_pgpClk_r 6.4ns; +TIMESPEC TS_clk40_r_clk80_r = FROM TG_clk40_r TO TG_clk80_r 12.8ns; + +# Nets to ignore for timing +NET "iResetInL" TIG; +timespec ts_02 = from ffs(*bz(0):*cz(0):*dz(0):*dz(1)) to ffs 640 MHz; +NET serialinb(*) maxskew = 250 ps ; +INST "U_IBLcableTesterCore/*U_pattern_mem/*receivedata/ff_*" IOB=FALSE; + + +#----------------------------------------------------------------------------- +#-------------------------- Pin Location Constraints ------------------------- +#----------------------------------------------------------------------------- +# This section contains the pin location constraints for the design +#----------------------------------------------------------------------------- +# Old P5 = New P5 +# Old P4 = New P4 +# Old P9 = New P3 +# Old P3 = New P2 + + +NET "iPgpRefClkP" LOC = "J1"; +NET "iPgpRefClkM" LOC = "K1"; +NET "iMainClkP" LOC = "H17"; +NET "iMainClkN" LOC = "J17"; +#fiber 1 +#NET "iMgtRxN" LOC = "N1"; +#NET "iMgtRxP" LOC = "M1"; +#NET "oMgtTxN" LOC = "T1"; +#NET "oMgtTxP" LOC = "R1"; +#fiber 2 +NET "iMgtRxN" LOC = "AA1"; +NET "iMgtRxP" LOC = "Y1"; +NET "oMgtTxN" LOC = "V1"; +NET "oMgtTxP" LOC = "U1"; +NET "iResetInL" LOC = "AJ19"; +NET "oDispClk" LOC = "AG22"; +NET "oDispDat" LOC = "AJ22"; +NET "oDispLoadL(1)" LOC = "AK17"; +NET "oDispLoadL(0)" LOC = "Ak18"; +NET "oDispRstL" LOC = "AH22"; +NET "oDebug(0)" LOC = "n10"; +NET "oDebug(1)" LOC = "n9"; +NET "oDebug(2)" LOC = "n8"; +NET "oDebug(3)" LOC = "n7"; +NET "oDebug(4)" LOC = "j6"; +NET "oDebug(5)" LOC = "k6"; +NET "oDebug(6)" LOC = "l6"; +NET "oDebug(7)" LOC = "l5"; +NET "oDebug(8)" LOC = "k4"; +NET "oDebug(9)" LOC = "k3"; +NET "oDebug(10)" LOC = "l4"; +NET "oDebug(11)" LOC = "l3"; +NET "oDebug(12)" LOC = "m6"; +NET "oDebug(13)" LOC = "m5"; +NET "oDebug(14)" LOC = "m3"; +NET "oDebug(15)" LOC = "n3"; +#NET "doricreset" LOC = "R26"; +#NET "rclk" LOC = "AM21"; +# fiber 1 +NET "transDis1" LOC = "AK4"; +#NET "clkout40" LOC = "F5"; +#NET "clkout40" IOSTANDARD="LVCMOS25"; +#NET "clkout40" SLEW="FAST"; +#NET "oClock40" SLEW="FAST"; +#NET "oClock40" LOC = "L4"; +#NET "oClock40" IOSTANDARD="LVCMOS25"; +#NET "oClk160_p" LOC = "T5"; +#NET "oClk160_n" LOC = "T4"; +##NET "oClk40_p" LOC = "P7"; +##NET "oClk40_n" LOC = "P6"; +#NET "iClock160_p" LOC = "J6"; +#NET "iClock160_n" LOC = "K6"; +#NET "iClock160_p" IOSTANDARD="ULVDS_25"; +#NET "iClock160_n" IOSTANDARD="ULVDS_25"; +#NET "iClock160_p" CLOCK_DEDICATED_ROUTE = FALSE; + +# VDC inputs DTO +NET "serialin_p(0)" LOC = "J25"; +NET "serialin_p(1)" LOC = "E24"; +NET "serialin_p(2)" LOC = "G22"; +NET "serialin_p(3)" LOC = "H24"; +NET "serialin_p(4)" LOC = "AJ16"; +NET "serialin_p(5)" LOC = "AE13"; +NET "serialin_p(6)" LOC = "AF15"; + +# VDC inputs DTO2 +NET "serialin_p(7)" LOC = "AH15"; +NET "serialin_p(8)" LOC = "AC12"; +NET "serialin_p(9)" LOC = "AG13"; +NET "serialin_p(10)" LOC = "AD11"; +NET "serialin_p(11)" LOC = "AD10"; +NET "serialin_p(12)" LOC = "AE14"; +NET "serialin_p(13)" LOC = "AB11"; +NET "serialin_p(14)" LOC = "AD14"; +NET "serialin_p(15)" LOC = "AB13"; + +# CMD receive +NET "serialin_p(16)" LOC = "N30"; +NET "serialin_p(17)" LOC = "N29"; +NET "serialin_p(18)" LOC = "L29"; +NET "serialin_p(19)" LOC = "R29"; +NET "serialin_p(20)" LOC = "N27"; +NET "serialin_p(21)" LOC = "M32"; +NET "serialin_p(22)" LOC = "G32"; +NET "serialin_p(23)" LOC = "K29"; +# CLK receive +NET "serialin_p(24)" LOC = "P32"; +NET "serialin_p(25)" LOC = "P31"; +NET "serialin_p(26)" LOC = "R32"; +NET "serialin_p(27)" LOC = "R28"; +NET "serialin_p(28)" LOC = "K32"; +NET "serialin_p(29)" LOC = "L31"; +NET "serialin_p(30)" LOC = "E32"; +NET "serialin_p(31)" LOC = "J32"; + +# VDC inputs DTO +NET "serialin_n(0)" LOC = "H25"; +NET "serialin_n(1)" LOC = "F24"; +NET "serialin_n(2)" LOC = "H22"; +NET "serialin_n(3)" LOC = "J24"; +NET "serialin_n(4)" LOC = "AK16"; +NET "serialin_n(5)" LOC = "AF13"; +NET "serialin_n(6)" LOC = "AG15"; +NET "serialin_n(7)" LOC = "AJ15"; + + +# VDC inputs DTO2 +NET "serialin_n(8)" LOC = "AB12"; +NET "serialin_n(9)" LOC = "AH13"; +NET "serialin_n(10)" LOC = "AE11"; +NET "serialin_n(11)" LOC = "AD9"; +NET "serialin_n(12)" LOC = "AF14"; +NET "serialin_n(13)" LOC = "AA11"; +NET "serialin_n(14)" LOC = "AC13"; +NET "serialin_n(15)" LOC = "AA13"; + +# CMD receive +NET "serialin_n(16)" LOC = "M30"; +NET "serialin_n(17)" LOC = "N28"; +NET "serialin_n(18)" LOC = "L28"; +NET "serialin_n(19)" LOC = "P29"; +NET "serialin_n(20)" LOC = "M28"; +NET "serialin_n(21)" LOC = "M31"; +NET "serialin_n(22)" LOC = "G31"; +NET "serialin_n(23)" LOC = "J29"; + +# CLK receive +NET "serialin_n(24)" LOC = "N32"; +NET "serialin_n(25)" LOC = "P30"; +NET "serialin_n(26)" LOC = "R31"; +NET "serialin_n(27)" LOC = "R27"; +NET "serialin_n(28)" LOC = "K31"; +NET "serialin_n(29)" LOC = "L30"; +NET "serialin_n(30)" LOC = "F31"; +NET "serialin_n(31)" LOC = "H32"; + + +# OUTPUTS + +# Data outputs DTO +NET "serialout_p(0)" LOC = "AF9"; +NET "serialout_p(1)" LOC = "AG12"; +NET "serialout_p(2)" LOC = "AL10"; +NET "serialout_p(3)" LOC = "AF10"; +NET "serialout_p(4)" LOC = "AL9"; +NET "serialout_p(5)" LOC = "AH14"; +NET "serialout_p(6)" LOC = "AL11"; +NET "serialout_p(7)" LOC = "AH10"; +NET "serialout_p(8)" LOC = "AK13"; +NET "serialout_p(9)" LOC = "AJ12"; +NET "serialout_p(10)" LOC = "AK14"; +NET "serialout_p(11)" LOC = "AH8"; +NET "serialout_p(12)" LOC = "AM8"; +NET "serialout_p(13)" LOC = "AJ9"; +NET "serialout_p(14)" LOC = "AM13"; +NET "serialout_p(15)" LOC = "AK7"; + + + +# CMD output +NET "serialout_p(16)" LOC = "K26"; +NET "serialout_p(17)" LOC = "D21"; +NET "serialout_p(18)" LOC = "P22"; +NET "serialout_p(19)" LOC = "E19"; +NET "serialout_p(20)" LOC = "L21"; +NET "serialout_p(21)" LOC = "L26"; +NET "serialout_p(22)" LOC = "P24"; +NET "serialout_p(23)" LOC = "K24"; + +# CLK output +NET "serialout_p(24)" LOC = "D30"; +NET "serialout_p(25)" LOC = "D29"; +NET "serialout_p(26)" LOC = "M26"; +NET "serialout_p(27)" LOC = "D32"; +NET "serialout_p(28)" LOC = "E31"; +NET "serialout_p(29)" LOC = "H28"; +NET "serialout_p(30)" LOC = "G30"; +NET "serialout_p(31)" LOC = "H30"; + + +# Data outputs DTO +NET "serialout_n(0)" LOC = "AE9"; +NET "serialout_n(1)" LOC = "AH12"; +NET "serialout_n(2)" LOC = "AM10"; +NET "serialout_n(3)" LOC = "AG10"; +NET "serialout_n(4)" LOC = "AK9"; +NET "serialout_n(5)" LOC = "AJ14"; +NET "serialout_n(6)" LOC = "AM11"; +NET "serialout_n(7)" LOC = "AJ10"; +NET "serialout_n(8)" LOC = "AL13"; +NET "serialout_n(9)" LOC = "AK12"; +NET "serialout_n(10)" LOC = "AL14"; +NET "serialout_n(11)" LOC = "AH7"; +NET "serialout_n(12)" LOC = "AM7"; +NET "serialout_n(13)" LOC = "AH9"; +NET "serialout_n(14)" LOC = "AM12"; +NET "serialout_n(15)" LOC = "AJ7"; + + + +# CMD output +NET "serialout_n(16)" LOC = "J26"; +NET "serialout_n(17)" LOC = "E21"; +NET "serialout_n(18)" LOC = "N22"; +NET "serialout_n(19)" LOC = "F19"; +NET "serialout_n(20)" LOC = "M22"; +NET "serialout_n(21)" LOC = "L25"; +NET "serialout_n(22)" LOC = "N24"; +NET "serialout_n(23)" LOC = "L24"; + +# CLK output +NET "serialout_n(24)" LOC = "C30"; +NET "serialout_n(25)" LOC = "C29"; +NET "serialout_n(26)" LOC = "M25"; +NET "serialout_n(27)" LOC = "C32"; +NET "serialout_n(28)" LOC = "D31"; +NET "serialout_n(29)" LOC = "H27"; +NET "serialout_n(30)" LOC = "F30"; +NET "serialout_n(31)" LOC = "H29"; + +#-----------------------------------------------------------------------------; +#-------------------------- IO Standard Constraints -------------------------- +#----------------------------------------------------------------------------- +# This section defines the IO types, IO delays and other IO parameters +#----------------------------------------------------------------------------- + +NET "iResetInL" IOSTANDARD = "LVCMOS33"; +NET "oDispClk" IOSTANDARD = "LVCMOS33"; +NET "oDispDat" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(1)" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(0)" IOSTANDARD = "LVCMOS33"; +NET "oDispRstL" IOSTANDARD = "LVCMOS33"; +NET "oDebug(0)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(1)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(2)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(3)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(4)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(5)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(6)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(7)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(8)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(9)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(10)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(11)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(12)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(13)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(14)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(15)" IOSTANDARD = "LVCMOS25"; +NET "doricreset" IOSTANDARD = "LVCMOS25"; + +NET "serialin_p(0)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(1)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(2)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(3)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(4)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(5)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(6)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(7)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(8)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(9)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(10)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(11)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(12)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(13)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(14)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(15)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(16)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(17)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(18)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(19)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(20)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(21)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(22)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(23)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(24)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(25)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(26)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(27)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(28)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(29)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(30)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(31)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(0)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(1)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(2)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(3)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(4)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(5)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(6)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(7)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(8)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(9)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(10)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(11)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(12)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(13)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(14)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(15)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(16)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(17)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(18)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(19)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(20)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(21)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(22)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(23)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(24)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(25)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(26)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(27)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(28)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(29)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(30)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(31)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(0)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(1)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(2)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(3)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(4)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(5)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(6)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(7)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(8)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(9)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(10)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(11)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(12)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(13)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(14)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(15)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(16)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(17)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(18)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(19)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(20)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(21)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(22)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(23)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(24)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(25)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(26)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(27)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(28)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(29)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(30)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(31)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(0)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(1)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(2)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(3)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(4)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(5)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(6)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(7)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(8)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(9)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(10)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(11)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(12)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(13)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(14)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(15)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(16)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(17)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(18)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(19)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(20)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(21)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(22)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(23)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(24)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(25)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(26)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(27)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(28)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(29)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(30)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(31)" IOSTANDARD = "LVDS_25"; + +#NET "clk40" IOSTANDARD = "LVCMOS25"; +#NET "rclk" IOSTANDARD = "LVCMOS25"; +NET "transDis1" IOSTANDARD = "LVCMOS25"; +#NET "clk40" SLEW = "FAST"; +#NET "rclk" SLEW = "FAST"; + + +#----------------------------------------------------------------------------- +#-------------------------- Logic Location Constraints ----------------------- +#----------------------------------------------------------------------------- +#INST "U_BnlAsicCore/U_AsicControl/U_ClockGen" AREA_GROUP = "AG_U_BnlAsicCore/U_AsicControl/U_ClockGen" ; +#AREA_GROUP "AG_U_BnlAsicCore/U_AsicControl/U_ClockGen" RANGE = SLICE_X52Y93:SLICE_X66Y29 ; + diff --git a/rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTester.ucf.cable.oldHSIO b/rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTester.ucf.cable.oldHSIO new file mode 100644 index 00000000..5728a6fa --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTester.ucf.cable.oldHSIO @@ -0,0 +1,457 @@ +#----------------------------------------------------------------------------- +# Title : LCLS BNL ASIC Test FPGA, Constraints File +# Project : LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# File : BnlAsic.ucf +# Author : Ryan Herbst, rherbst@slac.stanford.edu +# Created : 07/21/2008 +#----------------------------------------------------------------------------- +# Description: +# This file contains all of the user constraints required to implement the +# LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# Copyright (c) 2008 by Ryan Herbst. All rights reserved. +#----------------------------------------------------------------------------- +# Modification history +# 07/21/2008: created. +#----------------------------------------------------------------------------- + + +#----------------------------------------------------------------------------- +#-------------------------- Timing Constraints ------------------------------- +#----------------------------------------------------------------------------- +# This section contains the timing constraints for the FPGA +#----------------------------------------------------------------------------- + +# Define system clocks +NET pgpClk TNM_NET = FFS pgpClk; +NET sysClk125 TNM_NET = FFS sysClk125; +NET clk80 TNM_NET = FFS clk80; +NET clk40 TNM_NET = FFS clk40; +NET "U_IBLcableTesterCore/phaseclk" TNM_NET = "U_BnlAsicCore_phaseclk"; + +# Define system clocks +TIMESPEC TS_pgpClk = PERIOD pgpClk 156.25 Mhz HIGH 50%; +TIMESPEC TS_sysClk125 = PERIOD sysClk125 39.0625 Mhz HIGH 50%; +TIMESPEC TS_clk80 = PERIOD clk80 78.125 Mhz HIGH 50%; +TIMESPEC TS_clk40 = PERIOD clk40 39.0625 Mhz HIGH 50%; +TIMESPEC TS_phaseclk = PERIOD "U_BnlAsicCore_phaseclk" 78.125 Mhz HIGH 50%; + +# Define time groups for inter-clock constraints +TIMEGRP TG_pgpClk_r = RISING pgpClk; +TIMEGRP TG_sysClk125_r = RISING sysClk125; +TIMEGRP TG_clk80_r = RISING clk80; +TIMEGRP TG_clk40_r = RISING clk40; + +# Inter Domain Constraints +TIMESPEC TS_pgpClk_r_sysClk125_r = FROM TG_pgpClk_r TO TG_sysClk125_r 6.4ns; +TIMESPEC TS_sysClk125_r_pgpClk_r = FROM TG_sysClk125_r TO TG_pgpClk_r 6.4ns; +TIMESPEC TS_clk40_r_clk80_r = FROM TG_clk40_r TO TG_clk80_r 12.8ns; + +# Nets to ignore for timing +NET "iResetInL" TIG; + + +#----------------------------------------------------------------------------- +#-------------------------- Pin Location Constraints ------------------------- +#----------------------------------------------------------------------------- +# This section contains the pin location constraints for the design +#----------------------------------------------------------------------------- +# Old P5 = New P5 +# Old P4 = New P4 +# Old P9 = New P3 +# Old P3 = New P2 + + +NET "iPgpRefClkP" LOC = "J1"; +NET "iPgpRefClkM" LOC = "K1"; +NET "iMainClkP" LOC = "H17"; +NET "iMainClkN" LOC = "J17"; +#fiber 1 +#NET "iMgtRxN" LOC = "N1"; +#NET "iMgtRxP" LOC = "M1"; +#NET "oMgtTxN" LOC = "T1"; +#NET "oMgtTxP" LOC = "R1"; +#fiber 2 +NET "iMgtRxN" LOC = "AA1"; +NET "iMgtRxP" LOC = "Y1"; +NET "oMgtTxN" LOC = "V1"; +NET "oMgtTxP" LOC = "U1"; +NET "iResetInL" LOC = "AJ19"; +NET "oDispClk" LOC = "AG22"; +NET "oDispDat" LOC = "AJ22"; +NET "oDispLoadL(1)" LOC = "AK17"; +NET "oDispLoadL(0)" LOC = "Ak18"; +NET "oDispRstL" LOC = "AH22"; +NET "oDebug(0)" LOC = "n10"; +NET "oDebug(1)" LOC = "n9"; +NET "oDebug(2)" LOC = "n8"; +NET "oDebug(3)" LOC = "n7"; +NET "oDebug(4)" LOC = "j6"; +NET "oDebug(5)" LOC = "k6"; +NET "oDebug(6)" LOC = "l6"; +NET "oDebug(7)" LOC = "l5"; +NET "oDebug(8)" LOC = "k4"; +NET "oDebug(9)" LOC = "k3"; +NET "oDebug(10)" LOC = "l4"; +NET "oDebug(11)" LOC = "l3"; +NET "oDebug(12)" LOC = "m6"; +NET "oDebug(13)" LOC = "m5"; +NET "oDebug(14)" LOC = "m3"; +NET "oDebug(15)" LOC = "n3"; +#NET "doricreset" LOC = "R26"; +#NET "rclk" LOC = "AM21"; +# fiber 1 +NET "transDis1" LOC = "AE27"; +#NET "clkout40" LOC = "F5"; +#NET "clkout40" IOSTANDARD="LVCMOS25"; +#NET "clkout40" SLEW="FAST"; +#NET "oClock40" SLEW="FAST"; +#NET "oClock40" LOC = "L4"; +#NET "oClock40" IOSTANDARD="LVCMOS25"; +#NET "oClk160_p" LOC = "T5"; +#NET "oClk160_n" LOC = "T4"; +##NET "oClk40_p" LOC = "P7"; +##NET "oClk40_n" LOC = "P6"; +#NET "iClock160_p" LOC = "J6"; +#NET "iClock160_n" LOC = "K6"; +#NET "iClock160_p" IOSTANDARD="ULVDS_25"; +#NET "iClock160_n" IOSTANDARD="ULVDS_25"; +#NET "iClock160_p" CLOCK_DEDICATED_ROUTE = FALSE; + +# VDC inputs DTO +NET "serialin_p(0)" LOC = "J25"; +NET "serialin_p(1)" LOC = "E24"; +NET "serialin_p(2)" LOC = "G22"; +NET "serialin_p(3)" LOC = "H24"; +NET "serialin_p(4)" LOC = "AJ16"; +NET "serialin_p(5)" LOC = "AE13"; +NET "serialin_p(6)" LOC = "AF15"; + +# VDC inputs DTO2 +NET "serialin_p(7)" LOC = "AH15"; +NET "serialin_p(8)" LOC = "AC12"; +NET "serialin_p(9)" LOC = "AG13"; +NET "serialin_p(10)" LOC = "AD11"; +NET "serialin_p(11)" LOC = "AD10"; +NET "serialin_p(12)" LOC = "AE14"; +NET "serialin_p(13)" LOC = "AB11"; +NET "serialin_p(14)" LOC = "AD14"; +NET "serialin_p(15)" LOC = "AB13"; + +# CMD receive +NET "serialin_p(16)" LOC = "N30"; +NET "serialin_p(17)" LOC = "N29"; +NET "serialin_p(18)" LOC = "L29"; +NET "serialin_p(19)" LOC = "R29"; +NET "serialin_p(20)" LOC = "N27"; +NET "serialin_p(21)" LOC = "M32"; +NET "serialin_p(22)" LOC = "G32"; +NET "serialin_p(23)" LOC = "K29"; +# CLK receive +NET "serialin_p(24)" LOC = "P32"; +NET "serialin_p(25)" LOC = "P31"; +NET "serialin_p(26)" LOC = "R32"; +NET "serialin_p(27)" LOC = "R28"; +NET "serialin_p(28)" LOC = "K32"; +NET "serialin_p(29)" LOC = "L31"; +NET "serialin_p(30)" LOC = "E32"; +NET "serialin_p(31)" LOC = "J32"; + +# VDC inputs DTO +NET "serialin_n(0)" LOC = "H25"; +NET "serialin_n(1)" LOC = "F24"; +NET "serialin_n(2)" LOC = "H22"; +NET "serialin_n(3)" LOC = "J24"; +NET "serialin_n(4)" LOC = "AK16"; +NET "serialin_n(5)" LOC = "AF13"; +NET "serialin_n(6)" LOC = "AG15"; +NET "serialin_n(7)" LOC = "AJ15"; + + +# VDC inputs DTO2 +NET "serialin_n(8)" LOC = "AB12"; +NET "serialin_n(9)" LOC = "AH13"; +NET "serialin_n(10)" LOC = "AE11"; +NET "serialin_n(11)" LOC = "AD9"; +NET "serialin_n(12)" LOC = "AF14"; +NET "serialin_n(13)" LOC = "AA11"; +NET "serialin_n(14)" LOC = "AC13"; +NET "serialin_n(15)" LOC = "AA13"; + +# CMD receive +NET "serialin_n(16)" LOC = "M30"; +NET "serialin_n(17)" LOC = "N28"; +NET "serialin_n(18)" LOC = "L28"; +NET "serialin_n(19)" LOC = "P29"; +NET "serialin_n(20)" LOC = "M28"; +NET "serialin_n(21)" LOC = "M31"; +NET "serialin_n(22)" LOC = "G31"; +NET "serialin_n(23)" LOC = "J29"; + +# CLK receive +NET "serialin_n(24)" LOC = "N32"; +NET "serialin_n(25)" LOC = "P30"; +NET "serialin_n(26)" LOC = "R31"; +NET "serialin_n(27)" LOC = "R27"; +NET "serialin_n(28)" LOC = "K31"; +NET "serialin_n(29)" LOC = "L30"; +NET "serialin_n(30)" LOC = "F31"; +NET "serialin_n(31)" LOC = "H32"; + + +# OUTPUTS + +# Data outputs DTO +NET "serialout_p(0)" LOC = "AF9"; +NET "serialout_p(1)" LOC = "AG12"; +NET "serialout_p(2)" LOC = "AL10"; +NET "serialout_p(3)" LOC = "AF10"; +NET "serialout_p(4)" LOC = "AL9"; +NET "serialout_p(5)" LOC = "AH14"; +NET "serialout_p(6)" LOC = "AL11"; +NET "serialout_p(7)" LOC = "AH10"; +NET "serialout_p(8)" LOC = "AK13"; +NET "serialout_p(9)" LOC = "AJ12"; +NET "serialout_p(10)" LOC = "AK14"; +NET "serialout_p(11)" LOC = "AH8"; +NET "serialout_p(12)" LOC = "AM8"; +NET "serialout_p(13)" LOC = "AJ9"; +NET "serialout_p(14)" LOC = "AM13"; +NET "serialout_p(15)" LOC = "AK7"; + + + +# CMD output +NET "serialout_p(16)" LOC = "K26"; +NET "serialout_p(17)" LOC = "D21"; +NET "serialout_p(18)" LOC = "P22"; +NET "serialout_p(19)" LOC = "E19"; +NET "serialout_p(20)" LOC = "L21"; +NET "serialout_p(21)" LOC = "L26"; +NET "serialout_p(22)" LOC = "P24"; +NET "serialout_p(23)" LOC = "K24"; + +# CLK output +NET "serialout_p(24)" LOC = "D30"; +NET "serialout_p(25)" LOC = "D29"; +NET "serialout_p(26)" LOC = "M26"; +NET "serialout_p(27)" LOC = "D32"; +NET "serialout_p(28)" LOC = "E31"; +NET "serialout_p(29)" LOC = "H28"; +NET "serialout_p(30)" LOC = "G30"; +NET "serialout_p(31)" LOC = "H30"; + + +# Data outputs DTO +NET "serialout_n(0)" LOC = "AE9"; +NET "serialout_n(1)" LOC = "AH12"; +NET "serialout_n(2)" LOC = "AM10"; +NET "serialout_n(3)" LOC = "AG10"; +NET "serialout_n(4)" LOC = "AK9"; +NET "serialout_n(5)" LOC = "AJ14"; +NET "serialout_n(6)" LOC = "AM11"; +NET "serialout_n(7)" LOC = "AJ10"; +NET "serialout_n(8)" LOC = "AL13"; +NET "serialout_n(9)" LOC = "AK12"; +NET "serialout_n(10)" LOC = "AL14"; +NET "serialout_n(11)" LOC = "AH7"; +NET "serialout_n(12)" LOC = "AM7"; +NET "serialout_n(13)" LOC = "AH9"; +NET "serialout_n(14)" LOC = "AM12"; +NET "serialout_n(15)" LOC = "AJ7"; + + + +# CMD output +NET "serialout_n(16)" LOC = "J26"; +NET "serialout_n(17)" LOC = "E21"; +NET "serialout_n(18)" LOC = "N22"; +NET "serialout_n(19)" LOC = "F19"; +NET "serialout_n(20)" LOC = "M22"; +NET "serialout_n(21)" LOC = "L25"; +NET "serialout_n(22)" LOC = "N24"; +NET "serialout_n(23)" LOC = "L24"; + +# CLK output +NET "serialout_n(24)" LOC = "C30"; +NET "serialout_n(25)" LOC = "C29"; +NET "serialout_n(26)" LOC = "M25"; +NET "serialout_n(27)" LOC = "C32"; +NET "serialout_n(28)" LOC = "D31"; +NET "serialout_n(29)" LOC = "H27"; +NET "serialout_n(30)" LOC = "F30"; +NET "serialout_n(31)" LOC = "H29"; + +#-----------------------------------------------------------------------------; +#-------------------------- IO Standard Constraints -------------------------- +#----------------------------------------------------------------------------- +# This section defines the IO types, IO delays and other IO parameters +#----------------------------------------------------------------------------- + +NET "iResetInL" IOSTANDARD = "LVCMOS33"; +NET "oDispClk" IOSTANDARD = "LVCMOS33"; +NET "oDispDat" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(1)" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(0)" IOSTANDARD = "LVCMOS33"; +NET "oDispRstL" IOSTANDARD = "LVCMOS33"; +NET "oDebug(0)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(1)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(2)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(3)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(4)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(5)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(6)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(7)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(8)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(9)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(10)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(11)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(12)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(13)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(14)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(15)" IOSTANDARD = "LVCMOS25"; +NET "doricreset" IOSTANDARD = "LVCMOS25"; + +NET "serialin_p(0)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(1)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(2)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(3)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(4)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(5)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(6)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(7)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(8)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(9)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(10)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(11)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(12)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(13)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(14)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(15)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(16)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(17)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(18)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(19)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(20)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(21)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(22)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(23)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(24)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(25)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(26)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(27)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(28)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(29)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(30)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(31)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(0)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(1)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(2)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(3)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(4)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(5)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(6)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(7)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(8)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(9)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(10)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(11)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(12)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(13)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(14)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(15)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(16)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(17)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(18)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(19)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(20)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(21)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(22)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(23)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(24)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(25)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(26)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(27)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(28)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(29)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(30)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(31)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(0)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(1)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(2)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(3)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(4)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(5)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(6)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(7)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(8)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(9)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(10)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(11)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(12)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(13)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(14)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(15)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(16)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(17)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(18)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(19)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(20)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(21)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(22)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(23)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(24)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(25)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(26)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(27)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(28)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(29)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(30)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(31)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(0)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(1)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(2)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(3)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(4)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(5)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(6)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(7)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(8)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(9)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(10)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(11)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(12)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(13)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(14)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(15)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(16)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(17)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(18)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(19)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(20)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(21)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(22)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(23)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(24)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(25)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(26)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(27)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(28)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(29)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(30)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(31)" IOSTANDARD = "LVDS_25"; + +#NET "clk40" IOSTANDARD = "LVCMOS25"; +#NET "rclk" IOSTANDARD = "LVCMOS25"; +NET "transDis1" IOSTANDARD = "LVCMOS25"; +#NET "clk40" SLEW = "FAST"; +#NET "rclk" SLEW = "FAST"; + + +#----------------------------------------------------------------------------- +#-------------------------- Logic Location Constraints ----------------------- +#----------------------------------------------------------------------------- +#INST "U_BnlAsicCore/U_AsicControl/U_ClockGen" AREA_GROUP = "AG_U_BnlAsicCore/U_AsicControl/U_ClockGen" ; +#AREA_GROUP "AG_U_BnlAsicCore/U_AsicControl/U_ClockGen" RANGE = SLICE_X52Y93:SLICE_X66Y29 ; + diff --git a/rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTester.ucf.iblbert b/rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTester.ucf.iblbert new file mode 100644 index 00000000..9c8db3d4 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTester.ucf.iblbert @@ -0,0 +1,519 @@ +#----------------------------------------------------------------------------- +# Title : LCLS BNL ASIC Test FPGA, Constraints File +# Project : LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# File : BnlAsic.ucf +# Author : Ryan Herbst, rherbst@slac.stanford.edu +# Created : 07/21/2008 +#----------------------------------------------------------------------------- +# Description: +# This file contains all of the user constraints required to implement the +# LCLS BNL ASIC Test FPGA +#----------------------------------------------------------------------------- +# Copyright (c) 2008 by Ryan Herbst. All rights reserved. +#----------------------------------------------------------------------------- +# Modification history +# 07/21/2008: created. +#----------------------------------------------------------------------------- + + +#----------------------------------------------------------------------------- +#-------------------------- Timing Constraints ------------------------------- +#----------------------------------------------------------------------------- +# This section contains the timing constraints for the FPGA +#----------------------------------------------------------------------------- + +# Define system clocks +NET pgpClk TNM_NET = FFS pgpClk; +NET sysClk125 TNM_NET = FFS sysClk125; +NET sysClk250 TNM_NET = FFS sysClk250; +NET clk80 TNM_NET = FFS clk80; +NET clk40 TNM_NET = FFS clk40; +#NET "U_BnlAsicCore/fxclock" TNM_NET = "U_BnlAsicCore_fxclock"; +NET "U_IBLcableTesterCore/phaseclk" TNM_NET = "U_BnlAsicCore_phaseclk"; +# NET "U_BnlAsicCore/serclk" TNM_NET = "U_BnlAsicCore_serclk"; + +# Define system clocks +TIMESPEC TS_pgpClk = PERIOD pgpClk 156.25 Mhz HIGH 50%; +TIMESPEC TS_sysClk125 = PERIOD sysClk125 39.0625 Mhz HIGH 50%; +TIMESPEC TS_sysClk250 = PERIOD sysClk250 78.125 Mhz HIGH 50%; +TIMESPEC TS_clk80 = PERIOD clk80 78.125 Mhz HIGH 50%; +TIMESPEC TS_clk40 = PERIOD clk40 39.0625 Mhz HIGH 50%; +#TIMESPEC TS_fxclock = PERIOD "U_BnlAsicCore_fxclock" 78.125 Mhz HIGH 50%; +# TIMESPEC TS_serclk = PERIOD "U_BnlAsicCore_serclk" 200 Mhz HIGH 50%; +TIMESPEC TS_phaseclk = PERIOD "U_BnlAsicCore_phaseclk" 78.125 Mhz HIGH 50%; + +# Define time groups for inter-clock constraints +TIMEGRP TG_pgpClk_r = RISING pgpClk; +TIMEGRP TG_sysClk125_r = RISING sysClk125; +TIMEGRP TG_sysClk250_r = RISING sysClk250; +TIMEGRP TG_clk80_r = RISING clk80; +TIMEGRP TG_clk40_r = RISING clk40; + +# Inter Domain Constraints +TIMESPEC TS_pgpClk_r_sysClk125_r = FROM TG_pgpClk_r TO TG_sysClk125_r 6.4ns; +TIMESPEC TS_sysClk125_r_pgpClk_r = FROM TG_sysClk125_r TO TG_pgpClk_r 6.4ns; +TIMESPEC TS_sysClk125_r_sysClk250_r = FROM TG_sysClk125_r TO TG_sysClk250_r 12.8ns; +# TIMESPEC TS_clk80_r_clk160_r = FROM TG_clk80_r TO TG_clk160_r 8ns; +TIMESPEC TS_clk40_r_clk80_r = FROM TG_clk40_r TO TG_clk80_r 12.8ns; + +# Nets to ignore for timing +NET "iResetInL" TIG; + + +#----------------------------------------------------------------------------- +#-------------------------- Pin Location Constraints ------------------------- +#----------------------------------------------------------------------------- +# This section contains the pin location constraints for the design +#----------------------------------------------------------------------------- +# Old P5 = New P5 +# Old P4 = New P4 +# Old P9 = New P3 +# Old P3 = New P2 + + +NET "iPgpRefClkP" LOC = "J1"; +NET "iPgpRefClkM" LOC = "K1"; +NET "iMainClkP" LOC = "H17"; +NET "iMainClkN" LOC = "J17"; +#fiber 1 +#NET "iMgtRxN" LOC = "N1"; +#NET "iMgtRxP" LOC = "M1"; +#NET "oMgtTxN" LOC = "T1"; +#NET "oMgtTxP" LOC = "R1"; +#fiber 2 +NET "iMgtRxN" LOC = "AA1"; +NET "iMgtRxP" LOC = "Y1"; +NET "oMgtTxN" LOC = "V1"; +NET "oMgtTxP" LOC = "U1"; +NET "iResetInL" LOC = "AJ19"; +NET "oDispClk" LOC = "AG22"; +NET "oDispDat" LOC = "AJ22"; +NET "oDispLoadL(1)" LOC = "AK17"; +NET "oDispLoadL(0)" LOC = "Ak18"; +NET "oDispRstL" LOC = "AH22"; +NET "oDebug(0)" LOC = "n10"; +NET "oDebug(1)" LOC = "n9"; +NET "oDebug(2)" LOC = "n8"; +NET "oDebug(3)" LOC = "n7"; +NET "oDebug(4)" LOC = "j6"; +NET "oDebug(5)" LOC = "k6"; +NET "oDebug(6)" LOC = "l6"; +NET "oDebug(7)" LOC = "l5"; +NET "oDebug(8)" LOC = "k4"; +NET "oDebug(9)" LOC = "k3"; +NET "oDebug(10)" LOC = "l4"; +NET "oDebug(11)" LOC = "l3"; +NET "oDebug(12)" LOC = "m6"; +NET "oDebug(13)" LOC = "m5"; +NET "oDebug(14)" LOC = "m3"; +NET "oDebug(15)" LOC = "n3"; +NET "doricreset" LOC = "R26"; +#NET "rclk" LOC = "AM21"; +# fiber 1 +#NET "transDis1" LOC = "AH4"; +# fiber 2 +NET "transDis1" LOC = "AK4"; +#NET "clkout40" LOC = "F5"; +#NET "clkout40" IOSTANDARD="LVCMOS25"; +#NET "clkout40" SLEW="FAST"; +#NET "oClock40" SLEW="FAST"; +#NET "oClock40" LOC = "L4"; +#NET "oClock40" IOSTANDARD="LVCMOS25"; +#NET "oClk160_p" LOC = "T5"; +#NET "oClk160_n" LOC = "T4"; +##NET "oClk40_p" LOC = "P7"; +##NET "oClk40_n" LOC = "P6"; +#NET "iClock160_p" LOC = "J6"; +#NET "iClock160_n" LOC = "K6"; +#NET "iClock160_p" IOSTANDARD="ULVDS_25"; +#NET "iClock160_n" IOSTANDARD="ULVDS_25"; +#NET "iClock160_p" CLOCK_DEDICATED_ROUTE = FALSE; + +# VDC inputs DTO +NET "serialin_p(0)" LOC = "G22"; +NET "serialin_p(1)" LOC = "H24"; +NET "serialin_p(2)" LOC = "AJ16"; +NET "serialin_p(3)" LOC = "AE13"; +NET "serialin_p(4)" LOC = "AF15"; +NET "serialin_p(5)" LOC = "AH15"; +NET "serialin_p(6)" LOC = "AB13"; + +# VDC inputs DTO2 +NET "serialin_p(7)" LOC = "AD14"; +NET "serialin_p(8)" LOC = "AB11"; +NET "serialin_p(9)" LOC = "AE14"; +NET "serialin_p(10)" LOC = "AD10"; +NET "serialin_p(11)" LOC = "AD11"; +NET "serialin_p(12)" LOC = "AG13"; +NET "serialin_p(13)" LOC = "AC12"; + +#not used, cross-talk line +# NET "serialin_p(14)" LOC = "F29"; +# NET "serialin_p(15)" LOC = "H28"; + +# CMD receive +NET "serialin_p(16)" LOC = "G30"; +NET "serialin_p(17)" LOC = "D32"; +NET "serialin_p(18)" LOC = "D29"; +NET "serialin_p(19)" LOC = "K24"; +NET "serialin_p(20)" LOC = "L26"; +NET "serialin_p(21)" LOC = "E19"; +NET "serialin_p(22)" LOC = "D21"; + +# not used, cross-talk line +#NET "serialin_p(23)" LOC = "M32"; + +# VDC inputs DTO +NET "serialin_n(0)" LOC = "H22"; +NET "serialin_n(1)" LOC = "J24"; +NET "serialin_n(2)" LOC = "AK16"; +NET "serialin_n(3)" LOC = "AF13"; +NET "serialin_n(4)" LOC = "AG15"; +NET "serialin_n(5)" LOC = "AJ15"; +NET "serialin_n(6)" LOC = "AA13"; + + +# VDC inputs DTO2 +NET "serialin_n(7)" LOC = "AC13"; +NET "serialin_n(8)" LOC = "AA11"; +NET "serialin_n(9)" LOC = "AF14"; +NET "serialin_n(10)" LOC = "AD9"; +NET "serialin_n(11)" LOC = "AE11"; +NET "serialin_n(12)" LOC = "AH13"; +NET "serialin_n(13)" LOC = "AB12"; + + +# NET "serialin_n(14)" LOC = "E29"; +# NET "serialin_n(15)" LOC = "H27"; + +# CMD receive +NET "serialin_n(16)" LOC = "F30"; +NET "serialin_n(17)" LOC = "C32"; +NET "serialin_n(18)" LOC = "C29"; +NET "serialin_n(19)" LOC = "L24"; +NET "serialin_n(20)" LOC = "L25"; +NET "serialin_n(21)" LOC = "F19"; +NET "serialin_n(22)" LOC = "E21"; + +# not used, cross-talk line +# NET "serialin_n(23)" LOC = "M31"; + +# Data outputs DTO +NET "serialout_p(1)" LOC = "R29"; +NET "serialout_p(3)" LOC = "N29"; +NET "serialout_p(5)" LOC = "U28"; +NET "serialout_p(7)" LOC = "N27"; +NET "serialout_p(9)" LOC = "M32"; +NET "serialout_p(11)" LOC = "G32"; +NET "serialout_p(13)" LOC = "T31"; + + +# Data outputs DTO2 +NET "serialout_p(0)" LOC = "T29"; +NET "serialout_p(2)" LOC = "R32"; +NET "serialout_p(4)" LOC = "N30"; +NET "serialout_p(6)" LOC = "K32"; +NET "serialout_p(8)" LOC = "L31"; +NET "serialout_p(10)" LOC = "E32"; +NET "serialout_p(12)" LOC = "J32"; + +# Cross-talk 80 Mb/s +#NET "serialout_p(14)" LOC = "AH14"; +#NET "serialout_p(15)" LOC = "AF10"; +NET "serialoutxtf_p(0)" LOC = "AM13"; +NET "serialoutxtf_p(1)" LOC = "AK14"; +NET "serialoutxtf_p(2)" LOC = "AL11"; +NET "serialoutxtf_p(3)" LOC = "AL10"; +NET "serialoutxtf_p(4)" LOC = "AK7"; + +# output to DORIC +NET "serialout_p(16)" LOC = "AG12"; +NET "serialout_p(18)" LOC = "AF10"; +NET "serialout_p(17)" LOC = "AH14"; +NET "serialout_p(22)" LOC = "AH10"; +NET "serialout_p(21)" LOC = "AJ12"; +NET "serialout_p(20)" LOC = "AH8"; +NET "serialout_p(19)" LOC = "AF11"; + +#NET "serialout_p(23)" LOC = "AD10"; + +#cross-talk 40 Mb/s +NET "serialoutxts_p(0)" LOC = "AM8"; +NET "serialoutxts_p(1)" LOC = "AK13"; +NET "serialoutxts_p(2)" LOC = "AL9"; +NET "serialoutxts_p(3)" LOC = "AF9"; +NET "serialoutxts_p(4)" LOC = "AJ9"; + +# Data outputs DTO +NET "serialout_n(1)" LOC = "P29"; +NET "serialout_n(3)" LOC = "N28"; +NET "serialout_n(5)" LOC = "U27"; +NET "serialout_n(7)" LOC = "M28"; +NET "serialout_n(9)" LOC = "M31"; +NET "serialout_n(11)" LOC = "G31"; +NET "serialout_n(13)" LOC = "T30"; + +# Data outputs DTO2 +NET "serialout_n(0)" LOC = "T28"; +NET "serialout_n(2)" LOC = "R31"; +NET "serialout_n(4)" LOC = "M30"; +NET "serialout_n(6)" LOC = "K31"; +NET "serialout_n(8)" LOC = "L30"; +NET "serialout_n(10)" LOC = "F31"; +NET "serialout_n(12)" LOC = "H32"; + +# cross-talk 80 Mb/s +#NET "serialout_n(14)" LOC = "AJ14"; +#NET "serialout_n(15)" LOC = "AG10"; +NET "serialoutxtf_n(0)" LOC = "AM12"; +NET "serialoutxtf_n(1)" LOC = "AL14"; +NET "serialoutxtf_n(2)" LOC = "AM11"; +NET "serialoutxtf_n(3)" LOC = "AM10"; +NET "serialoutxtf_n(4)" LOC = "AJ7"; + +# output to DORIC +NET "serialout_n(16)" LOC = "AH12"; +NET "serialout_n(18)" LOC = "AG10"; +NET "serialout_n(17)" LOC = "AJ14"; +NET "serialout_n(22)" LOC = "AJ10"; +NET "serialout_n(21)" LOC = "AK12"; +NET "serialout_n(20)" LOC = "AH7"; +NET "serialout_n(19)" LOC = "AG11"; + +# cross-talk 40 Mb/s +#NET "serialout_n(23)" LOC = "AD9"; +NET "serialoutxts_n(0)" LOC = "AM7"; +NET "serialoutxts_n(1)" LOC = "AL13"; +NET "serialoutxts_n(2)" LOC = "AK9"; +NET "serialoutxts_n(3)" LOC = "AE9"; +NET "serialoutxts_n(4)" LOC = "AH9"; + +# Return clock +NET "retclock_p(16)" LOC = "H28"; +NET "retclock_p(17)" LOC = "M26"; +NET "retclock_p(18)" LOC = "D30"; +NET "retclock_p(19)" LOC = "P24"; +NET "retclock_p(20)" LOC = "L21"; +NET "retclock_p(21)" LOC = "P22"; +NET "retclock_p(22)" LOC = "K26"; + +#unused, cross-talk line +#NET "retclock_p(23)" LOC = "L31"; + +# Return clock +NET "retclock_n(16)" LOC = "H27"; +NET "retclock_n(17)" LOC = "M25"; +NET "retclock_n(18)" LOC = "C30"; +NET "retclock_n(19)" LOC = "N24"; +NET "retclock_n(20)" LOC = "M22"; +NET "retclock_n(21)" LOC = "N22"; +NET "retclock_n(22)" LOC = "J26"; + +#unused, cross-talk line +#NET "retclock_n(23)" LOC = "L30"; +#-----------------------------------------------------------------------------; +#-------------------------- IO Standard Constraints -------------------------- +#----------------------------------------------------------------------------- +# This section defines the IO types, IO delays and other IO parameters +#----------------------------------------------------------------------------- + +NET "iResetInL" IOSTANDARD = "LVCMOS33"; +NET "oDispClk" IOSTANDARD = "LVCMOS33"; +NET "oDispDat" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(1)" IOSTANDARD = "LVCMOS33"; +NET "oDispLoadL(0)" IOSTANDARD = "LVCMOS33"; +NET "oDispRstL" IOSTANDARD = "LVCMOS33"; +NET "oDebug(0)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(1)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(2)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(3)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(4)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(5)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(6)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(7)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(8)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(9)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(10)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(11)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(12)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(13)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(14)" IOSTANDARD = "LVCMOS25"; +NET "oDebug(15)" IOSTANDARD = "LVCMOS25"; +NET "doricreset" IOSTANDARD = "LVCMOS25"; + +NET "serialin_p(0)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(1)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(2)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(3)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(4)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(5)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(6)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(7)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(8)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(9)" IOSTANDARD = "LVDS_25"; + NET "serialin_p(10)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(11)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(12)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(13)" IOSTANDARD = "LVDS_25"; + NET "serialin_p(14)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(15)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(16)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(17)" IOSTANDARD = "LVDS_25"; + NET "serialin_p(18)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(19)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(20)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(21)" IOSTANDARD = "LVDS_25"; + NET "serialin_p(22)" IOSTANDARD = "LVDS_25"; +NET "serialin_p(23)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(0)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(1)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(2)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(3)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(4)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(5)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(6)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(7)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(8)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(9)" IOSTANDARD = "LVDS_25"; + NET "serialin_n(10)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(11)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(12)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(13)" IOSTANDARD = "LVDS_25"; + NET "serialin_n(14)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(15)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(16)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(17)" IOSTANDARD = "LVDS_25"; + NET "serialin_n(18)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(19)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(20)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(21)" IOSTANDARD = "LVDS_25"; + NET "serialin_n(22)" IOSTANDARD = "LVDS_25"; +NET "serialin_n(23)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(0)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(1)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(2)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(3)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(4)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(5)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(6)" IOSTANDARD = "LVDS_25"; +# NET "serialout_p(7)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(8)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(9)" IOSTANDARD = "LVDS_25"; +# NET "serialout_p(10)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(11)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(12)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(13)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(14)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(15)" IOSTANDARD = "LVDS_25"; +#NET "serialout_p(16)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(17)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(18)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(19)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(20)" IOSTANDARD = "LVDS_25"; +#NET "serialout_p(21)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(22)" IOSTANDARD = "LVDS_25"; +NET "serialout_p(23)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(0)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(1)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(2)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(3)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(4)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(5)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(6)" IOSTANDARD = "LVDS_25"; +#NET "serialout_n(7)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(8)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(9)" IOSTANDARD = "LVDS_25"; +# NET "serialout_n(10)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(11)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(12)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(13)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(14)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(15)" IOSTANDARD = "LVDS_25"; +# NET "serialout_n(16)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(17)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(18)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(19)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(20)" IOSTANDARD = "LVDS_25"; +#NET "serialout_n(21)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(22)" IOSTANDARD = "LVDS_25"; +NET "serialout_n(23)" IOSTANDARD = "LVDS_25"; + +NET "retclock_p(16)" IOSTANDARD = "LVDS_25"; +NET "retclock_p(17)" IOSTANDARD = "LVDS_25"; +NET "retclock_p(18)" IOSTANDARD = "LVDS_25"; +NET "retclock_p(19)" IOSTANDARD = "LVDS_25"; +NET "retclock_p(20)" IOSTANDARD = "LVDS_25"; +NET "retclock_p(21)" IOSTANDARD = "LVDS_25"; +NET "retclock_p(22)" IOSTANDARD = "LVDS_25"; +NET "retclock_p(23)" IOSTANDARD = "LVDS_25"; +NET "retclock_n(16)" IOSTANDARD = "LVDS_25"; +NET "retclock_n(17)" IOSTANDARD = "LVDS_25"; +NET "retclock_n(18)" IOSTANDARD = "LVDS_25"; +NET "retclock_n(19)" IOSTANDARD = "LVDS_25"; +NET "retclock_n(20)" IOSTANDARD = "LVDS_25"; +NET "retclock_n(21)" IOSTANDARD = "LVDS_25"; +NET "retclock_n(22)" IOSTANDARD = "LVDS_25"; +NET "retclock_n(23)" IOSTANDARD = "LVDS_25"; + +NET "serialout_p(0)" SLEW = "FAST"; +NET "serialout_p(1)" SLEW = "FAST"; +NET "serialout_p(2)" SLEW = "FAST"; +NET "serialout_p(3)" SLEW = "FAST"; +NET "serialout_p(4)" SLEW = "FAST"; +NET "serialout_p(5)" SLEW = "FAST"; +NET "serialout_p(6)" SLEW = "FAST"; +NET "serialout_p(7)" SLEW = "FAST"; +NET "serialout_p(8)" SLEW = "FAST"; +NET "serialout_p(9)" SLEW = "FAST"; +# NET "serialout_p(10)" SLEW = "FAST"; +NET "serialout_p(11)" SLEW = "FAST"; +NET "serialout_p(12)" SLEW = "FAST"; +NET "serialout_p(13)" SLEW = "FAST"; +# NET "serialout_p(14)" SLEW = "FAST"; +NET "serialout_p(15)" SLEW = "FAST"; +NET "serialout_p(16)" SLEW = "FAST"; +NET "serialout_p(17)" SLEW = "FAST"; +NET "serialout_p(18)" SLEW = "FAST"; +NET "serialout_p(19)" SLEW = "FAST"; +# NET "serialout_p(20)" SLEW = "FAST"; +NET "serialout_p(21)" SLEW = "FAST"; +NET "serialout_p(22)" SLEW = "FAST"; +NET "serialout_p(23)" SLEW = "FAST"; +NET "serialout_n(0)" SLEW = "FAST"; +NET "serialout_n(1)" SLEW = "FAST"; +NET "serialout_n(2)" SLEW = "FAST"; +NET "serialout_n(3)" SLEW = "FAST"; +NET "serialout_n(4)" SLEW = "FAST"; +NET "serialout_n(5)" SLEW = "FAST"; +NET "serialout_n(6)" SLEW = "FAST"; +NET "serialout_n(7)" SLEW = "FAST"; +NET "serialout_n(8)" SLEW = "FAST"; +NET "serialout_n(9)" SLEW = "FAST"; +# NET "serialout_n(10)" SLEW = "FAST"; +NET "serialout_n(11)" SLEW = "FAST"; +NET "serialout_n(12)" SLEW = "FAST"; +NET "serialout_n(13)" SLEW = "FAST"; +# NET "serialout_n(14)" SLEW = "FAST"; +NET "serialout_n(15)" SLEW = "FAST"; +NET "serialout_n(16)" SLEW = "FAST"; +NET "serialout_n(17)" SLEW = "FAST"; +NET "serialout_n(18)" SLEW = "FAST"; +NET "serialout_n(19)" SLEW = "FAST"; +# NET "serialout_n(20)" SLEW = "FAST"; +NET "serialout_n(21)" SLEW = "FAST"; +NET "serialout_n(22)" SLEW = "FAST"; +NET "serialout_n(23)" SLEW = "FAST"; +#NET "clk40" IOSTANDARD = "LVCMOS25"; +#NET "rclk" IOSTANDARD = "LVCMOS25"; +NET "transDis1" IOSTANDARD = "LVCMOS25"; +#NET "clk40" SLEW = "FAST"; +#NET "rclk" SLEW = "FAST"; + + +#----------------------------------------------------------------------------- +#-------------------------- Logic Location Constraints ----------------------- +#----------------------------------------------------------------------------- +#INST "U_BnlAsicCore/U_AsicControl/U_ClockGen" AREA_GROUP = "AG_U_BnlAsicCore/U_AsicControl/U_ClockGen" ; +#AREA_GROUP "AG_U_BnlAsicCore/U_AsicControl/U_ClockGen" RANGE = SLICE_X52Y93:SLICE_X66Y29 ; + diff --git a/rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTester.vhd b/rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTester.vhd new file mode 100755 index 00000000..054abd6a --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTester.vhd @@ -0,0 +1,523 @@ +------------------------------------------------------------------------------- +-- Title : BNL ASIC Test FGPA, Top Level +-- Project : LCLS Detector, BNL ASIC +------------------------------------------------------------------------------- +-- File : BnlAsic.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 07/21/2008 +------------------------------------------------------------------------------- +-- Description: +-- Top level logic for BNL ASIC test FPGA. +------------------------------------------------------------------------------- +-- Copyright (c) 2008 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 07/21/2008: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +Library Unisim; +USE ieee. std_logic_1164.ALL; +use ieee. std_logic_arith.all; +use ieee. std_logic_unsigned.all; +USE work.ALL; + +entity IBLcableTester is + port ( + + -- PGP Crystal Clock Input, 156.25Mhz + iPgpRefClkP : in std_logic; + iPgpRefClkM : in std_logic; + + -- System clock 125 MHz clock input + iMainClkP : in std_logic; + iMainClkN : in std_logic; + + oClock40 : out std_logic; + iClock160_p : in std_logic; + iClock160_n : in std_logic; + oClk160_p : out std_logic; + oClk160_n : out std_logic; + oClk40_p : out std_logic; + oClk40_n : out std_logic; + -- PGP Rx/Tx Lines + iMgtRxN : in std_logic; + iMgtRxP : in std_logic; + oMgtTxN : out std_logic; + oMgtTxP : out std_logic; + + -- ATLAS Pixel module pins + serialin_p : in std_logic_vector(31 downto 0); + serialin_n : in std_logic_vector(31 downto 0); + serialout_p : out std_logic_vector(31 downto 0); + serialout_n : out std_logic_vector(31 downto 0); + retclock_p : in std_logic_vector(23 downto 16); + retclock_n : in std_logic_vector(23 downto 16); + serialoutxtf_p : out std_logic_vector(4 downto 0); + serialoutxtf_n : out std_logic_vector(4 downto 0); + serialoutxts_p : out std_logic_vector(4 downto 0); + serialoutxts_n : out std_logic_vector(4 downto 0); + doricreset : out std_logic; + clkout40 : out std_logic; + + -- Reset button + iResetInL : in std_logic; + + -- LED Display + oDispClk : out std_logic; + oDispDat : out std_logic; + oDispLoadL : out std_logic_vector(1 downto 0); + oDispRstL : out std_logic; + + -- Debug + oDebug : out std_logic_vector(15 downto 0); + + -- Misc Signals + oPdBuff0 : out std_logic; + oPdBuff1 : out std_logic; + oPdBuff3 : out std_logic; + oPdBuff4 : out std_logic; + oLemoA : out std_logic; + iLemoB : in std_logic; + + -- Transmitter enable + transDis1 : out std_logic + ); +end IBLcableTester; + + +-- Define architecture for top level module +architecture IBLcableTester of IBLcableTester is + + -- Synthesis control attributes + attribute syn_useioff : boolean; + attribute syn_useioff of IBLcableTester : architecture is true; + attribute xc_fast_auto : boolean; + attribute xc_fast_auto of IBLcableTester : architecture is false; + attribute syn_noclockbuf : boolean; + attribute syn_noclockbuf of IBLcableTester : architecture is true; + + -- IO Pad components + component IBUF port ( O : out std_logic; I : in std_logic ); end component; + component OBUF port ( O : out std_logic; I : in std_logic ); end component; + component OBUFDS + generic( IOSTANDARD: STRING:= "LVDS_25"; + SLEW: STRING:="FAST"); + port ( O : out std_logic; OB : out std_logic; I : in std_logic ); + end component; + + -- Input LVDS with termination + component IBUFDS + generic ( DIFF_TERM : boolean := FALSE; + IOSTANDARD: STRING := "LVDS_25"); + port ( O : out std_logic; I : in std_logic; IB : in std_logic ); + end component; + + -- Xilinx global clock buffer component + component BUFGMUX + port ( + O : out std_logic; + I0 : in std_logic; + I1 : in std_logic; + S : in std_logic + ); + end component; + + + -- PGP Clock Generator + component PgpClkGen + generic ( + RefClkEn1 : string := "ENABLE"; -- ENABLE or DISABLE + RefClkEn2 : string := "DISABLE"; -- ENABLE or DISABLE + DcmClkSrc : string := "RefClk1"; -- RefClk1 or RefClk2 + UserFxDiv : integer := 5; -- DCM FX Output Divide + UserFxMult : integer := 4 -- DCM FX Output Divide, 4/5 * 156.25 = 125Mhz + ); + port ( + + -- Reference Clock Pad Inputs + pgpRefClkInP : in std_logic; + pgpRefClkInN : in std_logic; + + -- Power On Reset Input + ponResetL : in std_logic; + + -- Locally Generated Reset + locReset : in std_logic; + + -- Reference Clock To PGP MGT + -- Use one, See RefClkEn1 & RefClkEn2 Generics + pgpRefClk1 : out std_logic; + pgpRefClk2 : out std_logic; + + -- Global Clock & Reset For PGP Logic, 156.25Mhz + pgpClk : out std_logic; + pgpClk90 : out std_logic; + pgpReset : out std_logic; + + -- Global Clock & Reset For User Logic, 125Mhz + userClk : out std_logic; + userReset : out std_logic; + + -- Inputs clocks for reset generation connect + -- to pgpClk and userClk + pgpClkIn : in std_logic; + userClkIn : in std_logic + ); + end component; + + + -- Core Logic + component IBLcableTesterCore + port ( + sysClk250 : in std_logic; + sysClk125 : in std_logic; + sysRst125 : in std_logic; + sysRst250 : in std_logic; + refClock : in std_logic; + pgpClk : in std_logic; + pgpClk90 : in std_logic; + pgpReset : in std_logic; + mgtRxN : in std_logic; + mgtRxP : in std_logic; + mgtTxN : out std_logic; + mgtTxP : out std_logic; + serialin : in std_logic_vector(31 downto 0); + serialout : out std_logic_vector(31 downto 0); + retclock : in std_logic_vector(23 downto 16); + clock160 : in std_logic; + clock80 : in std_logic; + clock40 : in std_logic; + doricreset : out std_logic; + resetOut : out std_logic; + dispClk : out std_logic; + dispDat : out std_logic; + dispLoadL : out std_logic_vector(1 downto 0); + dispRstL : out std_logic; + debug : out std_logic_vector(15 downto 0) + ); + end component; + component clock160 + port ( + CLKIN_N_IN : in std_logic; + CLKIN_P_IN : in std_logic; + RST_IN : in std_logic; + CLKFX_OUT : out std_logic; + CLKIN_IBUFGDS_OUT : out std_logic; + CLK0_OUT : out std_logic; + LOCKED_OUT : out std_logic); + end component; +component IDELAY + generic (IOBDELAY_TYPE : string := "DEFAULT"; --(DEFAULT, FIXED, VARIABLE) + IOBDELAY_VALUE : integer := 0 --(0 to 63) + ); + port ( + O : out STD_LOGIC; + I : in STD_LOGIC; + C : in STD_LOGIC; + CE : in STD_LOGIC; + INC : in STD_LOGIC; + RST : in STD_LOGIC + ); +end component; +--component ila + --PORT ( + --CONTROL : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0); + --CLK : IN STD_LOGIC; + --DATA : IN STD_LOGIC_VECTOR(31 DOWNTO 0); + --TRIG0 : IN STD_LOGIC_VECTOR(0 DOWNTO 0)); +-- +--end component; + --component icon + --PORT ( + --CONTROL0 : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0)); +-- + --end component; + + + -- Local signals + signal resetInL : std_logic; + signal tmpClk250 : std_logic; + signal sysClk125 : std_logic; + signal sysRst125 : std_logic; + signal sysRst250 : std_logic; + signal sysClk250 : std_logic; + signal refClock : std_logic; + signal pgpClk : std_logic; + signal pgpClk90 : std_logic; + signal clk160 : std_logic; + signal clk80 : std_logic; + signal clk40 : std_logic; + signal pgpReset : std_logic; + signal resetOut : std_logic; + signal mgtRxN : std_logic; + signal mgtRxP : std_logic; + signal mgtTxN : std_logic; + signal mgtTxP : std_logic; + signal dispClk : std_logic; + signal dispDat : std_logic; + signal dispLoadL : std_logic_vector(1 downto 0); + signal dispRstL : std_logic; + signal debug : std_logic_vector(15 downto 0); + signal sysClk125i : std_logic; + signal doricresetb : std_logic; + signal mainClk : std_logic; + signal clk0 : std_logic; + signal clkin : std_logic; + signal holdrst : std_logic; + signal halfclock : std_logic; + signal clockfast : std_logic; + signal quarterclock : std_logic; + signal serialoutb : std_logic_vector(31 downto 0); + signal serialinb : std_logic_vector(31 downto 0); + signal retclockb : std_logic_vector(23 downto 16); + signal retclockd : std_logic_vector(23 downto 16); + signal retclocki : std_logic_vector(23 downto 16); + signal ccontrol: std_logic_vector(35 downto 0); + signal cdata: std_logic_vector(31 downto 0); + signal ctrig: std_logic_vector(0 downto 0); + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + + -- Black Box Attributes +-- attribute syn_noprune : boolean; +-- attribute syn_noprune of chipscope : label is true; +-- attribute syn_noprune of chipscopeicon : label is true; + attribute syn_black_box : boolean; + attribute syn_noprune : boolean; + attribute syn_black_box of IBUF : component is TRUE; + attribute syn_noprune of IBUF : component is TRUE; + attribute syn_black_box of OBUF : component is TRUE; + attribute syn_noprune of OBUF : component is TRUE; + attribute syn_black_box of IBUFDS : component is TRUE; + attribute syn_noprune of IBUFDS : component is TRUE; + attribute syn_black_box of OBUFDS : component is TRUE; + attribute syn_noprune of OBUFDS : component is TRUE; + attribute syn_black_box of BUFGMUX : component is TRUE; + attribute syn_noprune of BUFGMUX : component is TRUE; +begin + + -- Reset input + U_ResetIn: IBUF port map ( I => iResetInL, O => resetInL ); + + -- PGP Clock Generator + U_PgpClkGen: PgpClkGen generic map ( + RefClkEn1 => "ENABLE", + RefClkEn2 => "DISABLE", + DcmClkSrc => "RefClk1", + UserFxDiv => 4, + UserFxMult => 2 + ) port map ( + pgpRefClkInP => iPgpRefClkP, + pgpRefClkInN => iPgpRefClkM, + ponResetL => resetInL, + locReset => resetOut, + pgpRefClk1 => refClock, + pgpRefClk2 => open, + pgpClk => pgpClk, + pgpClk90 => pgpClk90, + pgpReset => pgpReset, + pgpClkIn => pgpClk, + userClk => sysClk125, + userReset => sysRst125, + userClkIn => sysClk125 + ); + + -- Generate Divided Clock, sample reset + process ( pgpClk ) begin + if rising_edge(pgpClk) then + tmpClk250 <= not tmpClk250 after tpd; + sysRst250 <= sysRst125 after tpd; + end if; + end process; + + -- Global Buffer For 125Mhz Clock + U_CLK250: BUFGMUX port map ( + O => sysClk250, + I0 => tmpClk250, + I1 => '0', + S => '0' + ); + + -- No Pads for MGT Lines + mgtRxN <= iMgtRxN; + mgtRxP <= iMgtRxP; + oMgtTxN <= mgtTxN; + oMgtTxP <= mgtTxP; + + -- LED Display + U_DispClk : OBUF port map ( I => dispClk , O => oDispClk ); + U_DispDat : OBUF port map ( I => dispDat , O => oDispDat ); + U_DispLoadL1 : OBUF port map ( I => dispLoadL(1) , O => oDispLoadL(1) ); + U_DispLoadL0 : OBUF port map ( I => dispLoadL(0) , O => oDispLoadL(0) ); + U_DispRstL : OBUF port map ( I => dispRstL , O => oDispRstL ); + U_clkout40 : OBUF port map ( I => clk40 , O => clkout40 ); + + + -- Debug + U_Debug0 : OBUF port map ( I => debug(0) , O => oDebug(0) ); + U_Debug1 : OBUF port map ( I => debug(1) , O => oDebug(1) ); + U_Debug2 : OBUF port map ( I => debug(2) , O => oDebug(2) ); + U_Debug3 : OBUF port map ( I => debug(3) , O => oDebug(3) ); + U_Debug4 : OBUF port map ( I => debug(4) , O => oDebug(4) ); + U_Debug5 : OBUF port map ( I => debug(5) , O => oDebug(5) ); + U_Debug6 : OBUF port map ( I => debug(6) , O => oDebug(6) ); + U_Debug7 : OBUF port map ( I => debug(7) , O => oDebug(7) ); + U_Debug8 : OBUF port map ( I => debug(8) , O => oDebug(8) ); + U_Debug9 : OBUF port map ( I => debug(9) , O => oDebug(9) ); + U_Debug10 : OBUF port map ( I => debug(10) , O => oDebug(10) ); + U_Debug11 : OBUF port map ( I => debug(11) , O => oDebug(11) ); + U_Debug12 : OBUF port map ( I => debug(12) , O => oDebug(12) ); + U_Debug13 : OBUF port map ( I => debug(13) , O => oDebug(13) ); + U_Debug14 : OBUF port map ( I => debug(14) , O => oDebug(14) ); + U_Debug15 : OBUF port map ( I => debug(15) , O => oDebug(15) ); + +-- U_clock40out : OBUF port map ( I => quarterclock , O => oClock40 ); +-- U_serialout1 : OBUFDS generic map ( +-- IOSTANDARD=>"LVDS_25", +-- SLEW=>"FAST") +-- port map ( I => mainClk , O => serialout_p(1) , OB => serialout_n(1) ); +-- U_serialout2 : OBUFDS generic map ( +-- IOSTANDARD=>"LVDS_25", +-- SLEW=>"FAST") +-- port map ( I => clkin , O => serialout_p(2) , OB => serialout_n(2) ); +-- U_clockout40 : OBUFDS generic map ( +-- IOSTANDARD=>"LVDS_25", +---- SLEW=>"FAST") +-- port map ( I => quarterclock , O => oClk40_p , OB => oClk40_n ); +-- U_clockout160 : OBUFDS generic map ( +-- IOSTANDARD=>"LVDS_25", +-- SLEW=>"FAST") +-- port map ( I => pgpClk , O => oClk160_p , OB => oClk160_n ); +-- U_clockin160 : IBUFDS generic map ( DIFF_TERM=>TRUE, +-- IOSTANDARD=>"ULVDS_25") +-- port map ( I => iClock160_p , IB=>iClock160_n , O => clk160 ); + + SERIAL_IO_DATA: + for I in 0 to 31 generate + U_serialout : OBUFDS generic map ( + IOSTANDARD=>"LVDS_25", + SLEW=>"FAST") + port map ( I => serialoutb(I) , O => serialout_p(I) , OB => serialout_n(I) ); + +-- SERIAL_IO_DATA_in: +-- for I in 0 to 15 generate + U_serialin : IBUFDS generic map ( DIFF_TERM=>TRUE, + IOSTANDARD=>"LVDS_25") + port map ( I => serialin_p(I) , IB=>serialin_n(I) , O => serialinb(I) ); + end generate SERIAL_IO_DATA; +-- end generate SERIAL_IO_DATA_in; + +-- SERIAL_IO_CMD: +-- for I in 16 to 23 generate +-- delayline : IDELAY +-- generic map ( +-- IOBDELAY_TYPE => "FIXED", -- Set to DEFAULT for -- Zero Hold Time Mode +-- IOBDELAY_VALUE => 10 -- (0 to 63) +-- ) +-- port map ( +-- O => retclockd(I), +-- I => retclockb(I), +-- C => '0', +-- CE => '0', +-- INC => '0', +-- RST => '0' +-- ); +-- --retclockd(I)<= not retclocki(I); +-- U_serialout : OBUFDS generic map ( +-- IOSTANDARD=>"LVDS_25", +-- SLEW=>"FAST") +-- port map ( I => serialoutb(I) , O => serialout_p(I) , OB => serialout_n(I) ); +-- +-- U_serialin : IBUFDS generic map ( DIFF_TERM=>TRUE, +-- IOSTANDARD=>"LVDS_25") +-- port map ( I => serialin_p(I) , IB=>serialin_n(I) , O => serialinb(I) ); +-- U_retclock : IBUFDS generic map ( DIFF_TERM=>TRUE, +-- IOSTANDARD=>"LVDS_25") +-- port map ( I => retclock_p(I) , IB=>retclock_n(I) , O => retclockb(I) ); +-- end generate SERIAL_IO_CMD; + +-- CROSSTALK: +-- for I in 0 to 4 generate +-- U_xtalkf : OBUFDS generic map ( +-- IOSTANDARD=>"LVDS_25", +---- SLEW=>"FAST") +-- port map ( I => serialoutb(15) , O => serialoutxtf_p(I) , OB => serialoutxtf_n(I) ); +-- +-- U_xtalks : OBUFDS generic map ( +-- IOSTANDARD=>"LVDS_25", +-- SLEW=>"FAST") +-- port map ( I => serialoutb(23) , O => serialoutxts_p(I) , OB => serialoutxts_n(I) ); +-- +-- end generate CROSSTALK; +-- +-- U_doric : OBUF port map ( I => doricresetb , O => doricreset ); + U_link : OBUF port map ( I => '0' , O => transDis1 ); + + + -- FPGA Core + U_IBLcableTesterCore: IBLcableTesterCore port map ( + sysClk250 => sysClk250, sysRst250 => sysRst250, + sysClk125 => sysClk125, sysRst125 => sysRst125, + refClock => refClock, pgpClk => pgpClk, + pgpClk90 => pgpClk90, + pgpReset => pgpReset, mgtRxN => mgtRxN, + mgtRxP => mgtRxP, mgtTxN => mgtTxN, + mgtTxP => mgtTxP, serialin => serialinb, + serialout => serialoutb, retclock => retclockb, + clock160 => pgpClk, + clock80 => sysClk250, clock40 => sysClk125, + doricreset => doricresetb, resetOut => resetOut, + dispClk => dispClk, dispDat => dispDat, + dispLoadL => dispLoadL, dispRstL => dispRstL, + debug => debug + ); + --sysClk125i <= not sysClk125; + sysClk125i<=debug(0); +-- U_clock160: clock160 port map( +-- CLKIN_N_IN => iMainClkN, +-- CLKIN_P_IN => iMainClkP, +-- RST_IN => sysRst125, +-- CLKFX_OUT => open, +-- CLKIN_IBUFGDS_OUT => clkin, +-- CLK0_OUT => clk0, +-- LOCKED_OUT => open); + process(pgpClk) + begin + if(pgpClk'event and pgpClk='1') then + halfclock<= not halfclock; + end if; + end process; + process(halfclock) + begin + if(halfclock'event and halfclock='1') then + quarterclock<= not quarterclock; + end if; + end process; + process(pgpClk) + begin + if(pgpClk'event and pgpClk='1') then + clk80<= not clk80; + end if; + end process; + process(clk80) + begin + if(clk80'event and clk80='1') then + clk40<= not clk40; + end if; + end process; + --cdata(7 downto 0)<=serialinb(7 downto 0); + --cdata(31 downto 8) <=(others=>'0'); + --ctrig(0)<='0'; + --chipscope : ila + --port map ( + --CONTROL => ccontrol, + --CLK => mainClk, + --DATA => cdata, + --TRIG0 => ctrig); + --chipscopeicon : icon + --port map ( + --CONTROL0 => ccontrol); + +end IBLcableTester; diff --git a/rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTesterCore.vhd b/rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTesterCore.vhd new file mode 100644 index 00000000..0e14f9f3 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTesterCore.vhd @@ -0,0 +1,670 @@ +------------------------------------------------------------------------------- +-- Title : BNL ASIC Test FGPA Core +-- Project : LCLS Detector, BNL ASIC +------------------------------------------------------------------------------- +-- File : IBLcableTesterCore.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 07/21/2008 +------------------------------------------------------------------------------- +-- Description: +-- Core logic for BNL ASIC test FPGA. +------------------------------------------------------------------------------- +-- Copyright (c) 2008 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 07/21/2008: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity IBLcableTesterCore is + port ( + + -- Master system clock, 250Mhz, 125Mhz + sysClk250 : in std_logic; + sysClk125 : in std_logic; + sysRst125 : in std_logic; + sysRst250 : in std_logic; + + -- PGP Clocks + refClock : in std_logic; + pgpClk : in std_logic; + pgpClk90 : in std_logic; + pgpReset : in std_logic; + + -- MGT Serial Pins + mgtRxN : in std_logic; + mgtRxP : in std_logic; + mgtTxN : out std_logic; + mgtTxP : out std_logic; + + -- ATLAS Pixel module pins + serialin : in std_logic_vector(31 downto 0); + serialout : out std_logic_vector(31 downto 0); + retclock : in std_logic_vector(23 downto 16); + clock160 : in std_logic; + clock80 : in std_logic; + clock40 : in std_logic; + doricreset : out std_logic; +-- serialclkout : out std_logic; + + -- Reset out to PGP Clock generation + resetOut : out std_logic; + + -- LED Display + dispClk : out std_logic; + dispDat : out std_logic; + dispLoadL : out std_logic_vector(1 downto 0); + dispRstL : out std_logic; + + + -- Debug + debug : out std_logic_vector(15 downto 0) + ); +end IBLcableTesterCore; + + +-- Define architecture +architecture IBLcableTesterCore of IBLcableTesterCore is + + -- LED Display Controller + component DisplayControl + port ( + sysClk : in std_logic; + sysRst : in std_logic; + dispStrobe : in std_logic; + dispUpdate : in std_logic; + dispRotate : in std_logic_vector(1 downto 0); + dispDigitA : in std_logic_vector(7 downto 0); + dispDigitB : in std_logic_vector(7 downto 0); + dispDigitC : in std_logic_vector(7 downto 0); + dispDigitD : in std_logic_vector(7 downto 0); + dispClk : out std_logic; + dispDat : out std_logic; + dispLoadL : out std_logic; + dispRstL : out std_logic + ); + end component; + component pattern_mem is + generic(DELAY: integer); + port( + clk: in std_logic; + serclk: in std_logic; + deserclk: in std_logic; + deserclk90: in std_logic; + rst: in std_logic; + pgpEnable: in std_logic; + pgpRW: in std_logic; + pgpAck: out std_logic; + pgpErr: out std_logic; + dataFromPgp:in std_logic_vector(31 downto 0); + addrPgp: in std_logic_vector(3 downto 0); + dataToPgp: out std_logic_vector(31 downto 0); + dataFromFE: in std_logic; + dataToFE: out std_logic + ); + end component; + component pattern_cmd is + port( + clk: in std_logic; + serclk: in std_logic; + deserclk: in std_logic; + retclk: in std_logic; + rst: in std_logic; + doricreset: out std_logic; + pgpEnable: in std_logic; + pgpRW: in std_logic; + pgpAck: out std_logic; + pgpErr: out std_logic; + dataFromPgp:in std_logic_vector(31 downto 0); + addrPgp: in std_logic_vector(3 downto 0); + dataToPgp: out std_logic_vector(31 downto 0); + dataFromFE: in std_logic; + dataToFE: out std_logic + ); + end component; + component clock200 + port( CLKIN_IN : in std_logic; + RST_IN : in std_logic; + CLKFX_OUT : out std_logic; + CLK0_OUT : out std_logic; + LOCKED_OUT : out std_logic); + end component; + component IDELAYCTRL + port ( RDY : out std_logic; + REFCLK : in std_logic; + RST : in std_logic + ); + end component; + component phaseshift + port ( CLKIN_IN : in std_logic; + DADDR_IN : in std_logic_vector (6 downto 0); + DCLK_IN : in std_logic; + DEN_IN : in std_logic; + DI_IN : in std_logic_vector (15 downto 0); + DWE_IN : in std_logic; + RST_IN : in std_logic; + CLK0_OUT : out std_logic; + CLK90_OUT : out std_logic; + CLKFX_OUT : out std_logic; + CLK2X_OUT : out std_logic; + DRDY_OUT : out std_logic; + LOCKED_OUT : out std_logic); + --PSDONE_OUT : out std_logic); + end component; + + component OBUF port ( O : out std_logic; I : in std_logic ); end component; + -- PGP Front End Wrapper + + component PgpFrontEnd + generic ( + MgtMode : string := "A"; + RefClkSel : string := "REFCLK1" + ); + port ( + pgpRefClk1 : in std_logic; + pgpRefClk2 : in std_logic; + mgtRxRecClk : out std_logic; + pgpClk : in std_logic; + pgpReset : in std_logic; + pgpDispA : out std_logic_vector(7 downto 0); + pgpDispB : out std_logic_vector(7 downto 0); + resetOut : out std_logic; + locClk : in std_logic; + locReset : in std_logic; + cmdEn : out std_logic; + cmdOpCode : out std_logic_vector(7 downto 0); + cmdCtxOut : out std_logic_vector(23 downto 0); + regReq : out std_logic; + regOp : out std_logic; + regAck : in std_logic; + regFail : in std_logic; + regAddr : out std_logic_vector(23 downto 0); + regDataOut : out std_logic_vector(31 downto 0); + regDataIn : in std_logic_vector(31 downto 0); + frameTxEnable : in std_logic; + frameTxSOF : in std_logic; + frameTxEOF : in std_logic; + frameTxEOFE : in std_logic; + frameTxData : in std_logic_vector(15 downto 0); + valid : out std_logic; + eof :out std_logic; + sof :out std_logic; + mgtRxN : in std_logic; + mgtRxP : in std_logic; + mgtTxN : out std_logic; + mgtTxP : out std_logic; + mgtCombusIn : in std_logic_vector(15 downto 0); + mgtCombusOut : out std_logic_vector(15 downto 0) + ); + end component; + + + -- Local Signals + signal cmdEn : std_logic; + signal cmdOpCode : std_logic_vector(7 downto 0); + signal cmdCtxOut : std_logic_vector(23 downto 0); + signal readDataValid : std_logic; + signal readDataSOF : std_logic; + signal readDataEOF : std_logic; + signal readDataEOFE : std_logic; + signal readData : std_logic_vector(15 downto 0); + signal dispDatA : std_logic; + signal dispDatB : std_logic; + signal pgpDispA : std_logic_vector(7 downto 0); + signal pgpDispB : std_logic_vector(7 downto 0); + signal regReq : std_logic; + signal regOp : std_logic; + signal regAck : std_logic; + signal regFail : std_logic; + signal regAddr : std_logic_vector(23 downto 0); + signal regDataOut : std_logic_vector(31 downto 0); + signal regDataIn : std_logic_vector(31 downto 0); + signal dispDigitA : std_logic_vector(7 downto 0); + signal dispDigitB : std_logic_vector(7 downto 0); + signal dispDigitC : std_logic_vector(7 downto 0); + signal dispDigitD : std_logic_vector(7 downto 0); + signal dispDigitE : std_logic_vector(7 downto 0); + signal dispDigitF : std_logic_vector(7 downto 0); + signal dispDigitG : std_logic_vector(7 downto 0); + signal dispDigitH : std_logic_vector(7 downto 0); + signal dispStrobe : std_logic; + signal dispUpdateA : std_logic; + signal dispUpdateB : std_logic; + signal sysClkCnt : std_logic_vector(15 downto 0); + signal ack : std_logic_vector(31 downto 0); + signal err : std_logic_vector(31 downto 0); + signal eof : std_logic; + signal sof : std_logic; + signal vvalid : std_logic; + signal regAck1 : std_logic; + signal regAck2 : std_logic; + signal regAck3 : std_logic; + signal regAck4 : std_logic; + signal regFail1 : std_logic; + signal regFail2 : std_logic; + signal regFail3 : std_logic; + signal regFail4 : std_logic; + type readback is array(31 downto 0) of std_logic_vector(31 downto 0); + signal thedata : readback; + signal req : std_logic_vector(31 downto 0); + signal counter1 : std_logic_vector(7 downto 0); + signal counter2 : std_logic_vector(7 downto 0); + signal idcounter : std_logic_vector(2 downto 0); + signal daddr : std_logic_vector (6 downto 0); + signal denfx : std_logic; + signal denphase : std_logic; + signal phaseclk : std_logic; + signal sysClk90 : std_logic; + signal fxclock : std_logic; + signal serclk : std_logic; + signal drdy : std_logic; + signal drdy2 : std_logic; + signal lockedfx : std_logic; + signal lockedid : std_logic; + signal oldlockedid : std_logic; + signal lockedphase : std_logic; + signal lockednophase : std_logic; + signal reqclkfx : std_logic; + signal reqclkphase : std_logic; + signal oldreqclkfx : std_logic; + signal oldreqclkphase : std_logic; + signal clkenafx : std_logic; + signal clkenaphase : std_logic; + signal psdone : std_logic; + signal holdrst : std_logic; + signal phaserst : std_logic; + signal clockrst : std_logic; + signal clockrst2 : std_logic; + signal idctrlrst : std_logic; + signal clkdata : std_logic_vector(15 downto 0); + signal holdctr : std_logic_vector(24 downto 0); + signal clockidctrl : std_logic; + signal dreset : std_logic_vector(23 downto 16); + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + type DELAR is array (0 to 31) of integer; + constant setting: DELAR := (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); + attribute syn_noprune : boolean; + attribute syn_noprune of U_idelayctrl: label is true; + +begin + + -- Display Controller A + U_DispCntrlA: DisplayControl port map ( + sysClk => sysClk125, sysRst => sysRst125, + dispStrobe => dispStrobe, dispUpdate => dispUpdateA, + dispRotate => "01", dispDigitA => dispDigitA, + dispDigitB => dispDigitB, dispDigitC => dispDigitC, + dispDigitD => dispDigitD, dispClk => dispClk, + dispDat => dispDatA, dispLoadL => dispLoadL(0), + dispRstL => dispRstL + ); + + -- Display Controller B + U_DispCntrlB: DisplayControl port map ( + sysClk => sysClk125, sysRst => sysRst125, + dispStrobe => dispStrobe, dispUpdate => dispUpdateB, + dispRotate => "01", dispDigitA => dispDigitE, + dispDigitB => dispDigitF, dispDigitC => dispDigitG, + dispDigitD => dispDigitH, dispClk => open, + dispDat => dispDatB, dispLoadL => dispLoadL(1), + dispRstL => open + ); + + -- Output LED Data + dispDat <= dispDatA or dispDatB; + dispDigitA <= pgpDispA; + dispDigitB <= pgpDispB; + dispDigitD <= regDataIn(7 downto 0); + dispDigitC <= "0000"&lockedid&lockednophase &lockedphase & lockedfx; + dispDigitE <= "0000" & counter1(7 downto 4); + dispDigitF <= "0000" & counter1(3 downto 0); + dispDigitG <= "0000" & counter2(7 downto 4); + dispDigitH <="0000" & counter2(3 downto 0); + + + -- Generate display strobe (200ns) and update control + process ( sysClk125, sysRst125 ) begin + if sysRst125 = '1' then + sysClkCnt <= (others=>'0') after tpd; + dispStrobe <= '0' after tpd; + dispUpdateA <= '0' after tpd; + dispUpdateB <= '0' after tpd; + elsif rising_edge(sysClk125) then + + -- Display strobe, 320ns + dispStrobe <= sysClkCnt(4) after tpd; + + -- Update Display 0 + if sysClkCnt(15 downto 0) = x"8000" then + dispUpdateA <= '1' after tpd; + else + dispUpdateA <= '0' after tpd; + end if; + + -- Update Display B + if sysClkCnt(15 downto 0) = x"0000" then + dispUpdateB <= '1' after tpd; + else + dispUpdateB <= '0' after tpd; + end if; + + -- Update counter + sysClkCnt <= sysClkCnt + 1 after tpd; + + if req(0)='1' then + counter1<=unsigned(counter1)+1; + end if; + + if req(1)='1' then + counter2<=unsigned(counter2)+1; + end if; + + end if; + end process; + + + -- PGP Front End + U_PgpFrontEnd: PgpFrontEnd port map ( + pgpRefClk1 => refClock, pgpRefClk2 => '0', + mgtRxRecClk => open, pgpClk => pgpClk, + pgpReset => pgpReset, pgpDispA => pgpDispA, + pgpDispB => pgpDispB, resetOut => resetOut, + locClk => sysClk125, locReset => sysRst125, + cmdEn => cmdEn, cmdOpCode => cmdOpCode, + cmdCtxOut => cmdCtxOut, regReq => regReq, + regOp => regOp, regAck => regAck, + regFail => regFail, regAddr => regAddr, + regDataOut => regDataOut, regDataIn => regDataIn, + frameTxEnable => readDataValid, frameTxSOF => readDataSOF, + frameTxEOF => readDataEOF, frameTxEOFE => readDataEOFE, + frameTxData => readData, valid => vvalid, + eof => eof, sof => sof, + mgtRxN => mgtRxN, + mgtRxP => mgtRxP, mgtTxN => mgtTxN, + mgtTxP => mgtTxP, mgtCombusIn => (others=>'0'), + mgtCombusOut => open + ); + + clkData<=(others=>'0'); + readDataValid<='0'; + vvalid<='0'; + readDataSOF<='0'; + readDataEOF<='0'; + readDataEOFE<='0'; + readData<=(others=>'0'); + regAck1<= (ack(0) or ack(1) or ack(2) or ack(3) or ack(4) or ack(5) or ack(6) or ack(7)); + regAck2<= (ack(8) or ack(9) or ack(10) or ack(11) or ack(12) or ack(13) or ack(14) or ack(15)); + regAck3<= (ack(16) or ack(17) or ack(18) or ack(19) or ack(20) or ack(21) or ack(22) or ack(23)); + regAck4<= (ack(24) or ack(25) or ack(26) or ack(27) or ack(28) or ack(29) or ack(30) or ack(31)); + regAck<= (regAck1 or regAck2 or regAck3 or regAck4 or drdy or drdy2); + regFail1<= (err(0) or err(1) or err(2) or err(3) or err(4) or err(5) or err(6) or err(7)); + regFail2<= (err(8) or err(9) or err(10) or err(11) or err(12) or err(13) or err(14) or err(15)); + regFail3<= (err(16) or err(17) or err(18) or err(19) or err(20) or err(21) or err(22) or err(23)); + regFail4<= (err(24) or err(25) or err(26) or err(27) or err(28) or err(29) or err(30) or err(31)); + regFail<= (regFail1 or regFail2 or regFail3 or regFail4); + req(0)<='1' when regReq='1' and (regAddr(9 downto 4) = "000000" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111110") else '0'; + req(1)<='1' when regReq='1' and (regAddr(9 downto 4) = "000001" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111110") else '0'; + req(2)<='1' when regReq='1' and (regAddr(9 downto 4) = "000010" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111110") else '0'; + req(3)<='1' when regReq='1' and (regAddr(9 downto 4) = "000011" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111110") else '0'; + req(4)<='1' when regReq='1' and (regAddr(9 downto 4) = "000100" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111110") else '0'; + req(5)<='1' when regReq='1' and (regAddr(9 downto 4) = "000101" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111110") else '0'; + req(6)<='1' when regReq='1' and (regAddr(9 downto 4) = "000110" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111110") else '0'; + req(7)<='1' when regReq='1' and (regAddr(9 downto 4) = "000111" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111110") else '0'; + req(8)<='1' when regReq='1' and (regAddr(9 downto 4) = "001000" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111110") else '0'; + req(9)<='1' when regReq='1' and (regAddr(9 downto 4) = "001001" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111110") else '0'; + req(10)<='1' when regReq='1' and (regAddr(9 downto 4) = "001010" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111110") else '0'; + req(11)<='1' when regReq='1' and (regAddr(9 downto 4) = "001011" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111110") else '0'; + req(12)<='1' when regReq='1' and (regAddr(9 downto 4) = "001100" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111110") else '0'; + req(13)<='1' when regReq='1' and (regAddr(9 downto 4) = "001101" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111110") else '0'; + req(14)<='1' when regReq='1' and (regAddr(9 downto 4) = "001110" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111110") else '0'; + req(15)<='1' when regReq='1' and (regAddr(9 downto 4) = "001111" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111110") else '0'; + req(16)<='1' when regReq='1' and (regAddr(9 downto 4) = "010000" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111101") else '0'; + req(17)<='1' when regReq='1' and (regAddr(9 downto 4) = "010001" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111101") else '0'; + req(18)<='1' when regReq='1' and (regAddr(9 downto 4) = "010010" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111101") else '0'; + req(19)<='1' when regReq='1' and (regAddr(9 downto 4) = "010011" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111101") else '0'; + req(20)<='1' when regReq='1' and (regAddr(9 downto 4) = "010100" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111101") else '0'; + req(21)<='1' when regReq='1' and (regAddr(9 downto 4) = "010101" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111101") else '0'; + req(22)<='1' when regReq='1' and (regAddr(9 downto 4) = "010110" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111101") else '0'; + req(23)<='1' when regReq='1' and (regAddr(9 downto 4) = "010111" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111101") else '0'; + req(24)<='1' when regReq='1' and (regAddr(9 downto 4) = "011000" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111101") else '0'; + req(25)<='1' when regReq='1' and (regAddr(9 downto 4) = "011001" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111101") else '0'; + req(26)<='1' when regReq='1' and (regAddr(9 downto 4) = "011010" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111101") else '0'; + req(27)<='1' when regReq='1' and (regAddr(9 downto 4) = "011011" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111101") else '0'; + req(28)<='1' when regReq='1' and (regAddr(9 downto 4) = "011100" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111101") else '0'; + req(29)<='1' when regReq='1' and (regAddr(9 downto 4) = "011101" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111101") else '0'; + req(30)<='1' when regReq='1' and (regAddr(9 downto 4) = "011110" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111101") else '0'; + req(31)<='1' when regReq='1' and (regAddr(9 downto 4) = "011111" or regAddr(9 downto 4) = "111111" or regAddr(9 downto 4) = "111101") else '0'; + reqclkphase <='1' when regReq='1' and (regAddr(9 downto 4) = "111000" or regAddr(9 downto 4) = "111001" or regAddr(9 downto 4) = "111010") else '0'; + reqclkfx<='1'when regreq='1' and (regAddr(9 downto 4) = "111011" or regAddr(9 downto 4) = "111100") else '0'; + with regAddr(9 downto 4) select + regDataIn <= thedata(0) when "000000", + thedata(1) when "000001", + thedata(2) when "000010", + thedata(3) when "000011", + thedata(4) when "000100", + thedata(5) when "000101", + thedata(6) when "000110", + thedata(7) when "000111", + thedata(8) when "001000", + thedata(9) when "001001", + thedata(10) when "001010", + thedata(11) when "001011", + thedata(12) when "001100", + thedata(13) when "001101", + thedata(14) when "001110", + thedata(15) when "001111", + thedata(16) when "010000", + thedata(17) when "010001", + thedata(18) when "010010", + thedata(19) when "010011", + thedata(20) when "010100", + thedata(21) when "010101", + thedata(22) when "010110", + thedata(23) when "010111", + thedata(24) when "011000", + thedata(25) when "011001", + thedata(26) when "011010", + thedata(27) when "011011", + thedata(28) when "011100", + thedata(29) when "011101", + thedata(30) when "011110", + thedata(31) when "011111", + x"0000" & clkdata when "111010", + x"ffffffff" when others; + + PATTERN_GEN_DATA: + for I in 0 to 15 generate + + U_pattern_mem: pattern_mem + generic map( + DELAY=>setting(I)) + port map ( + clk => sysClk125, + serclk => pgpClk, --was serclk + deserclk90 => pgpClk90, + deserclk => phaseclk, + rst => sysRst125, + pgpEnable => req(I), + pgpRW => regOp, + pgpAck => ack(I), + pgpErr => err(I), + dataFromPgp => regDataOut, + addrPgp => regAddr(3 downto 0), + dataToPgp => thedata(I), + dataFromFe => serialin(I), + dataToFe => serialout(I)); +end generate PATTERN_GEN_DATA; + PATTERN_GEN_DATA_2: + for I in 16 to 31 generate + + U_pattern_mem: pattern_mem + generic map( + DELAY=>setting(I)) + port map ( + clk => sysClk125, + serclk => sysclk125, --was serclk + deserclk90 => sysclk90, + deserclk => sysclk125, + rst => sysRst125, + pgpEnable => req(I), + pgpRW => regOp, + pgpAck => ack(I), + pgpErr => err(I), + dataFromPgp => regDataOut, + addrPgp => regAddr(3 downto 0), + dataToPgp => thedata(I), + dataFromFe => serialin(I), + dataToFe => serialout(I)); +end generate PATTERN_GEN_DATA_2; + PATTERN_GEN_CMD: + for I in 16 to 15 generate + + U_pattern_cmd: pattern_cmd port map ( + clk => sysClk125, + serclk => clock80, + deserclk => clock40, + retclk => retclock(I), + rst => sysRst125, + doricreset => dreset(I), + pgpEnable => req(I), + pgpRW => regOp, + pgpAck => ack(I), + pgpErr => err(I), + dataFromPgp => regDataOut, + addrPgp => regAddr(3 downto 0), + dataToPgp => thedata(I), + dataFromFe => serialin(I), + dataToFe => serialout(I)); +end generate PATTERN_GEN_CMD; + doricreset<=dreset(20); + + clockrst<=holdrst; + clockrst2<=phaserst; + U_idelctrlclk: clock200 port map( + CLKIN_IN => clock160, + RST_IN => clockrst, + CLKFX_OUT => clockidctrl, + CLK0_OUT => open, + LOCKED_OUT => lockedid); + U_idelayctrl: IDELAYCTRL port map( + RDY => open, + REFCLK => clockidctrl, + RST => idctrlrst); + + U_clockmult: phaseshift port map( + CLKIN_IN => sysClk125, -- was clock160 + DADDR_IN => daddr, + DCLK_IN => sysClk125, + DEN_IN => denfx, + DI_IN => regDataOut(15 downto 0), + --DO_OUT => clkdata, + DWE_IN => regOp, + RST_IN => clockrst, + CLK0_OUT => open, + CLK90_OUT => sysClk90, + CLKFX_OUT => fxclock, + CLK2X_OUT => open, + DRDY_OUT => drdy, + LOCKED_OUT=> lockedfx); + --PSDONE_OUT=> open); + U_phaseshift: phaseshift port map( + CLKIN_IN => pgpClk, -- was fxclock + DADDR_IN => daddr, + DCLK_IN => sysClk125, + DEN_IN => denphase, + DI_IN => regDataOut(15 downto 0), + --DO_OUT => (others=>'0'), + DWE_IN => regOp, + RST_IN => clockrst2, + CLK0_OUT => phaseclk, -- was open + CLKFX_OUT => open, + CLK2X_OUT => open, -- was phaseclk + DRDY_OUT => drdy2, + LOCKED_OUT=> lockedphase); + --PSDONE_OUT=> psdone); + U_noshift: phaseshift port map( + CLKIN_IN => fxclock, + DADDR_IN => (others=>'0'), + DCLK_IN => sysClk125, + DEN_IN => '0', + DI_IN => (others=>'0'), + --DO_OUT => (others=>'0'), + DWE_IN => '0', + RST_IN => clockrst2, + CLK0_OUT => open, + CLKFX_OUT => open, + CLK2X_OUT => serclk, + DRDY_OUT => open, + LOCKED_OUT=> lockednophase); + --PSDONE_OUT=> open); + + + with regAddr(9 downto 4) select + daddr<="1010101" when "111000", + "0010001" when "111001", + "0000000" when "111010", + "1010000" when "111011", + "1010010" when "111100", + "0000000" when others; + process(sysRst125, sysClk125) -- clock interface + begin + if (sysRst125='1') then + holdctr<=(others=>'1'); + holdrst<='1'; + clkenafx<='1'; + elsif(sysClk125'event and sysClk125='1') then + if (reqclkfx='1' and oldreqclkfx='0') then + clkenafx<='1'; + holdctr<=x"ffffff"&'1'; + holdrst<='1'; + else + clkenafx<='0'; + if (holdctr=x"000000"&'0') then + phaserst<='0'; + else + if (holdctr(24)='0') then + holdrst<='0'; + phaserst<='1'; + end if; + holdctr<=unsigned(holdctr)-1; + end if; + end if; + if (reqclkphase='1' and oldreqclkphase='0') then + clkenaphase<='1'; + else + clkenaphase<='0'; + end if; + denfx<=clkenafx; + denphase<=clkenaphase; + oldreqclkfx<=reqclkfx; + oldreqclkphase<=reqclkphase; + end if; + end process; + process(sysClk125, sysRst125) -- reset logic for IDELAYCTRL + begin + if(sysRst125='1') then + idctrlrst<='0'; + idcounter<="000"; + oldlockedid<='0'; + elsif(sysClk125'event and sysClk125='1') then + if(lockedid='1' and oldlockedid='0')then + idcounter<="111"; + idctrlrst<='1'; + elsif(unsigned(idcounter)>0)then + idcounter<=unsigned(idcounter)-1; + else + idctrlrst<='0'; + end if; + oldlockedid<=lockedid; + end if; + end process; + +end IBLcableTesterCore; + diff --git a/rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTesterCoreOld.vhd b/rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTesterCoreOld.vhd new file mode 100644 index 00000000..277fb278 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTesterCoreOld.vhd @@ -0,0 +1,622 @@ +------------------------------------------------------------------------------- +-- Title : BNL ASIC Test FGPA Core +-- Project : LCLS Detector, BNL ASIC +------------------------------------------------------------------------------- +-- File : IBLcableTesterCore.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 07/21/2008 +------------------------------------------------------------------------------- +-- Description: +-- Core logic for BNL ASIC test FPGA. +------------------------------------------------------------------------------- +-- Copyright (c) 2008 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 07/21/2008: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +use work.all; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity IBLcableTesterCore is + port ( + + -- Master system clock, 250Mhz, 125Mhz + sysClk250 : in std_logic; + sysClk125 : in std_logic; + sysRst125 : in std_logic; + sysRst250 : in std_logic; + + -- PGP Clocks + refClock : in std_logic; + pgpClk : in std_logic; + pgpReset : in std_logic; + + -- MGT Serial Pins + mgtRxN : in std_logic; + mgtRxP : in std_logic; + mgtTxN : out std_logic; + mgtTxP : out std_logic; + + -- ATLAS Pixel module pins + serialin : in std_logic_vector(23 downto 0); + serialout : out std_logic_vector(23 downto 0); + retclock : in std_logic_vector(23 downto 16); + clock160 : in std_logic; + clock80 : in std_logic; + clock40 : in std_logic; + doricreset : out std_logic; +-- serialclkout : out std_logic; + + -- Reset out to PGP Clock generation + resetOut : out std_logic; + + -- LED Display + dispClk : out std_logic; + dispDat : out std_logic; + dispLoadL : out std_logic_vector(1 downto 0); + dispRstL : out std_logic; + + + -- Debug + debug : out std_logic_vector(15 downto 0) + ); +end IBLcableTesterCore; + + +-- Define architecture +architecture IBLcableTesterCore of IBLcableTesterCore is + + -- LED Display Controller + component DisplayControl + port ( + sysClk : in std_logic; + sysRst : in std_logic; + dispStrobe : in std_logic; + dispUpdate : in std_logic; + dispRotate : in std_logic_vector(1 downto 0); + dispDigitA : in std_logic_vector(7 downto 0); + dispDigitB : in std_logic_vector(7 downto 0); + dispDigitC : in std_logic_vector(7 downto 0); + dispDigitD : in std_logic_vector(7 downto 0); + dispClk : out std_logic; + dispDat : out std_logic; + dispLoadL : out std_logic; + dispRstL : out std_logic + ); + end component; + component pattern_mem is + generic(DELAY: integer); + port( + clk: in std_logic; + serclk: in std_logic; + deserclk: in std_logic; + rst: in std_logic; + pgpEnable: in std_logic; + pgpRW: in std_logic; + pgpAck: out std_logic; + pgpErr: out std_logic; + dataFromPgp:in std_logic_vector(31 downto 0); + addrPgp: in std_logic_vector(3 downto 0); + dataToPgp: out std_logic_vector(31 downto 0); + dataFromFE: in std_logic; + dataToFE: out std_logic + ); + end component; + component pattern_cmd is + port( + clk: in std_logic; + serclk: in std_logic; + deserclk: in std_logic; + retclk: in std_logic; + rst: in std_logic; + doricreset: out std_logic; + pgpEnable: in std_logic; + pgpRW: in std_logic; + pgpAck: out std_logic; + pgpErr: out std_logic; + dataFromPgp:in std_logic_vector(31 downto 0); + addrPgp: in std_logic_vector(3 downto 0); + dataToPgp: out std_logic_vector(31 downto 0); + dataFromFE: in std_logic; + dataToFE: out std_logic + ); + end component; + component clock200 + port( CLKIN_IN : in std_logic; + RST_IN : in std_logic; + CLKFX_OUT : out std_logic; + CLK0_OUT : out std_logic; + LOCKED_OUT : out std_logic); + end component; + component IDELAYCTRL + port ( RDY : out std_logic; + REFCLK : in std_logic; + RST : in std_logic + ); + end component; + component phaseshift + port ( CLKIN_IN : in std_logic; + DADDR_IN : in std_logic_vector (6 downto 0); + DCLK_IN : in std_logic; + DEN_IN : in std_logic; + DI_IN : in std_logic_vector (15 downto 0); + DWE_IN : in std_logic; + RST_IN : in std_logic; + CLK0_OUT : out std_logic; + CLKFX_OUT : out std_logic; + CLK2X_OUT : out std_logic; + DRDY_OUT : out std_logic; + LOCKED_OUT : out std_logic); + --PSDONE_OUT : out std_logic); + end component; + + component OBUF port ( O : out std_logic; I : in std_logic ); end component; + -- PGP Front End Wrapper + + component PgpFrontEnd + generic ( + MgtMode : string := "A"; + RefClkSel : string := "REFCLK1" + ); + port ( + pgpRefClk1 : in std_logic; + pgpRefClk2 : in std_logic; + mgtRxRecClk : out std_logic; + pgpClk : in std_logic; + pgpReset : in std_logic; + pgpDispA : out std_logic_vector(7 downto 0); + pgpDispB : out std_logic_vector(7 downto 0); + resetOut : out std_logic; + locClk : in std_logic; + locReset : in std_logic; + cmdEn : out std_logic; + cmdOpCode : out std_logic_vector(7 downto 0); + cmdCtxOut : out std_logic_vector(23 downto 0); + regReq : out std_logic; + regOp : out std_logic; + regAck : in std_logic; + regFail : in std_logic; + regAddr : out std_logic_vector(23 downto 0); + regDataOut : out std_logic_vector(31 downto 0); + regDataIn : in std_logic_vector(31 downto 0); + frameTxEnable : in std_logic; + frameTxSOF : in std_logic; + frameTxEOF : in std_logic; + frameTxEOFE : in std_logic; + frameTxData : in std_logic_vector(15 downto 0); + valid : out std_logic; + eof :out std_logic; + sof :out std_logic; + mgtRxN : in std_logic; + mgtRxP : in std_logic; + mgtTxN : out std_logic; + mgtTxP : out std_logic; + mgtCombusIn : in std_logic_vector(15 downto 0); + mgtCombusOut : out std_logic_vector(15 downto 0) + ); + end component; + + + -- Local Signals + signal cmdEn : std_logic; + signal cmdOpCode : std_logic_vector(7 downto 0); + signal cmdCtxOut : std_logic_vector(23 downto 0); + signal readDataValid : std_logic; + signal readDataSOF : std_logic; + signal readDataEOF : std_logic; + signal readDataEOFE : std_logic; + signal readData : std_logic_vector(15 downto 0); + signal dispDatA : std_logic; + signal dispDatB : std_logic; + signal pgpDispA : std_logic_vector(7 downto 0); + signal pgpDispB : std_logic_vector(7 downto 0); + signal regReq : std_logic; + signal regOp : std_logic; + signal regAck : std_logic; + signal regFail : std_logic; + signal regAddr : std_logic_vector(23 downto 0); + signal regDataOut : std_logic_vector(31 downto 0); + signal regDataIn : std_logic_vector(31 downto 0); + signal dispDigitA : std_logic_vector(7 downto 0); + signal dispDigitB : std_logic_vector(7 downto 0); + signal dispDigitC : std_logic_vector(7 downto 0); + signal dispDigitD : std_logic_vector(7 downto 0); + signal dispDigitE : std_logic_vector(7 downto 0); + signal dispDigitF : std_logic_vector(7 downto 0); + signal dispDigitG : std_logic_vector(7 downto 0); + signal dispDigitH : std_logic_vector(7 downto 0); + signal dispStrobe : std_logic; + signal dispUpdateA : std_logic; + signal dispUpdateB : std_logic; + signal sysClkCnt : std_logic_vector(15 downto 0); + signal ack : std_logic_vector(23 downto 0); + signal err : std_logic_vector(23 downto 0); + signal eof : std_logic; + signal sof : std_logic; + signal vvalid : std_logic; + signal regAck1 : std_logic; + signal regAck2 : std_logic; + signal regAck3 : std_logic; + signal regFail1 : std_logic; + signal regFail2 : std_logic; + signal regFail3 : std_logic; + type readback is array(23 downto 0) of std_logic_vector(31 downto 0); + signal thedata : readback; + signal req : std_logic_vector(23 downto 0); + signal counter1 : std_logic_vector(7 downto 0); + signal counter2 : std_logic_vector(7 downto 0); + signal idcounter : std_logic_vector(2 downto 0); + signal daddr : std_logic_vector (6 downto 0); + signal denfx : std_logic; + signal denphase : std_logic; + signal phaseclk : std_logic; + signal fxclock : std_logic; + signal serclk : std_logic; + signal drdy : std_logic; + signal drdy2 : std_logic; + signal lockedfx : std_logic; + signal lockedid : std_logic; + signal oldlockedid : std_logic; + signal lockedphase : std_logic; + signal lockednophase : std_logic; + signal reqclkfx : std_logic; + signal reqclkphase : std_logic; + signal oldreqclkfx : std_logic; + signal oldreqclkphase : std_logic; + signal clkenafx : std_logic; + signal clkenaphase : std_logic; + signal psdone : std_logic; + signal holdrst : std_logic; + signal phaserst : std_logic; + signal clockrst : std_logic; + signal clockrst2 : std_logic; + signal idctrlrst : std_logic; + signal clkdata : std_logic_vector(15 downto 0); + signal holdctr : std_logic_vector(24 downto 0); + signal clockidctrl : std_logic; + signal dreset : std_logic_vector(23 downto 16); + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + type DELAR is array (0 to 15) of integer; + constant setting: DELAR := (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); + attribute syn_noprune : boolean; + attribute syn_noprune of U_idelayctrl: label is true; + +begin + + -- Display Controller A + U_DispCntrlA: DisplayControl port map ( + sysClk => sysClk125, sysRst => sysRst125, + dispStrobe => dispStrobe, dispUpdate => dispUpdateA, + dispRotate => "01", dispDigitA => dispDigitA, + dispDigitB => dispDigitB, dispDigitC => dispDigitC, + dispDigitD => dispDigitD, dispClk => dispClk, + dispDat => dispDatA, dispLoadL => dispLoadL(0), + dispRstL => dispRstL + ); + + -- Display Controller B + U_DispCntrlB: DisplayControl port map ( + sysClk => sysClk125, sysRst => sysRst125, + dispStrobe => dispStrobe, dispUpdate => dispUpdateB, + dispRotate => "01", dispDigitA => dispDigitE, + dispDigitB => dispDigitF, dispDigitC => dispDigitG, + dispDigitD => dispDigitH, dispClk => open, + dispDat => dispDatB, dispLoadL => dispLoadL(1), + dispRstL => open + ); + + -- Output LED Data + dispDat <= dispDatA or dispDatB; + dispDigitA <= pgpDispA; + dispDigitB <= pgpDispB; + dispDigitD <= regDataIn(7 downto 0); + dispDigitC <= "0000"&lockedid&lockednophase &lockedphase & lockedfx; + dispDigitE <= "0000" & counter1(7 downto 4); + dispDigitF <= "0000" & counter1(3 downto 0); + dispDigitG <= "0000" & counter2(7 downto 4); + dispDigitH <="0000" & counter2(3 downto 0); + + + -- Generate display strobe (200ns) and update control + process ( sysClk125, sysRst125 ) begin + if sysRst125 = '1' then + sysClkCnt <= (others=>'0') after tpd; + dispStrobe <= '0' after tpd; + dispUpdateA <= '0' after tpd; + dispUpdateB <= '0' after tpd; + elsif rising_edge(sysClk125) then + + -- Display strobe, 320ns + dispStrobe <= sysClkCnt(4) after tpd; + + -- Update Display 0 + if sysClkCnt(15 downto 0) = x"8000" then + dispUpdateA <= '1' after tpd; + else + dispUpdateA <= '0' after tpd; + end if; + + -- Update Display B + if sysClkCnt(15 downto 0) = x"0000" then + dispUpdateB <= '1' after tpd; + else + dispUpdateB <= '0' after tpd; + end if; + + -- Update counter + sysClkCnt <= sysClkCnt + 1 after tpd; + + if req(0)='1' then + counter1<=unsigned(counter1)+1; + end if; + + if req(1)='1' then + counter2<=unsigned(counter2)+1; + end if; + + end if; + end process; + + + -- PGP Front End + U_PgpFrontEnd: PgpFrontEnd port map ( + pgpRefClk1 => refClock, pgpRefClk2 => '0', + mgtRxRecClk => open, pgpClk => pgpClk, + pgpReset => pgpReset, pgpDispA => pgpDispA, + pgpDispB => pgpDispB, resetOut => resetOut, + locClk => sysClk125, locReset => sysRst125, + cmdEn => cmdEn, cmdOpCode => cmdOpCode, + cmdCtxOut => cmdCtxOut, regReq => regReq, + regOp => regOp, regAck => regAck, + regFail => regFail, regAddr => regAddr, + regDataOut => regDataOut, regDataIn => regDataIn, + frameTxEnable => readDataValid, frameTxSOF => readDataSOF, + frameTxEOF => readDataEOF, frameTxEOFE => readDataEOFE, + frameTxData => readData, valid => vvalid, + eof => eof, sof => sof, + mgtRxN => mgtRxN, + mgtRxP => mgtRxP, mgtTxN => mgtTxN, + mgtTxP => mgtTxP, mgtCombusIn => (others=>'0'), + mgtCombusOut => open + ); + + clkData<=(others=>'0'); + readDataValid<='0'; + vvalid<='0'; + readDataSOF<='0'; + readDataEOF<='0'; + readDataEOFE<='0'; + readData<=(others=>'0'); + regAck1<= (ack(0) or ack(1) or ack(2) or ack(3) or ack(4) or ack(5) or ack(6) or ack(7)); + regAck2<= (ack(8) or ack(9) or ack(10) or ack(11) or ack(12) or ack(13) or ack(14) or ack(15)); + regAck3<= (ack(16) or ack(17) or ack(18) or ack(19) or ack(20) or ack(21) or ack(22) or ack(23)); + regAck<= (regAck1 or regAck2 or regAck3 or drdy or drdy2); + regFail1<= (err(0) or err(1) or err(2) or err(3) or err(4) or err(5) or err(6) or err(7)); + regFail2<= (err(8) or err(9) or err(10) or err(11) or err(12) or err(13) or err(14) or err(15)); + regFail3<= (err(16) or err(17) or err(18) or err(19) or err(20) or err(21) or err(22) or err(23)); + regFail<= (regFail1 or regFail2 or regFail3); + req(0)<='1' when regReq='1' and (regAddr(8 downto 4) = "00000" or regAddr(8 downto 4) = "11111" or regAddr(8 downto 4) = "11110") else '0'; + req(1)<='1' when regReq='1' and (regAddr(8 downto 4) = "00001" or regAddr(8 downto 4) = "11111" or regAddr(8 downto 4) = "11110") else '0'; + req(2)<='1' when regReq='1' and (regAddr(8 downto 4) = "00010" or regAddr(8 downto 4) = "11111" or regAddr(8 downto 4) = "11110") else '0'; + req(3)<='1' when regReq='1' and (regAddr(8 downto 4) = "00011" or regAddr(8 downto 4) = "11111" or regAddr(8 downto 4) = "11110") else '0'; + req(4)<='1' when regReq='1' and (regAddr(8 downto 4) = "00100" or regAddr(8 downto 4) = "11111" or regAddr(8 downto 4) = "11110") else '0'; + req(5)<='1' when regReq='1' and (regAddr(8 downto 4) = "00101" or regAddr(8 downto 4) = "11111" or regAddr(8 downto 4) = "11110") else '0'; + req(6)<='1' when regReq='1' and (regAddr(8 downto 4) = "00110" or regAddr(8 downto 4) = "11111" or regAddr(8 downto 4) = "11110") else '0'; + req(7)<='1' when regReq='1' and (regAddr(8 downto 4) = "00111" or regAddr(8 downto 4) = "11111" or regAddr(8 downto 4) = "11110") else '0'; + req(8)<='1' when regReq='1' and (regAddr(8 downto 4) = "01000" or regAddr(8 downto 4) = "11111" or regAddr(8 downto 4) = "11110") else '0'; + req(9)<='1' when regReq='1' and (regAddr(8 downto 4) = "01001" or regAddr(8 downto 4) = "11111" or regAddr(8 downto 4) = "11110") else '0'; + req(10)<='1' when regReq='1' and (regAddr(8 downto 4) = "01010" or regAddr(8 downto 4) = "11111" or regAddr(8 downto 4) = "11110") else '0'; + req(11)<='1' when regReq='1' and (regAddr(8 downto 4) = "01011" or regAddr(8 downto 4) = "11111" or regAddr(8 downto 4) = "11110") else '0'; + req(12)<='1' when regReq='1' and (regAddr(8 downto 4) = "01100" or regAddr(8 downto 4) = "11111" or regAddr(8 downto 4) = "11110") else '0'; + req(13)<='1' when regReq='1' and (regAddr(8 downto 4) = "01101" or regAddr(8 downto 4) = "11111" or regAddr(8 downto 4) = "11110") else '0'; + req(14)<='1' when regReq='1' and (regAddr(8 downto 4) = "01110" or regAddr(8 downto 4) = "11111" or regAddr(8 downto 4) = "11110") else '0'; + req(15)<='1' when regReq='1' and (regAddr(8 downto 4) = "01111" or regAddr(8 downto 4) = "11111" or regAddr(8 downto 4) = "11110") else '0'; + req(16)<='1' when regReq='1' and (regAddr(8 downto 4) = "10000" or regAddr(8 downto 4) = "11111" or regAddr(8 downto 4) = "11101") else '0'; + req(17)<='1' when regReq='1' and (regAddr(8 downto 4) = "10001" or regAddr(8 downto 4) = "11111" or regAddr(8 downto 4) = "11101") else '0'; + req(18)<='1' when regReq='1' and (regAddr(8 downto 4) = "10010" or regAddr(8 downto 4) = "11111" or regAddr(8 downto 4) = "11101") else '0'; + req(19)<='1' when regReq='1' and (regAddr(8 downto 4) = "10011" or regAddr(8 downto 4) = "11111" or regAddr(8 downto 4) = "11101") else '0'; + req(20)<='1' when regReq='1' and (regAddr(8 downto 4) = "10100" or regAddr(8 downto 4) = "11111" or regAddr(8 downto 4) = "11101") else '0'; + req(21)<='1' when regReq='1' and (regAddr(8 downto 4) = "10101" or regAddr(8 downto 4) = "11111" or regAddr(8 downto 4) = "11101") else '0'; + req(22)<='1' when regReq='1' and (regAddr(8 downto 4) = "10110" or regAddr(8 downto 4) = "11111" or regAddr(8 downto 4) = "11101") else '0'; + req(23)<='1' when regReq='1' and (regAddr(8 downto 4) = "10111" or regAddr(8 downto 4) = "11111" or regAddr(8 downto 4) = "11101") else '0'; + reqclkphase <='1' when regReq='1' and (regAddr(8 downto 4) = "11000" or regAddr(8 downto 4) = "11001" or regAddr(8 downto 4) = "11010") else '0'; + reqclkfx<='1'when regreq='1' and (regAddr(8 downto 4) = "11011" or regAddr(8 downto 4) = "11100") else '0'; + with regAddr(8 downto 4) select + regDataIn <= thedata(0) when "00000", + thedata(1) when "00001", + thedata(2) when "00010", + thedata(3) when "00011", + thedata(4) when "00100", + thedata(5) when "00101", + thedata(6) when "00110", + thedata(7) when "00111", + thedata(8) when "01000", + thedata(9) when "01001", + thedata(10) when "01010", + thedata(11) when "01011", + thedata(12) when "01100", + thedata(13) when "01101", + thedata(14) when "01110", + thedata(15) when "01111", + thedata(16) when "10000", + thedata(17) when "10001", + thedata(18) when "10010", + thedata(19) when "10011", + thedata(20) when "10100", + thedata(21) when "10101", + thedata(22) when "10110", + thedata(23) when "10111", + x"0000" & clkdata when "11010", + x"ffffffff" when others; + + PATTERN_GEN_DATA: + for I in 0 to 15 generate + + U_pattern_mem: pattern_mem + generic map( + DELAY=>setting(I)) + port map ( + clk => sysClk125, + serclk => pgpClk, --was serclk + deserclk => phaseclk, + rst => sysRst125, + pgpEnable => req(I), + pgpRW => regOp, + pgpAck => ack(I), + pgpErr => err(I), + dataFromPgp => regDataOut, + addrPgp => regAddr(3 downto 0), + dataToPgp => thedata(I), + dataFromFe => serialin(I), + dataToFe => serialout(I)); +end generate PATTERN_GEN_DATA; + PATTERN_GEN_CMD: + for I in 16 to 23 generate + + U_pattern_cmd: pattern_cmd port map ( + clk => sysClk125, + serclk => clock80, + deserclk => clock40, + retclk => retclock(I), + rst => sysRst125, + doricreset => dreset(I), + pgpEnable => req(I), + pgpRW => regOp, + pgpAck => ack(I), + pgpErr => err(I), + dataFromPgp => regDataOut, + addrPgp => regAddr(3 downto 0), + dataToPgp => thedata(I), + dataFromFe => serialin(I), + dataToFe => serialout(I)); +end generate PATTERN_GEN_CMD; + doricreset<=dreset(20); + + clockrst<=holdrst; + clockrst2<=phaserst; + U_idelctrlclk: clock200 port map( + CLKIN_IN => clock160, + RST_IN => clockrst, + CLKFX_OUT => clockidctrl, + CLK0_OUT => open, + LOCKED_OUT => lockedid); + U_idelayctrl: IDELAYCTRL port map( + RDY => open, + REFCLK => clockidctrl, + RST => idctrlrst); + + U_clockmult: phaseshift port map( + CLKIN_IN => clock80, -- was clock160 + DADDR_IN => daddr, + DCLK_IN => sysClk125, + DEN_IN => denfx, + DI_IN => regDataOut(15 downto 0), + --DO_OUT => clkdata, + DWE_IN => regOp, + RST_IN => clockrst, + CLK0_OUT => open, + CLKFX_OUT => fxclock, + CLK2X_OUT => open, + DRDY_OUT => drdy, + LOCKED_OUT=> lockedfx); + --PSDONE_OUT=> open); + U_phaseshift: phaseshift port map( + CLKIN_IN => pgpClk, -- was fxclock + DADDR_IN => daddr, + DCLK_IN => sysClk125, + DEN_IN => denphase, + DI_IN => regDataOut(15 downto 0), + --DO_OUT => (others=>'0'), + DWE_IN => regOp, + RST_IN => clockrst2, + CLK0_OUT => phaseclk, -- was open + CLKFX_OUT => open, + CLK2X_OUT => open, -- was phaseclk + DRDY_OUT => drdy2, + LOCKED_OUT=> lockedphase); + --PSDONE_OUT=> psdone); + U_noshift: phaseshift port map( + CLKIN_IN => fxclock, + DADDR_IN => (others=>'0'), + DCLK_IN => sysClk125, + DEN_IN => '0', + DI_IN => (others=>'0'), + --DO_OUT => (others=>'0'), + DWE_IN => '0', + RST_IN => clockrst2, + CLK0_OUT => open, + CLKFX_OUT => open, + CLK2X_OUT => serclk, + DRDY_OUT => open, + LOCKED_OUT=> lockednophase); + --PSDONE_OUT=> open); + + + with regAddr(8 downto 4) select + daddr<="1010101" when "11000", + "0010001" when "11001", + "0000000" when "11010", + "1010000" when "11011", + "1010010" when "11100", + "0000000" when others; + process(sysRst125, sysClk125) -- clock interface + begin + if (sysRst125='1') then + holdctr<=(others=>'1'); + holdrst<='1'; + clkenafx<='1'; + elsif(sysClk125'event and sysClk125='1') then + if (reqclkfx='1' and oldreqclkfx='0') then + clkenafx<='1'; + holdctr<=x"ffffff"&'1'; + holdrst<='1'; + else + clkenafx<='0'; + if (holdctr=x"000000"&'0') then + phaserst<='0'; + else + if (holdctr(24)='0') then + holdrst<='0'; + phaserst<='1'; + end if; + holdctr<=unsigned(holdctr)-1; + end if; + end if; + if (reqclkphase='1' and oldreqclkphase='0') then + clkenaphase<='1'; + else + clkenaphase<='0'; + end if; + denfx<=clkenafx; + denphase<=clkenaphase; + oldreqclkfx<=reqclkfx; + oldreqclkphase<=reqclkphase; + end if; + end process; + process(sysClk125, sysRst125) -- reset logic for IDELAYCTRL + begin + if(sysRst125='1') then + idctrlrst<='0'; + idcounter<="000"; + oldlockedid<='0'; + elsif(sysClk125'event and sysClk125='1') then + if(lockedid='1' and oldlockedid='0')then + idcounter<="111"; + idctrlrst<='1'; + elsif(unsigned(idcounter)>0)then + idcounter<=unsigned(idcounter)-1; + else + idctrlrst<='0'; + end if; + oldlockedid<=lockedid; + end if; + end process; + +end IBLcableTesterCore; + diff --git a/rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTesterOld.vhd b/rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTesterOld.vhd new file mode 100755 index 00000000..6ed70298 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/hdl/IBLcableTesterOld.vhd @@ -0,0 +1,518 @@ +------------------------------------------------------------------------------- +-- Title : BNL ASIC Test FGPA, Top Level +-- Project : LCLS Detector, BNL ASIC +------------------------------------------------------------------------------- +-- File : BnlAsic.vhd +-- Author : Ryan Herbst, rherbst@slac.stanford.edu +-- Created : 07/21/2008 +------------------------------------------------------------------------------- +-- Description: +-- Top level logic for BNL ASIC test FPGA. +------------------------------------------------------------------------------- +-- Copyright (c) 2008 by Ryan Herbst. All rights reserved. +------------------------------------------------------------------------------- +-- Modification history: +-- 07/21/2008: created. +------------------------------------------------------------------------------- + +LIBRARY ieee; +Library Unisim; +USE ieee. std_logic_1164.ALL; +use ieee. std_logic_arith.all; +use ieee. std_logic_unsigned.all; +USE work.ALL; + +entity IBLcableTester is + port ( + + -- PGP Crystal Clock Input, 156.25Mhz + iPgpRefClkP : in std_logic; + iPgpRefClkM : in std_logic; + + -- System clock 125 MHz clock input + iMainClkP : in std_logic; + iMainClkN : in std_logic; + + oClock40 : out std_logic; + iClock160_p : in std_logic; + iClock160_n : in std_logic; + oClk160_p : out std_logic; + oClk160_n : out std_logic; + oClk40_p : out std_logic; + oClk40_n : out std_logic; + -- PGP Rx/Tx Lines + iMgtRxN : in std_logic; + iMgtRxP : in std_logic; + oMgtTxN : out std_logic; + oMgtTxP : out std_logic; + + -- ATLAS Pixel module pins + serialin_p : in std_logic_vector(23 downto 0); + serialin_n : in std_logic_vector(23 downto 0); + serialout_p : out std_logic_vector(23 downto 0); + serialout_n : out std_logic_vector(23 downto 0); + retclock_p : in std_logic_vector(23 downto 16); + retclock_n : in std_logic_vector(23 downto 16); + serialoutxtf_p : out std_logic_vector(4 downto 0); + serialoutxtf_n : out std_logic_vector(4 downto 0); + serialoutxts_p : out std_logic_vector(4 downto 0); + serialoutxts_n : out std_logic_vector(4 downto 0); + doricreset : out std_logic; + clkout40 : out std_logic; + + -- Reset button + iResetInL : in std_logic; + + -- LED Display + oDispClk : out std_logic; + oDispDat : out std_logic; + oDispLoadL : out std_logic_vector(1 downto 0); + oDispRstL : out std_logic; + + -- Debug + oDebug : out std_logic_vector(15 downto 0); + + -- Misc Signals + oPdBuff0 : out std_logic; + oPdBuff1 : out std_logic; + oPdBuff3 : out std_logic; + oPdBuff4 : out std_logic; + oLemoA : out std_logic; + iLemoB : in std_logic; + + -- Transmitter enable + transDis1 : out std_logic + ); +end IBLcableTester; + + +-- Define architecture for top level module +architecture IBLcableTester of IBLcableTester is + + -- Synthesis control attributes + attribute syn_useioff : boolean; + attribute syn_useioff of IBLcableTester : architecture is true; + attribute xc_fast_auto : boolean; + attribute xc_fast_auto of IBLcableTester : architecture is false; + attribute syn_noclockbuf : boolean; + attribute syn_noclockbuf of IBLcableTester : architecture is true; + + -- IO Pad components + component IBUF port ( O : out std_logic; I : in std_logic ); end component; + component OBUF port ( O : out std_logic; I : in std_logic ); end component; + component OBUFDS + generic( IOSTANDARD: STRING:= "LVDS_25"; + SLEW: STRING:="FAST"); + port ( O : out std_logic; OB : out std_logic; I : in std_logic ); + end component; + + -- Input LVDS with termination + component IBUFDS + generic ( DIFF_TERM : boolean := FALSE; + IOSTANDARD: STRING := "LVDS_25"); + port ( O : out std_logic; I : in std_logic; IB : in std_logic ); + end component; + + -- Xilinx global clock buffer component + component BUFGMUX + port ( + O : out std_logic; + I0 : in std_logic; + I1 : in std_logic; + S : in std_logic + ); + end component; + + + -- PGP Clock Generator + component PgpClkGen + generic ( + RefClkEn1 : string := "ENABLE"; -- ENABLE or DISABLE + RefClkEn2 : string := "DISABLE"; -- ENABLE or DISABLE + DcmClkSrc : string := "RefClk1"; -- RefClk1 or RefClk2 + UserFxDiv : integer := 5; -- DCM FX Output Divide + UserFxMult : integer := 4 -- DCM FX Output Divide, 4/5 * 156.25 = 125Mhz + ); + port ( + + -- Reference Clock Pad Inputs + pgpRefClkInP : in std_logic; + pgpRefClkInN : in std_logic; + + -- Power On Reset Input + ponResetL : in std_logic; + + -- Locally Generated Reset + locReset : in std_logic; + + -- Reference Clock To PGP MGT + -- Use one, See RefClkEn1 & RefClkEn2 Generics + pgpRefClk1 : out std_logic; + pgpRefClk2 : out std_logic; + + -- Global Clock & Reset For PGP Logic, 156.25Mhz + pgpClk : out std_logic; + pgpReset : out std_logic; + + -- Global Clock & Reset For User Logic, 125Mhz + userClk : out std_logic; + userReset : out std_logic; + + -- Inputs clocks for reset generation connect + -- to pgpClk and userClk + pgpClkIn : in std_logic; + userClkIn : in std_logic + ); + end component; + + + -- Core Logic + component IBLcableTesterCore + port ( + sysClk250 : in std_logic; + sysClk125 : in std_logic; + sysRst125 : in std_logic; + sysRst250 : in std_logic; + refClock : in std_logic; + pgpClk : in std_logic; + pgpReset : in std_logic; + mgtRxN : in std_logic; + mgtRxP : in std_logic; + mgtTxN : out std_logic; + mgtTxP : out std_logic; + serialin : in std_logic_vector(23 downto 0); + serialout : out std_logic_vector(23 downto 0); + retclock : in std_logic_vector(23 downto 16); + clock160 : in std_logic; + clock80 : in std_logic; + clock40 : in std_logic; + doricreset : out std_logic; + resetOut : out std_logic; + dispClk : out std_logic; + dispDat : out std_logic; + dispLoadL : out std_logic_vector(1 downto 0); + dispRstL : out std_logic; + debug : out std_logic_vector(15 downto 0) + ); + end component; + component clock160 + port ( + CLKIN_N_IN : in std_logic; + CLKIN_P_IN : in std_logic; + RST_IN : in std_logic; + CLKFX_OUT : out std_logic; + CLKIN_IBUFGDS_OUT : out std_logic; + CLK0_OUT : out std_logic; + LOCKED_OUT : out std_logic); + end component; +component IDELAY + generic (IOBDELAY_TYPE : string := "DEFAULT"; --(DEFAULT, FIXED, VARIABLE) + IOBDELAY_VALUE : integer := 0 --(0 to 63) + ); + port ( + O : out STD_LOGIC; + I : in STD_LOGIC; + C : in STD_LOGIC; + CE : in STD_LOGIC; + INC : in STD_LOGIC; + RST : in STD_LOGIC + ); +end component; +--component ila + --PORT ( + --CONTROL : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0); + --CLK : IN STD_LOGIC; + --DATA : IN STD_LOGIC_VECTOR(31 DOWNTO 0); + --TRIG0 : IN STD_LOGIC_VECTOR(0 DOWNTO 0)); +-- +--end component; + --component icon + --PORT ( + --CONTROL0 : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0)); +-- + --end component; + + + -- Local signals + signal resetInL : std_logic; + signal tmpClk250 : std_logic; + signal sysClk125 : std_logic; + signal sysRst125 : std_logic; + signal sysRst250 : std_logic; + signal sysClk250 : std_logic; + signal refClock : std_logic; + signal pgpClk : std_logic; + signal clk160 : std_logic; + signal clk80 : std_logic; + signal clk40 : std_logic; + signal pgpReset : std_logic; + signal resetOut : std_logic; + signal mgtRxN : std_logic; + signal mgtRxP : std_logic; + signal mgtTxN : std_logic; + signal mgtTxP : std_logic; + signal dispClk : std_logic; + signal dispDat : std_logic; + signal dispLoadL : std_logic_vector(1 downto 0); + signal dispRstL : std_logic; + signal debug : std_logic_vector(15 downto 0); + signal sysClk125i : std_logic; + signal doricresetb : std_logic; + signal mainClk : std_logic; + signal clk0 : std_logic; + signal clkin : std_logic; + signal holdrst : std_logic; + signal halfclock : std_logic; + signal clockfast : std_logic; + signal quarterclock : std_logic; + signal serialoutb : std_logic_vector(23 downto 0); + signal serialinb : std_logic_vector(23 downto 0); + signal retclockb : std_logic_vector(23 downto 16); + signal retclockd : std_logic_vector(23 downto 16); + signal retclocki : std_logic_vector(23 downto 16); + signal ccontrol: std_logic_vector(35 downto 0); + signal cdata: std_logic_vector(31 downto 0); + signal ctrig: std_logic_vector(0 downto 0); + + -- Register delay for simulation + constant tpd:time := 0.5 ns; + + -- Black Box Attributes +-- attribute syn_noprune : boolean; +-- attribute syn_noprune of chipscope : label is true; +-- attribute syn_noprune of chipscopeicon : label is true; + attribute syn_black_box : boolean; + attribute syn_noprune : boolean; + attribute syn_black_box of IBUF : component is TRUE; + attribute syn_noprune of IBUF : component is TRUE; + attribute syn_black_box of OBUF : component is TRUE; + attribute syn_noprune of OBUF : component is TRUE; + attribute syn_black_box of IBUFDS : component is TRUE; + attribute syn_noprune of IBUFDS : component is TRUE; + attribute syn_black_box of OBUFDS : component is TRUE; + attribute syn_noprune of OBUFDS : component is TRUE; + attribute syn_black_box of BUFGMUX : component is TRUE; + attribute syn_noprune of BUFGMUX : component is TRUE; +begin + + -- Reset input + U_ResetIn: IBUF port map ( I => iResetInL, O => resetInL ); + + -- PGP Clock Generator + U_PgpClkGen: PgpClkGen generic map ( + RefClkEn1 => "ENABLE", + RefClkEn2 => "DISABLE", + DcmClkSrc => "RefClk1", + UserFxDiv => 4, + UserFxMult => 2 + ) port map ( + pgpRefClkInP => iPgpRefClkP, + pgpRefClkInN => iPgpRefClkM, + ponResetL => resetInL, + locReset => resetOut, + pgpRefClk1 => refClock, + pgpRefClk2 => open, + pgpClk => pgpClk, + pgpReset => pgpReset, + pgpClkIn => pgpClk, + userClk => sysClk125, + userReset => sysRst125, + userClkIn => sysClk125 + ); + + -- Generate Divided Clock, sample reset + process ( pgpClk ) begin + if rising_edge(pgpClk) then + tmpClk250 <= not tmpClk250 after tpd; + sysRst250 <= sysRst125 after tpd; + end if; + end process; + + -- Global Buffer For 125Mhz Clock + U_CLK250: BUFGMUX port map ( + O => sysClk250, + I0 => tmpClk250, + I1 => '0', + S => '0' + ); + + -- No Pads for MGT Lines + mgtRxN <= iMgtRxN; + mgtRxP <= iMgtRxP; + oMgtTxN <= mgtTxN; + oMgtTxP <= mgtTxP; + + -- LED Display + U_DispClk : OBUF port map ( I => dispClk , O => oDispClk ); + U_DispDat : OBUF port map ( I => dispDat , O => oDispDat ); + U_DispLoadL1 : OBUF port map ( I => dispLoadL(1) , O => oDispLoadL(1) ); + U_DispLoadL0 : OBUF port map ( I => dispLoadL(0) , O => oDispLoadL(0) ); + U_DispRstL : OBUF port map ( I => dispRstL , O => oDispRstL ); + U_clkout40 : OBUF port map ( I => clk40 , O => clkout40 ); + + + -- Debug + U_Debug0 : OBUF port map ( I => debug(0) , O => oDebug(0) ); + U_Debug1 : OBUF port map ( I => debug(1) , O => oDebug(1) ); + U_Debug2 : OBUF port map ( I => debug(2) , O => oDebug(2) ); + U_Debug3 : OBUF port map ( I => debug(3) , O => oDebug(3) ); + U_Debug4 : OBUF port map ( I => debug(4) , O => oDebug(4) ); + U_Debug5 : OBUF port map ( I => debug(5) , O => oDebug(5) ); + U_Debug6 : OBUF port map ( I => debug(6) , O => oDebug(6) ); + U_Debug7 : OBUF port map ( I => debug(7) , O => oDebug(7) ); + U_Debug8 : OBUF port map ( I => debug(8) , O => oDebug(8) ); + U_Debug9 : OBUF port map ( I => debug(9) , O => oDebug(9) ); + U_Debug10 : OBUF port map ( I => debug(10) , O => oDebug(10) ); + U_Debug11 : OBUF port map ( I => debug(11) , O => oDebug(11) ); + U_Debug12 : OBUF port map ( I => debug(12) , O => oDebug(12) ); + U_Debug13 : OBUF port map ( I => debug(13) , O => oDebug(13) ); + U_Debug14 : OBUF port map ( I => debug(14) , O => oDebug(14) ); + U_Debug15 : OBUF port map ( I => debug(15) , O => oDebug(15) ); + +-- U_clock40out : OBUF port map ( I => quarterclock , O => oClock40 ); +-- U_serialout1 : OBUFDS generic map ( +-- IOSTANDARD=>"LVDS_25", +-- SLEW=>"FAST") +-- port map ( I => mainClk , O => serialout_p(1) , OB => serialout_n(1) ); +-- U_serialout2 : OBUFDS generic map ( +-- IOSTANDARD=>"LVDS_25", +-- SLEW=>"FAST") +-- port map ( I => clkin , O => serialout_p(2) , OB => serialout_n(2) ); +-- U_clockout40 : OBUFDS generic map ( +-- IOSTANDARD=>"LVDS_25", +---- SLEW=>"FAST") +-- port map ( I => quarterclock , O => oClk40_p , OB => oClk40_n ); +-- U_clockout160 : OBUFDS generic map ( +-- IOSTANDARD=>"LVDS_25", +-- SLEW=>"FAST") +-- port map ( I => pgpClk , O => oClk160_p , OB => oClk160_n ); +-- U_clockin160 : IBUFDS generic map ( DIFF_TERM=>TRUE, +-- IOSTANDARD=>"ULVDS_25") +-- port map ( I => iClock160_p , IB=>iClock160_n , O => clk160 ); + + SERIAL_IO_DATA: + for I in 0 to 15 generate + U_serialout : OBUFDS generic map ( + IOSTANDARD=>"LVDS_25", + SLEW=>"FAST") + port map ( I => serialoutb(I) , O => serialout_p(I) , OB => serialout_n(I) ); + +-- SERIAL_IO_DATA_in: +-- for I in 0 to 15 generate + U_serialin : IBUFDS generic map ( DIFF_TERM=>TRUE, + IOSTANDARD=>"LVDS_25") + port map ( I => serialin_p(I) , IB=>serialin_n(I) , O => serialinb(I) ); + end generate SERIAL_IO_DATA; +-- end generate SERIAL_IO_DATA_in; + + SERIAL_IO_CMD: + for I in 16 to 23 generate +-- delayline : IDELAY +-- generic map ( +-- IOBDELAY_TYPE => "FIXED", -- Set to DEFAULT for -- Zero Hold Time Mode +-- IOBDELAY_VALUE => 10 -- (0 to 63) +-- ) +-- port map ( +-- O => retclockd(I), +-- I => retclockb(I), +-- C => '0', +-- CE => '0', +-- INC => '0', +-- RST => '0' +-- ); +-- --retclockd(I)<= not retclocki(I); + U_serialout : OBUFDS generic map ( + IOSTANDARD=>"LVDS_25", + SLEW=>"FAST") + port map ( I => serialoutb(I) , O => serialout_p(I) , OB => serialout_n(I) ); + + U_serialin : IBUFDS generic map ( DIFF_TERM=>TRUE, + IOSTANDARD=>"LVDS_25") + port map ( I => serialin_p(I) , IB=>serialin_n(I) , O => serialinb(I) ); + U_retclock : IBUFDS generic map ( DIFF_TERM=>TRUE, + IOSTANDARD=>"LVDS_25") + port map ( I => retclock_p(I) , IB=>retclock_n(I) , O => retclockb(I) ); + end generate SERIAL_IO_CMD; + + CROSSTALK: + for I in 0 to 4 generate + U_xtalkf : OBUFDS generic map ( + IOSTANDARD=>"LVDS_25", + SLEW=>"FAST") + port map ( I => serialoutb(15) , O => serialoutxtf_p(I) , OB => serialoutxtf_n(I) ); + + U_xtalks : OBUFDS generic map ( + IOSTANDARD=>"LVDS_25", + SLEW=>"FAST") + port map ( I => serialoutb(23) , O => serialoutxts_p(I) , OB => serialoutxts_n(I) ); + + end generate CROSSTALK; + + U_doric : OBUF port map ( I => doricresetb , O => doricreset ); + U_link : OBUF port map ( I => '0' , O => transDis1 ); + + + -- FPGA Core + U_IBLcableTesterCore: IBLcableTesterCore port map ( + sysClk250 => sysClk250, sysRst250 => sysRst250, + sysClk125 => sysClk125, sysRst125 => sysRst125, + refClock => refClock, pgpClk => pgpClk, + pgpReset => pgpReset, mgtRxN => mgtRxN, + mgtRxP => mgtRxP, mgtTxN => mgtTxN, + mgtTxP => mgtTxP, serialin => serialinb, + serialout => serialoutb, retclock => retclockb, + clock160 => pgpClk, + clock80 => sysClk250, clock40 => sysClk125, + doricreset => doricresetb, resetOut => resetOut, + dispClk => dispClk, dispDat => dispDat, + dispLoadL => dispLoadL, dispRstL => dispRstL, + debug => debug + ); + --sysClk125i <= not sysClk125; + sysClk125i<=debug(0); +-- U_clock160: clock160 port map( +-- CLKIN_N_IN => iMainClkN, +-- CLKIN_P_IN => iMainClkP, +-- RST_IN => sysRst125, +-- CLKFX_OUT => open, +-- CLKIN_IBUFGDS_OUT => clkin, +-- CLK0_OUT => clk0, +-- LOCKED_OUT => open); + process(pgpClk) + begin + if(pgpClk'event and pgpClk='1') then + halfclock<= not halfclock; + end if; + end process; + process(halfclock) + begin + if(halfclock'event and halfclock='1') then + quarterclock<= not quarterclock; + end if; + end process; + process(pgpClk) + begin + if(pgpClk'event and pgpClk='1') then + clk80<= not clk80; + end if; + end process; + process(clk80) + begin + if(clk80'event and clk80='1') then + clk40<= not clk40; + end if; + end process; + --cdata(7 downto 0)<=serialinb(7 downto 0); + --cdata(31 downto 8) <=(others=>'0'); + --ctrig(0)<='0'; + --chipscope : ila + --port map ( + --CONTROL => ccontrol, + --CLK => mainClk, + --DATA => cdata, + --TRIG0 => ctrig); + --chipscopeicon : icon + --port map ( + --CONTROL0 => ccontrol); + +end IBLcableTester; diff --git a/rce/fw-hsio/projects/IBLcableTester/hdl/deser.vhd b/rce/fw-hsio/projects/IBLcableTester/hdl/deser.vhd new file mode 100644 index 00000000..110b8e6d --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/hdl/deser.vhd @@ -0,0 +1,70 @@ +-------------------------------------------------------------- +-- Serializer for High Speed I/O board (ATLAS Pixel teststand) +-- Martin Kocian 01/2009 +-------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use work.all; + +-------------------------------------------------------------- + +entity deser is + +port( clk: in std_logic; + rst: in std_logic; + go: in std_logic; + d_in: in std_logic; + d_out: out std_logic_vector(31 downto 0); + ld: out std_logic +); +end deser; + +-------------------------------------------------------------- + +architecture DESER of deser is + +signal reg : std_logic_vector(31 downto 0); +signal going: std_logic; +signal counter: std_logic_vector(4 downto 0); + +begin + + + process(rst, clk) + + begin + if(rst='1') then + reg<=x"00000000"; + d_out<=x"00000000"; + going<='0'; + ld<='0'; + elsif (clk'event and clk='1') then + if (going='0') then + if(go='1' and d_in='1')then + going<='1'; + else + counter<="11110"; + end if; + else + if (counter="11111") then + ld<='1'; + d_out<=reg; + if(go='0')then + going<='0'; + end if; + elsif(counter="11110")then + ld<='0'; + end if; + counter<=unsigned(counter)-1; + end if; + reg(31 downto 1)<=reg(30 downto 0); + reg(0)<=d_in; + end if; + + end process; + +end DESER; + +-------------------------------------------------------------- diff --git a/rce/fw-hsio/projects/IBLcableTester/hdl/deser16.vhd b/rce/fw-hsio/projects/IBLcableTester/hdl/deser16.vhd new file mode 100644 index 00000000..8d13af35 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/hdl/deser16.vhd @@ -0,0 +1,67 @@ +-------------------------------------------------------------- +-- Serializer for High Speed I/O board (ATLAS Pixel teststand) +-- Martin Kocian 01/2009 +-------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use work.all; + +-------------------------------------------------------------- + +entity deser16 is + +port( clk: in std_logic; + rst: in std_logic; + go: in std_logic; + d_in: in std_logic; + d_out: out std_logic_vector(15 downto 0); + ld: out std_logic +); +end deser16; + +-------------------------------------------------------------- + +architecture DESER16 of deser16 is + +signal reg : std_logic_vector(15 downto 0); +signal counter: std_logic_vector(3 downto 0); +signal going: std_logic; + +begin + + + process(rst, clk) + + begin + if(rst='1') then + reg<=x"0000"; + d_out<=x"0000"; + going<='0'; + ld<='0'; + elsif (clk'event and clk='1') then + if(going='0' and go='1' and d_in='1')then + going<='1'; + counter<="1110"; + else + if (going='1' and counter="1111") then + ld<='1'; + d_out<=reg; + if(go='0')then + going<='0'; + end if; + elsif(counter="1110")then + ld<='0'; + end if; + counter<=unsigned(counter)-1; + end if; + reg(15 downto 1)<=reg(14 downto 0); + reg(0)<=d_in; + end if; + + end process; + +end DESER16; + +-------------------------------------------------------------- diff --git a/rce/fw-hsio/projects/IBLcableTester/hdl/pattern_cmd.vhd b/rce/fw-hsio/projects/IBLcableTester/hdl/pattern_cmd.vhd new file mode 100644 index 00000000..a02a9a8e --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/hdl/pattern_cmd.vhd @@ -0,0 +1,575 @@ +-------------------------------------------------------------- +-- Serializer for High Speed I/O board (ATLAS Pixel teststand) +-- Martin Kocian 08/2009 +-------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use work.all; + +-------------------------------------------------------------- + +entity pattern_cmd is + +port( clk: in std_logic; + serclk: in std_logic; + deserclk: in std_logic; + retclk: in std_logic; + rst: in std_logic; + doricreset: out std_logic; + pgpEnable: in std_logic; + pgpRW: in std_logic; + pgpAck: out std_logic; + pgpErr: out std_logic; + dataFromPgp:in std_logic_vector(31 downto 0); + addrPgp: in std_logic_vector(3 downto 0); + dataToPgp: out std_logic_vector(31 downto 0); + dataFromFE: in std_logic; + dataToFE: out std_logic +); +end pattern_cmd; + +-------------------------------------------------------------- + +architecture PATTERN_CMD of pattern_cmd is + +signal nloaded : std_logic_vector(9 downto 0); +signal pointer : std_logic_vector(9 downto 0); +signal header : std_logic_vector(9 downto 0); +signal nwords: std_logic_vector(63 downto 0); +signal nerr: std_logic_vector(63 downto 0); +signal current: std_logic_vector(31 downto 0); +signal doutb: std_logic_vector(31 downto 0); +signal douta: std_logic_vector(31 downto 0); +signal dout2: std_logic_vector(35 downto 0); +signal din: std_logic_vector(35 downto 0); +signal dataout: std_logic_vector(31 downto 0); +signal serdata: std_logic_vector(31 downto 0); +signal deserdata: std_logic_vector(15 downto 0); +signal xorword: std_logic_vector(15 downto 0); +signal xorbit: std_logic; +signal going: std_logic; +signal oldgoing: std_logic; +signal isgoing: std_logic; +signal ld: std_logic; +signal dld: std_logic; +signal oldld: std_logic; +signal olddld: std_logic; +signal ena: std_logic; +signal memena: std_logic; +signal resena: std_logic; +signal memacc: std_logic; +signal resacc: std_logic; +signal enaold: std_logic; +signal pgpEnaOld: std_logic; +signal full: std_logic; +signal empty: std_logic; +signal dataFE: std_logic; +signal docount: std_logic; +signal rescount: std_logic; +signal rescountena: std_logic; +signal injacc: std_logic; +signal oldinjacc: std_logic; +signal injena: std_logic; +signal desergo: std_logic; +signal wrfifo: std_logic; +signal intclk: std_logic; +signal thedeserclk: std_logic; +signal ccontrol: std_logic_vector(35 downto 0); +signal cdata: std_logic_vector(31 downto 0); +signal ctrig: std_logic_vector(0 downto 0); +signal overflownerr: std_logic; +signal overflownwords: std_logic; +signal carrynerr: std_logic; +signal carrynwords: std_logic; +signal nerrce: std_logic; +signal oldoverflownerr: std_logic; +signal retclkd: std_logic; + +function vectorize(s: std_logic) return std_logic_vector is +variable v: std_logic_vector(0 downto 0); +begin +v(0) := s; +return v; +end; + +function vectorize(v: std_logic_vector) return std_logic_vector is +begin +return v; +end; +component ser + port( clk: in std_logic; + ld: out std_logic; + go: in std_logic; + --isgoing: in std_logic; + inj: in std_logic; + rst: in std_logic; + d_in: in std_logic_vector(31 downto 0); + d_out: out std_logic + ); +end component; +component deser16 + port( clk: in std_logic; + rst: in std_logic; + go: in std_logic; + d_in: in std_logic; + d_out: out std_logic_vector(15 downto 0); + ld: out std_logic + ); + end component; +component pattern_blk_mem + port ( + clka: IN std_logic; + dina: IN std_logic_VECTOR(31 downto 0); + addra: IN std_logic_VECTOR(9 downto 0); + ena: IN std_logic; + wea: IN std_logic_VECTOR(0 downto 0); + douta: OUT std_logic_VECTOR(31 downto 0); + clkb: IN std_logic; + dinb: IN std_logic_VECTOR(31 downto 0); + addrb: IN std_logic_VECTOR(9 downto 0); + enb: IN std_logic; + web: IN std_logic_VECTOR(0 downto 0); + doutb: OUT std_logic_VECTOR(31 downto 0)); +end component; + +component iblfifo + port ( + din: IN std_logic_VECTOR(35 downto 0); + rd_clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_clk: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(35 downto 0); + empty: OUT std_logic; + full: OUT std_logic); +end component; +component counter30 + port ( + clk: IN std_logic; + ce: IN std_logic; + aclr: IN std_logic; + q_thresh0: OUT std_logic; + q: OUT std_logic_VECTOR(29 downto 0)); +end component; +component BUFGMUX + port ( + O: out std_logic; + I0: in std_logic; + I1: in std_logic; + S: in std_logic + ); +end component; + +-- component ila +-- PORT ( +-- CONTROL : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0); +-- CLK : IN STD_LOGIC; +-- DATA : IN STD_LOGIC_VECTOR(31 DOWNTO 0); +-- TRIG0 : IN STD_LOGIC_VECTOR(0 DOWNTO 0)); +-- +--end component; +-- component icon +-- PORT ( +-- CONTROL0 : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0)); +-- +-- end component; +-- +-- attribute syn_noprune : boolean; +-- attribute syn_noprune of chipscope : label is true; +-- attribute syn_noprune of chipscopeicon : label is true; +begin + + -- serdesrst<=rst or softreset; + pgpAck<=enaold; + memena<= ena and memacc; + resena<= ena and resacc; + rescountena<= ena and rescount; + din<="0000" & serdata; + --dataToFE<=dataFE; +-- with pgpRW select + -- maddr <= nloaded when '1', + -- "0000000" & addrPgp when '0'; + with memacc select + dataTopgp <= dataout when '0', + douta when '1', + (others=>'0') when others; +-- BUFGMUX_inst : BUFGMUX +-- port map ( +-- O => thedeserclk, -- Clock MUX output +-- I0 => retclk, -- Clock0 input +-- I1 => deserclk, -- Clock1 input +-- S => intclk -- Clock select input +-- ); + + with intclk select + thedeserclk<= retclk when '0', + not deserclk when '1', + '0' when others; + process(rst, clk) -- user interface + + begin + if(rst='1') then + nloaded<="1111111111"; + header<="0000000000"; + current<=x"00000000"; + going<='0'; + ena<='1'; + enaold<='0'; + pgpEnaOld<='0'; + memacc<='0'; + pgpErr<='0'; + resacc<='1'; + oldgoing<='0'; + intclk<='0'; + elsif (clk'event and clk='1') then + if(pgpEnable='1' and pgpEnaOld='0') then + ena<='1'; + case pgpRW is + when '1' => -- WRITE + case going is + when '0' => -- not running + case addrPgp is + when "0000" => -- start + if(nloaded/="1111111111") then + going<='1'; + end if; + memacc<='0'; + pgpErr<='0'; + resacc<='0'; + rescount<='1'; + injacc<='0'; + when "0001" => -- stop + pgpErr<='1'; + memacc<='0'; + resacc<='0'; + rescount<='0'; + injacc<='0'; + when "0010" => -- reset + nloaded<="1111111111"; + header<="0000000000"; + current<=x"00000000"; + going<='0'; + memacc<='0'; + pgpErr<='0'; + resacc<='1'; + rescount<='1'; + injacc<='0'; + when "0011" => -- headersize + if unsigned(dataFromPgp(9 downto 0))>=unsigned(nloaded)+1 then + pgpErr<='1'; + memacc<='0'; + resacc<='0'; + injacc<='0'; + rescount<='0'; + else + pgpErr<='0'; + memacc<='0'; + resacc<='0'; + rescount<='0'; + injacc<='0'; + header<=dataFromPgp(9 downto 0); + end if; + when "0100" => -- write memory + if nloaded = "1111111110" then + memacc<='0'; + resacc<='0'; + pgpErr<='1'; + rescount<='0'; + injacc<='0'; + else + memacc<='1'; + resacc<='0'; + pgpErr<='0'; + nloaded<=unsigned(nloaded)+1; + rescount<='0'; + injacc<='0'; + end if; + when "0101" => -- reset counters + rescount<='1'; + memacc<='0'; + resacc<='0'; + pgpErr<='0'; + injacc<='0'; + when "0111" => -- Use internal receive clock + rescount<='0'; + memacc<='0'; + resacc<='0'; + pgpErr<='0'; + injacc<='0'; + intclk<='1'; + when "1000" => -- use receive clock from DORIC + rescount<='0'; + memacc<='0'; + resacc<='0'; + pgpErr<='0'; + injacc<='0'; + intclk<='0'; + when others => -- error + memacc<='0'; + resacc<='0'; + pgpErr<='1'; + rescount<='0'; + injacc<='0'; + end case; + when '1' => -- running + case addrPgp is + when "0001" => -- stop + pgpErr<='0'; + memacc<='0'; + resacc<='1'; + rescount<='0'; + injacc<='0'; + going<='0'; + when "0101" => -- reset counters + pgpErr<='0'; + memacc<='0'; + resacc<='0'; + rescount<='1'; + injacc<='0'; + when "0110" => -- inject error + rescount<='0'; + memacc<='0'; + resacc<='0'; + pgpErr<='0'; + injacc<='1'; + when others => + pgpErr<='1'; + memacc<='0'; + resacc<='0'; + injacc<='0'; + rescount<='0'; + end case; + when others => + end case; + when '0' => -- READ (both running and stopped) + resacc<='0'; + injacc<='0'; + rescount<='0'; + case addrPgp is + when "0000" => -- number of words MSB + memacc<='0'; + pgpErr<='0'; + dataout<=nwords(63 downto 32); + when "0001" => -- number of words LSB + memacc<='0'; + pgpErr<='0'; + dataout<=nwords(31 downto 0); + when "0010" => -- number of errors MSB + memacc<='0'; + pgpErr<='0'; + dataout<=nerr(63 downto 32); + when "0011" => -- number of errors LSB + memacc<='0'; + pgpErr<='0'; + dataout<=nerr(31 downto 0); + when "0100" => -- number of loaded words + memacc<='0'; + pgpErr<='0'; + dataout<="0000000000000000000000" & unsigned(nloaded)+1; + when "0101" => -- last loaded word + if (nloaded="1111111111") then + pgpErr<='1'; + memacc<='0'; + dataout<=x"ffffffff"; + else + pgpErr<='0'; + memacc<='1'; + end if; + when "0110" => -- empty and full flags + memacc<='0'; + pgpErr<='0'; + dataout<=x"0000000" &'0'& going & full & empty; + when others => + memacc<='0'; + pgpErr<='1'; + dataout<=x"ffffffff"; + end case; + when others=> + end case; + else + ena<='0'; + end if; + pgpEnaOld<=pgpEnable; + enaold<=ena; + oldgoing<=going; + + end if; + + end process; + + process(serclk,rst) -- serializer + begin + if (rst='1') then + oldld<='0'; + pointer<="0000000000"; + desergo<='0'; + wrfifo<='0'; + doricreset<='1'; + elsif (serclk'event and serclk='1') then + if (going='1') then + if (ld='0' and oldld='1') then + if pointer=nloaded then + pointer<=header; + else + pointer<=unsigned(pointer)+1; + end if; + if(desergo='1') then + wrfifo<='1'; + end if; + elsif (ld='1' and oldld='0') then + if(pointer>=header) then + desergo<='1'; + doricreset<='1'; + else + doricreset<='0'; + end if; + else + wrfifo<='0'; + end if; + elsif (going='0' and oldgoing='1') then + pointer<="0000000000" ; + desergo<='0'; + wrfifo<='0'; + end if; + if (injacc='1' and oldinjacc='0') then + injena<='1'; + else + injena<='0'; + end if; + oldinjacc<=injacc; + oldld<=ld; + end if; + end process; + + process(thedeserclk,rst) -- deserializer + begin + if (rst='1') then + olddld<='0'; + xorbit<='0'; + nerrce<='0'; + oldoverflownerr<='0'; + xorword<=x"0000"; + elsif (thedeserclk'event and thedeserclk='1') then + if (olddld='1') then + for I in 15 downto 0 loop + xorword(I) <= deserdata(I) xor dout2(I*2) xor dout2(I*2+1); + end loop; + else + xorword(15 downto 1) <= xorword(14 downto 0); + xorword(0)<='0'; + end if; + xorbit<=xorword(15); + nerrce<=xorbit; + if(overflownerr='1' and oldoverflownerr='0')then + carrynerr<='1'; + else + carrynerr<='0'; + end if; + carrynwords<=overflownwords and dld; + olddld<=dld; + oldoverflownerr<=overflownerr; + end if; + end process; + +the_mem : pattern_blk_mem + port map ( + clka => clk, + dina => dataFromPgp, + addra => nloaded, + ena => memena, + wea => vectorize(pgpRW), + douta => douta, + clkb => serclk, + dinb => (others=>'0'), + addrb => pointer, + enb => ld, + web => vectorize('0'), + doutb => serdata); +serializer : ser + port map ( + clk => serclk, + ld => ld, + go => going, + --isgoing => isgoing, + inj => injena, + rst => resena, + d_in => serdata, + d_out => dataToFE ); + + +valstore : iblfifo -- stores the values to be checked + port map ( + din => din, + rd_clk => thedeserclk, + rd_en => dld, + rst => resena, + wr_clk => serclk, + wr_en => wrfifo, + dout => dout2, + empty => empty, + full => full); +deserializer: deser16 + port map ( + clk => thedeserclk, + rst => resena, + go => desergo, + d_in => dataFromFE, + d_out => deserdata, + ld => dld); +nerrlow : counter30 + port map ( + clk => thedeserclk, + ce => nerrce, + aclr => rescountena, + q_thresh0 => overflownerr, + q => nerr(29 downto 0)); +nerrhigh : counter30 + port map ( + clk => thedeserclk, + ce => carrynerr, + aclr => rescountena, + q_thresh0 => open, + q => nerr(59 downto 30)); + +nerr(63 downto 60)<="0000"; + +nwordslow : counter30 + port map ( + clk => thedeserclk, + ce => olddld, + aclr => rescountena, + q_thresh0 => overflownwords, + q => nwords(29 downto 0)); +nwordshigh : counter30 + port map ( + clk => thedeserclk, + ce => carrynwords, + aclr => rescountena, + q_thresh0 => open, + q => nwords(59 downto 30)); + +nwords(63 downto 60)<="0000"; +-- cdata(0)<=dld; +-- cdata(1)<=olddld; +-- cdata(2)<=docount; +-- cdata(3)<=dataFromFE; +-- cdata(7 downto 4)<=dout2(31 downto 28); +-- cdata(23 downto 8)<=deserdata; +-- cdata(31 downto 24)<=dout2(7 downto 0); +-- ctrig(0)<=desergo; +-- chipscope : ila +-- port map ( +-- CONTROL => ccontrol, +-- CLK => deserclk, +-- DATA => cdata, +-- TRIG0 => ctrig); +-- chipscopeicon : icon +-- port map ( +-- CONTROL0 => ccontrol); + + +end PATTERN_CMD; +-------------------------------------------------------------- diff --git a/rce/fw-hsio/projects/IBLcableTester/hdl/pattern_mem.vhd b/rce/fw-hsio/projects/IBLcableTester/hdl/pattern_mem.vhd new file mode 100644 index 00000000..0ed40e5b --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/hdl/pattern_mem.vhd @@ -0,0 +1,745 @@ +-------------------------------------------------------------- +-- Serializer for High Speed I/O board (ATLAS Pixel teststand) +-- Martin Kocian 08/2009 +-------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use work.all; + +-------------------------------------------------------------- + +entity pattern_mem is +generic( DELAY: integer:=0); +port( clk: in std_logic; + serclk: in std_logic; + deserclk: in std_logic; + deserclk90: in std_logic; + rst: in std_logic; + pgpEnable: in std_logic; + pgpRW: in std_logic; + pgpAck: out std_logic; + pgpErr: out std_logic; + dataFromPgp:in std_logic_vector(31 downto 0); + addrPgp: in std_logic_vector(3 downto 0); + dataToPgp: out std_logic_vector(31 downto 0); + dataFromFE: in std_logic; + dataToFE: out std_logic +); +end pattern_mem; + +-------------------------------------------------------------- + +architecture PATTERN_MEM of pattern_mem is + +signal nloaded : std_logic_vector(9 downto 0); +signal pointer : std_logic_vector(9 downto 0); +signal header : std_logic_vector(9 downto 0); +signal nwords: std_logic_vector(63 downto 0); +signal nerr: std_logic_vector(63 downto 0); +signal current: std_logic_vector(31 downto 0); +signal doutb: std_logic_vector(31 downto 0); +signal douta: std_logic_vector(31 downto 0); +signal dout2: std_logic_vector(35 downto 0); +signal din: std_logic_vector(35 downto 0); +signal dataout: std_logic_vector(31 downto 0); +signal serdata: std_logic_vector(31 downto 0); +signal deserdata: std_logic_vector(31 downto 0); +signal xorword: std_logic_vector(31 downto 0); +signal xorword2: std_logic_vector(31 downto 0); +signal xorbit: std_logic; +signal going: std_logic; +signal oldgoing: std_logic; +signal ld: std_logic; +signal dld: std_logic; +signal oldld: std_logic; +signal olddld: std_logic; +signal ena: std_logic; +signal memena: std_logic; +signal resena: std_logic; +signal delena: std_logic; +signal delrstena: std_logic; +signal delayreset: std_logic; +signal delacc: std_logic; +signal delrstacc: std_logic; +signal memacc: std_logic; +signal resacc: std_logic; +signal enaold: std_logic; +signal pgpEnaOld: std_logic; +signal full: std_logic; +signal empty: std_logic; +signal dataFE: std_logic; +signal dataFEsync: std_logic; +signal dataFromFEd: std_logic; +signal rescount: std_logic; +signal rescountena: std_logic; +signal injacc: std_logic; +signal oldinjacc: std_logic; +signal injena: std_logic; +signal loopback: std_logic; +signal ccontrol: std_logic_vector(35 downto 0); +signal cdata: std_logic_vector(31 downto 0); +signal ctrig: std_logic_vector(0 downto 0); +signal overflownerr: std_logic; +signal overflownwords: std_logic; +signal carrynerr: std_logic; +signal carrynwords: std_logic; +signal nerrce: std_logic; +signal oldoverflownerr: std_logic; +signal dataToFEs: std_logic; +signal phaseConfig: std_logic; +signal oldPhaseConfig: std_logic; +signal doPhaseConfig: std_logic; + + +function vectorize(s: std_logic) return std_logic_vector is +variable v: std_logic_vector(0 downto 0); +begin +v(0) := s; +return v; +end; + +function vectorize(v: std_logic_vector) return std_logic_vector is +begin +return v; +end; +component ser + port( clk: in std_logic; + ld: out std_logic; + go: in std_logic; + inj: in std_logic; + rst: in std_logic; + d_in: in std_logic_vector(31 downto 0); + d_out: out std_logic + ); +end component; +component deser + port( clk: in std_logic; + rst: in std_logic; + go: in std_logic; + d_in: in std_logic; + d_out: out std_logic_vector(31 downto 0); + ld: out std_logic + ); + end component; + component syncdatac port ( + clk : in std_logic ; -- clock input + clk90 : in std_logic ; -- clock 90 input + rdatain : in std_logic; -- data input + rst : in std_logic ; -- reset input + useaout : out std_logic ; -- useA output for cascade + usebout : out std_logic ; -- useB output for cascade + usecout : out std_logic ; -- useC output for cascade + usedout : out std_logic ; -- useD output for cascade + sdataout : out std_logic; -- data out + phaseConfig : in std_logic); -- FS: Setting phase configuration flag + end component; +component pattern_blk_mem + port ( + clka: IN std_logic; + dina: IN std_logic_VECTOR(31 downto 0); + addra: IN std_logic_VECTOR(9 downto 0); + ena: IN std_logic; + wea: IN std_logic_VECTOR(0 downto 0); + douta: OUT std_logic_VECTOR(31 downto 0); + clkb: IN std_logic; + dinb: IN std_logic_VECTOR(31 downto 0); + addrb: IN std_logic_VECTOR(9 downto 0); + enb: IN std_logic; + web: IN std_logic_VECTOR(0 downto 0); + doutb: OUT std_logic_VECTOR(31 downto 0)); +end component; +COMPONENT pattern_blk_mem_62 + PORT ( + clka : IN STD_LOGIC; + ena : IN STD_LOGIC; + wea : IN STD_LOGIC_VECTOR(0 DOWNTO 0); + addra : IN STD_LOGIC_VECTOR(9 DOWNTO 0); + dina : IN STD_LOGIC_VECTOR(31 DOWNTO 0); + clkb : IN STD_LOGIC; + enb : IN STD_LOGIC; + addrb : IN STD_LOGIC_VECTOR(9 DOWNTO 0); + doutb : OUT STD_LOGIC_VECTOR(31 DOWNTO 0) + ); +END COMPONENT; +component iblfifo + port ( + din: IN std_logic_VECTOR(35 downto 0); + rd_clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_clk: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(35 downto 0); + empty: OUT std_logic; + full: OUT std_logic); +end component; +component counter30 + port ( + clk: IN std_logic; + ce: IN std_logic; + aclr: IN std_logic; + q_thresh0: OUT std_logic; + q: OUT std_logic_VECTOR(29 downto 0)); +end component; +component IDELAY + generic (IOBDELAY_TYPE : string := "DEFAULT"; --(DEFAULT, FIXED, VARIABLE) + IOBDELAY_VALUE : integer := 0 --(0 to 63) + ); + port ( + O : out STD_LOGIC; + I : in STD_LOGIC; + C : in STD_LOGIC; + CE : in STD_LOGIC; + INC : in STD_LOGIC; + RST : in STD_LOGIC + ); +end component; + +--component ila + --PORT ( + --CONTROL : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0); + --CLK : IN STD_LOGIC; + --DATA : IN STD_LOGIC_VECTOR(31 DOWNTO 0); + --TRIG0 : IN STD_LOGIC_VECTOR(0 DOWNTO 0)); +-- +--end component; + --component icon + --PORT ( + --CONTROL0 : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0)); +-- + --end component; + +-- attribute syn_noprune : boolean; +-- attribute syn_noprune of chipscope : label is true; +-- attribute syn_noprune of chipscopeicon : label is true; + +begin + + dataToFE<=dataToFEs; + -- serdesrst<=rst or softreset; + pgpAck<=enaold; + memena<= ena and memacc; + resena<= ena and resacc; + delena<= ena and delacc; + delrstena<= ena and delrstacc; + rescountena<= ena and rescount; + din<="0000" & serdata; + with loopback select + dataFE <= dataFromFEd when '0', + dataToFEs when '1', + '0' when others; +-- with pgpRW select + -- maddr <= nloaded when '1', + -- "0000000" & addrPgp when '0'; + with memacc select + dataTopgp <= dataout when '0', + douta when '1', + (others=>'0') when others; + + process(rst, clk) -- user interface + + begin + if(rst='1') then + nloaded<="1111111111"; + header<="0000000000"; + current<=x"00000000"; + going<='0'; + ena<='1'; + enaold<='0'; + pgpEnaOld<='0'; + memacc<='0'; + rescount<='0'; + pgpErr<='0'; + resacc<='1'; + delrstacc<='0'; + delacc<='0'; + oldgoing<='0'; + loopback<='0'; + phaseConfig <='0'; + elsif (clk'event and clk='1') then + if(pgpEnable='1' and pgpEnaOld='0') then + ena<='1'; + case pgpRW is + when '1' => -- WRITE + case going is + when '0' => -- not running + case addrPgp is + when "0000" => -- start + if(nloaded/="1111111111") then + going<='1'; + end if; + memacc<='0'; + pgpErr<='0'; + resacc<='0'; + rescount<='1'; + injacc<='0'; + delacc<='0'; + delrstacc<='0'; + phaseConfig<='0'; + when "0001" => -- stop + pgpErr<='1'; + memacc<='0'; + resacc<='0'; + rescount<='0'; + injacc<='0'; + delacc<='0'; + delrstacc<='0'; + phaseConfig<='0'; + when "0010" => -- reset + nloaded<="1111111111"; + header<="0000000000"; + current<=x"00000000"; + going<='0'; + memacc<='0'; + pgpErr<='0'; + resacc<='1'; + rescount<='1'; + injacc<='0'; + delacc<='0'; + delrstacc<='0'; + phaseConfig<='0'; + when "0011" => -- headersize + if unsigned(dataFromPgp(9 downto 0))>=unsigned(nloaded)+1 then + pgpErr<='1'; + memacc<='0'; + resacc<='0'; + injacc<='0'; + delacc<='0'; + rescount<='0'; + delrstacc<='0'; + phaseConfig<='0'; + else + pgpErr<='0'; + memacc<='0'; + resacc<='0'; + rescount<='0'; + injacc<='0'; + delacc<='0'; + delrstacc<='0'; + phaseConfig<='0'; + header<=dataFromPgp(9 downto 0); + end if; + when "0100" => -- write memory + if nloaded = "1111111110" then + memacc<='0'; + resacc<='0'; + pgpErr<='1'; + rescount<='0'; + injacc<='0'; + delacc<='0'; + delrstacc<='0'; + phaseConfig<='0'; + else + memacc<='1'; + resacc<='0'; + pgpErr<='0'; + nloaded<=unsigned(nloaded)+1; + rescount<='0'; + injacc<='0'; + delacc<='0'; + delrstacc<='0'; + phaseConfig<='0'; + end if; + when "0101" => -- reset counters + rescount<='1'; + memacc<='0'; + resacc<='0'; + pgpErr<='0'; + delacc<='0'; + injacc<='0'; + delrstacc<='0'; + phaseConfig<='0'; + when "0111" => -- loopback on + rescount<='0'; + memacc<='0'; + resacc<='0'; + pgpErr<='0'; + injacc<='0'; + delacc<='0'; + loopback<='1'; + delrstacc<='0'; + phaseConfig<='0'; + when "1000" => -- loopback off + rescount<='0'; + memacc<='0'; + resacc<='0'; + pgpErr<='0'; + injacc<='0'; + delacc<='0'; + loopback<='0'; + delrstacc<='0'; + phaseConfig<='0'; + when "1001" => -- increment delay for incoming serial data + memacc<='0'; + resacc<='0'; + pgpErr<='0'; + rescount<='0'; + injacc<='0'; + delacc<='1'; + delrstacc<='0'; + phaseConfig<='0'; + when "1010" => -- reset delay + memacc<='0'; + resacc<='0'; + pgpErr<='0'; + rescount<='0'; + injacc<='0'; + delacc<='0'; + delrstacc<='1'; + phaseConfig<='0'; + when others => -- error + memacc<='0'; + resacc<='0'; + pgpErr<='1'; + rescount<='0'; + injacc<='0'; + delacc<='0'; + delrstacc<='0'; + phaseConfig<='0'; + end case; + when '1' => -- running + case addrPgp is + when "0001" => -- stop + pgpErr<='0'; + memacc<='0'; + resacc<='1'; + rescount<='0'; + injacc<='0'; + delacc<='0'; + going<='0'; + delrstacc<='0'; + phaseConfig<='0'; + when "0101" => -- reset counters + pgpErr<='0'; + memacc<='0'; + resacc<='0'; + rescount<='1'; + injacc<='0'; + delacc<='0'; + delrstacc<='0'; + phaseConfig<='0'; + when "0110" => -- inject error + rescount<='0'; + memacc<='0'; + resacc<='0'; + pgpErr<='0'; + injacc<='1'; + delacc<='0'; + delrstacc<='0'; + phaseConfig<='0'; + when "1001" => -- increment delay for incoming serial data + pgpErr<='0'; + memacc<='0'; + resacc<='0'; + injacc<='0'; + rescount<='0'; + delacc<='1'; + delrstacc<='0'; + phaseConfig<='0'; + when "1010" => -- reset delay for incoming serial data + pgpErr<='0'; + memacc<='0'; + resacc<='0'; + injacc<='0'; + rescount<='0'; + delacc<='0'; + delrstacc<='1'; + phaseConfig<='0'; + when "1011" => -- calibrate phase + rescount<='0'; + memacc<='0'; + resacc<='0'; + pgpErr<='0'; + injacc<='0'; + delacc<='0'; + delrstacc<='0'; + phaseConfig<='1'; + when others => + pgpErr<='1'; + memacc<='0'; + resacc<='0'; + injacc<='0'; + rescount<='0'; + delacc<='0'; + delrstacc<='0'; + phaseConfig<='0'; + end case; + when others => + end case; + when '0' => -- READ (both running and stopped) + resacc<='0'; + injacc<='0'; + rescount<='0'; + delacc<='0'; + delrstacc<='0'; + phaseConfig<='0'; + case addrPgp is + when "0000" => -- number of words MSB + memacc<='0'; + pgpErr<='0'; + dataout<=nwords(63 downto 32); + when "0001" => -- number of words LSB + memacc<='0'; + pgpErr<='0'; + dataout<=nwords(31 downto 0); + when "0010" => -- number of errors MSB + memacc<='0'; + pgpErr<='0'; + dataout<=nerr(63 downto 32); + when "0011" => -- number of errors LSB + memacc<='0'; + pgpErr<='0'; + dataout<=nerr(31 downto 0); + when "0100" => -- number of loaded words + memacc<='0'; + pgpErr<='0'; + dataout<="0000000000000000000000" & unsigned(nloaded)+1; + when "0101" => -- last loaded word + if (nloaded="1111111111") then + pgpErr<='1'; + memacc<='0'; + dataout<=x"ffffffff"; + else + pgpErr<='0'; + memacc<='1'; + end if; + when "0110" => -- empty and full flags + memacc<='0'; + pgpErr<='0'; + dataout<=x"0000000" &'0'& going & full & empty; + when others => + memacc<='0'; + pgpErr<='1'; + dataout<=x"ffffffff"; + end case; + when others => + end case; + else + ena<='0'; + end if; + pgpEnaOld<=pgpEnable; + enaold<=ena; + oldgoing<=going; + delayreset<=delrstena or rst; + end if; + + end process; + + process(serclk,rst) -- serializer + begin + if (rst='1') then + oldld<='0'; + pointer<="0000000000"; + elsif (serclk'event and serclk='1') then + if (going='1') then + if (ld='0' and oldld='1') then + if pointer=nloaded then + pointer<=header; + else + pointer<=unsigned(pointer)+1; + end if; + end if; + elsif (going='0' and oldgoing='1') then + pointer<="0000000000" ; + end if; + if (injacc='1' and oldinjacc='0') then + injena<='1'; + else + injena<='0'; + end if; + oldinjacc<=injacc; + oldld<=ld; + end if; + end process; + + process(deserclk,rst) -- deserializer + begin + if (rst='1') then + oldphaseConfig <= '0'; + doPhaseConfig <='0'; + olddld<='0'; + nerrce<='0'; + oldoverflownerr<='0'; + xorword<=x"00000000"; + xorword2<=x"00000000"; + xorbit<='0'; + elsif (deserclk'event and deserclk='1') then + if (olddld='1') then + xorword2<=dout2(31 downto 0); + xorword<= deserdata ; +-- xorword<=x"12345678"; + else + xorword(31 downto 1) <= xorword(30 downto 0); + xorword(0)<='0'; + xorword2(31 downto 1) <= xorword2(30 downto 0); + xorword2(0)<='0'; + end if; + xorbit<=xorword(31) xor xorword2(31); + nerrce<=xorbit; + if(overflownerr='1' and oldoverflownerr='0')then + carrynerr<='1'; + else + carrynerr<='0'; + end if; + if(phaseConfig='1' and oldphaseConfig='0')then + doPhaseConfig<='1'; + else + doPhaseConfig<='0'; + end if; + carrynwords<=overflownwords and dld; + olddld<=dld; + oldoverflownerr<=overflownerr; + oldphaseConfig<=phaseConfig; + end if; + end process; + +the_mem : pattern_blk_mem + port map ( + clka => clk, + dina => dataFromPgp, + addra => nloaded, + ena => memena, + wea => vectorize(pgpRW), + douta => douta, + clkb => serclk, + dinb => (others=>'0'), + addrb => pointer, + enb => ld, + web => vectorize('0'), + doutb => serdata); +-- the_mem : pattern_blk_mem_62 +-- PORT MAP ( +-- clka => clk, +-- ena => memena, +-- wea => vectorize(pgpRW), +-- addra => nloaded, +-- dina => dataFromPgp, +-- clkb => serclk, +-- enb => ld, +-- addrb => pointer, +-- doutb => serdata +-- ); +serializer : ser + port map ( + clk => serclk, + ld => ld, + go => going, + inj => injena, + rst => resena, + d_in => serdata, + d_out => dataToFEs ); + +valstore : iblfifo -- stores the values to be checked + port map ( + din => din, + rd_clk => deserclk, + rd_en => dld, + rst => resena, + wr_clk => serclk, + wr_en => oldld, + dout => dout2, + empty => empty, + full => full); + receivedata: syncdatac + port map( + phaseConfig => doPhaseConfig, + clk => deserclk, + clk90 => deserclk90, + rdatain => dataFE, + --rdatain => IOMXOUT(1), + rst => rst, + useaout => open, + usebout => open, + usecout => open, + usedout => open, + sdataout => dataFEsync); +deserializer: deser + port map ( + clk => deserclk, + rst => resena, + go => going, + d_in => dataFEsync, + d_out => deserdata, + ld => dld); +nerrlow : counter30 + port map ( + clk => deserclk, + ce => nerrce, + aclr => rescountena, + q_thresh0 => overflownerr, + q => nerr(29 downto 0)); +nerrhigh : counter30 + port map ( + clk => deserclk, + ce => carrynerr, + aclr => rescountena, + q_thresh0 => open, + q => nerr(59 downto 30)); + +nerr(63 downto 60)<="0000"; + +nwordslow : counter30 + port map ( + clk => deserclk, + ce => olddld, + aclr => rescountena, + q_thresh0 => overflownwords, + q => nwords(29 downto 0)); +nwordshigh : counter30 + port map ( + clk => deserclk, + ce => carrynwords, + aclr => rescountena, + q_thresh0 => open, + q => nwords(59 downto 30)); + +nwords(63 downto 60)<="0000"; + +delayline : IDELAY + generic map ( + IOBDELAY_TYPE => "VARIABLE", -- Set to DEFAULT for -- Zero Hold Time Mode + IOBDELAY_VALUE => 0 -- (0 to 63) + ) + port map ( + O => dataFromFEd, + I => dataFromFE, + C => clk, + CE => delena, + INC => '1', + RST => delayreset + ); + + + +-- cdata(0)<=dld; +-- cdata(1)<=olddld; +-- cdata(2)<=overflownerr; +-- cdata(3)<=carrynerr; +-- cdata(4)<=nerrce; +-- cdata(5)<=nerr(30); +-- cdata(6)<=nerr(31); +-- cdata(7)<=nerr(0); +-- cdata(8)<=nerr(1); +-- cdata(3)<=olddld; +-- cdata(4)<=docount; +-- cdata(5)<=datafe; +-- cdata(6)<=xorword(31); +-- cdata(7)<=xorword2(31); +-- cdata(8)<=loopback; +-- cdata(9)<=dataFromFE; +-- cdata(31 downto 9) <=(others=>'0'); +-- ctrig(0)<=overflownerr; +-- chipscope : ila +-- port map ( +-- CONTROL => ccontrol, +-- CLK => deserclk, +-- DATA => cdata, +-- TRIG0 => ctrig); +-- chipscopeicon : icon +-- port map ( +-- CONTROL0 => ccontrol); + +end PATTERN_MEM; +-------------------------------------------------------------- diff --git a/rce/fw-hsio/projects/IBLcableTester/hdl/pattern_memOld.vhd b/rce/fw-hsio/projects/IBLcableTester/hdl/pattern_memOld.vhd new file mode 100644 index 00000000..856a4d99 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/hdl/pattern_memOld.vhd @@ -0,0 +1,677 @@ +-------------------------------------------------------------- +-- Serializer for High Speed I/O board (ATLAS Pixel teststand) +-- Martin Kocian 08/2009 +-------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use work.all; + +-------------------------------------------------------------- + +entity pattern_mem is +generic( DELAY: integer:=0); +port( clk: in std_logic; + serclk: in std_logic; + deserclk: in std_logic; + rst: in std_logic; + pgpEnable: in std_logic; + pgpRW: in std_logic; + pgpAck: out std_logic; + pgpErr: out std_logic; + dataFromPgp:in std_logic_vector(31 downto 0); + addrPgp: in std_logic_vector(3 downto 0); + dataToPgp: out std_logic_vector(31 downto 0); + dataFromFE: in std_logic; + dataToFE: out std_logic +); +end pattern_mem; + +-------------------------------------------------------------- + +architecture PATTERN_MEM of pattern_mem is + +signal nloaded : std_logic_vector(9 downto 0); +signal pointer : std_logic_vector(9 downto 0); +signal header : std_logic_vector(9 downto 0); +signal nwords: std_logic_vector(63 downto 0); +signal nerr: std_logic_vector(63 downto 0); +signal current: std_logic_vector(31 downto 0); +signal doutb: std_logic_vector(31 downto 0); +signal douta: std_logic_vector(31 downto 0); +signal dout2: std_logic_vector(35 downto 0); +signal din: std_logic_vector(35 downto 0); +signal dataout: std_logic_vector(31 downto 0); +signal serdata: std_logic_vector(31 downto 0); +signal deserdata: std_logic_vector(31 downto 0); +signal xorword: std_logic_vector(31 downto 0); +signal xorword2: std_logic_vector(31 downto 0); +signal xorbit: std_logic; +signal going: std_logic; +signal oldgoing: std_logic; +signal ld: std_logic; +signal dld: std_logic; +signal oldld: std_logic; +signal olddld: std_logic; +signal ena: std_logic; +signal memena: std_logic; +signal resena: std_logic; +signal delena: std_logic; +signal delrstena: std_logic; +signal delayreset: std_logic; +signal delacc: std_logic; +signal delrstacc: std_logic; +signal memacc: std_logic; +signal resacc: std_logic; +signal enaold: std_logic; +signal pgpEnaOld: std_logic; +signal full: std_logic; +signal empty: std_logic; +signal dataFE: std_logic; +signal dataFromFEd: std_logic; +signal rescount: std_logic; +signal rescountena: std_logic; +signal injacc: std_logic; +signal oldinjacc: std_logic; +signal injena: std_logic; +signal loopback: std_logic; +signal ccontrol: std_logic_vector(35 downto 0); +signal cdata: std_logic_vector(31 downto 0); +signal ctrig: std_logic_vector(0 downto 0); +signal overflownerr: std_logic; +signal overflownwords: std_logic; +signal carrynerr: std_logic; +signal carrynwords: std_logic; +signal nerrce: std_logic; +signal oldoverflownerr: std_logic; +signal dataToFEs: std_logic; + + +function vectorize(s: std_logic) return std_logic_vector is +variable v: std_logic_vector(0 downto 0); +begin +v(0) := s; +return v; +end; + +function vectorize(v: std_logic_vector) return std_logic_vector is +begin +return v; +end; +component ser + port( clk: in std_logic; + ld: out std_logic; + go: in std_logic; + inj: in std_logic; + rst: in std_logic; + d_in: in std_logic_vector(31 downto 0); + d_out: out std_logic + ); +end component; +component deser + port( clk: in std_logic; + rst: in std_logic; + go: in std_logic; + d_in: in std_logic; + d_out: out std_logic_vector(31 downto 0); + ld: out std_logic + ); + end component; +component pattern_blk_mem + port ( + clka: IN std_logic; + dina: IN std_logic_VECTOR(31 downto 0); + addra: IN std_logic_VECTOR(9 downto 0); + ena: IN std_logic; + wea: IN std_logic_VECTOR(0 downto 0); + douta: OUT std_logic_VECTOR(31 downto 0); + clkb: IN std_logic; + dinb: IN std_logic_VECTOR(31 downto 0); + addrb: IN std_logic_VECTOR(9 downto 0); + enb: IN std_logic; + web: IN std_logic_VECTOR(0 downto 0); + doutb: OUT std_logic_VECTOR(31 downto 0)); +end component; +COMPONENT pattern_blk_mem_62 + PORT ( + clka : IN STD_LOGIC; + ena : IN STD_LOGIC; + wea : IN STD_LOGIC_VECTOR(0 DOWNTO 0); + addra : IN STD_LOGIC_VECTOR(9 DOWNTO 0); + dina : IN STD_LOGIC_VECTOR(31 DOWNTO 0); + clkb : IN STD_LOGIC; + enb : IN STD_LOGIC; + addrb : IN STD_LOGIC_VECTOR(9 DOWNTO 0); + doutb : OUT STD_LOGIC_VECTOR(31 DOWNTO 0) + ); +END COMPONENT; +component iblfifo + port ( + din: IN std_logic_VECTOR(35 downto 0); + rd_clk: IN std_logic; + rd_en: IN std_logic; + rst: IN std_logic; + wr_clk: IN std_logic; + wr_en: IN std_logic; + dout: OUT std_logic_VECTOR(35 downto 0); + empty: OUT std_logic; + full: OUT std_logic); +end component; +component counter30 + port ( + clk: IN std_logic; + ce: IN std_logic; + aclr: IN std_logic; + q_thresh0: OUT std_logic; + q: OUT std_logic_VECTOR(29 downto 0)); +end component; +component IDELAY + generic (IOBDELAY_TYPE : string := "DEFAULT"; --(DEFAULT, FIXED, VARIABLE) + IOBDELAY_VALUE : integer := 0 --(0 to 63) + ); + port ( + O : out STD_LOGIC; + I : in STD_LOGIC; + C : in STD_LOGIC; + CE : in STD_LOGIC; + INC : in STD_LOGIC; + RST : in STD_LOGIC + ); +end component; + +--component ila + --PORT ( + --CONTROL : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0); + --CLK : IN STD_LOGIC; + --DATA : IN STD_LOGIC_VECTOR(31 DOWNTO 0); + --TRIG0 : IN STD_LOGIC_VECTOR(0 DOWNTO 0)); +-- +--end component; + --component icon + --PORT ( + --CONTROL0 : INOUT STD_LOGIC_VECTOR(35 DOWNTO 0)); +-- + --end component; + +-- attribute syn_noprune : boolean; +-- attribute syn_noprune of chipscope : label is true; +-- attribute syn_noprune of chipscopeicon : label is true; + +begin + + dataToFE<=dataToFEs; + -- serdesrst<=rst or softreset; + pgpAck<=enaold; + memena<= ena and memacc; + resena<= ena and resacc; + delena<= ena and delacc; + delrstena<= ena and delrstacc; + rescountena<= ena and rescount; + din<="0000" & serdata; + with loopback select + dataFE <= dataFromFEd when '0', + dataToFEs when '1', + '0' when others; +-- with pgpRW select + -- maddr <= nloaded when '1', + -- "0000000" & addrPgp when '0'; + with memacc select + dataTopgp <= dataout when '0', + douta when '1', + (others=>'0') when others; + + process(rst, clk) -- user interface + + begin + if(rst='1') then + nloaded<="1111111111"; + header<="0000000000"; + current<=x"00000000"; + going<='0'; + ena<='1'; + enaold<='0'; + pgpEnaOld<='0'; + memacc<='0'; + rescount<='0'; + pgpErr<='0'; + resacc<='1'; + delrstacc<='0'; + delacc<='0'; + oldgoing<='0'; + loopback<='0'; + elsif (clk'event and clk='1') then + if(pgpEnable='1' and pgpEnaOld='0') then + ena<='1'; + case pgpRW is + when '1' => -- WRITE + case going is + when '0' => -- not running + case addrPgp is + when "0000" => -- start + if(nloaded/="1111111111") then + going<='1'; + end if; + memacc<='0'; + pgpErr<='0'; + resacc<='0'; + rescount<='1'; + injacc<='0'; + delacc<='0'; + delrstacc<='0'; + when "0001" => -- stop + pgpErr<='1'; + memacc<='0'; + resacc<='0'; + rescount<='0'; + injacc<='0'; + delacc<='0'; + delrstacc<='0'; + when "0010" => -- reset + nloaded<="1111111111"; + header<="0000000000"; + current<=x"00000000"; + going<='0'; + memacc<='0'; + pgpErr<='0'; + resacc<='1'; + rescount<='1'; + injacc<='0'; + delacc<='0'; + delrstacc<='0'; + when "0011" => -- headersize + if unsigned(dataFromPgp(9 downto 0))>=unsigned(nloaded)+1 then + pgpErr<='1'; + memacc<='0'; + resacc<='0'; + injacc<='0'; + delacc<='0'; + rescount<='0'; + delrstacc<='0'; + else + pgpErr<='0'; + memacc<='0'; + resacc<='0'; + rescount<='0'; + injacc<='0'; + delacc<='0'; + delrstacc<='0'; + header<=dataFromPgp(9 downto 0); + end if; + when "0100" => -- write memory + if nloaded = "1111111110" then + memacc<='0'; + resacc<='0'; + pgpErr<='1'; + rescount<='0'; + injacc<='0'; + delacc<='0'; + delrstacc<='0'; + else + memacc<='1'; + resacc<='0'; + pgpErr<='0'; + nloaded<=unsigned(nloaded)+1; + rescount<='0'; + injacc<='0'; + delacc<='0'; + delrstacc<='0'; + end if; + when "0101" => -- reset counters + rescount<='1'; + memacc<='0'; + resacc<='0'; + pgpErr<='0'; + delacc<='0'; + injacc<='0'; + delrstacc<='0'; + when "0111" => -- loopback on + rescount<='0'; + memacc<='0'; + resacc<='0'; + pgpErr<='0'; + injacc<='0'; + delacc<='0'; + loopback<='1'; + delrstacc<='0'; + when "1000" => -- loopback off + rescount<='0'; + memacc<='0'; + resacc<='0'; + pgpErr<='0'; + injacc<='0'; + delacc<='0'; + loopback<='0'; + delrstacc<='0'; + when "1001" => -- increment delay for incoming serial data + memacc<='0'; + resacc<='0'; + pgpErr<='0'; + rescount<='0'; + injacc<='0'; + delacc<='1'; + delrstacc<='0'; + when "1010" => -- reset delay + memacc<='0'; + resacc<='0'; + pgpErr<='0'; + rescount<='0'; + injacc<='0'; + delacc<='0'; + delrstacc<='1'; + when others => -- error + memacc<='0'; + resacc<='0'; + pgpErr<='1'; + rescount<='0'; + injacc<='0'; + delacc<='0'; + delrstacc<='0'; + end case; + when '1' => -- running + case addrPgp is + when "0001" => -- stop + pgpErr<='0'; + memacc<='0'; + resacc<='1'; + rescount<='0'; + injacc<='0'; + delacc<='0'; + going<='0'; + delrstacc<='0'; + when "0101" => -- reset counters + pgpErr<='0'; + memacc<='0'; + resacc<='0'; + rescount<='1'; + injacc<='0'; + delacc<='0'; + delrstacc<='0'; + when "0110" => -- inject error + rescount<='0'; + memacc<='0'; + resacc<='0'; + pgpErr<='0'; + injacc<='1'; + delacc<='0'; + delrstacc<='0'; + when "1001" => -- increment delay for incoming serial data + pgpErr<='0'; + memacc<='0'; + resacc<='0'; + injacc<='0'; + rescount<='0'; + delacc<='1'; + delrstacc<='0'; + when "1010" => -- reset delay for incoming serial data + pgpErr<='0'; + memacc<='0'; + resacc<='0'; + injacc<='0'; + rescount<='0'; + delacc<='0'; + delrstacc<='1'; + when others => + pgpErr<='1'; + memacc<='0'; + resacc<='0'; + injacc<='0'; + rescount<='0'; + delacc<='0'; + delrstacc<='0'; + end case; + when others => + end case; + when '0' => -- READ (both running and stopped) + resacc<='0'; + injacc<='0'; + rescount<='0'; + delacc<='0'; + delrstacc<='0'; + case addrPgp is + when "0000" => -- number of words MSB + memacc<='0'; + pgpErr<='0'; + dataout<=nwords(63 downto 32); + when "0001" => -- number of words LSB + memacc<='0'; + pgpErr<='0'; + dataout<=nwords(31 downto 0); + when "0010" => -- number of errors MSB + memacc<='0'; + pgpErr<='0'; + dataout<=nerr(63 downto 32); + when "0011" => -- number of errors LSB + memacc<='0'; + pgpErr<='0'; + dataout<=nerr(31 downto 0); + when "0100" => -- number of loaded words + memacc<='0'; + pgpErr<='0'; + dataout<="0000000000000000000000" & unsigned(nloaded)+1; + when "0101" => -- last loaded word + if (nloaded="1111111111") then + pgpErr<='1'; + memacc<='0'; + dataout<=x"ffffffff"; + else + pgpErr<='0'; + memacc<='1'; + end if; + when "0110" => -- empty and full flags + memacc<='0'; + pgpErr<='0'; + dataout<=x"0000000" &'0'& going & full & empty; + when others => + memacc<='0'; + pgpErr<='1'; + dataout<=x"ffffffff"; + end case; + when others => + end case; + else + ena<='0'; + end if; + pgpEnaOld<=pgpEnable; + enaold<=ena; + oldgoing<=going; + delayreset<=delrstena or rst; + end if; + + end process; + + process(serclk,rst) -- serializer + begin + if (rst='1') then + oldld<='0'; + pointer<="0000000000"; + elsif (serclk'event and serclk='1') then + if (going='1') then + if (ld='0' and oldld='1') then + if pointer=nloaded then + pointer<=header; + else + pointer<=unsigned(pointer)+1; + end if; + end if; + elsif (going='0' and oldgoing='1') then + pointer<="0000000000" ; + end if; + if (injacc='1' and oldinjacc='0') then + injena<='1'; + else + injena<='0'; + end if; + oldinjacc<=injacc; + oldld<=ld; + end if; + end process; + + process(deserclk,rst) -- deserializer + begin + if (rst='1') then + olddld<='0'; + nerrce<='0'; + oldoverflownerr<='0'; + xorword<=x"00000000"; + xorword2<=x"00000000"; + xorbit<='0'; + elsif (deserclk'event and deserclk='1') then + if (olddld='1') then + xorword2<=dout2(31 downto 0); + xorword<= deserdata ; +-- xorword<=x"12345678"; + else + xorword(31 downto 1) <= xorword(30 downto 0); + xorword(0)<='0'; + xorword2(31 downto 1) <= xorword2(30 downto 0); + xorword2(0)<='0'; + end if; + xorbit<=xorword(31) xor xorword2(31); + nerrce<=xorbit; + if(overflownerr='1' and oldoverflownerr='0')then + carrynerr<='1'; + else + carrynerr<='0'; + end if; + carrynwords<=overflownwords and dld; + olddld<=dld; + oldoverflownerr<=overflownerr; + end if; + end process; + +the_mem : pattern_blk_mem + port map ( + clka => clk, + dina => dataFromPgp, + addra => nloaded, + ena => memena, + wea => vectorize(pgpRW), + douta => douta, + clkb => serclk, + dinb => (others=>'0'), + addrb => pointer, + enb => ld, + web => vectorize('0'), + doutb => serdata); +-- the_mem : pattern_blk_mem_62 +-- PORT MAP ( +-- clka => clk, +-- ena => memena, +-- wea => vectorize(pgpRW), +-- addra => nloaded, +-- dina => dataFromPgp, +-- clkb => serclk, +-- enb => ld, +-- addrb => pointer, +-- doutb => serdata +-- ); +serializer : ser + port map ( + clk => serclk, + ld => ld, + go => going, + inj => injena, + rst => resena, + d_in => serdata, + d_out => dataToFEs ); + +valstore : iblfifo -- stores the values to be checked + port map ( + din => din, + rd_clk => deserclk, + rd_en => dld, + rst => resena, + wr_clk => serclk, + wr_en => oldld, + dout => dout2, + empty => empty, + full => full); +deserializer: deser + port map ( + clk => deserclk, + rst => resena, + go => going, + d_in => dataFE, + d_out => deserdata, + ld => dld); +nerrlow : counter30 + port map ( + clk => deserclk, + ce => nerrce, + aclr => rescountena, + q_thresh0 => overflownerr, + q => nerr(29 downto 0)); +nerrhigh : counter30 + port map ( + clk => deserclk, + ce => carrynerr, + aclr => rescountena, + q_thresh0 => open, + q => nerr(59 downto 30)); + +nerr(63 downto 60)<="0000"; + +nwordslow : counter30 + port map ( + clk => deserclk, + ce => olddld, + aclr => rescountena, + q_thresh0 => overflownwords, + q => nwords(29 downto 0)); +nwordshigh : counter30 + port map ( + clk => deserclk, + ce => carrynwords, + aclr => rescountena, + q_thresh0 => open, + q => nwords(59 downto 30)); + +nwords(63 downto 60)<="0000"; + +delayline : IDELAY + generic map ( + IOBDELAY_TYPE => "VARIABLE", -- Set to DEFAULT for -- Zero Hold Time Mode + IOBDELAY_VALUE => 0 -- (0 to 63) + ) + port map ( + O => dataFromFEd, + I => dataFromFE, + C => clk, + CE => delena, + INC => '1', + RST => delayreset + ); + + + +-- cdata(0)<=dld; +-- cdata(1)<=olddld; +-- cdata(2)<=overflownerr; +-- cdata(3)<=carrynerr; +-- cdata(4)<=nerrce; +-- cdata(5)<=nerr(30); +-- cdata(6)<=nerr(31); +-- cdata(7)<=nerr(0); +-- cdata(8)<=nerr(1); +-- cdata(3)<=olddld; +-- cdata(4)<=docount; +-- cdata(5)<=datafe; +-- cdata(6)<=xorword(31); +-- cdata(7)<=xorword2(31); +-- cdata(8)<=loopback; +-- cdata(9)<=dataFromFE; +-- cdata(31 downto 9) <=(others=>'0'); +-- ctrig(0)<=overflownerr; +-- chipscope : ila +-- port map ( +-- CONTROL => ccontrol, +-- CLK => deserclk, +-- DATA => cdata, +-- TRIG0 => ctrig); +-- chipscopeicon : icon +-- port map ( +-- CONTROL0 => ccontrol); + +end PATTERN_MEM; +-------------------------------------------------------------- diff --git a/rce/fw-hsio/projects/IBLcableTester/hdl/phaseshift.vhd b/rce/fw-hsio/projects/IBLcableTester/hdl/phaseshift.vhd new file mode 100644 index 00000000..e1c3e162 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/hdl/phaseshift.vhd @@ -0,0 +1,104 @@ +-------------------------------------------------------------------------------- +-- Copyright (c) 1995-2008 Xilinx, Inc. All rights reserved. +-------------------------------------------------------------------------------- +-- ____ ____ +-- / /\/ / +-- /___/ \ / Vendor: Xilinx +-- \ \ \/ Version : 10.1.03 +-- \ \ Application : xaw2vhdl +-- / / Filename : phaseshift.vhd +-- /___/ /\ Timestamp : 08/24/2009 10:21:32 +-- \ \ / \ +-- \___\/\___\ +-- +--Command: xaw2vhdl-st /a/sulky20/g.ee.u07/kocian/minilat/xilinx/IBL/xil_cores//phaseshift.xaw /a/sulky20/g.ee.u07/kocian/minilat/xilinx/IBL/xil_cores//phaseshift +--Design Name: phaseshift +--Device: xc4vfx60-10ff1152 +-- +-- Module phaseshift +-- Generated by Xilinx Architecture Wizard +-- Written for synthesis tool: Synplify + +library ieee; +use ieee.std_logic_1164.ALL; +use ieee.numeric_std.ALL; +library UNISIM; +use UNISIM.Vcomponents.ALL; + +entity phaseshift is + port ( CLKIN_IN : in std_logic; + DADDR_IN : in std_logic_vector (6 downto 0); + DCLK_IN : in std_logic; + DEN_IN : in std_logic; + DI_IN : in std_logic_vector (15 downto 0); + DWE_IN : in std_logic; + RST_IN : in std_logic; + CLK0_OUT : out std_logic; + CLKFX_OUT : out std_logic; + CLK2X_OUT : out std_logic; + DRDY_OUT : out std_logic; + LOCKED_OUT : out std_logic); +end phaseshift; + +architecture BEHAVIORAL of phaseshift is + signal CLKFB_IN : std_logic; + signal CLK0_BUF : std_logic; + signal CLKFX_BUF : std_logic; + signal CLK2X_BUF : std_logic; +begin + CLK0_OUT <= CLKFB_IN; + CLK0_BUFG_INST : BUFG + port map (I=>CLK0_BUF, + O=>CLKFB_IN); + CLKFX_BUFG_INST : BUFG + port map (I=>CLKFX_BUF, + O=>CLKFX_OUT); + CLK2X_BUFG_INST : BUFG + port map (I=>CLK2X_BUF, + O=>CLK2X_OUT); + + DCM_ADV_INST : DCM_ADV + generic map( CLK_FEEDBACK => "1X", + CLKDV_DIVIDE => 2.0, + CLKFX_DIVIDE => 2, + CLKFX_MULTIPLY => 2, + CLKIN_DIVIDE_BY_2 => FALSE, + CLKIN_PERIOD => 12.8, + CLKOUT_PHASE_SHIFT => "DIRECT", + DCM_AUTOCALIBRATION => TRUE, + DCM_PERFORMANCE_MODE => "MAX_SPEED", + DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS", + DFS_FREQUENCY_MODE => "LOW", + DLL_FREQUENCY_MODE => "LOW", + DUTY_CYCLE_CORRECTION => TRUE, + FACTORY_JF => x"F0F0", + PHASE_SHIFT => 0, + STARTUP_WAIT => FALSE) + port map (CLKFB=>CLKFB_IN, + CLKIN=>CLKIN_IN, + DADDR(6 downto 0)=>DADDR_IN(6 downto 0), + DCLK=>DCLK_IN, + DEN=>DEN_IN, + DI(15 downto 0)=>DI_IN(15 downto 0), + DWE=>DWE_IN, + PSCLK=>'0', + PSEN=>'0', + PSINCDEC=>'0', + RST=>RST_IN, + CLKDV=>open, + CLKFX=>CLKFX_BUF, + CLKFX180=>open, + CLK0=>CLK0_BUF, + CLK2X=>CLK2X_BUF, + CLK2X180=>open, + CLK90=>open, + CLK180=>open, + CLK270=>open, + DO=>open, + DRDY=>DRDY_OUT, + LOCKED=>LOCKED_OUT, + PSDONE=>open); + +end BEHAVIORAL; + + diff --git a/rce/fw-hsio/projects/IBLcableTester/hdl/ser.vhd b/rce/fw-hsio/projects/IBLcableTester/hdl/ser.vhd new file mode 100644 index 00000000..8904613c --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/hdl/ser.vhd @@ -0,0 +1,74 @@ +-------------------------------------------------------------- +-- Serializer for High Speed I/O board (ATLAS Pixel teststand) +-- Martin Kocian 01/2009 +-------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use work.all; + +-------------------------------------------------------------- + +entity ser is + +port( clk: in std_logic; + ld: out std_logic; + go: in std_logic; + inj : in std_logic; + rst: in std_logic; + d_in: in std_logic_vector(31 downto 0); + d_out: out std_logic +); +end ser; + +-------------------------------------------------------------- + +architecture SER of ser is + +signal reg : std_logic_vector(31 downto 0); +signal going: std_logic; +signal counter: std_logic_vector(4 downto 0); + +begin + + + process(rst, clk) + + begin + if(rst='1') then + reg<=x"00000000"; + d_out<='0'; + going<='0'; + ld<='0'; + elsif (clk'event and clk='1') then + if (going='0')then + if(go='1')then + going<='1'; + else + counter<="00010"; + end if; + elsif (go='0' and counter="00010") then + going<='0'; -- Empty flag is asserted instantly so go for + else + if (counter="00000") then + reg<=d_in; + else + reg(31 downto 1)<=reg(30 downto 0); + reg(0)<='0'; + end if; + if(counter="00010") then -- it takes 2 cycles to + ld<='1'; -- get data from the FIFO; + elsif(counter="00001") then + ld<='0'; -- Request is only 1 cycle long. + end if; + counter<=unsigned(counter)-1; + end if; + d_out<=reg(31) xor inj; + end if; + + end process; + +end SER; + +-------------------------------------------------------------- diff --git a/rce/fw-hsio/projects/IBLcableTester/hdl/serbiphase.vhd b/rce/fw-hsio/projects/IBLcableTester/hdl/serbiphase.vhd new file mode 100644 index 00000000..de05b9c9 --- /dev/null +++ b/rce/fw-hsio/projects/IBLcableTester/hdl/serbiphase.vhd @@ -0,0 +1,86 @@ +-------------------------------------------------------------- +-- Serializer for High Speed I/O board (ATLAS Pixel teststand) +-- Martin Kocian 01/2009 +-------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use work.all; + +-------------------------------------------------------------- + +entity serbiphase is + +port( clk: in std_logic; + ld: out std_logic; + go: in std_logic; + isgoing: out std_logic; -- debugging + inj : in std_logic; + rst: in std_logic; + d_in: in std_logic_vector(31 downto 0); + d_out: out std_logic +); +end serbiphase; + +-------------------------------------------------------------- + +architecture SERBIPHASE of serbiphase is + +signal reg : std_logic_vector(31 downto 0); +signal gogo: std_logic; +signal clk40: std_logic; + +signal ldout : std_logic; + +begin + + ld<=ldout ; + isgoing<=gogo; -- debugging + + process(clk) + begin + if (clk'event and clk='1') then + clk40<=not clk40; + end if; + end process; + + process(rst, clk40) + + variable counter: std_logic_vector(3 downto 0); + variable going: std_logic; + begin + if(rst='1') then + reg<=x"00000000"; + d_out<='0'; + going:='0'; + ldout<='0'; + elsif (clk40'event and clk40='1') then + gogo<=going; + if (going='0' and go='1')then + going:='1'; + counter:="0010"; + elsif (go='0' and counter="0010") then + going:='0'; -- Empty flag is asserted instantly so go for + end if; -- another 32 bits to process the last word. + if (counter="0000" and going='1') then + reg<=d_in; + counter:="1111"; + else + reg(31 downto 2)<=reg(29 downto 0); + reg(1 downto 0)<="00"; + if(counter="0010" and going='1') then -- it takes 2 cycles to + ldout<='1'; -- get data from the FIFO; + elsif(counter="0001" and going='1') then + ldout<='0'; -- Request is only 1 cycle long. + end if; + counter:=unsigned(counter)-1; + end if; + d_out<=reg(31) xor reg(30) xor inj; + end if; + + end process; + +end SERBIPHASE; + +-------------------------------------------------------------- diff --git a/rce/fw-hsio/system.mk b/rce/fw-hsio/system.mk new file mode 100644 index 00000000..bf476d3e --- /dev/null +++ b/rce/fw-hsio/system.mk @@ -0,0 +1,262 @@ + +# Top level directory +export PROJ_DIR = $(abspath $(PWD)) +export TOP_DIR = $(abspath $(PROJ_DIR)/../..) + +# Project Build Directory +export OUT_DIR = $(TOP_DIR)/build/$(PROJECT) + +# Location of synthesis options files +CONFIG_DIR = $(PROJ_DIR)/config + +# Images Directory +IMAGES_DIR = $(PROJ_DIR)/images + +# Project RTL Location +PRJ_RTL = $(PROJ_DIR)/hdl + +# UCF File (always in PRJ_RTL/PROJECT.ucf) +UCF_FILE = $(PRJ_RTL)/$(PROJECT).ucf + +# Get Project Version +PRJ_VERSION = $(shell grep MAKE_VERSION $(PROJ_DIR)/Version.vhd | cut -d ' ' -f 8 | cut -d'"' -f2) + +define ACTION_HEADER +@echo +@echo "=============================================================================" +@echo $(1) +@echo " Project = $(PROJECT)" +@echo " Out Dir = $(OUT_DIR)" +@echo " Version = $(PRJ_VERSION)" +@echo -e " Changed = $(foreach ARG,$?,$(ARG)\n )" +@echo "=============================================================================" +@echo +endef + +.PHONY : all +all: prom trce + +.PHONY : test +test: + @echo PROJECT: $(PROJECT) + @echo PROJ_DIR: $(PROJ_DIR) + @echo PRJ_VERSION $(PRJ_VERSION) + @echo TOP_DIR: $(TOP_DIR) + @echo OUT_DIR: $(OUT_DIR) + @echo CONFIG_DIR: $(CONFIG_DIR) + @echo XST_OPTIONS_FILE $(XST_OPTIONS_FILE) + @echo RAW_SOURCES_FILE $(RAW_SOURCES_FILE) + @echo OUT_SOURCES_FILE $(OUT_SOURCES_FILE) + @echo RTL_FILES: + @echo -e "$(foreach ARG,$(RTL_FILES), $(ARG)\n)" + +#### Build Location ######################################## +.PHONY : dir +dir: + +#### Check Source Files ################################### +#%.vhd : +# @test -d $*.vhd || echo "$*.vhd does not exist"; false; +# +#%.v : +# @test -d $*.v || echo "$*.v does not exist"; false; +# + +#### Coregen ############################################### +xco_to_build = $(addprefix $(TOP_DIR)/build/coregen/, $(patsubst %.xco, %, $(notdir $(1))))/$(notdir $(patsubst %.xco, $(2), $(1))) + +XCO_FILES = $(foreach dir, $(CORE_DIRS), $(wildcard $(dir)/*.xco)) +XCO_NGC_FILES = $(foreach xcof, $(XCO_FILES), $(call xco_to_build, $(xcof), %.ngc)) +XCO_CGP_FILES = $(foreach xcof, $(XCO_FILES), $(call xco_to_build, $(xcof), %.xco)) +XCO_FILES_BUILD = $(foreach xcof, $(XCO_FILES), $(call xco_to_build, $(xcof), %.xco)) + +.SECONDARY: $(XCO_NGC_FILES) $(XCO_FILES_BUILD) $(XCO_CGP_FILES) +$(XCO_FILES_BUILD): $(XCO_FILES) + @test -d $(TOP_DIR)/build/ || { \ + echo ""; \ + echo "Build directory missing!"; \ + echo "You must create a build directory at the top level."; \ + echo ""; \ + echo "This directory can either be a normal directory:"; \ + echo " mkdir $(TOP_DIR)/build"; \ + echo ""; \ + echo "Or by creating a symbolic link to a directory on another disk:"; \ + echo " ln -s /tmp/build $(TOP_DIR)/build"; \ + echo ""; false; } + test -d $(dir $@) || mkdir -p $(dir $@) + cp $(foreach dir, $(CORE_DIRS), $(wildcard $(dir)/$(notdir $@))) $@ + +%.cgp: %.xco + ( \ + echo 'SET addpads = False'; \ + echo 'SET asysymbol = False'; \ + echo 'SET busformat = BusFormatAngleBracketNotRipped'; \ + echo 'SET createndf = False'; \ + echo 'SET designentry = VHDL'; \ + echo 'SET device = xc4vfx60'; \ + echo 'SET devicefamily = virtex4'; \ + echo 'SET flowvendor = Other'; \ + echo 'SET formalverification = False'; \ + echo 'SET foundationsym = False'; \ + echo 'SET implementationfiletype = Ngc'; \ + echo 'SET package = ff1152'; \ + echo 'SET removerpms = False'; \ + echo 'SET simulationfiles = Behavioral'; \ + echo 'SET speedgrade = -11'; \ + echo 'SET verilogsim = False'; \ + echo 'SET vhdlsim = True'; \ + ) > $@ + +%.ngc: %.xco %.cgp + $(call ACTION_HEADER,"Regenerating $(notdir $<)") + cd $(dir $<) && \ + coregen \ + -b $(notdir $<) \ + -p $(patsubst %.xco, %.cgp, $(notdir $<)) + +ip_cores: $(XCO_NGC_FILES) + +#### Synthesis ############################################# +XST_OPTIONS_FILE = $(CONFIG_DIR)/xst_options.txt +RAW_SOURCES_FILE = $(CONFIG_DIR)/sources.txt +OUT_SOURCES_FILE = $(OUT_DIR)/sources.txt + +RTL_FILES = $(abspath $(subst _PROJ_DIR_,$(PROJ_DIR),$(shell grep -o _PROJ_DIR_\.\*.[vhd,v] $(RAW_SOURCES_FILE)))) + +$(OUT_DIR)/$(PROJECT).ngc: $(RTL_FILES) $(XST_OPTIONS_FILE) $(RAW_SOURCES_FILE) $(XCO_NGC_FILES) + $(call ACTION_HEADER,"Synthesize") + @test -d $(TOP_DIR)/build/ || { \ + echo ""; \ + echo "Build directory missing!"; \ + echo "You must create a build directory at the top level."; \ + echo ""; \ + echo "This directory can either be a normal directory:"; \ + echo " mkdir $(TOP_DIR)/build"; \ + echo ""; \ + echo "Or by creating a symbolic link to a directory on another disk:"; \ + echo " ln -s /tmp/build $(TOP_DIR)/build"; \ + echo ""; false; } + @test -d $(OUT_DIR) || mkdir $(OUT_DIR) + @test -d $(OUT_DIR)/tmp || mkdir $(OUT_DIR)/tmp + @test -d $(OUT_DIR)/xst/ || mkdir $(OUT_DIR)/xst/ + @test -d $(OUT_DIR)/xst/tmp || mkdir $(OUT_DIR)/xst/tmp + @rm -f $(OUT_SOURCES_FILE) + @sed 's|_PROJ_DIR_|$(PROJ_DIR)|' $(RAW_SOURCES_FILE) > $(OUT_SOURCES_FILE) + @cd $(OUT_DIR); xst -ifn $(XST_OPTIONS_FILE) -ofn $*.srp + + +#### Translate ############################################# +TRANSLATE_OPTIONS_FILE = $(CONFIG_DIR)/ngdbuild_options.txt +####TRANSLATE_INPUT = .ngc #Override with .ngo to use ChipScope core inserter output +TRANSLATE_INPUT = .ngc #Override with .ngo to use ChipScope core inserter output +ifneq ($(BOOT_ELF),) + dep_bmm := $(PROJ_DIR)/boot/$(PROJECT).bmm + opt_bmm := -bm $(PROJ_DIR)/boot/$(PROJECT).bmm +endif +%.ngd: %$(TRANSLATE_INPUT) $(UCF_FILE) $(TRANSLATE_OPTIONS_FILE) $(dep_bmm) $(XCO_NGC_FILES) + $(call ACTION_HEADER,"Translate") + @cd $(OUT_DIR); ngdbuild \ + -sd $(OUT_DIR) \ + -f $(TRANSLATE_OPTIONS_FILE) \ + $(opt_bmm) \ + -dd $(OUT_DIR)/bld \ + -uc $(UCF_FILE) \ + $(foreach ARG,$(CORE_DIRS),-sd $(abspath $(PROJ_DIR)/$(ARG))) \ + $(foreach ARG,$(XCO_FILES_BUILD),-sd $(abspath $(dir $(ARG)))) \ + $*$(TRANSLATE_INPUT) \ + $*.ngd + + + +#### Map ################################################### +MAP_OPTIONS_FILE = $(CONFIG_DIR)/map_options.txt +%_map.ncd %.pcf: %.ngd $(MAP_OPTIONS_FILE) + $(call ACTION_HEADER,"Map") + @cd $(OUT_DIR); map \ + -w \ + -f $(MAP_OPTIONS_FILE) \ + -o $*_map.ncd \ + $*.ngd $*.pcf + +#### PAR ################################################### +PAR_OPTIONS_FILE = $(CONFIG_DIR)/par_options.txt +%.ncd: %_map.ncd %.pcf $(PAR_OPTIONS_FILE) + $(call ACTION_HEADER,"Place and Route") + @cd $(OUT_DIR); par \ + -w \ + -f $(PAR_OPTIONS_FILE) \ + $*_map.ncd \ + $*.ncd $*.pcf + +#### Trace ################################################# +TRCE_OPTIONS_FILE = $(CONFIG_DIR)/trce_options.txt +%.twr: %.ncd %.pcf $(TRCE_OPTIONS_FILE) + $(call ACTION_HEADER,"Trace") + @cd $(OUT_DIR); trce \ + -f $(TRCE_OPTIONS_FILE) \ + -o $*.twr \ + $*.ncd $*.pcf + +#### Bit ################################################### +BIT_OPTIONS_FILE = $(CONFIG_DIR)/bitgen_options.txt +ifneq ($(BOOT_ELF),) + dep_elf := $(PROJ_DIR)/boot/$(BOOT_ELF) + opt_elf := -bd $(PROJ_DIR)/boot/$(BOOT_ELF) +endif +%.bit: %.ncd $(BIT_OPTIONS_FILE) $(PROJ_DIR)/Makefile $(dep_elf) + $(call ACTION_HEADER,"Bitgen") + @cd $(OUT_DIR); bitgen \ + $(opt_elf) \ + -f $(BIT_OPTIONS_FILE) $(opt_elf) \ + $*.ncd + +$(IMAGES_DIR)/$(PROJECT)_$(PRJ_VERSION).bit : $(OUT_DIR)/$(PROJECT).bit + @cp $< $@ + @echo "" + @echo "Bit file copied to $@" + @echo "Don't forget to 'svn commit' when the image is stable!" + + +#### PROM ################################################## +PROM_OPTIONS_FILE = $(CONFIG_DIR)/promgen_options.txt +%.mcs: %.bit $(PROM_OPTIONS_FILE) + $(call ACTION_HEADER,"PROM Generate") + @cd $(OUT_DIR); promgen \ + -f $(PROM_OPTIONS_FILE) \ + -u 0 $*.bit + +$(IMAGES_DIR)/$(PROJECT)_$(PRJ_VERSION).mcs : $(OUT_DIR)/$(PROJECT).mcs + @cp $< $@ + @echo "" + @echo "Prom file copied to $@" + @echo "Don't forget to 'svn commit' when the image is stable!" + +#### Makefile Targets ###################################### +.PHONY : syn +syn : $(OUT_DIR)/$(PROJECT).ngc + + +.PHONY : translate +translate : $(OUT_DIR)/$(PROJECT).ngd + +.PHONY : map +map : $(OUT_DIR)/$(PROJECT)_map.ncd + +.PHONY : par +par : $(OUT_DIR)/$(PROJECT).ncd + +.PHONY : trce +trce : $(OUT_DIR)/$(PROJECT).twr + +.PHONY : bit +bit : $(IMAGES_DIR)/$(PROJECT)_$(PRJ_VERSION).bit + +.PHONY : prom +prom : bit $(IMAGES_DIR)/$(PROJECT)_$(PRJ_VERSION).mcs + +#### Clean ################################################# +.PHONY : clean +clean: + rm -rf $(OUT_DIR) + + diff --git a/rce/make/hw/Makefile.package.template b/rce/make/hw/Makefile.package.template new file mode 100644 index 00000000..a05ce51b --- /dev/null +++ b/rce/make/hw/Makefile.package.template @@ -0,0 +1,20 @@ +# Package level makefile +# ---------------------- +%.mk:; + +# Checks +# ------ +# Check release location variables +ifeq ($(RELEASE_DIR),) +export RELEASE_DIR := $(PWD)/../.. +endif + +include $(RELEASE_DIR)/make/share/setup.mk +include ../flags.mk + +ifndef PREMAKE_DONE +include $(RELEASE_DIR)/make/share/premake.mk +else +include constituents.mk +include $(RELEASE_DIR)/make/hw/package.mk +endif diff --git a/rce/make/hw/constituents.mk.template b/rce/make/hw/constituents.mk.template new file mode 100644 index 00000000..d7cba602 --- /dev/null +++ b/rce/make/hw/constituents.mk.template @@ -0,0 +1,29 @@ +# Site location with binary cores +# bcores := /afs/slac/g/npa/package/xilinx/bcores/rs_v6 + +# File which specifies synplify options +# synoptions := hdl/syntemplate_options + +# Specify design name, constraints, sdc, bmm and elf files +# designs := lcls +# ucf_lcls := hdl/lcls.ucf +# sdc_lcls := hdl/lcls.sdc +# bmm_lcls := hdl/lcls.bmm +# elf_lcls := $(bcores)/cem.elf + +# Specify list of source files +# topsynpl_lcls := hdl/lcls.src + + +# Simulation code source directory +# scores := $(RELEASE_DIR)/rcehw/lcls + +# Simulation settings +# simoptions := sim/synopsys.setup + +# Simulation designs +# simulations := temac_sim + +# Simulation source files (top level and wrappers) +# topwrapp_temac_sim := sim/temac_sim.src +# wrappers_temac_sim := sim/temac_export.src sim/temac_import.src diff --git a/rce/make/hw/flags.mk b/rce/make/hw/flags.mk new file mode 100644 index 00000000..14fa790d --- /dev/null +++ b/rce/make/hw/flags.mk @@ -0,0 +1,44 @@ +# Architecture flags +# ------------------ +arch_tgts := xc4vfx12 xc4vfx20 xc4vfx60 +arch_opts := + +define arch_opt_template +arch_tgts += $$(addsuffix -$(1),$$(arch_tgts)) +endef +$(foreach opt,$(arch_opts),$(eval $(call arch_opt_template,$(opt)))) + +ifneq ($(findstring xc4vfx12,$(tgt_arch)),) +PLATFORM := xc4vfx12-ff668-10 +endif + +ifneq ($(findstring xc4vfx20,$(tgt_arch)),) +PLATFORM := xc4vfx20-ff672-10 +endif + +ifneq ($(findstring xc4vfx60,$(tgt_arch)),) +PLATFORM := xc4vfx60-ff1152-11 +endif + +BITGENOPTS := -g DebugBitstream:No -g Binary:no -g CRC:Enable \ +-g ConfigRate:26 -g CclkPin:PullUp -g M0Pin:PullUp -g M1Pin:PullUp \ +-g M2Pin:PullUp -g ProgPin:PullUp -g DonePin:PullUp -g InitPin:Pullup \ +-g CsPin:Pullup -g DinPin:Pullup -g BusyPin:Pullup -g RdWrPin:Pullup \ +-g TckPin:PullUp -g TdiPin:PullUp -g TdoPin:PullUp -g TmsPin:PullUp \ +-g UnusedPin:PullDown -g UserID:0xDEADBEEF -g DCIUpdateMode:AsRequired \ +-g StartUpClk:CClk -g DONE_cycle:4 -g GTS_cycle:5 -g GWE_cycle:6 \ +-g LCK_cycle:NoWait -g Match_cycle:Auto -g Security:None -g Persist:No \ +-g DonePipe:No -g DriveDone:No -g Encrypt:No + +TIME := /usr/bin/time -f "(time %E: usr %U sys %S CPU %P i/o %I/%O)" +ACEGEN := $(TIME) xmd -tcl genace.tcl -jprog +BITGEN := $(TIME) bitgen -intstyle silent -d -w $(BITGENOPTS) +TWRGEN := $(TIME) trce -intstyle silent -v 50 -l 500 -u 100 +PARGEN := $(TIME) par -intstyle silent -w -ol high -xe n -t 4 +MAPGEN := $(TIME) map -intstyle silent -cm speed -ol high -p $(PLATFORM) -pr b -c 100 +NGDGEN := $(TIME) ngdbuild -intstyle silent -dd ngo -p $(PLATFORM) +XSTGEN := $(TIME) xst -intstyle silent +OPTGEN := $(RELEASE_DIR)/make/hw/optgen.py +PRJGEN := $(RELEASE_DIR)/make/hw/prjgen.py +TCLGEN := $(RELEASE_DIR)/make/hw/tclgen.py +SYNPLF := $(TIME) synplify_premier_dp -batch diff --git a/rce/make/hw/flags.mk.template b/rce/make/hw/flags.mk.template new file mode 100644 index 00000000..5ac3c650 --- /dev/null +++ b/rce/make/hw/flags.mk.template @@ -0,0 +1 @@ +include $(RELEASE_DIR)/make/hw/flags.mk diff --git a/rce/make/hw/optgen.py b/rce/make/hw/optgen.py new file mode 100755 index 00000000..55ab2257 --- /dev/null +++ b/rce/make/hw/optgen.py @@ -0,0 +1,23 @@ +#!/usr/bin/python + +import sys + +if __name__ == '__main__': + template = sys.argv[1] + projname = sys.argv[2] + useiobuf = sys.argv[3] + platform = sys.argv[4] + options = sys.argv[5] + + ftemplate = open(template, 'r') + foptions = open(options, 'w') + + lines = ftemplate.readlines() + for line in lines: + line = line.replace('PROJNAME', projname) + line = line.replace('USEIOBUF', useiobuf) + line = line.replace('PLATFORM', platform) + foptions.write(line) + + ftemplate.close() + foptions.close() diff --git a/rce/make/hw/package.mk b/rce/make/hw/package.mk new file mode 100644 index 00000000..ea434751 --- /dev/null +++ b/rce/make/hw/package.mk @@ -0,0 +1,296 @@ +# Package level makefile +# ---------------------- +Makefile:; + +# Symbols +# ------- +SHELL := /bin/sh +RM := rm -f +MV := mv -f + +pwd := $(shell pwd) +cwd := $(call reverse,$(subst /, ,$(pwd))) +pkg_name := $(word 1,$(cwd)) +prj_name := $(word 2,$(cwd)) + +# Procedures +# ---------- +pkgdir := $(RELEASE_DIR)/build/$(prj_name)/$(pkg_name)/$(tgt_arch) +blddir := $(pkgdir)/xil +xstdir := $(pkgdir)/xst +syndir := $(pkgdir)/syn +simdir := $(pkgdir)/sim +dirs := $(pkgdir) $(blddir) $(xstdir) $(syndir) $(simdir) + +ifneq ($(bcores),) +sdpaths := $(addprefix -sd , $(bcores)) +endif + +ifneq ($(guidefile),) + GUIDEFLAGS := -gf $(guidefile) +endif + +getstms = $(strip $(basename $(notdir $(1)))) +edfs = $(addsuffix .edf, $(addprefix $(1), $(call getstms,$(2)))) +ngcs = $(addsuffix .ngc, $(addprefix $(1), $(call getstms,$(2)))) +opts = $(addsuffix .opt, $(addprefix $(1), $(call getstms,$(2)))) +prjs = $(addsuffix .prj, $(addprefix $(1), $(call getstms,$(2)))) +done = $(addsuffix .done,$(addprefix $(1), $(call getstms,$(2)))) +getsrcfiles = $(shell srcs=`cut -f 3 -d ' ' $(1)`; echo $$srcs;) + +define wrapper_template + stem_$(1) := $$(call getstms,$(1)) + srcfiles_$$(stem_$(1)) := $$(addprefix $$(pwd)/,$$(call getsrcfiles,$(1))) + useiobuf_$$(stem_$(1)) := NO + src_$$(stem_$(1)) := $(1) + lso_$$(stem_$(1)) := $$(wildcard $$(patsubst %.src,%.lso,$(1))) + +$$(xstdir)/$$(stem_$(1)).ngc: $$(xstdir)/$$(stem_$(1)).opt $$(xstdir)/$$(stem_$(1)).prj $$(srcfiles_$$(stem_$(1))) + +$$(xstdir)/$$(stem_$(1)).prj: $$(src_$$(stem_$(1))) $$(lso_$$(stem_$(1))) +$$(xstdir)/$$(stem_$(1)).opt: $$(xstoptions) +endef + + +define synplify_template +# stem_$(1) := $$(call getstms,$(1)) +# srcfiles_$$(stem_$(1)) := $$(addprefix $$(pwd)/,$$(call getsrcfiles,$(1))) +# src_$$(stem_$(1)) := $(1) + src_$(1) := $$(pwd)/$$(syn_$(1)) + sdc_$(1) := $$(pwd)/$$(sdc_$(1)) + ucf_$(1) := $$(pwd)/$$(ucf_$(1)) + disiobuf_$(1) := 1 + +$$(syndir)/$(1).edf: $$(syndir)/$(1).prj $$(sdc_$(1)) $$(src_$(1)) $$(ucf_$(1)) + +$$(syndir)/$(1).prj: $$(synoptions) $$(src_$(1)) +endef + +define design_template + ace_$(1) := $$(pkgdir)/$(1)_ace.ace + bit_$(1) := $$(pkgdir)/$(1).bit + twr_$(1) := $$(pkgdir)/$(1).twr + ncd_$(1) := $$(pkgdir)/$(1).ncd + map_$(1) := $$(pkgdir)/$(1)_map.ncd + ngd_$(1) := $$(pkgdir)/$(1).ngd + ngcs_$(1) := $$(call ngcs,$$(xstdir)/,$$(wrappers_$(1)) $$(topwrapp_$(1))) + opts_$(1) := $$(call opts,$$(xstdir)/,$$(wrappers_$(1)) $$(topwrapp_$(1))) + prjs_$(1) := $$(call prjs,$$(xstdir)/,$$(wrappers_$(1)) $$(topwrapp_$(1))) + edfs_$(1) := $$(call edfs,$$(syndir)/,$$(synplifs_$(1)) $$(syn_$(1))) + tcls_$(1) := $$(call prjs,$$(syndir)/,$$(synplifs_$(1)) $$(syn_$(1))) + acefiles += $$(ace_$(1)) + bitfiles += $$(bit_$(1)) + twrfiles += $$(twr_$(1)) + ncdfiles += $$(ncd_$(1)) + mapfiles += $$(map_$(1)) + ngdfiles += $$(ngd_$(1)) + edffiles += $$(edfs_$(1)) $$(ngcs_$(1)) + prjfiles += $$(tcls_$(1)) $$(prjs_$(1)) $$(opts_$(1)) +ifneq ($$(bmm_$(1)),) + ubmm_$(1) := $$(blddir)/$(1).bmm + obmm_$(1) := -bm $$(notdir $$(bmm_$(1))) +$$(ubmm_$(1)): $$(bmm_$(1)) +endif +ifneq ($$(elf_$(1)),) + oelf_$(1) := -bd $$(elf_$(1)) +endif +ifneq ($$(syn_$(1)),) + edn_$(1) := $$(word $$(words $$(edfs_$(1))),$$(edfs_$(1))) +else + edn_$(1) := $$(word $$(words $$(ngcs_$(1))),$$(ngcs_$(1))) +endif + useiobuf_$(1) := YES + disiobuf_$(1) := 0 + +$$(ace_$(1)): $$(bit_$(1)) + +$$(bit_$(1)): $$(ncd_$(1)) $$(elf_$(1)) + +$$(twr_$(1)): $$(ncd_$(1)) + +$$(ncd_$(1)): $$(map_$(1)) + +$$(map_$(1)): $$(ngd_$(1)) + +$$(ngd_$(1)): $$(edfs_$(1)) $$(ngcs_$(1)) $$(ubmm_$(1)) +endef + +$(foreach dsg,$(designs),$(foreach wrapper,$(wrappers_$(dsg)) $(topwrapp_$(dsg)),$(eval $(call wrapper_template,$(wrapper))))) +#$(foreach dsg,$(designs),$(foreach syn,$(synplifs_$(dsg)) $(topsynpl_$(dsg)),$(eval $(call synplify_template,$(syn))))) +#cpo and perazzo eliminated loop over synplify stuff to simplify the makefile system. +$(foreach dsg,$(designs),$(eval $(call synplify_template,$(dsg)))) + +$(foreach dsg,$(designs),$(eval $(call design_template,$(dsg)))) + +define simwrapper_template + stem_$(1) := $$(call getstms,$(1)) + srcfiles_$$(stem_$(1)) := $$(addprefix $$(pwd)/,$$(call getsrcfiles,$(1))) + src_$$(stem_$(1)) := $(1) + lso_$$(stem_$(1)) := $$(wildcard $$(patsubst %.src,%.lso,$(1))) + +$$(simdir)/$$(stem_$(1)).done: $$(simdir)/$$(stem_$(1)).prj $$(srcfiles_$$(stem_$(1))) + +$$(simdir)/$$(stem_$(1)).prj: $$(src_$$(stem_$(1))) $$(lso_$$(stem_$(1))) +endef + +define simtoplevel_template + stem_$(1) := $$(call getstms,$(1)) + srcfiles_$$(stem_$(1)) := $$(addprefix $$(pwd)/,$$(call getsrcfiles,$(1))) + src_$$(stem_$(1)) := $(1) + lso_$$(stem_$(1)) := $$(wildcard $$(patsubst %.src,%.lso,$(1))) + done_$$(stem_$(1)) := $$(call done,$$(simdir)/,$$(wrappers_$$(stem_$(1)))) + +$$(simdir)/$$(stem_$(1)).done: $$(simdir)/$$(stem_$(1)).prj $$(srcfiles_$$(stem_$(1))) $$(done_$$(stem_$(1))) + +$$(simdir)/$$(stem_$(1)).prj: $$(src_$$(stem_$(1))) $$(lso_$$(stem_$(1))) +endef + +define simulation_template + sim_$(1) := $$(pkgdir)/$(1).sim + done_$(1) := $$(call done,$$(simdir)/,$$(wrappers_$(1)) $$(topwrapp_$(1))) + simfiles += $$(sim_$(1)) + +$$(sim_$(1)): $$(simdir)/.synopsys_vss.setup $$(done_$(1)) +endef + +$(foreach sim,$(simulations),$(foreach wrapper,$(wrappers_$(sim)),$(eval $(call simwrapper_template,$(wrapper))))) +$(foreach sim,$(simulations),$(eval $(call simtoplevel_template,$(topwrapp_$(sim))))) +$(foreach sim,$(simulations),$(eval $(call simulation_template,$(sim)))) + +# Rules +# ----- +.SUFFIXES: # Kills all implicit rules + +# Kill rules to remake source files, there really isn't anyway to do +# this and this just adds time to make's execution and verbage to +# debug output. +%.vhd :; +%.v :; +%.src :; +%.lso :; +%.ucf :; + +rules := all ace bit twr ncd map ngd edf prj sim dir clean cleansim print + +.PHONY: $(rules) + +all: ace sim; +ace: $(acefiles); +bit: $(bitfiles); +twr: $(twrfiles); +ncd: $(ncdfiles); +map: $(mapfiles); +ngd: $(ngdfiles); +edf: $(edffiles); +prj: $(prjfiles); +sim: $(simfiles); +dir: $(dirs); + +print: + @echo "pkgdir = $(pkgdir)" + @echo "ace = $(acefiles)" + @echo "bit = $(bitfiles)" + @echo "ncd = $(ncdfiles)" + @echo "map = $(mapfiles)" + @echo "ngd = $(ngdfiles)" + @echo "edf = $(edffiles)" + @echo "prj = $(prjfiles)" + @echo "sim = $(simfiles)" + @echo "ucf = $(ucffile)" + + +clean: + @echo "[CL] Remove $(pkgdir)" + $(quiet)rm -rf $(pkgdir) + +cleansim: + @echo "[CL] Remove $(simdir)" + $(quiet)rm -rf $(simdir) + + +# Directory structure +$(dirs): + $(quiet)mkdir -p $@ + + +# Xilinx +$(blddir)/%.bmm: +# Unfortunately the bmm file is needed under blddir by bitgen (through +# data2mem) since its location cannot be specified as bitgen argument + @echo "[BM] Copy BMM file to build directory for design $*" + $(quiet)cp $(bmm_$*) $(blddir) + +$(pkgdir)/%.ngd: + @echo "[GD] Generate NGD file for design $*" + $(quiet)cd $(blddir) && \ + $(NGDGEN) $(sdpaths) $(obmm_$*) -uc $(syndir)/synplicity.ucf $(edn_$*) $*.ngd && \ + mv $*.ngd ../ + +$(pkgdir)/%_map.ncd: + @echo "[MP] Generate MAP file for design $*" + $(quiet)cd $(blddir) && \ + $(MAPGEN) $(GUIDEFLAGS) -o $*_map.ncd ../$*.ngd $*.pcf && mv $*_map.ncd ../ + +$(pkgdir)/%.ncd: + @echo "[PR] Place and route design $*" + $(quiet)cd $(blddir) \ + && $(PARGEN) $(GUIDEFLAGS) ../$*_map.ncd $*.ncd $*.pcf && mv $*.ncd ../ + +$(pkgdir)/%.twr: + @echo "[BT] Generate timing report for design $*" + $(quiet)cd $(blddir) && \ + $(TWRGEN) -xml $* ../$*.ncd -o $*.twr $*.pcf && mv $*.twr ../ + +$(pkgdir)/%.bit: + @echo "[BT] Generate BIT file for design $*" + $(quiet)cd $(blddir) && \ + $(BITGEN) $(oelf_$*) ../$*.ncd $*.bit && mv $*.bit ../ + +$(pkgdir)/%_ace.ace: + @echo "[AC] Generate ACE file for design $*" + $(quiet)cd $(blddir) && \ + $(ACEGEN) -hw ../$*.bit -ace $*_ace.ace && mv $*_ace.ace ../ + + +# Xilinx XST +$(xstdir)/%.prj: + @echo "[XP] Generate list of source files for $*" + $(quiet)$(PRJGEN) $(scores) $(pwd) $@ $(src_$*) $(lso_$*) + +$(xstdir)/%.opt: + @echo "[XO] Generate synthesis options file for $*" + $(quiet)$(OPTGEN) $(xstoptions) $* $(useiobuf_$*) $(PLATFORM) $@ + +$(xstdir)/%.ngc: + @echo "[XD] Compile NGC file for $*" + $(quiet)cd $(xstdir) && rm -rf $* && $(XSTGEN) -ifn $*.opt + + +# Synplify +$(syndir)/%.prj: + @echo "[SL] Generate list of soure files for $*" + $(quiet)$(TCLGEN) $(synoptions) $* $(disiobuf_$*) $(pwd) $(sdc_$*) $(src_$*) $(ucf_$*) $@ + +$(syndir)/%.edf: + @echo "[SD] Compile EDF file for $*" + $(quiet)cd $(syndir) && rm -rf $* && $(SYNPLF) $*.prj + + +# Synopsys +$(simdir)/%.prj: + @echo "[SP] Generate list of simulation soure files for $*" + $(quiet)$(PRJGEN) $(scores) $(pwd) $@ $(src_$*) $(lso_$*) + +$(simdir)/%.done: + @echo "[SC] Compile SIM file for $*" + $(quiet)cd $(simdir) && \ + vhdlan -nc $(call getsrcfiles,$(simdir)/$*.prj) && touch $*.done + +$(simdir)/.synopsys_vss.setup: $(simoptions) + @echo "[ST] Copy simulation options file $<" + $(quiet)cp $< $@ + +$(pkgdir)/%.sim: + @echo "[SE] Generate simulation executable $*" + $(quiet)cd $(simdir) && rm -rf $@.db.dir \ + && scs -nc -debug -time "ps" -time_res "1ps" $* -exe $@ diff --git a/rce/make/hw/prjgen.py b/rce/make/hw/prjgen.py new file mode 100755 index 00000000..542fea0a --- /dev/null +++ b/rce/make/hw/prjgen.py @@ -0,0 +1,64 @@ +#!/usr/bin/python + +import sys +import os +import glob + +if __name__ == '__main__': + xipcores = sys.argv[1] + usrcores = sys.argv[2] + prjfile = sys.argv[3] + srcfile = sys.argv[4] + + fprj = open(prjfile, 'w') + + if len(sys.argv) > 5: + lsofile = sys.argv[5] + flso = open(lsofile, 'r') + for library in flso.readlines(): + library = library.strip() + paos = glob.glob('%s/%s/data/*.pao' %(xipcores, library)) + for pao in paos: + fpao = open(pao, 'r') + for depline in fpao.readlines(): + tokens = depline.split() + if len(tokens) > 2 and tokens[0] == 'lib': + dep = tokens[1] + src = tokens[2] + if src == 'all': + vhdls = glob.glob('%s/%s/hdl/vhdl/*.vhd' %(xipcores, dep)) + verilogs = glob.glob('%s/%s/hdl/verilog/*.v' %(xipcores, dep)) + for vhdl in vhdls: + fprj.write('vhdl %s %s\n' %(dep, vhdl)) + for verilog in verilogs: + fprj.write('verilog %s %s\n' %(dep, verilog)) + else: + vhdl = '%s/%s/hdl/vhdl/%s.vhd' %(xipcores, dep, src) + verilog = '%s/%s/hdl/verilog/%s.v' %(xipcores, dep, src) + if os.access(vhdl, os.R_OK): + fprj.write('vhdl %s %s\n' %(dep, vhdl)) + elif os.access(verilog, os.R_OK): + fprj.write('verilog %s %s\n' %(dep, verilog)) + else: + fprj.close() + os.remove(prjfile) + raise 'cannot find core file %s or %s' %(vhdl, verilog) + flso.close() + + fsrc = open(srcfile, 'r') + for line in fsrc.readlines(): + tokens = line.split() + if len(tokens) == 3 and (tokens[0] == 'vhdl' or tokens[0] == 'verilog'): + lang = tokens[0] + dep = tokens[1] + src = tokens[2] + src = os.path.join(usrcores, src) + if os.access(src, os.R_OK): + fprj.write('%s %s %s\n' %(lang, dep, src)) + else: + fprj.close() + os.remove(prjfile) + raise 'cannot find user core file %s' %(src) + + fsrc.close() + fprj.close() diff --git a/rce/make/hw/tclgen.py b/rce/make/hw/tclgen.py new file mode 100755 index 00000000..9ba8d611 --- /dev/null +++ b/rce/make/hw/tclgen.py @@ -0,0 +1,48 @@ +#!/usr/bin/python + +import sys +import os + +if __name__ == '__main__': + template = sys.argv[1] + projname = sys.argv[2] + disiobuf = sys.argv[3] + srcdir = sys.argv[4] + sdcfile = sys.argv[5] + srcfile = sys.argv[6] + ucffile = sys.argv[7] + tclfile = sys.argv[8] + + ftemplate = open(template, 'r') + fsrc = open(srcfile, 'r') + ftcl = open(tclfile, 'w') + + for line in fsrc.readlines(): + tokens = line.split() + if len(tokens) == 3 and (tokens[0] == 'vhdl' or tokens[0] == 'verilog'): + lang = tokens[0] + dep = tokens[1] + src = tokens[2] + src = os.path.join(srcdir, src) + if os.access(src, os.R_OK): + ftcl.write('add_file -%s -lib %s %s\n' %(lang, dep, src)) + else: + ftcl.close() + if os.access(tclfile, os.R_OK): + os.remove(tclfile) + raise 'cannot find user core file %s' %(src) + + ftcl.write('\nadd_file %s\n' %(ucffile)) + + sdcfile = os.path.join(srcdir, sdcfile) + ftcl.write('\nadd_file -constraint %s\n\n' %(sdcfile)) + + lines = ftemplate.readlines() + for line in lines: + line = line.replace('PROJNAME', projname) + line = line.replace('DISIOBUF', disiobuf) + ftcl.write(line) + + ftemplate.close() + fsrc.close() + ftcl.close() diff --git a/rce/make/share/Makefile.project.template b/rce/make/share/Makefile.project.template new file mode 100644 index 00000000..bd8fffcb --- /dev/null +++ b/rce/make/share/Makefile.project.template @@ -0,0 +1,17 @@ +# Project level makefile +# ---------------------- +%.mk:; + +# Checks +# ------ +# Check release location variables +ifeq ($(RELEASE_DIR),) +export RELEASE_DIR := $(PWD)/.. +endif + +# Includes +# -------- +include $(RELEASE_DIR)/make/share/setup.mk +include flags.mk +include packages.mk +include $(RELEASE_DIR)/make/share/project.mk diff --git a/rce/make/share/packages.mk.template b/rce/make/share/packages.mk.template new file mode 100644 index 00000000..72ae08f4 --- /dev/null +++ b/rce/make/share/packages.mk.template @@ -0,0 +1,2 @@ +# List packages for this project. Low level first. +# packages := pkg_a pkg_b diff --git a/rce/make/share/premake.mk b/rce/make/share/premake.mk new file mode 100644 index 00000000..501b2885 --- /dev/null +++ b/rce/make/share/premake.mk @@ -0,0 +1,41 @@ +# Prepare to run package level makefile +# ------------------------------------- +Makefile:; + +# This makefile is conditionally included at the start of each package +# specific Makefile. Its purpose is to correctly call itself after +# creating the appropriate directories, set tgt_arch and the target +# specific flags. + + +# Symbols +# ------- +# To be sure there is one, and only one, `-f Makefile' option +MAKE := $(filter-out -f Makefile, $(MAKE)) -f Makefile + +archs := $(arch_tgts) +archs.% := $(addsuffix .%,$(arch_tgts)) + +# Rule specific flags +clean-flags := no_depends=y +cleanall-flags := no_depends=y +userclean-flags := no_depends=y +print-flags := no_depends=y + + +# Rules +# ----- +.PHONY: $(archs) $(archs.%) + +define arch_template +$(1): + $$(quiet)$$(MAKE) PREMAKE_DONE=y tgt_arch=$(1) dir no_depends=y + $$(quiet)$$(MAKE) PREMAKE_DONE=y tgt_arch=$(1) all + +$(1).%: + $$(quiet)$$(MAKE) PREMAKE_DONE=y tgt_arch=$(1) dir no_depends=y + $$(quiet)$$(MAKE) PREMAKE_DONE=y tgt_arch=$(1) $$* $$($$*-flags) + +endef + +$(foreach arc,$(archs),$(eval $(call arch_template,$(arc)))) diff --git a/rce/make/share/project.mk b/rce/make/share/project.mk new file mode 100644 index 00000000..d103f2d2 --- /dev/null +++ b/rce/make/share/project.mk @@ -0,0 +1,39 @@ +# Project level makefile +# ---------------------- +Makefile:; + +# Symbols +# ------- +cwd := $(subst /, ,$(shell pwd)) +prj_name := $(word $(words $(cwd)),$(cwd)) + +archs := $(arch_tgts) +archs.% := $(addsuffix .%,$(arch_tgts)) +packages.% := $(addsuffix .%,$(packages)) + +# Rules +# ----- +.PHONY: $(archs) $(archs.%) $(packages) $(packages.%) + +define package_template +$(1).%: + $(quiet)echo "[PK] Target <$$*> package <$(1)>" + $(quiet)$$(MAKE) -C $(1) $$* +endef + +$(foreach pkg,$(packages),$(eval $(call package_template,$(pkg)))) + +define arch_template +packages_$(1) := $$(foreach pkg,$$(packages),$$(pkg).$(1)) +$(1): $$(packages_$(1)); +$(1).%: $$(addsuffix .%,$$(packages_$(1))); +endef + +$(foreach arc,$(archs),$(eval $(call arch_template,$(arc)))) + +cleanall: + @echo "[RO] Removing project $(prj_name) build directory" + $(quiet)$(RM) -r $(RELEASE_DIR)/build/$(prj_name) + +%:; + @echo "---- No target <$*> for project <$(prj_name)>" diff --git a/rce/make/share/release.mk b/rce/make/share/release.mk new file mode 100644 index 00000000..40640337 --- /dev/null +++ b/rce/make/share/release.mk @@ -0,0 +1,82 @@ +# Top level makefile +# ------------------ +Makefile:; + +# Symbols +# ------- +SHELL := /bin/bash + +# Minimal directory tree +tree_dirs = build + +# Rules +# ----- +.PHONY: dir cleanall $(projects) $(projects.%) + +dir: $(tree_dirs); +$(tree_dirs): + @echo "[DR] Target <dir> at top level"; + $(quiet)mkdir -p $@ + +cleanall: + @echo "[CL] Target <cleanall> at top level"; + $(quiet)$(RM) -r build + +define soft-link + if [ ! -e $(1) ]; then \ + if [ -e $(2) ]; then \ + echo '[SL] Make soft link $(1)'; \ + ln -s $(2) $(1); \ + else \ + echo '[SL] *** project $(2) not found'; \ + fi \ + fi +endef + +define delete-soft-links + for prj in $(projects); do \ + if [ -h build/$$prj ]; then \ + $(RM) build/$$prj; \ + fi; \ + done +endef + +define project_template +ifeq ($$(strip $$($(1)_use)),release) +$(1).%: dir + $(quiet)echo "[PR] Target <$$*> project <$(1)>" + $$(MAKE) -C $(1) $$* +else +ifeq ($$(strip $$($(1)_use)),base) +ifneq ($(base_use),) +$(1).%: dir + @$$(call soft-link,build/$(1),$(base_use)/build/$(1)) + @$$(call soft-link,$(1),$(base_use)/$(1)) +else +$$(error 'Project $(1) specifies base but no base_use statement found.') +endif +else +ifneq ($$(findstring /,$$($(1)_use),),) +$(1).%: dir + @$$(call soft-link,build/$(1),$$($(1)_use)) +else +$$(error 'Project $(1) lacks a use statement.') +endif +endif +endif +endef + +# revisit release_base +# $(1).%: dir +# @$$(call soft-link,build/$(1),$$(release_base)/build/$(1)) +# @$$(call soft-link,$(1),$$(release_base)/$(1)) + +$(foreach prj,$(projects),$(eval $(call project_template,$(prj)))) + +define all-projects + for prj in $(projects); do \ + $(MAKE) $$prj.$*; \ + done +endef + +%:; @$(all-projects) diff --git a/rce/make/share/setup.mk b/rce/make/share/setup.mk new file mode 100644 index 00000000..bb789b62 --- /dev/null +++ b/rce/make/share/setup.mk @@ -0,0 +1,49 @@ +# Checks +# ------ +SHELL := /bin/bash +REQUIRED_MAKE_VERSION := 3.80 + +required_make_major_version := $(word 1,$(subst ., ,$(REQUIRED_MAKE_VERSION))) +required_make_minor_version := $(word 2,$(subst ., ,$(REQUIRED_MAKE_VERSION))) +make_major_version := $(word 1,$(subst ., ,$(MAKE_VERSION))) +make_minor_version := $(word 2,$(subst ., ,$(MAKE_VERSION))) + +test_make_version = $(shell \ + if [[ $(make_major_version) < $(required_make_major_version) || \ + $(make_major_version) == $(required_make_major_version) && \ + $(make_minor_version) < $(required_make_minor_version) ]] ; then \ + echo 'error'; \ + else \ + echo 'ok'; \ + fi) + +ifneq ($(call test_make_version), ok) +$(error 'Makefile version is $(MAKE_VERSION) but needs to be $(REQUIRED_MAKE_VERSION) or higher') +endif + + +# Symbols +# ------- +# To be sure there is one, and only one, `-f Makefile' option +MAKE := $(filter-out -f Makefile, $(MAKE)) -f Makefile + +# Define reverse function +reverse = $(shell \ + set reversed=""; \ + for entry in $(1); do \ + reversed="$$entry $$reversed"; \ + done; \ + echo $$reversed) + +# Set verbosity +ifeq ($(verbose),y) + quiet := + MAKEFLAGS := +else + quiet := @ + MAKEFLAGS := -s +endif + +# Target variable +# --------------- +tgt_arch := $(MAKECMDGOALS) diff --git a/rce/make/sw/Makefile.package.template b/rce/make/sw/Makefile.package.template new file mode 100644 index 00000000..c73fd5ec --- /dev/null +++ b/rce/make/sw/Makefile.package.template @@ -0,0 +1,20 @@ +# Package level makefile +# ---------------------- +%.mk:; + +# Checks +# ------ +# Check release location variables +ifeq ($(RELEASE_DIR),) +export RELEASE_DIR := $(PWD)/../.. +endif + +include $(RELEASE_DIR)/make/share/setup.mk +include ../flags.mk + +ifndef PREMAKE_DONE +include $(RELEASE_DIR)/make/share/premake.mk +else +include constituents.mk +include $(RELEASE_DIR)/make/sw/package.mk +endif diff --git a/rce/make/sw/constituents.mk.template b/rce/make/sw/constituents.mk.template new file mode 100644 index 00000000..a98aa32c --- /dev/null +++ b/rce/make/sw/constituents.mk.template @@ -0,0 +1,39 @@ +# List targets (if any) for this package +# tgtnames := exe_a exe_b + +# List source files for each target +# tgtsrcs_exe_a := src_1.cc src_2.cc +# tgtsrcs_exe_b := src_3.cc + +# List system libraries (if any) needed by exe_a as <dir>/<lib>. +# Note that <lib> is the name of the library, not of the file: i.e. +# <lib> for 'libc.so' is 'c'. Low level first. +# tgtslib_exe_a := /usr/lib/rt + +# List project libraries (if any) needed by exe_a as <project>/<lib>. +# Note that <lib> is the name of the library, not of the file: i.e. +# <lib> for 'libc.so' is 'c'. Low level first. +# tgtlibs_exe_a := prj_x/lib_y + +# List special include directories (if any) needed by exe_a as +# <project>/<incdir>. Note that the top level release directory is +# already in the search path. +# tgtincs_exe_a := prj_x/include prj_x/include/Linux + +# List system include directories (if any) needed by exe_a as <incdir>. +# tgtsinc_exe_a := /usr/include + +# List libraries (if any) for this package +# libnames := lib_a lib_b + +# List source files for each library +# libsrcs_lib_a := src_4.cc src_5.cc +# libsrcs_lib_b := src_6.cc + +# List special include directories (if any) needed by lib_a as +# <project>/<incdir>. Note that the top level release directory is +# already in the search path. +# libincs_lib_a := prj_x/include/Linux + +# List system include directories (if any) needed by lib_a as <incdir>. +# libsinc_lib_a := /usr/include diff --git a/rce/make/sw/flags.mk b/rce/make/sw/flags.mk new file mode 100644 index 00000000..dca9fc38 --- /dev/null +++ b/rce/make/sw/flags.mk @@ -0,0 +1,236 @@ +# Architecture flags +# ------------------ +arch_tgts := ppc-rtems-rce405 i686-slc5-gcc43 ppc-rtems-rceG1 +arch_opts := opt dbg + +define arch_opt_template +arch_tgts += $$(addsuffix -$(1),$$(arch_tgts)) +endef +$(foreach opt,$(arch_opts),$(eval $(call arch_opt_template,$(opt)))) + +# Separate the components of tgt_arch using the dash as a separator. +archwords := $(subst -, ,$(strip $(tgt_arch))) +tgt_opt := $(filter $(arch_opts),$(archwords)) +archwords := $(filter-out $(arch_opts),$(archwords)) +tgt_cpu_family := $(word 1,$(archwords)) +tgt_os := $(word 2,$(archwords)) +tgt_board := $(word 3,$(archwords)) + + +ifeq ($(tgt_os),slc5) +tgt_cpu_family=i386 +tgt_gcc_version:= $(tgt_board) +tgt_board=i386 +tgt_os:=linux +endif + +# Define a compile-time macro for each architecture component. +DEFINES := -Dtgt_opt_$(tgt_opt) +DEFINES += -Dtgt_cpu_family_$(tgt_cpu_family) +DEFINES += -Dtgt_os_$(tgt_os) +DEFINES += -Dtgt_board_$(tgt_board) + + +# i386 Linux specific flags +ifeq ($(tgt_os),linux) +ifeq ($(LINUXVERS),SLC6) +DEFINES+= -D__USE_XOPEN2K8 +endif +ifeq ($(RCE_CORE_VERSION),2.2) +DEFINES+=-DRCE_V2 -Dtgt_board_i386 +endif +#generic toolchain +# pick compiler shipping with OS +AS.EXE:=as +CC.EXE:=gcc +CXX.EXE:=g++ + + +ifeq ($(tgt_gcc_version),gcc43) +CC.EXE:=gcc43 +CXX.EXE:=g++43 +endif + + + + +LD.EXE=$(CXX.EXE) +LX.EXE=$(CXX.EXE) + +AS := $(AS.EXE) +CPP := $(CC) -E +CC := $(CC.EXE) +CXX := $(CXX.EXE) +LD := $(LD.EXE) +LX := $(LX.EXE) + +ifeq ($(tgt_cpu_family),i386) +LIBEXTNS := so +DEPFLAGS := -MM -m32 $(DEFINES) +DEFINES += -fPIC -D_REENTRANT -D__pentium__ -Wall +CPPFLAGS := +CFLAGS := -m32 -g +CXXFLAGS := $(CFLAGS) +CASFLAGS := -x assembler-with-cpp -P $(CFLAGS) +LDFLAGS := -m32 -shared -g +LXFLAGS := -m32 -g +endif +ifeq ($(tgt_cpu_family),x86_64) +LIBEXTNS := so +DEPFLAGS := -MM -m64 +DEFINES += -fPIC -D_REENTRANT -D__pentium__ -Wall +CPPFLAGS := +CFLAGS := -m64 +CXXFLAGS := $(CFLAGS) +CASFLAGS := -x assembler-with-cpp -P $(CFLAGS) +LDFLAGS := -m64 -shared +LXFLAGS := -m64 +endif +else +# Sparc Solaris specific flags +ifeq ($(tgt_cpu_family)-$(tgt_os),sparc-solaris) +AS := as +CPP := gcc -E +CC := gcc +CXX := g++ +LD := g++ +LX := g++ + +LIBEXTNS := so +DEPFLAGS := -MM +DEFINES += -fPIC -D_REENTRANT -Wall +CPPFLAGS := +CFLAGS := +CXXFLAGS := $(CFLAGS) +CASFLAGS := -x assembler-with-cpp -P $(CFLAGS) +LDFLAGS := -shared +LXFLAGS := +else +# PowerPC RTEMS specific flags +ifeq ($(tgt_cpu_family)-$(tgt_os),ppc-rtems) + + +#make sure for cross compile to unset COMPILER_PATH +# this will make the x-compiler to look for includes in the TDAQ compiler path if set +AS := unset COMPILER_PATH;powerpc-rtems4.9-as +CPP := unset COMPILER_PATH;powerpc-rtems4.9-cpp +CC := unset COMPILER_PATH;powerpc-rtems4.9-gcc +CXX := unset COMPILER_PATH;powerpc-rtems4.9-g++ +LD := unset COMPILER_PATH;powerpc-rtems4.9-ld +LX := unset COMPILER_PATH;powerpc-rtems4.9-g++ +AR := unset COMPILER_PATH;powerpc-rtems4.9-ar +OBJCOPY :=unset COMPILER_PATH;powerpc-rtems4.9-objcopy + +ifeq ($(tgt_board),rceG1) +AS := unset COMPILER_PATH;powerpc-rtems4.10-as +CPP := unset COMPILER_PATH;powerpc-rtems4.10-cpp +CC := unset COMPILER_PATH;powerpc-rtems4.10-gcc +CXX := unset COMPILER_PATH;powerpc-rtems4.10-g++ +LD := unset COMPILER_PATH;powerpc-rtems4.10-ld +LX := unset COMPILER_PATH;powerpc-rtems4.10-g++ +AR := unset COMPILER_PATH;powerpc-rtems4.10-ar +OBJCOPY := unset COMPILER_PATH;powerpc-rtems4.10-objcopy +endif + +ifeq ($(tgt_board),rce405) +RTEMSDIR := $(RELEASE_DIR)/build/rtems/target/powerpc-rtems/rce405/lib +tgt_cpu=403 +endif + +ifeq ($(tgt_board),rceG1) +RTEMSDIR := $(RELEASE_DIR)/build/rtems/target/powerpc-rtems4.10/virtex4/lib +tgt_cpu=405 +endif + + + +ifeq ($(tgt_board),ml405) +RTEMSDIR := $(RELEASE_DIR)/build/rtems/target/powerpc-rtems/ml405/lib +endif +ifeq ($(RCE_CORE),"") +LDTOOLSD := $(RELEASE_DIR)/rce/ldtools +else +LDTOOLSD := $(RCE_CORE)/ldtools +endif +LIBEXTNS := a + +DEPFLAGS := -B$(RTEMSDIR) -MM -Dppc405=ppc405 $(DEFINES) +DEFINES += -Dppc405=ppc405 +MDEFINES := $(DEFINES) -DEXPORT='__attribute__((visibility("default")))' + +ifeq ($(tgt_board),rceG1) +DEFINES += -Dtgt_gen=gen1 -Drtems_majorv_macro=4 -Drtems_minorv_macro=10 -Drtems_revision_macro=2 -DRCE_V2 +MDEFINES += -Dtgt_gen=gen1 -Drtems_majorv_macro=4 -Drtems_minorv_macro=10 -Drtems_revision_macro=2 -DRCE_V2 +DEPFLAGS+= -Dtgt_gen=gen1 -Drtems_majorv_macro=4 -Drtems_minorv_macro=10 -Drtems_revision_macro=2 -DRCE_V2 +endif +CPPFLAGS := +CFLAGS := -B$(RTEMSDIR) -specs bsp_specs -qrtems -mcpu=$(tgt_cpu) -Wall +CXXFLAGS := $(CFLAGS) +CASFLAGS := -x assembler-with-cpp -P $(CFLAGS) +LDFLAGS := -r +#remove -s flag to not strip symbols +#LXFLAGS := -B$(RTEMSDIR) -specs $(LDTOOLSD)/dynamic_specs -qrtems -qnolinkcmds -Wl,-T$(LDTOOLSD)/dynamic.ld -mcpu=$(tgt_cpu) +#LXFLAGS := -B$(RTEMSDIR) -specs $(LDTOOLSD)/dynamic_specs -qrtems -qnolinkcmds -Wl,-T$(LDTOOLSD)/dynamic.ld -mcpu=$(tgt_cpu) +#old for debugger +ifeq ($(RCE_CORE_VERSION),2.2) +#LXFLAGS := -B$(RTEMSDIR) -specs $(LDTOOLSD)/dynamic_specs -qrtems -qnolinkcmds -Wl,-T$(LDTOOLSD)/bootLoader.ld -mcpu=$(tgt_cpu) +#for debug image +LXFLAGS := -B$(RTEMSDIR) -specs $(LDTOOLSD)/dynamic_specs -qrtems -qnolinkcmds -Wl,-T$(LDTOOLSD)/dynamic.ld -mcpu=$(tgt_cpu) +else +LXFLAGS := -s -B$(RTEMSDIR) -specs $(LDTOOLSD)/dynamic_specs -qrtems -qnolinkcmds -Wl,-T$(LDTOOLSD)/dynamic.ld -mcpu=$(tgt_cpu) +endif + + +MANAGERS := timer sem msg event signal part region dpmem io rtmon ext mp + +MCFLAGS := -B$(RTEMSDIR) -specs $(LDTOOLSD)/module_specs -qrtems -Wall -fvisibility=hidden -mlongcall -fno-pic -mcpu=$(tgt_cpu) +MCXXFLAGS := $(MCFLAGS) +MCASFLAGS := -x assembler-with-cpp -P $(MCFLAGS) +MLDFLAGS := -r +#remove -s flag to not strip symbols +#MLXFLAGS := -B$(RTEMSDIR) -specs $(LDTOOLSD)/module_specs -qrtems -qnolinkcmds -Wl,-T$(LDTOOLSD)/module.ld -mcpu=$(tgt_cpu) -shared -nostdlib +MLXFLAGS := -s -B$(RTEMSDIR) -specs $(LDTOOLSD)/module_specs -qrtems -qnolinkcmds -Wl,-T$(LDTOOLSD)/module.ld -mcpu=$(tgt_cpu) -shared -nostdlib + +ifeq ($(tgt_board),rceG1) +LXFLAGS += -L$(LDTOOLSD) -L$(LDTOOLSD)/rceG1 +LXFLAGS += $(RELEASE)/build/platform/obj/ppc-rtems-rceG1-opt/startup/src/Init.o +LXFLAGS += $(RELEASE)/build/platform/obj/ppc-rtems-rceG1-opt/startup/src/extrarefs.o +LXFLAGS += $(RELEASE)/build/platform/obj/ppc-rtems-rceG1-opt/startup/src/rce/Init.o +LXFLAGS += $(RELEASE)/build/platform/obj/ppc-rtems-rceG1-opt/startup/bldInfo_dpm.2.2.prod.o +MXFLAGS += -L$(LDTOOLSD) -L$(LDTOOLSD)/rceG1 +endif + +else +ifeq ($(tgt_cpu_family)-$(tgt_os),ppc-linux) +AS := as +CPP := gcc -E +CC := gcc +CXX := g++ +LD := g++ +LX := g++ + +LIBEXTNS := so +DEPFLAGS := -MM +DEFINES += -D_REENTRANT -Wall +CPPFLAGS := +CFLAGS := +CXXFLAGS := $(CFLAGS) +CASFLAGS := -x assembler-with-cpp -P $(CFLAGS) +LDFLAGS := -shared +LXFLAGS := + +endif +endif +endif +endif + + +ifeq ($(tgt_opt),opt) +DEFINES += -O4 +MDEFINES += -O4 +endif + +ifeq ($(tgt_opt),dbg) +DEFINES += -g +MDEFINES += -g +endif diff --git a/rce/make/sw/flags.mk.template b/rce/make/sw/flags.mk.template new file mode 100644 index 00000000..dadf67ae --- /dev/null +++ b/rce/make/sw/flags.mk.template @@ -0,0 +1 @@ +include $(RELEASE_DIR)/make/sw/flags.mk diff --git a/rce/make/sw/idl.mk b/rce/make/sw/idl.mk new file mode 100644 index 00000000..26e0977d --- /dev/null +++ b/rce/make/sw/idl.mk @@ -0,0 +1,24 @@ +# Call omniidl to preprocess .idl files + + +$(objdir)/%SK.o: $(objdir)/%SK.cc + @echo "[CX] Compiling $<" + $(quiet)$(CXX) $(incdirs_$*SK.cc) $(DEFINES) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ + + +$(objdir)/%SK.cc $(objdir)/%.hh: %.idl + @echo "[ID] IDL Preprocessing $<" + $(quiet)omniidl $(incdirs_$*SK.cc) -bcxx $(IDLFLAGS) -C$(objdir)/$(dir $*) $< + +$(modobjdir)/%SK.o: $(modobjdir)/%SK.cc + @echo "[MX] Compiling $<" + $(quiet)$(CXX) $(incdirs_$*SK.cc) $(CPPFLAGS) $(MDEFINES) $(MCXXFLAGS) -c $< -o $@ + + +$(modobjdir)/%SK.cc $(modobjdir)/%.hh: %.idl + @echo "[ID] IDL Preprocessing $<" + $(quiet)omniidl $(incdirs_$*SK.cc) -bcxx $(IDLFLAGS) -C$(modobjdir)/$(dir $*) $< + + + + diff --git a/rce/make/sw/package.mk b/rce/make/sw/package.mk new file mode 100644 index 00000000..0885ce14 --- /dev/null +++ b/rce/make/sw/package.mk @@ -0,0 +1,396 @@ +# Package level makefile +# ---------------------- +Makefile:; + +# Symbols +# ------- +SHELL := /bin/bash +RM := rm -f +MV := mv -f +empty := +space := $(empty) $(empty) + +cwd := $(call reverse,$(subst /, ,$(shell pwd))) +pkg_name := $(word 1,$(cwd)) +prj_name := $(word 2,$(cwd)) + +# Defines which directories are being created by this makefile +libdir := $(RELEASE_DIR)/build/$(prj_name)/lib/$(tgt_arch) +bindir := $(RELEASE_DIR)/build/$(prj_name)/bin/$(tgt_arch) +objdir := $(RELEASE_DIR)/build/$(prj_name)/obj/$(tgt_arch)/$(pkg_name) +moddir := $(RELEASE_DIR)/build/$(prj_name)/mod/$(tgt_arch) +modobjdir := $(RELEASE_DIR)/build/$(prj_name)/modobj/$(tgt_arch)/$(pkg_name) +modlibdir := $(RELEASE_DIR)/build/$(prj_name)/modlib/$(tgt_arch) +depdir := $(RELEASE_DIR)/build/$(prj_name)/dep/$(tgt_arch)/$(pkg_name) +moddepdir := $(RELEASE_DIR)/build/$(prj_name)/moddep/$(tgt_arch)/$(pkg_name) +prod_dirs := $(strip $(bindir) $(libdir) $(moddir) $(modlibdir)) +temp_dirs = $(strip $(sort $(foreach o,$(depends) $(objects),$(dir $(o))))) + +# Dummy shared library search (RTEMS only) +# ---------------------------------------- + +# In order to get a dynamic symbol table into a target it's necessary +# (but not sufficient) to search at least one shared library. Why a +# dynamic symbol table rather than a regular one? A dynamic symbol +# table is part of a loadable segment (and section) so ELF-loaders +# will automatically copy the table into memory; no painful hacks are +# required to extract the table and find a safe place for it. As a +# bonus we get a hash table to speed our lookups. + +# Make each target (executable) depend on the "dummy" library of +# package rce/ldtools. We can just append to the list of libraries +# for a target because the command line arguments generated +# for the final linking of the target don't depend on the type +# of library. It's up to rce/ldtools to make sure that the dummy +# library is indeed a shared library. + +ifeq ($(tgt_os),rtems) + +define adddummylib +ifndef tgtlibs_$(tgt) +tgtlibs_$(tgt) := +endif +ifeq ($(RCE_CORE_VERSION),2.2) +tgtlibs_$(tgt) += service/dummy +else +tgtlibs_$(tgt) += rce/dummy +endif +endef + +$(foreach tgt,$(tgtnames),$(eval $(adddummylib))) +endif + + +# Procedures +# ---------- + +# Define some procedures and create (different!) rules for libraries +# and targets. Note that 'eval' needs gmake >= 3.80. +libraries := +modules := +targets := +objects := +depends := +getobjects = $(strip \ + $(patsubst %.cc,$(1)/%.o,$(filter %.cc,$(2))) \ + $(patsubst %.cpp,$(1)/%.o,$(filter %.cpp,$(2))) \ + $(patsubst %.c,$(1)/%.o, $(filter %.c,$(2))) \ + $(patsubst %.s,$(1)/%.o, $(filter %.s,$(2)))) +getprj = $(word 1,$(subst /, ,$(1))) +getlib = $(word 2,$(subst /, ,$(1))) +getproject = $(RELEASE_DIR)/build/$(1)/lib/$(tgt_arch) +getlibrary = $(call getproject,$(call getprj,$(1)))/lib$(call getlib,$(1)).$(LIBEXTNS) +getlibraries = $(foreach prjlib,$(1),$(call getlibrary,$(prjlib))) +getprojects = $(foreach prjlib,$(1),$(call getprj,$(prjlib))) +getlinkdirs = $(addprefix -L, $(sort $(foreach prj,$(call getprojects,$(1)),$(call getproject,$(prj))))) +getlinksdir = $(addprefix -L, $(sort $(dir $(1)))) +getlinklibs = $(addprefix -l,$(foreach prjlib,$(1),$(call getlib,$(prjlib)))) +getlinkslib = $(addprefix -l,$(notdir $(1))) +getrpath = $$ORIGIN/../../../$(1)/lib/$(tgt_arch) +getrpaths = $(subst $(space),:,$(strip $(foreach prj,$(call getprojects,$(1)),$(call getrpath,$(prj))))) + +getmodname = $(word 1,$(subst ., ,$(1))) +getmodlibproject = $(RELEASE_DIR)/build/$(1)/modlib/$(tgt_arch) +getmodproject = $(RELEASE_DIR)/build/$(1)/mod/$(tgt_arch) +getmodlibrary = $(call getmodlibproject,$(call getprj,$(1)))/lib$(call getlib,$(1)).a +getmodlibraries = $(foreach prjlib,$(1),$(call getmodlibrary,$(prjlib))) +getmodlinkdirs = $(addprefix -L, $(sort $(foreach prj,$(call getprojects,$(1)),$(call getmodlibproject,$(prj))))) +expandneededmods = $(foreach needed,$(1),$(call getmodproject,$(call getprj,$(needed)))/$(call getlib,$(needed)).so) + + +define object_template + incdirs_$(1) := $$(addprefix -I$(RELEASE_DIR)/,$(2)) + incdirs_$(1) += -I$(RELEASE_DIR) + incdirs_$(1) += $$(addprefix -I$(RELEASE_DIR)/build/,$(2)) + incdirs_$(1) += -I$(RELEASE_DIR)/build + incdirs_$(1) += $$(addprefix -I,$(3)) +endef + +define library_template + library_$(1) := $$(libdir)/lib$(1).$(LIBEXTNS) + libobjs_$(1) := $$(call getobjects,$$(objdir),$$(libsrcs_$(1))) + libraries += $$(library_$(1)) + objects += $$(libobjs_$(1)) + depends += $$(libobjs_$(1):$$(objdir)/%.o=$$(depdir)/%.d) + libraries_$(1) := $$(call getlibraries,$$(liblibs_$(1))) + linkdirs_$(1) := $$(call getlinkdirs,$$(liblibs_$(1))) + linkdirs_$(1) += $$(call getlinksdir,$$(libslib_$(1))) +ifneq ($$(liblibs_$(1)),) + linklibs_$(1) := $$(call reverse,$$(call getlinklibs,$$(liblibs_$(1)))) +endif +ifneq ($$(libslib_$(1)),) + linklibs_$(1) += $$(call reverse,$$(call getlinkslib,$$(libslib_$(1)))) +endif +ifeq ($$(LIBEXTNS),so) +ifneq ($$(ifversn_$(1)),) + ifversnflags_$(1) := -Wl,--version-script=$$(ifversn_$(1)) +endif +endif + linkflags_$(1) := $$(linkdirs_$(1)) $$(linklibs_$(1)) +$$(library_$(1)): $$(libobjs_$(1)) +endef + +$(foreach lib,$(libnames),$(eval $(call library_template,$(lib)))) +$(foreach lib,$(libnames),$(foreach obj,$(libsrcs_$(lib)),$(eval $(call object_template,$(obj),$(libincs_$(lib)),$(libsinc_$(lib)))))) + +define target_template + target_$(1) := $$(bindir)/$(1) + tgtobjs_$(1) := $$(call getobjects,$$(objdir),$$(tgtsrcs_$(1))) + targets += $$(target_$(1)) + objects += $$(tgtobjs_$(1)) + depends += $$(tgtobjs_$(1):$$(objdir)/%.o=$$(depdir)/%.d) + libraries_$(1) := $$(call getlibraries,$$(tgtlibs_$(1))) + linkdirs_$(1) := $$(call getlinkdirs,$$(tgtlibs_$(1))) + linkdirs_$(1) += $$(call getlinksdir,$$(tgtslib_$(1))) +ifneq ($$(tgtlibs_$(1)),) + linklibs_$(1) := $$(call reverse,$$(call getlinklibs,$$(tgtlibs_$(1)))) +endif +ifneq ($$(tgtslib_$(1)),) + linklibs_$(1) += $$(call reverse,$$(call getlinkslib,$$(tgtslib_$(1)))) +endif +ifeq ($$(LIBEXTNS),so) + rpaths_$(1) := -Wl,-rpath='$$(call getrpaths,$$(tgtlibs_$(1)))' +endif + linkflags_$(1) := $$(linkdirs_$(1)) $$(linklibs_$(1)) $$(rpaths_$(1)) +ifneq ($$(MANAGERS),) + nomanagrs_$(1) := $$(filter-out $$(managrs_$(1)),$$(MANAGERS)) + nomanagrs_$(1) := $$(nomanagrs_$(1):%=$$(RTEMSDIR)/no-%.rel) + tgtobjs_$(1) += $$(nomanagrs_$(1)) +endif +$$(target_$(1)): $$(tgtobjs_$(1)) $$(libraries_$(1)) +endef + +$(foreach tgt,$(tgtnames),$(eval $(call target_template,$(tgt)))) +$(foreach tgt,$(tgtnames),$(foreach obj,$(tgtsrcs_$(tgt)),$(eval $(call object_template,$(obj),$(tgtincs_$(tgt)),$(tgtsinc_$(tgt)))))) + + +define module_library_template + library_$(1) := $$(modlibdir)/lib$(1).a + libobjs_$(1) := $$(call getobjects,$$(modobjdir),$$(libsrcs_$(1))) + libraries += $$(library_$(1)) + objects += $$(libobjs_$(1)) + depends += $$(libobjs_$(1):$$(modobjdir)/%.o=$$(moddepdir)/%.d) + libraries_$(1) := $$(call getmodlibraries,$$(liblibs_$(1))) + linkdirs_$(1) := $$(call getmodlinkdirs,$$(liblibs_$(1))) + linkdirs_$(1) += $$(call getmodlinksdir,$$(libslib_$(1))) +ifneq ($$(liblibs_$(1)),) + linklibs_$(1) := $$(call reverse,$$(call getlinklibs,$$(liblibs_$(1)))) +endif +ifneq ($$(libslib_$(1)),) + linklibs_$(1) += $$(call reverse,$$(call getlinkslib,$$(libslib_$(1)))) +endif + linkflags_$(1) := $$(linkdirs_$(1)) $$(linklibs_$(1)) +$$(library_$(1)): $$(libobjs_$(1)) +endef + +$(foreach lib,$(modlibnames),$(eval $(call module_library_template,$(lib)))) +$(foreach lib,$(modlibnames),$(foreach obj,$(libsrcs_$(lib)),$(eval $(call object_template,$(obj),$(libincs_$(lib)),$(libsinc_$(lib)))))) + + +define module_template + module_$(1) := $$(moddir)/$(1).$(majorv_$(1)).$(minorv_$(1)).$(branch_$(1)).so + modobjs_$(1) := $$(call getobjects,$$(modobjdir),$$(modsrcs_$(1))) + modules += $$(module_$(1)) + objects += $$(modobjs_$(1)) + depends += $$(modobjs_$(1):$$(modobjdir)/%.o=$$(moddepdir)/%.d) + libraries_$(1) := $$(call getmodlibraries,$$(modlibs_$(1))) + linkdirs_$(1) := $$(call getmodlinkdirs,$$(modlibs_$(1))) + linkdirs_$(1) += $$(call getlinksdir,$$(modslib_$(1))) +ifneq ($$(modlibs_$(1)),) + linklibs_$(1) := $$(call reverse,$$(call getlinklibs,$$(modlibs_$(1)))) +endif +ifneq ($$(modslib_$(1)),) + linklibs_$(1) += $$(call reverse,$$(call getlinkslib,$$(modslib_$(1)))) +endif + linkflags_$(1) := $$(linkdirs_$(1)) $$(linklibs_$(1)) +$$(module_$(1)): $$(modobjs_$(1)) $$(libraries_$(1)) $$(call expandneededmods,$$(modsneeded_$(1))) +endef + +$(foreach mod,$(modnames),$(eval $(call module_template,$(mod)))) +$(foreach mod,$(modnames),$(foreach obj,$(modsrcs_$(mod)),$(eval $(call object_template,$(obj),$(modincs_$(mod)),$(modsinc_$(mod)))))) + + +# Rules +# ----- +rules := all dir obj lib bin clean cleanall userall userclean print + +.PHONY: $(rules) $(libnames) $(tgtnames) + +.SUFFIXES: # Kills all implicit rules + +all: bin userall; + +obj: $(objects); + +lib: $(libraries); + +bin: lib $(targets) $(modules); + +dir: $(prod_dirs) $(temp_dirs); + +print: + @echo "bindir = $(bindir)" + @echo "moddir = $(moddir)" + @echo "libdir = $(libdir)" + @echo "objdir = $(objdir)" + @echo "modobjdir = $(modobjdir)" + @echo "depdir = $(depdir)" + @echo "moddepdir = $(moddepdir)" + @echo "targets = $(targets)" + @echo "libraries = $(libraries)" + @echo "modules = $(modules)" + @echo "depends = $(depends)" + @echo "objects = $(objects)" + @echo "managers = $(MANAGERS)" + +clean: userclean +ifneq ($(objects),) + @echo "[RO] Removing object files" + $(quiet)$(RM) $(objects) +endif +ifneq ($(depends),) + @echo "[RD] Removing depend files" + $(quiet)$(RM) $(depends) +endif +ifneq ($(libraries),) + @echo "[RL] Removing libraries: $(notdir $(libraries))" + $(quiet)$(RM) $(libraries) +endif +ifneq ($(targets),) + @echo "[RT] Removing targets: $(notdir $(targets))" + $(quiet)$(RM) $(targets) +endif +ifneq ($(modules),) + @echo "[RM] Removing modules: $(notdir $(modules))" + $(quiet)$(RM) $(modules) +endif + +cleanall: userclean + $(quiet)$(RM) -r $(temp_dirs) + + +# Directory structure +$(prod_dirs) $(temp_dirs): + $(quiet)mkdir -p $@ + + +# Libraries +$(libdir)/lib%.$(LIBEXTNS): + @echo "[LD] Build library $*" + $(quiet)$(LD) $(LDFLAGS) $(ifversnflags_$*) $(linkflags_$*) $^ -o $@ + + +# Exceutables +$(bindir)/%: + @echo "[LT] Linking target $*" + $(quiet)$(LX) $(DEFINES) $(tgtobjs_$*) $(linkflags_$*) $(LXFLAGS) -o $@ + +# Libraries for modules +$(modlibdir)/lib%.a: + @echo "[MD] Linking lib-for-modules $*" + $(quiet)$(LD) $(MLDFLAGS) $(linkflags_$*) $^ -o $@ + +# Modules +ifeq ($(RCE_CORE_VERSION),2.2) +ldtoolsobj := $(LDTOOLSD) +else +ldtoolsobj := $(RELEASE_DIR)/build/rce/modobj/$(tgt_arch)/ldtools +endif + +$(moddir)/%: + @echo "[LM] Linking module $* (modname = $(call getmodname,$*))" + $(quiet)$(LX) $(MLXFLAGS) -o $@ \ + -Wl,-soname,$(*:.so=) \ + -Wl,-Map,$(moddir)/$*.map \ + $(ldtoolsobj)/modbegin.o \ + $(ldtoolsobj)/rcework.o \ + $(modobjs_$(call getmodname,$*)) $(linkflags_$(call getmodname,$*)) \ + $(ldtoolsobj)/modend.o \ + $(modsneeded_$(call getmodname,$*)) + $(quiet)$(OBJCOPY) --set-section-flags .bss=alloc,contents,load $@ + +# Objects for C, C++ and assembly files not intended for modules +$(objdir)/%.o: %.c + @echo "[CC] Compiling $<" + $(quiet)$(CC) $(incdirs_$<) $(CPPFLAGS) $(DEFINES) $(CFLAGS) -c $< -o $@ + +$(objdir)/%.o: %.cc + @echo "[CX] Compiling $<" + $(quiet)$(CXX) $(incdirs_$<) $(CPPFLAGS) $(DEFINES) $(CXXFLAGS) -c $< -o $@ + +$(objdir)/%.o: %.cpp + @echo "[CX] Compiling $<" + $(quiet)$(CXX) $(incdirs_$<) $(CPPFLAGS) $(DEFINES) $(CXXFLAGS) -c $< -o $@ + +$(objdir)/%.o: %.s + @echo "[CS] Compiling $<" + $(quiet)$(CXX) $(incdirs_$<) $(CPPFLAGS) $(DEFINES) $(CASFLAGS) -c $< -o $@ + + +# Module objects for C, C++ and assembly files +$(modobjdir)/%.o: %.c + @echo "[MC] Compiling $<" + $(quiet)$(CC) $(incdirs_$<) $(CPPFLAGS) $(MDEFINES) $(MCFLAGS) -c $< -o $@ + +$(modobjdir)/%.o: %.cc + @echo "[MX] Compiling $<" + $(quiet)$(CXX) $(incdirs_$<) $(CPPFLAGS) $(MDEFINES) $(MCXXFLAGS) -c $< -o $@ + +$(modobjdir)/%.o: %.cpp + @echo "[MX] Compiling $<" + $(quiet)$(CXX) $(incdirs_$<) $(CPPFLAGS) $(MDEFINES) $(MCXXFLAGS) -c $< -o $@ + +$(modobjdir)/%.o: %.s + @echo "[MS] Compiling $<" + $(quiet)$(CXX) $(incdirs_$<) $(CPPFLAGS) $(MDEFINES) $(MCASFLAGS) -c $< -o $@ + + +# Defines rules to (re)build dependency files +DEPSED = sed '\''s!$(notdir $*)\.o!$(objdir)/$*\.o $@!g'\'' +CXXDEP = $(CXX) $(incdirs_$<) $(CPPFLAGS) $(DEPFLAGS) +CCDEP = $(CC) $(incdirs_$<) $(CPPFLAGS) $(DEPFLAGS) + +$(depdir)/%.d: %.c + @echo "[DC] Dependencies for $<" + $(quiet)$(SHELL) -ec '$(CCDEP) $< | $(DEPSED) > $@' + +$(depdir)/%.d: %.cc + @echo "[DX] Dependencies for $<" + $(quiet)$(SHELL) -ec '$(CXXDEP) $< | $(DEPSED) > $@' + +$(depdir)/%.d: %.cpp + @echo "[DX] Dependencies for $<" + $(quiet)$(SHELL) -ec '$(CXXDEP) $< | $(DEPSED) > $@' + +$(depdir)/%.d: %.s + @echo "[DS] Dependencies for $<" + $(quiet)$(SHELL) -ec '$(CCDEP) $< | $(DEPSED) > $@' + +MODDEPSED = sed '\''s!$(notdir $*)\.o!$(modobjdir)/$*\.o $@!g'\'' + +$(moddepdir)/%.d: %.c + @echo "[MDC] Dependencies for $<" + $(quiet)$(SHELL) -ec '$(CCDEP) $< | $(MODDEPSED) > $@' + +$(moddepdir)/%.d: %.cc + @echo "[MDX] Dependencies for $<" + $(quiet)$(SHELL) -ec '$(CXXDEP) $< | $(MODDEPSED) > $@' + +$(moddepdir)/%.d: %.cpp + @echo "[MDX] Dependencies for $<" + $(quiet)$(SHELL) -ec '$(CXXDEP) $< | $(MODDEPSED) > $@' + +$(moddepdir)/%.d: %.s + @echo "[MDS] Dependencies for $<" + $(quiet)$(SHELL) -ec '$(CCDEP) $< | $(MODDEPSED) > $@' + +# Include the dependency files. If one of the .d files in depends +# does not exist, then make invokes one of the rules [Dn] above to +# rebuild the missing .d file. This can be short-circuited by +# defining the symbol 'no_depends'. + +ifneq ($(depends),) +ifeq ($(no_depends),) +-include $(depends) +endif +endif diff --git a/rce/make/sw/python.mk b/rce/make/sw/python.mk new file mode 100644 index 00000000..790fdc21 --- /dev/null +++ b/rce/make/sw/python.mk @@ -0,0 +1,41 @@ +# Call sip interpreter for python wrappers +$(objdir)/%_sip_wrap.o: $(objdir)/%_sip_wrap.cpp + @echo "[CX] Compiling $<" + $(quiet)$(CXX) $(incdirs_$*_sip_wrap.cpp) $(DEFINES) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ + + +$(objdir)/%_sip_wrap.cpp: %_sip_wrap.sip + @echo "[WG] Python sip $<" + $(quiet)sip $(SIPFLAGS) -e -j 1 -c $(objdir)/ $< + cp $(objdir)/sip$*part0.cpp . + $(quiet)mv $(objdir)/sip$*part0.cpp $@ + +# $(incdirs_$*_sip_wrap.cpp) + + +# Call swig interpreter for python wrappers +$(objdir)/%_swig_wrap.o: $(objdir)/%_swig_wrap.c + @echo "[CC] Compiling $<" + $(quiet)$(CC) $(incdirs_$*_swig_wrap.c) $(DEFINES) $(CFLAGS) -c $< -o $@ + +$(objdir)/%_swig_wrap.c: %_swig_wrap.i + @echo "[WG] Python swig $<" + $(quiet)swig $(incdirs_$*_swig_wrap.c) -Wall -python -o $@ $< + +SWGDEPSED = sed '\''s!$(notdir $*)\_swig_wrap_wrap.c!$(objdir)/$*\_swig_wrap.c $@!g'\'' +SWGDEP = swig $(DEPFLAGS) $(incdirs_$*_swig_wrap.c) + +$(depdir)/%_swig_wrap.d: %_swig_wrap.i + @echo "[DI] Dependencies for $<" + $(quiet)$(SHELL) -ec '$(SWGDEP) $< | $(SWGDEPSED) > $@' + +# Include the dependency files. If one of the .d files in depends +# does not exist, then make invokes one of the rules [Dn] above to +# rebuild the missing .d file. This can be short-circuited by +# defining the symbol 'no_depends'. + +ifneq ($(depends),) +ifeq ($(no_depends),) +-include $(depends) +endif +endif diff --git a/rce/make/sw/qt.mk b/rce/make/sw/qt.mk new file mode 100644 index 00000000..816877e4 --- /dev/null +++ b/rce/make/sw/qt.mk @@ -0,0 +1,10 @@ +# Call Qt meta object compiler (moc) +MOC := $(RELEASE_DIR)/build/qt/bin/moc + +$(objdir)/%_moc.o: %_moc.cc + @echo "[CX] Compiling $<" + $(quiet)$(CXX) $(incdirs_$<) $(DEFINES) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@ + +%_moc.cc: %.hh + @echo "[MOC] Qt moc $<" + $(quiet)$(MOC) $< -o $@ diff --git a/rce/make/sw/rootcint.mk b/rce/make/sw/rootcint.mk new file mode 100644 index 00000000..b2055370 --- /dev/null +++ b/rce/make/sw/rootcint.mk @@ -0,0 +1,10 @@ +# Call rootcint to make root dictionary. +$(objdir)/%_rootDict.o: $(objdir)/%_rootDict.cc + @echo "[CX] Compiling $<" + $(quiet)$(CXX) $(incdirs_$(notdir $<)) $(DEFINES) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ + + + +$(objdir)/%_rootDict.cc: %_Linkdef.hh $(GUIHEADERSDEP) + @echo "[RC] Rootcint Preprocessing $<" + $(quiet)rootcint -f $@ -c $(CPPFLAGS) $(guiheaders_$(subst _Linkdef.hh,,$<)) $< diff --git a/rce/make/tools/options.py b/rce/make/tools/options.py new file mode 100644 index 00000000..68b8c2db --- /dev/null +++ b/rce/make/tools/options.py @@ -0,0 +1,47 @@ +import sys +import getopt + +class Options(object): + def __init__(self, mandatory, optional=[], switches=[]): + self.opts = {} + + self.__mand = mandatory + self.__optn = optional + self.__swtc = switches + + def __getattr__(self, attribute): + if attribute in self.opts: + return self.opts[attribute] + return None + + def usage(self, notes=''): + msg = 'usage: %s' %(sys.argv[0]) + for option in self.__mand: + msg += ' --%s <%sname>' %(option, option) + for option in self.__optn: + msg += ' [--%s <%sname>]' %(option, option) + for option in self.__swtc: + msg += ' [--%s]' %(option) + if notes != '': + msg += '\nnotes: ' + msg += notes + print msg + + + def parse(self): + opts = [] + for option in self.__mand: + opts.append(option+'=') + for option in self.__optn: + opts.append(option+'=') + for option in self.__swtc: + opts.append(option) + results = getopt.getopt(sys.argv[1:], '', opts) + if len(results[1]) > 0: + raise RuntimeError, 'unknown argument(s) \'%s\'' %(results[1]) + for opt in results[0]: + self.opts[opt[0][2:]] = opt[1] + for option in self.__mand: + if option not in self.opts: + raise RuntimeError, 'mandatory option \'--%s\' not found' %(option) + diff --git a/rce/make/tools/pkgcreate.py b/rce/make/tools/pkgcreate.py new file mode 100755 index 00000000..c11c77cd --- /dev/null +++ b/rce/make/tools/pkgcreate.py @@ -0,0 +1,50 @@ +#!/usr/bin/python + +import sys +import os +import shutil + +from options import Options + +def __pkgcreate(options): + prjdir = options.project + pkgdir = os.path.join(prjdir, options.package) + + if not os.path.exists(prjdir): + os.mkdir(prjdir) + shutil.copy('make/share/Makefile.project.template', + os.path.join(prjdir, 'Makefile')) + shutil.copy('make/share/packages.mk.template', + os.path.join(prjdir, 'packages.mk')) + if options.hw is None: + shutil.copy('make/sw/flags.mk.template', + os.path.join(prjdir, 'flags.mk')) + else: + shutil.copy('make/hw/flags.mk.template', + os.path.join(prjdir, 'flags.mk')) + + if not os.path.exists(pkgdir): + os.mkdir(pkgdir) + if options.hw is None: + shutil.copy('make/sw/Makefile.package.template', + os.path.join(pkgdir, 'Makefile')) + shutil.copy('make/sw/constituents.mk.template', + os.path.join(pkgdir, 'constituents.mk')) + else: + shutil.copy('make/hw/Makefile.package.template', + os.path.join(pkgdir, 'Makefile')) + shutil.copy('make/hw/constituents.mk.template', + os.path.join(pkgdir, 'constituents.mk')) + else: + print "Package %s already exists" %(pkgdir) + + +if __name__ == '__main__': + options = Options(['project', 'package'], [], ['hw']) + try: + options.parse() + except Exception, msg: + options.usage(str(msg)) + sys.exit() + + __pkgcreate(options) diff --git a/rce/make/tools/prjupdate.py b/rce/make/tools/prjupdate.py new file mode 100755 index 00000000..49e10535 --- /dev/null +++ b/rce/make/tools/prjupdate.py @@ -0,0 +1,48 @@ +#!/usr/bin/python + +import sys +import os +import shutil +import glob + +from options import Options + +def __prjupdate(options): + prjdir = options.project + + if os.path.exists(prjdir): + if os.path.exists(os.path.join(prjdir, 'Makefile')): + os.rename(os.path.join(prjdir, 'Makefile'), + os.path.join(prjdir, 'Makefile.orig')) + if os.path.exists(os.path.join(prjdir, 'flags.mk')): + os.rename(os.path.join(prjdir, 'flags.mk'), + os.path.join(prjdir, 'flags.mk.orig')) + shutil.copy('make/share/Makefile.project.template', + os.path.join(prjdir, 'Makefile')) + if options.hw is None: + shutil.copy('make/sw/flags.mk.template', + os.path.join(prjdir, 'flags.mk')) + else: + shutil.copy('make/hw/flags.mk.template', + os.path.join(prjdir, 'flags.mk')) + else: + print "Project %s does not exist" %(prjdir) + + pkgmakes = glob.glob(os.path.join(prjdir, '*/Makefile')) + for pkgmake in pkgmakes: + os.rename(pkgmake, pkgmake+'.orig') + if options.hw is None: + shutil.copy('make/sw/Makefile.package.template', pkgmake) + else: + shutil.copy('make/hw/Makefile.package.template', pkgmake) + + +if __name__ == '__main__': + options = Options(['project'], [], ['hw']) + try: + options.parse() + except Exception, msg: + options.usage(str(msg)) + sys.exit() + + __prjupdate(options) diff --git a/rce/make/tools/replace.pl b/rce/make/tools/replace.pl new file mode 100755 index 00000000..35614c98 --- /dev/null +++ b/rce/make/tools/replace.pl @@ -0,0 +1,23 @@ +#!/usr/bin/perl + +# Check number of arguments +if($#ARGV < 2){ + print STDERR "Usage: $0 <srcstring> <dststring> <files>\n"; + exit; +} + +$srcstring = shift @ARGV; +$dststring = shift @ARGV; + +foreach $srcfile (@ARGV) { + open (SRCFILE, "<$srcfile") or die "Can't open $srcfile: $!\n"; + $dstfile = "$srcfile.replace"; + open (DSTFILE, ">$dstfile") or die "Can't open $dstfile: $!\n"; + while (<SRCFILE>) { + s/$srcstring/$dststring/g; + print DSTFILE; + } + close SRCFILE; + close DSTFILE; + rename $dstfile, $srcfile; +} diff --git a/rce/pixelrce/config/FEI3/IPCModule.cc b/rce/pixelrce/config/FEI3/IPCModule.cc new file mode 100644 index 00000000..dc2e50fb --- /dev/null +++ b/rce/pixelrce/config/FEI3/IPCModule.cc @@ -0,0 +1,203 @@ +#ifndef FEI3__IPCMODULE_CC +#define FEI3__IPCMODULE_CC +#include "util/RceName.hh" +#include "config/FEI3/IPCModule.hh" +#include "ipc/partition.h" +#include "ers/ers.h" +#include <boost/lexical_cast.hpp> + +namespace FEI3{ + +template <class TP> +IPCModule<TP>::IPCModule(IPCPartition & p, const char * name, unsigned id, unsigned inlink, unsigned outlink, AbsFormatter* fmt): + IPCNamedObject<POA_ipc::IPCFEI3Adapter, TP>( p, std::string(boost::lexical_cast<std::string>(id)+"_RCE"+boost::lexical_cast<std::string>(RceName::getRceNumber())).c_str()) , + Module(name, id, inlink, outlink, fmt){ + // std::cout<<"IPCModule"<<std::endl; + try { + IPCNamedObject<POA_ipc::IPCFEI3Adapter,TP>::publish(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } +} + +template <class TP> +IPCModule<TP>::~IPCModule(){ + try { + IPCNamedObject<POA_ipc::IPCFEI3Adapter,TP>::withdraw(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::warning( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } +} + +template <class TP> +CORBA::Long IPCModule<TP>::IPCdownloadConfig(const ipc::PixelModuleConfig &legacyModuleConfig){ + m_mcc.setRegister(Mcc::MCC_LV1,legacyModuleConfig.MCCRegisters.regLV1); + m_mcc.setRegister(Mcc::MCC_CSR,legacyModuleConfig.MCCRegisters.regCSR); + m_mcc.setRegister(Mcc::MCC_CAL,legacyModuleConfig.MCCRegisters.regCAL); + m_mcc.setRegister(Mcc::MCC_FEEN,legacyModuleConfig.maskEnableFEConfig); + + const ipc::PixelFEConfig *legacyFEConfig; + const ipc::PixelFETrims *legacyFETrims; + const ipc::PixelFEMasks *legacyFEMasks; + for(int chip=0;chip<N_FRONTENDS;++chip) { + m_frontend[chip]->setChipAddress(chip, legacyModuleConfig.FEConfig[chip].FEIndex); + legacyFEConfig = &legacyModuleConfig.FEConfig[chip]; + legacyFETrims = &legacyFEConfig->FETrims; + legacyFEMasks = &legacyFEConfig->FEMasks; + + globalLegacyToUsr(legacyFEConfig, chip); + + m_frontend[chip]->setVcalCoeff(0, legacyFEConfig->FECalib.vcalCoeff[0]); + m_frontend[chip]->setVcalCoeff(1, legacyFEConfig->FECalib.vcalCoeff[1]); + m_frontend[chip]->setVcalCoeff(2, legacyFEConfig->FECalib.vcalCoeff[2]); + m_frontend[chip]->setVcalCoeff(3, legacyFEConfig->FECalib.vcalCoeff[3]); + m_frontend[chip]->setCapVal(0, legacyFEConfig->FECalib.cinjLo); + m_frontend[chip]->setCapVal(1, legacyFEConfig->FECalib.cinjHi); + + for(int col=0;col<Frontend::N_COLS;++col) { + for(int row=0;row<Frontend::N_ROWS;++row) { + unsigned char tdac = legacyFETrims->dacThresholdTrim[row][col]; + unsigned char fdac = legacyFETrims->dacFeedbackTrim[row][col]; + unsigned mask = (1 << (row & 0x1f)); + unsigned char enable = (legacyFEMasks->maskEnable[row >> 5][col] & mask) ? 1 : 0; + unsigned char select = (legacyFEMasks->maskSelect[row >> 5][col] & mask) ? 1 : 0; + unsigned char kill = (legacyFEMasks->maskPreamp[row >> 5][col] & mask) ? 1 : 0; + unsigned char hitbus = (legacyFEMasks->maskHitbus[row >> 5][col] & mask) ? 1 : 0; + PixelRegister* pixel=m_frontend[chip]->getPixelRegister(col,row); + pixel->setField(PixelRegister::tdac, tdac); + pixel->setField(PixelRegister::fdac, fdac); + pixel->setField(PixelRegister::enable, enable); + pixel->setField(PixelRegister::select, select); + pixel->setField(PixelRegister::kill, kill); + pixel->setField(PixelRegister::hitbus, hitbus); + } + } + } + std::cout<<"Configure done"<<std::endl; + return 0; +} +template <class TP> +void IPCModule<TP>::globalLegacyToUsr(const ipc::PixelFEConfig* legacyFE, unsigned chip){ + + const ipc::PixelFEGlobal *feGlobal; + feGlobal = &legacyFE->FEGlobal; + + m_frontend[chip]->setGlobalRegField("latency", feGlobal->latency); + m_frontend[chip]->setGlobalRegField("selfTriggerDelay", feGlobal->selfLatency); + m_frontend[chip]->setGlobalRegField("selfTriggerWidth", feGlobal->selfWidth); + m_frontend[chip]->setGlobalRegField("enableSelfTrigger", feGlobal->enableSelfTrigger); + m_frontend[chip]->setGlobalRegField("enableHitParity", feGlobal->enableHitParity); + m_frontend[chip]->setGlobalRegField("doMux", feGlobal->muxDO); + m_frontend[chip]->setGlobalRegField("selectMonHit", feGlobal->muxMonHit); + m_frontend[chip]->setGlobalRegField("tsiTscEnable", feGlobal->enableTimestamp); + + m_frontend[chip]->setGlobalRegField("selectDataPhase", 0); /* previously spare */ + m_frontend[chip]->setGlobalRegField("enableEOEParity", 0); /* previously spare */ + + m_frontend[chip]->setGlobalRegField("hitBusScaler", 0); /* read-only */ + + m_frontend[chip]->setGlobalRegField("monLeakADCRefTest", feGlobal->monADCRef); + m_frontend[chip]->setGlobalRegField("monLeakADCDAC", feGlobal->dacMonLeakADC); + m_frontend[chip]->setGlobalRegField("monLeakDACTest", feGlobal->monMonLeakADC); + m_frontend[chip]->setGlobalRegField("monLeakADCEnableComparator", feGlobal->enableMonLeak); + m_frontend[chip]->setGlobalRegField("monLeakADCMonComp", 0); /* status */ + m_frontend[chip]->setGlobalRegField("aRegTrim", feGlobal->aregTrim); + m_frontend[chip]->setGlobalRegField("enableARegMeas", feGlobal->enableAregMeas); + m_frontend[chip]->setGlobalRegField("aRegMeas", feGlobal->aregMeas); + m_frontend[chip]->setGlobalRegField("enableAReg", feGlobal->enableAreg); + m_frontend[chip]->setGlobalRegField("enableLVDSRefMeas", feGlobal->enableLvdsRegMeas); + m_frontend[chip]->setGlobalRegField("dRegTrim", feGlobal->dregTrim); + m_frontend[chip]->setGlobalRegField("enableDRegMeas", feGlobal->enableDregMeas); + m_frontend[chip]->setGlobalRegField("dRegMeas", feGlobal->dregMeas); + m_frontend[chip]->setGlobalRegField("capMeasCircuitry", feGlobal->capMeasure); + + m_frontend[chip]->setGlobalRegField("enableCapTest", feGlobal->enableCapTest); + m_frontend[chip]->setGlobalRegField("enableAnalogOut", feGlobal->enableBuffer); + m_frontend[chip]->setGlobalRegField("enableTestPixelMux", feGlobal->muxTestPixel); + m_frontend[chip]->setGlobalRegField("enableVCalMeas", feGlobal->enableVcalMeasure); + m_frontend[chip]->setGlobalRegField("enableLeakMeas", feGlobal->enableLeakMeasure); + m_frontend[chip]->setGlobalRegField("enableBufferBoost", feGlobal->enableBufferBoost); + + m_frontend[chip]->setGlobalRegField("enableCP8", feGlobal->enableCP8); + m_frontend[chip]->setGlobalRegField("testDacForIVDD2Dac", feGlobal->monIVDD2); + m_frontend[chip]->setGlobalRegField("dacIVDD2", feGlobal->dacIVDD2); + m_frontend[chip]->setGlobalRegField("dacID", feGlobal->dacID); + m_frontend[chip]->setGlobalRegField("testDacForIDDac", feGlobal->monID); + + m_frontend[chip]->setGlobalRegField("enableCP7", feGlobal->enableCP7); + m_frontend[chip]->setGlobalRegField("testDacForIP2Dac", feGlobal->monIP2); + m_frontend[chip]->setGlobalRegField("dacIP2", feGlobal->dacIP2); + m_frontend[chip]->setGlobalRegField("dacIP", feGlobal->dacIP); + m_frontend[chip]->setGlobalRegField("testDacForIPDac", feGlobal->monIP); + + m_frontend[chip]->setGlobalRegField("enableCP6", feGlobal->enableCP6); + m_frontend[chip]->setGlobalRegField("testDacForITrimThDac", feGlobal->monITRIMTH); + m_frontend[chip]->setGlobalRegField("dacITRIMTH", feGlobal->dacITRIMTH); + m_frontend[chip]->setGlobalRegField("dacIF", feGlobal->dacIF); + m_frontend[chip]->setGlobalRegField("testDacForIFDac", feGlobal->monIF); + + m_frontend[chip]->setGlobalRegField("enableCP5", feGlobal->enableCP5); + m_frontend[chip]->setGlobalRegField("testDacForITrimIfDac", feGlobal->monITRIMIF); + m_frontend[chip]->setGlobalRegField("dacITRIMIF", feGlobal->dacITRIMIF); + m_frontend[chip]->setGlobalRegField("dacVCAL", feGlobal->dacVCAL); + m_frontend[chip]->setGlobalRegField("testDacForVCalDac", feGlobal->monVCAL); + + m_frontend[chip]->setGlobalRegField("enableCP4", feGlobal->enableCP4); + m_frontend[chip]->setGlobalRegField("enableCinjHigh", feGlobal->enableCinjHigh); + m_frontend[chip]->setGlobalRegField("enableExternalInj", feGlobal->enableExternal); + m_frontend[chip]->setGlobalRegField("enableTestAnalogRef", feGlobal->enableTestAnalogRef); + m_frontend[chip]->setGlobalRegField("eocMux", feGlobal->muxEOC); + m_frontend[chip]->setGlobalRegField("CEUClockControl", feGlobal->frequencyCEU); + + m_frontend[chip]->setGlobalRegField("enableDigitalInject", feGlobal->enableDigital); + m_frontend[chip]->setGlobalRegField("enableCP3", feGlobal->enableCP3); + m_frontend[chip]->setGlobalRegField("testDacForITH1Dac", feGlobal->monITH1); + m_frontend[chip]->setGlobalRegField("dacITH1", feGlobal->dacITH1); + m_frontend[chip]->setGlobalRegField("dacITH2", feGlobal->dacITH2); + m_frontend[chip]->setGlobalRegField("testDacForITH2Dac", feGlobal->monITH2); + + m_frontend[chip]->setGlobalRegField("enableCP2", feGlobal->enableCP2); + m_frontend[chip]->setGlobalRegField("testDacILDac", feGlobal->monIL); + m_frontend[chip]->setGlobalRegField("dacIL", feGlobal->dacIL); + m_frontend[chip]->setGlobalRegField("dacIL2", feGlobal->dacIL2); + m_frontend[chip]->setGlobalRegField("testDacIL2Dac", feGlobal->monIL2); + + m_frontend[chip]->setGlobalRegField("enableCP1", feGlobal->enableCP1); + m_frontend[chip]->setGlobalRegField("threshTOTMinimum", feGlobal->threshTOTMinimum); + m_frontend[chip]->setGlobalRegField("threshTOTDouble", feGlobal->threshTOTDouble); + m_frontend[chip]->setGlobalRegField("modeTOTThresh", feGlobal->modeTOTThresh); + + m_frontend[chip]->setGlobalRegField("enableCP0", feGlobal->enableCP0); + m_frontend[chip]->setGlobalRegField("enableHitbus", feGlobal->enableHitbus); + m_frontend[chip]->setGlobalRegField("gTDac", feGlobal->gdac); + m_frontend[chip]->setGlobalRegField("enableTune", feGlobal->enableTune); + m_frontend[chip]->setGlobalRegField("enableBiasComp", feGlobal->enableBiasComp); + m_frontend[chip]->setGlobalRegField("enableIpMonitor", feGlobal->enableIpMonitor); +} + +template <class TP> +void IPCModule<TP>::shutdown(){ + std::cout<<"Shutdown"<<std::endl; +} + +template <class TP> +void IPCModule<TP>::destroy(){ + this->_destroy(); +} + + + +}; + +#endif diff --git a/rce/pixelrce/config/FEI3/IPCModule.hh b/rce/pixelrce/config/FEI3/IPCModule.hh new file mode 100644 index 00000000..a93971ad --- /dev/null +++ b/rce/pixelrce/config/FEI3/IPCModule.hh @@ -0,0 +1,27 @@ +#ifndef IPCFEI3MODULE_HH +#define IPCFEI3MODULE_HH + +#include "config/FEI3/Module.hh" +#include "ipc/object.h" +#include "PixelModuleConfig.hh" +#include "IPCFEI3Adapter.hh" + +class IPCPartition; +class AbsFormatter; + +namespace FEI3{ +template <class TP = ipc::single_thread> +class IPCModule: public IPCNamedObject<POA_ipc::IPCFEI3Adapter,TP>, public FEI3::Module { +public: + IPCModule(IPCPartition & p, const char * name, unsigned id, unsigned inlink, unsigned outlink, AbsFormatter* fmt); + ~IPCModule(); + CORBA::Long IPCdownloadConfig(const ipc::PixelModuleConfig &config); + void globalLegacyToUsr(const ipc::PixelFEConfig* legacy, unsigned chip); + void shutdown(); + void destroy(); + +}; +}; + + +#endif diff --git a/rce/pixelrce/config/FEI4/IPCFEI4AModule.cc b/rce/pixelrce/config/FEI4/IPCFEI4AModule.cc new file mode 100644 index 00000000..9ccf44da --- /dev/null +++ b/rce/pixelrce/config/FEI4/IPCFEI4AModule.cc @@ -0,0 +1,314 @@ +#ifndef FEI4__IPCMODULE_CC +#define FEI4__IPCMODULE_CC +#include "util/RceName.hh" +#include "config/FEI4/IPCFEI4AModule.hh" +#include "config/FEI4/FECommands.hh" +#include <boost/property_tree/ptree.hpp> +#include "HW/SerialIF.hh" +#include "ipc/partition.h" +#include "ers/ers.h" +#include <boost/lexical_cast.hpp> + +namespace FEI4{ + +template <class TP> +IPCFEI4AModule<TP>::IPCFEI4AModule(IPCPartition & p, const char * name, unsigned id, unsigned inLink, unsigned outLink, AbsFormatter* fmt): + IPCNamedObject<POA_ipc::IPCFEI4AAdapter, TP>( p, std::string(boost::lexical_cast<std::string>(id)+"_RCE"+boost::lexical_cast<std::string>(RceName::getRceNumber())).c_str()) , + FEI4AModule(name, id, inLink, outLink, fmt){ + // std::cout<<"IPCFEI4AModule"<<std::endl; + try { + IPCNamedObject<POA_ipc::IPCFEI4AAdapter,TP>::publish(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } +} + +template <class TP> +IPCFEI4AModule<TP>::~IPCFEI4AModule(){ + try { + IPCNamedObject<POA_ipc::IPCFEI4AAdapter,TP>::withdraw(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::warning( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } +} + +template <class TP> +void IPCFEI4AModule<TP>::IPCsetChipAddress(CORBA::ULong addr){ + m_commands->setAddr(addr); +} +template <class TP> +CORBA::Long IPCFEI4AModule<TP>::IPCverifyModuleConfigHW(){ + return verifyModuleConfigHW(); +} +template <class TP> +CORBA::Long IPCFEI4AModule<TP>::IPCdownloadConfig(const ipc::PixelFEI4AConfig &config){ + // geographical address + m_gAddr=config.FECommand.address; + m_commands->setAddr(m_gAddr); + + + const ipc::PixelFEI4AGlobal *cfg=&config.FEGlobal; + // global register + m_global->setField("TrigCnt", cfg->TrigCnt , GlobalRegister::SW); + m_global->setField("Conf_AddrEnable", cfg->Conf_AddrEnable , GlobalRegister::SW); + m_global->setField("Reg2Spare", cfg->Reg2Spare , GlobalRegister::SW); + m_global->setField("ErrMask0", cfg->ErrMask0 , GlobalRegister::SW); + m_global->setField("ErrMask1", cfg->ErrMask1 , GlobalRegister::SW); + m_global->setField("PrmpVbpRight", cfg->PrmpVbpRight , GlobalRegister::SW); + m_global->setField("Vthin", cfg->Vthin , GlobalRegister::SW); + m_global->setField("DisVbn_CPPM", cfg->DisVbn_CPPM , GlobalRegister::SW); + m_global->setField("PrmpVbp", cfg->PrmpVbp , GlobalRegister::SW); + m_global->setField("TdacVbp", cfg->TdacVbp , GlobalRegister::SW); + m_global->setField("DisVbn", cfg->DisVbn , GlobalRegister::SW); + m_global->setField("Amp2Vbn", cfg->Amp2Vbn , GlobalRegister::SW); + m_global->setField("Amp2VbpFol", cfg->Amp2VbpFol , GlobalRegister::SW); + m_global->setField("PrmpVbpTop", cfg->PrmpVbpTop , GlobalRegister::SW); + m_global->setField("Amp2Vbp", cfg->Amp2Vbp , GlobalRegister::SW); + m_global->setField("FdacVbn", cfg->FdacVbn , GlobalRegister::SW); + m_global->setField("Amp2Vbpf", cfg->Amp2Vbpf , GlobalRegister::SW); + m_global->setField("PrmpVbnFol", cfg->PrmpVbnFol , GlobalRegister::SW); + m_global->setField("PrmpVbpLeft", cfg->PrmpVbpLeft , GlobalRegister::SW); + m_global->setField("PrmpVbpf", cfg->PrmpVbpf , GlobalRegister::SW); + m_global->setField("PrmpVbnLcc", cfg->PrmpVbnLcc , GlobalRegister::SW); + m_global->setField("PxStrobes", cfg->PxStrobes , GlobalRegister::SW); + m_global->setField("S0", cfg->S0 , GlobalRegister::SW); + m_global->setField("S1", cfg->S1 , GlobalRegister::SW); + m_global->setField("LVDSDrvIref", cfg->LVDSDrvIref , GlobalRegister::SW); + m_global->setField("BonnDac", cfg->BonnDac , GlobalRegister::SW); + m_global->setField("PllIbias", cfg->PllIbias , GlobalRegister::SW); + m_global->setField("LVDSDrvVos", cfg->LVDSDrvVos , GlobalRegister::SW); + m_global->setField("TempSensBias", cfg->TempSensBias , GlobalRegister::SW); + m_global->setField("PllIcp", cfg->PllIcp , GlobalRegister::SW); + m_global->setField("Reg17Spare", cfg->Reg17Spare , GlobalRegister::SW); + m_global->setField("PlsrIdacRamp", cfg->PlsrIdacRamp , GlobalRegister::SW); + m_global->setField("Reg18Spare", cfg->Reg18Spare , GlobalRegister::SW); + m_global->setField("PlsrVgOPamp", cfg->PlsrVgOPamp , GlobalRegister::SW); + m_global->setField("PlsrDacBias", cfg->PlsrDacBias , GlobalRegister::SW); + m_global->setField("Reg19Spare", cfg->Reg19Spare , GlobalRegister::SW); + m_global->setField("Vthin_AltCoarse", cfg->Vthin_AltCoarse , GlobalRegister::SW); + m_global->setField("Vthin_AltFine", cfg->Vthin_AltFine , GlobalRegister::SW); + m_global->setField("PlsrDAC", cfg->PlsrDAC , GlobalRegister::SW); + m_global->setField("DIGHITIN_Sel", cfg->DIGHITIN_Sel , GlobalRegister::SW); + m_global->setField("DINJ_Override", cfg->DINJ_Override , GlobalRegister::SW); + m_global->setField("HITLD_In", cfg->HITLD_In , GlobalRegister::SW); + m_global->setField("Reg21Spare", cfg->Reg21Spare , GlobalRegister::SW); + m_global->setField("Reg22Spare2", cfg->Reg22Spare2 , GlobalRegister::SW); + m_global->setField("Colpr_Addr", cfg->Colpr_Addr , GlobalRegister::SW); + m_global->setField("Colpr_Mode", cfg->Colpr_Mode , GlobalRegister::SW); + m_global->setField("DisableColumnCnfg0", cfg->DisableColumnCnfg0 , GlobalRegister::SW); + m_global->setField("DisableColumnCnfg1", cfg->DisableColumnCnfg1 , GlobalRegister::SW); + m_global->setField("DisableColumnCnfg2", cfg->DisableColumnCnfg2 , GlobalRegister::SW); + m_global->setField("TrigLat", cfg->TrigLat , GlobalRegister::SW); + m_global->setField("CMDcnt", cfg->CMDcnt , GlobalRegister::SW); + m_global->setField("StopModeCnfg", cfg->StopModeCnfg , GlobalRegister::SW); + m_global->setField("HitDiscCnfg", cfg->HitDiscCnfg , GlobalRegister::SW); + m_global->setField("EN_PLL", cfg->EN_PLL , GlobalRegister::SW); + m_global->setField("Efuse_sense", cfg->Efuse_sense , GlobalRegister::SW); + m_global->setField("Stop_Clk", cfg->Stop_Clk , GlobalRegister::SW); + m_global->setField("ReadErrorReq", cfg->ReadErrorReq , GlobalRegister::SW); + m_global->setField("ReadSkipped", cfg->ReadSkipped , GlobalRegister::SW); + m_global->setField("Reg27Spare", cfg->Reg27Spare , GlobalRegister::SW); + m_global->setField("GateHitOr", cfg->GateHitOr , GlobalRegister::SW); + m_global->setField("CalEn", cfg->CalEn , GlobalRegister::SW); + m_global->setField("SR_clr", cfg->SR_clr , GlobalRegister::SW); + m_global->setField("Latch_en", cfg->Latch_en , GlobalRegister::SW); + m_global->setField("SR_Clock", cfg->SR_Clock , GlobalRegister::SW); + m_global->setField("LVDSDrvSet06", cfg->LVDSDrvSet06 , GlobalRegister::SW); + m_global->setField("Reg28Spare", cfg->Reg28Spare , GlobalRegister::SW); + m_global->setField("EN40M", cfg->EN40M , GlobalRegister::SW); + m_global->setField("EN80M", cfg->EN80M , GlobalRegister::SW); + m_global->setField("CLK1", cfg->CLK1 , GlobalRegister::SW); + m_global->setField("CLK0", cfg->CLK0 , GlobalRegister::SW); + m_global->setField("EN160M", cfg->EN160M , GlobalRegister::SW); + m_global->setField("EN320M", cfg->EN320M , GlobalRegister::SW); + m_global->setField("Reg29Spare1", cfg->Reg29Spare1 , GlobalRegister::SW); + m_global->setField("no8b10b", cfg->no8b10b , GlobalRegister::SW); + m_global->setField("Clk2OutCnfg", cfg->Clk2OutCnfg , GlobalRegister::SW); + m_global->setField("EmptyRecord", cfg->EmptyRecord , GlobalRegister::SW); + m_global->setField("Reg29Spare2", cfg->Reg29Spare2 , GlobalRegister::SW); + m_global->setField("LVDSDrvEn", cfg->LVDSDrvEn , GlobalRegister::SW); + m_global->setField("LVDSDrvSet30", cfg->LVDSDrvSet30 , GlobalRegister::SW); + m_global->setField("LVDSDrvSet12", cfg->LVDSDrvSet12 , GlobalRegister::SW); + m_global->setField("PlsrRiseUpTau", cfg->PlsrRiseUpTau , GlobalRegister::SW); + m_global->setField("PlsrPwr", cfg->PlsrPwr , GlobalRegister::SW); + m_global->setField("PlsrDelay", cfg->PlsrDelay , GlobalRegister::SW); + m_global->setField("ExtDigCalSW", cfg->ExtDigCalSW , GlobalRegister::SW); + m_global->setField("ExtAnaCalSW", cfg->ExtAnaCalSW , GlobalRegister::SW); + m_global->setField("Reg31Spare", cfg->Reg31Spare , GlobalRegister::SW); + m_global->setField("SELB0", cfg->SELB0 , GlobalRegister::SW); + m_global->setField("SELB1", cfg->SELB1 , GlobalRegister::SW); + m_global->setField("SELB2", cfg->SELB2 , GlobalRegister::SW); + m_global->setField("EfuseCref", cfg->EfuseCref , GlobalRegister::SW); + m_global->setField("Chip_SN", cfg->Chip_SN , GlobalRegister::SW); + + setVcalCoeff(0, config.FECalib.vcalCoeff[0]); + setVcalCoeff(1, config.FECalib.vcalCoeff[1]); + setVcalCoeff(2, config.FECalib.vcalCoeff[2]); + setVcalCoeff(3, config.FECalib.vcalCoeff[3]); + setCapVal(0, config.FECalib.cinjLo); + setCapVal(1, config.FECalib.cinjHi); + + + for(int i=0;i<ipc::IPC_N_I4_PIXEL_COLUMNS;i++){ + for(int j=0;j<ipc::IPC_N_I4_PIXEL_ROWS;j++){ + //Pixel DACs + m_pixel->setField(PixelRegister::tdac, j+1, i+1, config.FETrims.dacThresholdTrim[i][j]); + m_pixel->setField(PixelRegister::fdac, j+1, i+1, config.FETrims.dacFeedbackTrim[i][j]); + //Mask bits + m_pixel->setField(PixelRegister::enable, j+1, i+1, config.FEMasks[i][j]>>ipc::enable); + m_pixel->setField(PixelRegister::largeCap, j+1, i+1, config.FEMasks[i][j]>>ipc::largeCap); + m_pixel->setField(PixelRegister::smallCap, j+1, i+1, config.FEMasks[i][j]>>ipc::smallCap); + m_pixel->setField(PixelRegister::hitbus, j+1, i+1, config.FEMasks[i][j]>>ipc::hitbus); + } + } + // Configure the formatter + boost::property_tree::ptree *pt=new boost::property_tree::ptree; + pt->put("HitDiscCnfg",cfg->HitDiscCnfg); + AbsFormatter* fmt=getFormatter(); + if(fmt){ + std::cout<<"%%%%%%%%% Configuring Formatter"<<std::endl; + fmt->configure(pt); + } + delete pt; + + std::cout<<"Configure done"<<std::endl; + //dumpConfig(); + return 0; +} + +template <class TP> +CORBA::ULong IPCFEI4AModule<TP>::IPCwriteHWglobalRegister(CORBA::Long reg, CORBA::UShort val){ + switchModeHW(FECommands::CONF); + SerialIF::setChannelInMask(1<<getInLink()); + SerialIF::setChannelOutMask(1<<getOutLink()); + return m_global->writeRegisterHW(reg, val); +} + +template <class TP> +CORBA::ULong IPCFEI4AModule<TP>::IPCreadHWglobalRegister(CORBA::Long reg, CORBA::UShort &val){ + SerialIF::setChannelInMask(1<<getInLink()); + SerialIF::setChannelOutMask(1<<getOutLink()); + return m_global->readRegisterHW(reg, val); +} +template <class TP> +CORBA::ULong IPCFEI4AModule<TP>::IPCclearPixelLatches(){ + SerialIF::setChannelInMask(1<<getInLink()); + // choose double column + m_global->setField("Colpr_Addr", 0, GlobalRegister::SW); + m_global->setField("Colpr_Mode", 3, GlobalRegister::HW); // all columns + setupS0S1HitldHW(0, 0, 0); + setupGlobalPulseHW(GlobalRegister::SR_clr); //latch enable + BitStream *bs=new BitStream; + m_commands->globalPulse(bs, FECommands::PULSE_WIDTH); + bs->push_back(0); + SerialIF::send(bs, SerialIF::DONT_CLEAR); //global pulse + //now clear latches + setupGlobalPulseHW(GlobalRegister::Latch_en); //latch enable + setupPixelStrobesHW(0x1fff); + SerialIF::send(bs, SerialIF::DONT_CLEAR); //global pulse + setupPixelStrobesHW(0);//clear register + setupGlobalPulseHW(0); //clear register + delete bs; + return 0; +} + + // Function to be called directly from Linux for debugging purposes. +template <class TP> +CORBA::ULong IPCFEI4AModule<TP>::IPCwriteDoubleColumnHW(CORBA::ULong bit, CORBA::ULong dcol, const ipc::uvec & data, ipc::uvec_out retv){ + // clear pixel latches + //IPCclearPixelLatches(); + //retv=new ipc::uvec; + //return 0; + SerialIF::setChannelInMask(1<<getInLink()); + SerialIF::setChannelOutMask(1<<getOutLink()); + std::vector<unsigned> retvec; + + if(data.length()!=PixelRegister::DROW_WORDS)return BAD_SIZE; //wrong amount of data + if(bit>=PixelRegister::N_PIXEL_REGISTER_BITS)return BAD_PIXREG; + + switchModeHW(FECommands::CONF); + + // choose double column + m_global->setField("Colpr_Addr", dcol, GlobalRegister::SW); + m_global->setField("Colpr_Mode", 0, GlobalRegister::HW); // only write to 1 column pair + setupS0S1HitldHW(0, 0, 0); + unsigned stat=m_pixel->writeDoubleColumnHW((const unsigned*)&data[0], retvec); + if(bit!=PixelRegisterFields::fieldPos[PixelRegister::diginj]){ //no latching for diginj + setupGlobalPulseHW(GlobalRegister::Latch_en); //latch enable + //set up strobe bit + setupPixelStrobesHW(1<<bit); + BitStream *bs=new BitStream; + m_commands->globalPulse(bs, FECommands::PULSE_WIDTH); + bs->push_back(0); + SerialIF::send(bs); //global pulse + delete bs; + setupGlobalPulseHW(0); //clear + setupPixelStrobesHW(0); //clear + } + retv=new ipc::uvec; + retv->length(retvec.size()); + for(size_t i=0;i<retvec.size();i++)retv[i]=(CORBA::ULong)retvec[i]; + return stat; +} + + // Function to be called directly from Linux for debugging purposes. +template <class TP> +CORBA::ULong IPCFEI4AModule<TP>::IPCreadDoubleColumnHW(CORBA::ULong bit, CORBA::ULong dcol, ipc::uvec_out retv){ + SerialIF::setChannelInMask(1<<getInLink()); + SerialIF::setChannelOutMask(1<<getOutLink()); + std::vector<unsigned> retvec; + if(bit>=PixelRegister::N_PIXEL_REGISTER_BITS)return BAD_PIXREG; + if(dcol>=PixelRegister::N_COLS/2)return BAD_DCOL; + // set config mode + switchModeHW(FECommands::CONF); + // choose double column + m_global->setField("Colpr_Addr", dcol, GlobalRegister::SW); + m_global->setField("Colpr_Mode", 0, GlobalRegister::HW); // only write to 1 column pair + if(bit!=PixelRegisterFields::fieldPos[PixelRegister::diginj]){ //no latching for diginj + setupS0S1HitldHW(1, 1, 0); + setupGlobalPulseHW(GlobalRegister::SR_Clock); //SR clock + //set up strobe bit + setupPixelStrobesHW(1<<bit); + BitStream *bs=new BitStream; + bs->push_back(0); + m_commands->globalPulse(bs, FECommands::PULSE_WIDTH); + SerialIF::send(bs); //global pulse + delete bs; + } + //shift out bits and refill with config register. + setupGlobalPulseHW(0); //clear + setupPixelStrobesHW(0); //clear + setupS0S1HitldHW(0, 0, 0); + unsigned stat=m_pixel->writeDoubleColumnHW((const unsigned*)m_pixel->getDoubleColumn(bit, dcol), retvec); + retv=new ipc::uvec; + retv->length(retvec.size()); + for(size_t i=0;i<retvec.size();i++)retv[i]=(CORBA::ULong)retvec[i]; + return stat; +} + +template <class TP> +void IPCFEI4AModule<TP>::shutdown(){ + std::cout<<"Shutdown"<<std::endl; +} + +template <class TP> +void IPCFEI4AModule<TP>::destroy(){ + this->_destroy(); +} + + + +}; + +#endif diff --git a/rce/pixelrce/config/FEI4/IPCFEI4AModule.hh b/rce/pixelrce/config/FEI4/IPCFEI4AModule.hh new file mode 100644 index 00000000..ee303b98 --- /dev/null +++ b/rce/pixelrce/config/FEI4/IPCFEI4AModule.hh @@ -0,0 +1,32 @@ +#ifndef IPCFEI4AMODULE_HH +#define IPCFEI4AMODULE_HH + +#include "config/FEI4/FEI4AModule.hh" +#include "ipc/object.h" +#include "IPCFEI4AAdapter.hh" + +class IPCPartition; +class AbsFormatter; + +namespace FEI4{ +template <class TP = ipc::single_thread> +class IPCFEI4AModule: public IPCNamedObject<POA_ipc::IPCFEI4AAdapter,TP>, public FEI4::FEI4AModule { +public: + IPCFEI4AModule(IPCPartition & p, const char * name, unsigned id, unsigned inLink, unsigned outLink, AbsFormatter* fmt); + ~IPCFEI4AModule(); + CORBA::Long IPCdownloadConfig(const ipc::PixelFEI4AConfig &config); + void IPCsetChipAddress(CORBA::ULong addr); + CORBA::ULong IPCwriteHWglobalRegister(CORBA::Long reg, CORBA::UShort val); + CORBA::ULong IPCreadHWglobalRegister(CORBA::Long reg, CORBA::UShort &val); + CORBA::ULong IPCwriteDoubleColumnHW(CORBA::ULong bit, CORBA::ULong dcol, const ipc::uvec & data, ipc::uvec_out retv); + CORBA::ULong IPCreadDoubleColumnHW(CORBA::ULong bit, CORBA::ULong dcol, ipc::uvec_out retv); + CORBA::ULong IPCclearPixelLatches(); + CORBA::Long IPCverifyModuleConfigHW(); + void shutdown(); + void destroy(); + +}; +}; + + +#endif diff --git a/rce/pixelrce/config/FEI4/IPCFEI4BModule.cc b/rce/pixelrce/config/FEI4/IPCFEI4BModule.cc new file mode 100644 index 00000000..6d6f3d41 --- /dev/null +++ b/rce/pixelrce/config/FEI4/IPCFEI4BModule.cc @@ -0,0 +1,331 @@ +#ifndef FEI4__FEI4BIPCMODULE_CC +#define FEI4__FEI4BIPCMODULE_CC +#include "util/RceName.hh" +#include "config/FEI4/IPCFEI4BModule.hh" +#include "config/FEI4/FECommands.hh" +#include <boost/property_tree/ptree.hpp> +#include "HW/SerialIF.hh" +#include "ipc/partition.h" +#include "ers/ers.h" +#include <boost/lexical_cast.hpp> + + +namespace FEI4{ + +template <class TP> +IPCFEI4BModule<TP>::IPCFEI4BModule(IPCPartition & p, const char * name, unsigned id, unsigned inLink, unsigned outLink, AbsFormatter* fmt): + IPCNamedObject<POA_ipc::IPCFEI4BAdapter, TP>( p, std::string(boost::lexical_cast<std::string>(id)+"_RCE"+boost::lexical_cast<std::string>(RceName::getRceNumber())).c_str()) , + FEI4BModule(name, id, inLink, outLink, fmt){ + // std::cout<<"IPCFEI4BModule"<<std::endl; + try { + IPCNamedObject<POA_ipc::IPCFEI4BAdapter,TP>::publish(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } +} + +template <class TP> +IPCFEI4BModule<TP>::~IPCFEI4BModule(){ + try { + IPCNamedObject<POA_ipc::IPCFEI4BAdapter,TP>::withdraw(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::warning( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } +} + +template <class TP> +void IPCFEI4BModule<TP>::IPCsetChipAddress(CORBA::ULong addr){ + m_commands->setAddr(addr); +} +template <class TP> +CORBA::Long IPCFEI4BModule<TP>::IPCverifyModuleConfigHW(){ + return verifyModuleConfigHW(); +} +template <class TP> +CORBA::Long IPCFEI4BModule<TP>::IPCdownloadConfig(const ipc::PixelFEI4BConfig &config){ + // geographical address + m_gAddr=config.FECommand.address; + m_commands->setAddr(m_gAddr); + + const ipc::PixelFEI4BGlobal *cfg=&config.FEGlobal; + // global register + m_global->setField("TrigCnt", cfg->TrigCnt , GlobalRegister::SW); + m_global->setField("Conf_AddrEnable", cfg->Conf_AddrEnable , GlobalRegister::SW); + m_global->setField("Reg2Spare", cfg->Reg2Spare , GlobalRegister::SW); + m_global->setField("ErrMask0", cfg->ErrMask0 , GlobalRegister::SW); + m_global->setField("ErrMask1", cfg->ErrMask1 , GlobalRegister::SW); + m_global->setField("PrmpVbpRight", cfg->PrmpVbpRight , GlobalRegister::SW); + m_global->setField("BufVgOpAmp", cfg->BufVgOpAmp , GlobalRegister::SW); + m_global->setField("Reg6Spare", cfg->Reg6Spare , GlobalRegister::SW); + m_global->setField("PrmpVbp", cfg->PrmpVbp , GlobalRegister::SW); + m_global->setField("TdacVbp", cfg->TdacVbp , GlobalRegister::SW); + m_global->setField("DisVbn", cfg->DisVbn , GlobalRegister::SW); + m_global->setField("Amp2Vbn", cfg->Amp2Vbn , GlobalRegister::SW); + m_global->setField("Amp2VbpFol", cfg->Amp2VbpFol , GlobalRegister::SW); + m_global->setField("Reg9Spare", cfg->Reg9Spare , GlobalRegister::SW); + m_global->setField("Amp2Vbp", cfg->Amp2Vbp , GlobalRegister::SW); + m_global->setField("FdacVbn", cfg->FdacVbn , GlobalRegister::SW); + m_global->setField("Amp2Vbpf", cfg->Amp2Vbpf , GlobalRegister::SW); + m_global->setField("PrmpVbnFol", cfg->PrmpVbnFol , GlobalRegister::SW); + m_global->setField("PrmpVbpLeft", cfg->PrmpVbpLeft , GlobalRegister::SW); + m_global->setField("PrmpVbpf", cfg->PrmpVbpf , GlobalRegister::SW); + m_global->setField("PrmpVbnLcc", cfg->PrmpVbnLcc , GlobalRegister::SW); + m_global->setField("Reg13Spare", cfg->Reg13Spare , GlobalRegister::SW); + m_global->setField("PxStrobes", cfg->PxStrobes , GlobalRegister::SW); + m_global->setField("S0", cfg->S0 , GlobalRegister::SW); + m_global->setField("S1", cfg->S1 , GlobalRegister::SW); + m_global->setField("LVDSDrvIref", cfg->LVDSDrvIref , GlobalRegister::SW); + m_global->setField("GADCOpAmp", cfg->GADCOpAmp , GlobalRegister::SW); + m_global->setField("PllIbias", cfg->PllIbias , GlobalRegister::SW); + m_global->setField("LVDSDrvVos", cfg->LVDSDrvVos , GlobalRegister::SW); + m_global->setField("TempSensBias", cfg->TempSensBias , GlobalRegister::SW); + m_global->setField("PllIcp", cfg->PllIcp , GlobalRegister::SW); + m_global->setField("Reg17Spare", cfg->Reg17Spare , GlobalRegister::SW); + m_global->setField("PlsrIdacRamp", cfg->PlsrIdacRamp , GlobalRegister::SW); + m_global->setField("VrefDigTune", cfg->VrefDigTune , GlobalRegister::SW); + m_global->setField("PlsrVgOPamp", cfg->PlsrVgOPamp , GlobalRegister::SW); + m_global->setField("PlsrDacBias", cfg->PlsrDacBias , GlobalRegister::SW); + m_global->setField("VrefAnTune", cfg->VrefAnTune , GlobalRegister::SW); + m_global->setField("Vthin_AltCoarse", cfg->Vthin_AltCoarse , GlobalRegister::SW); + m_global->setField("Vthin_AltFine", cfg->Vthin_AltFine , GlobalRegister::SW); + m_global->setField("PlsrDAC", cfg->PlsrDAC , GlobalRegister::SW); + m_global->setField("DIGHITIN_Sel", cfg->DIGHITIN_Sel , GlobalRegister::SW); + m_global->setField("DINJ_Override", cfg->DINJ_Override , GlobalRegister::SW); + m_global->setField("HITLD_In", cfg->HITLD_In , GlobalRegister::SW); + m_global->setField("Reg21Spare", cfg->Reg21Spare , GlobalRegister::SW); + m_global->setField("Reg22Spare2", cfg->Reg22Spare2 , GlobalRegister::SW); + m_global->setField("Colpr_Addr", cfg->Colpr_Addr , GlobalRegister::SW); + m_global->setField("Colpr_Mode", cfg->Colpr_Mode , GlobalRegister::SW); + m_global->setField("Reg22Spare1", cfg->Reg22Spare1 , GlobalRegister::SW); + m_global->setField("DisableColumnCnfg0", cfg->DisableColumnCnfg0 , GlobalRegister::SW); + m_global->setField("DisableColumnCnfg1", cfg->DisableColumnCnfg1 , GlobalRegister::SW); + m_global->setField("DisableColumnCnfg2", cfg->DisableColumnCnfg2 , GlobalRegister::SW); + m_global->setField("TrigLat", cfg->TrigLat , GlobalRegister::SW); + m_global->setField("CMDcnt", cfg->CMDcnt , GlobalRegister::SW); + m_global->setField("StopModeCnfg", cfg->StopModeCnfg , GlobalRegister::SW); + m_global->setField("HitDiscCnfg", cfg->HitDiscCnfg , GlobalRegister::SW); + m_global->setField("EN_PLL", cfg->EN_PLL , GlobalRegister::SW); + m_global->setField("Efuse_sense", cfg->Efuse_sense , GlobalRegister::SW); + m_global->setField("Stop_Clk", cfg->Stop_Clk , GlobalRegister::SW); + m_global->setField("ReadErrorReq", cfg->ReadErrorReq , GlobalRegister::SW); + m_global->setField("Reg27Spare1", cfg->Reg27Spare1 , GlobalRegister::SW); + m_global->setField("GADC_Enable", cfg->GADC_Enable , GlobalRegister::SW); + m_global->setField("ShiftReadBack", cfg->ShiftReadBack , GlobalRegister::SW); + m_global->setField("Reg27Spare2", cfg->Reg27Spare2 , GlobalRegister::SW); + m_global->setField("GateHitOr", cfg->GateHitOr , GlobalRegister::SW); + m_global->setField("CalEn", cfg->CalEn , GlobalRegister::SW); + m_global->setField("SR_clr", cfg->SR_clr , GlobalRegister::SW); + m_global->setField("Latch_en", cfg->Latch_en , GlobalRegister::SW); + m_global->setField("SR_Clock", cfg->SR_Clock , GlobalRegister::SW); + m_global->setField("LVDSDrvSet06", cfg->LVDSDrvSet06 , GlobalRegister::SW); + m_global->setField("Reg28Spare", cfg->Reg28Spare , GlobalRegister::SW); + m_global->setField("EN40M", cfg->EN40M , GlobalRegister::SW); + m_global->setField("EN80M", cfg->EN80M , GlobalRegister::SW); + m_global->setField("CLK1", cfg->CLK1 , GlobalRegister::SW); + m_global->setField("CLK0", cfg->CLK0 , GlobalRegister::SW); + m_global->setField("EN160M", cfg->EN160M , GlobalRegister::SW); + m_global->setField("EN320M", cfg->EN320M , GlobalRegister::SW); + m_global->setField("Reg29Spare1", cfg->Reg29Spare1 , GlobalRegister::SW); + m_global->setField("no8b10b", cfg->no8b10b , GlobalRegister::SW); + m_global->setField("Clk2OutCnfg", cfg->Clk2OutCnfg , GlobalRegister::SW); + m_global->setField("EmptyRecord", cfg->EmptyRecord , GlobalRegister::SW); + m_global->setField("Reg29Spare2", cfg->Reg29Spare2 , GlobalRegister::SW); + m_global->setField("LVDSDrvEn", cfg->LVDSDrvEn , GlobalRegister::SW); + m_global->setField("LVDSDrvSet30", cfg->LVDSDrvSet30 , GlobalRegister::SW); + m_global->setField("LVDSDrvSet12", cfg->LVDSDrvSet12 , GlobalRegister::SW); + m_global->setField("TempSensDiodeSel", cfg->TempSensDiodeSel , GlobalRegister::SW); + m_global->setField("TempSensDisable", cfg->TempSensDisable , GlobalRegister::SW); + m_global->setField("IleakRange", cfg->IleakRange , GlobalRegister::SW); + m_global->setField("Reg30Spare", cfg->Reg30Spare , GlobalRegister::SW); + m_global->setField("PlsrRiseUpTau", cfg->PlsrRiseUpTau , GlobalRegister::SW); + m_global->setField("PlsrPwr", cfg->PlsrPwr , GlobalRegister::SW); + m_global->setField("PlsrDelay", cfg->PlsrDelay , GlobalRegister::SW); + m_global->setField("ExtDigCalSW", cfg->ExtDigCalSW , GlobalRegister::SW); + m_global->setField("ExtAnaCalSW", cfg->ExtAnaCalSW , GlobalRegister::SW); + m_global->setField("Reg31Spare", cfg->Reg31Spare , GlobalRegister::SW); + m_global->setField("GADCSel", cfg->GADCSel , GlobalRegister::SW); + m_global->setField("SELB0", cfg->SELB0 , GlobalRegister::SW); + m_global->setField("SELB1", cfg->SELB1 , GlobalRegister::SW); + m_global->setField("SELB2", cfg->SELB2 , GlobalRegister::SW); + m_global->setField("Reg34Spare1", cfg->Reg34Spare1 , GlobalRegister::SW); + m_global->setField("PrmpVbpMsnEn", cfg->PrmpVbpMsnEn , GlobalRegister::SW); + m_global->setField("Reg34Spare2", cfg->Reg34Spare2 , GlobalRegister::SW); + m_global->setField("Chip_SN", cfg->Chip_SN , GlobalRegister::SW); + m_global->setField("Reg1Spare", cfg->Reg1Spare , GlobalRegister::SW); + m_global->setField("SmallHitErase", cfg->SmallHitErase , GlobalRegister::SW); + m_global->setField("Eventlimit", cfg->Eventlimit , GlobalRegister::SW); + + setVcalCoeff(0, config.FECalib.vcalCoeff[0]); + setVcalCoeff(1, config.FECalib.vcalCoeff[1]); + setVcalCoeff(2, config.FECalib.vcalCoeff[2]); + setVcalCoeff(3, config.FECalib.vcalCoeff[3]); + setCapVal(0, config.FECalib.cinjLo); + setCapVal(1, config.FECalib.cinjHi); + + + for(int i=0;i<ipc::IPC_N_I4_PIXEL_COLUMNS;i++){ + for(int j=0;j<ipc::IPC_N_I4_PIXEL_ROWS;j++){ + //Pixel DACs + m_pixel->setField(PixelRegister::tdac, j+1, i+1, config.FETrims.dacThresholdTrim[i][j]); + m_pixel->setField(PixelRegister::fdac, j+1, i+1, config.FETrims.dacFeedbackTrim[i][j]); + //Mask bits + m_pixel->setField(PixelRegister::enable, j+1, i+1, config.FEMasks[i][j]>>ipc::enable); + m_pixel->setField(PixelRegister::largeCap, j+1, i+1, config.FEMasks[i][j]>>ipc::largeCap); + m_pixel->setField(PixelRegister::smallCap, j+1, i+1, config.FEMasks[i][j]>>ipc::smallCap); + m_pixel->setField(PixelRegister::hitbus, j+1, i+1, config.FEMasks[i][j]>>ipc::hitbus); + } + } + // Configure the formatter + AbsFormatter* fmt=getFormatter(); + if(fmt){ + std::cout<<"%%%%%%%%% Configuring Formatter"<<std::endl; + boost::property_tree::ptree *pt=new boost::property_tree::ptree; + pt->put("HitDiscCnfg",cfg->HitDiscCnfg); + fmt->configure(pt); + delete pt; + } + + std::cout<<"Configure done"<<std::endl; + //dumpConfig(std::cout); + return 0; +} + +template <class TP> +CORBA::ULong IPCFEI4BModule<TP>::IPCwriteHWglobalRegister(CORBA::Long reg, CORBA::UShort val){ + switchModeHW(FECommands::CONF); + SerialIF::setChannelInMask(1<<getInLink()); + SerialIF::setChannelOutMask(1<<getOutLink()); + return m_global->writeRegisterHW(reg, val); +} + +template <class TP> +CORBA::ULong IPCFEI4BModule<TP>::IPCreadHWglobalRegister(CORBA::Long reg, CORBA::UShort &val){ + SerialIF::setChannelInMask(1<<getInLink()); + SerialIF::setChannelOutMask(1<<getOutLink()); + return m_global->readRegisterHW(reg, val); +} +template <class TP> +CORBA::ULong IPCFEI4BModule<TP>::IPCclearPixelLatches(){ + SerialIF::setChannelInMask(1<<getInLink()); + // choose double column + m_global->setField("Colpr_Addr", 0, GlobalRegister::SW); + m_global->setField("Colpr_Mode", 3, GlobalRegister::HW); // all columns + setupS0S1HitldHW(0, 0, 0); + setupGlobalPulseHW(GlobalRegister::SR_clr); //latch enable + BitStream *bs=new BitStream; + m_commands->globalPulse(bs, FECommands::PULSE_WIDTH); + bs->push_back(0); + SerialIF::send(bs, SerialIF::DONT_CLEAR); //global pulse + //now clear latches + setupGlobalPulseHW(GlobalRegister::Latch_en); //latch enable + setupPixelStrobesHW(0x1fff); + SerialIF::send(bs, SerialIF::DONT_CLEAR); //global pulse + setupPixelStrobesHW(0);//clear register + setupGlobalPulseHW(0); //clear register + delete bs; + return 0; +} + + // Function to be called directly from Linux for debugging purposes. +template <class TP> +CORBA::ULong IPCFEI4BModule<TP>::IPCwriteDoubleColumnHW(CORBA::ULong bit, CORBA::ULong dcol, const ipc::uvec & data, ipc::uvec_out retv){ + // clear pixel latches + //IPCclearPixelLatches(); + //retv=new ipc::uvec; + //return 0; + SerialIF::setChannelInMask(1<<getInLink()); + SerialIF::setChannelOutMask(1<<getOutLink()); + std::vector<unsigned> retvec; + + if(data.length()!=PixelRegister::DROW_WORDS)return BAD_SIZE; //wrong amount of data + if(bit>=PixelRegister::N_PIXEL_REGISTER_BITS)return BAD_PIXREG; + + switchModeHW(FECommands::CONF); + + // choose double column + m_global->setField("Colpr_Addr", dcol, GlobalRegister::SW); + m_global->setField("Colpr_Mode", 0, GlobalRegister::HW); // only write to 1 column pair + m_global->setField("ShiftReadBack",0, GlobalRegister::HW); + setupS0S1HitldHW(0, 0, 0); + unsigned stat=m_pixel->writeDoubleColumnHW((const unsigned*)&data[0], retvec); + if(bit!=PixelRegisterFields::fieldPos[PixelRegister::diginj]){ //no latching for diginj + setupGlobalPulseHW(GlobalRegister::Latch_en); //latch enable + //set up strobe bit + setupPixelStrobesHW(1<<bit); + BitStream *bs=new BitStream; + m_commands->globalPulse(bs, FECommands::PULSE_WIDTH); + bs->push_back(0); + SerialIF::send(bs); //global pulse + delete bs; + setupGlobalPulseHW(0); //clear + setupPixelStrobesHW(0); //clear + } + retv=new ipc::uvec; + retv->length(retvec.size()); + for(size_t i=0;i<retvec.size();i++)retv[i]=(CORBA::ULong)retvec[i]; + return stat; +} + + // Function to be called directly from Linux for debugging purposes. +template <class TP> +CORBA::ULong IPCFEI4BModule<TP>::IPCreadDoubleColumnHW(CORBA::ULong bit, CORBA::ULong dcol, ipc::uvec_out retv){ + SerialIF::setChannelInMask(1<<getInLink()); + SerialIF::setChannelOutMask(1<<getOutLink()); + std::vector<unsigned> retvec; + if(bit>=PixelRegister::N_PIXEL_REGISTER_BITS)return BAD_PIXREG; + if(dcol>=PixelRegister::N_COLS/2)return BAD_DCOL; + // set config mode + switchModeHW(FECommands::CONF); + // choose double column + m_global->setField("Colpr_Addr", dcol, GlobalRegister::SW); + m_global->setField("Colpr_Mode", 0, GlobalRegister::HW); // only write to 1 column pair + m_global->setField("ShiftReadBack",1, GlobalRegister::HW); //enable readback + if(bit!=PixelRegisterFields::fieldPos[PixelRegister::diginj]){ //no latching for diginj + setupS0S1HitldHW(1, 1, 0); + setupGlobalPulseHW(GlobalRegister::SR_Clock); //SR clock + //set up strobe bit + setupPixelStrobesHW(1<<bit); + BitStream *bs=new BitStream; + bs->push_back(0); + m_commands->globalPulse(bs, FECommands::PULSE_WIDTH); + SerialIF::send(bs); //global pulse + delete bs; + } + //shift out bits and refill with config register. + m_global->setField("ShiftReadBack",0, GlobalRegister::SW); //setupGlobalPulse does the HW write for that register + setupGlobalPulseHW(0); //clear + setupPixelStrobesHW(0); //clear + setupS0S1HitldHW(0, 0, 0); + unsigned stat=m_pixel->writeDoubleColumnHW((const unsigned*)m_pixel->getDoubleColumn(bit, dcol), retvec); + retv=new ipc::uvec; + retv->length(retvec.size()); + for(size_t i=0;i<retvec.size();i++)retv[i]=(CORBA::ULong)retvec[i]; + return stat; +} + +template <class TP> +void IPCFEI4BModule<TP>::shutdown(){ + std::cout<<"Shutdown"<<std::endl; +} + +template <class TP> +void IPCFEI4BModule<TP>::destroy(){ + this->_destroy(); +} + + + +}; + +#endif diff --git a/rce/pixelrce/config/FEI4/IPCFEI4BModule.hh b/rce/pixelrce/config/FEI4/IPCFEI4BModule.hh new file mode 100644 index 00000000..bac03f8c --- /dev/null +++ b/rce/pixelrce/config/FEI4/IPCFEI4BModule.hh @@ -0,0 +1,32 @@ +#ifndef IPCFEI4BMODULE_HH +#define IPCFEI4BMODULE_HH + +#include "config/FEI4/FEI4BModule.hh" +#include "ipc/object.h" +#include "IPCFEI4BAdapter.hh" + +class IPCPartition; +class AbsFormatter; + +namespace FEI4{ +template <class TP = ipc::single_thread> +class IPCFEI4BModule: public IPCNamedObject<POA_ipc::IPCFEI4BAdapter,TP>, public FEI4::FEI4BModule { +public: + IPCFEI4BModule(IPCPartition & p, const char * name, unsigned id, unsigned inLink, unsigned outLink, AbsFormatter* fmt); + ~IPCFEI4BModule(); + CORBA::Long IPCdownloadConfig(const ipc::PixelFEI4BConfig &config); + void IPCsetChipAddress(CORBA::ULong addr); + CORBA::ULong IPCwriteHWglobalRegister(CORBA::Long reg, CORBA::UShort val); + CORBA::ULong IPCreadHWglobalRegister(CORBA::Long reg, CORBA::UShort &val); + CORBA::ULong IPCwriteDoubleColumnHW(CORBA::ULong bit, CORBA::ULong dcol, const ipc::uvec & data, ipc::uvec_out retv); + CORBA::ULong IPCreadDoubleColumnHW(CORBA::ULong bit, CORBA::ULong dcol, ipc::uvec_out retv); + CORBA::ULong IPCclearPixelLatches(); + CORBA::Long IPCverifyModuleConfigHW(); + void shutdown(); + void destroy(); + +}; +}; + + +#endif diff --git a/rce/pixelrce/config/IPCConfigIF.cc b/rce/pixelrce/config/IPCConfigIF.cc new file mode 100644 index 00000000..ac4ef551 --- /dev/null +++ b/rce/pixelrce/config/IPCConfigIF.cc @@ -0,0 +1,140 @@ +#ifndef IPCCONFIGIF_CC +#define IPCCONFIGIF_CC + +#include "config/IPCConfigIF.hh" + +template <class TP> +IPCConfigIF<TP>::IPCConfigIF(IPCPartition & p, const char * name, ModuleFactory* mf): + IPCNamedObject<POA_ipc::IPCConfigIFAdapter, TP>( p, name ) , ConfigIF(mf){ + try { + IPCNamedObject<POA_ipc::IPCConfigIFAdapter,TP>::publish(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } +} + +template <class TP> +IPCConfigIF<TP>::~IPCConfigIF(){ + try { + IPCNamedObject<POA_ipc::IPCConfigIFAdapter,TP>::withdraw(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::warning( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } +} + +//template <class TP> +//void IPCConfigIF<TP>::IPCsetupParameter(const char* name, CORBA::Long val){ +// setupParameter(name, val); +//} +template <class TP> +CORBA::ULong IPCConfigIF<TP>::IPCsetupParameter(const char* name, CORBA::Long val){ + setupParameter(name, val, false); //do not enable data taking because chip may be unconfigured + return 0; +} +template <class TP> +void IPCConfigIF<TP>::IPCsetupMaskStage(CORBA::Long stage){ + setupMaskStage(stage); +} +template <class TP> +void IPCConfigIF<TP>::IPCsendTrigger(){ + sendTrigger(); +} +template <class TP> +void IPCConfigIF<TP>::IPCenableTrigger(){ + enableTrigger(); +} +template <class TP> +void IPCConfigIF<TP>::IPCdisableTrigger(){ + disableTrigger(); +} +template <class TP> +void IPCConfigIF<TP>::IPCresetFE(){ + resetFE(); +} +template <class TP> +void IPCConfigIF<TP>::IPCconfigureModulesHW(){ + configureModulesHW(); +} +template <class TP> +CORBA::Long IPCConfigIF<TP>::IPCverifyModuleConfigHW(CORBA::Long id){ + return verifyModuleConfigHW(id); +} +template <class TP> +CORBA::ULong IPCConfigIF<TP>::IPCwriteHWregister(CORBA::ULong addr, CORBA::ULong val){ + return writeHWregister(addr,val); +} + +template <class TP> +CORBA::ULong IPCConfigIF<TP>::IPCreadHWregister(CORBA::ULong addr, CORBA::ULong& val){ + return readHWregister(addr, (unsigned int&)val); +} + +template <class TP> +CORBA::ULong IPCConfigIF<TP>::IPCsendHWcommand(CORBA::Octet opcode){ + return sendHWcommand(opcode); +} + +template <class TP> +CORBA::ULong IPCConfigIF<TP>::IPCwriteHWblockData(const ipc::blockdata& data){ + std::vector<unsigned> bldat; + for(size_t i=0;i<data.length();i++)bldat.push_back(data[i]); + return writeHWblockData(bldat); +} + +template <class TP> +CORBA::ULong IPCConfigIF<TP>::IPCreadHWblockData(const ipc::blockdata& data, ipc::blockdata_out retv){ + std::vector<unsigned> bldat; + for(size_t i=0;i<data.length();i++)bldat.push_back(data[i]); + std::vector<unsigned> retvec; + unsigned retval=readHWblockData(bldat, retvec); + retv=new ipc::blockdata; + retv->length(retvec.size()); + for(size_t i=0;i<retvec.size();i++)retv[i]=(CORBA::ULong)retvec[i]; + return retval; +} +template <class TP> +CORBA::ULong IPCConfigIF<TP>::IPCreadHWbuffers(ipc::chardata_out retv){ + std::vector<unsigned char> retvec; + unsigned retval=readHWbuffers(retvec); + retv=new ipc::chardata; + retv->length(retvec.size()); + for(size_t i=0;i<retvec.size();i++)retv[i]=(CORBA::Octet)retvec[i]; + return retval; +} + +template <class TP> +CORBA::Long IPCConfigIF<TP>::IPCnTrigger(){ + return nTrigger(); +} +template <class TP> +CORBA::Long IPCConfigIF<TP>::IPCsetupTriggerIF(const char* type){ + setupTriggerIF(type); + return 0; +} +template <class TP> +CORBA::Long IPCConfigIF<TP>::IPCsetupModule(const char* name, const char* type, const ipc::ModSetup& par, const char* formatter){ + //std::cout<<"IPCsetupModule"<<std::endl; + return setupModule(name, type, par.id, par.inLink, par.outLink, formatter); +} +template <class TP> +CORBA::Long IPCConfigIF<TP>::IPCdeleteModules(){ + deleteModules(); + return 0; +} +template <class TP> +void IPCConfigIF<TP>::shutdown(){ + std::cout<<"Shutdown"<<std::endl; +} + +#endif diff --git a/rce/pixelrce/config/IPCConfigIF.hh b/rce/pixelrce/config/IPCConfigIF.hh new file mode 100644 index 00000000..0b35ebe7 --- /dev/null +++ b/rce/pixelrce/config/IPCConfigIF.hh @@ -0,0 +1,41 @@ +#ifndef IPCCONFIGIF_HH +#define IPCCONFIGIF_HH + +#include "IPCConfigIFAdapter.hh" +#include "ipc/object.h" +#include "config/ConfigIF.hh" +#include "config/ModuleFactory.hh" +#include <omnithread.h> + +class IPCPartition; + +template <class TP = ipc::single_thread> +class IPCConfigIF: public IPCNamedObject<POA_ipc::IPCConfigIFAdapter,TP>, public ConfigIF { +public: + IPCConfigIF(IPCPartition & p, const char * name, ModuleFactory* mf); + ~IPCConfigIF(); + void IPCsendTrigger(); + //void IPCsetupParameter(const char* name, CORBA::Long val); + CORBA::ULong IPCsetupParameter(const char* name, CORBA::Long val); + void IPCsetupMaskStage(CORBA::Long stage); + void IPCenableTrigger(); + void IPCdisableTrigger(); + void IPCresetFE(); + void IPCconfigureModulesHW(); + CORBA::Long IPCverifyModuleConfigHW(CORBA::Long id); + CORBA::ULong IPCwriteHWregister(CORBA::ULong addr, CORBA::ULong val); + CORBA::ULong IPCsendHWcommand(CORBA::Octet opcode); + CORBA::ULong IPCwriteHWblockData(const ipc::blockdata& data); + CORBA::ULong IPCreadHWblockData(const ipc::blockdata & data, ipc::blockdata_out retv); + CORBA::ULong IPCreadHWbuffers(ipc::chardata_out retv); + CORBA::ULong IPCreadHWregister(CORBA::ULong addr, CORBA::ULong &val); + CORBA::Long IPCdeleteModules(); + CORBA::Long IPCnTrigger(); + CORBA::Long IPCsetupTriggerIF(const char* type); + CORBA::Long IPCsetupModule(const char* name, const char* type, const ipc::ModSetup& par, const char* formatter); + void shutdown(); + +}; + + +#endif diff --git a/rce/pixelrce/config/IPCModuleFactory.cc b/rce/pixelrce/config/IPCModuleFactory.cc new file mode 100644 index 00000000..0c95f815 --- /dev/null +++ b/rce/pixelrce/config/IPCModuleFactory.cc @@ -0,0 +1,116 @@ +#include "config/IPCModuleFactory.hh" +#include "config/FormatterFactory.hh" +#include "config/FEI3/Module.hh" +#include "config/FEI3/IPCModule.cc" +#include "config/FEI4/IPCFEI4AModule.cc" +#include "config/FEI4/IPCFEI4BModule.cc" +#include "config/hitbus/IPCModule.cc" +#include "config/afp-hptdc/IPCModule.cc" +#include "config/Trigger.hh" +#include "config/MultiTrigger.hh" +#include "config/EventFromFileTrigger.hh" +#include "config/MeasurementTrigger.hh" +#include "config/MultiShotTrigger.hh" +#include "config/HitorTrigger.hh" +#include "config/FEI4/TemperatureTrigger.hh" +#include "config/FEI4/MonleakTrigger.hh" +#include "config/FEI4/SNTrigger.hh" +#include "config/FEI4/Fei4RegisterTestTrigger.hh" +#include "util/exceptions.hh" +#include "stdio.h" +#include <iostream> + +IPCModuleFactory::IPCModuleFactory(IPCPartition& p):ModuleFactory(),m_partition(p){ + m_modulegroups.push_back(&m_modgroupi3); + m_modulegroups.push_back(&m_modgroupi4a); + m_modulegroups.push_back(&m_modgroupi4b); + m_modulegroups.push_back(&m_modgrouphitbus); + m_modulegroups.push_back(&m_modgroupafphptdc); +} + + +AbsModule* IPCModuleFactory::createModule(const char* name, const char* type, unsigned id, unsigned inLink, unsigned outLink, const char* formatter){ + FormatterFactory ff; + AbsFormatter* theformatter=ff.createFormatter(formatter, id); + if(std::string(type)=="FEI3"){ + FEI3::Module *mod= new FEI3::Module(name, id, inLink, outLink, theformatter); + m_modgroupi3.addModule(mod); + return mod; + } + if(std::string(type)=="IPC_FEI3_singleThread"){ + FEI3::Module *mod= new FEI3::IPCModule<ipc::single_thread>(m_partition, name,id, inLink, outLink, theformatter); + m_modgroupi3.addModule(mod); + return mod; + } + if(std::string(type)=="IPC_FEI3_multiThread"){ + FEI3::Module *mod= new FEI3::IPCModule<ipc::multi_thread>(m_partition, name,id, inLink, outLink, theformatter); + m_modgroupi3.addModule(mod); + return mod; + } + if(std::string(type)=="IPC_FEI4A_singleThread"){ + FEI4::Module *mod= new FEI4::IPCFEI4AModule<ipc::single_thread>(m_partition, name,id, inLink, outLink, theformatter); + m_modgroupi4a.addModule(mod); + return mod; + } + if(std::string(type)=="IPC_FEI4A_multiThread"){ + FEI4::Module *mod= new FEI4::IPCFEI4AModule<ipc::multi_thread>(m_partition, name,id, inLink, outLink, theformatter); + m_modgroupi4a.addModule(mod); + return mod; + } + if(std::string(type)=="IPC_FEI4B_singleThread"){ + FEI4::Module *mod= new FEI4::IPCFEI4BModule<ipc::single_thread>(m_partition, name,id, inLink, outLink, theformatter); + m_modgroupi4b.addModule(mod); + return mod; + } + if(std::string(type)=="IPC_FEI4B_multiThread"){ + FEI4::Module *mod= new FEI4::IPCFEI4BModule<ipc::multi_thread>(m_partition, name,id, inLink, outLink, theformatter); + m_modgroupi4b.addModule(mod); + return mod; + } + if(std::string(type)=="IPC_Hitbus_singleThread"){ + Hitbus::Module *mod= new Hitbus::IPCModule<ipc::single_thread>(m_partition, name,id, inLink, outLink, theformatter); + m_modgrouphitbus.addModule(mod); + return mod; + } + if(std::string(type)=="IPC_Hitbus_multiThread"){ + Hitbus::Module *mod= new Hitbus::IPCModule<ipc::multi_thread>(m_partition, name,id, inLink, outLink, theformatter); + m_modgrouphitbus.addModule(mod); + return mod; + } + if(std::string(type)=="IPC_AFPHPTDC_singleThread"){ + afphptdc::Module *mod= new afphptdc::IPCModule<ipc::single_thread>(m_partition, name,id, inLink, outLink, theformatter); + m_modgroupafphptdc.addModule(mod); + return mod; + } + if(std::string(type)=="IPC_AFPHPTDC_multiThread"){ + std::cout<<"Adding module"<<std::endl; + afphptdc::Module *mod= new afphptdc::IPCModule<ipc::multi_thread>(m_partition, name,id, inLink, outLink, theformatter); + std::cout<<"Added module"<<std::endl; + m_modgroupafphptdc.addModule(mod); + return mod; + } + std::cout<<"Unknown module type "<<type<<std::endl; + rcecalib::Unknown_Module_Type issue; + throw issue; + return 0; +} + +AbsTrigger* IPCModuleFactory::createTriggerIF(const char* type, ConfigIF* cif){ + // std::cout << "Creating trigger of type " << type << std::endl; + if(std::string(type)=="default") return new FEI3::Trigger; + else if(std::string(type)=="FEI3")return new FEI3::Trigger; + else if(std::string(type)=="EventFromFile")return new EventFromFileTrigger; + else if(std::string(type)=="MultiShot")return new MultiShotTrigger; + else if(std::string(type)=="MultiTrigger")return new MultiTrigger; + else if(std::string(type)=="Hitor")return new HitorTrigger(cif); + else if(std::string(type)=="Temperature")return new FEI4::TemperatureTrigger; + else if(std::string(type)=="Monleak")return new FEI4::MonleakTrigger; + else if(std::string(type)=="SerialNumber")return new FEI4::SNTrigger; + else if(std::string(type)=="Fei4RegisterTest")return new FEI4::Fei4RegisterTestTrigger; +#ifdef __rtems__ + else if(std::string(type)=="Measurement")return new MeasurementTrigger; +#endif + char msg[128]; + printf("No Trigger type %s",type); + assert(0); +} diff --git a/rce/pixelrce/config/IPCModuleFactory.hh b/rce/pixelrce/config/IPCModuleFactory.hh new file mode 100644 index 00000000..18d18130 --- /dev/null +++ b/rce/pixelrce/config/IPCModuleFactory.hh @@ -0,0 +1,32 @@ +#ifndef IPCMODULEFACTORY_HH +#define IPCMODULEFACTORY_HH + +#include "ipc/partition.h" + +#include "config/ModuleFactory.hh" +#include "config/FEI3/ModuleGroup.hh" +#include "config/FEI4/ModuleGroup.hh" +#include "config/hitbus/ModuleGroup.hh" +#include "config/afp-hptdc/ModuleGroup.hh" + +class ConfigIF; +class AbsFormatter; + +class IPCModuleFactory: public ModuleFactory { +public: + IPCModuleFactory(IPCPartition &p); + AbsModule* createModule(const char* name, const char* type, unsigned id, unsigned inpos, unsigned outPos, const char* formatter); + AbsFormatter* createFormatter(const char* formatter, int id); + AbsTrigger* createTriggerIF(const char* type, ConfigIF* cif); +private: + IPCPartition &m_partition; + FEI3::ModuleGroup m_modgroupi3; + FEI4::ModuleGroup m_modgroupi4a; + FEI4::ModuleGroup m_modgroupi4b; + Hitbus::ModuleGroup m_modgrouphitbus; + afphptdc::ModuleGroup m_modgroupafphptdc; + +}; + + +#endif diff --git a/rce/pixelrce/config/afp-hptdc/IPCModule.cc b/rce/pixelrce/config/afp-hptdc/IPCModule.cc new file mode 100644 index 00000000..612fc010 --- /dev/null +++ b/rce/pixelrce/config/afp-hptdc/IPCModule.cc @@ -0,0 +1,185 @@ +#ifndef AFPHPTDC__IPCMODULE_CC +#define AFPHPTDC__IPCMODULE_CC +#include "util/RceName.hh" +#include "config/afp-hptdc/IPCModule.hh" +#include "ipc/partition.h" +#include <boost/property_tree/ptree.hpp> +#include "ers/ers.h" +#include <boost/lexical_cast.hpp> + +namespace afphptdc{ + +template <class TP> +IPCModule<TP>::IPCModule(IPCPartition & p, const char * name, unsigned id, unsigned inlink, unsigned outlink, AbsFormatter* fmt): + IPCNamedObject<POA_ipc::IPCAFPHPTDCAdapter, TP>( p, std::string(boost::lexical_cast<std::string>(id)+"_RCE"+boost::lexical_cast<std::string>(RceName::getRceNumber())).c_str()) , + Module(name, id, inlink, outlink, fmt){ + // std::cout<<"IPCModule"<<std::endl; + try { + IPCNamedObject<POA_ipc::IPCAFPHPTDCAdapter,TP>::publish(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } +} + +template <class TP> +IPCModule<TP>::~IPCModule(){ + try { + IPCNamedObject<POA_ipc::IPCAFPHPTDCAdapter,TP>::withdraw(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::warning( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } +} + +template <class TP> +CORBA::Long IPCModule<TP>::IPCdownloadConfig(const ipc::AFPHPTDCModuleConfig &config){ + setFpgaField("test", config.test); + setFpgaField("tdcControl", config.tdcControl); + setFpgaField("run", config.run); + setFpgaField("bypassLut", config.bypassLut); + setFpgaField("localClockEn", config.localClockEn); + setFpgaField("calClockEn", config.calClockEn); + setFpgaField("refEn", config.refEn); + setFpgaField("hitTestEn", config.hitTestEn); + setFpgaField("inputSel", config.inputSel); + setFpgaField("address", config.address); + setFpgaField("fanspeed", config.fanspeed); + setFpgaField("channelEn", config.channelEn); + + for(int i=0;i<3;i++){ + for (int j=31;j>=0;j--){ + char offs[32]; + sprintf(offs, "offset%d", j); + setTdcField(offs, i, config.offset[j][i]); + } + setTdcField("test_select", i, config.test_select[i]); + setTdcField("enable_error_mark", i, config.enable_error_mark[i]); + setTdcField("enable_error_bypass", i, config.enable_error_bypass[i]); + setTdcField("enable_error", i, config.enable_error[i]); + setTdcField("readout_single_cycle_speed", i, config.readout_single_cycle_speed[i]); + setTdcField("serial_delay", i, config.serial_delay[i]); + setTdcField("strobe_select", i, config.strobe_select[i]); + setTdcField("readout_speed_select", i, config.readout_speed_select[i]); + setTdcField("token_delay", i, config.token_delay[i]); + setTdcField("enable_local_trailer", i, config.enable_local_trailer[i]); + setTdcField("enable_local_header", i, config.enable_local_header[i]); + setTdcField("enable_global_trailer", i, config.enable_global_trailer[i]); + setTdcField("enable_global_header", i, config.enable_global_header[i]); + setTdcField("keep_token", i, config.keep_token[i]); + setTdcField("master", i, config.master[i]); + setTdcField("enable_bytewise", i, config.enable_bytewise[i]); + setTdcField("enable_serial", i, config.enable_serial[i]); + setTdcField("enable_jtag_readout", i, config.enable_jtag_readout[i]); + setTdcField("tdc_id", i, config.tdc_id[i]); + setTdcField("select_bypass_inputs", i, config.select_bypass_inputs[i]); + setTdcField("readout_fifo_size", i, config.readout_fifo_size[i]); + setTdcField("reject_count_offset", i, config.reject_count_offset[i]); + setTdcField("search_window", i, config.search_window[i]); + setTdcField("match_window", i, config.match_window[i]); + setTdcField("leading_resolution", i, config.leading_resolution[i]); + setTdcField("fixed_pattern", i, config.fixed_pattern[i]); + setTdcField("enable_fixed_pattern", i, config.enable_fixed_pattern[i]); + setTdcField("max_event_size", i, config.max_event_size[i]); + setTdcField("reject_readout_fifo_full", i, config.reject_readout_fifo_full[i]); + setTdcField("enable_readout_occupancy", i, config.enable_readout_occupancy[i]); + setTdcField("enable_readout_separator", i, config.enable_readout_separator[i]); + setTdcField("enable_overflow_detect", i, config.enable_overflow_detect[i]); + setTdcField("enable_relative", i, config.enable_relative[i]); + setTdcField("enable_automatic_reject", i, config.enable_automatic_reject[i]); + setTdcField("event_count_offset", i, config.event_count_offset[i]); + setTdcField("trigger_count_offset", i, config.trigger_count_offset[i]); + setTdcField("enable_set_counters_on_bunch_reset", i, config.enable_set_counters_on_bunch_reset[i]); + setTdcField("enable_master_reset_code", i, config.enable_master_reset_code[i]); + setTdcField("enable_master_reset_code_on_event_reset", i, config.enable_master_reset_code_on_event_reset[i]); + setTdcField("enable_reset_channel_buffer_when_separator", i, config.enable_reset_channel_buffer_when_separator[i]); + setTdcField("enable_separator_on_event_reset", i, config.enable_separator_on_event_reset[i]); + setTdcField("enable_separator_on_bunch_reset", i, config.enable_separator_on_bunch_reset[i]); + setTdcField("enable_direct_event_reset", i, config.enable_direct_event_reset[i]); + setTdcField("enable_direct_bunch_reset", i, config.enable_direct_bunch_reset[i]); + setTdcField("enable_direct_trigger", i, config.enable_direct_trigger[i]); + setTdcField("coarse_count_offset", i, config.coarse_count_offset[i]); + setTdcField("dll_tap_adjust3_0", i, config.dll_tap_adjust3_0[i]); + setTdcField("dll_tap_adjust7_4", i, config.dll_tap_adjust7_4[i]); + setTdcField("dll_tap_adjust11_8", i, config.dll_tap_adjust11_8[i]); + setTdcField("dll_tap_adjust15_12", i, config.dll_tap_adjust15_12[i]); + setTdcField("dll_tap_adjust19_16", i, config.dll_tap_adjust19_16[i]); + setTdcField("dll_tap_adjust23_20", i, config.dll_tap_adjust23_20[i]); + setTdcField("dll_tap_adjust27_24", i, config.dll_tap_adjust27_24[i]); + setTdcField("dll_tap_adjust31_28", i, config.dll_tap_adjust31_28[i]); + setTdcField("rc_adjust", i, config.rc_adjust[i]); + setTdcField("not_used", i, config.not_used[i]); + setTdcField("low_power_mode", i, config.low_power_mode[i]); + setTdcField("width_select", i, config.width_select[i]); + setTdcField("vernier_offset", i, config.vernier_offset[i]); + setTdcField("dll_control", i, config.dll_control[i]); + setTdcField("dead_time", i, config.dead_time[i]); + setTdcField("test_invert", i, config.test_invert[i]); + setTdcField("test_mode", i, config.test_mode[i]); + setTdcField("enable_trailing", i, config.enable_trailing[i]); + setTdcField("enable_leading", i, config.enable_leading[i]); + setTdcField("mode_rc_compression", i, config.mode_rc_compression[i]); + setTdcField("mode_rc", i, config.mode_rc[i]); + setTdcField("dll_mode", i, config.dll_mode[i]); + setTdcField("pll_control", i, config.pll_control[i]); + setTdcField("serial_clock_delay", i, config.serial_clock_delay[i]); + setTdcField("io_clock_delay", i, config.io_clock_delay[i]); + setTdcField("core_clock_delay", i, config.core_clock_delay[i]); + setTdcField("dll_clock_delay", i, config.dll_clock_delay[i]); + setTdcField("serial_clock_source", i, config.serial_clock_source[i]); + setTdcField("io_clock_source", i, config.io_clock_source[i]); + setTdcField("core_clock_source", i, config.core_clock_source[i]); + setTdcField("dll_clock_source", i, config.dll_clock_source[i]); + setTdcField("roll_over", i, config.roll_over[i]); + setTdcField("enable_matching", i, config.enable_matching[i]); + setTdcField("enable_pair", i, config.enable_pair[i]); + setTdcField("enable_ttl_serial", i, config.enable_ttl_serial[i]); + setTdcField("enable_ttl_control", i, config.enable_ttl_control[i]); + setTdcField("enable_ttl_reset", i, config.enable_ttl_reset[i]); + setTdcField("enable_ttl_clock", i, config.enable_ttl_clock[i]); + setTdcField("enable_ttl_hit", i, config.enable_ttl_hit[i]); + } + AbsFormatter* fmt=getFormatter(); + if(fmt){ + // configure the formatter with the calibration constants + boost::property_tree::ptree *pt=new boost::property_tree::ptree; + for(int i=0;i<2;i++){ + for(int j=0;j<12;j++){ + for(int k=0;k<1024;k++){ + char name[32]; + sprintf(name, "c_%d_%d_%d", i, j, k); + pt->put(name, config.calib[i][j][k]); + } + } + } + std::cout<<"%%%%%%%%% Configuring HPTDC Formatter"<<std::endl; + fmt->configure(pt); + delete pt; + } + return 0; +} + +template <class TP> +void IPCModule<TP>::shutdown(){ + std::cout<<"Shutdown"<<std::endl; +} + +template <class TP> +void IPCModule<TP>::destroy(){ + this->_destroy(); +} + + + +}; + +#endif diff --git a/rce/pixelrce/config/afp-hptdc/IPCModule.hh b/rce/pixelrce/config/afp-hptdc/IPCModule.hh new file mode 100644 index 00000000..4ac7ed40 --- /dev/null +++ b/rce/pixelrce/config/afp-hptdc/IPCModule.hh @@ -0,0 +1,26 @@ +#ifndef IPCAFPHPTDCMODULE_HH +#define IPCAFPHPTDCMODULE_HH + +#include "config/afp-hptdc/Module.hh" +#include "ipc/object.h" +#include "AFPHPTDCModuleConfig.hh" +#include "IPCAFPHPTDCAdapter.hh" + +class IPCPartition; +class AbsFormatter; + +namespace afphptdc{ +template <class TP = ipc::single_thread> +class IPCModule: public IPCNamedObject<POA_ipc::IPCAFPHPTDCAdapter,TP>, public afphptdc::Module { +public: + IPCModule(IPCPartition & p, const char * name, unsigned id, unsigned inlink, unsigned outlink, AbsFormatter* fmt); + ~IPCModule(); + CORBA::Long IPCdownloadConfig(const ipc::AFPHPTDCModuleConfig &config); + void shutdown(); + void destroy(); + +}; +}; + + +#endif diff --git a/rce/pixelrce/config/hitbus/IPCModule.cc b/rce/pixelrce/config/hitbus/IPCModule.cc new file mode 100644 index 00000000..164fb3be --- /dev/null +++ b/rce/pixelrce/config/hitbus/IPCModule.cc @@ -0,0 +1,74 @@ +#ifndef HITBUS__IPCMODULE_CC +#define HITBUS__IPCMODULE_CC +#include "util/RceName.hh" +#include "config/hitbus/IPCModule.hh" +#include "ipc/partition.h" +#include "ers/ers.h" +#include <boost/lexical_cast.hpp> + +namespace Hitbus{ + +template <class TP> +IPCModule<TP>::IPCModule(IPCPartition & p, const char * name, unsigned id, unsigned inlink, unsigned outlink, AbsFormatter* fmt): + IPCNamedObject<POA_ipc::IPCHitbusAdapter, TP>( p, std::string(boost::lexical_cast<std::string>(id)+"_RCE"+boost::lexical_cast<std::string>(RceName::getRceNumber())).c_str()) , + Module(name, id, inlink, outlink, fmt){ + // std::cout<<"IPCModule"<<std::endl; + try { + IPCNamedObject<POA_ipc::IPCHitbusAdapter,TP>::publish(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } +} + +template <class TP> +IPCModule<TP>::~IPCModule(){ + try { + IPCNamedObject<POA_ipc::IPCHitbusAdapter,TP>::withdraw(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::warning( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } +} + +template <class TP> +CORBA::Long IPCModule<TP>::IPCdownloadConfig(const ipc::HitbusModuleConfig &config){ + setRegister("bpm", config.bpm); + setRegister("delay_tam1", config.delay_tam1); + setRegister("delay_tam2", config.delay_tam2); + setRegister("delay_tam3", config.delay_tam3); + setRegister("delay_tbm1", config.delay_tbm1); + setRegister("delay_tbm2", config.delay_tbm2); + setRegister("delay_tbm3", config.delay_tbm3); + setRegister("bypass_delay", config.bypass_delay); + setRegister("clock", config.clock); + setRegister("function_A", config.function_A); + setRegister("function_B", config.function_B); + std::cout<<"Configure done"<<std::endl; + return 0; +} + +template <class TP> +void IPCModule<TP>::shutdown(){ + std::cout<<"Shutdown"<<std::endl; +} + +template <class TP> +void IPCModule<TP>::destroy(){ + this->_destroy(); +} + + + +}; + +#endif diff --git a/rce/pixelrce/config/hitbus/IPCModule.hh b/rce/pixelrce/config/hitbus/IPCModule.hh new file mode 100644 index 00000000..d4fc9a3c --- /dev/null +++ b/rce/pixelrce/config/hitbus/IPCModule.hh @@ -0,0 +1,26 @@ +#ifndef IPCHITBUSMODULE_HH +#define IPCHITBUSMODULE_HH + +#include "config/hitbus/Module.hh" +#include "ipc/object.h" +#include "HitbusModuleConfig.hh" +#include "IPCHitbusAdapter.hh" + +class IPCPartition; +class AbsFormatter; + +namespace Hitbus{ +template <class TP = ipc::single_thread> +class IPCModule: public IPCNamedObject<POA_ipc::IPCHitbusAdapter,TP>, public Hitbus::Module { +public: + IPCModule(IPCPartition & p, const char * name, unsigned id, unsigned inlink, unsigned outlink, AbsFormatter* fmt); + ~IPCModule(); + CORBA::Long IPCdownloadConfig(const ipc::HitbusModuleConfig &config); + void shutdown(); + void destroy(); + +}; +}; + + +#endif diff --git a/rce/pixelrce/idl/IPCAFPHPTDCAdapter.idl b/rce/pixelrce/idl/IPCAFPHPTDCAdapter.idl new file mode 100644 index 00000000..3a754bdb --- /dev/null +++ b/rce/pixelrce/idl/IPCAFPHPTDCAdapter.idl @@ -0,0 +1,16 @@ +#ifndef IPCAFPHPTDCADAPTER_IDL +#define IPCAFPHPTDCADAPTER_IDL + +#include <ipc/ipc.idl> +#include "AFPHPTDCModuleConfig.idl" + +module ipc +{ + interface IPCAFPHPTDCAdapter : ipc::servant + { + long IPCdownloadConfig(in AFPHPTDCModuleConfig config); + + }; +}; + +#endif diff --git a/rce/pixelrce/idl/IPCConfigIFAdapter.idl b/rce/pixelrce/idl/IPCConfigIFAdapter.idl new file mode 100644 index 00000000..1f3e7350 --- /dev/null +++ b/rce/pixelrce/idl/IPCConfigIFAdapter.idl @@ -0,0 +1,42 @@ +#ifndef IPCCONFIGIF_IDL +#define IPCCONFIGIF_IDL + +#include <ipc/ipc.idl> + +module ipc +{ + struct ModSetup{ + long id; + long inLink; + long outLink; + }; + + typedef sequence<unsigned long> blockdata; + typedef sequence<octet> chardata; + + interface IPCConfigIFAdapter : ipc::servant + { + oneway void IPCsendTrigger(); + //oneway void IPCsetupParameter(in string name, in long val); + unsigned long IPCsetupParameter(in string name, in long val); + oneway void IPCsetupMaskStage(in long stage); + oneway void IPCenableTrigger(); + oneway void IPCdisableTrigger(); + oneway void IPCresetFE(); + oneway void IPCconfigureModulesHW(); + unsigned long IPCwriteHWregister(in unsigned long addr, in unsigned long val); + unsigned long IPCreadHWregister(in unsigned long addr, out unsigned long val); + unsigned long IPCsendHWcommand(in octet opcode); + unsigned long IPCwriteHWblockData(in blockdata data); + unsigned long IPCreadHWblockData(in blockdata data, out blockdata retv); + unsigned long IPCreadHWbuffers(out chardata retv); + long IPCverifyModuleConfigHW(in long id); + long IPCdeleteModules(); + long IPCnTrigger(); + long IPCsetupTriggerIF(in string type); + long IPCsetupModule(in string name, in string type, in ModSetup par, in string formatter); + + }; +}; + +#endif diff --git a/rce/pixelrce/idl/IPCFEI3Adapter.idl b/rce/pixelrce/idl/IPCFEI3Adapter.idl new file mode 100644 index 00000000..6305f3f3 --- /dev/null +++ b/rce/pixelrce/idl/IPCFEI3Adapter.idl @@ -0,0 +1,16 @@ +#ifndef IPCFEI3ADAPTER_IDL +#define IPCFEI3ADAPTER_IDL + +#include <ipc/ipc.idl> +#include "PixelModuleConfig.idl" + +module ipc +{ + interface IPCFEI3Adapter : ipc::servant + { + long IPCdownloadConfig(in PixelModuleConfig config); + + }; +}; + +#endif diff --git a/rce/pixelrce/idl/IPCFEI4AAdapter.idl b/rce/pixelrce/idl/IPCFEI4AAdapter.idl new file mode 100644 index 00000000..2ceb0576 --- /dev/null +++ b/rce/pixelrce/idl/IPCFEI4AAdapter.idl @@ -0,0 +1,20 @@ +#ifndef IPCFEI4AADAPTER_IDL +#define IPCFEI4AADAPTER_IDL + +#include <ipc/ipc.idl> +#include "PixelFEI4AConfig.idl" + +module ipc +{ + interface IPCFEI4AAdapter : ipc::servant + { + long IPCdownloadConfig(in PixelFEI4AConfig config); + oneway void IPCsetChipAddress(in unsigned long val); + unsigned long IPCwriteHWglobalRegister(in long reg, in unsigned short val); + unsigned long IPCreadHWglobalRegister(in long reg, out unsigned short val); + unsigned long IPCwriteDoubleColumnHW(in unsigned long bit, in unsigned long dcol, in uvec data, out uvec readback); + unsigned long IPCreadDoubleColumnHW(in unsigned long bit, in unsigned long dcol, out uvec readback); + }; +}; + +#endif diff --git a/rce/pixelrce/idl/IPCFEI4BAdapter.idl b/rce/pixelrce/idl/IPCFEI4BAdapter.idl new file mode 100644 index 00000000..798e8b4c --- /dev/null +++ b/rce/pixelrce/idl/IPCFEI4BAdapter.idl @@ -0,0 +1,20 @@ +#ifndef IPCFEI4BADAPTER_IDL +#define IPCFEI4BADAPTER_IDL + +#include <ipc/ipc.idl> +#include "PixelFEI4BConfig.idl" + +module ipc +{ + interface IPCFEI4BAdapter : ipc::servant + { + long IPCdownloadConfig(in PixelFEI4BConfig config); + oneway void IPCsetChipAddress(in unsigned long val); + unsigned long IPCwriteHWglobalRegister(in long reg, in unsigned short val); + unsigned long IPCreadHWglobalRegister(in long reg, out unsigned short val); + unsigned long IPCwriteDoubleColumnHW(in unsigned long bit, in unsigned long dcol, in uvec data, out uvec readback); + unsigned long IPCreadDoubleColumnHW(in unsigned long bit, in unsigned long dcol, out uvec readback); + }; +}; + +#endif diff --git a/rce/pixelrce/idl/IPCHitbusAdapter.idl b/rce/pixelrce/idl/IPCHitbusAdapter.idl new file mode 100644 index 00000000..eb0ac8e8 --- /dev/null +++ b/rce/pixelrce/idl/IPCHitbusAdapter.idl @@ -0,0 +1,16 @@ +#ifndef IPCHITBUSADAPTER_IDL +#define IPCHITBUSADAPTER_IDL + +#include <ipc/ipc.idl> +#include "HitbusModuleConfig.idl" + +module ipc +{ + interface IPCHitbusAdapter : ipc::servant + { + long IPCdownloadConfig(in HitbusModuleConfig config); + + }; +}; + +#endif diff --git a/rce/pixelrce/idl/IPCScanAdapter.idl b/rce/pixelrce/idl/IPCScanAdapter.idl new file mode 100644 index 00000000..ab7e3688 --- /dev/null +++ b/rce/pixelrce/idl/IPCScanAdapter.idl @@ -0,0 +1,21 @@ +#ifndef IPCSCANADAPTER_IDL +#define IPCSCANADAPTER_IDL + +#include <ipc/ipc.idl> +#include "ScanOptions.idl" + +module ipc +{ + interface IPCScanAdapter : ipc::servant + { + oneway void IPCstartScan(); + oneway void IPCpause(); + oneway void IPCresume(); + oneway void IPCwaitForData(); + oneway void IPCstopWaiting(); + long IPCgetStatus(); + oneway void IPCabort(); + }; +}; + +#endif diff --git a/rce/pixelrce/idl/IPCScanRootAdapter.idl b/rce/pixelrce/idl/IPCScanRootAdapter.idl new file mode 100644 index 00000000..a6e5d897 --- /dev/null +++ b/rce/pixelrce/idl/IPCScanRootAdapter.idl @@ -0,0 +1,23 @@ +#ifndef IPCSCANROOTADAPTER_IDL +#define IPCSCANROOTADAPTER_IDL + +#include <ipc/ipc.idl> +#include "ScanOptions.idl" +#include "Callback.idl" + +module ipc +{ + typedef sequence<string> StringVect; + + interface IPCScanRootAdapter : ipc::servant + { + long IPCconfigureScan(in ScanOptions options); + StringVect IPCgetHistoNames(in string reg); + StringVect IPCgetPublishedHistoNames(); + unsigned long IPCnEvents(); + oneway void IPCresynch(); + oneway void IPCconfigureCallback(in Callback cb, in Priority pr); + }; +}; + +#endif diff --git a/rce/pixelrce/scanctrl/IPCRceCallback.cc b/rce/pixelrce/scanctrl/IPCRceCallback.cc new file mode 100644 index 00000000..763b6545 --- /dev/null +++ b/rce/pixelrce/scanctrl/IPCRceCallback.cc @@ -0,0 +1,35 @@ +#include "scanctrl/IPCRceCallback.hh" +#include <iostream> + +IPCRceCallback::IPCRceCallback(): RceCallback(){ +} + +void IPCRceCallback::configure(ipc::Callback_ptr cb, ipc::Priority pr){ + m_cb = ipc::Callback::_duplicate( cb ); + m_pr=pr; + m_configured=true; +} + +void IPCRceCallback::SendMsg(ipc::Priority pr, const ipc::CallbackParams *msg){ + if(m_configured){ + if(pr>=m_pr){ + try { + m_cb->notify( *msg ); + } + catch(...) { + std::cout << "callback : notification fails" << std::endl; + } + } + } +} +void IPCRceCallback::Shutdown(){ + if(m_configured){ + try { + m_cb->stopServer(); + } + catch(...) { + std::cout << "callback : notification fails" << std::endl; + } + m_configured=false; + } +} diff --git a/rce/pixelrce/scanctrl/IPCRceCallback.hh b/rce/pixelrce/scanctrl/IPCRceCallback.hh new file mode 100644 index 00000000..96b64e11 --- /dev/null +++ b/rce/pixelrce/scanctrl/IPCRceCallback.hh @@ -0,0 +1,18 @@ +#ifndef IPCRCECALLBACK_HH +#define IPCRCECALLBACK_HH + +#include "scanctrl/RceCallback.hh" +#include <omnithread.h> + +class IPCRceCallback: public RceCallback{ +public: + IPCRceCallback(); + void SendMsg(ipc::Priority pr, const ipc::CallbackParams *msg); + void Shutdown(); + void configure( ipc::Callback_ptr cb, ipc::Priority pr); +private: + ipc::Callback_var m_cb; + +}; + +#endif diff --git a/rce/pixelrce/scanctrl/IPCScan.cc b/rce/pixelrce/scanctrl/IPCScan.cc new file mode 100644 index 00000000..8c1de989 --- /dev/null +++ b/rce/pixelrce/scanctrl/IPCScan.cc @@ -0,0 +1,99 @@ +#ifndef IPCSCAN_CC +#define IPCSCAN_CC + +#include "scanctrl/IPCScan.hh" +#include "ers/ers.h" +#include "ipc/partition.h" +#include <boost/property_tree/ptree.hpp> + +#include <string> +#include <iostream> + + +template <class TP> +void* IPCScan<TP>::startScanStatic(void* arg){ + ((IPCScan<TP>*)arg)->startScan(); + return 0; +} + +template <class TP> +IPCScan<TP>::IPCScan(IPCPartition & p, const char * name): + IPCNamedObject<POA_ipc::IPCScanAdapter, TP>( p, name ) , + Scan() { + + try { + IPCNamedObject<POA_ipc::IPCScanAdapter,TP>::publish(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } +} + + + +template <class TP> +IPCScan<TP>::~IPCScan(){ + try { + IPCNamedObject<POA_ipc::IPCScanAdapter,TP>::withdraw(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::warning( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } +} + +template <class TP> +void IPCScan<TP>::IPCpause(){ + std::cout<<"Pause"<<std::endl; + pause(); +} +template <class TP> +void IPCScan<TP>::IPCresume(){ + std::cout<<"Resume"<<std::endl; + resume(); +} +template <class TP> +void IPCScan<TP>::IPCabort(){ + std::cout<<"Abort"<<std::endl; + abort(); +} +template <class TP> +void IPCScan<TP>::IPCstartScan(){ + pthread_t mthread; + pthread_attr_t attr; + int ret; + // setting a new size + int stacksize = (PTHREAD_STACK_MIN + 0x20000); + pthread_attr_init(&attr); + ret=pthread_attr_setstacksize(&attr, stacksize); + pthread_create( &mthread, &attr , startScanStatic, this); + pthread_detach(mthread); + //startScan(); +} +template <class TP> +void IPCScan<TP>::IPCwaitForData(){ + waitForData(); +} +template <class TP> +void IPCScan<TP>::IPCstopWaiting(){ + stopWaiting(); +} +template <class TP> +CORBA::Long IPCScan<TP>::IPCgetStatus(){ + return getStatus(); +} + +template <class TP> +void IPCScan<TP>::shutdown(){ + std::cout<<"Shutdown"<<std::endl; +} + +#endif diff --git a/rce/pixelrce/scanctrl/IPCScan.hh b/rce/pixelrce/scanctrl/IPCScan.hh new file mode 100644 index 00000000..ba2357a1 --- /dev/null +++ b/rce/pixelrce/scanctrl/IPCScan.hh @@ -0,0 +1,29 @@ +#ifndef IPCSCAN_HH +#define IPCSCAN_HH + +#include "scanctrl/Scan.hh" +#include "ipc/object.h" +#include "ScanOptions.hh" +#include "IPCScanAdapter.hh" + +class IPCPartition; + +template <class TP = ipc::single_thread> +class IPCScan: public IPCNamedObject<POA_ipc::IPCScanAdapter,TP>, public Scan { +public: + IPCScan(IPCPartition & p, const char * name); + ~IPCScan(); + void IPCpause(); + void IPCresume(); + void IPCwaitForData(); + void IPCstopWaiting(); + void IPCabort(); + void IPCstartScan(); + CORBA::Long IPCgetStatus(); + void shutdown(); + static void *startScanStatic(void *arg); + +}; + + +#endif diff --git a/rce/pixelrce/scanctrl/IPCScanRoot.cc b/rce/pixelrce/scanctrl/IPCScanRoot.cc new file mode 100644 index 00000000..4ede2a25 --- /dev/null +++ b/rce/pixelrce/scanctrl/IPCScanRoot.cc @@ -0,0 +1,184 @@ +#ifndef IPCSCANROOT_CC +#define IPCSCANROOT_CC + +#include "scanctrl/IPCScanRoot.hh" +#include "ers/ers.h" +#include "ipc/partition.h" +#include <boost/property_tree/ptree.hpp> +#include "dataproc/AbsDataProc.hh" +#include "dataproc/AbsReceiver.hh" +#include "config/ConfigIF.hh" +#include "scanctrl/Scan.hh" +#include "util/HistoManager.hh" +#include "scanctrl/IPCRceCallback.hh" + +#include <string> +#include <iostream> + + +template <class TP> +IPCScanRoot<TP>::IPCScanRoot(IPCPartition & p, const char * name, ConfigIF* cif, Scan* scan): + IPCNamedObject<POA_ipc::IPCScanRootAdapter, TP>( p, name ) , ScanRoot(cif,scan), m_cb(new IPCRceCallback){ + try { + IPCNamedObject<POA_ipc::IPCScanRootAdapter,TP>::publish(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } +} + +template <class TP> +IPCScanRoot<TP>::~IPCScanRoot(){ + try { + IPCNamedObject<POA_ipc::IPCScanRootAdapter,TP>::withdraw(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::warning( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } +} + +template <class TP> +CORBA::Long IPCScanRoot<TP>::IPCconfigureScan(const ipc::ScanOptions &options){ + //PixScan::dump(options); + //std::cout<<"Start IPCScanRoot "<<std::endl; + //convert struct into property tree + boost::property_tree::ptree *pt=new boost::property_tree::ptree; + //Top level + pt->put("Name",options.name); // scan name. Can be used as a file name, for example. + pt->put("scanType",options.scanType); // scan type. Determines what loop setup to use + pt->put("Receiver",options.receiver); + pt->put("DataHandler",options.dataHandler); + pt->put("DataProc",options.dataProc); + pt->put("Timeout.Seconds",options.timeout.seconds); + pt->put("Timeout.Nanoseconds",options.timeout.nanoseconds); + pt->put("Timeout.AllowedTimeouts",options.timeout.allowedTimeouts); + pt->put("runNumber", options.runNumber); + pt->put("stagingMode",options.stagingMode); + //maskStages is not used in NewDsp, only nMaskStages + pt->put("maskStages", options.maskStages); + pt->put("nMaskStages",options.nMaskStages); + pt->put("firstStage",options.firstStage); + pt->put("stepStage",options.stepStage); + pt->put("nLoops",options.nLoops); + //Loops + for(int i=0;i<options.nLoops;i++){ + char loopname[128]; + sprintf (loopname,"scanLoop_%d.",i); + pt->put(std::string(loopname)+"scanParameter", options.scanLoop[i].scanParameter); + pt->put(std::string(loopname)+"nPoints",options.scanLoop[i].nPoints); + pt->put(std::string(loopname)+"endofLoopAction.Action", options.scanLoop[i].endofLoopAction.Action); + pt->put(std::string(loopname)+"endofLoopAction.fitFunction", options.scanLoop[i].endofLoopAction.fitFunction); + pt->put(std::string(loopname)+"endofLoopAction.targetThreshold", options.scanLoop[i].endofLoopAction.targetThreshold); + if(options.scanLoop[i].dataPoints.length()>0){ + char pointname[10]; + for(unsigned int j=0;j<options.scanLoop[i].dataPoints.length();j++){ + sprintf(pointname,"P_%d",j); + pt->put(std::string(loopname)+"dataPoints."+pointname,options.scanLoop[i].dataPoints[j]); + } + } + } + //Trigger options + pt->put("trigOpt.nEvents",options.trigOpt.nEvents); + pt->put("trigOpt.triggerMask",options.trigOpt.triggerMask); + pt->put("trigOpt.moduleTrgMask",options.trigOpt.moduleTrgMask); + pt->put("trigOpt.triggerDataOn",options.trigOpt.triggerDataOn); + pt->put("trigOpt.deadtime",options.trigOpt.deadtime); + pt->put("trigOpt.nL1AperEvent",options.trigOpt.nL1AperEvent); + pt->put("trigOpt.nTriggersPerGroup",options.trigOpt.nTriggersPerGroup); + pt->put("trigOpt.nTriggers",options.trigOpt.nTriggers); + pt->put("trigOpt.Lvl1_Latency",options.trigOpt.Lvl1_Latency); + pt->put("trigOpt.Lvl1_Latency_Secondary",options.trigOpt.Lvl1_Latency_Secondary); + pt->put("trigOpt.strobeDuration",options.trigOpt.strobeDuration); + pt->put("trigOpt.strobeMCCDelay",options.trigOpt.strobeMCCDelay); + pt->put("trigOpt.strobeMCCDelayRange",options.trigOpt.strobeMCCDelayRange); + pt->put("trigOpt.CalL1ADelay",options.trigOpt.CalL1ADelay); + pt->put("trigOpt.eventInterval",options.trigOpt.eventInterval); + pt->put("trigOpt.injectForTrigger",options.trigOpt.injectForTrigger); + pt->put("trigOpt.vcal_charge",options.trigOpt.vcal_charge); + pt->put("trigOpt.threshold",options.trigOpt.threshold); + pt->put("trigOpt.hitbusConfig",options.trigOpt.hitbusConfig); + + // each option gets an entry in the tree below optionsMask with value 1 + for (unsigned int i=0;i<options.trigOpt.optionsMask.length();i++){ + pt->put(std::string("trigOpt.optionsMask.")+(const char*)options.trigOpt.optionsMask[i],1); + } + pt->put("trigOpt.triggerMode", options.trigOpt.triggerMode); + + // front-end options + pt->put("feOpt.phi",options.feOpt.phi); + pt->put("feOpt.totThresholdMode",options.feOpt.totThresholdMode); + pt->put("feOpt.totMinimum",options.feOpt.totMinimum); + pt->put("feOpt.totTwalk",options.feOpt.totTwalk); + pt->put("feOpt.totLeMode",options.feOpt.totLeMode); + pt->put("feOpt.hitbus",options.feOpt.hitbus); + + pt->put("nHistoNames",options.histos.length()); + if(options.histos.length()>0){ + char pointname[10]; + for(unsigned int j=0;j<options.histos.length();j++){ + sprintf(pointname,"Name_%d",j); + pt->put(std::string("HistoNames.")+pointname,options.histos[j]); + } + } + //Trigger options + //call the real initScan function + //std::cout<<"Calling ScanRoot "<<std::endl; + configureScan(pt); + delete pt; + return 0; +} + +template <class TP> +ipc::StringVect* IPCScanRoot<TP>::IPCgetHistoNames(const char* reg){ + std::vector<std::string> strvec=HistoManager::instance()->getHistoNames(reg); + ipc::StringVect &ipcstringvect=*new ipc::StringVect; + ipcstringvect.length(strvec.size()); + for(size_t i=0;i<strvec.size();i++){ + ipcstringvect[i]=CORBA::string_dup(strvec[i].c_str()); + } + return &ipcstringvect; +} +template <class TP> +ipc::StringVect* IPCScanRoot<TP>::IPCgetPublishedHistoNames(){ + std::vector<std::string> strvec=HistoManager::instance()->getPublishedHistoNames(); + ipc::StringVect &ipcstringvect=*new ipc::StringVect; + ipcstringvect.length(strvec.size()); + for(size_t i=0;i<strvec.size();i++){ + ipcstringvect[i]=CORBA::string_dup(strvec[i].c_str()); + } + return &ipcstringvect; +} + +template <class TP> +CORBA::ULong IPCScanRoot<TP>::IPCnEvents(){ + if(m_dataProc) + return m_dataProc->nEvents(); + else + return 0; +} +template <class TP> +void IPCScanRoot<TP>::IPCresynch(){ + if(m_receiver) + m_receiver->resynch(); +} + +template <class TP> +void IPCScanRoot<TP>::IPCconfigureCallback(ipc::Callback_ptr cb, ipc::Priority pr){ + m_cb->configure(cb,pr); +} + +template <class TP> +void IPCScanRoot<TP>::shutdown(){ + std::cout<<"Shutdown"<<std::endl; +} + +#endif diff --git a/rce/pixelrce/scanctrl/IPCScanRoot.hh b/rce/pixelrce/scanctrl/IPCScanRoot.hh new file mode 100644 index 00000000..0704ccd7 --- /dev/null +++ b/rce/pixelrce/scanctrl/IPCScanRoot.hh @@ -0,0 +1,31 @@ +#ifndef IPCSCANROOT_HH +#define IPCSCANROOT_HH + +#include "scanctrl/ScanRoot.hh" +#include "ipc/object.h" +#include "ScanOptions.hh" +#include "IPCScanRootAdapter.hh" + +class IPCPartition; +class ConfigIF; +class Scan; +class IPCRceCallback; + +template <class TP = ipc::single_thread> +class IPCScanRoot: public IPCNamedObject<POA_ipc::IPCScanRootAdapter,TP>, public ScanRoot { +public: + IPCScanRoot(IPCPartition & p, const char * name, ConfigIF* cif, Scan* scan); + ~IPCScanRoot(); + CORBA::Long IPCconfigureScan(const ipc::ScanOptions &options); + ipc::StringVect* IPCgetHistoNames(const char* reg); + ipc::StringVect* IPCgetPublishedHistoNames(); + CORBA::ULong IPCnEvents(); + void IPCresynch(); + void IPCconfigureCallback(ipc::Callback_ptr cb, ipc::Priority pr); + void shutdown(); +private: + IPCRceCallback* m_cb; +}; + + +#endif diff --git a/rce/pixelrce/server/IPCCalibGui.cc b/rce/pixelrce/server/IPCCalibGui.cc new file mode 100644 index 00000000..0d3c6965 --- /dev/null +++ b/rce/pixelrce/server/IPCCalibGui.cc @@ -0,0 +1,54 @@ + +#include <ipc/partition.h> +#include <ipc/core.h> +#include "server/CalibGui.hh" +#include "server/IPCController.hh" +#include "server/IPCHistoController.hh" +#include <boost/program_options.hpp> +#include <TROOT.h> +#include <TStyle.h> +#include "TApplication.h" + +int main(int argc, char **argv){ + // + // Initialize command line parameters with default values + // + try { + IPCCore::init( argc, argv ); + } + catch( daq::ipc::Exception & ex ) { + ers::fatal( ex ); + return 1; + } + +// +// Parse arguments +// + boost::program_options::options_description desc("Allowed options"); + desc.add_options() + ("help,h", "produce help message") + ("partition,p", boost::program_options::value<std::string>(), "partition to work in."); + boost::program_options::variables_map vm; + boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm); + boost::program_options::notify(vm); + if(vm.count("help")){ + std::cout<<desc<<std::endl; + exit(0); + } + const char *p_name=getenv("TDAQ_PARTITION"); + if(p_name==NULL) p_name="rcetest"; + if(vm.count("partition"))p_name=vm["partition"].as<std::string>().c_str(); + IPCPartition* partition=new IPCPartition(p_name ); + AbsController* controller=new IPCController(*partition); + AbsHistoController* hcontroller=new IPCHistoController(*partition); + //check if somebody else is using the partition + gROOT->SetStyle("Plain"); + gStyle->SetOptStat(0); + gStyle->SetPalette(1); + + TApplication theapp("app",&argc,argv); + new CalibGui(controller, hcontroller, gClient->GetRoot(),800,735); + theapp.Run(); + return 0; +} + diff --git a/rce/pixelrce/server/IPCCallback.hh b/rce/pixelrce/server/IPCCallback.hh new file mode 100644 index 00000000..0d41d7eb --- /dev/null +++ b/rce/pixelrce/server/IPCCallback.hh @@ -0,0 +1,30 @@ +#ifndef IPCCALLBACK_HH +#define IPCCALLBACK_HH + +#include "ipc/object.h" +#include "Callback.hh" +#include <boost/thread/mutex.hpp> + +class IPCCallback : public IPCObject<POA_ipc::Callback> +{ +public: + IPCCallback(): m_rce(0){} + void notify( const ipc::CallbackParams &msg )=0; + void stopServer()=0; + void addRce(){m_rce++;} + void stop(){ + boost::mutex::scoped_lock pl( m_mutex ); + m_cond.notify_one(); + } + void run(){ + boost::mutex::scoped_lock pl(m_mutex); + m_cond.wait(pl); + } + +protected: + int m_rce; + boost::mutex m_mutex; + boost::condition_variable m_cond; +}; + +#endif diff --git a/rce/pixelrce/server/IPCController.cc b/rce/pixelrce/server/IPCController.cc new file mode 100644 index 00000000..ce5954ae --- /dev/null +++ b/rce/pixelrce/server/IPCController.cc @@ -0,0 +1,851 @@ + +#include "server/IPCController.hh" +#include "server/IPCRegularCallback.hh" +#include "server/IPCGuiCallback.hh" +#include "server/PixScan.hh" +#include "IPCFEI3Adapter.hh" +#include "IPCFEI4AAdapter.hh" +#include "IPCFEI4BAdapter.hh" +#include "IPCHitbusAdapter.hh" +#include "IPCAFPHPTDCAdapter.hh" +#include "IPCScanAdapter.hh" +#include "IPCConfigIFAdapter.hh" +#include "IPCScanRootAdapter.hh" +#include <is/infoT.h> +#include <is/infodictionary.h> +#include "ScanOptions.hh" +#include "ers/ers.h" +#include <stdio.h> +#include <string> + +IPCController::IPCController(IPCPartition &p):m_partition(p){} + +void IPCController::addRce(int rce){ + for(size_t i=0;i<m_rces.size();i++)if(m_rces[i]==rce)return; //RCE has already been added. + m_rces.push_back(rce); +} + + +void IPCController::downloadModuleConfig(int rce, int id, PixelConfig* config){ + config->downloadConfig(m_partition, rce, id); +} + +void IPCController::addModule(const char* name, const char* type, int id, int inLink, int outLink, int rce, const char* formatter){ + ipc::IPCConfigIFAdapter_var handle; + char cfa[128]; + sprintf(cfa, "configIF_RCE%d",rce); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + ipc::ModSetup s; + s.id=id; + s.inLink=inLink; + s.outLink=outLink; + std::string typestring; + if(std::string(type)=="FEI3")typestring="IPC_FEI3_multiThread"; + else if(std::string(type)=="FEI4A")typestring="IPC_FEI4A_multiThread"; + else if(std::string(type)=="FEI4B")typestring="IPC_FEI4B_multiThread"; + else if(std::string(type)=="Hitbus")typestring="IPC_Hitbus_multiThread"; + else if(std::string(type)=="HPTDC")typestring="IPC_AFPHPTDC_multiThread"; + else(assert(0)); + handle -> IPCsetupModule( name,typestring.c_str(),s , formatter); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } +} + +int IPCController::setupTrigger(const char* type){ + ipc::IPCConfigIFAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "configIF_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + return m_rces[i]+1000; + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + handle->IPCsetupTriggerIF(type); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } + return 0; +} + +void IPCController::removeAllModules(){ + ipc::IPCConfigIFAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "configIF_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + handle->IPCdeleteModules(); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } +} +void IPCController::startScan(){ + ipc::IPCScanAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "scanCtrl_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCScanAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + handle -> IPCstartScan( ); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } +} + +void IPCController::abortScan(){ + ipc::IPCScanAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "scanCtrl_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCScanAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + handle -> IPCabort( ); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } +} + +void IPCController::stopWaitingForData(){ + ipc::IPCScanAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "scanCtrl_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCScanAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + handle -> IPCstopWaiting( ); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } +} + +void IPCController::getEventInfo(unsigned* nevent) { + ipc::IPCConfigIFAdapter_var handle; + char cfa[128]; + assert(m_rces.size()>0); + sprintf(cfa, "configIF_RCE%d", m_rces[0]); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + *nevent= handle -> IPCnTrigger(); + + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } +} +int IPCController::verifyModuleConfigHW(int rce, int id) { + ipc::IPCConfigIFAdapter_var handle; + char cfa[128]; + int retval=0; + sprintf(cfa, "configIF_RCE%d",rce); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + retval|=handle -> IPCverifyModuleConfigHW(id); + + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + return retval; +} + +void IPCController::setupParameter(const char* par, int val) { + ipc::IPCConfigIFAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "configIF_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + handle -> IPCsetupParameter(par, val); + + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } +} + +void IPCController::setupMaskStage(int stage) { + ipc::IPCConfigIFAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "configIF_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + handle -> IPCsetupMaskStage(stage); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } +} + + +void IPCController::downloadScanConfig(ipc::ScanOptions& options){ + ipc::IPCScanRootAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "scanRoot_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCScanRootAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + handle -> IPCconfigureScan(options); + + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } +} + +void IPCController::waitForScanCompletion(ipc::Priority pr, CallbackInfo* callb){ + IPCCallback *cb=new IPCGuiCallback(callb); + ipc::IPCScanRootAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "scanRoot_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCScanRootAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + handle -> IPCconfigureCallback(cb->_this(), pr ); + cb->addRce(); + + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } + cb->run(); + cb->_destroy(); +} +void IPCController::runScan(ipc::Priority pr, CallbackInfo* callb){ + IPCCallback *cb=new IPCGuiCallback(callb); + ipc::IPCScanRootAdapter_var rhandle; + ipc::IPCScanAdapter_var shandle; + char cfa[128]; + char cfb[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "scanRoot_RCE%d", m_rces[i]); + sprintf(cfb, "scanCtrl_RCE%d", m_rces[i]); + try { + shandle = m_partition.lookup<ipc::IPCScanAdapter>( cfb ); + rhandle = m_partition.lookup<ipc::IPCScanRootAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + rhandle -> IPCconfigureCallback(cb->_this(), pr ); + cb->addRce(); + shandle->IPCstartScan(); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } + cb->run(); + cb->_destroy(); +} + +unsigned IPCController::getNEventsProcessed(){ + ipc::IPCScanRootAdapter_var handle; + char cfa[128]; + assert(m_rces.size()>0); + //maybe have to change if have multiple RCE's? + sprintf(cfa, "scanRoot_RCE%d", m_rces[0]); + try { + handle = m_partition.lookup<ipc::IPCScanRootAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + return handle -> IPCnEvents( ); + + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + return 0; +} + +void IPCController::resynch(){ + ipc::IPCScanRootAdapter_var handle; + char cfa[128]; + assert(m_rces.size()>0); + + for(size_t i=0;i<m_rces.size();i++){ + std::cout<<"IPCController sending resynch command to RCE "<<m_rces[i]<<std::endl; + + sprintf(cfa, "scanRoot_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCScanRootAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + handle -> IPCresynch( ); + + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + + } + +} + +void IPCController::resetFE(){ + ipc::IPCConfigIFAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "configIF_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + handle->IPCresetFE(); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } +} + +void IPCController::configureModulesHW(){ + ipc::IPCConfigIFAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "configIF_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + handle->IPCconfigureModulesHW(); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } +} + +unsigned IPCController::writeHWglobalRegister(const char* name, int reg, unsigned short val){ + ipc::IPCFEI4AAdapter_var modhandle; + try { + bool v=m_partition.isObjectValid<ipc::IPCFEI4AAdapter>(name); + if(!v) { + std::cout<<"Not valid"<<std::endl; + assert(0); + } + modhandle = m_partition.lookup<ipc::IPCFEI4AAdapter>( name ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + return modhandle->IPCwriteHWglobalRegister(reg,val); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + return 1000; +} + +unsigned IPCController::readHWglobalRegister(const char* name, int reg, unsigned short &val){ + ipc::IPCFEI4AAdapter_var modhandle; + try { + bool v=m_partition.isObjectValid<ipc::IPCFEI4AAdapter>(name); + if(!v) { + std::cout<<"Not valid"<<std::endl; + assert(0); + } + modhandle = m_partition.lookup<ipc::IPCFEI4AAdapter>( name ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + return modhandle->IPCreadHWglobalRegister(reg,val); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + return 1000; +} +unsigned IPCController::writeHWdoubleColumn(const char* name, unsigned bit, unsigned dcol, std::vector<unsigned> data, std::vector<unsigned> &retvec){ + ipc::IPCFEI4AAdapter_var modhandle; + try { + bool v=m_partition.isObjectValid<ipc::IPCFEI4AAdapter>(name); + if(!v) { + std::cout<<"Not valid"<<std::endl; + assert(0); + } + modhandle = m_partition.lookup<ipc::IPCFEI4AAdapter>( name ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + ipc::uvec ipcdata; + ipc::uvec_var retv; + ipcdata.length(data.size()); + for(size_t i=0;i<data.size();i++)ipcdata[i]=data[i]; + unsigned stat= modhandle->IPCwriteDoubleColumnHW(bit, dcol, ipcdata, retv); + for(unsigned i=0;i<retv->length();i++)retvec.push_back(retv[i]); + return stat; + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + return 1000; +} +unsigned IPCController::readHWdoubleColumn(const char* name, unsigned bit, unsigned dcol, std::vector<unsigned> &retvec){ + ipc::IPCFEI4AAdapter_var modhandle; + try { + bool v=m_partition.isObjectValid<ipc::IPCFEI4AAdapter>(name); + if(!v) { + std::cout<<"Not valid"<<std::endl; + assert(0); + } + modhandle = m_partition.lookup<ipc::IPCFEI4AAdapter>( name ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + ipc::uvec_var retv; + unsigned stat= modhandle->IPCreadDoubleColumnHW(bit, dcol, retv); + for(unsigned i=0;i<retv->length();i++)retvec.push_back(retv[i]); + return stat; + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + return 1000; +} + +unsigned IPCController::sendHWcommand(int rce, unsigned char opcode){ + ipc::IPCConfigIFAdapter_var handle; + bool foundRce=false; + for(size_t i=0;i<m_rces.size();i++)if(m_rces[i]==rce)foundRce=true; + assert(foundRce); + char cfa[128]; + sprintf(cfa, "configIF_RCE%d", rce); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + return handle->IPCsendHWcommand(opcode); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + return 1000; +} + +unsigned IPCController::writeHWregister(int rce, unsigned addr, unsigned val){ + ipc::IPCConfigIFAdapter_var handle; + bool foundRce=false; + for(size_t i=0;i<m_rces.size();i++)if(m_rces[i]==rce)foundRce=true; + assert(foundRce); + char cfa[128]; + sprintf(cfa, "configIF_RCE%d", rce); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + return handle->IPCwriteHWregister(addr,val); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + return 1000; +} + +unsigned IPCController::readHWregister(int rce, unsigned addr, unsigned &val){ + ipc::IPCConfigIFAdapter_var handle; + bool foundRce=false; + for(size_t i=0;i<m_rces.size();i++)if(m_rces[i]==rce)foundRce=true; + assert(foundRce); + char cfa[128]; + sprintf(cfa, "configIF_RCE%d", rce); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + return handle->IPCreadHWregister((CORBA::ULong)addr,(CORBA::ULong&) val); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + return 1000; +} +unsigned IPCController::writeHWblockData(int rce, std::vector<unsigned>& data){ + ipc::IPCConfigIFAdapter_var handle; + bool foundRce=false; + for(size_t i=0;i<m_rces.size();i++)if(m_rces[i]==rce)foundRce=true; + assert(foundRce); + char cfa[128]; + sprintf(cfa, "configIF_RCE%d", rce); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + ipc::blockdata ipcdata; + ipcdata.length(data.size()); + for(size_t i=0;i<data.size();i++)ipcdata[i]=data[i]; + return handle->IPCwriteHWblockData(ipcdata); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + return 1000; +} +unsigned IPCController::readHWblockData(int rce, std::vector<unsigned>& data,std::vector<unsigned>& retvec ){ + ipc::IPCConfigIFAdapter_var handle; + bool foundRce=false; + for(size_t i=0;i<m_rces.size();i++)if(m_rces[i]==rce)foundRce=true; + assert(foundRce); + char cfa[128]; + sprintf(cfa, "configIF_RCE%d", rce); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + ipc::blockdata ipcdata; + ipc::blockdata_var retv; + ipcdata.length(data.size()); + for(size_t i=0;i<data.size();i++)ipcdata[i]=data[i]; + unsigned stat= handle->IPCreadHWblockData(ipcdata, retv); + for(unsigned i=0;i<retv->length();i++)retvec.push_back(retv[i]); + return stat; + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + return 1000; +} + +unsigned IPCController::readHWbuffers(int rce, std::vector<unsigned char>& retvec ){ + ipc::IPCConfigIFAdapter_var handle; + bool foundRce=false; + for(size_t i=0;i<m_rces.size();i++)if(m_rces[i]==rce)foundRce=true; + assert(foundRce); + char cfa[128]; + sprintf(cfa, "configIF_RCE%d", rce); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + ipc::chardata_var retv; + unsigned nbuf= handle->IPCreadHWbuffers(retv); + for(unsigned i=0;i<retv->length();i++)retvec.push_back(retv[i]); + return nbuf; + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + return (unsigned)-1; +} + +int IPCController::getScanStatus(){ + ipc::IPCScanAdapter_var handle; + int status=0; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "scanCtrl_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCScanAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + status|= handle->IPCgetStatus(); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } + return status; +} + +bool IPCController::guiRunning(){ + ISInfoDictionary dict(m_partition); + ISInfoInt gui_running(0); + try{ + dict.getValue("RceIsServer.GUI_running", gui_running); + }catch(daq::is::RepositoryNotFound){ + std::cout<<"RceIsServer not running in the partition"<<std::endl; + exit(0); + }catch(daq::is::InfoNotFound){ + //std::cout<<"No entry for GUI_running"<<std::endl; + } + return gui_running; +} +void IPCController::setGuiRunning(bool on){ + ISInfoDictionary dict(m_partition); + ISInfoInt gui_running(on); + dict.checkin("RceIsServer.GUI_running", gui_running); +} diff --git a/rce/pixelrce/server/IPCController.hh b/rce/pixelrce/server/IPCController.hh new file mode 100644 index 00000000..21599ff3 --- /dev/null +++ b/rce/pixelrce/server/IPCController.hh @@ -0,0 +1,64 @@ +#ifndef IPCCONTROLLER_HH +#define IPCCONTROLLER_HH + +#include "ipc/partition.h" +#include "server/AbsController.hh" +#include "config/PixelConfig.hh" +#include "IPCScanRootAdapter.hh" +#include "IPCScanAdapter.hh" +#include <vector> +#include <map> + +class IPCCallback; +class CallbackInfo; +namespace ipc{ + class ScanOptions; +} + +class IPCController: public AbsController{ +public: + IPCController() {}; + IPCController(IPCPartition &p); + void addRce(int rce); + bool guiRunning(); + void setGuiRunning(bool on); + + void downloadModuleConfig(int rce, int id, PixelConfig* config); + void addModule(const char* name, const char* type, int id, int inLink, int outLink, int rce, const char* formatter); + int setupTrigger(const char* type="default"); + void removeAllModules(); + void resetFE(); + void configureModulesHW(); + + unsigned writeHWglobalRegister(const char* name, int reg, unsigned short val); + unsigned readHWglobalRegister(const char* name, int reg, unsigned short& val); + unsigned writeHWdoubleColumn(const char* name, unsigned bit, unsigned dcol, std::vector<unsigned> data, std::vector<unsigned> &retvec); + unsigned readHWdoubleColumn(const char* name, unsigned bit, unsigned dcol, std::vector<unsigned> &retvec); + + unsigned writeHWregister(int rce, unsigned addr, unsigned val); + unsigned readHWregister(int rce, unsigned addr, unsigned& val); + unsigned sendHWcommand(int rce, unsigned char opcode); + unsigned writeHWblockData(int rce, std::vector<unsigned> &data); + unsigned readHWblockData(int rce, std::vector<unsigned> &data, std::vector<unsigned>& retvec); + unsigned readHWbuffers(int rce, std::vector<unsigned char>& retvec); + + void downloadScanConfig(ipc::ScanOptions &scn); + int verifyModuleConfigHW(int rce, int id); + + void waitForScanCompletion(ipc::Priority pr, CallbackInfo* callb); + void runScan(ipc::Priority pr, CallbackInfo* callb); + void startScan(); + void abortScan(); + void stopWaitingForData(); + void getEventInfo(unsigned* nevent); + int getScanStatus(); + unsigned getNEventsProcessed(); + void resynch(); + void setupParameter(const char* par, int val); + void setupMaskStage(int stage); +private: + + IPCPartition m_partition; +}; + +#endif diff --git a/rce/pixelrce/server/IPCCosmicGui.cc b/rce/pixelrce/server/IPCCosmicGui.cc new file mode 100644 index 00000000..ace91aed --- /dev/null +++ b/rce/pixelrce/server/IPCCosmicGui.cc @@ -0,0 +1,62 @@ + +#include <ipc/partition.h> +#include <ipc/core.h> +#include "server/CosmicGui.hh" +#include "server/IPCController.hh" +#include "util/HistoManager.hh" +#include "TApplication.h" +#include <TROOT.h> +#include <TStyle.h> +#include <boost/program_options.hpp> +#include <is/infoT.h> +#include <is/infodictionary.h> + +int main(int argc, char **argv){ + // + // Initialize command line parameters with default values + // + try { + IPCCore::init( argc, argv ); + } + catch( daq::ipc::Exception & ex ) { + ers::fatal( ex ); + return 1; + } + +// +// Declare command object and its argument-iterator +// + bool start; + boost::program_options::options_description desc("Allowed options"); + desc.add_options() + ("help,h", "produce help message") + ("start,s", boost::program_options::value<bool>(&start)->default_value(false), "Start run when GUI comes up") + ("partition,p", boost::program_options::value<std::string>(), "partition to work in."); + boost::program_options::variables_map vm; + boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm); + boost::program_options::notify(vm); + if(vm.count("help")){ + std::cout<<desc<<std::endl; + exit(0); + } + const char *p_name=getenv("TDAQ_PARTITION"); + if(p_name==NULL) p_name="rcetest"; + if(vm.count("partition"))p_name=vm["partition"].as<std::string>().c_str(); + try{ + IPCPartition p(p_name ); + IPCController controller(p); + AbsController &acontroller(controller); + new HistoManager(0); + + gROOT->SetStyle("Plain"); + TApplication theapp("app",&argc,argv); + new CosmicGui(acontroller, start, gClient->GetRoot(),800, 735); + theapp.Run(); + return 0; + }catch(...){ + std::cout<<"Partition "<<p_name<<" does not exist."<<std::endl; + exit(0); + } +} + + diff --git a/rce/pixelrce/server/IPCGuiCallback.cc b/rce/pixelrce/server/IPCGuiCallback.cc new file mode 100644 index 00000000..cc109615 --- /dev/null +++ b/rce/pixelrce/server/IPCGuiCallback.cc @@ -0,0 +1,29 @@ + +#include "server/IPCGuiCallback.hh" +#include "server/CallbackInfo.hh" + +void IPCGuiCallback::notify(const ipc::CallbackParams& msg){ + if(msg.status==ipc::SCANNING){ + m_cbinfo->setStage(msg.maskStage); + m_cbinfo->addToMask(CallbackInfo::NEWSTAGE); + std::cout<<"RCE "<<msg.rce<<": Mask Stage "<<msg.maskStage<<std::endl; + }else if(msg.status==ipc::FITTING){ + std::cout<<"RCE "<<msg.rce<<": Fitting"<<std::endl; + m_cbinfo->addToMask(CallbackInfo::FIT); + }else if(msg.status==ipc::DOWNLOADING){ + std::cout<<"RCE "<<msg.rce<<": Downloading"<<std::endl; + m_cbinfo->addToMask(CallbackInfo::DOWNLOAD); + }else if(msg.status==ipc::FAILED){ + m_cbinfo->addToMask(CallbackInfo::FAILED); + std::cout<<"RCE "<<msg.rce<<": Failed"<<std::endl; + } +} + +void IPCGuiCallback::stopServer(){ + m_rce--; + if(m_rce<=0){ + m_cbinfo->addToMask(CallbackInfo::STOP); + stop(); + } +} + diff --git a/rce/pixelrce/server/IPCGuiCallback.hh b/rce/pixelrce/server/IPCGuiCallback.hh new file mode 100644 index 00000000..77e779b9 --- /dev/null +++ b/rce/pixelrce/server/IPCGuiCallback.hh @@ -0,0 +1,18 @@ +#ifndef IPCGUICALLBACK_HH +#define IPCGUICALLBACK_HH + +#include "server/IPCCallback.hh" + +class CallbackInfo; + +class IPCGuiCallback : public IPCCallback { +public: + IPCGuiCallback(CallbackInfo* info): IPCCallback(),m_cbinfo(info){ + } + void notify( const ipc::CallbackParams & msg ); + void stopServer(); +private: + CallbackInfo* m_cbinfo; +}; + +#endif diff --git a/rce/pixelrce/server/IPCHistoController.cc b/rce/pixelrce/server/IPCHistoController.cc new file mode 100644 index 00000000..dfe22e24 --- /dev/null +++ b/rce/pixelrce/server/IPCHistoController.cc @@ -0,0 +1,170 @@ + +#include "server/IPCHistoController.hh" +#include "IPCScanRootAdapter.hh" +#include "ers/ers.h" +#include <oh/OHIterator.h> +#ifdef TDAQ_RELEASE_4 +#include <oh/OHServerIterator.h> +#endif +#include <oh/OHRootReceiver.h> +#include <is/infodictionary.h> +#include "TH1D.h" +#include "TH2D.h" +#include "TH2C.h" +#include "TH2S.h" + +class HistoReceiver : public OHRootReceiver { +public: + void clearList(){ + m_list.clear(); + } + void receive( OHRootHistogram & h ) + { + m_list.push_back(h.histogram.get()); + h.histogram.release(); // we ask the histogram auto_ptr to drop ownership + // for the histogram since it will be kept by ROOT + } + std::vector<TH1*>& getHistos(){return m_list;} +private: + std::vector<TH1*> m_list; +}; + +IPCHistoController::IPCHistoController(IPCPartition &p):m_partition(p){} +void IPCHistoController::addRce(int rce){ + for(size_t i=0;i<m_rces.size();i++)if(m_rces[i]==rce)return; //RCE has already been added. + m_rces.push_back(rce); +} +void IPCHistoController::removeAllRces(){ + m_rces.clear(); +} + +std::vector<TH1*> IPCHistoController::getHistos(const char* reg){ + HistoReceiver hr; + try{ + OHHistogramIterator it( m_partition, "RceIsServer", ".*", reg); + while ( it++ ){ + it.retrieve( hr ); + if(hr.getHistos().back()!=0) + hr.getHistos().back()->SetName(it.name().c_str()); + } + }catch(daq::is::InvalidCriteria){ + std::cout<<"Invalid object"<<std::endl; + }catch(daq::is::RepositoryNotFound){ + std::cout<<"Object not found"<<std::endl; + }catch ( daq::ipc::InvalidPartition & ex ){ + std::cout<<"partition does not exist"<<std::endl; + }catch ( daq::is::Exception & ex ){ + std::cout<<"IS exception"<<std::endl; + }catch(...){ + std::cout<<"Something else went wrong"<<std::endl; + } + return hr.getHistos(); +} + +std::vector<std::string> IPCHistoController::getHistoNames(const char* reg){ + std::vector<std::string> retvect; + ipc::StringVect_var stringvect; + ipc::IPCScanRootAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "scanRoot_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCScanRootAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + stringvect=handle -> IPCgetHistoNames(reg); + + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + + + for(unsigned int i=0;i<stringvect->length();i++){ + retvect.push_back(std::string(stringvect[i])); + } + } + return retvect; +} + +std::vector<std::string> IPCHistoController::getPublishedHistoNames(){ + std::vector<std::string> retvect; + ipc::StringVect_var stringvect; + ipc::IPCScanRootAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "scanRoot_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCScanRootAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + stringvect=handle -> IPCgetPublishedHistoNames(); + + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + + + for(unsigned int i=0;i<stringvect->length();i++){ + retvect.push_back(std::string(stringvect[i])); + } + } + return retvect; + } + + + +bool IPCHistoController::clear() +{ +#ifndef TDAQ_RELEASE_4 + ISInfoDictionary dict(m_partition); + try{ + dict.removeAll("RceIsServer", ~oh::Histogram::type() ); + } + catch( daq::is::Exception &ex){ + ers::error( ex ); + return false; + } + return true; +#else + try { + OHServerIterator sit( m_partition, "RceIsServer" ); + while ( sit++ ) { + try { + OHHistogramIterator hit(m_partition, sit.name(), ".*", ".*"); + if ( hit.entries() ) { + hit.removeAll(); + } + } catch( ers::Issue & ex ) { + ers::error( ex ); + return false; + } + } + } catch ( ers::Issue & ex ) { + ers::error( ex ); + return false; + } + + return true; +#endif +} + diff --git a/rce/pixelrce/server/IPCHistoController.hh b/rce/pixelrce/server/IPCHistoController.hh new file mode 100644 index 00000000..df10265b --- /dev/null +++ b/rce/pixelrce/server/IPCHistoController.hh @@ -0,0 +1,30 @@ +#ifndef IPCHISTOCONTROLLER_HH +#define IPCHISTOCONTROLLER_HH + +#include "ipc/partition.h" +#include "IPCScanRootAdapter.hh" +#include "server/AbsHistoController.hh" +#include <vector> + +#include <TH1.h> + + +class IPCHistoController: public AbsHistoController{ +public: + IPCHistoController() {}; + IPCHistoController(IPCPartition &p); + + void addRce(int rce); + void removeAllRces(); + std::vector<TH1*> getHistos(const char* reg); + std::vector<std::string> getHistoNames(const char* reg); + std::vector<std::string> getPublishedHistoNames(); + + std::string getIPCPartitionName() { return m_partition.name(); } + + bool clear(); + + IPCPartition m_partition; +}; + +#endif diff --git a/rce/pixelrce/server/IPCRceOfflineProducer.cc b/rce/pixelrce/server/IPCRceOfflineProducer.cc new file mode 100644 index 00000000..cb162885 --- /dev/null +++ b/rce/pixelrce/server/IPCRceOfflineProducer.cc @@ -0,0 +1,76 @@ +#include <ipc/core.h> +#include "server/RceOfflineProducer.hh" +#include "server/IPCController.hh" +#include "util/HistoManager.hh" +#include <boost/program_options.hpp> +#include <netdb.h> + + +int main ( int argc, char ** argv ) +{ + int rce; + std::string hostname; + boost::program_options::options_description desc("Allowed options"); + desc.add_options() + ("help,h", "produce help message") + ("rce,r", boost::program_options::value<int>(&rce)->required(), "RCE to connect to") + ("runcontrol,d", boost::program_options::value<std::string>(&hostname)->required(), "Runcontrol hostname") + ("partition,p", boost::program_options::value<std::string>(), "partition to work in."); + boost::program_options::variables_map vm; + try{ + boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm); + boost::program_options::notify(vm); + }catch(boost::program_options::error& e){ + std::cout<<std::endl<<"ERROR: "<<e.what()<<std::endl<<std::endl; + std::cout<<desc<<std::endl; + exit(0); + } + + if(vm.count("help")){ + std::cout<<desc<<std::endl; + exit(0); + } + + try { + IPCCore::init( argc, argv ); + } + catch( daq::ipc::Exception & ex ) { + ers::fatal( ex ); + return 1; + } + + std::string rchost; + hostent * ipAddrContainer = gethostbyname(hostname.c_str()); + if (ipAddrContainer != 0) { + int nBytes; + if (ipAddrContainer->h_addrtype == AF_INET) nBytes = 4; + else if (ipAddrContainer->h_addrtype == AF_INET6) nBytes = 6; + else { + std::cout << "Unrecognized IP address type. Run not started." + << std::endl; + exit(0); + } + std::stringstream ss("tcp://"); + ss << "tcp://"; + for (int i = 0, curVal; i < nBytes; i++) + { + curVal = static_cast<int>(ipAddrContainer->h_addr[i]); + if (curVal < 0) curVal += 256; + ss << curVal; + if (i != nBytes - 1) ss << "."; + } + ss<<":44000"; + rchost=ss.str(); + }else{ + std::cout<<"Bad IP address. Exiting."<<std::endl; + exit(0); + } + const char *p_name=getenv("TDAQ_PARTITION"); + if(p_name==NULL) p_name="rcetest"; + if(vm.count("partition"))p_name=vm["partition"].as<std::string>().c_str(); + IPCPartition p(p_name ); + IPCController controller(p); + new HistoManager(0); + RceOfflineProducer producer("RceOfflineProducer", rchost.c_str(), &controller, rce); + sleep(100000000); +} diff --git a/rce/pixelrce/server/IPCRegularCallback.cc b/rce/pixelrce/server/IPCRegularCallback.cc new file mode 100644 index 00000000..ea0a12c2 --- /dev/null +++ b/rce/pixelrce/server/IPCRegularCallback.cc @@ -0,0 +1,19 @@ + +#include "server/IPCRegularCallback.hh" + +void IPCRegularCallback::notify(const ipc::CallbackParams& msg){ + if(msg.status==ipc::SCANNING){ + std::cout<<"RCE "<<msg.rce<<": Mask Stage "<<msg.maskStage<<std::endl; + }else if(msg.status==ipc::FITTING){ + std::cout<<"RCE "<<msg.rce<<": Fitting"<<std::endl; + } +} + +void IPCRegularCallback::stopServer(){ + m_rce--; + if(m_rce<=0){ + std::cout<<"Done"<<std::endl; + stop(); + } +} + diff --git a/rce/pixelrce/server/IPCRegularCallback.hh b/rce/pixelrce/server/IPCRegularCallback.hh new file mode 100644 index 00000000..b9a9a592 --- /dev/null +++ b/rce/pixelrce/server/IPCRegularCallback.hh @@ -0,0 +1,13 @@ +#ifndef IPCREGULARCALLBACK_HH +#define IPCREGULARCALLBACK_HH + +#include "server/IPCCallback.hh" + +class IPCRegularCallback : public IPCCallback { +public: + IPCRegularCallback(): IPCCallback(){} + void notify( const ipc::CallbackParams & msg ); + void stopServer(); +}; + +#endif diff --git a/rce/pixelrce/server/IPClinux_server_pgp.cc b/rce/pixelrce/server/IPClinux_server_pgp.cc new file mode 100644 index 00000000..0e3ae500 --- /dev/null +++ b/rce/pixelrce/server/IPClinux_server_pgp.cc @@ -0,0 +1,104 @@ +// +// linux_server_pgp.cc +// +// IPC based calibration executable for Linux. +// +// Martin Kocian +///////////////////////////////////////////////////////////////////////////////// +#include <stdio.h> +#include <signal.h> +#include <unistd.h> + +#include <ipc/object.h> +#include <ipc/alarm.h> +#include <ipc/core.h> + +#include "util/IPCProvider.hh" +#include "util/HistoManager.hh" +#include "scanctrl/IPCScan.cc" +#include "scanctrl/IPCScanRoot.cc" +#include "config/IPCConfigIF.cc" +#include "HW/SerialHexdump.hh" +#include "HW/SerialPgpFei4.hh" +#include "config/IPCModuleFactory.hh" +#include "util/RceName.hh" +#include "util/IsMonitoring.hh" +#include "scanctrl/Scan.hh" +#include "server/PgpModL.hh" +boost::mutex mutex; +boost::condition_variable cond; + + +void sig_handler( int sig ) +{ + std::cout << " :: [IPCServer::sigint_handler] the signal " << sig << " received - exiting ... "<<std::endl; + boost::mutex::scoped_lock pl( mutex ); + cond.notify_one(); +} + + +////////////////////////////////////////// +// +// Main function +// +////////////////////////////////////////// + + +int main ( int argc, char ** argv ) +{ + + try { + IPCCore::init( argc, argv ); + } + catch( daq::ipc::Exception & ex ) { + ers::fatal( ex ); + return 1; + } + + + signal( SIGINT , sig_handler ); + signal( SIGTERM, sig_handler ); + + + const char *p_name=getenv("TDAQ_PARTITION"); + if(p_name==NULL) p_name="rcetest"; + IPCPartition p((const char*)p_name); + + //Serial IF + PgpModL pgp; + pgp.open(); + //new SerialHexdump; + new SerialPgpFei4; + + new IsMonitoring(p, "RceIsServer", RceName::getRceNumber()); + + //Module Factory + + ModuleFactory *moduleFactory=new IPCModuleFactory(p); + + char name[128]; + sprintf(name, "configIF_RCE%d", RceName::getRceNumber()); + // Config IF + IPCConfigIF<ipc::single_thread> *cif=new IPCConfigIF<ipc::single_thread>(p, name, moduleFactory); + + sprintf(name, "scanCtrl_RCE%d", RceName::getRceNumber()); + IPCScan<ipc::multi_thread> *scan = new IPCScan<ipc::multi_thread>( p, name); + sprintf(name, "scanRoot_RCE%d", RceName::getRceNumber()); + IPCScanRoot<ipc::single_thread> * scanroot = new IPCScanRoot<ipc::single_thread>( p, name, (ConfigIF*)cif, (Scan*)scan); + + sprintf(name, "RCE%d", RceName::getRceNumber()); + Provider* ipcprov=new Provider(p,"RceIsServer", name); + new HistoManager(ipcprov); + // + std::cout << "ipc_test_server has been started." << std::endl; + + boost::mutex::scoped_lock pl(mutex); + cond.wait(pl); + std::cout << "Shutdown." << std::endl; + + cif->_destroy(); + scanroot->_destroy(); + scan->_destroy(); + + return 0; +} diff --git a/rce/pixelrce/server/IPCrebootHSIO.cc b/rce/pixelrce/server/IPCrebootHSIO.cc new file mode 100644 index 00000000..61b78d20 --- /dev/null +++ b/rce/pixelrce/server/IPCrebootHSIO.cc @@ -0,0 +1,80 @@ + +#include <ipc/partition.h> +#include <ipc/core.h> +#include <ipc/object.h> +#include <boost/regex.hpp> +#include "server/IPCController.hh" +#include "IPCConfigIFAdapter.hh" + +#include <boost/program_options.hpp> +#include <iostream> +#include <stdlib.h> + +int main( int argc, char ** argv ){ + boost::program_options::options_description desc("Allowed options"); + desc.add_options() + ("help,h", "produce help message") + ("partition,p", boost::program_options::value<std::string>(), "partition to work in."); + boost::program_options::variables_map vm; + boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm); + boost::program_options::notify(vm); + if(vm.count("help")){ + std::cout<<desc<<std::endl; + exit(0); + } + +// +// Initialize command line parameters with default values +// + try { + IPCCore::init( argc, argv ); + } + catch( daq::ipc::Exception & ex ) { + ers::fatal( ex ); + return 1; + } + + const char *p_name=getenv("TDAQ_PARTITION"); + if(p_name==NULL) p_name="rcetest"; + if(vm.count("partition"))p_name=vm["partition"].as<std::string>().c_str(); + IPCPartition p(p_name ); + IPCController controller(p); + // How many RCEs are in the partition? + std::map< std::string, ipc::IPCConfigIFAdapter_var > objects; + std::vector<int> rces; + p.getObjects<ipc::IPCConfigIFAdapter>( objects ); + std::map< std::string, ipc::IPCConfigIFAdapter_var >::iterator it; + for ( it = objects.begin(); it != objects.end(); it++ ){ + boost::regex re("configIF_RCE(\\d+)"); + boost::cmatch matches; + if(boost::regex_search(it->first.c_str(), matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + rces.push_back(strtol(match.c_str(),0,10)); + } + } + if(rces.size()==0){ + std::cout<<"No RCE in your partition. Exiting."<<std::endl; + exit(0); + } + int rce=rces[0]; + if(rces.size()>1){ + std::cout<<"There are multiple RCEs in your partition:"<<std::endl; + while(1){ + for(size_t i=0;i<rces.size();i++)std::cout<<rces[i]<<std::endl; + std::cout<<"Which one has the HSIO attached that you would like to reboot (99 = all)?"<<std::endl; + std::cin>>rce; + bool valid=false; + for(size_t i=0;i<rces.size();i++)if(rce==99 || rce==rces[i])valid=true; + if(valid)break; + std::cout<<"This RCE is not on the list. Try again."<<std::endl; + } + } + for(size_t i=0;i<rces.size();i++){ + if(rce==99||rce==rces[i]){ + controller.addRce(rces[i]); + std::cout<<"Rebooting HSIO on RCE "<<rces[i]<<std::endl; + controller.sendHWcommand(rces[i],8); //reboot + } + } +} diff --git a/rce/pixelrce/util/IPCProvider.hh b/rce/pixelrce/util/IPCProvider.hh new file mode 100644 index 00000000..b5497092 --- /dev/null +++ b/rce/pixelrce/util/IPCProvider.hh @@ -0,0 +1,53 @@ +#ifndef PROVIDER_HH +#define PROVIDER_HH +#include "ipc/partition.h" +#include "oh/OHRawProvider.h" +#include "util/RceHistoAxis.hh" + +class OHBins; +template<class T> class OHRawProvider; + +class Provider { +public: + Provider(IPCPartition& p, const char* servername, const char* providername){ + m_provider=new OHRawProvider<>(p, servername, providername, 0); + } + ~Provider(){ + delete m_provider; + } + double dsw(float inval){ +#ifdef __rtems__ + return (double)inval; +#else + double invald=(double)inval; + unsigned long long iv=*(unsigned long long*)&invald; + unsigned long long ov=iv<<32 | iv>>32; + return *(double*)&ov; +#endif + } + template<class TC,class TE> + void publish(const std::string & name, + const std::string & title, + RceHistoAxis & xaxis, + const TC * bins, + const TE * errors, + bool hasOverflowAndUnderflow, + int tag , + const std::vector< std::pair<std::string,std::string> > & annotations) ; + template<class TC,class TE> + void publish(const std::string & name, + const std::string & title, + RceHistoAxis & xaxis, + RceHistoAxis & yaxis, + const TC * bins, + const TE * errors, + bool hasOverflowAndUnderflow, + int tag , + const std::vector< std::pair<std::string,std::string> > & annotations ) ; +private: + OHRawProvider<OHBins>* m_provider; +}; + +#include "util/IPCProvider.i" + +#endif diff --git a/rce/pixelrce/util/IPCProvider.i b/rce/pixelrce/util/IPCProvider.i new file mode 100644 index 00000000..c6a82a2b --- /dev/null +++ b/rce/pixelrce/util/IPCProvider.i @@ -0,0 +1,58 @@ +#ifndef PROVIDER_CC +#define PROVIDER_CC + + +template<class TC,class TE> +void +Provider::publish(const std::string & name, + const std::string & title, + RceHistoAxis & xaxis, + const TC * bins, + const TE * errors, + bool hasOverflowAndUnderflow, + int tag , + const std::vector< std::pair<std::string,std::string> > & annotations){ + OHAxis xaxisoh=OHMakeAxis<double>(xaxis.label().c_str(), xaxis.bincount(), dsw(xaxis.low()), dsw(xaxis.width()) ); + // Publish in OH + try { + m_provider->publish(name, title, xaxisoh, bins, errors, hasOverflowAndUnderflow, tag, annotations); + } catch (daq::oh::RepositoryNotFound) { + std::string mess = "The repository is not found "; + std::cout<<mess<<std::endl; + } catch (daq::oh::ObjectTypeMismatch) { + std::string mess = "Arguments invalid "; + std::cout<<mess<<std::endl; + } catch (...) { + std::string mess = "Unknown exception thrown "; + std::cout<<mess<<std::endl; + } +} + +template<class TC,class TE> +void +Provider::publish(const std::string & name, + const std::string & title, + RceHistoAxis & xaxis, + RceHistoAxis & yaxis, + const TC * bins, + const TE * errors, + bool hasOverflowAndUnderflow, + int tag, + const std::vector< std::pair<std::string,std::string> > & annotations ) { + OHAxis xaxisoh=OHMakeAxis<double>(xaxis.label().c_str(), xaxis.bincount(), dsw(xaxis.low()), dsw(xaxis.width()) ); + OHAxis yaxisoh=OHMakeAxis<double>(yaxis.label().c_str(), yaxis.bincount(), dsw(yaxis.low()), dsw(yaxis.width()) ); + try { + m_provider->publish(name, title, xaxisoh, yaxisoh, bins, errors, hasOverflowAndUnderflow, tag, annotations); + } catch (daq::oh::RepositoryNotFound) { + std::string mess = "The repository is not found "; + std::cout<<mess<<std::endl; + } catch (daq::oh::ObjectTypeMismatch) { + std::string mess = "Arguments invalid "; + std::cout<<mess<<std::endl; + } catch (...) { + std::string mess = "Unknown exception thrown "; + std::cout<<mess<<std::endl; + } +} + +#endif diff --git a/rce/projects.mk b/rce/projects.mk new file mode 100644 index 00000000..43dc1696 --- /dev/null +++ b/rce/projects.mk @@ -0,0 +1,34 @@ +# List of projects (low level first) +projects := rtems +projects+= root +ifeq ($(RCE_CORE_VERSION),2.2) +projects+=tool +projects+=configuration +projects+=service +projects+=oldPpi +projects+=platform +else +projects+= rce +projects+= rceusr +projects+= rceapp +endif +projects+= rcecalib +projects+= rcedcs +rtems_use := $(RTEMS) +ifeq ($(RCE_CORE_VERSION),2.2) +tool_use:=$(RCE_CORE)/build/tool +configuration_use:=$(RCE_CORE)/build/configuration +service_use:=$(RCE_CORE)/build/service +oldPpi_use:=$(RCE_CORE)/build/oldPpi +platform_use+=$(RCE_CORE)/build/platform +else +rce_use := $(RCE_CORE)/build/rce +rceusr_use := $(RCE_CORE)/build/rceusr +rceapp_use := $(RCE_CORE)/build/rceapp +endif +rcecalib_use := release +rcedcs_use := release +root_use := $(ROOTSYS) + + + diff --git a/rce/rcecalib/HW/BitStream.hh b/rce/rcecalib/HW/BitStream.hh new file mode 100644 index 00000000..8023f0f6 --- /dev/null +++ b/rce/rcecalib/HW/BitStream.hh @@ -0,0 +1,22 @@ +#ifndef BITSTREAM_HH +#define BITSTREAM_HH + +#include <vector> + +typedef std::vector<unsigned> BitStream; + +class BitStreamUtils{ +public: + static void byteSwap(BitStream* bs){ + for (unsigned int i=0;i<bs->size();i++){ + unsigned tmp=(*bs)[i]; + (*bs)[i] = ((tmp&0xff)<<24) | ((tmp&0xff00)<<8) | + ((tmp&0xff0000)>>8) | ((tmp&0xff000000)>>24); + } + } + static void prependZeros(BitStream *bs, int num=4){ + for(int i=0;i<num;i++)bs->push_back(0); + } +}; + +#endif diff --git a/rce/rcecalib/HW/Headers.hh b/rce/rcecalib/HW/Headers.hh new file mode 100644 index 00000000..daa46766 --- /dev/null +++ b/rce/rcecalib/HW/Headers.hh @@ -0,0 +1,107 @@ +#include <new> + +namespace PgpTrans{ + + class PgpHeader { + public: + enum VChannel {VC0, VC1, VC2, VC3}; + PgpHeader() {} + PgpHeader(VChannel vc, unsigned dest, unsigned tid) {_data = (tid<<8) | + (dest&1)<<2 | vc;} + unsigned tid() const {return (_data&0xffffff00)>>8;} + VChannel vc() const {return (VChannel)(_data&0x3);} + unsigned const destination() {return ((_data&4)>>2);} + private: + unsigned _data; + }; + + class PgpHeaderSwapped { + public: + enum VChannel {VC0, VC1, VC2, VC3}; + PgpHeaderSwapped() {} + PgpHeaderSwapped(VChannel vc, unsigned dest, unsigned tid) {_data = (tid<<8) | + (dest&1)<<2 | vc;} + unsigned tid() const {return (_data&0xffffff00)>>24;} + VChannel vc() const {return (VChannel)((_data>>16)&0x3);} + unsigned const destination() {return (((_data>>16)&4)>>2);} + private: + unsigned _data; + }; + + class RegHeader { + public: + RegHeader() {} + enum Opcode {Read, Write, Set, Clear}; + RegHeader(unsigned address, Opcode oc) {_data = (oc<<30) | address;} + RegHeader(unsigned address, Opcode oc, unsigned writeData) { + new(this) RegHeader(address, oc); + data = writeData; + } + unsigned address() {return _data&0xffffff;} + Opcode opcode() {return (Opcode)((_data>>30)&0x3);} + unsigned timeout() {return _status&0x20000;} + unsigned fail() {return _status&0x10000;} + unsigned status() {return _status;} + private: + unsigned _data; + public: + unsigned data; + private: + unsigned _status; + }; + + class RegTxHeader { + public: + RegTxHeader() {} + PgpHeader pgpHeader; + RegHeader regHeader; + RegTxHeader(unsigned tid, unsigned addr, RegHeader::Opcode oc) : + pgpHeader(PgpHeader::VC1, 0, tid), regHeader(addr, oc) {} + RegTxHeader(unsigned tid, unsigned addr, RegHeader::Opcode oc, + unsigned data) { + new(this) RegTxHeader(tid, addr, oc); + regHeader.data=data; + } + }; + + class RegRxHeader { + public: + RegRxHeader() {} + PgpHeader pgpHeader; + RegHeader regHeader; + }; + class CmdHeader { + public: + CmdHeader() {} + CmdHeader( unsigned char oc) {_data = (unsigned)oc;} + unsigned char opcode() {return (unsigned char)(_data&0xff);} + private: + unsigned _data; + }; + + class CmdTxHeader { + public: + CmdTxHeader() {} + PgpHeader pgpHeader; + CmdHeader cmdHeader; + CmdTxHeader( unsigned char oc, unsigned tid=0) : + pgpHeader(PgpHeader::VC0, 0, tid), cmdHeader(oc) {} + }; + class BlockWriteHeader{ + public: + BlockWriteHeader(bool handshake){ + _data= handshake ? 1: 0; + } + private: + unsigned _data; + }; + class BlockWriteTxHeader { + public: + PgpHeader pgpHeader; + BlockWriteHeader blockHeader; + BlockWriteTxHeader(bool handshake ) : + pgpHeader(PgpHeader::VC3, 0, 0),blockHeader(handshake){} + }; + +} + diff --git a/rce/rcecalib/HW/Makefile b/rce/rcecalib/HW/Makefile new file mode 100644 index 00000000..c73fd5ec --- /dev/null +++ b/rce/rcecalib/HW/Makefile @@ -0,0 +1,20 @@ +# Package level makefile +# ---------------------- +%.mk:; + +# Checks +# ------ +# Check release location variables +ifeq ($(RELEASE_DIR),) +export RELEASE_DIR := $(PWD)/../.. +endif + +include $(RELEASE_DIR)/make/share/setup.mk +include ../flags.mk + +ifndef PREMAKE_DONE +include $(RELEASE_DIR)/make/share/premake.mk +else +include constituents.mk +include $(RELEASE_DIR)/make/sw/package.mk +endif diff --git a/rce/rcecalib/HW/RCDImaster.cc b/rce/rcecalib/HW/RCDImaster.cc new file mode 100644 index 00000000..3dc84e91 --- /dev/null +++ b/rce/rcecalib/HW/RCDImaster.cc @@ -0,0 +1,344 @@ +#ifdef RCE_V2 +#include "datCode.hh" +#include DAT_PUBLIC( oldPpi, pic, Tds.hh) +#include DAT_PUBLIC( oldPpi, pic, Pool.hh) +#include DAT_PUBLIC( oldPpi, pgp, Driver.hh) +#include DAT_PUBLIC( oldPpi, pgp, DriverList.hh) +#include DAT_PUBLIC( service, fci, Exception.hh) +#else +#include "rce/pic/Tds.hh" +#include "rce/pgp/Driver.hh" +#include "rce/pgp/DriverList.hh" +#include "rce/service/Exception.hh" +#include "rce/pic/Pool.hh" +#endif +#include "RCDImaster.hh" +#include "Headers.hh" +#include "Receiver.hh" +#include <stdio.h> +#include <assert.h> +#include <iostream> + +using namespace PgpTrans; + +RCDImaster* RCDImaster::_instance=0; +omni_mutex RCDImaster::_guard; + +RCDImaster* RCDImaster::instance(){ + if( ! _instance){ + omni_mutex_lock ml(_guard); + if( ! _instance){ + _instance=new RCDImaster; + } + } + return _instance; +} + + + +RCDImaster::RCDImaster():_pgp_driver(0),_receiver(0),_pool(0), + _tid(0),_data_cond(&_data_mutex), + _status(0), _data(0), _handshake(false),_blockread(false){ + try { + const RcePic::Params Tx = { + RcePic::NonContiguous, + 16, // Header + 64*132, // Payload + 32 // Number of buffers + }; + + RcePic::Pool * pool = new RcePic::Pool::Pool(Tx); + RcePgp::DriverList * driverList = RcePgp::DriverList::instance(); + setPool(pool); // tell the handler so it can put back the buffers + RcePgp::Driver * pgpd = 0; + for (int i=0;i<4;i++){ + pgpd=driverList->handler(static_cast<RcePgp::port_number_t>(i), this); + } + pgpd=driverList->lookup(static_cast<RcePgp::port_number_t>(0)); + if (!pgpd){ + printf("serialPorts: Could not find the driver\n"); + assert(0); + } + setDriver(pgpd); + rtems_task_wake_after(10); // hack wait for initialization to complete + } catch (RceSvc::Exception& e) { + printf("*** rce exception %s", e.what()); + } catch (std::exception& e) { + printf("*** c++ exception %s", e.what()); + } + //printf("Handler %p\n",this); + m_counter=0; + +} + + + +void RCDImaster::setPool(RcePic::Pool *p){_pool=p;} + +void RCDImaster::setDriver(RcePgp::Driver *pgpd){_pgp_driver=pgpd;} + +void RCDImaster::setReceiver(Receiver* receiver){_receiver=receiver;} +Receiver* RCDImaster::receiver(){return _receiver;} + +unsigned int RCDImaster::writeRegister(unsigned address, unsigned value){ + // std::cout<<"Register write address "<<address<<" value "<<value<<std::endl; + //std::cout<<"RCDImaster"<<std::endl; + RcePic::Tds* tds=_pool->allocate(); + assert (tds!=0); + _tid++; + new(tds->header())RegTxHeader(_tid,address, RegHeader::Write, value); + tds->payloadsize(0); + // printf("Write register\n"); + omni_mutex_lock pl( _data_mutex ); + _pgp_driver->post(tds,RcePgp::Driver::Contiguous,RcePgp::Driver::DoNotComplete); + //printf("P %d",_pgp_driver->port_number()); + //printf("b\n"); + //printf("Posted \n"); + unsigned long abs_sec,abs_nsec; + omni_thread::get_time(&abs_sec,&abs_nsec,0,RECEIVETIMEOUT); + int signalled=_data_cond.timedwait(abs_sec,abs_nsec); + if(signalled==0){ //timeout. Something went wrong with the data. + printf("PGP Write Register: No reply from front end.\n"); + _pool->deallocate(tds); + return RECEIVEFAILED; + } + //printf("Status %d\n",stat); + //printf("a\n"); + //printf("Write register done\n"); + _pool->deallocate(tds); + return _status; +} +unsigned int RCDImaster::blockWrite(RcePic::Tds* tds){ + _pgp_driver->post(tds,RcePgp::Driver::NonContiguous,RcePgp::Driver::DoNotComplete); + return 0; +} + +unsigned int RCDImaster::blockWrite(unsigned* data, int size, bool handshake,bool byteswap){ + //printf("Size %d\n",size); + RcePic::Tds* tds=_pool->allocate(); + assert (tds!=0); + char* header=(char*)tds->header(); + int headersize=tds->headersize(); + for (int i=0;i<headersize;i++)header[i]=0; + new(tds->header())BlockWriteTxHeader(handshake); + unsigned* payload=(unsigned*)tds->payload(); + for(int i=0;i<size;i++){ +#ifdef SWAP_DATA +#warning Swapping of data turned on + if(byteswap) + payload[i]= ((data[i]&0xff)<<8) | ((data[i]&0xff00)>>8) | + ((data[i]&0xff0000)<<8) | ((data[i]&0xff000000)>>8); + else + payload[i]=data[i]<<16 | data[i]>>16; +#else + if(byteswap) + payload[i]= ((data[i]&0xff)<<24) | ((data[i]&0xff00)<<8) | + ((data[i]&0xff0000)>>8) | ((data[i]&0xff000000)>>24); + else{ + payload[i]=data[i]; + // std::cout<<"data "<<data[i]<<std::endl; + } +#endif + } + tds->payloadsize(size*sizeof(unsigned)); + tds->flush(true); + _handshake=handshake; + //printf("Posting config data\n"); + if(handshake){ + _data_mutex.lock(); + //m_timer.Start(); + } + //else { + // m_timer.Start(); + // m_counter=0; + //} + _pgp_driver->post(tds,RcePgp::Driver::NonContiguous,RcePgp::Driver::DoNotComplete); + if(handshake){ + unsigned long abs_sec,abs_nsec; + omni_thread::get_time(&abs_sec,&abs_nsec,0,RECEIVETIMEOUT); + int signalled=_data_cond.timedwait(abs_sec,abs_nsec); + _data_mutex.unlock(); + if(signalled==0){ //timeout. Something went wrong with the data. + std::cout<<"PGP Block R/W: No reply from frontend."<<std::endl; + _pool->deallocate(tds); + return RECEIVEFAILED; + } + } + _pool->deallocate(tds); + //printf("Done posting config data\n"); + return 0; +} + +unsigned int RCDImaster::blockRead(unsigned* data, int size, std::vector<unsigned>& retvec){ + _blockread=true; + blockWrite(data,size,true,false); + _blockread=false; + if(nBuffers()!=0){ + unsigned char *header, *payload; + unsigned headerlen, payloadlen; + currentBuffer(header, headerlen, payload, payloadlen); + payloadlen/=sizeof(unsigned); + unsigned* ptr=(unsigned*)payload; + for(unsigned i=0;i<payloadlen;i++) retvec.push_back(*ptr++); + discardCurrentBuffer(); + } + return 0; +} +unsigned int RCDImaster::readBuffers(std::vector<unsigned char>& retvec){ + unsigned char *header, *payload; + unsigned headerlen, payloadlen; + unsigned count=0; + while(nBuffers()!=0){ + count++; + currentBuffer(header, headerlen, payload, payloadlen); + for(unsigned i=0;i<payloadlen;i++) retvec.push_back(payload[i]); + if(payloadlen%3!=0){ + retvec.push_back(0); + if(payloadlen%3==1) retvec.push_back(0); + } + discardCurrentBuffer(); + } + return count; +} + +unsigned int RCDImaster::readRegister(unsigned address, unsigned &value){ + RcePic::Tds* tds=_pool->allocate(); + _tid++; + if(_tid>0xffffff)_tid=0; + new(tds->header())RegTxHeader(_tid,address, RegHeader::Read); + tds->payloadsize(0); + // printf("Read register tid=%d\n",_tid); + omni_mutex_lock pl( _data_mutex ); + _pgp_driver->post(tds,RcePgp::Driver::Contiguous,RcePgp::Driver::DoNotComplete); + unsigned long abs_sec,abs_nsec; + omni_thread::get_time(&abs_sec,&abs_nsec,0,RECEIVETIMEOUT); + int signalled=_data_cond.timedwait(abs_sec,abs_nsec); + if(signalled==0){ //timeout. Something went wrong with the data. + printf("PGP Read Register: No reply from frontend.\n"); + _pool->deallocate(tds); + return RECEIVEFAILED; + } + value=_data; + //printf("Read register done tid=%d\n",_tid); + _pool->deallocate(tds); + return _status; +} + +unsigned int RCDImaster::sendCommand(unsigned char opcode, unsigned context){ + // if(opcode==111){ + // m_timer.Print("RCDImaster"); + // m_timer.Reset(); + // return 0; + //} + RcePic::Tds* tds=_pool->allocate(); + new(tds->header())CmdTxHeader(opcode, context&0xffffff ); + tds->payloadsize(0); + _pgp_driver->post(tds,RcePgp::Driver::Contiguous,RcePgp::Driver::DoNotComplete); + _pool->deallocate(tds); + return 0; +} + +unsigned RCDImaster::transferred(RcePic::Tds* tds) { + return ((unsigned*)tds->result())[1]; +} + +void RCDImaster::completed(RcePic::Tds *tds, RcePgp::Driver* pgpd) +{ + // if(tds->edw()!=0)printf("Completion error %d\n",tds->edw()); + // _pool->deallocate(tds); +} +//int ibuf=0; +void RCDImaster::received(RcePic::Tds *tds, RcePgp::Driver *pgpd){ + PgpHeader *pgpheader=(PgpHeader*)tds->header(); + if (pgpheader->vc()==1 && pgpheader->destination()==0){ // Register + //std::cout<<"Register"<<std::endl; + RegRxHeader* rxheader= (RegRxHeader*)tds->header(); + unsigned tid=rxheader->pgpHeader.tid(); + if(tid!=_tid){ + printf ("Bad tid\n"); + } + _status=rxheader->regHeader.status(); + _data=rxheader->regHeader.data; + if (rxheader->regHeader.fail()){ + printf("Register operation failed\n"); + } else if (rxheader->regHeader.timeout()){ + printf("Register operation timed out\n"); + } + pgpd->release(tds,true); + omni_mutex_lock pl( _data_mutex ); + _data_cond.signal(); + } else if (pgpheader->vc()==0 && pgpheader->destination()==0){ // data + //std::cout<<"Data"<<std::endl; + if(_receiver!=NULL && _blockread==false){ + // if(_handshake==false){ + PgpData pgpdata; + pgpdata.header=(unsigned char*)tds->header(); + pgpdata.payload=(unsigned*)tds->payload(); + unsigned size=transferred(tds); + const unsigned headersize=8; + pgpdata.payloadSize=size/sizeof(unsigned)- headersize; + if(size%4!=0)std::cout<<"PGP Data size not a multiple of 32 bit."<<std::endl; + _receiver->receive(&pgpdata); + // m_counter++; + //if(m_counter==16){ + // m_timer.Stop(); + //} + //} + // printf("%d Did not release buffer\n",ibuf++); + pgpd->release(tds,true); + }else{ + _buffers.push_back(tds); + } + if(_handshake){ + _handshake=false; + omni_mutex_lock pl( _data_mutex ); + _data_cond.signal(); + } + }else{ + printf("Received message with vc = %d dest = %d\n",pgpheader->vc(),pgpheader->destination()); + //assert(0); + omni_mutex_lock pl( _data_mutex ); + _data_cond.signal(); + } +} + +unsigned RCDImaster::nBuffers(){ + return _buffers.size(); +} + +int RCDImaster::currentBuffer(unsigned char*& header, unsigned &headerSize, unsigned char*&payload, unsigned &payloadSize){ + int retval=1; + if(_buffers.empty()){ + header=0; + headerSize=0; + payload=0; + payloadSize=0; + retval=1; + }else{ + RcePic::Tds *tds=*_buffers.begin(); + header=(unsigned char*)tds->header(); + headerSize=tds->headersize(); + payload=(unsigned char*)tds->payload(); + payloadSize=transferred(tds)-headerSize; + retval=0; + } + return retval; +} + +int RCDImaster::discardCurrentBuffer(){ + int retval=1; + if(_buffers.empty()){ + retval=1; + }else{ + RcePic::Tds *tds=*_buffers.begin(); + _pgp_driver->release(tds,true); + _buffers.pop_front(); + retval=0; + } + return retval; +} + + + + + diff --git a/rce/rcecalib/HW/RCDImaster.hh b/rce/rcecalib/HW/RCDImaster.hh new file mode 100644 index 00000000..6e566f03 --- /dev/null +++ b/rce/rcecalib/HW/RCDImaster.hh @@ -0,0 +1,72 @@ +// +// Implements the master RCDI interface +// +// Martin Kocian, SLAC, 6/6/2009 +// + +#ifndef RCDIMASTER_H +#define RCDIMASTER_H + +#include <omnithread.h> +#ifdef RCE_V2 +#include "datCode.hh" +#include DAT_PUBLIC( oldPpi, pgp, Handler.hh) +#else +#include "rce/pgp/Handler.hh" +#endif +#include "rcecalib/profiler/Profiler.hh" +#include <list> +#include <vector> +#include <omnithread.h> + +#include "namespace_aliases.hh" + +namespace PgpTrans { + + class Receiver; + + class RCDImaster: public RcePgp::Handler { + public: + enum ERRCODES{SENDFAILED=666, RECEIVEFAILED=667}; + enum TIMEOUTS{RECEIVETIMEOUT=100000000}; //in ns + static RCDImaster* instance(); + void setPool(RcePic::Pool *p); + void setDriver(RcePgp::Driver *pgpd); + unsigned int writeRegister(unsigned address, unsigned value); + unsigned int readRegister(unsigned address, unsigned& value); + unsigned int blockWrite(unsigned* data, int size, bool handshake, bool byteswap); + unsigned int blockWrite(RcePic::Tds* tds); + unsigned int blockRead(unsigned* data, int size, std::vector<unsigned>& retvec); + unsigned int readBuffers(std::vector<unsigned char>& retvec); + unsigned int sendCommand(unsigned char opcode, unsigned context=0); + void setReceiver(Receiver* receiver); + Receiver* receiver(); + unsigned nBuffers(); + int currentBuffer(unsigned char*& header, unsigned &headerSize, unsigned char*&payload, unsigned &payloadSize); + int discardCurrentBuffer(); + protected: + RCDImaster(); + virtual void completed(RcePic::Tds *tds, RcePgp::Driver *pgpd); + virtual void received(RcePic::Tds *tds, RcePgp::Driver *pgpd); + unsigned transferred(RcePic::Tds* tds); + private: + RcePgp::Driver *_pgp_driver; + Receiver* _receiver; + RcePic::Pool * _pool; + unsigned int _tid; + omni_mutex _data_mutex; + omni_condition _data_cond; + unsigned _status; + unsigned _data; + std::list<RcePic::Tds*> _buffers; + bool _handshake; + bool _blockread; + Profiler::Timer m_timer; + int m_counter; + static omni_mutex _guard; + static RCDImaster* _instance; + }; + +}//namespace + +#endif diff --git a/rce/rcecalib/HW/Receiver.hh b/rce/rcecalib/HW/Receiver.hh new file mode 100644 index 00000000..e9f8cb5b --- /dev/null +++ b/rce/rcecalib/HW/Receiver.hh @@ -0,0 +1,22 @@ +#ifndef PGPTRANS_RECEIVER_HH +#define PGPTRANS_RECEIVER_HH + +#include "namespace_aliases.hh" + +namespace PgpTrans { + + struct PgpData{ + unsigned char *header; + unsigned *payload; + unsigned payloadSize;}; + + class Receiver { + public: + Receiver() {} + virtual ~Receiver(){} + virtual void receive(PgpData* pgpdata)=0; + }; + +} + +#endif diff --git a/rce/rcecalib/HW/SerialHexdump.cc b/rce/rcecalib/HW/SerialHexdump.cc new file mode 100644 index 00000000..82cf907e --- /dev/null +++ b/rce/rcecalib/HW/SerialHexdump.cc @@ -0,0 +1,71 @@ +#include "rcecalib/HW/SerialHexdump.hh" +#include "rcecalib/HW/BitStream.hh" +#include <stdio.h> +#include <iostream> + + + + +SerialHexdump::SerialHexdump(): SerialIF() { + m_flog=fopen("dbg.txt","w+"); +} + + +void SerialHexdump::Send(BitStream* bs, int opt){ + char txt[28]; + if(!m_flog) return; + // fprintf(m_flog,"sendWaitX\n"); + // std::cout<<"sendWaitX"<<std::endl; + for (unsigned int i=0;i<bs->size();i++){ + if(opt & SerialIF::BYTESWAP){ + unsigned tmp=(*bs)[i]; + unsigned tmp2 = ((tmp&0xff)<<24) | ((tmp&0xff00)<<8) | + ((tmp&0xff0000)>>8) | ((tmp&0xff000000)>>24); + sprintf(txt,"%x\n",tmp2); + } else{ + sprintf(txt,"%x\n",(*bs)[i]); + } + fprintf(m_flog,txt); + // std::cout<<txt; + } + if((opt&SerialIF::DONT_CLEAR)==0)bs->clear(); +} +void SerialHexdump::SetChannelInMask(unsigned linkmask){ +} +void SerialHexdump::SetChannelOutMask(unsigned linkmask){ +} +int SerialHexdump::EnableTrigger(bool on){ + return 0; +} +unsigned SerialHexdump::SendCommand(unsigned char opcode) { + if(opcode==77)fclose(m_flog); + std::cout<<"Opcode: "<<(unsigned)opcode<<std::endl; + return 0; +} +unsigned SerialHexdump::WriteRegister(unsigned addr, unsigned val){ + std::cout<<"Address: "<<addr<<" Value: "<<val<<std::endl; + return 0; +} +unsigned SerialHexdump::ReadRegister(unsigned addr, unsigned &val){ + std::cout<<"Address: "<<addr<<" setting to 55"<<std::endl; + val=55; + return 0; +} +unsigned SerialHexdump::WriteBlockData(std::vector<unsigned>& data){ + //std::cout<<"Block data"<<std::endl; + for (size_t i=0;i<data.size();i++){ + // std::cout<<"Word "<<i<<": "<<data[i]<<std::endl; + fprintf(m_flog, "%x\n", data[i]); + } + return 0; +} +unsigned SerialHexdump::ReadBlockData(std::vector<unsigned>& data, std::vector<unsigned>& retvec){ + //std::cout<<"Block data"<<std::endl; + for (size_t i=0;i<data.size();i++){ + fprintf(m_flog, "%x\n", data[i]); + // std::cout<<"Word "<<i<<": "<<data[i]<<std::endl; + } + // for (int i=0;i<1000;i++)retvec.push_back(i); + return 0; +} + diff --git a/rce/rcecalib/HW/SerialHexdump.hh b/rce/rcecalib/HW/SerialHexdump.hh new file mode 100644 index 00000000..b3f1feef --- /dev/null +++ b/rce/rcecalib/HW/SerialHexdump.hh @@ -0,0 +1,25 @@ +#ifndef SERIALHEXDUMP_HH +#define SERIALHEXDUMP_HH + +#include "rcecalib/HW/SerialIF.hh" +#include <stdio.h> + +class SerialHexdump: public SerialIF { +public: + SerialHexdump(); + virtual ~SerialHexdump(){} +private: + void Send(BitStream* bs, int opt); + void SetChannelInMask(unsigned linkmask); + void SetChannelOutMask(unsigned linkmask); + int EnableTrigger(bool on); + unsigned SendCommand(unsigned char opcode); + unsigned WriteRegister(unsigned addr, unsigned val); + unsigned ReadRegister(unsigned addr, unsigned &val); + unsigned WriteBlockData(std::vector<unsigned>& data); + unsigned ReadBlockData(std::vector<unsigned>& data, std::vector<unsigned>& retvec); + FILE* m_flog; +}; + + +#endif diff --git a/rce/rcecalib/HW/SerialIF.cc b/rce/rcecalib/HW/SerialIF.cc new file mode 100644 index 00000000..e3547696 --- /dev/null +++ b/rce/rcecalib/HW/SerialIF.cc @@ -0,0 +1,67 @@ +#include "rcecalib/HW/SerialIF.hh" +#include "ers/ers.h" + +SerialIF* SerialIF::m_serial=0; + +SerialIF::SerialIF(){ + ERS_ASSERT_MSG(m_serial==0,"the interface exists already"); + m_serial=this; +} +void SerialIF::destroy(){ + ERS_ASSERT_MSG(m_serial!=0,"there is no serial interface defined"); + delete m_serial; + m_serial=0; +} + +void SerialIF::send(BitStream *bs, int opt){ + ERS_ASSERT_MSG(m_serial!=0,"there is no serial interface defined"); + m_serial->Send(bs,opt); +} +void SerialIF::setChannelInMask(unsigned linkmask){ + ERS_ASSERT_MSG(m_serial!=0,"there is no serial interface defined"); + m_serial->SetChannelInMask(linkmask); +} +void SerialIF::setChannelOutMask(unsigned linkmask){ + ERS_ASSERT_MSG(m_serial!=0,"there is no serial interface defined"); + m_serial->SetChannelOutMask(linkmask); +} +int SerialIF::enableTrigger(bool on){ + ERS_ASSERT_MSG(m_serial!=0,"there is no serial interface defined"); + return m_serial->EnableTrigger(on); +} +void SerialIF::disableOutput(){ + ERS_ASSERT_MSG(m_serial!=0,"there is no serial interface defined"); + m_serial->DisableOutput(); +} +void SerialIF::setOutputMode(unsigned mode){ + ERS_ASSERT_MSG(m_serial!=0,"there is no serial interface defined"); + m_serial->SetOutputMode(mode); +} +void SerialIF::setDataRate(Rate rate){ + ERS_ASSERT_MSG(m_serial!=0,"there is no serial interface defined"); + m_serial->SetDataRate(rate); +} +unsigned SerialIF::sendCommand(unsigned char opcode){ + ERS_ASSERT_MSG(m_serial!=0,"there is no serial interface defined"); + return m_serial->SendCommand(opcode); +} +unsigned SerialIF::writeRegister(unsigned addr, unsigned val){ + ERS_ASSERT_MSG(m_serial!=0,"there is no serial interface defined"); + return m_serial->WriteRegister(addr,val); +} +unsigned SerialIF::readRegister(unsigned addr, unsigned &val){ + ERS_ASSERT_MSG(m_serial!=0,"there is no serial interface defined"); + return m_serial->ReadRegister(addr, val); +} +unsigned SerialIF::writeBlockData(std::vector<unsigned>& data){ + ERS_ASSERT_MSG(m_serial!=0,"there is no serial interface defined"); + return m_serial->WriteBlockData(data); +} +unsigned SerialIF::readBlockData(std::vector<unsigned>& data, std::vector<unsigned>& retvec){ + ERS_ASSERT_MSG(m_serial!=0,"there is no serial interface defined"); + return m_serial->ReadBlockData(data, retvec); +} +unsigned SerialIF::readBuffers(std::vector<unsigned char>& retvec){ + ERS_ASSERT_MSG(m_serial!=0,"there is no serial interface defined"); + return m_serial->ReadBuffers(retvec); +} diff --git a/rce/rcecalib/HW/SerialIF.hh b/rce/rcecalib/HW/SerialIF.hh new file mode 100644 index 00000000..59cf2461 --- /dev/null +++ b/rce/rcecalib/HW/SerialIF.hh @@ -0,0 +1,45 @@ +#ifndef SERIALIF_HH +#define SERIALIF_HH +#include "rcecalib/HW/BitStream.hh" +#include <vector> + + +class SerialIF{ +public: + enum Options {DONT_CLEAR=1, BYTESWAP=4, WAITFORDATA=8}; + enum Rate {M40, M80, M160, M320}; + static void send(BitStream *bs, int opt=0); + static void setChannelInMask(unsigned linkmask); + static void setChannelOutMask(unsigned linkmask); + static void destroy(); + static int enableTrigger(bool on); + static void disableOutput(); + static void setOutputMode(unsigned mode); + static void setDataRate(Rate rate); + static unsigned sendCommand(unsigned char opcode); + static unsigned writeRegister(unsigned addr, unsigned val); + static unsigned readRegister(unsigned addr, unsigned& val); + static unsigned writeBlockData(std::vector<unsigned>& data); + static unsigned readBlockData(std::vector<unsigned>& data, std::vector<unsigned>& retvec); + static unsigned readBuffers(std::vector<unsigned char>& retvec); +protected: + SerialIF(); + virtual ~SerialIF(){}; + virtual void Send(BitStream *bs, int opt )=0; + virtual void SetChannelInMask(unsigned linkmask)=0; + virtual void SetChannelOutMask(unsigned linkmask)=0; + virtual int EnableTrigger(bool on)=0; + virtual void DisableOutput(){} + virtual void SetOutputMode(unsigned mode){} + virtual void SetDataRate(Rate rate){}; + virtual unsigned SendCommand(unsigned char opcode){return (unsigned)-1;} + virtual unsigned WriteRegister(unsigned addr, unsigned val){return (unsigned)-1;} + virtual unsigned ReadRegister(unsigned addr, unsigned &val){return (unsigned)-1;} + virtual unsigned WriteBlockData(std::vector<unsigned>& data){return (unsigned)-1;} + virtual unsigned ReadBlockData(std::vector<unsigned>& data,std::vector<unsigned>& retvec ){return (unsigned)-1;} + virtual unsigned ReadBuffers(std::vector<unsigned char>& retvec){return(unsigned)-1;} + static SerialIF* m_serial; +}; + + +#endif diff --git a/rce/rcecalib/HW/SerialPgp.cc b/rce/rcecalib/HW/SerialPgp.cc new file mode 100644 index 00000000..6a919e81 --- /dev/null +++ b/rce/rcecalib/HW/SerialPgp.cc @@ -0,0 +1,50 @@ +#include "rcecalib/HW/SerialPgp.hh" +#include "rcecalib/HW/RCDImaster.hh" +#include "rcecalib/HW/BitStream.hh" +#include <iostream> +#include <assert.h> + + + + +SerialPgp::SerialPgp(): SerialIF() { +} + + +void SerialPgp::Send(BitStream* bs, int opt){ + /* + PgpTrans::RCDImaster* pgp= PgpTrans::RCDImaster::instance(); + // std::cout<<"sendWaitX"<<std::endl; + unsigned serstat; + if(opt&SerialIF::BYTESWAP){ + for (unsigned int i=0;i<bs->size();i++){ + unsigned tmp=(*bs)[i]; + unsigned tmp2 = ((tmp&0xff)<<24) | ((tmp&0xff00)<<8) | + ((tmp&0xff0000)>>8) | ((tmp&0xff000000)>>24); + serstat=pgp->writeRegister(0,tmp2); + assert(serstat==0); + } + }else{ + for (unsigned int i=0;i<bs->size();i++){ + serstat= pgp->writeRegister(0,(*bs)[i]); + assert(serstat==0); + } + } + if(opt&WAITFORDATA){ + serstat=pgp->sendCommand(3);// 3 is serialize and wait + }else{ + serstat=pgp->sendCommand(1);// 1 is serialize + } + assert(serstat==0); + pgp->semaphore()->take(); // wait for handshake + + if((opt&SerialIF::DONT_CLEAR)==0)bs->clear(); + */ +} +void SerialPgp::SetChannelInMask(unsigned linkmask){ +} +void SerialPgp::SetChannelOutMask(unsigned linkmask){ +} +int SerialPgp::EnableTrigger(bool on){ + return 0; +} diff --git a/rce/rcecalib/HW/SerialPgp.hh b/rce/rcecalib/HW/SerialPgp.hh new file mode 100644 index 00000000..b71ff7c0 --- /dev/null +++ b/rce/rcecalib/HW/SerialPgp.hh @@ -0,0 +1,19 @@ +#ifndef SERIALPGP_HH +#define SERIALPGP_HH + +#include "rcecalib/HW/SerialIF.hh" +#include <fstream> + +class SerialPgp: public SerialIF { +public: + SerialPgp(); +private: + void Send(BitStream* bs, int opt); + void SetChannelMask(unsigned linkmask); + void SetChannelInMask(unsigned linkmask); + void SetChannelOutMask(unsigned linkmask); + int EnableTrigger(bool on); +}; + + +#endif diff --git a/rce/rcecalib/HW/SerialPgpBw.cc b/rce/rcecalib/HW/SerialPgpBw.cc new file mode 100644 index 00000000..5aa3021b --- /dev/null +++ b/rce/rcecalib/HW/SerialPgpBw.cc @@ -0,0 +1,67 @@ +#include "rcecalib/HW/SerialPgpBw.hh" +#include "rcecalib/HW/RCDImaster.hh" +#include "rcecalib/HW/BitStream.hh" +#include <iostream> +#include <assert.h> + + + + +SerialPgpBw::SerialPgpBw(): SerialIF() { +} + + +void SerialPgpBw::Send(BitStream* bs, int opt){ + PgpTrans::RCDImaster* pgp= PgpTrans::RCDImaster::instance(); + // std::cout<<"sendWaitX"<<std::endl; + unsigned serstat; + if(opt&WAITFORDATA){ + //std::cout<<"SerialPgpBw::Trigger"<<std::endl; + serstat=pgp->blockWrite(&((*bs)[0]),bs->size(),0,opt&SerialIF::BYTESWAP);// no handshake + }else{ + // std::cout<<"SerialPgpBw::handshake bitstream size is "<<bs->size()<<std::endl; + //pgp->blockWrite(buf,sz,1,opt&SerialIF::BYTESWAP);// handshake + serstat=pgp->blockWrite(&((*bs)[0]),bs->size(),1,opt&SerialIF::BYTESWAP);// handshake + } + assert(serstat==0); + + if((opt&SerialIF::DONT_CLEAR)==0)bs->clear(); +} +void SerialPgpBw::SetChannelInMask(unsigned linkmask){ + BitStream bs; + //bs.push_back(0); + //Send(&bs, 0); //clear FIFO + unsigned serstat=PgpTrans::RCDImaster::instance()->writeRegister(0,linkmask); + assert(serstat==0); +} +void SerialPgpBw::SetChannelOutMask(unsigned linkmask){ + unsigned serstat=PgpTrans::RCDImaster::instance()->writeRegister(13,linkmask); + assert(serstat==0); +} +int SerialPgpBw::EnableTrigger(bool on){ + unsigned serstat; + if(on) + serstat=PgpTrans::RCDImaster::instance()->sendCommand(3); + else + serstat=PgpTrans::RCDImaster::instance()->sendCommand(5); + assert(serstat==0); + return 0; +} +unsigned SerialPgpBw::SendCommand(unsigned char opcode){ + return PgpTrans::RCDImaster::instance()->sendCommand(opcode); +} +unsigned SerialPgpBw::WriteRegister(unsigned addr, unsigned val){ + return PgpTrans::RCDImaster::instance()->writeRegister(addr,val); +} +unsigned SerialPgpBw::ReadRegister(unsigned addr, unsigned& val){ + return PgpTrans::RCDImaster::instance()->readRegister(addr, val); +} +unsigned SerialPgpBw::WriteBlockData(std::vector<unsigned>& data){ + return PgpTrans::RCDImaster::instance()->blockWrite(&data[0],data.size(),1, 0);// handshake +} +unsigned SerialPgpBw::ReadBlockData(std::vector<unsigned>& data, std::vector<unsigned>& retvec){ + return PgpTrans::RCDImaster::instance()->blockRead(&data[0],data.size(), retvec); +} +unsigned SerialPgpBw::ReadBuffers(std::vector<unsigned char>& retvec){ + return PgpTrans::RCDImaster::instance()->readBuffers(retvec); +} diff --git a/rce/rcecalib/HW/SerialPgpBw.hh b/rce/rcecalib/HW/SerialPgpBw.hh new file mode 100644 index 00000000..1c58a9a3 --- /dev/null +++ b/rce/rcecalib/HW/SerialPgpBw.hh @@ -0,0 +1,25 @@ +#ifndef SERIALPGPBW_HH +#define SERIALPGPBW_HH + +#include "rcecalib/HW/SerialIF.hh" +#include <vector> + +class SerialPgpBw: public SerialIF { +public: + SerialPgpBw(); +protected: + void Send(BitStream* bs, int opt); + void SetChannelMask(unsigned linkmask); + void SetChannelInMask(unsigned linkmask); + void SetChannelOutMask(unsigned linkmask); + int EnableTrigger(bool on); + unsigned SendCommand(unsigned char opcode); + unsigned WriteRegister(unsigned addr, unsigned val); + unsigned ReadRegister(unsigned addr, unsigned &val); + unsigned WriteBlockData(std::vector<unsigned>& data); + unsigned ReadBlockData(std::vector<unsigned>& data, std::vector<unsigned>& retvec); + unsigned ReadBuffers(std::vector<unsigned char>& retvec); +}; + + +#endif diff --git a/rce/rcecalib/HW/SerialPgpFei4.cc b/rce/rcecalib/HW/SerialPgpFei4.cc new file mode 100644 index 00000000..59d472b3 --- /dev/null +++ b/rce/rcecalib/HW/SerialPgpFei4.cc @@ -0,0 +1,18 @@ +#include "rcecalib/HW/SerialPgpFei4.hh" +#include <iostream> + +SerialPgpFei4::SerialPgpFei4(): SerialPgpBw(){} + +void SerialPgpFei4::DisableOutput(){ + WriteRegister(13,0); +} + +void SerialPgpFei4::SetOutputMode(unsigned mode){ + unsigned m= mode ? 0 : 1; + WriteRegister(16, m); +} +void SerialPgpFei4::SetDataRate(Rate rate){ + std::cout<<"Setting Data Rate (reg 10) to "<<rate<<std::endl; + WriteRegister(10,rate); +} + diff --git a/rce/rcecalib/HW/SerialPgpFei4.hh b/rce/rcecalib/HW/SerialPgpFei4.hh new file mode 100644 index 00000000..38f19227 --- /dev/null +++ b/rce/rcecalib/HW/SerialPgpFei4.hh @@ -0,0 +1,17 @@ +#ifndef SERIALPGPFEI4_HH +#define SERIALPGPFEI4_HH + +#include "rcecalib/HW/SerialPgpBw.hh" +#include <vector> + +class SerialPgpFei4: public SerialPgpBw { +public: + SerialPgpFei4(); +protected: + void DisableOutput(); + void SetOutputMode(unsigned mode); + virtual void SetDataRate(Rate rate); +}; + + +#endif diff --git a/rce/rcecalib/HW/constituents.mk b/rce/rcecalib/HW/constituents.mk new file mode 100644 index 00000000..03ba51cd --- /dev/null +++ b/rce/rcecalib/HW/constituents.mk @@ -0,0 +1,34 @@ + +ifdef SWAP_DATA +CPPFLAGS+= '-DSWAP_DATA' +endif + +ifneq ($(findstring ppc-rtems-rce,$(tgt_arch)),) +modlibnames := HW +libsrcs_HW := SerialIF.cc \ + RCDImaster.cc \ + SerialPgp.cc \ + SerialPgpBw.cc \ + SerialPgpFei4.cc \ + SerialHexdump.cc + +libincs_HW := rcecalib \ + rceowl/owl \ + rceers/ers \ + omniorb/include/$(tgt_arch) \ + boost +endif + +ifneq ($(findstring linux,$(tgt_os)),) +libnames := HW + +libsrcs_HW := SerialIF.cc \ + SerialHexdump.cc + +libincs_HW := rcecalib \ + rceowl/owl \ + rceers/ers \ + omniorb/include/$(tgt_arch) \ + boost +endif + diff --git a/rce/rcecalib/Makefile b/rce/rcecalib/Makefile new file mode 100644 index 00000000..bd8fffcb --- /dev/null +++ b/rce/rcecalib/Makefile @@ -0,0 +1,17 @@ +# Project level makefile +# ---------------------- +%.mk:; + +# Checks +# ------ +# Check release location variables +ifeq ($(RELEASE_DIR),) +export RELEASE_DIR := $(PWD)/.. +endif + +# Includes +# -------- +include $(RELEASE_DIR)/make/share/setup.mk +include flags.mk +include packages.mk +include $(RELEASE_DIR)/make/share/project.mk diff --git a/rce/rcecalib/analysis/AnalysisFactory.cc b/rce/rcecalib/analysis/AnalysisFactory.cc new file mode 100644 index 00000000..f0832ff4 --- /dev/null +++ b/rce/rcecalib/analysis/AnalysisFactory.cc @@ -0,0 +1,90 @@ +#include "analysis/AnalysisFactory.hh" +#include "analysis/NoiseAnalysis.hh" +#include "analysis/Iff_Analysis.hh" +#include "analysis/Fdac_Analysis.hh" +#include "analysis/StuckPixelAnalysis.hh" +#include "analysis/GdacAnalysis.hh" +#include "analysis/GdacFastAnalysis.hh" +#include "analysis/GdacCoarseFastAnalysis.hh" +#include "analysis/TdacAnalysis.hh" +#include "analysis/TdacFastAnalysis.hh" +#include "analysis/ThresholdAnalysis.hh" +#include "analysis/TotAnalysis.hh" +#include "analysis/TotCalibAnalysis.hh" +#include "analysis/DigitalTestAnalysis.hh" +#include "analysis/ModuleCrosstalkAnalysis.hh" +#include "analysis/OffsetAnalysis.hh" +#include "analysis/CrosstalkAnalysis.hh" +#include "analysis/T0Analysis.hh" +#include "analysis/TimeWalkAnalysis.hh" +#include "analysis/MultiTrigAnalysis.hh" +#include "analysis/MultiTrigNoiseAnalysis.hh" +#include "analysis/SerialNumberAnalysis.hh" +#include "analysis/TemperatureAnalysis.hh" +#include "analysis/RegisterTestAnalysis.hh" +#include "analysis/Fei3CfgFileWriter.hh" +#include "analysis/Fei4CfgFileWriter.hh" +#include <iostream> + +CalibAnalysis* AnalysisFactory::getAnalysis(std::string &type){ + CalibAnalysis* ana=0; + if(type=="Fei3Noise") + ana=new NoiseAnalysis(new Fei3CfgFileWriter); + if(type=="Fei4Noise") + ana=new NoiseAnalysis(new Fei4CfgFileWriter); + else if(type=="Fei3StuckPixel") + ana=new StuckPixelAnalysis(new Fei3CfgFileWriter); + else if(type=="Fei4StuckPixel") + ana=new StuckPixelAnalysis(new Fei4CfgFileWriter); + else if(type=="Gdac") + ana=new GdacAnalysis; + else if(type=="GdacFast") + ana=new GdacFastAnalysis; + else if(type=="GdacCoarseFast") + ana=new GdacCoarseFastAnalysis; + else if(type=="Fei3Tdac_tune") + ana=new TdacAnalysis(new Fei3CfgFileWriter); + else if(type=="Fei4Tdac_tune") + ana=new TdacAnalysis(new Fei4CfgFileWriter); + else if(type=="Fei4TdacFast_tune") + ana=new TdacFastAnalysis(new Fei4CfgFileWriter); + else if(type=="Threshold") + ana=new ThresholdAnalysis; + else if(type=="Iffanalysis") + ana=new IffAnalysis; + else if(type=="Fei3Fdacanalysis") + ana=new FdacAnalysis(new Fei3CfgFileWriter); + else if(type=="Fei4Fdacanalysis") + ana=new FdacAnalysis(new Fei4CfgFileWriter); + else if(type=="Fei3DigitalTest") + ana=new DigitalTestAnalysis(new Fei3CfgFileWriter); + else if(type=="Fei4DigitalTest") + ana=new DigitalTestAnalysis(new Fei4CfgFileWriter); + else if(type=="TOT") + ana=new TotAnalysis; + else if(type=="TOTCALIB") + ana=new TotCalibAnalysis; + else if(type=="Offset") + ana=new OffsetAnalysis; + else if(type=="ModuleCrosstalk") + ana=new ModuleCrosstalkAnalysis; + else if(type=="Crosstalk") + ana=new CrosstalkAnalysis; + else if(type=="T0") + ana=new T0Analysis; + else if(type=="TimeWalk") + ana=new TimeWalkAnalysis; + else if(type=="MultiTrig") + ana=new MultiTrigAnalysis; + else if(type=="MultiTrigNoise") + ana=new MultiTrigNoiseAnalysis; + else if(type=="SerialNumber") + ana=new SerialNumberAnalysis; + else if(type=="Temperature") + ana=new TemperatureAnalysis; + else if(type=="RegisterTest") + ana=new RegisterTestAnalysis; + else + std::cout<<"Analysis type "<<type<<" is not defined. "<<std::endl; + return ana; +} diff --git a/rce/rcecalib/analysis/AnalysisFactory.hh b/rce/rcecalib/analysis/AnalysisFactory.hh new file mode 100644 index 00000000..1b323238 --- /dev/null +++ b/rce/rcecalib/analysis/AnalysisFactory.hh @@ -0,0 +1,15 @@ +#ifndef ANALYSISFACTORY_HH +#define ANALYSISFACTORY_HH + +#include <string> + +class CalibAnalysis; + +class AnalysisFactory{ +public: + AnalysisFactory(){}; + ~AnalysisFactory(){}; + CalibAnalysis* getAnalysis(std::string &type); +}; + +#endif diff --git a/rce/rcecalib/analysis/AnalysisGui.cc b/rce/rcecalib/analysis/AnalysisGui.cc new file mode 100644 index 00000000..a73e3249 --- /dev/null +++ b/rce/rcecalib/analysis/AnalysisGui.cc @@ -0,0 +1,205 @@ +#include "rcecalib/analysis/AnalysisGui.hh" +#include "rcecalib/server/PixScan.hh" +#include "rcecalib/analysis/CalibAnalysis.hh" +#include "rcecalib/analysis/AnalysisFactory.hh" +#include "TApplication.h" +#include "TGMsgBox.h" +#include "TH1.h" +#include "TKey.h" +#include "TGIcon.h" +#include "TGMenu.h" +#include "TCanvas.h" +#include "TGCanvas.h" +#include "TGListTree.h" +#include "TRootEmbeddedCanvas.h" +#include <TGFileDialog.h> +#include <TROOT.h> +#include <TStyle.h> +#include <assert.h> +#include <iostream> +#include <time.h> +#include <sys/stat.h> +#include <fstream> +#include <list> +#include <pthread.h> +#include <vector> +#include <stdlib.h> + +using namespace RCE; + +AnalysisGui::~AnalysisGui(){ + Cleanup(); +} + +AnalysisGui::AnalysisGui(const char* filename, int scantype, int flavor, const TGWindow *p,UInt_t w,UInt_t h) + : TGMainFrame(p,w,h) { + + // connect x icon on window manager + Connect("CloseWindow()","AnalysisGui",this,"quit()"); + + TGMenuBar *menubar=new TGMenuBar(this,1,1,kHorizontalFrame | kRaisedFrame); + TGLayoutHints *menubarlayout=new TGLayoutHints(kLHintsTop|kLHintsLeft,0,4,0,0); + // menu "File" + TGPopupMenu* filepopup=new TGPopupMenu(gClient->GetRoot()); + //filepopup->AddEntry("&Load Config",LOAD); + //filepopup->AddEntry("&Save Config",SAVE); + filepopup->AddSeparator(); + filepopup->AddEntry("&Quit",QUIT); + menubar->AddPopup("&File",filepopup,menubarlayout); + + AddFrame(menubar, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 0,0,0,2)); + + filepopup->Connect("Activated(Int_t)","AnalysisGui",this,"handleFileMenu(Int_t)"); + + TGVerticalFrame* datapanel=new TGVerticalFrame(this,1,1, kSunkenFrame); + // scan panel + TGHorizontalFrame *datapanel5 = new TGHorizontalFrame(datapanel, 2, 2, kSunkenFrame); + datapanel->AddFrame(datapanel5,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY)); + AddFrame(datapanel,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY)); + + TGVerticalFrame *treepanel = new TGVerticalFrame(datapanel5, 150, 2, kSunkenFrame); + datapanel5->AddFrame(treepanel,new TGLayoutHints(kLHintsExpandY)); + TGVerticalFrame *plotpanel = new TGVerticalFrame(datapanel5, 2, 2, kSunkenFrame); + datapanel5->AddFrame(plotpanel,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY)); + + m_tgc=new TGCanvas(treepanel, 300,100); + //TGViewPort* vp=tgc->GetViewPort(); + m_tree=new TGListTree(m_tgc, kHorizontalFrame); + m_tree->Connect("Clicked(TGListTreeItem*, Int_t)","AnalysisGui", this, "displayHisto(TGListTreeItem*, Int_t)"); + //tree->AddItem(0,"/"); + treepanel->AddFrame(m_tgc,new TGLayoutHints(kLHintsExpandY)); + m_canvas=new TRootEmbeddedCanvas("Canvas",plotpanel,100,100); + m_canvas->GetCanvas()->GetPad(0)->SetRightMargin(0.15); + plotpanel->AddFrame(m_canvas,new TGLayoutHints(kLHintsExpandY|kLHintsExpandX)); + + SetWindowName("Analysis GUI"); + Resize(w,h); + Layout(); + MapSubwindows(); + MapWindow(); + m_file=new TFile(filename,""); + m_anfile=new TFile("analysis.root", "recreate"); + TGListTreeItem* root=m_tree->AddItem(0,"Histos"); + m_file->cd(); + fillHistoTree(root); + + // now run the analysis + std::cout<<"Analyzing"<<std::endl; + PixScan pixscan((PixScan::ScanType)scantype, (PixLib::EnumFEflavour::FEflavour) flavor); + std::string type=pixscan.getAnalysisType(); + std::cout<<"Analysis type is "<<type<<std::endl; + AnalysisFactory af; + CalibAnalysis* ana=af.getAnalysis(type); + if(ana){ + ana->analyze(m_file, m_anfile, &pixscan, 0, 0); + m_anfile->ReOpen("read"); //re-open file for reading + TGListTreeItem* root=m_tree->FindChildByName(0,"Histos"); + TGListTreeItem* anroot=m_tree->AddItem(root,"Analysis"); + const TGPicture *thp = gClient->GetPicture("h1_t.xpm"); + m_anfile->cd(); + TList* histos=gDirectory->GetListOfKeys(); + for(int i=0;i<histos->GetEntries();i++){ + TGListTreeItem* item=m_tree->AddItem(anroot,((TH1*)histos->At(i))->GetName()); + item->SetPictures(thp,thp); + } + updateTree(); + delete ana; + } +} + +void AnalysisGui::quit(){ + m_file->Close(); + m_anfile->Close(); + gApplication->Terminate(0); +} + + +void AnalysisGui::handleFileMenu(int item){ + if(item==QUIT)quit(); +} +void AnalysisGui::clearTree(){ + TGListTreeItem* root=m_tree->FindChildByName(0,"Histos"); + if(root) m_tree->DeleteChildren(root); + root->SetOpen(false); + updateTree(); +} +void AnalysisGui::updateTree(){ + int x=m_tgc->GetViewPort()->GetX(); + int y=m_tgc->GetViewPort()->GetY(); + int w=m_tgc->GetViewPort()->GetWidth(); + int h=m_tgc->GetViewPort()->GetHeight(); + m_tree->DrawRegion(x,y,w,h); +} + +void AnalysisGui::fillHistoTree(TGListTreeItem* branch){ + const TGPicture *thp = gClient->GetPicture("h1_t.xpm"); + TIter nextkey(gDirectory->GetListOfKeys()); + TKey *key; + while ((key=(TKey*)nextkey())) { + TObject *obj = key->ReadObj(); + if(std::string(obj->ClassName())=="TDirectoryFile"){ + gDirectory->cd(key->GetName()); + TGListTreeItem* subdir=m_tree->AddItem(branch,key->GetName()); + fillHistoTree(subdir); + }else{ + TGListTreeItem* his=m_tree->AddItem(branch,key->GetName()); + his->SetPictures(thp, thp); + } + delete obj; + } + gDirectory->cd(".."); +} +void AnalysisGui::displayHisto(TGListTreeItem* item, int b){ + TGListTreeItem *parent=item->GetParent(); + if(parent==0)return; + const char* histoname=item->GetText(); + if(std::string(histoname).substr(0,4)=="loop")return; + if(std::string(histoname).substr(0,8)=="Analysis")return; + if(std::string(parent->GetText())=="Analysis"){ + m_anfile->cd(); + m_histo=(TH1*)gDirectory->Get(histoname); + assert(m_histo!=0); + }else{ + TGListTreeItem *parent1=parent->GetParent(); + if(parent1==0)m_file->cd(); + else{ + TGListTreeItem *parent2=parent1->GetParent(); + if(parent2==0)m_file->cd(parent->GetText()); + else{ + char dir[128]; + sprintf(dir, "%s/%s",parent1->GetText(), parent->GetText()); + m_file->cd(dir); + } + } + m_histo=(TH1*)gDirectory->Get(histoname); + assert(m_histo!=0); + } + m_histo->SetMinimum(0); + if(m_histo->GetDimension()==1)m_histo->Draw(); + else { + m_histo->Draw("colz"); + } + m_canvas->GetCanvas()->Update(); +} + + +//==================================================================== +int main(int argc, char **argv){ + if(argc!=4){ + std::cout<<"Usage: analysisGui filename scantype FE flavor"<<std::endl; + exit(0); + } + gROOT->SetStyle("Plain"); + gStyle->SetOptStat(0); + gStyle->SetPalette(1); + const char *filename=argv[1]; + std::cout<<"Filename "<<filename<<std::endl; + int scantype=atoi(argv[2]); + int flavor=atoi(argv[3]); + TApplication theapp("app",&argc,argv); + new AnalysisGui(filename, scantype, flavor, gClient->GetRoot(),800,600); + theapp.Run(); + return 0; +} + + diff --git a/rce/rcecalib/analysis/AnalysisGui.hh b/rce/rcecalib/analysis/AnalysisGui.hh new file mode 100644 index 00000000..8d39d44f --- /dev/null +++ b/rce/rcecalib/analysis/AnalysisGui.hh @@ -0,0 +1,44 @@ +#ifndef ANALYSISGUI_HH +#define ANALYSISGUI_HH + +#include "TGMdiMainFrame.h" +#include <TGLabel.h> +#include <TGTextEntry.h> +#include <TGNumberEntry.h> +#include "TFile.h" +#include "TH2F.h" +#include <string> + + +class TGListTree; +class TGListTreeItem; +class TH1; +class TRootEmbeddedCanvas; +class IPCGuiCallback; + +class AnalysisGui: public TGMainFrame { +public: + AnalysisGui(const char* filename, int scantype, int flavor, const TGWindow *p,UInt_t w,UInt_t h); + virtual ~AnalysisGui(); + void handleFileMenu(Int_t); + void quit(); + void clearTree(); + void updateTree(); + void displayHisto(TGListTreeItem* item, int b); +private: + + void fillHistoTree(TGListTreeItem* branch); + enum Filemenu {LOAD, SAVE, QUIT}; + TGTextButton* *m_quit; + TGListTree* m_tree; + TH1 *m_histo; + TRootEmbeddedCanvas *m_canvas; + TFile *m_file, *m_anfile; + std::string m_dir; + bool m_delhisto; + TGCanvas *m_tgc; + int m_indx; + +ClassDef (AnalysisGui,0) +}; +#endif diff --git a/rce/rcecalib/analysis/CalibAnalysis.cc b/rce/rcecalib/analysis/CalibAnalysis.cc new file mode 100644 index 00000000..86d84107 --- /dev/null +++ b/rce/rcecalib/analysis/CalibAnalysis.cc @@ -0,0 +1,147 @@ +#include "rcecalib/analysis/CalibAnalysis.hh" +#include "rcecalib/server/ConfigGui.hh" +#include "rcecalib/server/FEI4AConfigFile.hh" +#include "rcecalib/server/FEI4BConfigFile.hh" +#include "rcecalib/server/TurboDaqFile.hh" + +#include <TFile.h> +#include <boost/regex.hpp> +#include <string> +#include <iostream> + +std::string CalibAnalysis::getPath(TFile* file){ + std::string fn(file->GetName()); + std::string name=""; + boost::regex re("[^/]*\\.root"); + std::string maskfilename = boost::regex_replace (fn, re, name); + return maskfilename; +} + +ipc::PixelFEI4AConfig* CalibAnalysis::findFEI4AConfig(ConfigGui* cfg[], int id){ + for(int i=0;i<ConfigGui::MAX_MODULES;i++){ + if(cfg!=0 && cfg[i]->isIncluded() && cfg[i]->getType()=="FEI4A" && cfg[i]->getId()==id){ + cfg[i]->setConfig(); //restore config + m_cfg=cfg[i]; + m_channel=i; + return cfg[i]->getFEI4AConfig(); + } + } + return 0; +} + +const char* CalibAnalysis::findFieldName(ConfigGui* cfg[], int id){ + for(int i=0;i<ConfigGui::MAX_MODULES;i++){ + if(cfg!=0 && cfg[i]->isIncluded() && cfg[i]->getId()==id){ + return cfg[i]->getName(); + } + } + return ""; +} + +const std::string CalibAnalysis::findFEType(ConfigGui* cfg[], int id){ + for(int i=0;i<ConfigGui::MAX_MODULES;i++){ + if(cfg!=0 && cfg[i]->isIncluded() && cfg[i]->getId()==id){ + return cfg[i]->getType(); + } + } + return ""; +} + +ipc::PixelFEI4BConfig* CalibAnalysis::findFEI4BConfig(ConfigGui* cfg[], int id){ + for(int i=0;i<ConfigGui::MAX_MODULES;i++){ + if(cfg!=0 && cfg[i]->isIncluded() && cfg[i]->getType()=="FEI4B" && cfg[i]->getId()==id){ + cfg[i]->setConfig(); //restore config + m_cfg=cfg[i]; + m_channel=i; + return cfg[i]->getFEI4BConfig(); + } + } + return 0; +} + +ipc::PixelModuleConfig* CalibAnalysis::findFEI3Config(ConfigGui* cfg[], int id){ + for(int i=0;i<ConfigGui::MAX_MODULES;i++){ + if(cfg!=0 && cfg[i]->isIncluded() && cfg[i]->getType()=="FEI3" && cfg[i]->getId()==id){ + cfg[i]->setConfig(); //restore config + m_cfg=cfg[i]; + m_channel=i; + return cfg[i]->getModuleConfig(); + } + } + return 0; +} + +void CalibAnalysis::writeTopFile(ConfigGui* cfg[],TFile* anfile, int runno ){ + char key[16]; + sprintf(key, "%d", runno); + std::string path=getPath(anfile)+"configUpdate"; + //std::cout << path << std::endl; + std::ofstream topfile((path+"/top/config__"+key+".cfg").c_str()); + std::string name; + for(int i=0;i<ConfigGui::MAX_MODULES;i++){ + if(cfg[i]->isIncluded()) + name=path+"/"+cfg[i]->getConfdir()+"/configs/"+cfg[i]->getConfigName()+"__"+key+".cfg"; + else + name=cfg[i]->getFilename(); + cfg[i]->copyConfig(topfile, name.c_str()); + } + topfile.close(); + m_update=true; +} + +void CalibAnalysis::writeFEI4Config(TFile* anfile, int runno){ + if(m_cfg!=0){ + char key[16]; + sprintf(key, "%d", runno); + std::string path=getPath(anfile)+"configUpdate"; + m_update=true; + if(m_cfg->getType()=="FEI4A"){ + FEI4AConfigFile cf; + cf.writeModuleConfig(m_cfg->getFEI4AConfig(), path.c_str(), m_cfg->getConfdir(), m_cfg->getConfigName(), key); + } else if(m_cfg->getType()=="FEI4B"){ + FEI4BConfigFile cf; + cf.writeModuleConfig(m_cfg->getFEI4BConfig(), path.c_str(), m_cfg->getConfdir(), m_cfg->getConfigName(), key); + } + m_cfg->setConfig(); //restore config + } +} + +void CalibAnalysis::writeFEI3Config(TFile* anfile, int runno){ + if(m_cfg!=0){ + char key[16]; + sprintf(key, "%d", runno); + std::string path=getPath(anfile)+"configUpdate"; + m_update=true; + if(m_cfg->getType()=="FEI3"){ + TurboDaqFile cf; + //cf.dump(* m_cfg->getFEI3Config()); + cf.writeModuleConfig(m_cfg->getModuleConfig(), path.c_str(), m_cfg->getConfdir(), m_cfg->getConfigName(), key); + } + m_cfg->setConfig(); //restore config + } +} + +void CalibAnalysis::clearFEI4Masks(unsigned char (*masks)[ipc::IPC_N_I4_PIXEL_ROWS]){ + for(int i=0;i<ipc::IPC_N_I4_PIXEL_COLUMNS;i++){ + for(int j=0;j<ipc::IPC_N_I4_PIXEL_ROWS;j++){ + masks[i][j]|=0x1; //set bit 0 (enable) + masks[i][j]&=0xf7; //reset bit 3 (hitbus) + } + } +} + +std::string CalibAnalysis::addPosition(const char* hname, ConfigGui* cfg[]){ + boost::cmatch matches; + boost::regex re("Mod_(\\d+)"); + if(boost::regex_search(hname, matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + int id=strtol(match.c_str(),0,10); + for(int i=0;i<ConfigGui::MAX_MODULES;i++){ + if(cfg[i]->isIncluded() && cfg[i]->getId()==id){ + return std::string(Form("%d", 1+i/(ConfigGui::MAX_MODULES/2)))+std::string(cfg[i]->getName())+":"+hname; + } + } + } + return hname; +} diff --git a/rce/rcecalib/analysis/CalibAnalysis.hh b/rce/rcecalib/analysis/CalibAnalysis.hh new file mode 100644 index 00000000..4fd5bf3a --- /dev/null +++ b/rce/rcecalib/analysis/CalibAnalysis.hh @@ -0,0 +1,38 @@ +#ifndef CALIBANALYSIS_HH +#define CALIBANALYSIS_HH + +#include <string> +#include "PixelFEI4AConfig.hh" +#include "PixelFEI4BConfig.hh" +#include "PixelModuleConfig.hh" + +class TFile; +class ConfigGui; +namespace RCE{ + class PixScan; +} + +class CalibAnalysis{ +public: + CalibAnalysis(): m_cfg(0), m_update(false){} + virtual ~CalibAnalysis(){} + virtual void analyze(TFile* file, TFile* anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[])=0; + std::string getPath(TFile* file); + ipc::PixelFEI4AConfig* findFEI4AConfig(ConfigGui* cfg[], int id); + ipc::PixelFEI4BConfig* findFEI4BConfig(ConfigGui* cfg[], int id); + ipc::PixelModuleConfig* findFEI3Config(ConfigGui* cfg[], int id); + void writeFEI4Config(TFile *anfile, int runno); + void writeFEI3Config(TFile *anfile, int runno); + bool configUpdate(){return m_update;} + void writeTopFile(ConfigGui* cfg[], TFile* anfile, int runno); + const char* findFieldName(ConfigGui* cfg[], int id); + const std::string findFEType(ConfigGui* cfg[], int id); + void clearFEI4Masks(unsigned char (*masks)[ipc::IPC_N_I4_PIXEL_ROWS]); + static std::string addPosition(const char* hname, ConfigGui* cfg[]); +private: + ConfigGui* m_cfg; + int m_channel; + bool m_update; +}; + +#endif diff --git a/rce/rcecalib/analysis/CfgFileWriter.cc b/rce/rcecalib/analysis/CfgFileWriter.cc new file mode 100644 index 00000000..f8c9af76 --- /dev/null +++ b/rce/rcecalib/analysis/CfgFileWriter.cc @@ -0,0 +1,13 @@ +#include "rcecalib/analysis/CfgFileWriter.hh" +#include <TFile.h> +#include <boost/regex.hpp> +#include <string> +#include <iostream> + +std::string CfgFileWriter::getPath(TFile* file){ + std::string fn(file->GetName()); + std::string name=""; + boost::regex re("[^/]*\\.root"); + std::string maskfilename = boost::regex_replace (fn, re, name); + return maskfilename; +} diff --git a/rce/rcecalib/analysis/CfgFileWriter.hh b/rce/rcecalib/analysis/CfgFileWriter.hh new file mode 100644 index 00000000..4fa14d72 --- /dev/null +++ b/rce/rcecalib/analysis/CfgFileWriter.hh @@ -0,0 +1,17 @@ +#ifndef CFGFILEWRITER_HH +#define CFGFILEWRITER_HH + +class TH2; +class TFile; +#include <string> + +class CfgFileWriter{ +public: + CfgFileWriter(){} + virtual ~CfgFileWriter(){} + virtual void writeDacFile(const char* filename, TH2* his)=0; + virtual void writeMaskFile(const char* filename, TH2* his)=0; + std::string getPath(TFile*); +}; + +#endif diff --git a/rce/rcecalib/analysis/CrosstalkAnalysis.cc b/rce/rcecalib/analysis/CrosstalkAnalysis.cc new file mode 100644 index 00000000..32ef1385 --- /dev/null +++ b/rce/rcecalib/analysis/CrosstalkAnalysis.cc @@ -0,0 +1,168 @@ +#include "rcecalib/analysis/CrosstalkAnalysis.hh" +#include "rcecalib/server/PixScan.hh" + +#include <TFile.h> +#include <TH2.h> +#include <TH2D.h> +#include <TH1.h> +#include <TKey.h> +#include <boost/regex.hpp> +#include <iostream> +#include <fstream> +#include "TH1D.h" +#include "TF1.h" +#include "TStyle.h" + + +void CrosstalkAnalysis::analyze(TFile* file, TFile *anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]){ + std::cout<<"Crosstalk analysis"<<std::endl; + unsigned int numval=scan->getLoopVarValues(0).size(); + gStyle->SetOptFit(10); + gStyle->SetOptStat(0); + std::map<int, TH1D*> histmap; + TIter nextkey(gDirectory->GetListOfKeys()); // histograms + TKey *key; + while ((key=(TKey*)nextkey())) { + file->cd(); + std::string hname(key->GetName()); + boost::cmatch matches; + boost::regex re("_(\\d+)_Mean"); + boost::regex re2("Mean"); + char name[128]; + char title[128]; + if(boost::regex_search(hname.c_str(), matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + int id=strtol(match.c_str(),0,10); + std::string chi2HistoName = boost::regex_replace (hname, re2, "ChiSquare"); + std::string sigmaHistoName = boost::regex_replace (hname, re2, "Sigma"); + TH2* histo = (TH2*)key->ReadObj(); + TH2* chi2Histo=(TH2*)gDirectory->Get(chi2HistoName.c_str()); + TH2* sigmahisto=(TH2*)gDirectory->Get(sigmaHistoName.c_str()); + assert(chi2Histo!=0); + assert(sigmahisto!=0); + int binsx=histo->GetNbinsX(); + int binsy=histo->GetNbinsY(); + sprintf(name, "thresh2d_Mod_%d", id); + sprintf(title, "Thresholds Module %d at %s", id, findFieldName(cfg, id)); + TH2F* thresh2d=new TH2F(name, title, binsx, 0, binsx, binsy, 0, binsy); + thresh2d->GetXaxis()->SetTitle("Column"); + thresh2d->GetYaxis()->SetTitle("Row"); + sprintf(name, "thresh1d_Mod_%d", id); + sprintf(title, "Thresholds Module %d at %s", id, findFieldName(cfg, id)); + int nbins=binsx*binsy; + TH1F* thresh1d=new TH1F(name, title, nbins, 0, (float)nbins); + thresh1d->GetXaxis()->SetTitle("Channel"); + thresh1d->SetOption("p9"); + sprintf(name, "sigma1d_Mod_%d", id); + sprintf(title, "Sigma Module %d at %s", id, findFieldName(cfg, id)); + TH1F* sigma1d=new TH1F(name, title, nbins, 0, (float)nbins); + sigma1d->GetXaxis()->SetTitle("Channel"); + sigma1d->SetOption("p9"); + sprintf(name, "threshdist_Mod_%d", id); + sprintf(title, "Threshold distribution Module %d at %s", id, findFieldName(cfg, id)); + TH1F* threshdist=new TH1F(name, title, 500, 20000, 60000); + threshdist->GetXaxis()->SetTitle("Threshold"); + sprintf(name, "sigmadist_Mod_%d", id); + sprintf(title, "Sigma distribution Module %d at %s", id, findFieldName(cfg, id)); + TH1F* sigmadist=new TH1F(name, title, 100, 0, 12000); + sigmadist->GetXaxis()->SetTitle("Sigma"); + sprintf(name, "crosstalk2d_Mod_%d", id); + sprintf(title, "Crosstalk for Last Scan Point, Module %d at %s", id, findFieldName(cfg, id)); + TH2F* crosstalk2d=new TH2F(name, title, binsx, 0, binsx, binsy, 0, binsy); + crosstalk2d->GetXaxis()->SetTitle("Column"); + crosstalk2d->GetYaxis()->SetTitle("Row"); + sprintf(name, "crosstalk1d_Mod_%d", id); + sprintf(title, "Crosstalk for Last Scan Point, Module %d at %s", id, findFieldName(cfg, id)); + TH1F* crosstalk1d=new TH1F(name, title, nbins, 0, (float)nbins); + crosstalk1d->GetXaxis()->SetTitle("Channel"); + crosstalk1d->SetOption("p9"); + + TH1D* hits1d=new TH1D(Form("HitsPerBin_Mod_%d", id), + Form("Hits per bin Mod %d at %s", id, findFieldName(cfg, id)), + numval, -.5, (float)numval-.5) ; + hits1d->GetXaxis()->SetTitle("Scan Point"); + + + for (int i=1;i<=histo->GetNbinsX();i++){ + for(int j=1;j<=histo->GetNbinsY();j++){ + thresh2d->SetBinContent(i,j,histo->GetBinContent(i,j)); + thresh1d->SetBinContent((i-1)*histo->GetNbinsY()+j, histo->GetBinContent(i,j)); + threshdist->Fill(histo->GetBinContent(i,j)); + sigma1d->SetBinContent((i-1)*histo->GetNbinsY()+j, sigmahisto->GetBinContent(i,j)); + sigmadist->Fill(sigmahisto->GetBinContent(i,j)); + } + } + + TF1 gauss("gauss", "gaus"); + gauss.SetParameter(0, threshdist->GetMaximum()); + gauss.SetParameter(1, threshdist->GetMaximumBin()*threshdist->GetBinWidth(1)); + threshdist->Fit(&gauss,"q", ""); + + + + int numdistbins=100; + + std::string finalhistoName = boost::regex_replace (hname, re2, Form("Occupancy_Point_%03d", numval-1)); + TH2* finalOccHisto=(TH2*)gDirectory->Get(finalhistoName.c_str()); + if(finalOccHisto!=0){ + numdistbins = finalOccHisto->GetMaximum(); + } + + sprintf(name, "crosstalkdist_Mod_%d", id); + sprintf(title, "Occupancy distribution for highest Scan Point, Module %d at %s", id, findFieldName(cfg, id)); + TH1F* crosstalkdist=new TH1F(name, title, numdistbins, -0.5, (float)numdistbins - 0.5); + crosstalkdist->GetXaxis()->SetTitle("Occupancy for highest Scan Point"); + + if(finalOccHisto==0){ + std::cout<<"Final Occupancy histogram not found. Won't fill crosstalk histos."<<std::endl; + } + else{ + + for (int i=1;i<=finalOccHisto->GetNbinsX();i++){ + for(int j=1;j<=finalOccHisto->GetNbinsY();j++){ + crosstalk2d->SetBinContent(i,j,finalOccHisto->GetBinContent(i,j)); + crosstalk1d->SetBinContent((i-1)*finalOccHisto->GetNbinsY()+j, finalOccHisto->GetBinContent(i,j)); + crosstalkdist->Fill(finalOccHisto->GetBinContent(i,j)); + } + } + + } + + + for(unsigned int k=0;k<numval;k++){ + + std::string histoName = boost::regex_replace (hname, re2, Form("Occupancy_Point_%03d", k)); + TH2* occHisto=(TH2*)gDirectory->Get(histoName.c_str()); + if(occHisto==0){ + std::cout<<"No Occupancy histograms found. Won't fill 1-d hit histo."<<std::endl; + break; + } + hits1d->SetBinContent(k+1, occHisto->GetSumOfWeights()); + } + + anfile->cd(); + thresh2d->Write(); + thresh2d->SetDirectory(gDirectory); + thresh1d->Write(); + thresh1d->SetDirectory(gDirectory); + threshdist->Write(); + threshdist->SetDirectory(gDirectory); + sigma1d->Write(); + sigma1d->SetDirectory(gDirectory); + sigmadist->Write(); + sigmadist->SetDirectory(gDirectory); + + crosstalk2d->Write(); + crosstalk2d->SetDirectory(gDirectory); + crosstalk1d->Write(); + crosstalk1d->SetDirectory(gDirectory); + crosstalkdist->Write(); + crosstalkdist->SetDirectory(gDirectory); + + hits1d->Write(); + hits1d->SetDirectory(gDirectory); + } + } + +} diff --git a/rce/rcecalib/analysis/CrosstalkAnalysis.hh b/rce/rcecalib/analysis/CrosstalkAnalysis.hh new file mode 100644 index 00000000..b5e52fa4 --- /dev/null +++ b/rce/rcecalib/analysis/CrosstalkAnalysis.hh @@ -0,0 +1,24 @@ +#ifndef CROSSTALKANALYSIS_HH +#define CROSSTALKANALYSIS_HH + +#include "rcecalib/analysis/CalibAnalysis.hh" +#include <map> + +class ConfigGui; +class TFile; +class TH2; +class TH1D; + +namespace RCE{ + class PixScan; +} + +class CrosstalkAnalysis: public CalibAnalysis{ +public: + CrosstalkAnalysis(): CalibAnalysis(){} + ~CrosstalkAnalysis(){} + void analyze(TFile* file, TFile* anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]); +}; + + +#endif diff --git a/rce/rcecalib/analysis/DigitalTestAnalysis.cc b/rce/rcecalib/analysis/DigitalTestAnalysis.cc new file mode 100644 index 00000000..7cdaeed2 --- /dev/null +++ b/rce/rcecalib/analysis/DigitalTestAnalysis.cc @@ -0,0 +1,111 @@ +#include "rcecalib/analysis/DigitalTestAnalysis.hh" +#include "rcecalib/server/PixScan.hh" + +#include <TFile.h> +#include <TH2.h> +#include <TH2D.h> +#include <TH1.h> +#include <TKey.h> +#include <boost/regex.hpp> +#include <iostream> +#include <fstream> + +namespace{ + const double threshold=0; +} +using namespace RCE; + +void DigitalTestAnalysis::analyze(TFile* file, TFile *anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]){ + std::cout<<"Digital test analysis"<<std::endl; + if(file->Get("loop1_0"))file->cd("loop1_0"); + TIter nextkey(gDirectory->GetListOfKeys()); + TKey *key; + std::vector<float> masks; + std::vector<float> digimaskdistros; + std::vector<std::string> pos; + boost::regex re("_(\\d+)_Occupancy"); + double nHits=(double)scan->getRepetitions(); + + + while ((key=(TKey*)nextkey())) { + std::string name(key->GetName()); + boost::cmatch matches; + if(boost::regex_search(name.c_str(), matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + int id=strtol(match.c_str(),0,10); + std::string match2=addPosition(name.c_str(), cfg).substr(0,5); + pos.push_back(match2); + + TH2* histo = (TH2*)key->ReadObj(); + TH2D* mhis=new TH2D(Form("Mask_Mod_%d",id), Form("Mask Mod %d at %s", id, findFieldName(cfg, id)), + histo->GetNbinsX(), histo->GetXaxis()->GetXmin(), histo->GetXaxis()->GetXmax(), + histo->GetNbinsY(), histo->GetYaxis()->GetXmin(), histo->GetYaxis()->GetXmax()); + mhis->GetXaxis()->SetTitle("Column"); + mhis->GetYaxis()->SetTitle("Row"); + unsigned char (*masks)[ipc::IPC_N_I4_PIXEL_ROWS]=0; + ipc::PixelFEI4AConfig* conf=findFEI4AConfig(cfg, id); + if(conf)masks=conf->FEMasks; + else { + ipc::PixelFEI4BConfig* confb=findFEI4BConfig(cfg, id); + if(confb)masks=confb->FEMasks; + } + if(masks && scan->clearMasks()==true)clearFEI4Masks(masks); + for (int i=0;i<histo->GetNbinsX();i++){ + for(int j=0;j<histo->GetNbinsY();j++){ + if(histo->GetBinContent(i+1, j+1)!=nHits){ + mhis->SetBinContent(i+1,j+1,1); + if(masks){ + masks[i][j]&=0xfe; //reset bit 0 (enable) + masks[i][j]|=0x8; //reset bit 3 (hitbus) + } + } + } + } + digimaskdistros.push_back(mhis->Integral()); + if(masks) writeFEI4Config(anfile, runno); + m_fw->writeMaskFile(Form("%sMask_Mod_%d", m_fw->getPath(anfile).c_str(), id), mhis); + delete histo; + anfile->cd(); + mhis->Write(); + mhis->SetDirectory(gDirectory); + } + } + + TH1I* mask_distro[2]; + mask_distro[0]=new TH1I(Form("1-Mask"), Form("Mask Distribution 1st stave"), 32, 0, 32); + mask_distro[1]=new TH1I(Form("2-Mask"), Form("Mask Distribution 2nd stave"), 32, 0, 32); + char position[10]; + + for(int i=0;i<4;i++){ //half stave + if(i%2==0)position[0]='A'; + else position[0]='C'; + //mhis[i]->GetYaxis()->SetTitle("Threshold (e)"); + for(int j=1;j<=8;j++){ //module + for(int k=1;k<=2;k++){ //FE + sprintf(&position[1], "%d-%d", j,k); + int bin=0; + if(i%2==0)bin=17-((j-1)*2+k); // A side + else bin=16+(j-1)*2+k; + mask_distro[i/2]->GetXaxis()->SetBinLabel(bin,position); + for(size_t l=0;l<pos.size();l++){ + if(std::string(position)==pos[l].substr(1,4) && + pos[l].substr(0,1)==Form("%d", i/2+1)){ + mask_distro[i/2]->SetBinContent(bin, digimaskdistros[l]); + } + } + } + + } + if(i%2==1){ + //anfile->cd(); + mask_distro[i/2]->SetFillColor(kRed); + mask_distro[i/2]->Write(); + mask_distro[i/2]->SetDirectory(gDirectory); + } + + } + + if(configUpdate())writeTopFile(cfg, anfile, runno); +} + diff --git a/rce/rcecalib/analysis/DigitalTestAnalysis.hh b/rce/rcecalib/analysis/DigitalTestAnalysis.hh new file mode 100644 index 00000000..d80dd817 --- /dev/null +++ b/rce/rcecalib/analysis/DigitalTestAnalysis.hh @@ -0,0 +1,25 @@ +#ifndef DIGITALTESTANALYSIS_HH +#define DIGITALTESTANALYSIS_HH + +#include "rcecalib/analysis/CalibAnalysis.hh" +#include "rcecalib/analysis/CfgFileWriter.hh" + +class ConfigGui; +class TFile; +class TH2D; +namespace RCE{ + class PixScan; +} + +class DigitalTestAnalysis: public CalibAnalysis{ +public: + DigitalTestAnalysis(CfgFileWriter* fw): CalibAnalysis(), m_fw(fw){} + ~DigitalTestAnalysis(){delete m_fw;} + void analyze(TFile* file, TFile* anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]); + void writeMaskFile(TH2D* his, TFile* anfile); +private: + CfgFileWriter* m_fw; +}; + + +#endif diff --git a/rce/rcecalib/analysis/Fdac_Analysis.cc b/rce/rcecalib/analysis/Fdac_Analysis.cc new file mode 100644 index 00000000..e979458f --- /dev/null +++ b/rce/rcecalib/analysis/Fdac_Analysis.cc @@ -0,0 +1,218 @@ +#include "rcecalib/analysis/Fdac_Analysis.hh" +#include "rcecalib/config/FEI3/Frontend.hh" +#include <boost/regex.hpp> + +#include <TFile.h> +#include <TH2.h> +#include <TH2D.h> +#include <TH1D.h> +#include <TKey.h> +#include <TStyle.h> +#include <iostream> +#include <iomanip> +#include <fstream> +#include <cmath> + +void FdacAnalysis::analyze(TFile* file, TFile *anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]){ + gStyle->SetOptFit(111); + printf("Begin FDAC Analysis\n"); + float target = float(scan->getTotTargetValue()); + printf("Target Tot Value: %2.1f\n",target); + std::vector<float> loopVar=scan->getLoopVarValues(0); + size_t numvals=loopVar.size(); + //TH1F* iffhis = new TH1F("iff_v_module","Best IF Setting",128,0,127); + //iffhis->GetXaxis()->SetTitle("Module"); + //iffhis->GetYaxis()->SetTitle("IF Setting"); + std::map<int, odata> *histomap=new std::map<int, odata>[numvals]; + TKey *key; + int binsx=0, binsy=0; + for (size_t i=0;i<numvals;i++){ + TIter nextkey(gDirectory->GetListOfKeys()); // FDAC settings + while ((key=(TKey*)nextkey())) { + std::string name(key->GetName()); + boost::regex re(Form("_(\\d+)_Occupancy_Point_%03d", i)); + boost::cmatch matches; + if(boost::regex_search(name.c_str(), matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + int lnm=strtol(match.c_str(),0,10); + histomap[i][lnm].occ = (TH2*)key->ReadObj(); + boost::regex re2("Occupancy"); + std::string totHistoName = boost::regex_replace (name, re2, "ToT"); + histomap[i][lnm].tot=(TH2*)gDirectory->Get(totHistoName.c_str()); + std::string tot2HistoName = boost::regex_replace (name, re2, "ToT2"); + histomap[i][lnm].tot2=(TH2*)gDirectory->Get(tot2HistoName.c_str()); + assert(histomap[i][lnm].tot2); + binsx=histomap[i][lnm].tot2->GetNbinsX(); + binsy=histomap[i][lnm].tot2->GetNbinsY(); + } + } + } + for(std::map<int, odata>::iterator it=histomap[0].begin();it!=histomap[0].end();it++){ + int id=it->first; + int max=16; + if(findFEType(cfg, id)=="FEI3")max=64; + struct ipc::PixelFEI4Trims *trims=0; + struct ipc::PixelModuleConfig *conf3=0; + ipc::PixelFEI4AConfig* confa=findFEI4AConfig(cfg, id); + if(confa)trims=&confa->FETrims; + else{ + ipc::PixelFEI4BConfig* confb=findFEI4BConfig(cfg, id); + if(confb)trims=&confb->FETrims; + else conf3=findFEI3Config(cfg, id); + } + TH2D* fdachis = new TH2D(Form("FDAC_Mod_%i", id), + Form("Best FDAC Settings Mod %d at %s", id, findFieldName(cfg, id)), + binsx,0,binsx,binsy,0,binsy); + fdachis->GetXaxis()->SetTitle("Column"); + fdachis->GetYaxis()->SetTitle("Row"); + TH2D* ahis = new TH2D(Form("ToT_MinDiff_Mod_%i", id), + Form("min(ToT - Target ToT) Mod %d at %s", id, findFieldName(cfg, id)), + binsx,0,binsx,binsy,0,binsy); + ahis->GetXaxis()->SetTitle("Column"); + ahis->GetYaxis()->SetTitle("Row"); + TH2D* badpix = new TH2D(Form("BadPixels_Mod_%i", id), + Form("Bad Pixel Map Mod %d at %s", id, findFieldName(cfg, id)), + binsx,0,binsx,binsy,0,binsy); + badpix->GetXaxis()->SetTitle("Column"); + badpix->GetYaxis()->SetTitle("Row"); + TH1D* channel = new TH1D(Form("ToT_MinDiff_Channel_Mod_%i", id), + Form("min(ToT - Target ToT) Mod %d at %s", id, findFieldName(cfg, id)), + binsx*binsy,0,binsx*binsy); + channel->GetXaxis()->SetTitle("Channel"); + channel->SetOption("p9"); + TH1D* dist = new TH1D(Form("ToT_MinDiff_Dist_Mod_%i", id), + Form("ToT - Target Mod %d at %s", id, findFieldName(cfg, id)), + 100, -2, 2); + dist->GetXaxis()->SetTitle("ToT"); + TH1D* totdist; + if(findFEType(cfg, id)=="FEI3"){ + totdist = new TH1D(Form("ToT_Dist_Mod_%i", id), + Form("ToT Mod %d at %s", id, findFieldName(cfg, id)), + 641, -.05, 64.05); + }else{ + totdist = new TH1D(Form("ToT_Dist_Mod_%i", id), + Form("ToT Mod %d at %s", id, findFieldName(cfg, id)), + 161, -.05, 16.05); + } + totdist->GetXaxis()->SetTitle("ToT"); + TH1F* tot1d=new TH1F(Form("tot1d_Mod_%d", id), + Form("ToT Module %d at %s", id, findFieldName(cfg, id)), + binsx*binsy, 0, (float)binsx*binsy); + tot1d->GetXaxis()->SetTitle("Channel"); + tot1d->SetMinimum(0); + tot1d->SetMaximum(max); + tot1d->SetOption("p9"); + TH2F* tot2d=new TH2F(Form("tot2d_Mod_%d", id), + Form("ToT Module %d at %s", id, findFieldName(cfg, id)), + binsx, 0, binsx, binsy, 0, binsy); + tot2d->GetXaxis()->SetTitle("Column"); + tot2d->GetYaxis()->SetTitle("Row"); + tot2d->SetMinimum(0); + tot2d->SetMaximum(max); + int chan; + for(int c = 1; c <= binsx; c++){ + for(int r = 1; r <= binsy ; r++){ + ahis->SetBinContent(c,r,-1.0); + chan = r + (c-1)*binsy; + channel->SetBinContent(chan,-1.0); + } + } + for(int j = 1; j <= fdachis->GetNbinsX(); j++){ + for(int k = 1; k <= fdachis->GetNbinsY(); k++){ + int value = 0; + float min = 999999.9; + float diff= 999999.9; + std::vector<float> vals; + for(unsigned i = 0; i < numvals; i++){ + //printf("Point %3i\n",i); + TH2* occ_histo=histomap[i][id].occ; + TH2* tot_histo=histomap[i][id].tot; + float nhits = occ_histo->GetBinContent(j,k); + float tot=0; + if(nhits != 0){ + tot = float(tot_histo->GetBinContent(j,k)) / nhits; + if(fabs(tot - target) < min){ + min = fabs(tot - target); + diff = (tot-target); + value = i; + } + } + vals.push_back(tot); + } + // interpolate + int intval=int(loopVar[value]+.1); + /* + //below found value + if(value!=0 && vals[value-1]!=vals[value] && loopVar[value]!=loopVar[value-1]){ + float m=(vals[value]-vals[value-1])/(loopVar[value]-loopVar[value-1]); + float n=vals[value]-m*loopVar[value]; + for (int i=int(loopVar[value-1]+1.1);i<int(loopVar[value]+0.1);i++){ + if(fabs(m*i+n-target)<min){ + min=fabs(m*i+n-target); + diff=m*i+n-target; + intval=i; + } + } + } + //above found value + if((unsigned)value!=numvals-1 && vals[value+1]!=vals[value] && loopVar[value]!=loopVar[value+1]){ + float m=(vals[value]-vals[value+1])/(loopVar[value]-loopVar[value+1]); + float n=vals[value]-m*loopVar[value]; + for (int i=int(loopVar[value]+1.1);i<int(loopVar[value+1]+0.1);i++){ + if(fabs(m*i+n-target)<min){ + min=fabs(m*i+n-target); + diff=m*i+n-target; + intval=i; + } + } + } + */ + if(min < 1000){ + ahis->SetBinContent(j,k,min); + fdachis->SetBinContent(j,k,intval); + if(trims)trims->dacFeedbackTrim[j-1][k-1]=intval; + else if (conf3){ + int chip=(j-1)/FEI3::Frontend::N_COLS; + int col=(j-1)%FEI3::Frontend::N_COLS; + int row=k-1; + conf3->FEConfig[chip].FETrims.dacFeedbackTrim[row][col]=intval; + } + chan = k + (j-1)*binsy; + if(min<max)channel->SetBinContent(chan,min); + dist->Fill(diff); + totdist->Fill(diff+target); + tot1d->SetBinContent(chan, diff+target); + tot2d->SetBinContent(j, k, diff+target); + if(min>1)badpix->SetBinContent(j,k,1); + } + else badpix->SetBinContent(j,k,1); + } + } + dist->Fit("gaus"); + anfile->cd(); + fdachis->Write(); + fdachis->SetDirectory(gDirectory); + ahis->Write(); + ahis->SetDirectory(gDirectory); + badpix->Write(); + badpix->SetDirectory(gDirectory); + channel->Write(); + channel->SetDirectory(gDirectory); + dist->Write(); + dist->SetDirectory(gDirectory); + totdist->Write(); + totdist->SetDirectory(gDirectory); + tot1d->Write(); + tot1d->SetDirectory(gDirectory); + tot2d->Write(); + tot2d->SetDirectory(gDirectory); + m_fw->writeDacFile(Form("%sFdacs_Mod_%d", m_fw->getPath(anfile).c_str(), id), fdachis); + if(trims) writeFEI4Config(anfile, runno); + if(conf3) writeFEI3Config(anfile, runno); + } + if(configUpdate())writeTopFile(cfg, anfile, runno); + delete [] histomap; + printf("Done Analysis\n"); +} + diff --git a/rce/rcecalib/analysis/Fdac_Analysis.hh b/rce/rcecalib/analysis/Fdac_Analysis.hh new file mode 100644 index 00000000..d6a53bf3 --- /dev/null +++ b/rce/rcecalib/analysis/Fdac_Analysis.hh @@ -0,0 +1,30 @@ +#ifndef FDAC_ANALYSIS_HH +#define FDAC_ANALYSIS_HH + +#include "rcecalib/analysis/CalibAnalysis.hh" +#include "rcecalib/analysis/CfgFileWriter.hh" +#include "rcecalib/server/PixScan.hh" + +class ConfigGui; +class TFile; +class TH2; +namespace RCE{ + class PixScan; +} + +class FdacAnalysis: public CalibAnalysis{ +public: + struct odata{ + TH2* occ; + TH2* tot; + TH2* tot2; + }; + FdacAnalysis(CfgFileWriter* fw): CalibAnalysis(), m_fw(fw){} + ~FdacAnalysis(){delete m_fw;} + void analyze(TFile* file, TFile* anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]); +private: + CfgFileWriter* m_fw; +}; + + +#endif diff --git a/rce/rcecalib/analysis/Fei3CfgFileWriter.cc b/rce/rcecalib/analysis/Fei3CfgFileWriter.cc new file mode 100644 index 00000000..458ee8ca --- /dev/null +++ b/rce/rcecalib/analysis/Fei3CfgFileWriter.cc @@ -0,0 +1,52 @@ +#include "rcecalib/analysis/Fei3CfgFileWriter.hh" + +#include <iostream> +#include <fstream> +#include <boost/regex.hpp> +#include <TFile.h> +#include <TH2.h> + + +void Fei3CfgFileWriter::writeDacFile(const char* filename, TH2* tdac){ + int ncol=18; + int nrow=160; + std::cout<<std::dec; + for (int i=0;i<16;i++){ + std::string name(filename); + name+=Form("_FE_%d.dat",i); + std::ofstream maskfile(name.c_str()); + for (int col=1;col<=ncol;col++){ + for (int row=1;row<=nrow;row++){ + maskfile<<int(tdac->GetBinContent(i*ncol+col, row)+0.1)<<" "; + } + maskfile<<std::endl; + } + maskfile.close(); + } +} + + +void Fei3CfgFileWriter::writeMaskFile(const char* filename, TH2* histo){ + int ncol=18; + std::cout<<std::dec; + for (int i=0;i<16;i++){ + std::string name(filename); + name+=Form("_FE_%d.dat",i); + std::ofstream maskfile(name.c_str()); + for (int l=0;l<ncol;l++){ + std::cout<<Form("%-6d", l); + for(int j=4;j>=0;j--){ + unsigned mask=0; + std::cout<<" "; + for(int k=31;k>=0;k--){ + if(histo->GetBinContent(i*ncol+l+1, j*32+k+1)!=0)mask|=1; + mask<<=1; + } + std::cout<<std::hex<<mask<<std::dec; + } + std::cout<<std::endl; + } + maskfile<<std::endl; + maskfile.close(); + } +} diff --git a/rce/rcecalib/analysis/Fei3CfgFileWriter.hh b/rce/rcecalib/analysis/Fei3CfgFileWriter.hh new file mode 100644 index 00000000..7c0381de --- /dev/null +++ b/rce/rcecalib/analysis/Fei3CfgFileWriter.hh @@ -0,0 +1,14 @@ +#ifndef FEI3CFGFILEWRITER_HH +#define FEI3CFGFILEWRITER_HH + +#include "rcecalib/analysis/CfgFileWriter.hh" + +class Fei3CfgFileWriter: public CfgFileWriter{ +public: + Fei3CfgFileWriter(){} + ~Fei3CfgFileWriter(){} + void writeDacFile(const char* filename, TH2* his); + void writeMaskFile(const char* filename, TH2* his); +}; + +#endif diff --git a/rce/rcecalib/analysis/Fei4CfgFileWriter.cc b/rce/rcecalib/analysis/Fei4CfgFileWriter.cc new file mode 100644 index 00000000..8342ff51 --- /dev/null +++ b/rce/rcecalib/analysis/Fei4CfgFileWriter.cc @@ -0,0 +1,51 @@ +#include "rcecalib/analysis/Fei4CfgFileWriter.hh" + +#include <iostream> +#include <fstream> +#include <boost/regex.hpp> +#include <TFile.h> +#include <TH2.h> + +void Fei4CfgFileWriter::writeDacFile(const char* filename, TH2* tdac){ + std::ofstream maskfile(Form("%s.dat",filename)); + char line[512]; + for (int i=0;i<674;i++){ + if(i>1){ + sprintf(line, "%3d",i/2); + maskfile<<line; + if(i%2==0)maskfile<<"a "; + else maskfile<<"b "; + }else{ + maskfile<<"### "; + } + for (int j=1;j<=40;j++){ + if(i==0)sprintf(line, "%2d ",j); + else if(i==1)sprintf(line, "%2d ",j+40); + else { + int val = int(tdac->GetBinContent((i%2)*40+j, (i-2)/2+1)+0.1); + sprintf(line, "%2d ",val); + } + maskfile<<line; + if(j%10==0)maskfile<<" "; + } + maskfile<<std::endl; + } +} + + +void Fei4CfgFileWriter::writeMaskFile(const char* filename, TH2* histo){ + std::ofstream maskfile(Form("%s.dat",filename)); + maskfile<<"### 1 6 11 16 21 26 31 36 41 46 51 56 61 66 71 76"<<std::endl; + char linenr[128]; + for(int i=1;i<=336;i++){ + sprintf(linenr,"%3d ", i); + maskfile<<linenr; + for (int j=1;j<=80;j++){ + if(histo->GetBinContent(j,i)==1)maskfile<<0; + else maskfile<<1; + if(j%10==0)maskfile<<" "; + else if(j%5==0)maskfile<<"-"; + } + maskfile<<std::endl; + } +} diff --git a/rce/rcecalib/analysis/Fei4CfgFileWriter.hh b/rce/rcecalib/analysis/Fei4CfgFileWriter.hh new file mode 100644 index 00000000..972ba9a6 --- /dev/null +++ b/rce/rcecalib/analysis/Fei4CfgFileWriter.hh @@ -0,0 +1,14 @@ +#ifndef FEI4CFGFILEWRITER_HH +#define FEI4CFGFILEWRITER_HH + +#include "rcecalib/analysis/CfgFileWriter.hh" + +class Fei4CfgFileWriter: public CfgFileWriter{ +public: + Fei4CfgFileWriter(){} + ~Fei4CfgFileWriter(){} + void writeDacFile(const char* filename, TH2* his); + void writeMaskFile(const char* filename, TH2* his); +}; + +#endif diff --git a/rce/rcecalib/analysis/GdacAnalysis.cc b/rce/rcecalib/analysis/GdacAnalysis.cc new file mode 100644 index 00000000..4c3a94dd --- /dev/null +++ b/rce/rcecalib/analysis/GdacAnalysis.cc @@ -0,0 +1,199 @@ +#include "rcecalib/analysis/GdacAnalysis.hh" +#include "rcecalib/server/PixScan.hh" +#include "rcecalib/server/ConfigGui.hh" +#include "rcecalib/config/FEI3/Module.hh" +#include "rcecalib/config/FEI4/Module.hh" + +#include <TFile.h> +#include <TH2.h> +#include <TH2D.h> +#include <TH1.h> +#include <TKey.h> +#include <boost/regex.hpp> +#include <iostream> +#include <fstream> +#include "TH1D.h" +#include "TF1.h" +#include "TStyle.h" + +void GdacAnalysis::analyze(TFile* file, TFile *anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]){ + gStyle->SetOptFit(111); + std::map<int, std::vector<TH1D*> > histmap; + file->cd("loop2_0"); + TIter nextkey(gDirectory->GetListOfKeys()); // GDAC settings + TKey *key; + int index=0; + while ((key=(TKey*)nextkey())) { + gDirectory->cd(key->GetName()); + + + TIter snextkey(gDirectory->GetListOfKeys()); // histograms + TKey *skey; + while ((skey=(TKey*)snextkey())) { + std::string name(skey->GetName()); + boost::cmatch matches; + boost::regex re("_(\\d+)_Mean"); + boost::regex re2("Mean"); + + if(boost::regex_search(name.c_str(), matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + int id=strtol(match.c_str(),0,10); + std::string chi2HistoName = boost::regex_replace (name, re2, "ChiSquare"); + TH2* histo = (TH2*)skey->ReadObj(); + TH1* chi2Histo=(TH1*)gDirectory->Get(chi2HistoName.c_str()); + assert(chi2Histo!=0); + TH1* gdacValHisto=(TH1*)gDirectory->Get(Form("GDAC_settings_Mod_%d_it_%d", id, index)); + int numfrontend=0; + if(findFEType(cfg, id)=="FEI3") numfrontend = FEI3::Module::N_FRONTENDS; + else numfrontend = FEI4::Module::N_FRONTENDS; + + char name[128]; + char title[128]; + int gdac=0; + if(histmap.find(id)==histmap.end()){ + for (int k=0;k<numfrontend;k++){ + if(numfrontend==1){ + sprintf(name, "GDAC_mod_%d", id); + sprintf(title, "GDAC vs charge module %d at %s", id, findFieldName(cfg, id)); + }else{ + sprintf(name, "GDAC_mod_%d_frontent_%i", id, k); + sprintf(title, "GDAC vs charge module %d frontend %i at %s", id, k, findFieldName(cfg, id)); + } + TH1D *hold =new TH1D (name, title, 256, -.5, 255.5); + histmap[id].push_back(hold); + } + } + for (int k=0;k<numfrontend;k++){ + + if(gdacValHisto!=0)gdac=gdacValHisto->GetBinContent(k+1); + else gdac=int(scan->getLoopVarValues(1)[index]); + + if(numfrontend==1){ + sprintf(name, "threshold_id_%d_step_%d_gdac_%d", id, index, gdac); + sprintf(title, "Threshold id=%d at %s step=%d gdac=%d", id, findFieldName(cfg, id), index, gdac); + }else{ + sprintf(name, "threshold_id_%d_frontend_%d_step_%d_gdac_%d", id, k, index, gdac); + sprintf(title, "Threshold id=%d at %s frontend=%d step=%d gdac=%d", id, findFieldName(cfg, id), k, index, gdac); + } + TH1D *fithist = new TH1D(name, title, 100, 0, 10000); + + int histnum = histo->GetNbinsX()/numfrontend; + for (int i=histnum*k+1;i<=histnum*(k+1);i++){ + for(int j=1;j<=histo->GetNbinsY();j++){ + if(chi2Histo->GetBinContent(i,j)!=0&&chi2Histo->GetBinContent(i,j)<5){ + fithist->Fill(histo->GetBinContent(i,j)); + } + } + } + fithist->Fit("gaus","lq"); + double val=fithist->GetFunction("gaus")->GetParameter(1); + double err=fithist->GetFunction("gaus")->GetParError(1); + if(val>100 && val<30000 && err>0 && err<5000 && fithist->GetEntries()>100){ //arbitrary criteria + histmap[id][k]->SetBinContent(gdac+1, val); + histmap[id][k]->SetBinError(gdac+1, err); + } + anfile->cd(); + fithist->Write(); + fithist->SetDirectory(gDirectory); + file->cd("loop2_0"); + gDirectory->cd(key->GetName()); + } + } + } + file->cd("loop2_0"); + index++; + } + anfile->cd(); + for(std::map<int, std::vector<TH1D*> >::iterator it=histmap.begin();it!=histmap.end();it++){ + int id=it->first; + ipc::PixelFEI4AConfig* confa=findFEI4AConfig(cfg, id); + ipc::PixelFEI4BConfig* confb=findFEI4BConfig(cfg, id); + ipc::PixelModuleConfig* conf3=findFEI3Config(cfg, id); + int numfrontend=0; + if(findFEType(cfg, id)=="FEI3") numfrontend = FEI3::Module::N_FRONTENDS; + else numfrontend = FEI4::Module::N_FRONTENDS; + for (int k=0;k<numfrontend;k++){ + unsigned short confval=interpolate(id, scan->getThresholdTargetValue(), histmap[id][k]); + if(confa)confa->FEGlobal.Vthin_AltFine=confval; + if(confb)confb->FEGlobal.Vthin_AltFine=confval; + if(conf3)conf3->FEConfig[k].FEGlobal.gdac=confval; + histmap[id][k]->Write(); + histmap[id][k]->SetDirectory(gDirectory); + } + if(scan->getScanType()==RCE::PixScan::GDAC_TUNE){ + std::vector<float> varValues=scan->getLoopVarValues(2); + if(varValues.size()>=1){ + int val=(int)varValues[0]; + int ncol, nrow, nchip; + if(conf3){ + ncol=18; + nrow=160; + nchip=16; + }else{ + ncol=80; + nrow=336; + nchip=1; + } + for (int chip=0;chip<nchip;chip++){ + for (int col=0;col<ncol;col++){ + for (int row=0;row<nrow;row++){ + if(confa)confa->FETrims.dacThresholdTrim[col][row]=val; + else if(confb)confb->FETrims.dacThresholdTrim[col][row]=val; + else conf3->FEConfig[chip].FETrims.dacThresholdTrim[row][col]=val; + } + } + } + + }else{ + std::cout<<"No outer loop for GDAC tuning. Not setting up TDAC values"<<std::endl; + } + } + if(confa || confb) writeFEI4Config(anfile, runno); + if (conf3) writeFEI3Config(anfile,runno); + } + + if(configUpdate()){ + writeTopFile(cfg, anfile, runno); + } +} + +unsigned short GdacAnalysis::interpolate(int id, int target, TH1D* histo){ + double lower=-1,higher=-1; + int lowerbin=0, higherbin=0; + int firstbin=-1, lastbin=-1; + for(int i=1;i<=histo->GetNbinsX();i++){ + if(histo->GetBinContent(i)!=0){ + if(firstbin==-1)firstbin=i-1; + lastbin=i-1; + if(target>=histo->GetBinContent(i)){ + lower=histo->GetBinContent(i); + lowerbin=i-1; + }else{ + higher=histo->GetBinContent(i); + higherbin=i-1; + break; + } + } + } + unsigned short confval=0; + if(lower==-1){ + std::cout<<"Target is lower than lowest scan point "<<firstbin<<" for module id="<<id<<std::endl; + confval=firstbin; + }else if (higher==-1){ + std::cout<<"Target is larger than highest scan point "<<lastbin<<" for module id="<<id<<std::endl; + confval=lastbin; + }else{ + double m=(higher-lower)/(higherbin-lowerbin); + if(m==0){ + std::cout<<"Slope is 0, no interpolation possible for module id="<<id<<std::endl; + confval=lowerbin; + }else{ + double n=higher-m*higherbin; + double x=(target-n)/m; + std::cout<<"vthin_altFine for module id="<<id<<" at a target threshold of "<<target<<" electrons is "<<x<<std::endl; + confval=x; + } + } + return confval; +} diff --git a/rce/rcecalib/analysis/GdacAnalysis.hh b/rce/rcecalib/analysis/GdacAnalysis.hh new file mode 100644 index 00000000..3802146a --- /dev/null +++ b/rce/rcecalib/analysis/GdacAnalysis.hh @@ -0,0 +1,33 @@ +#ifndef GDACANALYSIS_HH +#define GDACANALYSIS_HH + +#include "rcecalib/analysis/CalibAnalysis.hh" +#include <map> +#include <vector> + +class ConfigGui; +class TFile; +class TH2D; +class TH1D; + +namespace RCE{ + class PixScan; +} +namespace{ + struct fitval{ + double val; + double err; + }; +} + +class GdacAnalysis: public CalibAnalysis{ +public: + GdacAnalysis(): CalibAnalysis(){} + ~GdacAnalysis(){} + void analyze(TFile* file, TFile* anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]); + void findThreshold(TFile *anfile, int gdac, std::map<int, std::vector<fitval> > & ret, ConfigGui* cfg[]); + unsigned short interpolate(int id, int target, TH1D* histo); +}; + + +#endif diff --git a/rce/rcecalib/analysis/GdacCoarseFastAnalysis.cc b/rce/rcecalib/analysis/GdacCoarseFastAnalysis.cc new file mode 100644 index 00000000..60d7b60a --- /dev/null +++ b/rce/rcecalib/analysis/GdacCoarseFastAnalysis.cc @@ -0,0 +1,127 @@ +#include "rcecalib/analysis/GdacCoarseFastAnalysis.hh" +#include "rcecalib/server/PixScan.hh" +#include "rcecalib/server/ConfigGui.hh" +#include "rcecalib/config/FEI3/Module.hh" +#include "rcecalib/config/FEI4/Module.hh" + +#include <TFile.h> +#include <TH2.h> +#include <TH2D.h> +#include <TH1.h> +#include <TKey.h> +#include <boost/regex.hpp> +#include <iostream> +#include <fstream> +#include "TH1D.h" +#include "TStyle.h" + +void GdacCoarseFastAnalysis::analyze(TFile* file, TFile *anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]){ + int repetitions = scan->getRepetitions(); + double targetEff = 0.5; + TKey* key; + char subdir[128]; + char name[128]; + char title[128]; + int binsx=0; + size_t numvals=scan->getLoopVarValues(1).size(); + std::map<int, hdatagdaccoarsefast> *histomap=new std::map<int, hdatagdaccoarsefast>[numvals]; + double *val=new double[numvals]; + for (size_t i=0;i<numvals;i++){ + sprintf(subdir, "/loop2_0/loop1_%d", i); + file->cd(subdir); // GDAC steps + TIter nextkey(gDirectory->GetListOfKeys()); // histos + while ((key=(TKey*)nextkey())) { + boost::cmatch matches; + boost::regex re("_(\\d+)_Occupancy_Point_000"); + if(boost::regex_search(key->GetName(), matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + int id=strtol(match.c_str(),0,10); + TH2* histo = (TH2*)key->ReadObj(); + histo->SetMinimum(0); histo->SetMaximum(repetitions); + TH1* gdachisto=(TH1*)gDirectory->Get(Form("GDACCoarse_settings_Mod_%d_it_%d", id, i)); + assert(gdachisto); + histomap[i][id].occupancy=histo; + histomap[i][id].gdac=gdachisto; + binsx=gdachisto->GetNbinsX(); + } + } + } + for(std::map<int, hdatagdaccoarsefast>::iterator it=histomap[0].begin();it!=histomap[0].end();it++){ + int id=it->first; + float pct = 100; + sprintf(name, "BestOcc_Mod_%d", id); + sprintf(title, "Best Occupancy Module %d at %s", id, findFieldName(cfg, id)); + TH1F* occBest=new TH1F(name, title, binsx, 0, binsx); + occBest->SetMinimum(0); occBest->SetMaximum(pct); + occBest->GetXaxis()->SetTitle("Chip"); + occBest->GetYaxis()->SetTitle("Occupancy[%]"); + + sprintf(name, "BestGdacCoarse_Mod_%d", id); + sprintf(title, "Best GdacCoarse Module %d at %s", id, findFieldName(cfg, id)); + TH1F* gdac=new TH1F(name, title, binsx, 0, binsx); + gdac->GetXaxis()->SetTitle("Chip"); + gdac->GetYaxis()->SetTitle("GdacCoarse"); + + ipc::PixelFEI4AConfig* confa=findFEI4AConfig(cfg, id); + ipc::PixelFEI4BConfig* confb=findFEI4BConfig(cfg, id); + + int ncol, nrow, nchip, maxval, maxstage; + if (confa) { + ncol=80; + nrow=336; + nchip=1; + maxval=256; + maxstage=120; + } + else { + ncol=80; + nrow=336; + nchip=1; + maxval=256; + maxstage=24; + } + + int nstages = scan->getMaskStageSteps(); + int npixtotal = nchip*ncol*nrow; + float npixused=float(nstages)/float(maxstage)*npixtotal; + + int nfe = binsx; + for (int i = 0; i < nfe; i++){ + int index = 0; + for (size_t k = 0; k < numvals; k++) { + int histfebins = (histomap[k][id].occupancy->GetNbinsX())/nfe; + int nbinsy = histomap[k][id].occupancy->GetNbinsY(); + float meanEff = 0.0; + for (int binx = histfebins*i+1; binx <= histfebins*(i+1); binx++) { + for (int biny = 1; biny <= nbinsy; biny++) { + meanEff += histomap[k][id].occupancy->GetBinContent(binx, biny) / repetitions; + } + } + val[k] = meanEff/npixused; + if (val[k] < targetEff) { + index = k; + break; + } + } + occBest->SetBinContent(i+1, pct*val[index]); + gdac->SetBinContent(i+1, histomap[index][id].gdac->GetBinContent(i+1)); + std::cout<<"Best GDACCoarse for module " << id << " is " << histomap[index][id].gdac->GetBinContent(i+1) << std::endl; + if(confa)confa->FEGlobal.Vthin_AltCoarse = histomap[index][id].gdac->GetBinContent(i+1); + if(confb)confb->FEGlobal.Vthin_AltCoarse = histomap[index][id].gdac->GetBinContent(i+1); + } + + anfile->cd(); + + occBest->Write(); + occBest->SetDirectory(gDirectory); + + gdac->Write(); + gdac->SetDirectory(gDirectory); + + if(confa || confb) writeFEI4Config(anfile, runno); + } + if (configUpdate()) writeTopFile(cfg, anfile, runno); + delete [] histomap; + delete [] val; +} diff --git a/rce/rcecalib/analysis/GdacCoarseFastAnalysis.hh b/rce/rcecalib/analysis/GdacCoarseFastAnalysis.hh new file mode 100644 index 00000000..ab2380de --- /dev/null +++ b/rce/rcecalib/analysis/GdacCoarseFastAnalysis.hh @@ -0,0 +1,31 @@ +#ifndef GDACCOARSEFASTANALYSIS_HH +#define GDACCOARSEFASTANALYSIS_HH + +#include "rcecalib/analysis/CalibAnalysis.hh" +#include <map> +#include <vector> + +class ConfigGui; +class TFile; +class TH2; +class TH1; + +namespace RCE{ + class PixScan; +} +namespace{ + struct hdatagdaccoarsefast{ + TH2* occupancy; + TH1* gdac; + }; +} + +class GdacCoarseFastAnalysis: public CalibAnalysis{ +public: + GdacCoarseFastAnalysis(): CalibAnalysis(){} + ~GdacCoarseFastAnalysis(){} + void analyze(TFile* file, TFile* anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]); +}; + + +#endif diff --git a/rce/rcecalib/analysis/GdacFastAnalysis.cc b/rce/rcecalib/analysis/GdacFastAnalysis.cc new file mode 100644 index 00000000..dc9e0f77 --- /dev/null +++ b/rce/rcecalib/analysis/GdacFastAnalysis.cc @@ -0,0 +1,155 @@ +#include "rcecalib/analysis/GdacFastAnalysis.hh" +#include "rcecalib/server/PixScan.hh" +#include "rcecalib/server/ConfigGui.hh" +#include "rcecalib/config/FEI3/Module.hh" +#include "rcecalib/config/FEI4/Module.hh" + +#include <TFile.h> +#include <TH2.h> +#include <TH2D.h> +#include <TH1.h> +#include <TKey.h> +#include <boost/regex.hpp> +#include <iostream> +#include <fstream> +#include "TH1D.h" +#include "TStyle.h" + +void GdacFastAnalysis::analyze(TFile* file, TFile *anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]){ + int repetitions = scan->getRepetitions(); + double targetEff = 0.5; + TKey* key; + char subdir[128]; + char name[128]; + char title[128]; + int binsx=0; + size_t numvals=scan->getLoopVarValues(1).size(); + std::map<int, hdatagdacfast> *histomap=new std::map<int, hdatagdacfast>[numvals]; + double *val=new double[numvals]; + for (size_t i=0;i<numvals;i++){ + sprintf(subdir, "/loop2_0/loop1_%d", i); + file->cd(subdir); // GDAC steps + TIter nextkey(gDirectory->GetListOfKeys()); // histos + while ((key=(TKey*)nextkey())) { + boost::cmatch matches; + boost::regex re("_(\\d+)_Occupancy_Point_000"); + if(boost::regex_search(key->GetName(), matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + int id=strtol(match.c_str(),0,10); + TH2* histo = (TH2*)key->ReadObj(); + histo->SetMinimum(0); histo->SetMaximum(repetitions); + TH1* gdachisto=(TH1*)gDirectory->Get(Form("GDAC_settings_Mod_%d_it_%d", id, i)); + assert(gdachisto); + histomap[i][id].occupancy=histo; + histomap[i][id].gdac=gdachisto; + binsx=gdachisto->GetNbinsX(); + } + } + } + for(std::map<int, hdatagdacfast>::iterator it=histomap[0].begin();it!=histomap[0].end();it++){ + int id=it->first; + float pct = 100; + sprintf(name, "BestOcc_Mod_%d", id); + sprintf(title, "Best Occupancy Module %d at %s", id, findFieldName(cfg, id)); + TH1F* occBest=new TH1F(name, title, binsx, 0, binsx); + occBest->SetMinimum(0); occBest->SetMaximum(pct); + occBest->GetXaxis()->SetTitle("Chip"); + occBest->GetYaxis()->SetTitle("Occupancy[%]"); + + sprintf(name, "BestGdac_Mod_%d", id); + sprintf(title, "Best Gdacs Module %d at %s", id, findFieldName(cfg, id)); + TH1F* gdac=new TH1F(name, title, binsx, 0, binsx); + gdac->GetXaxis()->SetTitle("Chip"); + gdac->GetYaxis()->SetTitle("Gdac"); + + ipc::PixelFEI4AConfig* confa=findFEI4AConfig(cfg, id); + ipc::PixelFEI4BConfig* confb=findFEI4BConfig(cfg, id); + ipc::PixelModuleConfig* conf3=findFEI3Config(cfg, id); + + int ncol, nrow, nchip, maxval, maxstage; + if (confa) { + ncol=80; + nrow=336; + nchip=1; + maxval=256; + maxstage=120; + } + else if (confb) { + ncol=80; + nrow=336; + nchip=1; + maxval=256; + maxstage=24; + } + else { + ncol=18; + nrow=160; + nchip=16; + maxval=32; + maxstage=32; + } + int nstages = scan->getMaskStageSteps(); + int npixtotal = nchip*ncol*nrow; + float npixused=float(nstages)/float(maxstage)*npixtotal; + + int nfe = binsx; + for (int i = 0; i < nfe; i++){ + double bestval = 10*targetEff; // must be larger than 1 (with possibilty of double hit) + int index = 0; + for (size_t k = 0; k < numvals; k++) { + int histfebins = (histomap[k][id].occupancy->GetNbinsX())/nfe; + int nbinsy = histomap[k][id].occupancy->GetNbinsY(); + float meanEff = 0.0; + for (int binx = histfebins*i+1; binx <= histfebins*(i+1); binx++) { + for (int biny = 1; biny <= nbinsy; biny++) { + meanEff += histomap[k][id].occupancy->GetBinContent(binx, biny) / repetitions; + } + } + val[k] = meanEff/npixused; + if (fabs(val[k]-targetEff) < bestval) { + index = k; + bestval = fabs(val[k]-targetEff); + } + } + occBest->SetBinContent(i+1, pct*val[index]); + gdac->SetBinContent(i+1, histomap[index][id].gdac->GetBinContent(i+1)); + std::cout<<"Best GDAC for module " << id << " is " << histomap[index][id].gdac->GetBinContent(i+1) << std::endl; + if(confa)confa->FEGlobal.Vthin_AltFine = histomap[index][id].gdac->GetBinContent(i+1); + if(confb)confb->FEGlobal.Vthin_AltFine = histomap[index][id].gdac->GetBinContent(i+1); + if(conf3)conf3->FEConfig[i].FEGlobal.gdac = histomap[index][id].gdac->GetBinContent(i+1); + } + + anfile->cd(); + + occBest->Write(); + occBest->SetDirectory(gDirectory); + + gdac->Write(); + gdac->SetDirectory(gDirectory); + + if(scan->getScanType()==RCE::PixScan::GDAC_FAST_TUNE){ + std::vector<float> varValues=scan->getLoopVarValues(2); + if(varValues.size()>=1){ + int val=(int)varValues[0]; + for (int chip=0;chip<nchip;chip++){ + for (int col=0;col<ncol;col++){ + for (int row=0;row<nrow;row++){ + if(confa)confa->FETrims.dacThresholdTrim[col][row]=val; + else if(confb)confb->FETrims.dacThresholdTrim[col][row]=val; + else conf3->FEConfig[chip].FETrims.dacThresholdTrim[row][col]=val; + } + } + } + + }else{ + std::cout<<"No outer loop for GDAC tuning. Not setting up TDAC values"<<std::endl; + } + } + if(confa || confb) writeFEI4Config(anfile, runno); + if (conf3) writeFEI3Config(anfile,runno); + } + if (configUpdate()) writeTopFile(cfg, anfile, runno); + delete [] histomap; + delete [] val; +} diff --git a/rce/rcecalib/analysis/GdacFastAnalysis.hh b/rce/rcecalib/analysis/GdacFastAnalysis.hh new file mode 100644 index 00000000..da831bf2 --- /dev/null +++ b/rce/rcecalib/analysis/GdacFastAnalysis.hh @@ -0,0 +1,31 @@ +#ifndef GDACFASTANALYSIS_HH +#define GDACFASTANALYSIS_HH + +#include "rcecalib/analysis/CalibAnalysis.hh" +#include <map> +#include <vector> + +class ConfigGui; +class TFile; +class TH2; +class TH1; + +namespace RCE{ + class PixScan; +} +namespace{ + struct hdatagdacfast{ + TH2* occupancy; + TH1* gdac; + }; +} + +class GdacFastAnalysis: public CalibAnalysis{ +public: + GdacFastAnalysis(): CalibAnalysis(){} + ~GdacFastAnalysis(){} + void analyze(TFile* file, TFile* anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]); +}; + + +#endif diff --git a/rce/rcecalib/analysis/HistoViewerGui.cc b/rce/rcecalib/analysis/HistoViewerGui.cc new file mode 100644 index 00000000..d3aa73cd --- /dev/null +++ b/rce/rcecalib/analysis/HistoViewerGui.cc @@ -0,0 +1,194 @@ +#include "rcecalib/analysis/HistoViewerGui.hh" +#include "rcecalib/server/PixScan.hh" +#include "TApplication.h" +#include "TGMsgBox.h" +#include "TH1.h" +#include "TKey.h" +#include "TGIcon.h" +#include "TGMenu.h" +#include "TCanvas.h" +#include "TGCanvas.h" +#include "TGListTree.h" +#include "TRootEmbeddedCanvas.h" +#include <TGFileDialog.h> +#include <TROOT.h> +#include <TStyle.h> +#include <boost/regex.hpp> +#include <assert.h> +#include <iostream> +#include <time.h> +#include <sys/stat.h> +#include <fstream> +#include <list> +#include <pthread.h> +#include <vector> +#include <stdlib.h> + +using namespace RCE; + +HistoViewerGui::~HistoViewerGui(){ + Cleanup(); +} + +HistoViewerGui::HistoViewerGui(const char* filename, const TGWindow *p,UInt_t w,UInt_t h) + : TGMainFrame(p,w,h) { + + // connect x icon on window manager + Connect("CloseWindow()","HistoViewerGui",this,"quit()"); + + TGMenuBar *menubar=new TGMenuBar(this,1,1,kHorizontalFrame | kRaisedFrame); + TGLayoutHints *menubarlayout=new TGLayoutHints(kLHintsTop|kLHintsLeft,0,4,0,0); + // menu "File" + TGPopupMenu* filepopup=new TGPopupMenu(gClient->GetRoot()); + //filepopup->AddEntry("&Load Config",LOAD); + //filepopup->AddEntry("&Save Config",SAVE); + filepopup->AddSeparator(); + filepopup->AddEntry("&Quit",QUIT); + menubar->AddPopup("&File",filepopup,menubarlayout); + TGPopupMenu* plotpopup=new TGPopupMenu(gClient->GetRoot()); + plotpopup->AddEntry("&Save as png",PNG); + plotpopup->AddEntry("&Savefd as pdf",PDF); + menubar->AddPopup("&Plot",plotpopup,menubarlayout); + plotpopup->Connect("Activated(Int_t)","HistoViewerGui",this,"handlePlotMenu(Int_t)"); + + AddFrame(menubar, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 0,0,0,2)); + + filepopup->Connect("Activated(Int_t)","HistoViewerGui",this,"handleFileMenu(Int_t)"); + + TGVerticalFrame* datapanel=new TGVerticalFrame(this,1,1, kSunkenFrame); + // scan panel + TGHorizontalFrame *datapanel5 = new TGHorizontalFrame(datapanel, 2, 2, kSunkenFrame); + datapanel->AddFrame(datapanel5,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY)); + AddFrame(datapanel,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY)); + + TGVerticalFrame *treepanel = new TGVerticalFrame(datapanel5, 150, 2, kSunkenFrame); + datapanel5->AddFrame(treepanel,new TGLayoutHints(kLHintsExpandY)); + TGVerticalFrame *plotpanel = new TGVerticalFrame(datapanel5, 2, 2, kSunkenFrame); + datapanel5->AddFrame(plotpanel,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY)); + + m_tgc=new TGCanvas(treepanel, 300,100); + //TGViewPort* vp=tgc->GetViewPort(); + m_tree=new TGListTree(m_tgc, kHorizontalFrame); + m_tree->Connect("Clicked(TGListTreeItem*, Int_t)","HistoViewerGui", this, "displayHisto(TGListTreeItem*, Int_t)"); + //tree->AddItem(0,"/"); + treepanel->AddFrame(m_tgc,new TGLayoutHints(kLHintsExpandY)); + m_canvas=new TRootEmbeddedCanvas("Canvas",plotpanel,100,100); + m_canvas->GetCanvas()->GetPad(0)->SetRightMargin(0.15); + plotpanel->AddFrame(m_canvas,new TGLayoutHints(kLHintsExpandY|kLHintsExpandX)); + + SetWindowName("HistoViewer GUI"); + Resize(w,h); + Layout(); + MapSubwindows(); + MapWindow(); + m_file=new TFile(filename,""); + TGListTreeItem* root=m_tree->AddItem(0,"Histos"); + m_file->cd(); + fillHistoTree(root); + updateTree(); +} + +void HistoViewerGui::quit(){ + m_file->Close(); + gApplication->Terminate(0); +} + +void HistoViewerGui::handlePlotMenu(int item){ + if(item==PNG){ + m_canvas->GetCanvas()->SaveAs("c1.png"); + }else if(item==PDF){ + m_canvas->GetCanvas()->SaveAs("c1.pdf"); + } +} + +void HistoViewerGui::handleFileMenu(int item){ + if(item==QUIT)quit(); +} +void HistoViewerGui::clearTree(){ + TGListTreeItem* root=m_tree->FindChildByName(0,"Histos"); + if(root) m_tree->DeleteChildren(root); + root->SetOpen(false); + updateTree(); +} +void HistoViewerGui::updateTree(){ + int x=m_tgc->GetViewPort()->GetX(); + int y=m_tgc->GetViewPort()->GetY(); + int w=m_tgc->GetViewPort()->GetWidth(); + int h=m_tgc->GetViewPort()->GetHeight(); + m_tree->DrawRegion(x,y,w,h); +} + +void HistoViewerGui::fillHistoTree(TGListTreeItem* branch){ + const TGPicture *thp = gClient->GetPicture("h1_t.xpm"); + TIter nextkey(gDirectory->GetListOfKeys()); + TKey *key; + while ((key=(TKey*)nextkey())) { + TObject *obj = key->ReadObj(); + if(std::string(obj->ClassName())=="TDirectoryFile"){ + gDirectory->cd(key->GetName()); + TGListTreeItem* subdir=m_tree->AddItem(branch,key->GetName()); + fillHistoTree(subdir); + }else{ + std::string hisname(key->GetName()); + boost::regex re("at ([AC]\\d+-\\d+)"); + boost::cmatch matches; + if(boost::regex_search(key->GetTitle(), matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + hisname=match+":"+hisname; + } + TGListTreeItem* his=m_tree->AddItem(branch,hisname.c_str()); + his->SetPictures(thp, thp); + } + delete obj; + } + gDirectory->cd(".."); +} +void HistoViewerGui::displayHisto(TGListTreeItem* item, int b){ + TGListTreeItem *parent=item->GetParent(); + if(parent==0)return; + std::string histonames=item->GetText(); + if(histonames[4]==':')histonames=histonames.substr(5); + const char* histoname=histonames.c_str(); + if(std::string(histoname).substr(0,4)=="loop")return; + if(std::string(histoname).substr(0,8)=="Analysis")return; + TGListTreeItem *parent1=parent->GetParent(); + if(parent1==0)m_file->cd(); + else{ + TGListTreeItem *parent2=parent1->GetParent(); + if(parent2==0)m_file->cd(parent->GetText()); + else{ + char dir[128]; + sprintf(dir, "%s/%s",parent1->GetText(), parent->GetText()); + m_file->cd(dir); + } + } + m_histo=(TH1*)gDirectory->Get(histoname); + assert(m_histo!=0); + m_histo->SetMinimum(0); + if(m_histo->GetDimension()==1)m_histo->Draw(); + else { + m_histo->Draw("colz"); + } + m_canvas->GetCanvas()->Update(); +} + + +//==================================================================== +int main(int argc, char **argv){ + if(argc!=2){ + std::cout<<"Usage: histoViewer rootfile_name"<<std::endl; + exit(0); + } + gROOT->SetStyle("Plain"); + gStyle->SetOptStat(0); + gStyle->SetPalette(1); + const char *filename=argv[1]; + std::cout<<"Filename "<<filename<<std::endl; + TApplication theapp("app",&argc,argv); + new HistoViewerGui(filename, gClient->GetRoot(),800,600); + theapp.Run(); + return 0; +} + + diff --git a/rce/rcecalib/analysis/HistoViewerGui.hh b/rce/rcecalib/analysis/HistoViewerGui.hh new file mode 100644 index 00000000..82065a07 --- /dev/null +++ b/rce/rcecalib/analysis/HistoViewerGui.hh @@ -0,0 +1,45 @@ +#ifndef HISTOVIEWERGUI_HH +#define HISTOVIEWERGUI_HH + +#include "TGMdiMainFrame.h" +#include <TGLabel.h> +#include <TGTextEntry.h> +#include <TGNumberEntry.h> +#include "TFile.h" +#include "TH2F.h" +#include <string> + + +class TGListTree; +class TGListTreeItem; +class TH1; +class TRootEmbeddedCanvas; + +class HistoViewerGui: public TGMainFrame { +public: + HistoViewerGui(const char* filename, const TGWindow *p,UInt_t w,UInt_t h); + virtual ~HistoViewerGui(); + void handleFileMenu(Int_t); + void handlePlotMenu(Int_t); + void quit(); + void clearTree(); + void updateTree(); + void displayHisto(TGListTreeItem* item, int b); +private: + + void fillHistoTree(TGListTreeItem* branch); + enum Filemenu {LOAD, SAVE, QUIT}; + enum Plotmenu {PNG, PDF}; + TGTextButton* *m_quit; + TGListTree* m_tree; + TH1 *m_histo; + TRootEmbeddedCanvas *m_canvas; + TFile *m_file, *m_anfile; + std::string m_dir; + bool m_delhisto; + TGCanvas *m_tgc; + int m_indx; + +ClassDef (HistoViewerGui,0) +}; +#endif diff --git a/rce/rcecalib/analysis/Iff_Analysis.cc b/rce/rcecalib/analysis/Iff_Analysis.cc new file mode 100644 index 00000000..62cd9cc5 --- /dev/null +++ b/rce/rcecalib/analysis/Iff_Analysis.cc @@ -0,0 +1,169 @@ +#include "rcecalib/analysis/Iff_Analysis.hh" +#include "rcecalib/config/FEI4/Module.hh" +#include "rcecalib/config/FEI3/Module.hh" + +#include <TFile.h> +#include <TH2.h> +#include <TH2D.h> +#include <TH1.h> +#include <TH1F.h> +#include <TKey.h> +#include <boost/regex.hpp> +#include <iostream> +#include <fstream> +#include <math.h> + +using namespace RCE; + +void IffAnalysis::analyze(TFile* file, TFile *anfile, PixScan* scan, int runno, ConfigGui* cfg[]){ + printf("Begin IFF Analysis\n"); + float target = float(scan->getTotTargetValue()); + printf("Target Tot Value: %2.1f\n",target); + std::vector<float> loopVar=scan->getLoopVarValues(0); + size_t numvals=loopVar.size(); + //TH1F* iffhis = new TH1F("iff_v_module","Best IF Setting",128,0,127); + //iffhis->GetXaxis()->SetTitle("Module"); + //iffhis->GetYaxis()->SetTitle("IF Setting"); + std::map<int, odata> *histomap=new std::map<int, odata>[numvals]; + TKey *key; + for (size_t i=0;i<numvals;i++){ + file->cd("loop1_0"); + TIter nextkey(gDirectory->GetListOfKeys()); + while ((key=(TKey*)nextkey())) { + std::string name(key->GetName()); + boost::regex re(Form("_(\\d+)_Occupancy_Point_%03d", i)); + boost::cmatch matches; + if(boost::regex_search(name.c_str(), matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + int lnm=strtol(match.c_str(),0,10); + histomap[i][lnm].occ = (TH2*)key->ReadObj(); + boost::regex re2("Occupancy"); + std::string totHistoName = boost::regex_replace (name, re2, "ToT"); + histomap[i][lnm].tot=(TH2*)gDirectory->Get(totHistoName.c_str()); + } + } + } + // write out results in a file + std::string fn(anfile->GetName()); + std::string name="IFscan_results.dat"; + boost::regex re("[^/]*\\.root"); + std::string maskfilename = boost::regex_replace (fn, re, name); + std::ofstream maskfile(maskfilename.c_str()); + for(std::map<int, odata>::iterator it=histomap[0].begin();it!=histomap[0].end();it++){ + int id=it->first; + ipc::PixelFEI4AConfig* confa=findFEI4AConfig(cfg, id); + ipc::PixelFEI4BConfig* confb=findFEI4BConfig(cfg, id); + ipc::PixelModuleConfig* confm=findFEI3Config(cfg, id); + int nchip; + int nrow; + int ncol; + int fei; + if(findFEType(cfg, id)=="FEI3"){ + nchip=FEI3::Module::N_FRONTENDS; + nrow=FEI3::Frontend::N_ROWS; + ncol=FEI3::Frontend::N_COLS; + fei=3; + }else{ + nchip=FEI4::Module::N_FRONTENDS; + nrow=FEI4::PixelRegister::N_ROWS; + ncol=FEI4::PixelRegister::N_COLS; + fei=4; + } + for(int chip=0;chip<nchip;chip++){ + TH1F* ahis; + if(findFEType(cfg, id)=="FEI3"){ + ahis = new TH1F(Form("Mod_%i_FE_%i_ToT_v_IFF",id, chip), + Form("ToT vs. IFF Mod %d FE %d at %s", id, chip, findFieldName(cfg, id)), + 256,-.5,255.5); + }else{ + ahis = new TH1F(Form("Mod_%i_ToT_v_IFF",id), + Form("ToT vs. IFF Mod %d at %s", id, findFieldName(cfg, id)), + 256,-.5,255.5); + } + ahis->GetXaxis()->SetTitle("IF Setting"); + ahis->GetYaxis()->SetTitle("Time over Threshold"); + int value = 0; + float min = 999999.9; + std::vector<float> vals; + for(unsigned i = 0; i < numvals; i++){ + double tot = 0.0; + double tot2 = 0.0; + float numBadPixels = 0.0; + for(int j = chip*ncol+1; j <= (chip+1)*ncol; j++){ + //for(int j = 1; j <= histomap[i][id].occ->GetNbinsX(); j++){ + for(int k = 1; k <= nrow; k++){ + int nhits = int(histomap[i][id].occ->GetBinContent(j,k)); + if(nhits == scan->getRepetitions()) { + double totval=histomap[i][id].tot->GetBinContent(j,k) / nhits; + tot += totval; + tot2 += totval*totval; + } else numBadPixels++; + } + } + float norm= float(nrow*ncol - numBadPixels); + if(norm!=0){ + tot/=norm; + tot2=sqrt(tot2/norm-tot*tot); + }else{ + tot=0; + tot2=0; + } + int bin=ahis->FindBin(loopVar[i]); + ahis->SetBinContent(bin,tot); + vals.push_back(tot); + ahis->SetBinError(bin,tot2); + if(fabs(tot - target) < min){ + min = fabs(tot - target); + value = i; + } + } + // interpolate + int intval=int(loopVar[value]+.1); + //below found value + if(value!=0 && vals[value-1]!=vals[value] && loopVar[value]!=loopVar[value-1]){ + float m=(vals[value]-vals[value-1])/(loopVar[value]-loopVar[value-1]); + float n=vals[value]-m*loopVar[value]; + for (int i=int(loopVar[value-1]+1.1);i<int(loopVar[value]+0.1);i++){ + if(fabs(m*i+n-target)<min){ + min=fabs(m*i+n-target); + intval=i; + } + } + } + //above found value + if((unsigned)value!=numvals-1 && vals[value+1]!=vals[value] && loopVar[value]!=loopVar[value+1]){ + float m=(vals[value]-vals[value+1])/(loopVar[value]-loopVar[value+1]); + float n=vals[value]-m*loopVar[value]; + for (int i=int(loopVar[value]+1.1);i<int(loopVar[value+1]+0.1);i++){ + if(fabs(m*i+n-target)<min){ + min=fabs(m*i+n-target); + intval=i; + } + } + } + printf("Module ID: %d Closest Setting: %d \nDistance From Target: %4.3f\n",id, intval,min); + char line[512]; + if(fei==4) sprintf(line, "Module ID: %d Best setting: %d\n", id, intval); + else sprintf(line, "Module ID: %d Chip: %d Best setting: %d\n", id, chip, intval); + maskfile<<line; + anfile->cd(); + ahis->Write(); + ahis->SetDirectory(gDirectory); + if(confa) confa->FEGlobal.PrmpVbpf=intval; + if(confb) confb->FEGlobal.PrmpVbpf=intval; + if(confm) confm->FEConfig[chip].FEGlobal.dacIF=intval; + } + for(unsigned i = 0; i < numvals; i++){ + delete histomap[i][id].occ; + delete histomap[i][id].tot; + delete histomap[i][id].tot2; + } + if(confa || confb) writeFEI4Config(anfile, runno); + if(confm)writeFEI3Config(anfile, runno); + } + if(configUpdate())writeTopFile(cfg, anfile, runno); + printf("Done Analysis\n"); + delete [] histomap; +} + diff --git a/rce/rcecalib/analysis/Iff_Analysis.hh b/rce/rcecalib/analysis/Iff_Analysis.hh new file mode 100644 index 00000000..516be9a7 --- /dev/null +++ b/rce/rcecalib/analysis/Iff_Analysis.hh @@ -0,0 +1,26 @@ +#ifndef IFFANALYSIS2_HH +#define IFFANALYSIS2_HH + +#include "rcecalib/analysis/CalibAnalysis.hh" +#include "rcecalib/server/PixScan.hh" + +class TFile; +class TH2; +namespace RCE{ + class PixScan; +} + +class IffAnalysis: public CalibAnalysis{ +public: + struct odata{ + TH2* occ; + TH2* tot; + TH2* tot2; + }; + IffAnalysis(): CalibAnalysis(){} + ~IffAnalysis(){} + void analyze(TFile* file, TFile* anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]); +}; + + +#endif diff --git a/rce/rcecalib/analysis/Makefile b/rce/rcecalib/analysis/Makefile new file mode 100644 index 00000000..3cd076af --- /dev/null +++ b/rce/rcecalib/analysis/Makefile @@ -0,0 +1,21 @@ +# Package level makefile +# ---------------------- +%.mk:; + +# Checks +# ------ +# Check release location variables +ifeq ($(RELEASE_DIR),) +export RELEASE_DIR := $(PWD)/../.. +endif + +include $(RELEASE_DIR)/make/share/setup.mk +include ../flags.mk + +ifndef PREMAKE_DONE +include $(RELEASE_DIR)/make/share/premake.mk +else +include constituents.mk +include $(RELEASE_DIR)/make/sw/package.mk +include $(RELEASE_DIR)/make/sw/rootcint.mk +endif diff --git a/rce/rcecalib/analysis/MergeMaskFilesFei4.cc b/rce/rcecalib/analysis/MergeMaskFilesFei4.cc new file mode 100644 index 00000000..f26133f7 --- /dev/null +++ b/rce/rcecalib/analysis/MergeMaskFilesFei4.cc @@ -0,0 +1,50 @@ +#include <iostream> +#include <fstream> +#include <TH2D.h> +#include "rcecalib/analysis/Fei4CfgFileWriter.hh" +#include <boost/algorithm/string.hpp> + +const unsigned int NROWS=336; +const unsigned int NCOLS=80; + +void fillMask(TH2D& histo, const char* filename){ + std::string inpline; + unsigned short row=0; + std::ifstream maskfile(filename); + while(true){ + getline(maskfile, inpline); + if(maskfile.eof())break; + boost::trim(inpline); + if(inpline.size()!=0 && inpline[0]!='#'){ //remove comment lines and empty lines + std::vector<std::string> splitVec; + split( splitVec, inpline, boost::is_any_of(" -"), boost::token_compress_on ); + if(splitVec.size()!=17){ + std::cout<<"Bad input line "<<inpline<<std::endl; + continue; + } + int r=strtol(splitVec[0].c_str(),0,10); + assert(r==++row);//check and increment row number + std::string oneline; + for(int i=1;i<17;i++)oneline+=splitVec[i]; //concatenate everyting. + assert(oneline.size()==NCOLS); + for(unsigned int i=0;i<NCOLS;i++){ + if(oneline[i]=='0')histo.SetBinContent(i+1, row, 1); + } + } + } + assert(row==NROWS); +} + + +int main(int argc, char **argv){ + if(argc<4){ + std::cout<<"Usage: mergeMasksFei4 outfile maskfile1 maskfile2 ..."<<std::endl; + exit(0); + } + TH2D mask("mask","mask", NCOLS, 0, NCOLS, NROWS, 0, NROWS); + for(int i=2;i<argc;i++){ + fillMask(mask, argv[i]); + } + Fei4CfgFileWriter fw; + fw.writeMaskFile(argv[1], &mask); +} diff --git a/rce/rcecalib/analysis/ModuleCrosstalkAnalysis.cc b/rce/rcecalib/analysis/ModuleCrosstalkAnalysis.cc new file mode 100644 index 00000000..a7b9e085 --- /dev/null +++ b/rce/rcecalib/analysis/ModuleCrosstalkAnalysis.cc @@ -0,0 +1,70 @@ +#include "rcecalib/analysis/ModuleCrosstalkAnalysis.hh" +#include "rcecalib/server/PixScan.hh" +#include "rcecalib/server/ConfigGui.hh" + +#include <TFile.h> +#include <TH2.h> +#include <TH2D.h> +#include <TH1.h> +#include <TKey.h> +#include <boost/regex.hpp> +#include <iostream> +#include <fstream> + +using namespace RCE; + +void ModuleCrosstalkAnalysis::analyze(TFile* file, TFile *anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]){ + std::cout<<"Module crosstalk analysis"<<std::endl; + unsigned int numval=scan->getLoopVarValues(0).size(); + unsigned short trgmask=scan->getModuleTrgMask(); + file->cd(); + TIter nextkey(gDirectory->GetListOfKeys()); + + TKey *key; + boost::regex re("_(\\d+)_Mean"); + while ((key=(TKey*)nextkey())) { + std::string name(key->GetName()); + boost::cmatch matches; + if(boost::regex_search(name.c_str(), matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + int id=strtol(match.c_str(),0,10); + + int outlink = 99; + for(int i_conf=0;i_conf<ConfigGui::MAX_MODULES;i_conf++){ + if(cfg[i_conf]->isIncluded() && cfg[i_conf]->getId()==id){ + outlink = cfg[i_conf]->getOutLink(); + } + } + + if(((1<<outlink)&trgmask)==0)continue; + TH2* histo = (TH2*)key->ReadObj(); + TH2D* mhis=new TH2D(Form("Hits_Mod_%d",id), Form("All Hits Mod %d at %s", id, findFieldName(cfg, id)), + histo->GetNbinsX(), histo->GetXaxis()->GetXmin(), histo->GetXaxis()->GetXmax(), + histo->GetNbinsY(), histo->GetYaxis()->GetXmin(), histo->GetYaxis()->GetXmax()); + mhis->GetXaxis()->SetTitle("Column"); + mhis->GetYaxis()->SetTitle("Row"); + TH1D* hits1d=new TH1D(Form("HitsPerBin_Mod_%d", id), + Form("Hits per bin Mod %d at %s", id, findFieldName(cfg, id)), + numval, -.5, (float)numval-.5) ; + hits1d->GetXaxis()->SetTitle("Scan Point"); + + for(unsigned int k=0;k<numval;k++){ + boost::regex re2("Mean"); + std::string histoName = boost::regex_replace (name, re2, Form("Occupancy_Point_%03d", k)); + TH2* occHisto=(TH2*)gDirectory->Get(histoName.c_str()); + assert(occHisto); + mhis->Add(occHisto); + hits1d->SetBinContent(k+1, occHisto->GetSumOfWeights()); + } + anfile->cd(); + mhis->Write(); + mhis->SetDirectory(gDirectory); + hits1d->Write(); + hits1d->SetDirectory(gDirectory); + delete histo; + file->cd(); //change back to this directory, because will need to access its histograms later + } + } +} + diff --git a/rce/rcecalib/analysis/ModuleCrosstalkAnalysis.hh b/rce/rcecalib/analysis/ModuleCrosstalkAnalysis.hh new file mode 100644 index 00000000..2032e40b --- /dev/null +++ b/rce/rcecalib/analysis/ModuleCrosstalkAnalysis.hh @@ -0,0 +1,21 @@ +#ifndef MODULECROSSTALKANALYSIS_HH +#define MODULECROSSTALKANALYSIS_HH + +#include "rcecalib/analysis/CalibAnalysis.hh" + +class ConfigGui; +class TFile; +class TH2D; +namespace RCE{ + class PixScan; +} + +class ModuleCrosstalkAnalysis: public CalibAnalysis{ +public: + ModuleCrosstalkAnalysis(): CalibAnalysis(){} + ~ModuleCrosstalkAnalysis(){} + void analyze(TFile* file, TFile* anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]); +}; + + +#endif diff --git a/rce/rcecalib/analysis/MultiTrigAnalysis.cc b/rce/rcecalib/analysis/MultiTrigAnalysis.cc new file mode 100644 index 00000000..0570e134 --- /dev/null +++ b/rce/rcecalib/analysis/MultiTrigAnalysis.cc @@ -0,0 +1,263 @@ +#include "rcecalib/analysis/MultiTrigAnalysis.hh" +#include "rcecalib/server/PixScan.hh" + +#include <TFile.h> +#include <TH2.h> +#include <TH2D.h> +#include <TH1.h> +#include <TKey.h> +#include <boost/regex.hpp> +#include <iostream> +#include <fstream> +#include "TH1D.h" +#include "TF1.h" +#include "TStyle.h" + + +void MultiTrigAnalysis::analyze(TFile* file, TFile *anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]){ + std::cout<<"MultiTrig analysis"<<std::endl; + unsigned int numval=scan->getLoopVarValues(0).size(); + const int totalScans=scan->getLoopVarValues(1).size(); + + gStyle->SetOptFit(10); + gStyle->SetOptStat(0); + + float xVals[totalScans]; + + std::map<int, std::vector<TH1D*> > histoMeanScan; + std::map<int, std::vector<TH1D*> > histoSigmaScan; + std::map<int, std::vector<float> > meanVals; + std::map<int, std::vector<float> > sigmaVals; + + // float meanVals[totalScans][2]; + // float sigmaVals[totalScans][2]; + + + float xMin = scan->getLoopVarValues(1).at(0); + float xMax = scan->getLoopVarValues(1).at(totalScans-1); + if(xMax<xMin){ + float xtemp = xMax; + xMax = xMin; + xMin = xtemp; + } + + int nScanBins = (xMax - xMin + 3); + + + //loop over the different values of multitrig_interval + for(int iScan = 0; iScan<totalScans; iScan++){ + file->cd(Form("loop1_%d",iScan)); + + std::map<int, TH1D*> histmap; + boost::regex re0("_(\\d+)_Trig0_Mean"); + boost::regex re1("_(\\d+)_Trig1_Mean"); + boost::regex re2("Mean"); + + int trigId=-1; + TIter nextkey(gDirectory->GetListOfKeys()); // histograms + TKey *key; + + while ((key=(TKey*)nextkey())) { + std::string hname(key->GetName()); + boost::cmatch matches; + + char name[128]; + char title[128]; + + bool foundMatch=false; + if(boost::regex_search(hname.c_str(), matches, re0)){ + trigId=0; + foundMatch=true; + } + else if(boost::regex_search(hname.c_str(), matches, re1)){ + trigId=1; + foundMatch=true; + } + + if(foundMatch){ + + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + // std::cout<<"Match = "<<match.c_str()<<std::endl; + // std::cout<<"name = "<<hname.c_str()<<std::endl; + + int id=strtol(match.c_str(),0,10); + std::string chi2HistoName = boost::regex_replace (hname, re2, "ChiSquare"); + std::string sigmaHistoName = boost::regex_replace (hname, re2, "Sigma"); + TH2* histo = (TH2*)key->ReadObj(); + //std::cout<<"Looking for "<<chi2HistoName.c_str()<<std::endl; + + TH2* chi2Histo=(TH2*)gDirectory->Get(chi2HistoName.c_str()); + TH2* sigmahisto=(TH2*)gDirectory->Get(sigmaHistoName.c_str()); + assert(chi2Histo!=0); + assert(sigmahisto!=0); + int binsx=histo->GetNbinsX(); + int binsy=histo->GetNbinsY(); + sprintf(name, "thresh2d_%d_Mod_%d_Trig%d", iScan,id,trigId); + sprintf(title, "Thresholds Module %d at %s Trig %d, Scan %d", id, findFieldName(cfg,id), trigId, iScan); + TH2F* thresh2d=new TH2F(name, title, binsx, 0, binsx, binsy, 0, binsy); + thresh2d->GetXaxis()->SetTitle("Column"); + thresh2d->GetYaxis()->SetTitle("Row"); + sprintf(name, "thresh1d_%d_Mod_%d_Trig%d", iScan, id, trigId); + sprintf(title, "Thresholds 2D Module %d at %s Trig %d, Scan %d", id, findFieldName(cfg,id), trigId, iScan); + int nbins=binsx*binsy; + TH1F* thresh1d=new TH1F(name, title, nbins, 0, (float)nbins); + thresh1d->GetXaxis()->SetTitle("Channel"); + thresh1d->SetOption("p9"); + sprintf(name, "sigma1d_%d_Mod_%d_Trig%d", iScan, id, trigId); + sprintf(title, "Sigma Module %d at %s Trig %d, Scan %d", id, findFieldName(cfg,id), trigId, iScan); + TH1F* sigma1d=new TH1F(name, title, nbins, 0, (float)nbins); + sigma1d->GetXaxis()->SetTitle("Channel"); + sigma1d->SetOption("p9"); + sprintf(name, "threshdist_%d_Mod_%d_Trig%d", iScan, id, trigId); + sprintf(title, "Threshold distribution Module %d at %s Trig %d, Scan %d", id, findFieldName(cfg,id), trigId, iScan); + TH1F* threshdist=new TH1F(name, title, 500, 1000, 6000); + threshdist->GetXaxis()->SetTitle("Threshold"); + sprintf(name, "sigmadist_%d_Mod_%d_Trig%d", iScan, id, trigId); + sprintf(title, "Sigma distribution Module %d at %s Trig %d, Scan %d", id, findFieldName(cfg,id), trigId, iScan); + TH1F* sigmadist=new TH1F(name, title, 100, 0, 500); + sigmadist->GetXaxis()->SetTitle("Sigma"); + sprintf(name, "BadPixels_%d_Mod_%d_Trig%d", iScan, id, trigId); + sprintf(title, "Bad Pixels Module %d at %s Trig %d, Scan %d", id, findFieldName(cfg,id), trigId, iScan); + TH2F* bad=new TH2F(name, title, binsx, 0, binsx, binsy, 0, binsy); + bad->GetXaxis()->SetTitle("Column"); + bad->GetYaxis()->SetTitle("Row"); + TH1D* hits1d=new TH1D(Form("HitsPerBin_%d_Mod_%d_Trig%d", iScan, id, trigId), Form("Hits per bin Mod %d at %s Trig %d, Scan %d", id, findFieldName(cfg,id), trigId, iScan), numval, -.5, (float)numval-.5) ; + hits1d->GetXaxis()->SetTitle("Scan Point"); + + for (int i=1;i<=histo->GetNbinsX();i++){ + for(int j=1;j<=histo->GetNbinsY();j++){ + thresh2d->SetBinContent(i,j,histo->GetBinContent(i,j)); + thresh1d->SetBinContent((i-1)*histo->GetNbinsY()+j, histo->GetBinContent(i,j)); + threshdist->Fill(histo->GetBinContent(i,j)); + sigma1d->SetBinContent((i-1)*histo->GetNbinsY()+j, sigmahisto->GetBinContent(i,j)); + sigmadist->Fill(sigmahisto->GetBinContent(i,j)); + if(chi2Histo->GetBinContent(i,j)==0)bad->SetBinContent(i,j,1); + } + } + TF1 gauss("gauss", "gaus", 100, 10000); + gauss.SetParameter(0, threshdist->GetMaximum()); + gauss.SetParameter(1, threshdist->GetMaximumBin()*threshdist->GetBinWidth(1)); + threshdist->Fit(&gauss,"q", "", 100, 10000); + sigmadist->Fit("gaus","q"); + + for(unsigned int k=0;k<numval;k++){ + boost::regex re2("Mean"); + std::string histoName = boost::regex_replace (hname, re2, Form("Occupancy_Point_%03d", k)); + TH2* occHisto=(TH2*)gDirectory->Get(histoName.c_str()); + if(occHisto==0){ + std::cout<<"Looking for "<<histoName.c_str()<<std::endl; + std::cout<<"No Occupancy histograms found. Won't fill 1-d hit histo."<<std::endl; + break; + } + hits1d->SetBinContent(k+1, occHisto->GetSumOfWeights()); + } + + xVals[iScan] = scan->getLoopVarValues(1).at(iScan); + + + if(histoMeanScan.find(id)==histoMeanScan.end()){ + + std::vector<TH1D*> temphistMean(2); + std::vector<TH1D*> temphistSigma(2); + + for(int iTrig=0; iTrig<2; iTrig++){ + temphistMean[iTrig] = new TH1D(Form("MeanScan_Mod%d_Trig%d",id,iTrig),Form("Threshold Mean versus Interval for Module %d, Trigger %d",id,iTrig+1), nScanBins,xMin-1,xMax+1); + temphistMean[iTrig]->GetXaxis()->SetTitle("Interval between 1st and 2nd inject"); + temphistMean[iTrig]->GetYaxis()->SetTitle("Threshold Mean, Ne^{-}"); + temphistMean[iTrig]->SetOption("P"); + temphistMean[iTrig]->SetMarkerStyle(2); + temphistMean[iTrig]->SetMarkerSize(2); + + temphistSigma[iTrig] = new TH1D(Form("SigmaScan_Mod%d_Trig%d",id,iTrig),Form("Threshold Sigma versus Interval for Module %d, Trigger %d",id,iTrig+1), nScanBins,xMin-1,xMax+1); + temphistSigma[iTrig]->GetXaxis()->SetTitle("Interval between 1st and 2nd inject"); + temphistSigma[iTrig]->GetYaxis()->SetTitle("Threshold Sigma, Ne^{-}"); + temphistSigma[iTrig]->SetOption("P"); + temphistSigma[iTrig]->SetMarkerStyle(2); + temphistSigma[iTrig]->SetMarkerSize(2); + + } + + histoMeanScan[id] = temphistMean; + histoSigmaScan[id] = temphistSigma; + std::vector<float> tempMeans(2*totalScans,0); + std::vector<float> tempSigmas(2*totalScans,0); + meanVals[id] = tempMeans; + sigmaVals[id] = tempSigmas; + + }//end if id not in histoSigmaScan map + + + TF1* meanGauss = threshdist->GetFunction("gauss"); + TF1* sigmaGauss = sigmadist->GetFunction("gaus"); + + int myIndex = 2*iScan + trigId; + if(meanGauss){ + meanVals[id].at(myIndex) = meanGauss->GetParameter(1); + } + else{ + meanVals[id].at(myIndex) = -1; + } + if(sigmaGauss){ + sigmaVals[id].at(myIndex) = sigmaGauss->GetParameter(1); + } + else{ + sigmaVals[id].at(myIndex) = -1; + } + + std::cout<<"Trigger "<<trigId+1<<" , interval "<<xVals[iScan]<<" : threshold mean = " + <<meanVals[id].at(myIndex)<<" ; sigma = "<<sigmaVals[id].at(myIndex)<<std::endl; + + + anfile->cd(); + thresh2d->Write(); + thresh2d->SetDirectory(gDirectory); + //thresh1d->Write(); + //thresh1d->SetDirectory(gDirectory); + threshdist->Write(); + threshdist->SetDirectory(gDirectory); + //sigma1d->Write(); + //sigma1d->SetDirectory(gDirectory); + sigmadist->Write(); + sigmadist->SetDirectory(gDirectory); + //bad->Write(); + //bad->SetDirectory(gDirectory); + hits1d->Write(); + hits1d->SetDirectory(gDirectory); + + file->cd(Form("loop1_%d",iScan)); + + }//if foundmatch + + }//end loop over keys + + } //end loop over iScan + + for(std::map<int, std::vector<TH1D*> >::iterator it=histoMeanScan.begin();it!=histoMeanScan.end();it++){ + int id=it->first; + + for(int iScan = 0; iScan<totalScans; iScan++){ + + int myIndex = 2*iScan; + histoMeanScan[id].at(0)->Fill(xVals[iScan], meanVals[id].at(myIndex+0) ); + histoSigmaScan[id].at(0)->Fill(xVals[iScan], sigmaVals[id].at(myIndex+0) ); + histoMeanScan[id].at(1)->Fill(xVals[iScan], meanVals[id].at(myIndex+1) ); + histoSigmaScan[id].at(1)->Fill(xVals[iScan], sigmaVals[id].at(myIndex+1) ); + + } + + anfile->cd(); + + for(int iTrig=0; iTrig<2; iTrig++){ + histoMeanScan[id].at(iTrig)->Write(); + histoMeanScan[id].at(iTrig)->SetDirectory(gDirectory); + histoSigmaScan[id].at(iTrig)->Write(); + histoSigmaScan[id].at(iTrig)->SetDirectory(gDirectory); + } + + } //end iterate over histoMeanScan + +} + + + diff --git a/rce/rcecalib/analysis/MultiTrigAnalysis.hh b/rce/rcecalib/analysis/MultiTrigAnalysis.hh new file mode 100644 index 00000000..7cd76ec8 --- /dev/null +++ b/rce/rcecalib/analysis/MultiTrigAnalysis.hh @@ -0,0 +1,24 @@ +#ifndef MULTITRIGANALYSIS_HH +#define MULTITRIGANALYSIS_HH + +#include "rcecalib/analysis/CalibAnalysis.hh" +#include <map> + +class ConfigGui; +class TFile; +class TH2; +class TH1D; + +namespace RCE{ + class PixScan; +} + +class MultiTrigAnalysis: public CalibAnalysis{ +public: + MultiTrigAnalysis(): CalibAnalysis(){} + ~MultiTrigAnalysis(){} + void analyze(TFile* file, TFile* anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]); +}; + + +#endif diff --git a/rce/rcecalib/analysis/MultiTrigNoiseAnalysis.cc b/rce/rcecalib/analysis/MultiTrigNoiseAnalysis.cc new file mode 100644 index 00000000..822d8d2b --- /dev/null +++ b/rce/rcecalib/analysis/MultiTrigNoiseAnalysis.cc @@ -0,0 +1,144 @@ +#include "rcecalib/analysis/MultiTrigNoiseAnalysis.hh" +#include "rcecalib/server/PixScan.hh" + +#include <TFile.h> +#include <TH2.h> +#include <TH2D.h> +#include <TH1.h> +#include <TKey.h> +#include <boost/regex.hpp> +#include <iostream> +#include <fstream> +#include "TH1D.h" +#include "TF1.h" +#include "TStyle.h" + + +void MultiTrigNoiseAnalysis::analyze(TFile* file, TFile *anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]){ + std::cout<<"MultiTrigNoise analysis"<<std::endl; + + const int totalScans=scan->getLoopVarValues(1).size(); + + gStyle->SetOptFit(10); + gStyle->SetOptStat(0); + + float xVals[totalScans]; + + std::map<int, std::vector<TH1D*> > histoNumhitsScan; + std::map<int, std::vector<float> > numhitsVals; + + float xMin = scan->getLoopVarValues(1).at(0); + float xMax = scan->getLoopVarValues(1).at(totalScans-1); + if(xMax<xMin){ + float xtemp = xMax; + xMax = xMin; + xMin = xtemp; + } + + int nScanBins = (xMax - xMin + 3); + + + //loop over the different values of multitrig_interval + for(int iScan = 0; iScan<totalScans; iScan++){ + file->cd(Form("loop1_%d",iScan)); + + std::map<int, TH1D*> histmap; + boost::regex re0("_(\\d+)_Trig0_Occupancy_Point_000"); + boost::regex re1("_(\\d+)_Trig1_Occupancy_Point_000"); + boost::regex re2("Mean"); + + int trigId=-1; + TIter nextkey(gDirectory->GetListOfKeys()); // histograms + TKey *key; + + while ((key=(TKey*)nextkey())) { + std::string hname(key->GetName()); + boost::cmatch matches; + + bool foundMatch=false; + if(boost::regex_search(hname.c_str(), matches, re0)){ + trigId=0; + foundMatch=true; + } + else if(boost::regex_search(hname.c_str(), matches, re1)){ + trigId=1; + foundMatch=true; + } + + if(foundMatch){ + + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + // std::cout<<"Match = "<<match.c_str()<<std::endl; + // std::cout<<"name = "<<hname.c_str()<<std::endl; + + int id=strtol(match.c_str(),0,10); + + TH2* occHisto = (TH2*)key->ReadObj(); + + double totalNumHits = occHisto->GetSumOfWeights(); + + xVals[iScan] = scan->getLoopVarValues(1).at(iScan); + + + //check if the hits vs. interval histos have already been initialized for this Module ID + if(histoNumhitsScan.find(id)==histoNumhitsScan.end()){ + + std::vector<TH1D*> temphistHits(2); + + for(int iTrig=0; iTrig<2; iTrig++){ + temphistHits[iTrig] = new TH1D(Form("HitsScan_Mod%d_Trig%d",id,iTrig),Form("Total Hits versus Interval for Module %d, Trigger %d",id,iTrig+1), nScanBins,xMin-1,xMax+1); + temphistHits[iTrig]->GetXaxis()->SetTitle("Interval between 1st and 2nd inject"); + temphistHits[iTrig]->GetYaxis()->SetTitle("Total Hits"); + temphistHits[iTrig]->SetOption("P"); + temphistHits[iTrig]->SetMarkerStyle(2); + temphistHits[iTrig]->SetMarkerSize(2); + + } + + histoNumhitsScan[id] = temphistHits; + std::vector<float> tempVecHits(2*totalScans,0); + numhitsVals[id] = tempVecHits; + + }//end if id not in histoNumhitsScan map + + + int myIndex = 2*iScan + trigId; + numhitsVals[id].at(myIndex) = totalNumHits; + + std::cout<<"Trigger "<<trigId+1<<" , interval "<<xVals[iScan]<<" : Total hits = " + <<numhitsVals[id].at(myIndex)<<std::endl; + + + file->cd(Form("loop1_%d",iScan)); + + }//if foundmatch + + }//end loop over keys + + } //end loop over iScan + + for(std::map<int, std::vector<TH1D*> >::iterator it=histoNumhitsScan.begin();it!=histoNumhitsScan.end();it++){ + int id=it->first; + + for(int iScan = 0; iScan<totalScans; iScan++){ + + int myIndex = 2*iScan; + histoNumhitsScan[id].at(0)->Fill(xVals[iScan], numhitsVals[id].at(myIndex+0) ); + histoNumhitsScan[id].at(1)->Fill(xVals[iScan], numhitsVals[id].at(myIndex+1) ); + + } + + anfile->cd(); + + for(int iTrig=0; iTrig<2; iTrig++){ + histoNumhitsScan[id].at(iTrig)->Write(); + histoNumhitsScan[id].at(iTrig)->SetDirectory(gDirectory); + } + + } //end iterate over histoNumhitsScan + +} + + + diff --git a/rce/rcecalib/analysis/MultiTrigNoiseAnalysis.hh b/rce/rcecalib/analysis/MultiTrigNoiseAnalysis.hh new file mode 100644 index 00000000..b06ce190 --- /dev/null +++ b/rce/rcecalib/analysis/MultiTrigNoiseAnalysis.hh @@ -0,0 +1,24 @@ +#ifndef MULTITRIGNOISEANALYSIS_HH +#define MULTITRIGNOISEANALYSIS_HH + +#include "rcecalib/analysis/CalibAnalysis.hh" +#include <map> + +class ConfigGui; +class TFile; +class TH2; +class TH1D; + +namespace RCE{ + class PixScan; +} + +class MultiTrigNoiseAnalysis: public CalibAnalysis{ +public: + MultiTrigNoiseAnalysis(): CalibAnalysis(){} + ~MultiTrigNoiseAnalysis(){} + void analyze(TFile* file, TFile* anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]); +}; + + +#endif diff --git a/rce/rcecalib/analysis/NoiseAnalysis.cc b/rce/rcecalib/analysis/NoiseAnalysis.cc new file mode 100644 index 00000000..62013404 --- /dev/null +++ b/rce/rcecalib/analysis/NoiseAnalysis.cc @@ -0,0 +1,85 @@ +#include "rcecalib/analysis/NoiseAnalysis.hh" +#include "rcecalib/server/PixScan.hh" + +#include <TFile.h> +#include <TH2.h> +#include <TH2D.h> +#include <TH1.h> +#include <TKey.h> +#include <boost/regex.hpp> +#include <iostream> +#include <fstream> + +namespace{ + const double threshold=0; +} +using namespace RCE; + +void NoiseAnalysis::analyze(TFile* file, TFile *anfile, RCE::PixScan* scn, int runno, ConfigGui* cfg[]){ + TIter nextkey(file->GetListOfKeys()); + TKey *key; + boost::regex re("_(\\d+)_NoiseOccupancy"); + boost::regex re2("NoiseOccupancy"); + while ((key=(TKey*)nextkey())) { + file->cd(); + std::string name(key->GetName()); + boost::cmatch matches; + if(boost::regex_search(name.c_str(), matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + int id=strtol(match.c_str(),0,10); + std::string neHistoName = boost::regex_replace (name, re2, "nEvents"); + TH2* histo = (TH2*)key->ReadObj(); + TH1* neHisto=(TH1*)gDirectory->Get(neHistoName.c_str()); + assert(neHisto!=0); + double nev=(double)neHisto->GetBinContent(1); + if(nev==0){ + std::cout<<"Number of events in "<<neHistoName<<" is 0"<<std::endl; + continue; + } + TH2D* ahis=new TH2D(Form("norm_occ_mod_%d",id), Form("Occupancy Mod %d at %s",id, findFieldName(cfg, id)), + histo->GetNbinsX(), histo->GetXaxis()->GetXmin(), histo->GetXaxis()->GetXmax(), + histo->GetNbinsY(), histo->GetYaxis()->GetXmin(), histo->GetYaxis()->GetXmax()); + ahis->GetXaxis()->SetTitle("Column"); + ahis->GetYaxis()->SetTitle("Row"); + TH2D* mhis=new TH2D(Form("mask_mod_%d",id), Form("Mask Mod %d at %s", id, findFieldName(cfg, id)), + histo->GetNbinsX(), histo->GetXaxis()->GetXmin(), histo->GetXaxis()->GetXmax(), + histo->GetNbinsY(), histo->GetYaxis()->GetXmin(), histo->GetYaxis()->GetXmax()); + mhis->GetXaxis()->SetTitle("Column"); + mhis->GetYaxis()->SetTitle("Row"); + unsigned char (*masks)[ipc::IPC_N_I4_PIXEL_ROWS]=0; + ipc::PixelFEI4AConfig* conf=findFEI4AConfig(cfg, id); + if(conf)masks=conf->FEMasks; + else { + ipc::PixelFEI4BConfig* confb=findFEI4BConfig(cfg, id); + if(confb)masks=confb->FEMasks; + } + if(masks && scn->clearMasks()==true)clearFEI4Masks(masks); + for (int i=0;i<histo->GetNbinsX();i++){ + for(int j=0;j<histo->GetNbinsY();j++){ + if(nev>0){ + ahis->SetBinContent(i+1,j+1,(double)histo->GetBinContent(i+1, j+1)/nev); + if((scn->useAbsoluteNoiseThreshold()==true && (double)histo->GetBinContent(i+1, j+1)>scn->getNoiseThreshold()) + || (scn->useAbsoluteNoiseThreshold()==false && ahis->GetBinContent(i+1, j+1)>scn->getNoiseThreshold())){ + mhis->SetBinContent(i+1,j+1,1); + if(masks){ + masks[i][j]&=0xfe; //reset bit 0 (enable) + masks[i][j]|=0x8; //reset bit 3 (hitbus) + } + } + } + } + } + if(masks) writeFEI4Config(anfile, runno); + m_fw->writeMaskFile(Form("%sNoiseMask_Mod_%d", m_fw->getPath(anfile).c_str(), id), mhis); + delete histo; + anfile->cd(); + ahis->Write(); + ahis->SetDirectory(gDirectory); + mhis->Write(); + mhis->SetDirectory(gDirectory); + } + } + if(configUpdate())writeTopFile(cfg, anfile, runno); +} + diff --git a/rce/rcecalib/analysis/NoiseAnalysis.hh b/rce/rcecalib/analysis/NoiseAnalysis.hh new file mode 100644 index 00000000..b39e8964 --- /dev/null +++ b/rce/rcecalib/analysis/NoiseAnalysis.hh @@ -0,0 +1,25 @@ +#ifndef NOISEANALYSIS_HH +#define NOISEANALYSIS_HH + +#include "rcecalib/analysis/CalibAnalysis.hh" +#include "rcecalib/analysis/CfgFileWriter.hh" + +class ConfigGui; +class TFile; +class TH2D; +namespace RCE{ + class PixScan; +} + +class NoiseAnalysis: public CalibAnalysis{ +public: + NoiseAnalysis(CfgFileWriter* fw): CalibAnalysis(), m_fw(fw){} + ~NoiseAnalysis(){delete m_fw;} + void analyze(TFile* file, TFile* anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]); + void writeMaskFile(TH2D* his, TFile* anfile); +private: + CfgFileWriter* m_fw; +}; + + +#endif diff --git a/rce/rcecalib/analysis/OffsetAnalysis.cc b/rce/rcecalib/analysis/OffsetAnalysis.cc new file mode 100644 index 00000000..457e088c --- /dev/null +++ b/rce/rcecalib/analysis/OffsetAnalysis.cc @@ -0,0 +1,132 @@ +#include "rcecalib/analysis/OffsetAnalysis.hh" +#include "rcecalib/server/PixScan.hh" + +#include <TFile.h> +#include <TStyle.h> +#include <TH2.h> +#include <TH2D.h> +#include <TH1.h> +#include <TF1.h> +#include <TKey.h> +#include <boost/regex.hpp> +#include <iostream> +#include <fstream> + +namespace{ + const double threshold=0; +} +using namespace RCE; + +void OffsetAnalysis::analyze(TFile* file, TFile *anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]){ + unsigned int numval=scan->getLoopVarValues(0).size(); + gStyle->SetOptFit(10); + gStyle->SetOptStat(0); + std::cout<<"Offset analysis"<<std::endl; + file->cd("loop1_0"); + TIter nextkey(gDirectory->GetListOfKeys()); + TKey *key; + boost::regex re("_(\\d+)_Mean"); + boost::regex re2("Mean"); + while ((key=(TKey*)nextkey())) { + file->cd("loop1_0"); + std::string name(key->GetName()); + boost::cmatch matches; + if(boost::regex_search(name.c_str(), matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + int id=strtol(match.c_str(),0,10); + std::string chi2HistoName = boost::regex_replace (name, re2, "ChiSquare"); + TH2* histo = (TH2*)key->ReadObj(); + TH2* chi2Histo=(TH2*)gDirectory->Get(chi2HistoName.c_str()); + assert(chi2Histo); + TH1D* hits1d[2]; + for (int i=0;i<2;i++){ + hits1d[i]=new TH1D(Form("HitsPerBin_%d__Mod_%d", i, id), + Form("Hits per bin %d Mod %d at %s", i, id, findFieldName(cfg, id)), + numval, -.5, (float)numval-.5) ; + hits1d[i]->GetXaxis()->SetTitle("Scan Point"); + } + fillHit1d(name, hits1d[0], numval); + file->cd("loop1_1"); + fillHit1d(name, hits1d[1], numval); + TH2* histo2 = (TH2*)gDirectory->Get(name.c_str()); + TH2* chi2Histo2 = (TH2*)gDirectory->Get(chi2HistoName.c_str()); + TH1D* offset=new TH1D(Form("Offset_Mod_%d",id), + Form("Offset Mod %d at %s", id, findFieldName(cfg, id)), 50, 0, 0.05); + offset->GetXaxis()->SetTitle("Offset (mV)"); + float clo=1.9; + float chi=3.9; + float m=1.4e-3; + struct ipc::PixelFECalibFEI4 *fecalib=0; + ipc::PixelFEI4AConfig* confa=findFEI4AConfig(cfg, id); + if(confa)fecalib=&confa->FECalib; + else{ + ipc::PixelFEI4BConfig* confb=findFEI4BConfig(cfg, id); + if(confb)fecalib=&confb->FECalib; + } + if(fecalib){ + clo=fecalib->cinjLo; + chi=fecalib->cinjHi; + m=fecalib->vcalCoeff[1]; + if(clo==0){ + std::cout<<"Cannot determine alpha because clo is 0 for module "<<id<<std::endl; + continue; + } + }else{ + std::cout<<"No configuration available. Using default values."<<std::endl; + } + float alpha=(clo+chi)/clo; + if(alpha==1){ + std::cout<<"Cannot determine offset because alpha is 1 for module "<<id<<std::endl; + continue; + } + for (int i=1;i<=histo->GetNbinsX();i++){ + for(int j=1;j<=histo->GetNbinsY();j++){ + if(chi2Histo->GetBinContent(i, j)!=0 && chi2Histo2->GetBinContent(i, j)!=0) { + float v1=histo->GetBinContent(i, j); + float v2=histo2->GetBinContent(i, j); + float n=m*(v1-alpha*v2)/(alpha-1); + offset->Fill(n); + } + } + } + offset->Fit("gaus"); + TF1* gaus=offset->GetFunction("gaus"); + double off=0; + if(gaus)off=gaus->GetParameter(1); + else std::cout<<"Warning: Fit for offset failed. Using default value of 0"<<std::endl; + std::cout<<"Offset for module "<<id<<" is "<<off<<std::endl; + if(off<0 || off>0.06){ + std::cout<<"Offset out of range (0..50). Setting to 0"<<std::endl; + off=0; + } + if(fecalib){ + m=fecalib->vcalCoeff[0]=off; + writeFEI4Config(anfile, runno); + } + + delete histo; + anfile->cd(); + offset->Write(); + offset->SetDirectory(gDirectory); + hits1d[0]->Write(); + hits1d[0]->SetDirectory(gDirectory); + hits1d[1]->Write(); + hits1d[1]->SetDirectory(gDirectory); + } + } + if(configUpdate())writeTopFile(cfg, anfile, runno); +} + +void OffsetAnalysis::fillHit1d(std::string &name, TH1* hits1d, unsigned numval){ +for(unsigned int k=0;k<numval;k++){ + boost::regex re2("Mean"); + std::string histoName = boost::regex_replace (name, re2, Form("Occupancy_Point_%03d", k)); + TH2* occHisto=(TH2*)gDirectory->Get(histoName.c_str()); + if(occHisto==0){ + std::cout<<"No Occupancy histograms found. Won't fill 1-d hit histo."<<std::endl; + break; + } + hits1d->SetBinContent(k+1, occHisto->GetSumOfWeights()); + } +} diff --git a/rce/rcecalib/analysis/OffsetAnalysis.hh b/rce/rcecalib/analysis/OffsetAnalysis.hh new file mode 100644 index 00000000..8f809f81 --- /dev/null +++ b/rce/rcecalib/analysis/OffsetAnalysis.hh @@ -0,0 +1,23 @@ +#ifndef OFFSETANALYSIS_HH +#define OFFSETANALYSIS_HH + +#include "rcecalib/analysis/CalibAnalysis.hh" + +class ConfigGui; +class TFile; +class TH2D; +class TH1; +namespace RCE{ + class PixScan; +} + +class OffsetAnalysis: public CalibAnalysis{ +public: + OffsetAnalysis(): CalibAnalysis(){} + ~OffsetAnalysis(){} + void analyze(TFile* file, TFile* anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]); + void fillHit1d(std::string &name, TH1* hits1d, unsigned numval); +}; + + +#endif diff --git a/rce/rcecalib/analysis/RegisterTestAnalysis.cc b/rce/rcecalib/analysis/RegisterTestAnalysis.cc new file mode 100644 index 00000000..c9540fa0 --- /dev/null +++ b/rce/rcecalib/analysis/RegisterTestAnalysis.cc @@ -0,0 +1,168 @@ +#include "rcecalib/analysis/RegisterTestAnalysis.hh" +#include "rcecalib/server/PixScan.hh" +#include "rcecalib/config/FEI4/Utils.hh" + +#include <TFile.h> +#include <TStyle.h> +#include <TH2.h> +#include <TH2D.h> +#include <TH1.h> +#include <TF1.h> +#include <TKey.h> +#include <boost/regex.hpp> +#include <iostream> +#include <fstream> + +namespace{ + const double threshold=0; +} +using namespace RCE; + +void RegisterTestAnalysis::analyze(TFile* file, TFile *anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]){ + gStyle->SetOptStat(0); + std::cout<<"Register Test Analysis"<<std::endl; + file->cd(); + TIter nextkey(gDirectory->GetListOfKeys()); + TKey *key; + boost::regex re("_(\\d+)_Pixel_Reg"); + boost::regex re2("Pixel"); + while ((key=(TKey*)nextkey())) { + file->cd(); + std::string hname(key->GetName()); + boost::cmatch matches; + if(boost::regex_search(hname.c_str(), matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + int id=strtol(match.c_str(),0,10); + std::string globHistoName = boost::regex_replace (hname, re2, "Global"); + TH2* histo = (TH2*)key->ReadObj(); + TH1* globHisto=(TH2*)gDirectory->Get(globHistoName.c_str()); + assert(globHisto); + int binsx=histo->GetNbinsX(); + int binsy=histo->GetNbinsY(); + char name[128]; + char title[128]; + sprintf(name, "Mod_%d_Enable", id); + sprintf(title, "Enable Bit Module %d at %s", id, findFieldName(cfg, id)); + TH2F* enable=new TH2F(name, title, binsx, 0, binsx, binsy, 0, binsy); + enable->GetXaxis()->SetTitle("Column"); + enable->GetYaxis()->SetTitle("Row"); + sprintf(name, "Mod_%d_TDAC", id); + sprintf(title, "TDAC Bits Module %d at %s", id, findFieldName(cfg, id)); + TH2F* tdac=new TH2F(name, title, binsx, 0, binsx, binsy, 0, binsy); + tdac->GetXaxis()->SetTitle("Column"); + tdac->GetYaxis()->SetTitle("Row"); + sprintf(name, "Mod_%d_LargeCap", id); + sprintf(title, "Large Cap Bit Module %d at %s", id, findFieldName(cfg, id)); + TH2F* largeCap=new TH2F(name, title, binsx, 0, binsx, binsy, 0, binsy); + largeCap->GetXaxis()->SetTitle("Column"); + largeCap->GetYaxis()->SetTitle("Row"); + sprintf(name, "Mod_%d_SmallCap", id); + sprintf(title, "Small Cap Bit Module %d at %s", id, findFieldName(cfg, id)); + TH2F* smallCap=new TH2F(name, title, binsx, 0, binsx, binsy, 0, binsy); + smallCap->GetXaxis()->SetTitle("Column"); + smallCap->GetYaxis()->SetTitle("Row"); + sprintf(name, "Mod_%d_Hitbus", id); + sprintf(title, "Hitbus Bit Module %d at %s", id, findFieldName(cfg, id)); + TH2F* hitbus=new TH2F(name, title, binsx, 0, binsx, binsy, 0, binsy); + hitbus->GetXaxis()->SetTitle("Column"); + hitbus->GetYaxis()->SetTitle("Row"); + sprintf(name, "Mod_%d_FDAC", id); + sprintf(title, "FDAC Bits Module %d at %s", id, findFieldName(cfg, id)); + TH2F* fdac=new TH2F(name, title, binsx, 0, binsx, binsy, 0, binsy); + fdac->GetXaxis()->SetTitle("Column"); + fdac->GetYaxis()->SetTitle("Row"); + + for (int i=0;i<binsx;i++){ + for (int j=0;j<binsy;j++){ + int val=histo->GetBinContent(i+1, j+1); + for (int k=0;k<13;k++){ + int bit=val&(1<<k); + if(bit){ + std::cout<<"FE "<<id<<": Pixel Register Problem."<<std::endl; + if(k==0)enable->Fill(i,j); + else if(k>=1 && k<=5)tdac->Fill(i,j); + else if(k==6)largeCap->Fill(i,j); + else if(k==7)smallCap->Fill(i,j); + else if(k==8)hitbus->Fill(i,j); + else if(k>=9)fdac->Fill(i,j); + } + } + } + } + delete histo; + anfile->cd(); + enable->Write(); + enable->SetDirectory(gDirectory); + tdac->Write(); + tdac->SetDirectory(gDirectory); + largeCap->Write(); + largeCap->SetDirectory(gDirectory); + smallCap->Write(); + smallCap->SetDirectory(gDirectory); + hitbus->Write(); + hitbus->SetDirectory(gDirectory); + fdac->Write(); + fdac->SetDirectory(gDirectory); + ipc::PixelFEI4BConfig* confb=findFEI4BConfig(cfg, id); + if(confb){ + sprintf(name, "Mod_%d_Global_Register_Diff", id); + sprintf(title, "Diff of Global Reg Module %d at %s", id, findFieldName(cfg, id)); + TH1F* glob=new TH1F(name, title, 36, -0.5, 35.5); + glob->GetXaxis()->SetTitle("Register"); + unsigned short reg[36]; + reg[0]=0; + reg[1]=(confb->FEGlobal.SmallHitErase<<8) | flipBits(8,confb->FEGlobal.Eventlimit); + reg[2]=0xffff & ((42<<12) | (1<<11)); //ConfAddrEnable was explicitely turned on, TrigCnt was 42 + reg[3]=confb->FEGlobal.ErrMask0; + reg[4]=confb->FEGlobal.ErrMask1; + reg[5]=(flipBits(8, confb->FEGlobal.PrmpVbpRight)<<8)| flipBits(8, confb->FEGlobal.BufVgOpAmp); + reg[6]=flipBits(8, confb->FEGlobal.PrmpVbp); + reg[7]=(flipBits(8, confb->FEGlobal.TdacVbp)<<8)| flipBits(8, confb->FEGlobal.DisVbn); + reg[8]=(flipBits(8, confb->FEGlobal.Amp2Vbn)<<8)| flipBits(8, confb->FEGlobal.Amp2VbpFol); + reg[9]=flipBits(8, confb->FEGlobal.Amp2Vbp); + reg[10]=(flipBits(8, confb->FEGlobal.FdacVbn)<<8)| flipBits(8, confb->FEGlobal.Amp2Vbpf); + reg[11]=(flipBits(8, confb->FEGlobal.PrmpVbnFol)<<8)| flipBits(8, confb->FEGlobal.PrmpVbpLeft); + reg[12]=(flipBits(8, confb->FEGlobal.PrmpVbpf)<<8)| flipBits(8, confb->FEGlobal.PrmpVbnLcc); + reg[13]=0; + reg[14]=(flipBits(8, confb->FEGlobal.LVDSDrvIref)<<8)| flipBits(8, confb->FEGlobal.GADCOpAmp); + reg[15]=(flipBits(8, confb->FEGlobal.PllIbias)<<8)| flipBits(8, confb->FEGlobal.LVDSDrvVos); + reg[16]=(flipBits(8, confb->FEGlobal.TempSensBias)<<8)| flipBits(8, confb->FEGlobal.PllIcp); + reg[17]=flipBits(8, confb->FEGlobal.PlsrIdacRamp); + reg[18]=(flipBits(8, confb->FEGlobal.VrefDigTune)<<8)| flipBits(8, confb->FEGlobal.PlsrVgOPamp); + reg[19]=(flipBits(8, confb->FEGlobal.PlsrDacBias)<<8)| flipBits(8, confb->FEGlobal.VrefAnTune); + reg[20]=(flipBits(8, confb->FEGlobal.Vthin_AltCoarse)<<8)| flipBits(8, confb->FEGlobal.Vthin_AltFine); + reg[21]=(confb->FEGlobal.HITLD_In<<12)| (confb->FEGlobal.DINJ_Override<<11) | (confb->FEGlobal.DIGHITIN_Sel<<10) | flipBits(10, 341); + reg[22]=768; + reg[23]=confb->FEGlobal.DisableColumnCnfg0; + reg[24]=confb->FEGlobal.DisableColumnCnfg1; + reg[25]=(100<<8)| confb->FEGlobal.DisableColumnCnfg2; + reg[26]=(12<<3)| (confb->FEGlobal.StopModeCnfg<<2) | (confb->FEGlobal.HitDiscCnfg); + reg[27]=(confb->FEGlobal.EN_PLL<<15); + reg[28]=(confb->FEGlobal.LVDSDrvSet06<<15)| (confb->FEGlobal.EN40M<<9) | (confb->FEGlobal.EN80M<<8) + |(confb->FEGlobal.CLK1<<5)|(confb->FEGlobal.CLK0<<2) | (confb->FEGlobal.EN160M<<1) | confb->FEGlobal.EN320M; + reg[29]=(confb->FEGlobal.no8b10b<<13) |(flipBits(8, confb->FEGlobal.EmptyRecord)<<4) + | (confb->FEGlobal.LVDSDrvEn<<2) |(confb->FEGlobal.LVDSDrvSet30<<1) | confb->FEGlobal.LVDSDrvSet12; + reg[30]=(flipBits(2, confb->FEGlobal.TempSensDiodeSel)<<14) | (confb->FEGlobal.TempSensDisable<<13) | (confb->FEGlobal.IleakRange<<12); + reg[31]=(confb->FEGlobal.PlsrRiseUpTau<<13)| (confb->FEGlobal.PlsrPwr<<12) |(flipBits(6, confb->FEGlobal.PlsrDelay)<<6)| (confb->FEGlobal.EN80M<<8) + | (confb->FEGlobal.ExtDigCalSW<<5) | (confb->FEGlobal.ExtAnaCalSW<<4) | confb->FEGlobal.GADCSel; + reg[32]=confb->FEGlobal.SELB0; + reg[33]=confb->FEGlobal.SELB1; + reg[34]=(confb->FEGlobal.SELB2<<8)|(confb->FEGlobal.PrmpVbpMsnEn<<4); + reg[35]=confb->FEGlobal.Chip_SN; + for(int i=0;i<36;i++){ + if(globHisto->GetBinContent(i+1)!=reg[i]){ + std::cout<<"Frontend "<<id<<" global register "<<i<<" content differs: "; + std::cout<<"Setting= 0x"<<std::hex<<reg[i]<<" readback= 0x"<<(unsigned)globHisto->GetBinContent(i+1)<<std::dec<<std::endl; + glob->SetBinContent(i+1, unsigned(globHisto->GetBinContent(i+1))^reg[i]); + } + } + glob->Write(); + glob->SetDirectory(gDirectory); + }else{ + std::cout<<"Not an FEI4B chip. Not checking global register"<<std::endl; + } + } + } +} + diff --git a/rce/rcecalib/analysis/RegisterTestAnalysis.hh b/rce/rcecalib/analysis/RegisterTestAnalysis.hh new file mode 100644 index 00000000..79bc6a6b --- /dev/null +++ b/rce/rcecalib/analysis/RegisterTestAnalysis.hh @@ -0,0 +1,22 @@ +#ifndef REGISTERTESTANALYSIS_HH +#define REGISTERTESTANALYSIS_HH + +#include "rcecalib/analysis/CalibAnalysis.hh" + +class ConfigGui; +class TFile; +class TH2D; +class TH1; +namespace RCE{ + class PixScan; +} + +class RegisterTestAnalysis: public CalibAnalysis{ +public: + RegisterTestAnalysis(): CalibAnalysis(){} + ~RegisterTestAnalysis(){} + void analyze(TFile* file, TFile* anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]); +}; + + +#endif diff --git a/rce/rcecalib/analysis/SerialNumberAnalysis.cc b/rce/rcecalib/analysis/SerialNumberAnalysis.cc new file mode 100644 index 00000000..c3fb38ae --- /dev/null +++ b/rce/rcecalib/analysis/SerialNumberAnalysis.cc @@ -0,0 +1,53 @@ +#include "rcecalib/analysis/SerialNumberAnalysis.hh" +#include "rcecalib/server/PixScan.hh" + +#include <TFile.h> +#include <TH1.h> +#include <TKey.h> +#include <boost/regex.hpp> +#include <iostream> +#include <fstream> + +using namespace RCE; + +void SerialNumberAnalysis::analyze(TFile* file, TFile *anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]){ + std::cout<<"Serial number analysis"<<std::endl; + TIter nextkey(file->GetListOfKeys()); + TKey *key; + boost::regex re("_(\\d+)_SN"); + boost::regex re2("at ([AC][1-8]-[12]) "); + int sn=0; + int allmatch=true; + while ((key=(TKey*)nextkey())) { + std::string name(key->GetName()); + std::string title(key->GetTitle()); + boost::cmatch matches; + if(boost::regex_search(name.c_str(), matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + int id=strtol(match.c_str(),0,10); + boost::regex_search(title.c_str(), matches, re2); + assert(matches.size()>1); + std::string match2(matches[1].first, matches[1].second); + TH1* histo = (TH1*)key->ReadObj(); + int sn_read=histo->GetBinContent(1); + ipc::PixelFEI4BConfig* conf=findFEI4BConfig(cfg, id); + if(conf){ + sn=conf->FEGlobal.Chip_SN; + if(sn!=sn_read){ + std::cout<<"FE at "<<match2<<": Readback of serial number ("<<sn_read<<") does not match serial number in config file ("<<sn<<")."<<std::endl; + allmatch=false; + }else{ + std::cout<<"FE at "<<match2<<": Readback of serial number ("<<sn_read<<") identical as in config file."<<std::endl; + } + conf->FEGlobal.Chip_SN=sn_read; + writeFEI4Config(anfile, runno); + } + delete histo; + } + } + if(allmatch)std::cout<<"The configurations for all frontends match between EFUSE and config file."<<std::endl; + else std::cout<<"!!!!!!! There are mismatches between read back values and config files."<<std::endl; + if(configUpdate())writeTopFile(cfg, anfile, runno); +} + diff --git a/rce/rcecalib/analysis/SerialNumberAnalysis.hh b/rce/rcecalib/analysis/SerialNumberAnalysis.hh new file mode 100644 index 00000000..ade2c92d --- /dev/null +++ b/rce/rcecalib/analysis/SerialNumberAnalysis.hh @@ -0,0 +1,21 @@ +#ifndef SERIALNUMBERANALYSIS_HH +#define SERIALNUMBERANALYSIS_HH + +#include "rcecalib/analysis/CalibAnalysis.hh" + +class ConfigGui; +class TFile; +class TH2D; +namespace RCE{ + class PixScan; +} + +class SerialNumberAnalysis: public CalibAnalysis{ +public: + SerialNumberAnalysis(): CalibAnalysis(){} + ~SerialNumberAnalysis(){} + void analyze(TFile* file, TFile* anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]); +}; + + +#endif diff --git a/rce/rcecalib/analysis/StuckPixelAnalysis.cc b/rce/rcecalib/analysis/StuckPixelAnalysis.cc new file mode 100644 index 00000000..b0556443 --- /dev/null +++ b/rce/rcecalib/analysis/StuckPixelAnalysis.cc @@ -0,0 +1,52 @@ +#include "rcecalib/analysis/StuckPixelAnalysis.hh" +#include "rcecalib/server/PixScan.hh" + +#include <TFile.h> +#include <TH2.h> +#include <TH1.h> +#include <TKey.h> +#include <boost/regex.hpp> +#include <iostream> +#include <fstream> +using namespace RCE; + +void StuckPixelAnalysis::analyze(TFile* file, TFile *anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]){ + TIter nextkey(file->GetListOfKeys()); + TKey *key; + boost::regex re("_(\\d+)_Hitor"); + while ((key=(TKey*)nextkey())) { + file->cd(); + std::string name(key->GetName()); + std::cout<<name<<std::endl; + boost::cmatch matches; + if(boost::regex_search(name.c_str(), matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + int id=strtol(match.c_str(),0,10); + TH2* histo = (TH2*)key->ReadObj(); + m_fw->writeMaskFile(Form("%sStuckPixelMask_Mod_%d", m_fw->getPath(anfile).c_str(), id), histo); + unsigned char (*masks)[ipc::IPC_N_I4_PIXEL_ROWS]=0; + ipc::PixelFEI4AConfig* conf=findFEI4AConfig(cfg, id); + if(conf)masks=conf->FEMasks; + else { + ipc::PixelFEI4BConfig* confb=findFEI4BConfig(cfg, id); + if(confb)masks=confb->FEMasks; + } + if(masks){ + if(scan->clearMasks()==true)clearFEI4Masks(masks); + for (int i=0;i<histo->GetNbinsX();i++){ + for(int j=0;j<histo->GetNbinsY();j++){ + if(histo->GetBinContent(i+1, j+1)==1){ + masks[i][j]&=0xfe; //reset bit 0 (enable) + masks[i][j]|=0x8; //reset bit 3 (hitbus) + } + } + } + writeFEI4Config(anfile, runno); + } + delete histo; + } + } + if(configUpdate())writeTopFile(cfg, anfile, runno); +} + diff --git a/rce/rcecalib/analysis/StuckPixelAnalysis.hh b/rce/rcecalib/analysis/StuckPixelAnalysis.hh new file mode 100644 index 00000000..b302bc04 --- /dev/null +++ b/rce/rcecalib/analysis/StuckPixelAnalysis.hh @@ -0,0 +1,25 @@ +#ifndef STUCKPIXELANALYSIS_HH +#define STUCKPIXELANALYSIS_HH + +#include "rcecalib/analysis/CalibAnalysis.hh" +#include "rcecalib/analysis/CfgFileWriter.hh" + +class ConfigGui; +class TFile; +class TH2; +namespace RCE{ + class PixScan; +} + +class StuckPixelAnalysis: public CalibAnalysis{ +public: + StuckPixelAnalysis(CfgFileWriter *fw): CalibAnalysis(), m_fw(fw){} + ~StuckPixelAnalysis(){delete m_fw;} + void analyze(TFile* file, TFile* anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]); + void writeMaskFile(TH2* his, TFile* anfile); +private: + CfgFileWriter* m_fw; +}; + + +#endif diff --git a/rce/rcecalib/analysis/T0Analysis.cc b/rce/rcecalib/analysis/T0Analysis.cc new file mode 100644 index 00000000..4a54723e --- /dev/null +++ b/rce/rcecalib/analysis/T0Analysis.cc @@ -0,0 +1,311 @@ +#include "rcecalib/analysis/T0Analysis.hh" +#include "rcecalib/server/PixScan.hh" + +#include <TFile.h> +#include <TStyle.h> +#include <TH2.h> +#include <TH2D.h> +#include <TH1.h> +#include <TF1.h> +#include <TKey.h> +#include <boost/regex.hpp> +#include <iostream> +#include <fstream> + +namespace{ + const double threshold=0; +} +using namespace RCE; + +void T0Analysis::analyze(TFile* file, TFile *anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]){ + unsigned int numval=scan->getLoopVarValues(0).size(); + gStyle->SetOptFit(10); + gStyle->SetOptStat(0); + std::cout<<"T0 analysis"<<std::endl; + file->cd("loop1_0"); + TIter nextkey(gDirectory->GetListOfKeys()); + TKey *key; + boost::regex re("_(\\d+)_Mean"); + boost::regex re2("Mean"); + while ((key=(TKey*)nextkey())) { + file->cd("loop1_0"); + std::string name(key->GetName()); + boost::cmatch matches; + if(boost::regex_search(name.c_str(), matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + + + // std::cout<<"match = "<<match.c_str()<<std::endl; + int id=strtol(match.c_str(),0,10); + + // std::cout<<"id = "<<id<<std::endl; + + std::string sigmaHistoName = boost::regex_replace (name, re2, "Sigma"); + + struct ipc::PixelFEI4AGlobal *feglobalA=0; + struct ipc::PixelFEI4BGlobal *feglobalB=0; + + ipc::PixelFEI4AConfig* confa=findFEI4AConfig(cfg, id); + if(confa)feglobalA=&confa->FEGlobal; + else{ + ipc::PixelFEI4BConfig* confb=findFEI4BConfig(cfg, id); + if(confb)feglobalB=&confb->FEGlobal; + } + + TH2* histo = (TH2*)key->ReadObj(); + TH2* sigmaHisto=(TH2*)gDirectory->Get(sigmaHistoName.c_str()); + assert(sigmaHisto); + TH1D* hits1d[2]; + + for (int iScan=0;iScan<2;iScan++){ + hits1d[iScan]=new TH1D(Form("HitsPerBin_%d_Mod_%d", iScan, id), + Form("Hits per bin Mod %d at %s (Scan %d)" + , id, findFieldName(cfg, id), iScan), + numval, -.5, (float)numval-.5) ; + hits1d[iScan]->GetXaxis()->SetTitle("Scan Point"); + } + + fillHit1d(name, hits1d[0], numval); + file->cd("loop1_1"); + fillHit1d(name, hits1d[1], numval); + + TH2* histo2 = (TH2*)gDirectory->Get(name.c_str()); + TH2* sigmaHisto2 = (TH2*)gDirectory->Get(sigmaHistoName.c_str()); + + + + //Get histogram ranges + float maxval[2] = {0,0}; + float minval[2] = {1e8, 1e8}; + float vals[4] = {0,0,0,0}; + + for (int i=1;i<=histo->GetNbinsX();i++){ + for(int j=1;j<=histo->GetNbinsY();j++){ + + vals[0] = histo->GetBinContent(i, j); + vals[1] = histo2->GetBinContent(i, j); + vals[2] = sigmaHisto->GetBinContent(i, j); + vals[3] = sigmaHisto2->GetBinContent(i, j); + + for(int kpar = 0; kpar<2; kpar++){ + if(vals[kpar]>maxval[0]){ + maxval[0] = vals[kpar]; + } + if(vals[kpar]<minval[0]&&vals[kpar]>0){ + minval[0] = vals[kpar]; + } + } + + for(int kpar = 2; kpar<4; kpar++){ + if(vals[kpar]>maxval[1]){ + maxval[1] = vals[kpar]; + } + if(vals[kpar]<minval[1]&&vals[kpar]>0){ + minval[1] = vals[kpar]; + } + } + + } + } + + TH1D* t0mean[2]; + TH1D* t0sigma[2]; + + int nGoodPixels = 0; + float sumT0Diffs = 0; + + for(int iScan=0; iScan<2; iScan++){ + + t0mean[iScan] =new TH1D(Form("T0_%d_Mod_%d",iScan,id), + Form("T0 for each pixel in Mod %d at %s (Scan %d)", + id, findFieldName(cfg, id), iScan), 50, minval[0]-1, maxval[0]+1); + t0sigma[iScan] =new TH1D(Form("Sigma_%d_Mod_%d",iScan,id), + Form("T0 S-CURVE sigma for each pixel in Mod %d at %s (Scan %d)", + id, findFieldName(cfg, id), iScan), 50, minval[1]-1, maxval[1]+1); + + + t0mean[iScan]->GetXaxis()->SetTitle("t0 (strobe delay counts)"); + t0sigma[iScan]->GetXaxis()->SetTitle("t0 S-Curve sigma (strobe delay counts)"); + + } + + + + + + for (int i=1;i<=histo->GetNbinsX();i++){ + for(int j=1;j<=histo->GetNbinsY();j++){ + + float val=0; + + if(histo->GetBinContent(i, j)!=0 ){ + val = histo->GetBinContent(i, j); + t0mean[0]->Fill(val); + + if(histo2->GetBinContent(i, j)!=0 ){ + nGoodPixels++; + float val2 = histo2->GetBinContent(i, j); + sumT0Diffs += (val2 - val); + } + + } + if(histo2->GetBinContent(i, j)!=0 ){ + val = histo2->GetBinContent(i, j); + t0mean[1]->Fill(val); + } + + if(sigmaHisto->GetBinContent(i, j)!=0 ){ + val = sigmaHisto->GetBinContent(i, j); + t0sigma[0]->Fill(val); + } + if(sigmaHisto2->GetBinContent(i, j)!=0 ){ + val = sigmaHisto2->GetBinContent(i, j); + t0sigma[1]->Fill(val); + } + + } + + } + float avgt0diff = sumT0Diffs/nGoodPixels; + + float t0[2]; + for(int iScan=0; iScan<2; iScan++){ + + t0mean[iScan]->Fit("gaus"); + t0[iScan] = t0mean[iScan]->GetFunction("gaus")->GetParameter(1); + std::cout<<"T0 for module "<<id<<" for scan "<<iScan<<" is "<<t0[iScan]<<std::endl; + + } + + assert(t0[1] > t0[0]); + + float convFactor = 25.6/(avgt0diff); //one clock tick=25.6 ns + + std::cout<<"delay/(strobe-delay count) = "<<convFactor<<" (ns/count)"<<std::endl; + + + TH1D* t0mean_ns[2]; + TH1D* t0sigma_ns[2]; + TH1D* t0diff_ns; + + + for(int iScan=0; iScan<2; iScan++){ + + t0mean_ns[iScan] = new TH1D(Form("T0_%d_Mod_%d_ns",iScan,id), + Form("T0 (in ns) for each pixel in Mod %d at %s (Scan %d)", + id, findFieldName(cfg, id), iScan), 50, minval[0]-1, maxval[0]+1); + t0sigma_ns[iScan] = new TH1D(Form("Sigma_%d_Mod_%d_ns",iScan,id), + Form("T0 S-CURVE sigma (in ns) for each pixel in Mod %d at %s (Scan %d)", + id, findFieldName(cfg, id), iScan), 50, minval[1]-1, maxval[1]+1); + + t0mean_ns[iScan]->GetXaxis()->SetTitle("t0 (ns)"); + t0sigma_ns[iScan]->GetXaxis()->SetTitle("t0 S-Curve sigma (ns)"); + + } + + t0diff_ns =new TH1D(Form("T0_Diff_%d",id), + Form("T0 difference (in ns) for each pixel in Mod %d at %s", + id, findFieldName(cfg, id)), 50, 20., 30.); + t0diff_ns->GetXaxis()->SetTitle("t0_2 - t0_1 (ns)"); + + + for (int i=1;i<=histo->GetNbinsX();i++){ + for(int j=1;j<=histo->GetNbinsY();j++){ + + float val=0; + + if(histo->GetBinContent(i, j)!=0 ){ + val = histo->GetBinContent(i, j)*convFactor; + t0mean_ns[0]->Fill(val); + + if(histo2->GetBinContent(i, j)!=0){ + float val2 = histo2->GetBinContent(i, j)*convFactor; + t0diff_ns->Fill(val2 - val); + } + + } + if(histo2->GetBinContent(i, j)!=0 ){ + val = histo2->GetBinContent(i, j)*convFactor; + t0mean_ns[1]->Fill(val); + } + + if(sigmaHisto->GetBinContent(i, j)!=0 ){ + val = sigmaHisto->GetBinContent(i, j)*convFactor; + t0sigma_ns[0]->Fill(val); + } + if(sigmaHisto2->GetBinContent(i, j)!=0 ){ + val = sigmaHisto2->GetBinContent(i, j)*convFactor; + t0sigma_ns[1]->Fill(val); + } + + } + + } + + + float t0_ns[2]; + + for(int iScan=0; iScan<2; iScan++){ + t0mean_ns[iScan]->Fit("gaus"); + t0_ns[iScan] = t0mean_ns[iScan]->GetFunction("gaus")->GetParameter(1); + } + + float strobeDel = (t0_ns[1] + 5.0)/convFactor; + int strobeDelInt = (int)(strobeDel+0.5); + std::cout<<"t0 = "<<t0_ns[1]<<" ; strobe delay = "<<strobeDel<<" = "<<strobeDelInt<<std::endl; + + int trigLat = scan->getLoopVarValues(1).at(1); + + if(feglobalA){ + feglobalA->PlsrDelay=strobeDelInt; + feglobalA->TrigLat=trigLat; + writeFEI4Config(anfile, runno); + } + if(feglobalB){ + feglobalB->PlsrDelay=strobeDelInt; + feglobalB->TrigLat=trigLat; + writeFEI4Config(anfile, runno); + } + + + delete histo; + anfile->cd(); + + for(int iScan=0; iScan<2; iScan++){ + + t0mean[iScan]->Write(); + t0mean[iScan]->SetDirectory(gDirectory); + t0sigma[iScan]->Write(); + t0sigma[iScan]->SetDirectory(gDirectory); + + t0mean_ns[iScan]->Write(); + t0mean_ns[iScan]->SetDirectory(gDirectory); + t0sigma_ns[iScan]->Write(); + t0sigma_ns[iScan]->SetDirectory(gDirectory); + + hits1d[iScan]->Write(); + hits1d[iScan]->SetDirectory(gDirectory); + + } + t0diff_ns->Write(); + t0diff_ns->SetDirectory(gDirectory); + + + } + } + if(configUpdate())writeTopFile(cfg, anfile, runno); +} + +void T0Analysis::fillHit1d(std::string &name, TH1* hits1d, unsigned numval){ +for(unsigned int k=0;k<numval;k++){ + boost::regex re2("Mean"); + std::string histoName = boost::regex_replace (name, re2, Form("Occupancy_Point_%03d", k)); + TH2* occHisto=(TH2*)gDirectory->Get(histoName.c_str()); + if(occHisto==0){ + std::cout<<"No Occupancy histograms found. Won't fill 1-d hit histo."<<std::endl; + break; + } + hits1d->SetBinContent(k+1, occHisto->GetSumOfWeights()); + } +} diff --git a/rce/rcecalib/analysis/T0Analysis.hh b/rce/rcecalib/analysis/T0Analysis.hh new file mode 100644 index 00000000..c72e9d82 --- /dev/null +++ b/rce/rcecalib/analysis/T0Analysis.hh @@ -0,0 +1,23 @@ +#ifndef T0ANALYSIS_HH +#define T0ANALYSIS_HH + +#include "rcecalib/analysis/CalibAnalysis.hh" + +class ConfigGui; +class TFile; +class TH2D; +class TH1; +namespace RCE{ + class PixScan; +} + +class T0Analysis: public CalibAnalysis{ +public: + T0Analysis(): CalibAnalysis(){} + ~T0Analysis(){} + void analyze(TFile* file, TFile* anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]); + void fillHit1d(std::string &name, TH1* hits1d, unsigned numval); +}; + + +#endif diff --git a/rce/rcecalib/analysis/TdacAnalysis.cc b/rce/rcecalib/analysis/TdacAnalysis.cc new file mode 100644 index 00000000..b0a10e41 --- /dev/null +++ b/rce/rcecalib/analysis/TdacAnalysis.cc @@ -0,0 +1,157 @@ +#include "rcecalib/analysis/TdacAnalysis.hh" +#include "rcecalib/server/PixScan.hh" +#include "rcecalib/config/FEI3/Frontend.hh" + +#include <TFile.h> +#include <TH2.h> +#include <TH2D.h> +#include <TH1.h> +#include <TKey.h> +#include <boost/regex.hpp> +#include <iostream> +#include "TH1D.h" +#include "TF1.h" +#include "TStyle.h" + +namespace{ + const double BAD_THRESHOLD=150; +} + + +void TdacAnalysis::analyze(TFile* file, TFile *anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]){ + //gStyle->SetOptStat(1110); + gStyle->SetOptFit(10); + gStyle->SetOptStat(0); + file->cd(); + TKey *key; + char subdir[128]; + char name[128]; + char title[128]; + int binsx=0, binsy=0; + size_t numvals=scan->getLoopVarValues(1).size(); + std::map<int, hdata> *histomap=new std::map<int, hdata>[numvals]; + double *val=new double[numvals]; + for (size_t i=0;i<numvals;i++){ + sprintf(subdir, "loop1_%d", i); + file->cd(subdir); + TIter nextkey(gDirectory->GetListOfKeys()); // TDAC settings + while ((key=(TKey*)nextkey())) { + boost::regex re("_(\\d+)_Mean"); + boost::cmatch matches; + if(boost::regex_search(key->GetName(), matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + int lnm=strtol(match.c_str(),0,10); + char tdachistoname[128]; + sprintf (tdachistoname, "TDAC_settings_Mod_%d_it_%d", lnm, i); + TH2* histo = (TH2*)key->ReadObj(); + TH2* tdachisto=(TH2*)gDirectory->Get(tdachistoname); + assert(tdachisto); + histomap[i][lnm].mean=histo; + histomap[i][lnm].tdac=tdachisto; + binsx=histo->GetNbinsX(); + binsy=histo->GetNbinsY(); + } + } + } + int target=scan->getThresholdTargetValue(); + for(std::map<int, hdata>::iterator it=histomap[0].begin();it!=histomap[0].end();it++){ + int id=it->first; + sprintf(name, "threshdist_Mod_%d", id); + sprintf(title, "Threshold distribution Module %d at %s", id, findFieldName(cfg, id)); + TH1F* thresh1d=new TH1F(name, title, 400, 1000, 5000); + thresh1d->GetXaxis()->SetTitle("Threshold"); + sprintf(name, "BestMean_Mod_%d", id); + sprintf(title, "Best Mean Module %d at %s", id, findFieldName(cfg, id)); + TH2F* mean=new TH2F(name, title, binsx, 0, binsx, binsy, 0, binsy); + mean->GetXaxis()->SetTitle("Column"); + mean->GetYaxis()->SetTitle("Row"); + sprintf(name, "diff2d_Mod_%d", id); + sprintf(title, "Distance wrt %d electrons Module %d at %s", target, id, findFieldName(cfg, id)); + TH2F* diff2d=new TH2F(name, title, binsx, 0, binsx, binsy, 0, binsy); + diff2d->GetXaxis()->SetTitle("Column"); + diff2d->GetYaxis()->SetTitle("Row"); + sprintf(name, "thresh1d_Mod_%d", id); + sprintf(title, "Thresholds Module %d at %s", id, findFieldName(cfg, id)); + int nbins=binsx*binsy; + TH1F* diff1d=new TH1F(name, title, nbins, 0, (float)nbins); + diff1d->GetXaxis()->SetTitle("Channel"); + diff1d->SetOption("p9"); + sprintf(name, "BestTdac_Mod_%d", id); + sprintf(title, "Best Tdacs Module %d at %s", id, findFieldName(cfg, id)); + TH2F* tdac=new TH2F(name, title, binsx, 0, binsx, binsy, 0, binsy); + tdac->GetXaxis()->SetTitle("Column"); + tdac->GetYaxis()->SetTitle("Row"); + sprintf(name, "BadPixels_Mod_%d", id); + sprintf(title, "Bad Pixels Module %d at %s", id, findFieldName(cfg, id)); + TH2F* bad=new TH2F(name, title, binsx, 0, binsx, binsy, 0, binsy); + bad->GetXaxis()->SetTitle("Column"); + bad->GetYaxis()->SetTitle("Row"); + sprintf(name, "threshdiff_Mod_%d", id); + sprintf(title, "Threshold distribution around target value Module %d at %s", id, findFieldName(cfg, id)); + TH1F* threshdist=new TH1F(name, title, 200, -500, 500); + threshdist->GetXaxis()->SetTitle("Threshold"); + struct ipc::PixelFEI4Trims *trims=0; + struct ipc::PixelModuleConfig *conf3=0; + ipc::PixelFEI4AConfig* confa=findFEI4AConfig(cfg, id); + if(confa)trims=&confa->FETrims; + else{ + ipc::PixelFEI4BConfig* confb=findFEI4BConfig(cfg, id); + if(confb)trims=&confb->FETrims; + else conf3=findFEI3Config(cfg, id); + } + for (int i=1;i<=mean->GetNbinsX();i++){ + for(int j=1;j<=mean->GetNbinsY();j++){ + double bestval=10000; + int index=0; + for(size_t k=0;k<numvals;k++){ + val[k]=histomap[k][id].mean->GetBinContent(i,j); + if(fabs(val[k]-target)<bestval){ + index=k; + bestval=fabs(val[k]-target); + } + } + mean->SetBinContent(i,j,val[index]); + diff2d->SetBinContent(i,j,fabs(val[index]-target)); + diff1d->SetBinContent((i-1)*mean->GetNbinsY()+j, val[index]); + thresh1d->Fill(val[index]); + threshdist->Fill(val[index]-target); + tdac->SetBinContent(i,j,histomap[index][id].tdac->GetBinContent(i,j)); + if(trims)trims->dacThresholdTrim[i-1][j-1]=histomap[index][id].tdac->GetBinContent(i,j); + else if (conf3){ + int chip=(i-1)/FEI3::Frontend::N_COLS; + int col=(i-1)%FEI3::Frontend::N_COLS; + int row=j-1; + conf3->FEConfig[chip].FETrims.dacThresholdTrim[row][col]=histomap[index][id].tdac->GetBinContent(i,j); + } + if(fabs(val[index]-target)>BAD_THRESHOLD)bad->SetBinContent(i,j,1); + } + } + TF1 gauss("gauss", "gaus", 100, 10000); + gauss.SetParameter(0, threshdist->GetMaximum()); + gauss.SetParameter(1, threshdist->GetMaximumBin()*threshdist->GetBinWidth(1)); + thresh1d->Fit(&gauss,"q", "", 100, 10000); + anfile->cd(); + mean->Write(); + mean->SetDirectory(gDirectory); + diff2d->Write(); + diff2d->SetDirectory(gDirectory); + diff1d->Write(); + diff1d->SetDirectory(gDirectory); + tdac->Write(); + tdac->SetDirectory(gDirectory); + bad->Write(); + bad->SetDirectory(gDirectory); + threshdist->Write(); + threshdist->SetDirectory(gDirectory); + thresh1d->Write(); + thresh1d->SetDirectory(gDirectory); + m_fw->writeDacFile(Form("%sTdacs_Mod_%d", m_fw->getPath(anfile).c_str(), id), tdac); + if(trims) writeFEI4Config(anfile, runno); + if(conf3) writeFEI3Config(anfile, runno); + } + if(configUpdate())writeTopFile(cfg, anfile, runno); + delete [] histomap; + delete [] val; +} + diff --git a/rce/rcecalib/analysis/TdacAnalysis.hh b/rce/rcecalib/analysis/TdacAnalysis.hh new file mode 100644 index 00000000..0c8ec228 --- /dev/null +++ b/rce/rcecalib/analysis/TdacAnalysis.hh @@ -0,0 +1,33 @@ +#ifndef TDACANALYSIS_HH +#define TDACANALYSIS_HH + +#include "rcecalib/analysis/CalibAnalysis.hh" +#include "rcecalib/analysis/CfgFileWriter.hh" +#include <map> + +class ConfigGui; +class TFile; +class TH2; +class TH1D; + +namespace RCE{ + class PixScan; +} +namespace{ + struct hdata{ + TH2* mean; + TH2* tdac; + }; +} + +class TdacAnalysis: public CalibAnalysis{ +public: + TdacAnalysis(CfgFileWriter* fw): CalibAnalysis(), m_fw(fw){} + ~TdacAnalysis(){delete m_fw;} + void analyze(TFile* file, TFile* anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]); +private: + CfgFileWriter* m_fw; +}; + + +#endif diff --git a/rce/rcecalib/analysis/TdacFastAnalysis.cc b/rce/rcecalib/analysis/TdacFastAnalysis.cc new file mode 100644 index 00000000..4c7b74ea --- /dev/null +++ b/rce/rcecalib/analysis/TdacFastAnalysis.cc @@ -0,0 +1,124 @@ +#include "rcecalib/analysis/TdacFastAnalysis.hh" +#include "rcecalib/server/PixScan.hh" +#include "rcecalib/config/FEI3/Frontend.hh" + +#include <TFile.h> +#include <TH2.h> +#include <TH2D.h> +#include <TH1.h> +#include <TKey.h> +#include <boost/regex.hpp> +#include <iostream> +#include <string> +#include <sstream> +#include "TH1D.h" +#include "TF1.h" +#include "TStyle.h" + +namespace{ + const double BAD_THRESHOLD=150; +} + + +void TdacFastAnalysis::analyze(TFile* file, TFile *anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]){ + int repetitions = scan->getRepetitions(); + double targetEff = 0.5; + file->cd(); + TKey *key; + char subdir[128]; + char name[128]; + char title[128]; + int binsx=0, binsy=0; + size_t numvals=scan->getLoopVarValues(1).size(); + std::map<int, hdatafast> *histomap=new std::map<int, hdatafast>[numvals]; + double *val=new double[numvals]; + for (size_t i=0;i<numvals;i++){ + sprintf(subdir, "loop1_%d", i); + file->cd(subdir); // TDAC steps + TIter nextkey(gDirectory->GetListOfKeys()); // histos + while ((key=(TKey*)nextkey())) { + boost::regex re("_(\\d+)_Occupancy_Point_000"); + boost::cmatch matches; + if(boost::regex_search(key->GetName(), matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + int lnm=strtol(match.c_str(),0,10); + char tdachistoname[128]; + sprintf (tdachistoname, "TDAC_settings_Mod_%d_it_%d", lnm, i); + TH2* histo = (TH2*)key->ReadObj(); + histo->SetMinimum(0); histo->SetMaximum(repetitions); + TH2* tdachisto=(TH2*)gDirectory->Get(tdachistoname); + assert(tdachisto); + histomap[i][lnm].occupancy=histo; + histomap[i][lnm].tdac=tdachisto; + binsx=histo->GetNbinsX(); + binsy=histo->GetNbinsY(); + } + } + } + for(std::map<int, hdatafast>::iterator it=histomap[0].begin();it!=histomap[0].end();it++){ + int id=it->first; + float pct = 100; + sprintf(name, "BestOcc_Mod_%d", id); + sprintf(title, "Best Occupancy Module %d at %s", id, findFieldName(cfg, id)); + TH2F* occBest=new TH2F(name, title, binsx, 0, binsx, binsy, 0, binsy); + occBest->SetMinimum(0); occBest->SetMaximum(pct); + occBest->GetXaxis()->SetTitle("Column"); + occBest->GetYaxis()->SetTitle("Row"); + occBest->GetZaxis()->SetTitle("Occupancy[%]"); + + sprintf(name, "BestTdac_Mod_%d", id); + sprintf(title, "Best Tdacs Module %d at %s", id, findFieldName(cfg, id)); + TH2F* tdac=new TH2F(name, title, binsx, 0, binsx, binsy, 0, binsy); + tdac->GetXaxis()->SetTitle("Column"); + tdac->GetYaxis()->SetTitle("Row"); + tdac->GetZaxis()->SetTitle("Tdac"); + + struct ipc::PixelFEI4Trims *trims=0; + struct ipc::PixelModuleConfig *conf3=0; + ipc::PixelFEI4AConfig* confa=findFEI4AConfig(cfg, id); + if(confa)trims=&confa->FETrims; + else{ + ipc::PixelFEI4BConfig* confb=findFEI4BConfig(cfg, id); + if(confb)trims=&confb->FETrims; + else conf3=findFEI3Config(cfg, id); + } + for (int i=1;i<=occBest->GetNbinsX();i++){ + for(int j=1;j<=occBest->GetNbinsY();j++){ + double bestval = 10*targetEff; // must be larger than 1 (with possibilty of double hit) + int index=0; + for(size_t k=0;k<numvals;k++){ + val[k] = histomap[k][id].occupancy->GetBinContent(i,j) / repetitions; + if(fabs(val[k]-targetEff)<bestval){ + index=k; + bestval=fabs(val[k]-targetEff); + } + } + occBest->SetBinContent(i,j,pct*val[index]); + tdac->SetBinContent(i,j,histomap[index][id].tdac->GetBinContent(i,j)); + if(trims)trims->dacThresholdTrim[i-1][j-1]=histomap[index][id].tdac->GetBinContent(i,j); + else if (conf3){ + int chip=(i-1)/FEI3::Frontend::N_COLS; + int col=(i-1)%FEI3::Frontend::N_COLS; + int row=j-1; + conf3->FEConfig[chip].FETrims.dacThresholdTrim[row][col]=histomap[index][id].tdac->GetBinContent(i,j); + } + } + } + + anfile->cd(); + occBest->Write(); + occBest->SetDirectory(gDirectory); + + tdac->Write(); + tdac->SetDirectory(gDirectory); + + m_fw->writeDacFile(Form("%sTdacs_Mod_%d", m_fw->getPath(anfile).c_str(), id), tdac); + if(trims) writeFEI4Config(anfile, runno); + if(conf3) writeFEI3Config(anfile, runno); + } + if(configUpdate())writeTopFile(cfg, anfile, runno); + delete [] histomap; + delete [] val; +} + diff --git a/rce/rcecalib/analysis/TdacFastAnalysis.hh b/rce/rcecalib/analysis/TdacFastAnalysis.hh new file mode 100644 index 00000000..08d8d5e5 --- /dev/null +++ b/rce/rcecalib/analysis/TdacFastAnalysis.hh @@ -0,0 +1,33 @@ +#ifndef TDACFASTANALYSIS_HH +#define TDACFASTANALYSIS_HH + +#include "rcecalib/analysis/CalibAnalysis.hh" +#include "rcecalib/analysis/CfgFileWriter.hh" +#include <map> + +class ConfigGui; +class TFile; +class TH2; +class TH1D; + +namespace RCE{ + class PixScan; +} +namespace{ + struct hdatafast{ + TH2* occupancy; + TH2* tdac; + }; +} + +class TdacFastAnalysis: public CalibAnalysis{ +public: + TdacFastAnalysis(CfgFileWriter* fw): CalibAnalysis(), m_fw(fw){} + ~TdacFastAnalysis(){delete m_fw;} + void analyze(TFile* file, TFile* anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]); +private: + CfgFileWriter* m_fw; +}; + + +#endif diff --git a/rce/rcecalib/analysis/TemperatureAnalysis.cc b/rce/rcecalib/analysis/TemperatureAnalysis.cc new file mode 100644 index 00000000..e98ae253 --- /dev/null +++ b/rce/rcecalib/analysis/TemperatureAnalysis.cc @@ -0,0 +1,106 @@ +#include "rcecalib/analysis/TemperatureAnalysis.hh" +#include "rcecalib/server/PixScan.hh" + +#include <TFile.h> +#include <TH2.h> +#include <TH2D.h> +#include <TH1.h> +#include <TKey.h> +#include <boost/regex.hpp> +#include <iostream> +#include <fstream> +#include <math.h> + +using namespace RCE; + +void TemperatureAnalysis::analyze(TFile* file, TFile *anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]){ + std::cout<<"Temperature analysis"<<std::endl; + std::vector<float> loopVar=scan->getLoopVarValues(0); + size_t numvals=loopVar.size(); + if(numvals<2){ + std::cout<<"Need at least two values instead of "<<numvals<<std::endl; + return; + } + float a[2]; + for(int i=0;i<2;i++){ + if(loopVar[i]==1)a[i]=1; + else if(loopVar[i]==2)a[i]=10; + else if(loopVar[i]==3)a[i]=1000; + else{ + a[i]=-1; + std::cout<<"Bad setup for temperature scan"<<std::endl; + } + } + float m=a[1]/a[0]; + if(m<1)m=1./m; + std::cout<<"Factor is "<<m<<std::endl; + TIter nextkey(file->GetListOfKeys()); + TKey *key; + boost::regex re("_(\\d+)_Voltage"); + std::vector<std::string> pos; + std::vector<float> temps; + std::vector<float> errs; + while ((key=(TKey*)nextkey())) { + std::string name(key->GetName()); + std::string title(key->GetTitle()); + boost::cmatch matches; + if(boost::regex_search(name.c_str(), matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + int id=strtol(match.c_str(),0,10); + std::string match2=addPosition(name.c_str(), cfg).substr(0,5); + pos.push_back(match2); + TH1D* mhis=new TH1D(Form("Temperature_Mod_%d",id), Form("Temperature Mod %d at %s", id, findFieldName(cfg, id)), 1,0,1); + mhis->GetYaxis()->SetTitle("Temperature (C)"); + TH1* histo = (TH1*)key->ReadObj(); + float val1=histo->GetBinContent(1); + float err1=sqrt(histo->GetBinError(1)); + float val2=histo->GetBinContent(2); + float err2=sqrt(histo->GetBinError(2)); + float volttoadc=1.013; + float fact=1.6e-19/1.38e-23/logf(m)/1000./volttoadc; + float temp=(val2-val1)*fact; + if(temp<0)temp=-temp; + temp-=273.15; + float err=sqrt(err1*err1+err2*err2)*fact; + mhis->SetBinContent(1,temp); + mhis->SetBinError(1,err); + std::cout<<"FE at "<<match2<<" has a temperature of "<<temp<<"+-"<<err<<" degrees Celsius."<<std::endl; + temps.push_back(temp); + errs.push_back(err); + anfile->cd(); + mhis->Write(); + mhis->SetDirectory(gDirectory); + delete histo; + } + } + TH1D* mhis[4]; + mhis[0]=new TH1D(Form("1-StavetempsA"), Form("Frontend Temperatures A side"), 16, 0, 16); + mhis[1]=new TH1D(Form("1-StavetempsC"), Form("Frontend Temperatures C side"), 16, 0, 16); + mhis[2]=new TH1D(Form("2-StavetempsA"), Form("Frontend Temperatures A side (2)"), 16, 0, 16); + mhis[3]=new TH1D(Form("2-StavetempsC"), Form("Frontend Temperatures C side (2)"), 16, 0, 16); + char position[10]; + for(int i=0;i<4;i++){ //half stave + if(i%2==0)position[0]='A'; + else position[0]='C'; + mhis[i]->GetYaxis()->SetTitle("Temperature (C)"); + for(int j=1;j<=8;j++){ //module + for(int k=1;k<=2;k++){ //FE + sprintf(&position[1], "%d-%d", j,k); + int bin=(j-1)*2+k; + mhis[i]->GetXaxis()->SetBinLabel(bin,position); + for(size_t l=0;l<pos.size();l++){ + if(std::string(position)==pos[l].substr(1,4) && + pos[l].substr(0,1)==Form("%d", i/2+1)){ + mhis[i]->SetBinContent(bin, temps[l]); + mhis[i]->SetBinError(bin, errs[l]); + } + } + } + } + anfile->cd(); + mhis[i]->Write(); + mhis[i]->SetDirectory(gDirectory); + } +} + diff --git a/rce/rcecalib/analysis/TemperatureAnalysis.hh b/rce/rcecalib/analysis/TemperatureAnalysis.hh new file mode 100644 index 00000000..94482b34 --- /dev/null +++ b/rce/rcecalib/analysis/TemperatureAnalysis.hh @@ -0,0 +1,21 @@ +#ifndef TEMPERATUREANALYSIS_HH +#define TEMPERATUREANALYSIS_HH + +#include "rcecalib/analysis/CalibAnalysis.hh" + +class ConfigGui; +class TFile; +class TH2D; +namespace RCE{ + class PixScan; +} + +class TemperatureAnalysis: public CalibAnalysis{ +public: + TemperatureAnalysis(): CalibAnalysis(){} + ~TemperatureAnalysis(){} + void analyze(TFile* file, TFile* anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]); +}; + + +#endif diff --git a/rce/rcecalib/analysis/ThresholdAnalysis.cc b/rce/rcecalib/analysis/ThresholdAnalysis.cc new file mode 100644 index 00000000..6a1e230b --- /dev/null +++ b/rce/rcecalib/analysis/ThresholdAnalysis.cc @@ -0,0 +1,191 @@ +#include "rcecalib/analysis/ThresholdAnalysis.hh" +#include "rcecalib/server/PixScan.hh" + +#include <TFile.h> +#include <TH2.h> +#include <TH2D.h> +#include <TH1.h> +#include <TKey.h> +#include <boost/regex.hpp> +#include <iostream> +#include <fstream> +#include "TH1D.h" +#include "TF1.h" +#include "TStyle.h" + + +void ThresholdAnalysis::analyze(TFile* file, TFile *anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]){ + std::cout<<"Threshold analysis"<<std::endl; + unsigned int numval=scan->getLoopVarValues(0).size(); + gStyle->SetOptFit(10); + //gStyle->SetOptStat(0); + std::map<int, TH1D*> histmap; + TIter nextkey(gDirectory->GetListOfKeys()); // histograms + TKey *key; + std::vector<std::string> pos; + std::vector<float> threshs; + std::vector<float> thresherrs; + std::vector<float> sigmas; + std::vector<float> sigmaerrs; + while ((key=(TKey*)nextkey())) { + file->cd(); + std::string hname(key->GetName()); + boost::cmatch matches; + boost::regex re("_(\\d+)_Mean"); + boost::regex re2("Mean"); + char name[128]; + char title[128]; + if(boost::regex_search(hname.c_str(), matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + int id=strtol(match.c_str(),0,10); + std::string match2=addPosition(hname.c_str(), cfg).substr(0,5); + pos.push_back(match2); + std::string chi2HistoName = boost::regex_replace (hname, re2, "ChiSquare"); + std::string sigmaHistoName = boost::regex_replace (hname, re2, "Sigma"); + TH2* histo = (TH2*)key->ReadObj(); + TH2* chi2Histo=(TH2*)gDirectory->Get(chi2HistoName.c_str()); + TH2* sigmahisto=(TH2*)gDirectory->Get(sigmaHistoName.c_str()); + assert(chi2Histo!=0); + assert(sigmahisto!=0); + int binsx=histo->GetNbinsX(); + int binsy=histo->GetNbinsY(); + sprintf(name, "thresh2d_Mod_%d", id); + sprintf(title, "Thresholds Module %d at %s", id, findFieldName(cfg, id)); + TH2F* thresh2d=new TH2F(name, title, binsx, 0, binsx, binsy, 0, binsy); + thresh2d->GetXaxis()->SetTitle("Column"); + thresh2d->GetYaxis()->SetTitle("Row"); + sprintf(name, "thresh1d_Mod_%d", id); + sprintf(title, "Thresholds Module %d at %s", id, findFieldName(cfg, id)); + int nbins=binsx*binsy; + TH1F* thresh1d=new TH1F(name, title, nbins, 0, (float)nbins); + thresh1d->GetXaxis()->SetTitle("Channel"); + thresh1d->SetOption("p9"); + sprintf(name, "sigma1d_Mod_%d", id); + sprintf(title, "Sigma Module %d at %s", id, findFieldName(cfg, id)); + TH1F* sigma1d=new TH1F(name, title, nbins, 0, (float)nbins); + sigma1d->GetXaxis()->SetTitle("Channel"); + sigma1d->SetOption("p9"); + sprintf(name, "threshdist_Mod_%d", id); + sprintf(title, "Threshold distribution Module %d at %s", id, findFieldName(cfg, id)); + TH1F* threshdist=new TH1F(name, title, 600, 0, 6000); + threshdist->GetXaxis()->SetTitle("Threshold"); + sprintf(name, "sigmadist_Mod_%d", id); + sprintf(title, "Sigma distribution Module %d at %s", id, findFieldName(cfg, id)); + TH1F* sigmadist=new TH1F(name, title, 500, 0, 1000); + sigmadist->GetXaxis()->SetTitle("Sigma"); + sprintf(name, "BadPixels_Mod_%d", id); + sprintf(title, "Bad Pixels Module %d at %s", id, findFieldName(cfg, id)); + TH2F* bad=new TH2F(name, title, binsx, 0, binsx, binsy, 0, binsy); + bad->GetXaxis()->SetTitle("Column"); + bad->GetYaxis()->SetTitle("Row"); + TH1D* hits1d=new TH1D(Form("HitsPerBin_Mod_%d", id), + Form("Hits per bin Mod %d at %s", id, findFieldName(cfg, id)), + numval, -.5, (float)numval-.5) ; + hits1d->GetXaxis()->SetTitle("Scan Point"); + unsigned char (*masks)[ipc::IPC_N_I4_PIXEL_ROWS]=0; + ipc::PixelFEI4AConfig* conf=findFEI4AConfig(cfg, id); + if(conf)masks=conf->FEMasks; + else { + ipc::PixelFEI4BConfig* confb=findFEI4BConfig(cfg, id); + if(confb)masks=confb->FEMasks; + } + if(masks && scan->clearMasks()==true)clearFEI4Masks(masks); + + for (int i=1;i<=histo->GetNbinsX();i++){ + for(int j=1;j<=histo->GetNbinsY();j++){ + thresh2d->SetBinContent(i,j,histo->GetBinContent(i,j)); + thresh1d->SetBinContent((i-1)*histo->GetNbinsY()+j, histo->GetBinContent(i,j)); + threshdist->Fill(histo->GetBinContent(i,j)); + sigma1d->SetBinContent((i-1)*histo->GetNbinsY()+j, sigmahisto->GetBinContent(i,j)); + sigmadist->Fill(sigmahisto->GetBinContent(i,j)); + if(chi2Histo->GetBinContent(i,j)==0){ + bad->SetBinContent(i,j,1); + if(masks){ + masks[i-1][j-1]&=0xfe; //reset bit 0 (enable) + masks[i-1][j-1]|=0x8; //reset bit 3 (hitbus) + } + } + } + } + TF1 gauss("gauss", "gaus", 100, 10000); + gauss.SetParameter(0, threshdist->GetMaximum()); + gauss.SetParameter(1, threshdist->GetMaximumBin()*threshdist->GetBinWidth(1)); + threshdist->Fit(&gauss,"q", "", 100, 10000); + sigmadist->Fit("gaus","q"); + threshs.push_back(threshdist->GetMean()); + thresherrs.push_back(threshdist->GetRMS()); + sigmas.push_back(sigmadist->GetMean()); + sigmaerrs.push_back(sigmadist->GetRMS()); + + for(unsigned int k=0;k<numval;k++){ + boost::regex re2("Mean"); + std::string histoName = boost::regex_replace (hname, re2, Form("Occupancy_Point_%03d", k)); + TH2* occHisto=(TH2*)gDirectory->Get(histoName.c_str()); + if(occHisto==0){ + std::cout<<"No Occupancy histograms found. Won't fill 1-d hit histo."<<std::endl; + break; + } + hits1d->SetBinContent(k+1, occHisto->GetSumOfWeights()); + } + + if(masks) writeFEI4Config(anfile, runno); + anfile->cd(); + thresh2d->Write(); + thresh2d->SetDirectory(gDirectory); + thresh1d->Write(); + thresh1d->SetDirectory(gDirectory); + threshdist->Write(); + threshdist->SetDirectory(gDirectory); + sigma1d->Write(); + sigma1d->SetDirectory(gDirectory); + sigmadist->Write(); + sigmadist->SetDirectory(gDirectory); + bad->Write(); + bad->SetDirectory(gDirectory); + hits1d->Write(); + hits1d->SetDirectory(gDirectory); + } + } + TH1D* mhis[2]; + mhis[0]=new TH1D(Form("1-Thresholds"), Form("Thresholds 1st stave"), 32, 0, 32); + mhis[1]=new TH1D(Form("2-Thresholds"), Form("Thresholds 2nd stave"), 32, 0, 32); + TH1D* shis[2]; + shis[0]=new TH1D(Form("1-Sigma"), Form("Sigma 1st stave"), 32, 0, 32); + shis[1]=new TH1D(Form("2-Sigma"), Form("Sigma 2nd stave"), 32, 0, 32); + char position[10]; + for(int i=0;i<4;i++){ //half stave + if(i%2==0)position[0]='A'; + else position[0]='C'; + //mhis[i]->GetYaxis()->SetTitle("Threshold (e)"); + for(int j=1;j<=8;j++){ //module + for(int k=1;k<=2;k++){ //FE + sprintf(&position[1], "%d-%d", j,k); + int bin=0; + if(i%2==0)bin=17-((j-1)*2+k); // A side + else bin=16+(j-1)*2+k; + mhis[i/2]->GetXaxis()->SetBinLabel(bin,position); + shis[i/2]->GetXaxis()->SetBinLabel(bin,position); + for(size_t l=0;l<pos.size();l++){ + if(std::string(position)==pos[l].substr(1,4) && + pos[l].substr(0,1)==Form("%d", i/2+1)){ + mhis[i/2]->SetBinContent(bin, threshs[l]); + mhis[i/2]->SetBinError(bin, thresherrs[l]); + shis[i/2]->SetBinContent(bin, sigmas[l]); + shis[i/2]->SetBinError(bin, sigmaerrs[l]); + } + } + } + } + if(i%2==1){ + anfile->cd(); + mhis[i/2]->Write(); + mhis[i/2]->SetDirectory(gDirectory); + shis[i/2]->Write(); + shis[i/2]->SetDirectory(gDirectory); + } + } + + if(configUpdate())writeTopFile(cfg, anfile, runno); + +} diff --git a/rce/rcecalib/analysis/ThresholdAnalysis.hh b/rce/rcecalib/analysis/ThresholdAnalysis.hh new file mode 100644 index 00000000..b4b41597 --- /dev/null +++ b/rce/rcecalib/analysis/ThresholdAnalysis.hh @@ -0,0 +1,24 @@ +#ifndef THRESHOLDANALYSIS_HH +#define THRESHOLDANALYSIS_HH + +#include "rcecalib/analysis/CalibAnalysis.hh" +#include <map> + +class ConfigGui; +class TFile; +class TH2; +class TH1D; + +namespace RCE{ + class PixScan; +} + +class ThresholdAnalysis: public CalibAnalysis{ +public: + ThresholdAnalysis(): CalibAnalysis(){} + ~ThresholdAnalysis(){} + void analyze(TFile* file, TFile* anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]); +}; + + +#endif diff --git a/rce/rcecalib/analysis/TimeWalkAnalysis.cc b/rce/rcecalib/analysis/TimeWalkAnalysis.cc new file mode 100644 index 00000000..26ff39c7 --- /dev/null +++ b/rce/rcecalib/analysis/TimeWalkAnalysis.cc @@ -0,0 +1,237 @@ +#include "rcecalib/analysis/TimeWalkAnalysis.hh" +#include "rcecalib/server/PixScan.hh" + +#include <TFile.h> +#include <TStyle.h> +#include <TH2.h> +#include <TH2D.h> +#include <TH1.h> +#include <TF1.h> +#include <TKey.h> +#include <boost/regex.hpp> +#include <iostream> +#include <fstream> + +namespace{ + const double threshold=0; +} +using namespace RCE; + +void TimeWalkAnalysis::analyze(TFile* file, TFile *anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]){ + //unsigned int numval=scan->getLoopVarValues(0).size(); + gStyle->SetOptFit(10); + gStyle->SetOptStat(0); + std::cout<<"TimeWalk analysis"<<std::endl; + + const int totalScans = scan->getLoopVarValues(1).size(); + + float xVals[totalScans]; + float yVals[totalScans]; + + + TH1D* t0mean[totalScans]; + // TH1D* t0sigma[totalScans]; + + TH1D* histoTW(0); + + + float xMin = scan->getLoopVarValues(1).at(0); + float xMax = scan->getLoopVarValues(1).at(totalScans-1); + + if(xMax<xMin){ + float xtemp = xMax; + xMax = xMin; + xMin = xtemp; + } + + histoTW = new TH1D(Form("TimeWalk"), Form("Time Walk integrated over all pixels"), 50, xMin - 1, xMax + 1); + histoTW->GetXaxis()->SetTitle("N(e^{-})"); + histoTW->GetYaxis()->SetTitle("t0 (strobe delay counts)"); + + histoTW->SetOption("P"); + histoTW->SetMarkerStyle(2); + histoTW->SetMarkerSize(2); + + + + + //loop over the different T0 scans + for(int iScan = 0; iScan<totalScans; iScan++){ + + file->cd(Form("loop1_%d",iScan)); + + + TIter nextkey(gDirectory->GetListOfKeys()); + TKey *key; + boost::regex re("_(\\d+)_Mean"); + boost::regex re2("Mean"); + while ((key=(TKey*)nextkey())) { + std::string name(key->GetName()); + boost::cmatch matches; + if(boost::regex_search(name.c_str(), matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + + + // std::cout<<"match = "<<match.c_str()<<std::endl; + int id=strtol(match.c_str(),0,10); + + // std::cout<<"id = "<<id<<std::endl; + + std::string sigmaHistoName = boost::regex_replace (name, re2, "Sigma"); + + struct ipc::PixelFECalibFEI4 *fecalib=0; + ipc::PixelFEI4AConfig* confa=findFEI4AConfig(cfg, id); + if(confa)fecalib=&confa->FECalib; + else{ + ipc::PixelFEI4BConfig* confb=findFEI4BConfig(cfg, id); + if(confb)fecalib=&confb->FECalib; + } + + TH2* histo = (TH2*)key->ReadObj(); + TH2* sigmaHisto=(TH2*)gDirectory->Get(sigmaHistoName.c_str()); + assert(sigmaHisto); + + + + //Get histogram ranges + float maxval[2] = {0,0}; + float minval[2] = {1e8, 1e8}; + float vals[2] = {0,0}; + + for (int i=1;i<=histo->GetNbinsX();i++){ + for(int j=1;j<=histo->GetNbinsY();j++){ + + vals[0] = histo->GetBinContent(i, j); + vals[1] = sigmaHisto->GetBinContent(i, j); + + for(int kpar = 0; kpar<2; kpar++){ + if(vals[kpar]>maxval[kpar]){ + maxval[kpar] = vals[kpar]; + } + if(vals[kpar]<minval[kpar]&&vals[kpar]>0){ + minval[kpar] = vals[kpar]; + } + } + + } + } + + // TH1D* t0sigma[2]; + + + t0mean[iScan] =new TH1D(Form("T0_%d_Mod_%d",iScan,id), + Form("T0 for each pixel in Mod %d at %s (Scan %d)" + , id, findFieldName(cfg, id), iScan), + 50, minval[0]-1, maxval[0]+1); + // t0sigma[iScan] =new TH1D(Form("Sigma_%d_Mod_%d",iScan,id), Form("T0 S-CURVE sigma for each pixel in Mod %d (Scan %d)", id, iScan), 50, minval[1]-1, maxval[1]+1); + + t0mean[iScan]->GetXaxis()->SetTitle("t0 (strobe delay counts)"); + // t0sigma[iScan]->GetXaxis()->SetTitle("t0 S-Curve sigma (strobe delay counts)"); + + + for (int i=1;i<=histo->GetNbinsX();i++){ + for(int j=1;j<=histo->GetNbinsY();j++){ + + float val=0; + + if(histo->GetBinContent(i, j)!=0 ){ + val = histo->GetBinContent(i, j); + t0mean[iScan]->Fill(val); + } + + + // if(sigmaHisto->GetBinContent(i, j)!=0 ){ + // val = sigmaHisto->GetBinContent(i, j); + // t0sigma[iScan]->Fill(val); + // } + + } + + } + + t0mean[iScan]->Fit("gaus"); + yVals[iScan] = t0mean[iScan]->GetFunction("gaus")->GetParameter(1); + std::cout<<"T0 for module "<<id<<" for scan "<<iScan<<" is "<<yVals[iScan]<<std::endl; + + + + + xVals[iScan] = scan->getLoopVarValues(1).at(iScan); + + // std::cout<<"at scan "<<iScan<<" , x = "<<xVals[iScan]<<std::endl; + + + // for (int i=1;i<=histo->GetNbinsX();i++){ + // for(int j=1;j<=histo->GetNbinsY();j++){ + + // float val=0; + + // if(histo->GetBinContent(i, j)!=0 ){ + // val = histo->GetBinContent(i, j)*convFactor; + // t0mean_ns[0]->Fill(val); + // } + // if(histo2->GetBinContent(i, j)!=0 ){ + // val = histo2->GetBinContent(i, j)*convFactor; + // t0mean_ns[1]->Fill(val); + // } + + // if(sigmaHisto->GetBinContent(i, j)!=0 ){ + // val = sigmaHisto->GetBinContent(i, j)*convFactor; + // t0sigma_ns[0]->Fill(val); + // } + // if(sigmaHisto2->GetBinContent(i, j)!=0 ){ + // val = sigmaHisto2->GetBinContent(i, j)*convFactor; + // t0sigma_ns[1]->Fill(val); + // } + + // } + + // } + + + delete histo; + anfile->cd(); + + t0mean[iScan]->Write(); + t0mean[iScan]->SetDirectory(gDirectory); +// t0sigma[scan]->Write(); +// t0sigma[scan]->SetDirectory(gDirectory); + +// t0mean_ns[scan]->Write(); +// t0mean_ns[scan]->SetDirectory(gDirectory); +// t0sigma_ns[scan]->Write(); +// t0sigma_ns[scan]->SetDirectory(gDirectory); + file->cd(Form("loop1_%d",iScan)); + + } + + } + + } //end loop over iScan + + + for(int iScan = 0; iScan<totalScans; iScan++){ + + histoTW->Fill(xVals[iScan], yVals[iScan]); + + } + anfile->cd(); + histoTW->Write(); + histoTW->SetDirectory(gDirectory); + +} + + +void TimeWalkAnalysis::fillHit1d(std::string &name, TH1* hits1d, unsigned numval){ +for(unsigned int k=0;k<numval;k++){ + boost::regex re2("Mean"); + std::string histoName = boost::regex_replace (name, re2, Form("Occupancy_Point_%03d", k)); + TH2* occHisto=(TH2*)gDirectory->Get(histoName.c_str()); + if(occHisto==0){ + std::cout<<"No Occupancy histograms found. Won't fill 1-d hit histo."<<std::endl; + break; + } + hits1d->SetBinContent(k+1, occHisto->GetSumOfWeights()); + } +} diff --git a/rce/rcecalib/analysis/TimeWalkAnalysis.hh b/rce/rcecalib/analysis/TimeWalkAnalysis.hh new file mode 100644 index 00000000..0e0bfddb --- /dev/null +++ b/rce/rcecalib/analysis/TimeWalkAnalysis.hh @@ -0,0 +1,23 @@ +#ifndef TIMEWALKANALYSIS_HH +#define TIMEWALKANALYSIS_HH + +#include "rcecalib/analysis/CalibAnalysis.hh" + +class ConfigGui; +class TFile; +class TH2D; +class TH1; +namespace RCE{ + class PixScan; +} + +class TimeWalkAnalysis: public CalibAnalysis{ +public: + TimeWalkAnalysis(): CalibAnalysis(){} + ~TimeWalkAnalysis(){} + void analyze(TFile* file, TFile* anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]); + void fillHit1d(std::string &name, TH1* hits1d, unsigned numval); +}; + + +#endif diff --git a/rce/rcecalib/analysis/TotAnalysis.cc b/rce/rcecalib/analysis/TotAnalysis.cc new file mode 100644 index 00000000..fa30aa55 --- /dev/null +++ b/rce/rcecalib/analysis/TotAnalysis.cc @@ -0,0 +1,169 @@ +#include "rcecalib/analysis/TotAnalysis.hh" +#include <boost/regex.hpp> + +#include <TFile.h> +#include <TH2.h> +#include <TH2D.h> +#include <TH1D.h> +#include <TKey.h> +#include <TStyle.h> +#include <iostream> +#include <iomanip> +#include <fstream> +#include <cmath> + +void TotAnalysis::analyze(TFile* file, TFile *anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]){ + gStyle->SetOptFit(111); + printf("Begin TOT Analysis\n"); + std::map<int, odata> histomap; + TKey *key; + std::vector<std::string> pos; + std::vector<float> tots; + std::vector<float> toterrs; + std::vector<float> sigmas; + std::vector<float> sigmaerrs; + + int binsx=0, binsy=0; + TIter nextkey(gDirectory->GetListOfKeys()); // TDAC settings + while ((key=(TKey*)nextkey())) { + std::string name(key->GetName()); + boost::regex re(Form("_(\\d+)_Occupancy_Point_%03d", 0)); + boost::cmatch matches; + if(boost::regex_search(name.c_str(), matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + int lnm=strtol(match.c_str(),0,10); + std::string match2=addPosition(name.c_str(), cfg).substr(0,5); + pos.push_back(match2); + histomap[lnm].occ = (TH2*)key->ReadObj(); + boost::regex re2("Occupancy"); + std::string totHistoName = boost::regex_replace (name, re2, "ToT"); + histomap[lnm].tot=(TH2*)gDirectory->Get(totHistoName.c_str()); + std::string tot2HistoName = boost::regex_replace (name, re2, "ToT2"); + histomap[lnm].tot2=(TH2*)gDirectory->Get(tot2HistoName.c_str()); + assert(histomap[lnm].tot2); + binsx=histomap[lnm].tot2->GetNbinsX(); + binsy=histomap[lnm].tot2->GetNbinsY(); + } + } + for(std::map<int, odata>::iterator it=histomap.begin();it!=histomap.end();it++){ + int id=it->first; + int max=15; + if(findFEType(cfg, id)=="FEI3")max=63; + TH2D* ahis = new TH2D(Form("ToT_Mean_Mod_%i", id), + Form("ToT Mean Mod %d at %s", id, findFieldName(cfg, id)), + binsx,0,binsx,binsy,0,binsy); + ahis->GetXaxis()->SetTitle("Column"); + ahis->GetYaxis()->SetTitle("Row"); + ahis->SetMinimum(0); + ahis->SetMaximum(max+1); + TH2D* shis = new TH2D(Form("ToT_Sigma_Mod_%i", id), + Form("ToT Sigma Mod %d at %s", id, findFieldName(cfg, id)), + binsx,0,binsx,binsy,0,binsy); + ahis->GetXaxis()->SetTitle("Column"); + ahis->GetYaxis()->SetTitle("Row"); + TH2D* badpix = new TH2D(Form("BadPixels_Mod_%i", id), Form("Bad Pixel Map Mod %d", id),binsx,0,binsx,binsy,0,binsy); + badpix->GetXaxis()->SetTitle("Column"); + badpix->GetYaxis()->SetTitle("Row"); + TH1D* channel = new TH1D(Form("ToT_Mean_Channel_Mod_%i", id), + Form("ToT Mean Mod %d at %s", id, findFieldName(cfg, id)), + binsx*binsy,0,binsx*binsy); + channel->GetXaxis()->SetTitle("Channel"); + channel->SetOption("p9"); + channel->SetMinimum(0); + channel->SetMaximum(max+1); + TH1D* schannel = new TH1D(Form("ToT_Sigma_Channel_Mod_%i", id), + Form("ToT Sigma Mod %d at %s", id, findFieldName(cfg, id)), + binsx*binsy,0,binsx*binsy); + schannel->GetXaxis()->SetTitle("Channel"); + schannel->SetOption("p9"); + TH1D* dist=new TH1D(Form("ToT_Mean_Dist_Mod_%i", id), + Form("ToT Distribution Mod %d at %s", id, findFieldName(cfg, id)), + 100, 0, max); + dist->GetXaxis()->SetTitle("ToT"); + TH1D* sdist=new TH1D(Form("ToT_Sigma_Dist_Mod_%i", id), + Form("ToT Sigma Distribution Mod %d at %s", id, findFieldName(cfg, id)), + 100, 0, 3); + sdist->GetXaxis()->SetTitle("ToT"); + TH2* occ_histo=histomap[id].occ; + TH2* tot_histo=histomap[id].tot; + TH2* tot2_histo=histomap[id].tot2; + for(int j = 1; j <= ahis->GetNbinsX(); j++){ + for(int k = 1; k <= ahis->GetNbinsY(); k++){ + //printf("Point %3i\n",i); + float nhits = occ_histo->GetBinContent(j,k); + float tot=0; + if(nhits != 0){ + tot = float(tot_histo->GetBinContent(j,k)) / nhits; + float tot2=tot2_histo->GetBinContent(j,k); + float sig=0; + if(tot2>0)sig=sqrt(tot2/nhits-tot*tot); + ahis->SetBinContent(j,k,tot); + shis->SetBinContent(j,k,sig); + channel->SetBinContent(k+(j-1)*binsy, tot); + schannel->SetBinContent(k+(j-1)*binsy, sig); + dist->Fill(tot); + sdist->Fill(sig); + } + else badpix->SetBinContent(j,k,1); + } + } + dist->Fit("gaus"); + tots.push_back(dist->GetMean()); + std::cout<<"Dist Mean value: "<<dist->GetMean()<<", Dist Err: "<<dist->GetRMS()<<"|| Module: "<<findFieldName(cfg,id)<<std::endl; + toterrs.push_back(dist->GetRMS()); + anfile->cd(); + ahis->Write(); + ahis->SetDirectory(gDirectory); + shis->Write(); + shis->SetDirectory(gDirectory); + badpix->Write(); + badpix->SetDirectory(gDirectory); + channel->Write(); + channel->SetDirectory(gDirectory); + schannel->Write(); + schannel->SetDirectory(gDirectory); + dist->Write(); + dist->SetDirectory(gDirectory); + sdist->Write(); + sdist->SetDirectory(gDirectory); + } + TH1D* mhis[2]; + mhis[0]=new TH1D(Form("1-Tots"), Form("Tots 1st stave"), 32, 0, 32); + mhis[1]=new TH1D(Form("2-Tots"), Form("Tots 2nd stave"), 32, 0, 32); + + char position[10]; + for(int i=0;i<4;i++){ //half stave + if(i%2==0)position[0]='A'; + else position[0]='C'; + //mhis[i]->GetYaxis()->SetTitle("Threshold (e)"); + for(int j=1;j<=8;j++){ //module + for(int k=1;k<=2;k++){ //FE + sprintf(&position[1], "%d-%d", j,k); + int bin=0; + if(i%2==0)bin=17-((j-1)*2+k); // A side + else bin=16+(j-1)*2+k; + mhis[i/2]->GetXaxis()->SetBinLabel(bin,position); + for(size_t l=0;l<pos.size();l++){ + if(std::string(position)==pos[l].substr(1,4) && + pos[l].substr(0,1)==Form("%d", i/2+1)){ + mhis[i/2]->SetBinContent(bin, tots[l]); + mhis[i/2]->SetBinError(bin, toterrs[l]); + + } + } + } + } + if(i%2==1){ + anfile->cd(); + mhis[i/2]->Write(); + mhis[i/2]->SetDirectory(gDirectory); + } + } + + + + + printf("Done Analysis\n"); +} + diff --git a/rce/rcecalib/analysis/TotAnalysis.hh b/rce/rcecalib/analysis/TotAnalysis.hh new file mode 100644 index 00000000..420364ae --- /dev/null +++ b/rce/rcecalib/analysis/TotAnalysis.hh @@ -0,0 +1,28 @@ +#ifndef TOT_ANALYSIS_HH +#define TOT_ANALYSIS_HH + +#include "rcecalib/analysis/CalibAnalysis.hh" +#include "rcecalib/analysis/CfgFileWriter.hh" +#include "rcecalib/server/PixScan.hh" + +class TFile; +class TH2; +namespace RCE{ + class PixScan; +} +class ConfigGui; + +class TotAnalysis: public CalibAnalysis{ +public: + struct odata{ + TH2* occ; + TH2* tot; + TH2* tot2; + }; + TotAnalysis(): CalibAnalysis(){} + ~TotAnalysis(){} + void analyze(TFile* file, TFile* anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]); +}; + + +#endif diff --git a/rce/rcecalib/analysis/TotCalibAnalysis.cc b/rce/rcecalib/analysis/TotCalibAnalysis.cc new file mode 100644 index 00000000..a0e4200f --- /dev/null +++ b/rce/rcecalib/analysis/TotCalibAnalysis.cc @@ -0,0 +1,165 @@ +#include "analysis/TotCalibAnalysis.hh" +#include "server/PixScan.hh" +#include "server/ConfigGui.hh" +#include "config/FEI3/Module.hh" +#include "config/FEI4/Module.hh" + +#include <TFile.h> +#include <TH2.h> +#include <TH2D.h> +#include <TH1.h> +#include <TF1.h> +#include <TCanvas.h> +#include <TKey.h> +#include <TMath.h> +#include <boost/regex.hpp> +#include <iostream> +#include <fstream> +#include "TH1D.h" +#include "TStyle.h" + +void TotCalibAnalysis::analyze(TFile* file, TFile *anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]){ + std::cout<<"TOT Calibration analysis running..."<<std::endl; + int repetitions = scan->getRepetitions(); + double targetEff = 0.5; + TKey* key; + char subdir[128]; + char name[128]; + char title[128]; + int binsx=0; + size_t numvals=scan->getLoopVarValues(1).size(); + std::map<int, int> idmap; + std::vector<int> modmap; + int nmod=0; + int nrows=336; + int ncols=80; + std::vector<float> varValues=scan->getLoopVarValues(1); + std::vector<std::vector<double**> > n, x, x2; + for (size_t i=0;i<numvals;i++){ + sprintf(subdir, "loop1_%d", i); + file->cd(subdir); // GDAC steps + TIter nextkey(gDirectory->GetListOfKeys()); // histos + while ((key=(TKey*)nextkey())) { + boost::cmatch matches; + boost::regex re("_(\\d+)_Occupancy_ToT_(\\d+)"); + if(boost::regex_search(key->GetName(), matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + int id=strtol(match.c_str(),0,10); + std::string match2(matches[2].first, matches[2].second); + int tot=strtol(match2.c_str(),0,10); + TH2* histo = (TH2*)key->ReadObj(); + if(idmap.find(id)==idmap.end()){ + std::vector<double** > nvec; + std::vector<double** > xvec; + std::vector<double** > x2vec; + n.push_back(nvec); + x.push_back(xvec); + x2.push_back(x2vec); + for(int l=0;l<16;l++){ + n[nmod].push_back(new double*[ncols]); + x[nmod].push_back(new double*[ncols]); + x2[nmod].push_back(new double*[ncols]); + for(int j=0;j<ncols;j++){ + n[nmod][l][j]=new double[nrows]; + x[nmod][l][j]=new double[nrows]; + x2[nmod][l][j]=new double[nrows]; + for(int k=0;k<nrows;k++){ + n[nmod][l][j][k]=0; + x[nmod][l][j][k]=0; + x2[nmod][l][j][k]=0; + } + + } + } + modmap.push_back(id); + idmap[id]=nmod++; + } + int mod=idmap[id]; + struct ipc::PixelFECalibFEI4 *fecalib=0; + ipc::PixelFEI4AConfig* confa=findFEI4AConfig(cfg, id); + if(confa)fecalib=&confa->FECalib; + else{ + ipc::PixelFEI4BConfig* confb=findFEI4BConfig(cfg, id); + if(confb)fecalib=&confb->FECalib; + } + assert(fecalib); + float clo=fecalib->cinjLo; + float chi=fecalib->cinjHi; + float vcal1=fecalib->vcalCoeff[1]; + float vcal0=fecalib->vcalCoeff[0]; + float capacitance=0; + if(scan->getMaskStageMode()==PixLib::EnumMaskStageMode::FEI4_ENA_SCAP)capacitance=clo; + else if(scan->getMaskStageMode()==PixLib::EnumMaskStageMode::FEI4_ENA_LCAP)capacitance=chi; + else if(scan->getMaskStageMode()==PixLib::EnumMaskStageMode::FEI4_ENA_BCAP)capacitance=chi+clo; + capacitance=capacitance*6241; + float fldac=(float)varValues[i]; + float el= capacitance*(vcal0 + vcal1*fldac); + + for(int row=0;row<nrows;row++){ + for(int col=0;col<ncols;col++){ + double nentries=histo->GetBinContent(col+1, row+1); + n[mod][tot][col][row]+=nentries; + x[mod][tot][col][row]+=el*nentries; + x2[mod][tot][col][row]+=el*el*nentries; + } + } + } + } + } + std::cout<<"Part 1 done"<<std::endl; + anfile->cd(); + TH1D cc("calibration curve", "calibration curve", 16, 0, 16); + for (int mod=0;mod<nmod;mod++){ + int id=modmap[mod]; + TH2D* p0=new TH2D(Form("P0_Mod_%i",id),Form("P0 Mod %d at %s", id, findFieldName(cfg, id)),ncols, 0, ncols, nrows, 0, nrows); + TH2D* p1=new TH2D(Form("P1_Mod_%i",id),Form("P1 Mod %d at %s", id, findFieldName(cfg, id)),ncols, 0, ncols, nrows, 0, nrows); + TH2D* p2=new TH2D(Form("P2_Mod_%i",id),Form("P2 Mod %d at %s", id, findFieldName(cfg, id)),ncols, 0, ncols, nrows, 0, nrows); + for(int col=0;col<ncols;col++){ + for(int row=0;row<nrows;row++){ + cc.Reset(); + for(int tot=0;tot<16;tot++){ + double nent=n[mod][tot][col][row]; + if(nent!=0){ + cc.SetBinContent(tot+1, x[mod][tot][col][row]/nent); + cc.SetBinError(tot+1, TMath::Sqrt(TMath::Abs(x2[mod][tot][col][row]-x[mod][tot][col][row]*x[mod][tot][col][row]/nent))/nent); + } + } + cc.Fit("pol2", "", "", 1, 13); + TF1* fitfun=cc.GetFunction("pol2"); + if(fitfun && fitfun->GetNpar()==3){ + p0->SetBinContent(col+1,row+1, fitfun->GetParameter(0)); + p1->SetBinContent(col+1,row+1, fitfun->GetParameter(1)); + p2->SetBinContent(col+1,row+1, fitfun->GetParameter(2)); + } + } + } + p0->Write(); + p1->Write(); + p2->Write(); + } + for(size_t i=0;i<n.size();i++){ + for(int j=0;j<16;j++){ + for(int k=0;k<ncols;k++){ + delete [] n[i][j][k]; + } + delete [] n[i][j]; + } + } + for(size_t i=0;i<n.size();i++){ + for(int j=0;j<16;j++){ + for(int k=0;k<ncols;k++){ + delete [] x[i][j][k]; + } + delete [] x[i][j]; + } + } + for(size_t i=0;i<n.size();i++){ + for(int j=0;j<16;j++){ + for(int k=0;k<ncols;k++){ + delete [] x2[i][j][k]; + } + delete [] x2[i][j]; + } + } +} diff --git a/rce/rcecalib/analysis/TotCalibAnalysis.hh b/rce/rcecalib/analysis/TotCalibAnalysis.hh new file mode 100644 index 00000000..3fae4b4f --- /dev/null +++ b/rce/rcecalib/analysis/TotCalibAnalysis.hh @@ -0,0 +1,23 @@ +#ifndef TOTCALIB_ANALYSIS_HH +#define TOTCALIB_ANALYSIS_HH + +#include "analysis/CalibAnalysis.hh" +#include "analysis/CfgFileWriter.hh" +#include "server/PixScan.hh" + +class TFile; +class TH2; +namespace RCE{ + class PixScan; +} +class ConfigGui; + +class TotCalibAnalysis: public CalibAnalysis{ +public: + TotCalibAnalysis(): CalibAnalysis(){} + ~TotCalibAnalysis(){} + void analyze(TFile* file, TFile* anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]); +}; + + +#endif diff --git a/rce/rcecalib/analysis/analysisGui_Linkdef.hh b/rce/rcecalib/analysis/analysisGui_Linkdef.hh new file mode 100644 index 00000000..798aa03f --- /dev/null +++ b/rce/rcecalib/analysis/analysisGui_Linkdef.hh @@ -0,0 +1,2 @@ +#pragma link C++ class AnalysisGui; +#pragma link C++ class ConfigGui; diff --git a/rce/rcecalib/analysis/constituents.mk b/rce/rcecalib/analysis/constituents.mk new file mode 100644 index 00000000..a1bfff7c --- /dev/null +++ b/rce/rcecalib/analysis/constituents.mk @@ -0,0 +1,124 @@ +ifeq ($(profiler),y) +CPPFLAGS+='-D__PROFILER_ENABLED__' +profiler_lib=rcecalib/profiler +endif + + +ifneq ($(findstring linux,$(tgt_os)),) +libnames := analysis +libsrcs_analysis:= NoiseAnalysis.cc \ + GdacAnalysis.cc \ + GdacFastAnalysis.cc \ + GdacCoarseFastAnalysis.cc \ + TdacAnalysis.cc \ + TdacFastAnalysis.cc \ + Fdac_Analysis.cc \ + ThresholdAnalysis.cc \ + Iff_Analysis.cc \ + TotAnalysis.cc \ + TotCalibAnalysis.cc \ + DigitalTestAnalysis.cc \ + ModuleCrosstalkAnalysis.cc \ + OffsetAnalysis.cc \ + CrosstalkAnalysis.cc \ + T0Analysis.cc \ + TimeWalkAnalysis.cc \ + AnalysisFactory.cc \ + CalibAnalysis.cc \ + CfgFileWriter.cc \ + Fei4CfgFileWriter.cc \ + Fei3CfgFileWriter.cc \ + StuckPixelAnalysis.cc \ + MultiTrigAnalysis.cc \ + MultiTrigNoiseAnalysis.cc \ + SerialNumberAnalysis.cc \ + RegisterTestAnalysis.cc \ + TemperatureAnalysis.cc + +libincs_analysis := \ + rcecalib + + +LXFLAGS +=-pthread -lm -ldl -rdynamic +rootlibs:= \ + $(RELEASE_DIR)/build/root/lib/Gui \ + $(RELEASE_DIR)/build/root/lib/Thread \ + $(RELEASE_DIR)/build/root/lib/MathCore \ + $(RELEASE_DIR)/build/root/lib/Physics \ + $(RELEASE_DIR)/build/root/lib/Matrix \ + $(RELEASE_DIR)/build/root/lib/Postscript \ + $(RELEASE_DIR)/build/root/lib/Rint \ + $(RELEASE_DIR)/build/root/lib/Tree \ + $(RELEASE_DIR)/build/root/lib/Gpad \ + $(RELEASE_DIR)/build/root/lib/Graf3d \ + $(RELEASE_DIR)/build/root/lib/Graf \ + $(RELEASE_DIR)/build/root/lib/Hist \ + $(RELEASE_DIR)/build/root/lib/Net \ + $(RELEASE_DIR)/build/root/lib/RIO \ + $(RELEASE_DIR)/build/root/lib/Cint \ + $(RELEASE_DIR)/build/root/lib/Core + +tgtnames := analysisGui mergeMaskFilesFei4 histoViewer + +GUIHEADERSDEP = AnalysisGui.hh ../server/ConfigGui.hh HistoViewerGui.hh + +#-------------------------------------------- +tgtsrcs_analysisGui := AnalysisGui.cc \ + ../server/PixScan.cc \ + ../server/ConfigGui.cc \ + ../server/FEI4AConfigFile.cc \ + ../server/FEI4BConfigFile.cc \ + ../server/TurboDaqFile.cc \ + ../server/HitbusConfigFile.cc \ + ../server/AFPHPTDCConfigFile.cc \ + analysisGui_rootDict.cc + +guiheaders_analysisGui := AnalysisGui.hh ../server/ConfigGui.hh + + +tgtincs_analysisGui := \ + rcecalib \ + rcecalib/analysis + + + +tgtlibs_analysisGui := \ + rcecalib/analysis + +tgtslib_analysisGui := \ + dl\ + $(z_lib) \ + $(rootlibs) \ + $(omniorb_lib) \ + $(omnithread_lib) \ + $(ers_lib) \ + $(boost_regex_lib) +#-------------------------------------------- +tgtsrcs_histoViewer := HistoViewerGui.cc \ + histoViewer_rootDict.cc + +guiheaders_histoViewer := HistoViewerGui.hh + + +tgtincs_histoViewer := \ + rcecalib \ + rcecalib/analysis + + + +tgtlibs_histoViewer := + +tgtslib_histoViewer := \ + dl\ + $(z_lib) \ + $(rootlibs) \ + $(omniorb_lib) \ + $(omnithread_lib) \ + $(ers_lib) \ + $(boost_regex_lib) +tgtsrcs_mergeMaskFilesFei4 := MergeMaskFilesFei4.cc Fei4CfgFileWriter.cc +tgtincs_mergeMaskFilesFei4 := $(root_include_path) $(boost_include_path) +tgtslib_mergeMaskFilesFei4 := $(rootlibs) + +endif + diff --git a/rce/rcecalib/analysis/histoViewer_Linkdef.hh b/rce/rcecalib/analysis/histoViewer_Linkdef.hh new file mode 100644 index 00000000..5d778d12 --- /dev/null +++ b/rce/rcecalib/analysis/histoViewer_Linkdef.hh @@ -0,0 +1 @@ +#pragma link C++ class HistoViewerGui; diff --git a/rce/rcecalib/analysis/tdacScanAnalysis.cc b/rce/rcecalib/analysis/tdacScanAnalysis.cc new file mode 100644 index 00000000..02d55a28 --- /dev/null +++ b/rce/rcecalib/analysis/tdacScanAnalysis.cc @@ -0,0 +1,89 @@ +#include "rcecalib/analysis/tdacScanAnalysis.hh" + +#include <TFile.h> +#include <TH2.h> +#include <TH2D.h> +#include <TH1.h> +#include <TKey.h> +#include <iostream> +#include <iomanip> +#include <fstream> +#include <cmath> + +void tdacScanAnalysis::analyze(TFile* file, TFile *anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]){ + printf("Begin TDAC Analysis\n"); + float target = scan->getThresholdTargetValue(); + printf("Target Threshold Value: %2.1f\n",target); + for(int rce = 0; rce < 8; rce++){ + for(int module = 0; module < 16; module++){ + if(file->Get(Form("loop1_0/RCE%i_Mod_%i_Mean",rce,module)) == 0) continue; + TH2D* tdachis = new TH2D(Form("RCE%i_Mod_%i_TDAC",rce,module),"Best TDAC Settings",80,0,80,336,0,336); + tdachis->GetXaxis()->SetTitle("Column"); + tdachis->GetYaxis()->SetTitle("Row"); + TH2D* ahis = new TH2D(Form("RCE%i_Mod_%i_Threshold_MinDiff",rce,module),"min(Threshold - Target Threshold)",80,0,80,336,0,336); + ahis->GetXaxis()->SetTitle("Column"); + ahis->GetYaxis()->SetTitle("Row"); + for(int c = 1; c < 81; c++){ + for(int r = 1; r < 337; r++){ + ahis->SetBinContent(c,r,-1.0); + } + } + for(int i = 0; i < 32; i++){ + //printf("Point %3i\n",i); + TH2* mean_histo; + TH2* occ_histo; + mean_histo = (TH2*)file->Get(Form("loop1_%i/RCE%i_Mod_%i_Mean",i,rce,module)); + occ_histo = (TH2*)file->Get(Form("loop1_%i/RCE%i_Mod_%i_Occupancy_Point_100",i,rce,module)); + double mean = 0.0; + for(int j = 1; j <= mean_histo->GetNbinsX(); j++){ + for(int k = 1; k <= mean_histo->GetNbinsY(); k++){ + float nhits = occ_histo->GetBinContent(j,k); + if(nhits != 0){ + mean = mean_histo->GetBinContent(j,k); + if(std::fabs(mean - target) < ahis->GetBinContent(j,k) || ahis->GetBinContent(j,k) < 0){ + ahis->SetBinContent(j,k,std::fabs(mean - target)); + tdachis->SetBinContent(j,k,i); + } + } + } + } + delete mean_histo; + delete occ_histo; + } + std::string fn(anfile->GetName()); + int pos = fn.find("analysis.root"); + std::string outname = Form("%stdacs%i.dat",fn.substr(0,pos).c_str(),(rce*16+module)); + ofstream outfile(outname.c_str()); + outfile << "### "; + for (int i=1; i<41;i++) { + outfile << std::setw(4) << i; + } + outfile << std::endl; + outfile << "### "; + for (int i=41; i<81;i++) { + outfile << std::setw(4) << i; + } + outfile << std::endl; + for (int row=1; row<337; row++) { + outfile << std::setw(3) << row << "a"; + for (int col=1; col<41; col++) { + outfile << std::setw(4) << int(tdachis->GetBinContent(col,row)); + } + outfile << std::endl; + outfile << std::setw(3) << row << "b"; + for (int col=41; col<81; col++) { + outfile << std::setw(4) << int(tdachis->GetBinContent(col,row)); + } + outfile << std::endl; + + } + anfile->cd(); + tdachis->Write(); + ahis->Write(); + delete ahis; + delete tdachis; + } + } + printf("Done Analysis\n"); +} + diff --git a/rce/rcecalib/analysis/tdacScanAnalysis.hh b/rce/rcecalib/analysis/tdacScanAnalysis.hh new file mode 100644 index 00000000..3f5b2778 --- /dev/null +++ b/rce/rcecalib/analysis/tdacScanAnalysis.hh @@ -0,0 +1,22 @@ +#ifndef TDACSCANANALYSIS_HH +#define TDACSCANANALYSIS_HH + +#include "rcecalib/analysis/CalibAnalysis.hh" +#include "rcecalib/server/PixScan.hh" + +class ConfigGui; +class TFile; +class TH2D; +namespace RCE{ + class PixScan; +} + +class tdacScanAnalysis: public CalibAnalysis{ +public: + tdacScanAnalysis(): CalibAnalysis(){} + ~tdacScanAnalysis(){} + void analyze(TFile* file, TFile* anfile, RCE::PixScan* scan, int runno, ConfigGui* cfg[]); +}; + + +#endif diff --git a/rce/rcecalib/config/AbsFormatter.hh b/rce/rcecalib/config/AbsFormatter.hh new file mode 100644 index 00000000..a91dff03 --- /dev/null +++ b/rce/rcecalib/config/AbsFormatter.hh @@ -0,0 +1,22 @@ +#ifndef ABSFORMATTER_HH +#define ABSFORMATTER_HH + +#include <vector> +#include <string> +#include <boost/property_tree/ptree_fwd.hpp> + +class AbsFormatter{ +public: + AbsFormatter(int id, const char* name=""):m_rb(0), m_name(name), m_id(id){} + virtual ~AbsFormatter(){} + virtual int decode(const unsigned* data, int size, unsigned* parsedData, int &parsedsize, int &nL1A)=0; + virtual void configure(boost::property_tree::ptree* scanOptions){}; + virtual void setReadbackPointer(std::vector<unsigned>* p){m_rb=p;} + const char* getName(){return m_name.c_str();} + int getId(){return m_id;} +protected: + std::vector<unsigned> *m_rb; + std::string m_name; + int m_id; +}; +#endif diff --git a/rce/rcecalib/config/AbsModule.hh b/rce/rcecalib/config/AbsModule.hh new file mode 100644 index 00000000..cb0957a2 --- /dev/null +++ b/rce/rcecalib/config/AbsModule.hh @@ -0,0 +1,40 @@ +#ifndef ABSMODULE_HH +#define ABSMODULE_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/config/ModuleInfo.hh" +#include "rcecalib/config/AbsFormatter.hh" + + +class AbsModule{ +public: + AbsModule(const char* name, unsigned id, unsigned inLink, unsigned outLink, AbsFormatter* fmt) + :m_name(name), m_id(id), m_inLink(inLink), m_outLink(outLink), m_formatter(fmt){} + virtual ~AbsModule(){delete m_formatter;} + virtual void configureHW()=0; + virtual void setupMaskStageHW(int stage)=0; + virtual int setupParameterHW(const char* name, int val)=0; //HW setup + virtual int configureScan(boost::property_tree::ptree* scanOptions)=0; + virtual void resetFE()=0; + virtual void enableDataTakingHW()=0; + virtual int verifyModuleConfigHW(){return 0;} + unsigned getId(){return m_id;} + AbsFormatter* getFormatter(){return m_formatter;} + virtual ModuleInfo getModuleInfo()=0; + virtual const float dacToElectrons(int fe, int dac)=0; + unsigned getInLink(){return m_inLink;} + unsigned getOutLink(){return m_outLink;} + void setInLink(unsigned pos){m_inLink=pos;} + void setOutLink(unsigned pos){m_outLink=pos;} + std::string getName(){return m_name;} + virtual void destroy()=0; + +protected: + std::string m_name; + unsigned m_id; + unsigned m_inLink; + unsigned m_outLink; + AbsFormatter *m_formatter; +}; + +#endif diff --git a/rce/rcecalib/config/AbsModuleGroup.cc b/rce/rcecalib/config/AbsModuleGroup.cc new file mode 100644 index 00000000..dab1c36c --- /dev/null +++ b/rce/rcecalib/config/AbsModuleGroup.cc @@ -0,0 +1,22 @@ +#include "rcecalib/config/AbsModuleGroup.hh" +#include "rcecalib/HW/SerialIF.hh" + +void AbsModuleGroup::setChannelInMask(){ + SerialIF::setChannelInMask(m_channelInMask); +} +void AbsModuleGroup::setChannelOutMask(){ + SerialIF::setChannelOutMask(m_channelOutMask); +} +void AbsModuleGroup::disableAllOutChannels(){ + SerialIF::setChannelOutMask(0); +} +void AbsModuleGroup::disableAllInChannels(){ + SerialIF::setChannelInMask(0); +} + +unsigned AbsModuleGroup::getChannelInMask(){ + return m_channelInMask; +} +unsigned AbsModuleGroup::getChannelOutMask(){ + return m_channelOutMask; +} diff --git a/rce/rcecalib/config/AbsModuleGroup.hh b/rce/rcecalib/config/AbsModuleGroup.hh new file mode 100644 index 00000000..0c87a0ec --- /dev/null +++ b/rce/rcecalib/config/AbsModuleGroup.hh @@ -0,0 +1,32 @@ +#ifndef ABSMODULEGROUP_HH +#define ABSMODULEGROUP_HH +#include <boost/property_tree/ptree_fwd.hpp> +#include <vector> + +class AbsModuleGroup{ +public: + AbsModuleGroup(): m_channelInMask(0), m_channelOutMask(0){} + virtual ~AbsModuleGroup(){}; + void setChannelInMask(); + void setChannelOutMask(); + unsigned getChannelInMask(); + unsigned getChannelOutMask(); + void disableAllOutChannels(); + void disableAllInChannels(); + virtual void deleteModules()=0; + virtual int setupParameterHW(const char* name, int val, bool bcOK)=0; + virtual int setupMaskStageHW(int stage)=0; + virtual void configureModulesHW()=0; + virtual int verifyModuleConfigHW()=0; + virtual void resetErrorCountersHW()=0; + virtual int configureScan(boost::property_tree::ptree *scanOptions)=0; + virtual void resetFE()=0; + virtual void enableDataTakingHW()=0; + virtual unsigned getNmodules()=0; +protected: + unsigned m_channelInMask; + unsigned m_channelOutMask; + +}; + +#endif diff --git a/rce/rcecalib/config/AbsTrigger.cc b/rce/rcecalib/config/AbsTrigger.cc new file mode 100644 index 00000000..774c4f09 --- /dev/null +++ b/rce/rcecalib/config/AbsTrigger.cc @@ -0,0 +1,9 @@ +#include "rcecalib/config/AbsTrigger.hh" +#include <algorithm> + + +bool AbsTrigger::lookupParameter(const char* name){ + std::list<std::string>::iterator result = std::find(m_parameters.begin(), m_parameters.end(), name); + if( result==m_parameters.end())return false; + else return true; + } diff --git a/rce/rcecalib/config/AbsTrigger.hh b/rce/rcecalib/config/AbsTrigger.hh new file mode 100644 index 00000000..be15ff4c --- /dev/null +++ b/rce/rcecalib/config/AbsTrigger.hh @@ -0,0 +1,27 @@ +#ifndef ABSTRIGGER_HH +#define ABSTRIGGER_HH + +#include <list> +#include <boost/property_tree/ptree_fwd.hpp> + +class AbsTrigger{ +public: + AbsTrigger():m_i(0){}; + virtual ~AbsTrigger(){} + // configureScan and setupParameter can be overridden by daughter classes + virtual int configureScan(boost::property_tree::ptree* scanOptions){ + m_i=0; + return 0; + } + virtual int setupParameter(const char* name, int val){return 0;} + virtual int sendTrigger()=0; + virtual int getNTriggers(){return m_i;} + virtual int enableTrigger(bool on)=0; + virtual int resetCounters(){return 0;} + bool lookupParameter(const char* name); +protected: + int m_i; + std::list<std::string> m_parameters; +}; + +#endif diff --git a/rce/rcecalib/config/BFU.hh b/rce/rcecalib/config/BFU.hh new file mode 100644 index 00000000..0ac17af0 --- /dev/null +++ b/rce/rcecalib/config/BFU.hh @@ -0,0 +1,157 @@ +#ifndef BFU_H +#define BFU_H + + +/* ---------------------------------------------------------------------- *//*! + + \file BFU.h + \brief Bit Field Unpack Routines + \author JJRussell - russell@slac.stanford.edu + + Inline functions to (left justified) unpack bit fields. + */ +/* ---------------------------------------------------------------------- */ + + +/* ---------------------------------------------------------------------- *\ + * + * HISTORY + * ------- + * + * DATE WHO WHAT + * -------- --- --------------------------------------------------------- + * 08.25.09 jjr Pilfered from the LAT code, then made two modifications + * 1. Changed BFU from a structure to unsigned long long + * Turns out that any structure that is returned from + * a routine is returned via stack memory. This defeats + * the whole purpose of the bit-extraction routines + * which is to avoid memory like the plague. + * 2. Then, after looking at the generated code, made + * macro versions of BFU__wordL, BFU__wordR, BFU__boolean. + * While changing BFU as indicated in (1) did result + * in it being returned in registers, the generated + * code showed a lot of register thrashing. Once the + * move to a macro was made, the interface was no longer + * constrained to being able to modify just two 32-bit + * values (typically the cached bit field and the + * extracted value). To take advantage of this, the + * buffer address is now incremented when a new cache + * value is extracted. + * + * This made a factor of 2 difference in the MCC decoder. + * + * Future improvements + * 1. Started on a better implementation of the left + * justified extraction routines. Currently they + * just call the right justified extraction routines + * and appropriately shift the result. While this + * produces the correct answer, it has a performance + * cost. + * 2. Add probe routine for the booleans. Since the + * cache value always contains at least one valid + * bit, it can be probed without advancing the stream. + * Doing arbitrary field probes is also possible, + * but is much more difficult. + * 3. The most ambitious thing would be to build custom + * routines for the different platforms. In particular, + * a PPC-specific routine could be substantially faster, + * taking advantage of the rlinm instructions. + * + * 09.30.06 jjr Corrected _bfu_construct (it didn't used the newly + * calculated bit offset to extract the buffered word into + * cur). Added _bfu_constructW for constructing a BFU from + * an aligned source buffer. + * 09.30.06 jjr Added History log +\* ---------------------------------------------------------------------- */ +#ifdef __cplusplus +extern "C" { +#endif + + + + +#define _bfu_wordR(_val, _cur, _wrds, _position, _width) \ +{ \ + /* Compute where in the current word this field is to be extracted from */ \ + int rposition = (_position) & 0x1f; \ + int shift = 32 - (rposition + (_width)); \ + unsigned int msk = ((((unsigned int)0x1) << ((_width)-1)) << 1) - 1; \ + \ + if (shift > 0) _val = ((_cur) >> shift) & msk; \ + else if (shift == 0) \ + { \ + _val = (_cur) & msk; \ + _cur = *(++_wrds); \ + } \ + else \ + { \ + /* \ + | Crosses over to the next word \ + | In this case -shift is the number of bits in the next word \ + */ \ + shift = -shift; \ + _val = ((_cur) & (msk >> shift)) << shift; \ + _cur = *(++_wrds); \ + _val |= (_cur) >> (32 - shift); \ + } \ +} + + +#if 1 + +/* + | This is the original version of the extrating a left justified field. + | It calls the right justified field extrractor, then shifts the value + | into place. This is algorithmically correct, but costs in performance +*/ +#define _bfu_wordL(_val, _cur, _wrds, _position, _width) \ +{ \ + _bfu_wordR (_val, _cur, _wrds, _position, _width); \ + _val <<= 32 - (_width); \ +} + +#else + + +/* + | This is an experimental version of extracting a left justified field + | Basically it works, but because its interface differs slightly from + | the original version above (the difference is that the unused bits + | are not cleared, but actually carry the next 'n' bits of the data + | stream, which, in certain applications can be useful as a look-ahead + | operation) cannot be a drop-in replacement. + | + | It should be more efficient than the original version. +*/ +#define _bfu_wordL(_val, _cur, _wrds, _position, _width) \ +{ \ + /* Compute where in the current word this field is to be extracted from */ \ + int rposition = (_position) & 0x1f; \ + int end = (rposition + (_width)); \ + int left = 32 - end; \ + \ + _val = _cur << _position; \ + if (left <= 0) \ + { \ + _cur = *(++_wrds); \ + if (left < 0) \ + { \ + unsigned int s = 32 - (_position); \ + unsigned int x = _cur >> s; \ + _val &= (signed)0x80000000 >> (s-1); \ + _val |= x; \ + } \ + } \ +} + +#endif + +/* ---------------------------------------------------------------------- */ +#define _bfu_testBit(_cur, _position) (_cur << ((_position) & 0x1f)) +/* ---------------------------------------------------------------------- */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/rce/rcecalib/config/ConfigIF.cc b/rce/rcecalib/config/ConfigIF.cc new file mode 100644 index 00000000..baa032a3 --- /dev/null +++ b/rce/rcecalib/config/ConfigIF.cc @@ -0,0 +1,250 @@ +//Dummy interface for debugging + +#include "ConfigIF.hh" +#include <boost/property_tree/ptree.hpp> +#include <stdio.h> +#include "rcecalib/config/ModuleFactory.hh" +#include "rcecalib/config/AbsModule.hh" +#include "rcecalib/config/AbsModuleGroup.hh" +#include "rcecalib/config/AbsTrigger.hh" +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/util/VerifyErrors.hh" +#include "ers/ers.h" +#include "ipc/object.h" +#include "rcecalib/HW/SerialIF.hh" + +ConfigIF::ConfigIF(ModuleFactory *mf):m_moduleFactory(mf),m_trigger(0), m_linkInMask(0), m_linkOutMask(0){ + m_modulegroups=mf->getModuleGroups(); +} + +int ConfigIF::setupParameter(const char* name, int val, bool enable){ + int retval=0; + assert(m_trigger!=0); + bool istrgpar=m_trigger->lookupParameter(name); + if(istrgpar==true){ + retval=m_trigger->setupParameter(name,val); + }else{ + disableAllChannels(); + for (unsigned int i=0;i<m_modulegroups.size();i++){ + if(m_modulegroups[i]->getNmodules()!=0)retval+=m_modulegroups[i]->setupParameterHW(name,val, enable); + } + if(enable){ + enableDataTakingHW(); + setChannelMask(); + } + // m_trigger->resetCounters(); + } + return retval; +} + +int ConfigIF::setupMaskStage(int stage){ + disableAllChannels(); + for (unsigned int i=0;i<m_modulegroups.size();i++){ + if(m_modulegroups[i]->getNmodules()!=0)m_modulegroups[i]->setupMaskStageHW(stage); + } + enableDataTakingHW(); + setChannelMask(); + // m_trigger->resetCounters(); + return 0; +} + +void ConfigIF::configureModulesHW(bool enable){ + //std::cout<<"Configure Modules HW"<<std::endl; + disableAllChannels(); + sendHWcommand(9); // reset Firmware + for (unsigned int i=0;i<m_modulegroups.size();i++){ + if(m_modulegroups[i]->getNmodules()!=0)m_modulegroups[i]->configureModulesHW(); + } + if(enable==true){ + enableDataTakingHW(); + setChannelMask(); + if(m_trigger){ + //std::cout<<"Resetting counters"<<std::endl; + m_trigger->resetCounters(); + } + } +} + +int ConfigIF::verifyModuleConfigHW(int id){ + int retval=0; + int mod=-1; + for (size_t i=0; i<m_modules.size();i++){ + if(m_modules[i]->getModuleInfo().getId()==id){ + mod=i; + break; + } + } + if(mod<0)return ModuleVerify::NO_MODULE; + SerialIF::setChannelInMask(m_modules[mod]->getInLink()); + SerialIF::setChannelOutMask(m_modules[mod]->getOutLink()); + retval=m_modules[mod]->verifyModuleConfigHW(); + disableAllChannels(); + return retval; +} + +unsigned ConfigIF::getNmodules(){ + return m_modules.size(); +} + +int ConfigIF::sendTrigger(){ + m_trigger->sendTrigger(); + return 0; +} + +int ConfigIF::setChannelMask(){ + SerialIF::setChannelInMask(m_linkInMask); + SerialIF::setChannelOutMask(m_linkOutMask); + //std::cout<<"Link In Mask "<<std::hex<<m_linkInMask<<std::dec<<std::endl; + //std::cout<<"Link Out Mask "<<std::hex<<m_linkOutMask<<std::dec<<std::endl; + return 0; +} + +void ConfigIF::disableAllChannels(){ + SerialIF::setChannelInMask(0); + SerialIF::setChannelOutMask(0); +} +unsigned ConfigIF::sendHWcommand(unsigned char opcode){ + return SerialIF::sendCommand(opcode); +} +unsigned ConfigIF::writeHWregister(unsigned addr, unsigned val){ + return SerialIF::writeRegister(addr,val); +} +unsigned ConfigIF::readHWregister(unsigned addr, unsigned &val){ + return SerialIF::readRegister(addr, val); +} +unsigned ConfigIF::writeHWblockData(std::vector<unsigned>& data){ + return SerialIF::writeBlockData(data); +} +unsigned ConfigIF::readHWblockData(std::vector<unsigned>& data, std::vector<unsigned>& retvec){ + return SerialIF::readBlockData(data, retvec); +} +unsigned ConfigIF::readHWbuffers(std::vector<unsigned char>& retvec){ + return SerialIF::readBuffers(retvec); +} +void ConfigIF::resetCountersHW(){ + m_trigger->resetCounters(); +} + +int ConfigIF::enableTrigger(){ + return m_trigger->enableTrigger(1); +} +int ConfigIF::disableTrigger(){ + return m_trigger->enableTrigger(0); +} +void ConfigIF::resetFE(){ + disableAllChannels(); + for (unsigned int i=0;i<m_modulegroups.size();i++){ + if(m_modulegroups[i]->getNmodules()!=0)m_modulegroups[i]->resetFE(); + } + if(m_trigger)disableTrigger(); +} +void ConfigIF::resetErrorCountersHW(){ + for (unsigned int i=0;i<m_modulegroups.size();i++){ + if(m_modulegroups[i]->getNmodules()!=0)m_modulegroups[i]->resetErrorCountersHW(); + } +} +void ConfigIF::enableDataTakingHW(){ + //std::cout<<"ConfigIF enabled data taking"<<std::endl; + for (unsigned int i=0;i<m_modulegroups.size();i++){ + if(m_modulegroups[i]->getNmodules()!=0)m_modulegroups[i]->enableDataTakingHW(); + } +} + +int ConfigIF::configureScan(boost::property_tree::ptree *scanOptions){ + int retval=0; + if(m_trigger!=0)retval=m_trigger->configureScan(scanOptions); + for (unsigned int i=0;i<m_modulegroups.size();i++){ + if(m_modulegroups[i]->getNmodules()!=0)retval+=m_modulegroups[i]->configureScan(scanOptions); + } + return retval; +} + +int ConfigIF::setupModule(const char* name, const char* type, unsigned id, unsigned inLink, unsigned outLink, const char* formatter){ + int retval=0; + char err_msg[128]; + try{ + //name, id, link are unique. Check that they don't exist already. + for (unsigned int i=0;i<m_modules.size();i++){ + if(m_modules[i]->getId()==id ){ + std::cout<<"setupModule error: Duplicate id "<<id<<std::endl; + sprintf(err_msg,"id = %d",id); + rcecalib::Param_exists issue(ERS_HERE,err_msg); + throw issue; + } + if(m_modules[i]->getName()==name ){ + std::cout<<"setupModule error: Duplicate name "<<name<<std::endl; + sprintf(err_msg,"name = %s",name); + rcecalib::Param_exists issue(ERS_HERE,err_msg); + throw issue; + } + if( m_modules[i]->getOutLink()==outLink){ + std::cout<<"setupModule error: Duplicate outlink "<<outLink<<std::endl; + sprintf(err_msg,"link = %d",outLink); + rcecalib::Param_exists issue(ERS_HERE,err_msg); + throw issue; + } + } + //std::cout<<name<<" "<<type<<" "<<id<<" "<<link<<std::endl; + AbsModule *newmod=m_moduleFactory->createModule(name, type,id, inLink, outLink, formatter); + //std::cout<<"setupModule after create "<<newmod<<std::endl; + //success + if(std::string(type)!="IPC_Hitbus_multiThread"){ + m_modules.push_back(newmod); + m_linkInMask|=1<<newmod->getInLink(); + } + m_linkOutMask|=1<<newmod->getOutLink(); + } + catch(rcecalib::Param_exists ex){ + ers::error(ex); + retval=1; + } + catch(rcecalib::Unknown_Module_Type ex){ + ers::error(ex); + retval=1; + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + catch(std::bad_alloc &ex){ + std::cerr<<"Bad alloc "<<ex.what()<<std::endl; + } + catch(...){ + std::cerr<<"Unknown error "<<std::endl; + } + return retval; +} + +int ConfigIF::setupTriggerIF(const char* type){ + delete m_trigger; + m_trigger=m_moduleFactory->createTriggerIF(type, this); + return 0; +} + +void ConfigIF::deleteModules(){ + for (unsigned i=0; i<m_modulegroups.size();i++){ + //cannot call delete directly because IPC modules need to call _destroy() instead. + m_modulegroups[i]->deleteModules(); + } + m_modules.clear(); + m_linkInMask=0; + m_linkOutMask=0; +} + +int ConfigIF::nTrigger(){ + return m_trigger!=0? m_trigger->getNTriggers(): -1; +} + +ModuleInfo ConfigIF::getModuleInfo(int mod){ + ERS_ASSERT(mod<(int)m_modules.size()); + return m_modules[mod]->getModuleInfo(); +} +const float ConfigIF::dacToElectrons(int mod, int fe, int dac){ + if(mod>=(int)m_modules.size())return -1; + return m_modules[mod]->dacToElectrons(fe,dac); +} diff --git a/rce/rcecalib/config/ConfigIF.hh b/rce/rcecalib/config/ConfigIF.hh new file mode 100644 index 00000000..414af219 --- /dev/null +++ b/rce/rcecalib/config/ConfigIF.hh @@ -0,0 +1,53 @@ +#ifndef CONFIGIF_HH +#define CONFIGIF_HH +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/config/ModuleInfo.hh" +#include <vector> + +class ModuleFactory; +class AbsModule; +class AbsModuleGroup; +class AbsTrigger; + +class ConfigIF{ +public: + ConfigIF(ModuleFactory*); + virtual ~ConfigIF(){} + int setupParameter(const char* name, int val, bool enable=true); + int setupMaskStage(int stage); + int sendTrigger(); + int setChannelMask(); + void disableAllChannels(); + void configureModulesHW(bool enable=true); + int verifyModuleConfigHW(int id); + int enableTrigger(); + int disableTrigger(); + unsigned sendHWcommand(unsigned char opcode); + unsigned writeHWregister(unsigned addr, unsigned val); + unsigned readHWregister(unsigned addr, unsigned &val); + unsigned writeHWblockData(std::vector<unsigned>& data); + unsigned readHWblockData(std::vector<unsigned>& data, std::vector<unsigned>& retvec); + unsigned readHWbuffers(std::vector<unsigned char>& retvec); + void resetCountersHW(); + void resetErrorCountersHW(); + int nTrigger(); + int configureScan(boost::property_tree::ptree *scanOptions); + unsigned getNmodules(); + ModuleInfo getModuleInfo(int mod); + const float dacToElectrons(int mod, int fe, int dac); + void deleteModules(); + void resetFE(); + void enableDataTakingHW(); + int setupTriggerIF(const char* type); + int setupModule(const char* name, const char* type, unsigned id, unsigned inLink, unsigned outLink, const char* formatter); +private: + std::vector<AbsModule*> m_modules; + std::vector<AbsModuleGroup*> m_modulegroups; + ModuleFactory* m_moduleFactory; + AbsTrigger* m_trigger; + unsigned m_linkInMask; + unsigned m_linkOutMask; + +}; + +#endif diff --git a/rce/rcecalib/config/DummyFormatter.cc b/rce/rcecalib/config/DummyFormatter.cc new file mode 100644 index 00000000..0d743fd9 --- /dev/null +++ b/rce/rcecalib/config/DummyFormatter.cc @@ -0,0 +1,20 @@ +#include "rcecalib/config/DummyFormatter.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/util/exceptions.hh" +#include "ers/ers.h" +#include <iostream> +#include <stdio.h> + +DummyFormatter::DummyFormatter(int id): + AbsFormatter(id){ +} +DummyFormatter::~DummyFormatter(){ +} +void DummyFormatter::configure(boost::property_tree::ptree* config){ +} + +int DummyFormatter::decode (const unsigned int *buffer, int buflen, unsigned* parsedData, int &parsedsize, int &nL1A){ + std::cout<<"Dummy formatter called!"<<std::endl; + return 0; +} + diff --git a/rce/rcecalib/config/DummyFormatter.hh b/rce/rcecalib/config/DummyFormatter.hh new file mode 100644 index 00000000..2febd19f --- /dev/null +++ b/rce/rcecalib/config/DummyFormatter.hh @@ -0,0 +1,13 @@ +#ifndef DUMMYFORMATTER_HH +#define DUMMYFORMATTER_HH + +#include "rcecalib/config/AbsFormatter.hh" + +class DummyFormatter:public AbsFormatter{ +public: + DummyFormatter(int id); + virtual ~DummyFormatter(); + int decode(const unsigned* data, int size, unsigned* parsedData, int &parsedsize, int &nL1A); + void configure(boost::property_tree::ptree* scanOptions); +}; +#endif diff --git a/rce/rcecalib/config/Endianness.hh b/rce/rcecalib/config/Endianness.hh new file mode 100644 index 00000000..8156d423 --- /dev/null +++ b/rce/rcecalib/config/Endianness.hh @@ -0,0 +1,270 @@ +#ifndef ENDIANNESS_H +#define ENDIANNESS_H + + + +/* ---------------------------------------------------------------------- *//*! + + \file Endianness.h + \brief Provides definitions of the ENDIANNESS of the target machine. The + symbols \a ENDIANNESS_IS_LITTLE and \a ENDIANNESS_IS_BIG should be + used in preprocessing directives to determine the endianness of + the machine, while the symbol \a ENDIANNESS can be more easily + used in 'C' code. + \author JJRussell - russell@slac.stanford.edu + +\verbatim + + CVS $Id: Endianness.hh,v 1.2 2010/10/15 11:34:31 wittgen Exp $ +\endverbatim + + \par SYNOPSIS + One of two symbols are defined + - \a ENDIANNESS_IS_LITTLE + - \a ENDIANNESS_IS_BIG. + + \par + As a convenience to the programmer, an overall symbol, \a ENDIANNESS + is also defined. It will take on one of the three values. + + - ENDIANNESS_K_UNKNOWN + - ENDIANNESS_K_LITTLE + - ENDIANNESS_K_BIG + + \par USAGE + One should use this as follows \par + + \code + #if ENDIANNESS_IS_LITTLE + + / * Do little endian kind of things * / + + #elif ENDIANNESS_IS_BIG + + / * Do big endian kind of things * / + + #else + + #error _FILE_ Endianness not determined in this file + + #endif + \endcode + + \par + It is recommended that both BIG and LITTLE conditions are tested for. + This can save one from embarrassing typographical errors. For example, + consider the consequences of the following \par + + \code + + #if ENDIANESS_IS_LITTLE + + / * Do little endian kind of things * / + + #else + + / * Do big endian kind of things * / + + #endif + + \endcode + + \par + It takes a keen eye to note the misspelling of \a ENDIANNESS_IS_LITTLE + as \a ENDIANESS_IS_LITTLE. Since there is no such symbol as + \a ENDIANESS_IS_LITTLE, the 'big' endian kind of things will always be + done. + + \par + It is also recommended that one use \e \#if preprocessor directive over + the \#ifdef form. Either works with the current implementation, but + future implementations reserves the right to support only the \#if + form. + + \par TARGET PLATFORMS + All FSW supported platforms. + */ +/* --------------------------------------------------------------------- */ + + +/* ---------------------------------------------------------------------- *\ + * + * HISTORY WHO WHAT + * ------- --- ------------------------------------------------------- + * 09.28.05 jjr Corrected documentation formating for Doxygen 1.4.4 + * 09.28.05 jjr Added history log + * +\* ---------------------------------------------------------------------- */ + + + + +/* --------------------------------------------------------------------- *//*! + + \def ENDIANNESS_IS_LITTLE + \brief Defined and set to a non-zero value, \a ENDIANNESS_K_LITTLE, if + the target is a little endian machine. + */ +/* --------------------------------------------------------------------- */ + + + + +/* --------------------------------------------------------------------- *//*! + + \def ENDIANNESS_IS_BIG + \brief Defined and set to a non-zero value, \a ENDIANNESS_BIG, if + the target is a big endian machine. + */ +/* --------------------------------------------------------------------- */ + + + + + +/* --------------------------------------------------------------------- *//*! + + \def ENDIANNESS_K_UNKNOWN + \brief Value of ENDIANNESS the endianness of the target is undefined. + */ +/* --------------------------------------------------------------------- */ +#define ENDIANNESS_K_UNKNOWN 0 +/* --------------------------------------------------------------------- */ + + +/* --------------------------------------------------------------------- *//*! + + \def ENDIANNESS_K_LITTLE + \brief Value of ENDIANNESS if the target is a little endian machine. + */ +/* --------------------------------------------------------------------- */ +#define ENDIANNESS_K_LITTLE 1 +/* --------------------------------------------------------------------- */ + + +/* --------------------------------------------------------------------- *//*! + + \def ENDIANNESS_K_BIG + \brief Value of ENDIANNESS if the target is a big endian machine + machine. + */ +/* --------------------------------------------------------------------- */ +#define ENDIANNESS_K_BIG 2 +/* --------------------------------------------------------------------- */ + + + + +/* --------------------------------------------------------------------- *//*! + + \def ENDIANNESS + \brief \a ENDINANESS assumes one of the values, + \li \a ENDIANNESS_K_LITTLE + \li \a ENDIANNESS_K_BIG + \li \a ENDIANNESS_K_UNKNOWN. + + + \note + Since DOXYGEN does not have access to the full set of compile time + preprocessor symbols, \a ENDIANNESS will appear to be defined as + \a ENDIANNESS_K_UNKNOWN. + + \warning + It is not recommended that this symbol be used in preprocessor + directives to determine the endianness of the machine. Use + \a ENDIANNESS_IS_LITTLE or \a ENDIANNESS_IS_BIG. Why? To do this + correctly one must use the following long-winded style: \par + + \code + if defined (ENDIANNESS) && (ENDIANNESS == ENDIANNESS_K_LITTLE) + { + . + . + } + elif defined (ENDIANNESS) && (ENDIANNESS == ENDIANNESS_K_BIG) + { + . + . + } + else + { + . + / * Endianness unknown * / + } + \endcode + + \par + The check for \a ENDIANNESS being defined is mandatory for robustness. + If the user forgets to include "PBI/Endiannness.h", all the \e ENDIANNESS + symbols are, in fact, undefined. Without the check that \a ENDIANNESS + is defined, the simple check of (\a ENDIANNESS == \a ENDIANNESS_K_LITTLE) + will \b always succeed, causing the big endian if clause to always be + taken. If the code is developed on a big endian machine, it is only + when the code is ported to a little endian machine will the problem + show up as malfunctioning code which the poor developer will eventually + trace to the ill-constructed endianness determination. + */ +/* --------------------------------------------------------------------- */ + +#if defined(__LITTLE_ENDIAN__) && (__BIG_ENDIAN__) + + # define ENDIANNESS_IS_LITTLE ENDIANNESS_K_UNKNOWN + # define ENDIANNESS_IS_BIG ENDIANNESS_K_UNKNOWN + + # undef ENDIANNESS_IS_LITTLE + # undef ENDIANNESS_IS_BIG + + #error "Endianness.h:found both __BIG_ENDIAN__ and __LITTLE_ENDIAN defined" + +#else +/* MW fix for gcc version > 4.1 */ +#if defined(__i386) || defined(i386) || defined(__IEEE_LITTLE_ENDIAN) || (__LITTLE_ENDIAN_) + + + # define ENDIANNESS_IS_LITTLE ENDIANNESS_K_LITTLE + # define ENDIANNESS ENDIANNESS_K_LITTLE +// #warning "Little endian" + + + #elif defined(__sparc) || defined(__IEEE_BIG_ENDIAN) || (__BIG_ENDIAN__) + + # define ENDIANNESS_IS_BIG ENDIANNESS_K_BIG + # define ENDIANNESS ENDIANNESS_K_BIG +// #warning "Big endian" + + #else + + # define ENDIANNESS ENDIANNESS_K_UNKNOWN + + /* + | From a programming standpoint this not necessary, but since + | DOXYGEN does not have access to the full set of compile time + | preprocessor symbols, the first two clauses will not define + | ENDIANNESS_IS_LITTLE or ENDIAN_IS_BIG, causing DOXYGEN to complain + | about documented, but undefined symbols. In effect, these two + | statements are just to keep DOXYGEN from spitting out compliants. + */ + # define ENDIANNESS_IS_LITTLE ENDIANNESS_K_UNKNOWN + # define ENDIANNESS_IS_BIG ENDIANNESS_K_UNKNOWN + + # undef ENDIANNESS_IS_LITTLE + # undef ENDIANNESS_IS_BIG + + # error "Endianness.h: Cannot determine the endianness of the machine" + + #endif +#endif +/* --------------------------------------------------------------------- */ + + +#endif + + + + + + + + + + diff --git a/rce/rcecalib/config/EventFromDspTrigger.cc b/rce/rcecalib/config/EventFromDspTrigger.cc new file mode 100644 index 00000000..d6326ac2 --- /dev/null +++ b/rce/rcecalib/config/EventFromDspTrigger.cc @@ -0,0 +1,93 @@ +#include "rcecalib/config/EventFromDspTrigger.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/config/TriggerReceiverIF.hh" +#include "rcecalib/legacy/dsp_types.h" +#include "rcecalib/legacy/sysParams_specific.h" +#include "rcecalib/legacy/histogram.h" +#include "rcecalib/legacy/histogramCtrl.h" + +#include <iostream> + + + + +EventFromDspTrigger::EventFromDspTrigger():AbsTrigger(){ + m_inpf.open("/reg/lab1/home/wittgen/data/___slave_dump___",std::ios::binary); + unsigned int file_header[3]; + if(m_inpf.is_open()) { + m_inpf.read((char*)&file_header,sizeof(file_header)); + unsigned int nFrames=file_header[1]; + unsigned int nWords=file_header[2]; + std::cout << nFrames << " " << nWords <<std::endl; + HistogramOptions histogramOptions; + m_inpf.read((char*)&histogramOptions,sizeof(HistogramOptions)); + std::cout<<"nTriggers= "<<histogramOptions.nTriggers<<std::endl; + std::cout<<"nFrames= "<<nFrames<<std::endl; + std::cout<<"nTriggers= "<<histogramOptions.nTriggers<<std::endl; + std::cout<<"nBins= "<<histogramOptions.nBins[0]<<std::endl; + std::cout<<"nModules= "<<histogramOptions.nModules<<std::endl; + histogramOptions.nMaskStages--; + std::cout<<"nMaskStages= "<<histogramOptions.nMaskStages<<std::endl; + + std::cout<<"maskStageBegin= "<<histogramOptions.maskStageBegin<<std::endl; + std::cout<<"type= "<<histogramOptions.type<<std::endl; + std::cout<<"maskStageTotalSteps= "<<histogramOptions.maskStageTotalSteps<<std::endl; + + + + m_nBins=histogramOptions.nBins[0]; + m_nStages=histogramOptions.nMaskStages; + } + m_inpf.read((char *) &m_frame_header,sizeof(m_frame_header)); + m_bin=m_frame_header[2]; + m_stage=m_frame_header[3]; + m_frameSize=m_frame_header[1]; + m_inpf.read((char*) &m_frame,m_frameSize*sizeof(unsigned int)); + m_inpf.read((char*) &m_frame_trailer,sizeof(m_frame_trailer)); + +} + + +int EventFromDspTrigger::sendTrigger(){ + // static int count=0; + static int eof=0; + static int bof=0; + static int hits=0; + static int skipframe=0; + static int newEvent=0; + + + + newEvent=0;hits=0; + do { + if(!skipframe) { + if(m_frame[255]==0xe0f00000) skipframe=1; + for(int i=0;i<m_frameSize;i++) { + if((m_frame[i]&0xffff0000)==0xb0f00000) {bof++;} + if((m_frame[i]>>28)==0x8) { + m_event[hits]=m_frame[i]; + hits++; + } + if((m_frame[i]&0xffff0000)==0xe0f00000) {eof++;newEvent=1;break;} + } + } else skipframe=0; + + m_inpf.read((char *) &m_frame_header,sizeof(m_frame_header)); + m_bin=m_frame_header[2]; + m_stage=m_frame_header[3]; + m_frameSize=m_frame_header[1]; + m_inpf.read((char*) &m_frame,m_frameSize*sizeof(unsigned int)); + m_inpf.read((char*) &m_frame_trailer,sizeof(m_frame_trailer)); + + } while(!m_inpf.eof() && m_bin<m_nBins && m_stage<m_nStages && !newEvent); + // std::cout << "send Trigger "<< count++ << std::endl; + TriggerReceiverIF::receive(&m_event[0],hits); + m_i++; + // if(m_i%100==0) std::cout << "trigger " << m_i<<std::endl; + + return 0; +} + + + diff --git a/rce/rcecalib/config/EventFromDspTrigger.hh b/rce/rcecalib/config/EventFromDspTrigger.hh new file mode 100644 index 00000000..b3a76145 --- /dev/null +++ b/rce/rcecalib/config/EventFromDspTrigger.hh @@ -0,0 +1,28 @@ +#ifndef EVENTFROMDSPRIGGER_HH +#define EVENTFROMDSPTRIGGER_HH +#include <fstream> +#include "rcecalib/config/AbsTrigger.hh" +#include <vector> + + + class EventFromDspTrigger: public AbsTrigger{ + public: + EventFromDspTrigger(); + ~EventFromDspTrigger(){if(m_inpf.is_open()) m_inpf.close();}; + int sendTrigger(); + int enableTrigger(bool on){return 0;} + private: + unsigned m_event[2048]; + std::ifstream m_inpf; + int m_bin; + int m_stage; + int m_nBins; + int m_nStages; + int m_frameSize; + unsigned int m_frame_header[4]; + unsigned int m_frame_trailer; + unsigned int m_frame[256]; + }; + + +#endif diff --git a/rce/rcecalib/config/EventFromFileTrigger.cc b/rce/rcecalib/config/EventFromFileTrigger.cc new file mode 100644 index 00000000..57631f74 --- /dev/null +++ b/rce/rcecalib/config/EventFromFileTrigger.cc @@ -0,0 +1,29 @@ + +#include "rcecalib/config/EventFromFileTrigger.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/config/TriggerReceiverIF.hh" +#include <iostream> +#include <fstream> + + + +EventFromFileTrigger::EventFromFileTrigger():AbsTrigger(){ + //std::cout<<"eventfromfiletrigger"<<std::endl; + std::ifstream flog("/nfs/event1.txt"); + while(!flog.eof()){ + unsigned word; + flog>>std::hex>>word; + m_event.push_back((word<<16)|(word>>16)); + } + m_event.push_back(0); + } + + + int EventFromFileTrigger::sendTrigger(){ + TriggerReceiverIF::receive(&m_event[0],m_event.size()); + m_i++; + return 0; + } + + diff --git a/rce/rcecalib/config/EventFromFileTrigger.hh b/rce/rcecalib/config/EventFromFileTrigger.hh new file mode 100644 index 00000000..0a4419c1 --- /dev/null +++ b/rce/rcecalib/config/EventFromFileTrigger.hh @@ -0,0 +1,19 @@ +#ifndef EVENTFROMFILETRIGGER_HH +#define EVENTFROMFILETRIGGER_HH + +#include "rcecalib/config/AbsTrigger.hh" +#include <vector> + + + class EventFromFileTrigger: public AbsTrigger{ + public: + EventFromFileTrigger(); + ~EventFromFileTrigger(){}; + int sendTrigger(); + int enableTrigger(bool on){return 0;} + private: + std::vector<unsigned> m_event; + }; + + +#endif diff --git a/rce/rcecalib/config/FEI3/CrosstalkMaskStaging.cc b/rce/rcecalib/config/FEI3/CrosstalkMaskStaging.cc new file mode 100644 index 00000000..1538c87d --- /dev/null +++ b/rce/rcecalib/config/FEI3/CrosstalkMaskStaging.cc @@ -0,0 +1,42 @@ +#include "rcecalib/config/FEI3/CrosstalkMaskStaging.hh" +#include "rcecalib/config/FEI3/Module.hh" + +namespace FEI3{ + + CrosstalkMaskStaging::CrosstalkMaskStaging(FEI3::Module* mod, Masks masks, std::string type) + :MaskStaging<FEI3::Module>(mod, masks, type){ + m_nStages=2880; + } + + void CrosstalkMaskStaging::setupMaskStageHW(int maskStage){ + if(maskStage % Frontend::N_ROWS < 2 || maskStage % Frontend::N_ROWS == 159){ + clearBitsHW(); + for (int i=0;i<Module::N_FRONTENDS;i++){ + int nPixelsPerChip = Frontend::N_ROWS * Frontend::N_COLS; + for(int index=maskStage;index<nPixelsPerChip;index+=m_nStages){ + int row = (int) index % Frontend::N_ROWS; + int col = (int) index / Frontend::N_ROWS; + if( col%2 ) row = 159 - row; + PixelRegister *pixel=m_module->frontend(i)->getPixelRegister(col,row); + pixel->set(pixel->get() | m_masks.xtalk_on); + if(row<159){ + PixelRegister *pixelm=m_module->frontend(i)->getPixelRegister(col,row+1); + pixelm->set(pixelm->get() | m_masks.xtalk_off); + } + if(row>0){ + PixelRegister *pixell=m_module->frontend(i)->getPixelRegister(col,row-1); + pixell->set(pixell->get() | m_masks.xtalk_off); + } + } + } + m_module->configureHW(); + }else{ + m_module->resetHW(false); // only reset MCC, not FE + m_module->mcc()->configureHW(); + //std::cout<<"Shifting enables"<<std::endl; + for (int i=0;i<Module::N_FRONTENDS;i++){ + m_module->frontend(i)->shiftEnablesHW(m_masks.iMask); + } + } + } +} diff --git a/rce/rcecalib/config/FEI3/CrosstalkMaskStaging.hh b/rce/rcecalib/config/FEI3/CrosstalkMaskStaging.hh new file mode 100644 index 00000000..10091ca4 --- /dev/null +++ b/rce/rcecalib/config/FEI3/CrosstalkMaskStaging.hh @@ -0,0 +1,19 @@ +#ifndef FEI3CROSSTALKMASKSTAGING_HH +#define FEI3CROSSTALKMASKSTAGING_HH + +#include "rcecalib/config/Masks.hh" +#include "rcecalib/config/MaskStaging.hh" + +namespace FEI3{ + class Module; + + class CrosstalkMaskStaging: public MaskStaging<FEI3::Module>{ + public: + CrosstalkMaskStaging(FEI3::Module* module, Masks masks, std::string type); + void setupMaskStageHW(int maskStage); + private: + int m_nStages; + }; + +} +#endif diff --git a/rce/rcecalib/config/FEI3/FECommands.cc b/rce/rcecalib/config/FEI3/FECommands.cc new file mode 100644 index 00000000..42d55c43 --- /dev/null +++ b/rce/rcecalib/config/FEI3/FECommands.cc @@ -0,0 +1,63 @@ + +#include "rcecalib/config/FEI3/FECommands.hh" + +namespace FEI3{ + + void FECommands::mccWriteRegister(BitStream *bs, Mcc::Register reg, unsigned value){ + bs->push_back(0x1); /* header (10110) + field2 (1011) + field3 (0000) */ + bs->push_back(0x6B000000 | (reg << 16) | (value & 0xffff)); /* field4 = (address(3:0)) + data(15:0) */ + bs->push_back(0); // padding a la NewDsp + } + void FECommands::resetMCC(BitStream *bs){ + bs->push_back(0x16B900); + bs->push_back(0); // padding a la NewDsp + } + void FECommands::resetFE(BitStream *bs, unsigned width) { + bs->push_back(0x16BA00 | (width & 0xf)); + bs->push_back(0); + } + void FECommands::enableDataTaking(BitStream *bs) { + bs->push_back(0); + bs->push_back(0x0016B800); + bs->push_back(0); + } + void FECommands::L1A(BitStream *bs){ + bs->push_back(0xE8000000); + } + void FECommands::sendECR(BitStream *bs){ + bs->push_back(0); + bs->push_back(0x00162000); /* MCC ECR command */ + bs->push_back(0); + } + void FECommands::sendBCR(BitStream *bs){ + bs->push_back(0); + bs->push_back(0x00161000); /* MCC BCR command */ + bs->push_back(0); + } + void FECommands::feWriteCommand(BitStream *bs, unsigned chip, int cmd, bool rw){ + if(rw){ + bs->push_back(0x16B50); + }else{ + bs->push_back(0x16B40); // write only + } + unsigned mask = 0x00800000; + unsigned command=cmd; + unsigned parity = 0; + for(int k=1;k<24;++k,mask>>=1) { + if(mask & command) parity ^= 1; + } + command |= parity; + command <<= 5; /* for geographical address */ + command |= chip; + for(int k=7;k>-1;--k) { + unsigned word=0; + for (int i=3;i>=0;i--){ + word<<=8; + if((command>>(k*4+i))&0x1)word|=0xff; + } + bs->push_back(word); + } + } + + +}; diff --git a/rce/rcecalib/config/FEI3/FECommands.hh b/rce/rcecalib/config/FEI3/FECommands.hh new file mode 100644 index 00000000..c64e0da1 --- /dev/null +++ b/rce/rcecalib/config/FEI3/FECommands.hh @@ -0,0 +1,46 @@ +#ifndef FECOMMANDS_FEI3_HH +#define FECOMMANDS_FEI3_HH + +#include "rcecalib/HW/BitStream.hh" +#include "rcecalib/config/FEI3/Mcc.hh" + +namespace FEI3{ + + class FECommands{ + public: + enum Command{ + FE_CMD_NULL=0x000000, + FE_CMD_REF_RESET=0x000002, + FE_CMD_SOFT_RESET=0x00000C , + FE_CMD_CLOCK_GLOBAL=0x000010, + FE_CMD_WRITE_GLOBAL=0x000060, + FE_CMD_READ_GLOBAL=0x000080, + FE_CMD_CLOCK_PIXEL=0x000100, + FE_CMD_WRITE_HITBUS=0x000200, + FE_CMD_WRITE_SELECT=0x000400, + FE_CMD_WRITE_MASK=0x000800, + FE_CMD_WRITE_TDAC0=0x001000, + FE_CMD_WRITE_TDAC1=0x002000, + FE_CMD_WRITE_TDAC2=0x004000, + FE_CMD_WRITE_TDAC3=0x008000, + FE_CMD_WRITE_TDAC4=0x010000, + FE_CMD_WRITE_TDAC5=0x020000, + FE_CMD_WRITE_TDAC6=0x040000, + FE_CMD_WRITE_FDAC0=0x080000, + FE_CMD_WRITE_FDAC1=0x100000, + FE_CMD_WRITE_FDAC2=0x200000, + FE_CMD_WRITE_KILL=0x400000, + FE_CMD_READ_PIXEL=0x800000}; + static void mccWriteRegister(BitStream* bs, Mcc::Register reg, unsigned value); + static void resetMCC(BitStream *bs); + static void resetFE(BitStream* bs, unsigned width); + static void enableDataTaking(BitStream *bs); + static void L1A(BitStream *bs); + static void sendECR(BitStream *bs); + static void sendBCR(BitStream *bs); + static void feWriteCommand(BitStream* bs, unsigned chip, int cmd, bool rw=0); + }; + +}; +#endif + diff --git a/rce/rcecalib/config/FEI3/Frontend.cc b/rce/rcecalib/config/FEI3/Frontend.cc new file mode 100644 index 00000000..ffc32a9e --- /dev/null +++ b/rce/rcecalib/config/FEI3/Frontend.cc @@ -0,0 +1,204 @@ + +#include "rcecalib/config/FEI3/Frontend.hh" +#include "rcecalib/config/FEI3/FECommands.hh" +#include "rcecalib/HW/SerialIF.hh" +#include <iostream> + +namespace FEI3{ + + Frontend::Frontend(unsigned chip):m_chip(chip){ + m_global=new GlobalRegister(chip, chip); + } + Frontend::~Frontend(){ + delete m_global; + } + void Frontend::setChipAddress(unsigned i, unsigned addr){ + if(i<16 && addr<16){ + if(m_chip!=addr){ // cannot use the cached global register + delete m_global; + m_global=new GlobalRegister(i, addr); + std::cout<<"Creating new GlobalRegister position "<<i<<" address "<<addr<<std::endl; + } + m_chip=addr; + } + } + + void Frontend::writeGlobalRegisterHW(){ + //std::cout<<"write global register chip "<<m_chip<<std::endl; + m_global->writeHW(); + } + void Frontend::setGlobalRegField(const char* name, int val){ + m_global->setField(name,val); + } + + void Frontend::setPixelParameter(PixelRegister::Field field, int val){ + for(int j=0;j<N_COLS;j++){ + for (int i=0;i<N_ROWS;i++){ + m_pixel[j][i].setField(field, val); + } + } + for(unsigned int i=fieldPos[field]; i<fieldPos[field+1];i++){ + writePixelRegisterHW(i); + } + } + + void Frontend::writePixelRegisterHW(unsigned bit){ + //std::cout<<"write pixel register "<<bit<<" in chip "<<m_chip<<std::endl; + BitStream *bs=new BitStream; + BitStreamUtils::prependZeros(bs); + unsigned nPixelsPerChip = Frontend::N_COLS * Frontend::N_ROWS; + unsigned dcnt = nPixelsPerChip; /* all column pairs */ + unsigned cnt = (dcnt << 3) | 4; + FECommands::mccWriteRegister(bs, Mcc::MCC_CNT, cnt); + FECommands::feWriteCommand(bs,m_chip, FECommands::FE_CMD_CLOCK_PIXEL); + pixelUsrToRaw(bs, bit); + bs->push_back(0);// one clean word afterwards + cnt = 4; + FECommands::mccWriteRegister(bs, Mcc::MCC_CNT, cnt); + FECommands::feWriteCommand(bs, m_chip, FECommands::FE_CMD_WRITE_HITBUS << bit); + bs->push_back(0); + FECommands::feWriteCommand(bs, m_chip, FECommands::FE_CMD_NULL); + bs->push_back(0); + SerialIF::send(bs); + delete bs; +} + + void Frontend::pixelUsrToRaw(BitStream *bs, unsigned bit){ + int col; + unsigned row; + unsigned short *pixelReg, mask; + mask = (1 << bit); + col = 0; + /* form the snake pattern */ + col = Frontend::N_COLS - 1; /* the last column */ + while(col > 0) { /* works because we are decrementing by 2 each loop. otherwise, > -1 */ + pixelReg = (unsigned short*)&m_pixel[col][0]; + --col; + for(row=0;row<Frontend::N_ROWS/sizeof(unsigned);++row){ + unsigned word=0; + for(int i=0;i<4;i++){ + word<<=8; + word|= (*pixelReg++ & mask) ? 0xff : 0x00; /* upwards */ + } + bs->push_back(word); + } + pixelReg = (unsigned short*)&m_pixel[col][Frontend::N_ROWS-1]; + --col; + for(row=0;row<Frontend::N_ROWS/sizeof(unsigned);++row){ + unsigned word=0; + for(int i=0;i<4;i++){ + word<<=8; + word |= (*pixelReg-- & mask) ? 0xff : 0x00; /* backwards */ + } + bs->push_back(word); + } + } + } + void Frontend::setVcalCoeff(unsigned i, float val){ + if(i<4)m_vcalCoeff[i]=val; + } + void Frontend::setCapVal(unsigned i, float val){ + if(i<2)m_capVal[i]=val; + } + float Frontend::getVcalCoeff(unsigned i){ + if(i<4)return m_vcalCoeff[i]; + else return -999; + } + float Frontend::getCapVal(unsigned i){ + if(i<2)return m_capVal[i]; + else return -999; + } + + // TODO: get rid of float + const float Frontend::dacToElectrons(int dac){ + bool isChigh=m_global->getField("enableCinjHigh"); + float capacity = 6.241495961*(isChigh ? m_capVal[1] : m_capVal[0]); + float fldac=(float)dac; + return capacity*(m_vcalCoeff[0] + (m_vcalCoeff[1] + (m_vcalCoeff[2] + m_vcalCoeff[3]*fldac)*fldac)*fldac); + } + + const int Frontend::electronsToDac(float ne) { + float min=10000.; + int mini=-1; + for(int i=0;i<1024;i++) { + float diff=(ne-dacToElectrons(i)); + if(diff<0.) diff=-diff; + if(diff<min) { + min=diff;mini=i; + } + } + return mini; + } + + + PixelRegister* Frontend::getPixelRegister(unsigned col, unsigned row){ + return &m_pixel[col][row]; + } + + void Frontend::configureHW(){ + m_global->enableAll(); + //std::cout<<"write global register chip "<<m_chip<<std::endl; + m_global->writeHW(); + for (int i=0;i<N_PIXEL_REGISTER_BITS;i++){ + writePixelRegisterHW(i); + } + } + + void Frontend::shiftEnablesHW(unsigned short bitmask){ + m_global->enableAll(); + //global bitstream is cached + m_global->setField("doMux",11); + BitStream* bitStream=new BitStream; + for (int bit=0;bit<N_PIXEL_REGISTER_BITS;bit++){ + if(bitmask & (1<<bit)){ + m_global->writeHW(); + int cnt = 4; + FECommands::mccWriteRegister(bitStream, Mcc::MCC_CNT, cnt); + FECommands::feWriteCommand(bitStream, m_chip, FECommands::FE_CMD_READ_PIXEL); + bitStream->push_back(0); + FECommands::feWriteCommand(bitStream, m_chip, (FECommands::FE_CMD_WRITE_HITBUS << bit) | + FECommands::FE_CMD_READ_PIXEL); + + bitStream->push_back(0); + int dcnt = 2; + cnt = (dcnt << 3) | 4; + FECommands::mccWriteRegister(bitStream, Mcc::MCC_CNT, cnt); + FECommands::feWriteCommand(bitStream, m_chip, (FECommands::FE_CMD_WRITE_HITBUS << bit) | + FECommands::FE_CMD_READ_PIXEL | FECommands::FE_CMD_CLOCK_PIXEL); + bitStream->push_back(0); + bitStream->push_back(0); + bitStream->push_back(0); + + cnt = 4; + FECommands::mccWriteRegister(bitStream, Mcc::MCC_CNT, cnt); + FECommands::feWriteCommand(bitStream, m_chip, (FECommands::FE_CMD_WRITE_HITBUS << bit) | + FECommands::FE_CMD_READ_PIXEL); + + bitStream->push_back(0); + FECommands::feWriteCommand(bitStream, m_chip, FECommands::FE_CMD_READ_PIXEL); + bitStream->push_back(0); + FECommands::feWriteCommand(bitStream, m_chip, FECommands::FE_CMD_NULL); + + bitStream->push_back(0); + dcnt = 1; // was npixels which always seems to be 1 + cnt = (dcnt << 3) | 4; + FECommands::mccWriteRegister(bitStream, Mcc::MCC_CNT, cnt); + + FECommands::feWriteCommand(bitStream, m_chip, FECommands::FE_CMD_CLOCK_PIXEL); + bitStream->push_back(0); + + cnt = 4; + FECommands::mccWriteRegister(bitStream, Mcc::MCC_CNT, cnt); + FECommands::feWriteCommand(bitStream, m_chip, FECommands::FE_CMD_WRITE_HITBUS << bit); + bitStream->push_back(0); + FECommands::feWriteCommand(bitStream, m_chip, FECommands::FE_CMD_NULL); + bitStream->push_back(0); + SerialIF::send(bitStream); + } + } + delete bitStream; + m_global->setField("doMux",8); + m_global->writeHW(); + } + +}; diff --git a/rce/rcecalib/config/FEI3/Frontend.hh b/rce/rcecalib/config/FEI3/Frontend.hh new file mode 100644 index 00000000..1146532e --- /dev/null +++ b/rce/rcecalib/config/FEI3/Frontend.hh @@ -0,0 +1,42 @@ +#ifndef FEI3__FRONTEND_HH +#define FEI3__FRONTEND_HH + +#include "rcecalib/HW/BitStream.hh" +#include "rcecalib/config/FEI3/GlobalRegister.hh" +#include "rcecalib/config/FEI3/PixelRegister.hh" + +namespace FEI3{ + + class Frontend{ + public: + Frontend(unsigned chip); + ~Frontend(); + enum{N_COLS=18, N_ROWS=160 ,N_PIXEL_REGISTER_BITS=14}; + void setChipAddress(unsigned i, unsigned addr); + void setVcalCoeff(unsigned i, float val); + void setCapVal(unsigned i, float val); + float getVcalCoeff(unsigned i); + float getCapVal(unsigned i); + void writePixelRegisterHW(unsigned bit); + void writeGlobalRegisterHW(); + void setGlobalRegField(const char *name, int val); + void setPixelParameter(PixelRegister::Field field, int val); + void configureHW(); + void shiftEnablesHW(unsigned short bitmask); + PixelRegister* getPixelRegister(unsigned col, unsigned row); + GlobalRegister* getGlobalRegister(){return m_global;} + const float dacToElectrons(int dac); + const int electronsToDac(float ne); + + private: + void pixelUsrToRaw(BitStream *bs, unsigned bit); + unsigned m_chip; + GlobalRegister *m_global; + PixelRegister m_pixel[N_COLS][N_ROWS]; + float m_vcalCoeff[4]; + float m_capVal[2]; + }; + +}; + +#endif diff --git a/rce/rcecalib/config/FEI3/GlobalRegister.cc b/rce/rcecalib/config/FEI3/GlobalRegister.cc new file mode 100644 index 00000000..bba6aef0 --- /dev/null +++ b/rce/rcecalib/config/FEI3/GlobalRegister.cc @@ -0,0 +1,235 @@ + +#include "rcecalib/config/FEI3/GlobalRegister.hh" +#include "rcecalib/config/FEI3/FECommands.hh" +#include "rcecalib/HW/SerialIF.hh" +#include <iostream> +#include "ers/ers.h" +#include <stdio.h> + +namespace FEI3{ + + GlobalRegister::GlobalRegister(unsigned fe, unsigned chip){ + // initialize static field dictionay + if(!m_initialized)initialize(); + + //now build the write global register stream which will be cached. + // enable the front end + BitStreamUtils::prependZeros(&m_bitStream); + FECommands::mccWriteRegister(&m_bitStream, Mcc::MCC_FEEN, (1 << fe)); + + // cnt register with dcnt = # of global register bits = 231 + unsigned dcnt = FE_I3_N_GLOBAL_BITS; + unsigned cnt = (dcnt << 3) | 4; + FECommands::mccWriteRegister(&m_bitStream, Mcc::MCC_CNT, cnt); + + // clock in the global register. + FECommands::feWriteCommand(&m_bitStream, chip, FECommands::FE_CMD_CLOCK_GLOBAL); + // remember the index at which the global register itself will go + unsigned globalReg=m_bitStream.size(); + // initialize the register with zeroes. + unsigned gsize=(m_pos+sizeof(unsigned)-1)/sizeof(unsigned); + for(unsigned int i=0;i<gsize;i++)m_bitStream.push_back(0); + + // cnt register with dcnt = 0 + cnt = 4; + FECommands::mccWriteRegister(&m_bitStream, Mcc::MCC_CNT, cnt); + + // issue a write global + FECommands::feWriteCommand(&m_bitStream, chip, FECommands::FE_CMD_WRITE_GLOBAL); + m_bitStream.push_back(0); + FECommands::feWriteCommand(&m_bitStream, chip, FECommands::FE_CMD_NULL); + m_bitStream.push_back(0); + + // byte swap because the global register is big endian + //BitStreamUtils::byteSwap(&m_bitStream); + //set the pointer to the location of the global register + m_data=(unsigned char*)&m_bitStream[globalReg]; + } + GlobalRegister::~GlobalRegister(){ + } + void GlobalRegister::writeHW(){ + //SerialIF::send(&m_bitStream,SerialIF::DONT_CLEAR, SerialIF::BYTESWAP); + SerialIF::send(&m_bitStream,SerialIF::DONT_CLEAR); + } + + void GlobalRegister::setField(const char* name, unsigned val){ + char msg[128]; + sprintf(msg,"parameter %s is invalid",name); + ERS_ASSERT_MSG(m_fields.find(name)!=m_fields.end(),msg); + FieldParams params=m_fields[name]; + unsigned parity=0; + if(params.parity==true) + parity=getField("parity"); + unsigned char par; + for (unsigned int i=0;i<params.width;i++){ + unsigned char bit=(val>>(params.width-1-i))&0x1; + unsigned char bit5mhz= bit ? 0xff : 0; + if(params.parity){ + par=bit5mhz ^ m_data[params.position+i]; + parity ^= par; + } + m_data[params.position+i]=bit5mhz; + } + if(params.parity){ + setField("parity",parity); + } + } + + unsigned GlobalRegister::getField(const char* name){ + ERS_ASSERT_MSG(m_fields.find(name)!=m_fields.end(),"parameter name is invalid"); + FieldParams params=m_fields[name]; + unsigned retval=0; + for (unsigned int i=0;i<params.width;i++){ + retval<<=1; + if(m_data[params.position+i]) retval|=1; + } + return retval; + } + void GlobalRegister::enableAll(){ + setField("enableCP0",1); + setField("enableCP1",1); + setField("enableCP2",1); + setField("enableCP3",1); + setField("enableCP4",1); + setField("enableCP5",1); + setField("enableCP6",1); + setField("enableCP7",1); + setField("enableCP8",1); + setField("doMux",8); +} + + + std::string GlobalRegister::lookupParameter(const char* name){ + // check if this is the last name used, return cached value + if(name==m_cachedName)return m_cachedField; + // Now check if we can translate the name to a field name + if(m_parameters.find(name)!=m_parameters.end()){ + //cache result + m_cachedName=name; + m_cachedField=m_parameters[name]; + return m_cachedField; + // maybe it's a proper field name? + } else if (m_fields.find(name)!=m_fields.end()){ + m_cachedName=name; + m_cachedField=name; + return m_cachedField; + } + // not found. + else return ""; + } + void GlobalRegister::addParameter(const char* name, const char* field){ + m_parameters[name]=field; + } + void GlobalRegister::addField(const char* name,unsigned width, bool parity){ + FieldParams temp; + temp.position=m_pos; + temp.width=width; + temp.parity=parity; + m_fields[name]=temp; + m_pos+=width; + } + + std::map<std::string, FieldParams > GlobalRegister::m_fields; + std::map<std::string, std::string> GlobalRegister::m_parameters; + unsigned GlobalRegister::m_pos = 0; + bool GlobalRegister::m_initialized = false; + std::string GlobalRegister::m_cachedName; + std::string GlobalRegister::m_cachedField; + + void GlobalRegister::initialize(){ + addField("enableIpMonitor",1); + addField("enableBiasComp",1); + addField("enableTune",1); + addField("gTDac",5); + addField("enableHitbus",1); + addField("enableCP0",1); + addField("modeTOTThresh",2); + addField("threshTOTDouble",8); + addField("threshTOTMinimum",8); + addField("enableCP1",1); + addField("testDacIL2Dac",1); + addField("dacIL2",8); + addField("dacIL",8); + addField("testDacILDac",1); + addField("enableCP2",1); + addField("testDacForITH2Dac",1); + addField("dacITH2",8); + addField("dacITH1",8); + addField("testDacForITH1Dac",1); + addField("enableCP3",1); + addField("enableDigitalInject",1); + addField("CEUClockControl",2); + addField("eocMux",2); + addField("enableTestAnalogRef",1); + addField("enableExternalInj",1); + addField("enableCinjHigh",1); + addField("enableCP4",1); + addField("testDacForVCalDac",1); + addField("dacVCAL",10); + addField("dacITRIMIF",8); + addField("testDacForITrimIfDac",1); + addField("enableCP5",1); + addField("testDacForIFDac",1); + addField("dacIF",8); + addField("dacITRIMTH",8); + addField("testDacForITrimThDac",1); + addField("enableCP6",1); + addField("testDacForIPDac",1); + addField("dacIP",8); + addField("dacIP2",8); + addField("testDacForIP2Dac",1); + addField("enableCP7",1); + addField("testDacForIDDac",1); + addField("dacID",8); + addField("dacIVDD2",8); + addField("testDacForIVDD2Dac",1); + addField("enableCP8",1); + addField("enableBufferBoost",1); + addField("enableLeakMeas",1); + addField("enableVCalMeas",1); + addField("enableTestPixelMux",2); + addField("enableAnalogOut",1); + addField("enableCapTest",1); + addField("capMeasCircuitry",6); + addField("dRegMeas",2); + addField("enableDRegMeas",1); + addField("dRegTrim",2); + addField("enableLVDSRefMeas",1); + addField("enableAReg",1); + addField("aRegMeas",2); + addField("enableARegMeas",1); + addField("aRegTrim",2); + addField("monLeakADCMonComp",1, 0); // does not contribute to parity + addField("monLeakADCEnableComparator",1); + addField("monLeakDACTest",1); + addField("monLeakADCDAC",10); + addField("monLeakADCRefTest",1); + addField("hitBusScaler",8, 0); // does not contribute to parity + addField("enableEOEParity",1); + addField("selectDataPhase",1); + addField("tsiTscEnable",1); + addField("selectMonHit",4); + addField("doMux",4); + addField("enableHitParity",1); + addField("enableSelfTrigger",1); + addField("selfTriggerWidth",4); + addField("selfTriggerDelay",4); + addField("latency",8); + addField("parity",1, 0); + addField("rsvd",1, 0);/*to ensure word alignment*/ + + // Translation from scan parameter to Global register field + addParameter("LATENCY", "latency"); + addParameter("GDAC", "gTDac"); + addParameter("VCAL", "dacVCAL"); + addParameter("IF", "dacIF"); + m_initialized=true; + } + void GlobalRegister::dump(){ + std::cout<<"Global Register"<<std::endl; + for(std::map<std::string, FieldParams>::iterator it=m_fields.begin(); it!=m_fields.end();it++){ + std::cout<<it->first<<" "<<getField(it->first.c_str())<<std::endl; + } + } + +}; diff --git a/rce/rcecalib/config/FEI3/GlobalRegister.hh b/rce/rcecalib/config/FEI3/GlobalRegister.hh new file mode 100644 index 00000000..45ca255a --- /dev/null +++ b/rce/rcecalib/config/FEI3/GlobalRegister.hh @@ -0,0 +1,44 @@ +#ifndef GLOBALREGISTER_FEI3_HH +#define GLOBALREGISTER_FEI3_HH + +#include <map> +#include <string> +#include "rcecalib/HW/BitStream.hh" + +namespace FEI3{ + + struct FieldParams{ + unsigned position; + unsigned width; + bool parity; + }; + + class GlobalRegister{ + public: + GlobalRegister(unsigned fe, unsigned chip); + ~GlobalRegister(); + void setField(const char* name, unsigned val); + unsigned getField(const char* name); + void writeHW(); + void enableAll(); + static std::string lookupParameter(const char* name); + enum {FE_I3_N_GLOBAL_BITS=231}; + void dump(); + private: + unsigned char* m_data; + BitStream m_bitStream; + + // static functions + static void addField(const char* name, unsigned width, bool parity=1); + static void addParameter(const char* name, const char* field); + static void initialize(); + static std::map<std::string, FieldParams> m_fields; + static std::map<std::string, std::string> m_parameters; + static std::string m_cachedName, m_cachedField; + static unsigned m_pos; + static bool m_initialized; + }; + +}; + +#endif diff --git a/rce/rcecalib/config/FEI3/IPCModule.cc b/rce/rcecalib/config/FEI3/IPCModule.cc new file mode 100644 index 00000000..402a60d8 --- /dev/null +++ b/rce/rcecalib/config/FEI3/IPCModule.cc @@ -0,0 +1,203 @@ +#ifndef FEI3__IPCMODULE_CC +#define FEI3__IPCMODULE_CC +#include "rcecalib/util/RceName.hh" +#include "rcecalib/config/FEI3/IPCModule.hh" +#include "ipc/partition.h" +#include "ers/ers.h" +#include <boost/lexical_cast.hpp> + +namespace FEI3{ + +template <class TP> +IPCModule<TP>::IPCModule(IPCPartition & p, const char * name, unsigned id, unsigned inlink, unsigned outlink, AbsFormatter* fmt): + IPCNamedObject<POA_ipc::IPCFEI3Adapter, TP>( p, std::string(boost::lexical_cast<std::string>(id)+"_RCE"+boost::lexical_cast<std::string>(RceName::getRceNumber())).c_str()) , + Module(name, id, inlink, outlink, fmt){ + // std::cout<<"IPCModule"<<std::endl; + try { + IPCNamedObject<POA_ipc::IPCFEI3Adapter,TP>::publish(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } +} + +template <class TP> +IPCModule<TP>::~IPCModule(){ + try { + IPCNamedObject<POA_ipc::IPCFEI3Adapter,TP>::withdraw(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::warning( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } +} + +template <class TP> +CORBA::Long IPCModule<TP>::IPCdownloadConfig(const ipc::PixelModuleConfig &legacyModuleConfig){ + m_mcc.setRegister(Mcc::MCC_LV1,legacyModuleConfig.MCCRegisters.regLV1); + m_mcc.setRegister(Mcc::MCC_CSR,legacyModuleConfig.MCCRegisters.regCSR); + m_mcc.setRegister(Mcc::MCC_CAL,legacyModuleConfig.MCCRegisters.regCAL); + m_mcc.setRegister(Mcc::MCC_FEEN,legacyModuleConfig.maskEnableFEConfig); + + const ipc::PixelFEConfig *legacyFEConfig; + const ipc::PixelFETrims *legacyFETrims; + const ipc::PixelFEMasks *legacyFEMasks; + for(int chip=0;chip<N_FRONTENDS;++chip) { + m_frontend[chip]->setChipAddress(chip, legacyModuleConfig.FEConfig[chip].FEIndex); + legacyFEConfig = &legacyModuleConfig.FEConfig[chip]; + legacyFETrims = &legacyFEConfig->FETrims; + legacyFEMasks = &legacyFEConfig->FEMasks; + + globalLegacyToUsr(legacyFEConfig, chip); + + m_frontend[chip]->setVcalCoeff(0, legacyFEConfig->FECalib.vcalCoeff[0]); + m_frontend[chip]->setVcalCoeff(1, legacyFEConfig->FECalib.vcalCoeff[1]); + m_frontend[chip]->setVcalCoeff(2, legacyFEConfig->FECalib.vcalCoeff[2]); + m_frontend[chip]->setVcalCoeff(3, legacyFEConfig->FECalib.vcalCoeff[3]); + m_frontend[chip]->setCapVal(0, legacyFEConfig->FECalib.cinjLo); + m_frontend[chip]->setCapVal(1, legacyFEConfig->FECalib.cinjHi); + + for(int col=0;col<Frontend::N_COLS;++col) { + for(int row=0;row<Frontend::N_ROWS;++row) { + unsigned char tdac = legacyFETrims->dacThresholdTrim[row][col]; + unsigned char fdac = legacyFETrims->dacFeedbackTrim[row][col]; + unsigned mask = (1 << (row & 0x1f)); + unsigned char enable = (legacyFEMasks->maskEnable[row >> 5][col] & mask) ? 1 : 0; + unsigned char select = (legacyFEMasks->maskSelect[row >> 5][col] & mask) ? 1 : 0; + unsigned char kill = (legacyFEMasks->maskPreamp[row >> 5][col] & mask) ? 1 : 0; + unsigned char hitbus = (legacyFEMasks->maskHitbus[row >> 5][col] & mask) ? 1 : 0; + PixelRegister* pixel=m_frontend[chip]->getPixelRegister(col,row); + pixel->setField(PixelRegister::tdac, tdac); + pixel->setField(PixelRegister::fdac, fdac); + pixel->setField(PixelRegister::enable, enable); + pixel->setField(PixelRegister::select, select); + pixel->setField(PixelRegister::kill, kill); + pixel->setField(PixelRegister::hitbus, hitbus); + } + } + } + std::cout<<"Configure done"<<std::endl; + return 0; +} +template <class TP> +void IPCModule<TP>::globalLegacyToUsr(const ipc::PixelFEConfig* legacyFE, unsigned chip){ + + const ipc::PixelFEGlobal *feGlobal; + feGlobal = &legacyFE->FEGlobal; + + m_frontend[chip]->setGlobalRegField("latency", feGlobal->latency); + m_frontend[chip]->setGlobalRegField("selfTriggerDelay", feGlobal->selfLatency); + m_frontend[chip]->setGlobalRegField("selfTriggerWidth", feGlobal->selfWidth); + m_frontend[chip]->setGlobalRegField("enableSelfTrigger", feGlobal->enableSelfTrigger); + m_frontend[chip]->setGlobalRegField("enableHitParity", feGlobal->enableHitParity); + m_frontend[chip]->setGlobalRegField("doMux", feGlobal->muxDO); + m_frontend[chip]->setGlobalRegField("selectMonHit", feGlobal->muxMonHit); + m_frontend[chip]->setGlobalRegField("tsiTscEnable", feGlobal->enableTimestamp); + + m_frontend[chip]->setGlobalRegField("selectDataPhase", 0); /* previously spare */ + m_frontend[chip]->setGlobalRegField("enableEOEParity", 0); /* previously spare */ + + m_frontend[chip]->setGlobalRegField("hitBusScaler", 0); /* read-only */ + + m_frontend[chip]->setGlobalRegField("monLeakADCRefTest", feGlobal->monADCRef); + m_frontend[chip]->setGlobalRegField("monLeakADCDAC", feGlobal->dacMonLeakADC); + m_frontend[chip]->setGlobalRegField("monLeakDACTest", feGlobal->monMonLeakADC); + m_frontend[chip]->setGlobalRegField("monLeakADCEnableComparator", feGlobal->enableMonLeak); + m_frontend[chip]->setGlobalRegField("monLeakADCMonComp", 0); /* status */ + m_frontend[chip]->setGlobalRegField("aRegTrim", feGlobal->aregTrim); + m_frontend[chip]->setGlobalRegField("enableARegMeas", feGlobal->enableAregMeas); + m_frontend[chip]->setGlobalRegField("aRegMeas", feGlobal->aregMeas); + m_frontend[chip]->setGlobalRegField("enableAReg", feGlobal->enableAreg); + m_frontend[chip]->setGlobalRegField("enableLVDSRefMeas", feGlobal->enableLvdsRegMeas); + m_frontend[chip]->setGlobalRegField("dRegTrim", feGlobal->dregTrim); + m_frontend[chip]->setGlobalRegField("enableDRegMeas", feGlobal->enableDregMeas); + m_frontend[chip]->setGlobalRegField("dRegMeas", feGlobal->dregMeas); + m_frontend[chip]->setGlobalRegField("capMeasCircuitry", feGlobal->capMeasure); + + m_frontend[chip]->setGlobalRegField("enableCapTest", feGlobal->enableCapTest); + m_frontend[chip]->setGlobalRegField("enableAnalogOut", feGlobal->enableBuffer); + m_frontend[chip]->setGlobalRegField("enableTestPixelMux", feGlobal->muxTestPixel); + m_frontend[chip]->setGlobalRegField("enableVCalMeas", feGlobal->enableVcalMeasure); + m_frontend[chip]->setGlobalRegField("enableLeakMeas", feGlobal->enableLeakMeasure); + m_frontend[chip]->setGlobalRegField("enableBufferBoost", feGlobal->enableBufferBoost); + + m_frontend[chip]->setGlobalRegField("enableCP8", feGlobal->enableCP8); + m_frontend[chip]->setGlobalRegField("testDacForIVDD2Dac", feGlobal->monIVDD2); + m_frontend[chip]->setGlobalRegField("dacIVDD2", feGlobal->dacIVDD2); + m_frontend[chip]->setGlobalRegField("dacID", feGlobal->dacID); + m_frontend[chip]->setGlobalRegField("testDacForIDDac", feGlobal->monID); + + m_frontend[chip]->setGlobalRegField("enableCP7", feGlobal->enableCP7); + m_frontend[chip]->setGlobalRegField("testDacForIP2Dac", feGlobal->monIP2); + m_frontend[chip]->setGlobalRegField("dacIP2", feGlobal->dacIP2); + m_frontend[chip]->setGlobalRegField("dacIP", feGlobal->dacIP); + m_frontend[chip]->setGlobalRegField("testDacForIPDac", feGlobal->monIP); + + m_frontend[chip]->setGlobalRegField("enableCP6", feGlobal->enableCP6); + m_frontend[chip]->setGlobalRegField("testDacForITrimThDac", feGlobal->monITRIMTH); + m_frontend[chip]->setGlobalRegField("dacITRIMTH", feGlobal->dacITRIMTH); + m_frontend[chip]->setGlobalRegField("dacIF", feGlobal->dacIF); + m_frontend[chip]->setGlobalRegField("testDacForIFDac", feGlobal->monIF); + + m_frontend[chip]->setGlobalRegField("enableCP5", feGlobal->enableCP5); + m_frontend[chip]->setGlobalRegField("testDacForITrimIfDac", feGlobal->monITRIMIF); + m_frontend[chip]->setGlobalRegField("dacITRIMIF", feGlobal->dacITRIMIF); + m_frontend[chip]->setGlobalRegField("dacVCAL", feGlobal->dacVCAL); + m_frontend[chip]->setGlobalRegField("testDacForVCalDac", feGlobal->monVCAL); + + m_frontend[chip]->setGlobalRegField("enableCP4", feGlobal->enableCP4); + m_frontend[chip]->setGlobalRegField("enableCinjHigh", feGlobal->enableCinjHigh); + m_frontend[chip]->setGlobalRegField("enableExternalInj", feGlobal->enableExternal); + m_frontend[chip]->setGlobalRegField("enableTestAnalogRef", feGlobal->enableTestAnalogRef); + m_frontend[chip]->setGlobalRegField("eocMux", feGlobal->muxEOC); + m_frontend[chip]->setGlobalRegField("CEUClockControl", feGlobal->frequencyCEU); + + m_frontend[chip]->setGlobalRegField("enableDigitalInject", feGlobal->enableDigital); + m_frontend[chip]->setGlobalRegField("enableCP3", feGlobal->enableCP3); + m_frontend[chip]->setGlobalRegField("testDacForITH1Dac", feGlobal->monITH1); + m_frontend[chip]->setGlobalRegField("dacITH1", feGlobal->dacITH1); + m_frontend[chip]->setGlobalRegField("dacITH2", feGlobal->dacITH2); + m_frontend[chip]->setGlobalRegField("testDacForITH2Dac", feGlobal->monITH2); + + m_frontend[chip]->setGlobalRegField("enableCP2", feGlobal->enableCP2); + m_frontend[chip]->setGlobalRegField("testDacILDac", feGlobal->monIL); + m_frontend[chip]->setGlobalRegField("dacIL", feGlobal->dacIL); + m_frontend[chip]->setGlobalRegField("dacIL2", feGlobal->dacIL2); + m_frontend[chip]->setGlobalRegField("testDacIL2Dac", feGlobal->monIL2); + + m_frontend[chip]->setGlobalRegField("enableCP1", feGlobal->enableCP1); + m_frontend[chip]->setGlobalRegField("threshTOTMinimum", feGlobal->threshTOTMinimum); + m_frontend[chip]->setGlobalRegField("threshTOTDouble", feGlobal->threshTOTDouble); + m_frontend[chip]->setGlobalRegField("modeTOTThresh", feGlobal->modeTOTThresh); + + m_frontend[chip]->setGlobalRegField("enableCP0", feGlobal->enableCP0); + m_frontend[chip]->setGlobalRegField("enableHitbus", feGlobal->enableHitbus); + m_frontend[chip]->setGlobalRegField("gTDac", feGlobal->gdac); + m_frontend[chip]->setGlobalRegField("enableTune", feGlobal->enableTune); + m_frontend[chip]->setGlobalRegField("enableBiasComp", feGlobal->enableBiasComp); + m_frontend[chip]->setGlobalRegField("enableIpMonitor", feGlobal->enableIpMonitor); +} + +template <class TP> +void IPCModule<TP>::shutdown(){ + std::cout<<"Shutdown"<<std::endl; +} + +template <class TP> +void IPCModule<TP>::destroy(){ + this->_destroy(); +} + + + +}; + +#endif diff --git a/rce/rcecalib/config/FEI3/IPCModule.hh b/rce/rcecalib/config/FEI3/IPCModule.hh new file mode 100644 index 00000000..e47a335d --- /dev/null +++ b/rce/rcecalib/config/FEI3/IPCModule.hh @@ -0,0 +1,27 @@ +#ifndef IPCFEI3MODULE_HH +#define IPCFEI3MODULE_HH + +#include "rcecalib/config/FEI3/Module.hh" +#include "ipc/object.h" +#include "PixelModuleConfig.hh" +#include "IPCFEI3Adapter.hh" + +class IPCPartition; +class AbsFormatter; + +namespace FEI3{ +template <class TP = ipc::single_thread> +class IPCModule: public IPCNamedObject<POA_ipc::IPCFEI3Adapter,TP>, public FEI3::Module { +public: + IPCModule(IPCPartition & p, const char * name, unsigned id, unsigned inlink, unsigned outlink, AbsFormatter* fmt); + ~IPCModule(); + CORBA::Long IPCdownloadConfig(const ipc::PixelModuleConfig &config); + void globalLegacyToUsr(const ipc::PixelFEConfig* legacy, unsigned chip); + void shutdown(); + void destroy(); + +}; +}; + + +#endif diff --git a/rce/rcecalib/config/FEI3/JJFormatter.cc b/rce/rcecalib/config/FEI3/JJFormatter.cc new file mode 100644 index 00000000..9cba38ac --- /dev/null +++ b/rce/rcecalib/config/FEI3/JJFormatter.cc @@ -0,0 +1,774 @@ +#include "rcecalib/config/FEI3/JJFormatter.hh" +#include "rcecalib/config/FormattedRecord.hh" +#include "rcecalib/config/Endianness.hh" +#include "rcecalib/config/BFU.hh" +#include <stdio.h> +//#define DEBUG +/* ====================================================================== */ +/* NEW DECODER */ +/* ---------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- */ +/*! brief Maps out the sizes of the objects that are common amongst + various classes. */ +/* ---------------------------------------------------------------------- */ +namespace Size +{ + /* ------------------------------------------------------------------ */ + /*!< \brief The sizes of common objects */ + /* ------------------------------------------------------------------ */ + enum Size + { + HEADER = 5, + L1ID = 8, + SYNCH = 1, + BCID = 8, + KEY = 4, + FENUM = 4, + LEFT = 32-(HEADER + L1ID + SYNCH + BCID + SYNCH + KEY), + ZEROES = LEFT - 1 + }; + + + /* ------------------------------------------------------------------ */ + /*!< \brief Size of the three possible record types */ + /* ------------------------------------------------------------------ */ + namespace Record + { + enum Record + { + HEADER = 31, + MCCFE = 9, + HIT = 22, + TRAILER = 23 + }; + }; +} +/* ---------------------------------------------------------------------- */ + + + +/* ---------------------------------------------------------------------- *//*! + + \brief The value of the key field. + + The key field describes the 4-bit object identifier + */ +/* ---------------------------------------------------------------------- */ +namespace Key +{ + enum Key + { + MCCFE = 0xe, + FEFLAG = 0xf, + TRAILER = 0x0 + }; +} +/* ---------------------------------------------------------------------- */ + + +/* ---------------------------------------------------------------------- *//*! + + \brief The value of the left-justified key field including the SYNCH bit + */ +/* ---------------------------------------------------------------------- */ +namespace SynchKey +{ + enum Key + { + MCCFE = (1<<31) | (Key::MCCFE << 27), + FEFLAG = (1<<31) | (Key::FEFLAG << 27), + TRAILER = (1<<31) | (Key::TRAILER << 27) + }; +} +/* ---------------------------------------------------------------------- */ + + + +/* ---------------------------------------------------------------------- *//*! + + \brief Maps out the first 32-bits of the record + */ +/* ---------------------------------------------------------------------- */ +namespace Header +{ + /* -------------------------------- *\ + | | + | 0123456789abcdef0123456789abcdef | + | -------------------------------- | + | hhhhhllllllllsbbbbbbbbskkkkffffs | + | 11101........1........11110....1 | + | | + \* -------------------------------- */ + struct MccFe + { +#if ENDIANNESS_IS_BIG + + unsigned int header: Size::HEADER; + unsigned int l1id: Size:: L1ID; + unsigned int synch0: Size:: SYNCH; + unsigned int bcid: Size:: BCID; + unsigned int synch1: Size:: SYNCH; + unsigned int key: Size:: KEY; + unsigned int fenum: Size:: FENUM; + unsigned int synch2: Size:: SYNCH; + +#elif ENDIANNESS_IS_LITTLE + + unsigned int synch2: Size::SYNCH; + unsigned int fenum: Size::FENUM; + unsigned int key: Size:: KEY; + unsigned int synch1: Size:: SYNCH; + unsigned int bcid: Size:: BCID; + unsigned int synch0: Size:: SYNCH; + unsigned int l1id: Size:: L1ID; + unsigned int header: Size::HEADER; + +#else + +#error ENDIANNESS is not defined + +#endif + }; + + + /* -------------------------------- *\ + | | + | 0123456789abcdef0123456789abcdef | + | -------------------------------- | + | hhhhhllllllllsbbbbbbbbskkkkxxxxx | + | 11101........1........1........ | + | | + \* -------------------------------- */ + struct Generic + { +#if ENDIANNESS_IS_BIG + + unsigned int header: Size::HEADER; + unsigned int l1id: Size:: L1ID; + unsigned int synch0: Size:: SYNCH; + unsigned int bcid: Size:: BCID; + unsigned int synch1: Size:: SYNCH; + unsigned int key: Size:: KEY; + unsigned int left: Size:: LEFT; + +#elif ENDIANNESS_IS_LITTLE + + unsigned int left: Size:: LEFT; + unsigned int key: Size:: KEY; + unsigned int synch1: Size:: SYNCH; + unsigned int bcid: Size:: BCID; + unsigned int synch0: Size:: SYNCH; + unsigned int l1id: Size:: L1ID; + unsigned int header: Size::HEADER; + +#else + +#error ENDIANNESS is not defined + +#endif + }; + + + /* -------------------------------- *\ + | | + | 0123456789abcdef0123456789abcdef | + | -------------------------------- | + | hhhhhllllllllsbbbbbbbbskkkksxxxx | + | 11101........1........1....1... | + | | + \* -------------------------------- */ + struct Trailer + { +#if ENDIANNESS_IS_BIG + + unsigned int header: Size::HEADER; + unsigned int l1id: Size:: L1ID; + unsigned int synch0: Size:: SYNCH; + unsigned int bcid: Size:: BCID; + unsigned int synch1: Size:: SYNCH; + unsigned int key: Size:: KEY; + unsigned int synch2: Size:: SYNCH; + unsigned int zeroes: Size::ZEROES; + +#elif ENDIANNESS_IS_LITTLE + + unsigned int zeroes: Size::ZEROES; + unsigned int synch2: Size:: SYNCH; + unsigned int key: Size:: KEY; + unsigned int synch1: Size:: SYNCH; + unsigned int bcid: Size:: BCID; + unsigned int synch0: Size:: SYNCH; + unsigned int l1id: Size:: L1ID; + unsigned int header: Size::HEADER; + +#else + +#error ENDIANNESS is not defined + +#endif + }; + + + union Header + { + unsigned int ui; + Generic bf; + MccFe fe; + Trailer trailer; + } + u; +} +/* ---------------------------------------------------------------------- */ + + + + +/* ---------------------------------------------------------------------- *//*! + + \brief Maps out the extracted value word when it is interpretted as an + MCC-FE record + */ +/* ---------------------------------------------------------------------- */ +namespace MccFe +{ + struct MccFe_bf + { +#if ENDIANNESS_IS_BIG + + unsigned int synch: Size::SYNCH; + unsigned int key: Size:: KEY; + unsigned int fenum: Size::FENUM; + unsigned int pad: 32 - (Size::SYNCH + Size::KEY + Size::FENUM); + +#elif ENDIANNESS_IS_LITTLE + + unsigned int pad: 32 - (Size::SYNCH + Size::KEY + Size::FENUM); + unsigned int fenum: Size::FENUM; + unsigned int key: Size:: KEY; + unsigned int synch: Size::SYNCH; + +#endif + + }; + + union MccFe + { + unsigned int ui; + MccFe_bf bf; + }; +} +/* ---------------------------------------------------------------------- */ + + + + +/* ---------------------------------------------------------------------- *//*! + + \brief Maps out the extracted value word when it is interpretted as a + HIT record + */ +/* ---------------------------------------------------------------------- */ +namespace Hit +{ + enum Size + { + ROW = 8, + COL = 5, + TOT = 8, + VAL = ROW + COL + TOT + }; + + struct Hit_val + { + +#if ENDIANNESS_IS_BIG + + unsigned int synch: Size::SYNCH; + unsigned int val: VAL; + unsigned int pad: 32 - (Size::SYNCH + VAL); + +#elif ENDIANNESS_IS_LITTLE + + unsigned int pad: 32 - (Size::SYNCH + VAL); + unsigned int val: VAL; + unsigned int synch: Size::SYNCH; + +#endif + }; + + struct Hit_bf + { + +#if ENDIANNESS_IS_BIG + + unsigned int synch: Size::SYNCH; + unsigned int row: ROW; + unsigned int col: COL; + unsigned int tot: TOT; + unsigned int pad: 32 - (Size::SYNCH + VAL); + +#elif ENDIANNESS_IS_LITTLE + + unsigned int pad: 32 - (Size::SYNCH + VAL); + unsigned int tot: TOT; + unsigned int col: COL; + unsigned int row: ROW; + unsigned int synch: Size::SYNCH; + +#endif + }; + + union Hit + { + unsigned int ui; + Hit_val val; + Hit_bf bf; + }; + +} +/* ---------------------------------------------------------------------- */ + + + +/* ---------------------------------------------------------------------- *//*! + + \brief Maps out the extracted value word when it is interpretted as a + FEFLAG record + */ +/* ---------------------------------------------------------------------- */ +namespace FeFlag +{ + enum Size + { + MB1 = 1, + MCC = 8, + FE = 8, + VAL = MB1 + MCC + FE + }; + + + struct FeFlag_val + { +#if ENDIANNESS_IS_BIG + + unsigned int synch: Size::SYNCH; + unsigned int key: Size:: KEY; + unsigned int val: VAL; + unsigned int pad: 32 - (Size::SYNCH + Size::KEY + VAL); + +#elif ENDIANNESS_IS_LITTLE + + unsigned int pad: 32 - (Size::SYNCH + Size::KEY + VAL); + unsigned int val: VAL; + unsigned int key: Size:: KEY; + unsigned int synch: Size::SYNCH; + +#endif + }; + + struct FeFlag_bf + { + +#if ENDIANNESS_IS_BIG + + unsigned int synch: Size::SYNCH; + unsigned int key: Size:: KEY; + unsigned int mb1: MB1; + unsigned int mcc: MCC; + unsigned int fe: FE; + unsigned int pad: 32 - (Size::SYNCH + Size::KEY + VAL); + +#elif ENDIANNESS_IS_LITTLE + + unsigned int pad: 32 - (Size::SYNCH + Size::KEY + VAL); + unsigned int fe: FE; + unsigned int mcc: MCC; + unsigned int mb1: MB1; + unsigned int key: Size:: KEY; + unsigned int synch: Size::SYNCH; + +#endif + }; + + union FeFlag + { + unsigned int ui; + FeFlag_val val; + FeFlag_bf bf; + }; +} +/* ---------------------------------------------------------------------- */ + + +/* ====================================================================== */ +/* DEBUGGING AIDs */ +/* ---------------------------------------------------------------------- */ +#ifdef DEBUG + +static inline void print_header_fe (Header::Header hdr) +{ + printf ("MccFe: %8.8x H:%2.2x L1:%2.2x Synch:%1u BC:%2.2x " + "Synch:%1u Key:%1.1x Fenum:%1x Synch:%1x\n", + hdr.ui, + hdr.fe.header, + hdr.fe.l1id, + hdr.fe.synch0, + hdr.fe.bcid, + hdr.fe.synch1, + hdr.fe.key, + hdr.fe.fenum, + hdr.fe.synch2); + return; +} + +static inline void print_header_trailer (Header::Header hdr) +{ + printf ("Trailer: %8.8x H:%2.2x L1:%2.2x Synch:%1u BC:%2.2x " + "Synch:%1u Key:%1.1x Synch:%1u zeroes:%2.2x\n", + hdr.ui, + hdr.trailer.header, + hdr.trailer.l1id, + hdr.trailer.synch0, + hdr.trailer.bcid, + hdr.trailer.synch1, + hdr.trailer.key, + hdr.trailer.synch2, + hdr.trailer.zeroes + ); + return; +} + +static inline void print_title (Header::Header hdr) +{ + printf ( +" Value What Raw Fe Row Col Tot Mb1 Mcc Fe L1id BCid\n" +" -------- ------- -------- ---- --- --- --- --- --- --- %2x %2x\n", + hdr.bf.l1id, + hdr.bf.bcid); + return; +} + +static inline void print_mccfe0 (Header::Header header) +{ + printf (" MccFe ........ %4x ... ... ... ... ... ...\n", + header.fe.fenum); + return; +} + + +static inline void print_hit (unsigned int val) +{ + Hit::Hit hit; + hit.ui = val; + printf (" %8.8x Hit %8.8x .... %3x %3x %3x ... ... ...\n", + hit.ui, + hit.val.val, + hit.bf.row, + hit.bf.col, + hit.bf.tot); + return; +} + +static inline void print_mccfe (unsigned int val) +{ + MccFe::MccFe mccfe; + mccfe.ui = val; + printf (" %8.8x MccFe ........ %4x ... ... ... ... ... ...\n", + mccfe.ui, + mccfe.bf.fenum); + return; +} + +static inline void print_feflag (unsigned int val) +{ + FeFlag::FeFlag feflag; + feflag.ui = val; + printf (" %8.8x FeFlag %8.8x .... ... ... ... %3x %3x %3x\n", + feflag.ui, + feflag.val.val, + feflag.bf.mb1, + feflag.bf.mcc, + feflag.bf.fe); + return; +} + +static inline void print_error (unsigned int val) +{ + printf (" %8.8x Error\n", val); + return; +} + + +static inline void print_trailer (unsigned int val) +{ + printf (" %8.8x Trailer\n", val); + return; +} + +#else +#define print_header_fe(_hdr) +#define print_header_trailer(_hdr) +#define print_title(_hdr) +#define print_mccfe0(_intro) +#define print_hit(_val) +#define print_mccfe(_val) +#define print_feflag(_val) +#define print_error(_val) +#define print_trailer(_val) + +#endif +/* ====================================================================== */ + + + + + +/* ---------------------------------------------------------------------- */ +namespace Decoder { +namespace Status { + + +/* ---------------------------------------------------------------------- *//*! + + \brief Enumerate the various return status codes that decoder can return + + The usual UNIX convention is used. If the value is + - > 0, none currently + - ==0, Successful + - < 0, Error + */ +/* ---------------------------------------------------------------------- */ +enum Status +{ + OK = 0, /*!< Clean finish */ + HeaderSynch = -1, /*!< Initial synch bit in the header not found */ + L1IdSynch = -2, /*!< Synch bit preceeding the LI id not found */ + BCIdSynch = -3, /*!< Synch bit preceeding the BC id not found */ + HeaderTrailer = -4, /*!< Malformed trailer key occurred in the header */ + HeaderKey = -5, /*!< An illegal key occurred in the header, only + MccFe and Trailer keys are allowed */ + PrematureEos = -6, /*!< The bit stream-terminated too soon. There + must be at least a TRAILER records worth of + bits after the header record has been + processed. */ + NoSynch = -7, /*!< Synch bit on a record after the header was + not found. */ +}; + +}} + + + +/* ====================================================================== *//*! + + \brief The record decoder + + \param buffer The record buffer to decoder + \param buflen The length, in 32-bit words, of \a buffer + */ +/* ---------------------------------------------------------------------- */ +int JJFormatter::decode (const unsigned int *buffer, int buflen, unsigned* parsedData, int &parsedsize, int &nL1A) +{ + using namespace Decoder; + + int end = buflen * 32; + int position = 0; + Header::Header hdr; + const unsigned int *buf = buffer; + Hit::Hit hit; + MccFe::MccFe mccfe; + + // Loop over all events in this buffer + while (1) + { + unsigned int val; + unsigned int cur = buffer[position >> 5]; + while(position < end && (signed)_bfu_testBit(cur,position)>=0){ + _bfu_wordL (val, cur, buf, position, 1); + position += 1; + } + + // Check if have enough bits to continue + if (position + Size::Record::HEADER >= end) return Status::OK; + + + _bfu_wordL (hdr.ui, cur, buf, position, Size::Record::HEADER); + position += Size::Record::HEADER; + print_title (hdr); + // printf("%x\n",hdr.ui); + + if(hdr.ui==0)return Status::OK; + // If the synch bit (its in the sign bit) is not set, then error + if ((signed)hdr.ui > 0) + { + print_error (hdr.ui); + return Status::HeaderSynch; + } + + unsigned int key = hdr.bf.key; + + /* + | In the usual case, the key should be MCCFE. + | The only other legitimate value is the TRAILER. + */ + if (key != Key::MCCFE) + { + // Either immediate end or error + if (key == Key::TRAILER) + { + //print_header_trailer (hdr); + + // Need another 14 bits of 0s to complete the trailer + _bfu_wordL (val, cur, buf, position, Size::Record::TRAILER + - Size::Record::MCCFE); + position += Size::Record::TRAILER - Size::Record::MCCFE; + + // If non-zero, error + if (val) + { + print_error (hdr.ui); + return Status::HeaderTrailer; + } + + print_trailer (hdr.ui); + nL1A++; + FormattedRecord fr(FormattedRecord::HEADER); + fr.setL1id(hdr.trailer.l1id); + fr.setBxid(hdr.trailer.bcid); + parsedData[parsedsize++]=fr.getWord(); + continue; + } + + // Illegitimate record key found + print_error (hdr.ui); + return Status::HeaderKey; + } + + + // Print the header as holding an MCC FE record + print_mccfe (hdr.ui); + mccfe.bf.fenum = hdr.fe.fenum; + FormattedRecord fr(FormattedRecord::HEADER); + fr.setL1id(hdr.fe.l1id); + fr.setBxid(hdr.fe.bcid); + parsedData[parsedsize++]=fr.getWord(); + nL1A++; + + + /* + | Start the real decoding + | The loop grabs 22 bits at a time on the premise that the only + | object not at least that long is the MCC-FE. Note the trailer + | is 23 bits, so if it is encountered, one more bit needs to be + | grabbed. If the MCC-FE is found, special action is taken which + | consists of (effectively) pushing the overread bits back into + | the input stream. + */ + while (1) + { + // Must have at least 23 bits remaining for the trailer + if (position + Size::Record::TRAILER >= end) + { + print_error (0xffffffff); + return Status::PrematureEos; + } + + _bfu_wordL (val, cur, buf, position, Size::Record::HIT); + position += Size::Record::HIT; + + /* + | Since the synch bit is in the sign bit, if the signed + | interpretation is greater than 0, then, error + */ + if ((signed)val > 0) + { + // Error, the stream is lost + print_error (val); + return Status::NoSynch; + } + + + if (val < (unsigned)SynchKey::MCCFE) + { + // This is either a hit or the trailer + if ((val << 1) == 0) + { + /* + | Looks like the trailer, but maybe HIT = 0 exception + | The next bit determines which. If this is not the end + | then this bit is effectively the synch bit for the + | next record. If it is, we don't want to read it, that + | would leave the bit stream at the wrong place. So here + | we just test it. + */ + val = _bfu_testBit (cur, position); + + // If >=0, then have hit the trailer for this event + if ((signed)val >= 0) + { + print_trailer (val); + + // The test bit belongs with the trailer, update pos + _bfu_wordL (val, cur, buf, position, 1); + position += 1; + + // Check if any left + if (position + Size::Record::HEADER >= end) + { + /* + | !!! Need to check that the remaining bits to + | the end of the 32-bit word are 0. + */ + return Status::OK; + } + + /* + | Done with this event, but still more to process + | The reestablishment of 'cur' happens at the top + | of loop that reads the header. + */ + break; + } + + // This was the case of ROW = 0, COL = 0 TOT = 0 + // Just continue + } + + // Just a hit + print_hit (val); + hit.ui=val; + FormattedRecord fr(FormattedRecord::DATA); + fr.setToT(hit.bf.tot); + fr.setCol(hit.bf.col); + fr.setRow(hit.bf.row); + fr.setFE(mccfe.bf.fenum); + parsedData[parsedsize++]=fr.getWord(); + } + + + else if (val < (unsigned)SynchKey::FEFLAG) + { + /* + | MCCFe, have pulled too many bits, put the excess back + | Have pulled 22 bits, + | 5 are the synch and key, + | 4 are the fenum + | This means 22 - 9 must be pushed backed + */ + print_mccfe (val); + mccfe.ui=val; + position -= (Size::Record::HIT - Size::Record::MCCFE); + buf = buffer + (position >> 5); + cur = *buf; + } + + else + { + print_feflag (val); + //printf("fe flag\n"); + } + } + } +} +/* ====================================================================== */ diff --git a/rce/rcecalib/config/FEI3/JJFormatter.hh b/rce/rcecalib/config/FEI3/JJFormatter.hh new file mode 100644 index 00000000..b81d6d46 --- /dev/null +++ b/rce/rcecalib/config/FEI3/JJFormatter.hh @@ -0,0 +1,14 @@ +#ifndef JJFORMATTER_HH +#define JJFORMATTER_HH + +#include "rcecalib/config/AbsFormatter.hh" + +class JJFormatter:public AbsFormatter{ +public: + JJFormatter(int id): + AbsFormatter(id, "JJ"){} + virtual ~JJFormatter(){} + int decode(const unsigned* data, int size, unsigned* parsedData, int &parsedsize, int &nL1A); + +}; +#endif diff --git a/rce/rcecalib/config/FEI3/MaskStageFactory.cc b/rce/rcecalib/config/FEI3/MaskStageFactory.cc new file mode 100644 index 00000000..97d3b160 --- /dev/null +++ b/rce/rcecalib/config/FEI3/MaskStageFactory.cc @@ -0,0 +1,86 @@ +#include "rcecalib/config/MaskStageFactory.hh" +#include "rcecalib/config/FEI3/Module.hh" +#include "rcecalib/config/FEI3/PixelRegister.hh" +#include "rcecalib/config/FEI3/RegularMaskStaging.hh" +#include "rcecalib/config/FEI3/CrosstalkMaskStaging.hh" +#include "rcecalib/config/Masks.hh" +#include <assert.h> +#include <string> +#include <iostream> + +using namespace FEI3; + +template<> Masks MaskStageFactory::createIOmasks<FEI3::Module>(const char* maskStagingMode){ + Masks m; + m.oMask=m.iMask=m.xtalk_on=m.xtalk_off=m.crosstalking=0; + std::string stagingMode(maskStagingMode); + if(std::string(stagingMode)=="SEL"){ + m.oMask=(1<<fieldPos[PixelRegister::select]) + | (1<<fieldPos[PixelRegister::hitbus]); + m.iMask=(1<<fieldPos[PixelRegister::select]); + } else if(std::string(stagingMode)=="ENA"){ + m.oMask=(1<<fieldPos[PixelRegister::hitbus]) + | (1<<fieldPos[PixelRegister::enable]); + m.iMask=(1<<fieldPos[PixelRegister::enable]); + } else if(std::string(stagingMode)=="SEL_ENA"){ + m.oMask=(1<<fieldPos[PixelRegister::hitbus]) + | (1<<fieldPos[PixelRegister::enable]) + | (1<<fieldPos[PixelRegister::select]); + m.iMask=(1<<fieldPos[PixelRegister::enable]) + | (1<<fieldPos[PixelRegister::select]); + } else if(std::string(stagingMode)=="SEL_ENA_PRE"){ + m.oMask=(1<<fieldPos[PixelRegister::hitbus]) + | (1<<fieldPos[PixelRegister::enable]) + | (1<<fieldPos[PixelRegister::select]) + | (1<<fieldPos[PixelRegister::kill]); + m.iMask=(1<<fieldPos[PixelRegister::enable]) + | (1<<fieldPos[PixelRegister::select]) + | (1<<fieldPos[PixelRegister::kill]); + } else if(std::string(stagingMode)=="SEL_PRE"){ + m.oMask=(1<<fieldPos[PixelRegister::hitbus]) + | (1<<fieldPos[PixelRegister::select]) + | (1<<fieldPos[PixelRegister::kill]); + m.iMask=(1<<fieldPos[PixelRegister::select]) + | (1<<fieldPos[PixelRegister::kill]); + } else if(std::string(stagingMode)=="SENS_XTALK"){ + m.crosstalking = 1; + m.oMask=(1<<fieldPos[PixelRegister::hitbus]) + | (1<<fieldPos[PixelRegister::enable]) + | (1<<fieldPos[PixelRegister::select]); + m.iMask=(1<<fieldPos[PixelRegister::enable]) + | (1<<fieldPos[PixelRegister::select]) + | (1<<fieldPos[PixelRegister::kill]); + m.xtalk_off=(1<<fieldPos[PixelRegister::select]) + | (1<<fieldPos[PixelRegister::kill]); + m.xtalk_on=(1<<fieldPos[PixelRegister::enable]) + | (1<<fieldPos[PixelRegister::kill]); + } else if(std::string(stagingMode)=="XTALK"){ + m.crosstalking = 1; + m.oMask=(1<<fieldPos[PixelRegister::hitbus]) + | (1<<fieldPos[PixelRegister::enable]) + | (1<<fieldPos[PixelRegister::select]) + | (1<<fieldPos[PixelRegister::kill]); + m.iMask=(1<<fieldPos[PixelRegister::enable]) + | (1<<fieldPos[PixelRegister::select]) + | (1<<fieldPos[PixelRegister::kill]); + m.xtalk_off=(1<<fieldPos[PixelRegister::select]); + m.xtalk_on=(1<<fieldPos[PixelRegister::enable]) + | (1<<fieldPos[PixelRegister::kill]); + } + m.oMask=~m.oMask; // invert + return m; +} + +template<> +MaskStaging<FEI3::Module>* MaskStageFactory::createMaskStaging(FEI3::Module* mod, const char* maskStagingType, const char* maskStagingMode){ + Masks iomask=createIOmasks<FEI3::Module>(maskStagingMode); + std::string stagingType(maskStagingType); + if(stagingType.substr(0,6)=="STEPS_" && iomask.crosstalking==false) + return new FEI3::RegularMaskStaging(mod, iomask, stagingType); + else if(stagingType=="STEPS_2880" && iomask.crosstalking==true) + return new FEI3::CrosstalkMaskStaging(mod, iomask, stagingType); + else{ + std::cout<<"Wrong staging type "<<stagingType<<std::endl; + assert(0); + } +} diff --git a/rce/rcecalib/config/FEI3/MaskStaging.cc b/rce/rcecalib/config/FEI3/MaskStaging.cc new file mode 100644 index 00000000..aff466d4 --- /dev/null +++ b/rce/rcecalib/config/FEI3/MaskStaging.cc @@ -0,0 +1,22 @@ +#include "rcecalib/config/MaskStaging.hh" +#include "rcecalib/config/FEI3/Module.hh" + +using namespace FEI3; + +template<> bool MaskStaging<FEI3::Module>::cLow(){ + return m_clow; +} +template<> bool MaskStaging<FEI3::Module>::cHigh(){ + return m_chigh; +} + +template<> void MaskStaging<FEI3::Module>::clearBitsHW(){ + for (int k=0;k<Module::N_FRONTENDS;k++){ + for (int i=0;i<Frontend::N_COLS;i++){ + for (int j=0;j<Frontend::N_ROWS;j++){ + PixelRegister *pixel=m_module->frontend(k)->getPixelRegister(i,j); + pixel->set(pixel->get() & m_masks.oMask); + } + } + } +} diff --git a/rce/rcecalib/config/FEI3/Mcc.cc b/rce/rcecalib/config/FEI3/Mcc.cc new file mode 100644 index 00000000..59f3db22 --- /dev/null +++ b/rce/rcecalib/config/FEI3/Mcc.cc @@ -0,0 +1,92 @@ + +#include "rcecalib/config/FEI3/Mcc.hh" +#include "rcecalib/config/FEI3/FECommands.hh" +#include "rcecalib/HW/SerialIF.hh" +#include "ers/ers.h" + +namespace FEI3{ + Mcc::Mcc(){ + clear(); + } + Mcc::~Mcc(){} + void Mcc::clear(){ + for (int i=0;i<MCC_NREG;i++)m_register[i]=0; + } + + void Mcc::setRegister(Mcc::Register reg, unsigned val){ + if(reg<MCC_NREG){ + m_register[reg]=val; + } + } + void Mcc::setNLvl1(unsigned val){ + ERS_ASSERT_MSG(val<=16, "the number of L1A triggers is too large"); + m_register[MCC_LV1]=(val-1)<<8; + } + void Mcc::enableDelay(bool on){ + if(on){ + m_register[MCC_CAL]|=(1<<10); + }else{ + m_register[MCC_CAL]&=~(1<<10); + } + } + void Mcc::setBandwidth(unsigned val){ + m_register[MCC_CSR]=val; + } + void Mcc::setChipEnables(unsigned val){ + m_register[MCC_FEEN]=val; + } + void Mcc::setStrobeDuration(unsigned val){ + m_register[MCC_CNT]=val; + } + void Mcc::setStrobeDelayRange(unsigned val){ + ERS_ASSERT_MSG(val<16, "value is too large"); + m_register[MCC_CAL]&=~(0xf<<6); //clear the field + m_register[MCC_CAL]|=(val<<6); + } + void Mcc::setStrobeDelay(unsigned val){ + ERS_ASSERT_MSG(val<64, "value is too large"); + m_register[MCC_CAL]&=~(0x3f); //clear the field + m_register[MCC_CAL]|=val; + enableDelay(1);//delay gets enabled implicitely + // std::cout<<" MCC_CAL "<<std::hex<<m_register[MCC_CAL]<<std::dec<<std::endl; + } + void Mcc::writeRegister(BitStream *bs, Mcc::Register reg){ + FECommands::mccWriteRegister(bs,reg,m_register[reg]); + } + void Mcc::configureHW(){ + BitStream* bs=new BitStream; + BitStreamUtils::prependZeros(bs); + writeRegister(bs, Mcc::MCC_CSR); + writeRegister(bs, Mcc::MCC_LV1); + writeRegister(bs, Mcc::MCC_CAL); + writeRegister(bs, Mcc::MCC_CNT); + SerialIF::send(bs); + delete bs; + } + + int Mcc::setParameter(const char* name, int val){ + int retval=1; + if(std::string(name)=="STROBE_DELAY"){ + setStrobeDelay(val); + }else if(std::string(name)=="STROBE_DEL_RANGE"){ + setStrobeDelayRange(val); + }else if (std::string(name)=="trigOpt.nL1AperEvent"){ + setNLvl1(val); + }else if (std::string(name)=="trigOpt.strobeMCCDelay"){ + setStrobeDelay(val); + }else if (std::string(name)=="trigOpt.strobeMCCDelayRange"){ + setStrobeDelayRange(val); + }else if (std::string(name)=="trigOpt.strobeDuration"){ + setStrobeDuration(val); + }else if (std::string(name)=="bandwidth"){ + setBandwidth(val); + }else if (std::string(name)=="enables"){ + setChipEnables(val); + }else{ + retval=0; + } + return retval; + } +}; + + diff --git a/rce/rcecalib/config/FEI3/Mcc.hh b/rce/rcecalib/config/FEI3/Mcc.hh new file mode 100644 index 00000000..d1a69c03 --- /dev/null +++ b/rce/rcecalib/config/FEI3/Mcc.hh @@ -0,0 +1,37 @@ +#ifndef MCC_HH +#define MCC_HH + +#include <map> +#include "rcecalib/HW/BitStream.hh" + +namespace FEI3{ + +class Mcc{ +public: + enum Register{MCC_CSR, MCC_LV1, MCC_FEEN, MCC_WFE, MCC_WMCC, MCC_CNT, MCC_CAL, MCC_PEF, MCC_NREG}; + Mcc(); + ~Mcc(); + void setRegister(Register reg, unsigned val); + void setNLvl1(unsigned val); + void enableDelay(bool on); + void setStrobeDelayRange(unsigned val); + void setStrobeDelay(unsigned val); + void setStrobeDuration(unsigned val); + void setBandwidth(unsigned val); + void setChipEnables(unsigned val); + void writeRegister(BitStream* bs, Mcc::Register reg); + void configureHW(); + void clear(); + int setParameter(const char* name, int val); + // MCC related commands + static void writeRegister(BitStream* bs, Mcc::Register reg, unsigned value); + static void resetMCC(BitStream *bs); + + +private: + unsigned short m_register[8]; + +}; + +}; +#endif diff --git a/rce/rcecalib/config/FEI3/Module.cc b/rce/rcecalib/config/FEI3/Module.cc new file mode 100644 index 00000000..e8c45626 --- /dev/null +++ b/rce/rcecalib/config/FEI3/Module.cc @@ -0,0 +1,172 @@ +#include "rcecalib/config/FEI3/Module.hh" +#include "rcecalib/config/MaskStageFactory.hh" +#include "rcecalib/HW/BitStream.hh" +#include "rcecalib/config/FEI3/FECommands.hh" +#include "rcecalib/HW/SerialIF.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/util/exceptions.hh" +#include <iostream> +#include "ers/ers.h" +#include <stdio.h> + +namespace FEI3{ + + Module::Module(const char* name, unsigned id, unsigned inLink, unsigned outLink, AbsFormatter* fmt) + :AbsModule(name, id,inLink, outLink, fmt), m_maskStaging(0){ + // std::cout<<"Module"<<std::endl; + for (int i=0;i<N_FRONTENDS;i++){ + m_frontend[i]=new Frontend(i); + } + } + Module::~Module(){ + for (int i=0;i<N_FRONTENDS;i++){ + delete m_frontend[i]; + } + delete m_maskStaging; + } + void Module::configureHW(){ + //std::cout<<"Configuring "<<m_inLink<<std::endl; + resetHW(); + m_mcc.configureHW(); + for (int i=0;i<N_FRONTENDS;i++){ + m_frontend[i]->configureHW(); + } + } + + void Module::resetFE(){ + resetHW(true); + } + void Module::resetHW(bool resetfe){ + BitStream *bs=new BitStream; + BitStreamUtils::prependZeros(bs); + FECommands::resetMCC(bs); + if(resetfe)FECommands::resetFE(bs,FECommands::FE_CMD_SOFT_RESET); + SerialIF::send(bs); + delete bs; + } + void Module::enableDataTakingHW(){ + BitStream *bs=new BitStream; + BitStreamUtils::prependZeros(bs); + FECommands::sendECR(bs); + FECommands::sendBCR(bs); + SerialIF::send(bs); + BitStreamUtils::prependZeros(bs); + m_mcc.writeRegister(bs, Mcc::MCC_CNT); + m_mcc.writeRegister(bs, Mcc::MCC_FEEN); + FECommands::enableDataTaking(bs); + SerialIF::send(bs); + delete bs; + } + + void Module::setupMaskStageHW(int maskStage) { + m_maskStaging->setupMaskStageHW(maskStage); + } + + //set the value in the register but not in the frontend + Module::PAR Module::setParameter(const char* name, int val){ + if(std::string(name)=="CHARGE"){ + for (int i=0;i<N_FRONTENDS;i++){ + //std::cout<<"Fronted "<<i<<" dac setting "<<m_frontend[i]->electronsToDac(val)<<std::endl; + m_frontend[i]->setGlobalRegField("dacVCAL", m_frontend[i]->electronsToDac(val)); + } + return SPECIAL; + } + if (std::string(name)=="NO_PAR"){ + return SPECIAL; + } + PixelRegister::Field fpar=PixelRegister::lookupParameter(name); + if (fpar!=PixelRegister::not_found){ + for (int i=0;i<N_FRONTENDS;i++){ + m_frontend[i]->setPixelParameter(fpar, val); + } + return PIXEL; + } + std::string par=GlobalRegister::lookupParameter(name); + if(par!=""){ //it's a global variable + for (int i=0;i<N_FRONTENDS;i++){ + m_frontend[i]->setGlobalRegField(par.c_str(), val); + } + return GLOBAL; + } + // wasn't a global variable, should be MCC then. + int rt=m_mcc.setParameter(name, val); + if(rt)return MCC; + char error_message[128]; + sprintf(error_message, "parameter %s was not found.",name); + ERS_ASSERT_MSG(NOT_FOUND, error_message); + return NOT_FOUND; + } + // set a parameter (global or MCC) in the frontend + int Module::setupParameterHW(const char* name, int val){ + int retval=1; + //first set the appropriate internal register + PAR p=setParameter(name,val); + // now send the config to the frontend + if(p!=NOT_FOUND){ + retval=0; + resetHW(false); //don't reset FE, only MCC + m_mcc.configureHW(); + for (int i=0;i<N_FRONTENDS;i++){ + m_frontend[i]->writeGlobalRegisterHW(); + } + } + return retval; + } + + int Module::configureScan(boost::property_tree::ptree *scanOptions){ + int retval=0; + //std::cout<<"FEI3::Module::configureScan"<<std::endl; + try{ + // MCC + setParameter("trigOpt.nL1AperEvent",scanOptions->get<int>("trigOpt.nL1AperEvent")); + setParameter("bandwidth",0); + setParameter("trigOpt.strobeMCCDelayRange",scanOptions->get<int>("trigOpt.strobeMCCDelayRange")); + setParameter("trigOpt.strobeMCCDelay",scanOptions->get<int>("trigOpt.strobeMCCDelay")); + setParameter("trigOpt.strobeDuration",scanOptions->get<int>("trigOpt.strobeDuration")); + //setParameter("enables",0xffff); + // Global regs + int diginject=scanOptions->get("trigOpt.optionsMask.DIGITAL_INJECT", 0); + if(diginject)setParameter("enableDigitalInject",1); + else setParameter("enableDigitalInject",0); + setParameter("latency",scanOptions->get<int>("trigOpt.Lvl1_Latency")); + int chigh=scanOptions->get("trigOpt.optionsMask.USE_CHIGH", 0); + if(chigh)setParameter("enableCinjHigh",1); + else setParameter("enableCinjHigh",0); + std::string stagingMode=scanOptions->get<std::string>("stagingMode"); + std::string maskStages=scanOptions->get<std::string>("maskStages"); + delete m_maskStaging; + MaskStageFactory msf; + m_maskStaging=msf.createMaskStaging(this, maskStages.c_str(), stagingMode.c_str()); + if(chigh){ + m_maskStaging->setClow(0); + m_maskStaging->setChigh(1); + }else{ + m_maskStaging->setClow(1); + m_maskStaging->setChigh(0); + } + setParameter("doMux",8); // event data + // set Vcal for each FE + std::string par="dacVCAL"; + if(scanOptions->get("trigOpt.optionsMask.SPECIFY_CHARGE_NOT_VCAL", 0)==1)par="CHARGE"; + setParameter(par.c_str(),scanOptions->get<int>("trigOpt.vcal_charge")); + } + catch(boost::property_tree::ptree_bad_path ex){ + retval=1; + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + } + // std::cout<<"FEI3::Module::configureScan end"<<std::endl; + return retval; + } + void Module::destroy(){ + delete this; + } + ModuleInfo Module::getModuleInfo(){ + return ModuleInfo(m_name, m_id,m_inLink, m_outLink,Module::N_FRONTENDS,Frontend::N_ROWS,Frontend::N_COLS, m_formatter); + } + const float Module::dacToElectrons(int fe, int dac){ + if(fe>=N_FRONTENDS)return -1; + return m_frontend[fe]->dacToElectrons(dac); + } +}; + diff --git a/rce/rcecalib/config/FEI3/Module.hh b/rce/rcecalib/config/FEI3/Module.hh new file mode 100644 index 00000000..96897d7a --- /dev/null +++ b/rce/rcecalib/config/FEI3/Module.hh @@ -0,0 +1,41 @@ +#ifndef FEI3__MODULE_HH +#define FEI3__MODULE_HH + +#include "rcecalib/config/FEI3/Frontend.hh" +#include "rcecalib/config/FEI3/Mcc.hh" +#include "rcecalib/config/AbsModule.hh" +#include "rcecalib/config/MaskStaging.hh" +#include <boost/property_tree/ptree_fwd.hpp> + +class AbsFormatter; + +namespace FEI3{ + + class Module: public AbsModule{ + public: + Module(const char* name, unsigned id, unsigned inLink, unsigned outLink, AbsFormatter* fmt); + virtual ~Module(); + enum {N_FRONTENDS=16}; + enum PAR{NOT_FOUND, GLOBAL, MCC, SPECIAL, PIXEL}; + Mcc* mcc(){return &m_mcc;} + Frontend* frontend(int i){return m_frontend[i];} + void configureHW(); + void resetHW(bool resetfe=true); + void resetFE(); + void setupMaskStageHW(int stage); + void enableDataTakingHW(); + int setupParameterHW(const char* name, int val); //HW setup + PAR setParameter(const char* name, int val); // internal setup + int configureScan(boost::property_tree::ptree* scanOptions); + ModuleInfo getModuleInfo(); + const float dacToElectrons(int fe, int dac); + virtual void destroy(); + +protected: + Frontend *m_frontend[N_FRONTENDS]; + Mcc m_mcc; + MaskStaging<FEI3::Module>* m_maskStaging; +}; + +}; +#endif diff --git a/rce/rcecalib/config/FEI3/ModuleGroup.cc b/rce/rcecalib/config/FEI3/ModuleGroup.cc new file mode 100644 index 00000000..63e65e59 --- /dev/null +++ b/rce/rcecalib/config/FEI3/ModuleGroup.cc @@ -0,0 +1,88 @@ + +#include <boost/property_tree/ptree.hpp> +#include <stdio.h> +#include "rcecalib/config/FEI3/Module.hh" +#include "rcecalib/config/FEI3/ModuleGroup.hh" +#include "rcecalib/util/exceptions.hh" +#include "ers/ers.h" +#include "rcecalib/HW/SerialIF.hh" + +namespace FEI3{ + +void ModuleGroup::addModule(Module* module){ + m_modules.push_back(module); + m_channelInMask|=1<<module->getInLink(); + m_channelOutMask|=1<<module->getOutLink(); +} + +void ModuleGroup::deleteModules(){ + for (unsigned i=0; i<m_modules.size();i++){ + //cannot call delete directly because IPC modules need to call _destroy() instead. + m_modules[i]->destroy(); + } + m_modules.clear(); + m_channelInMask=0; + m_channelOutMask=0; +} + +int ModuleGroup::setupParameterHW(const char* name, int val, bool bcOK){ + int retval=0; + for (unsigned int i=0;i<m_modules.size();i++){ + SerialIF::setChannelInMask(1<<m_modules[i]->getInLink()); + retval+=m_modules[i]->setupParameterHW(name,val); + } + disableAllInChannels(); + return retval; +} + +int ModuleGroup::setupMaskStageHW(int stage){ + for (unsigned int i=0;i<m_modules.size();i++){ + SerialIF::setChannelInMask(1<<m_modules[i]->getInLink()); + m_modules[i]->setupMaskStageHW(stage); + } + disableAllInChannels(); + return 0; +} + +void ModuleGroup::configureModulesHW(){ + //std::cout<<"Configure Modules HW"<<std::endl; + for (unsigned int i=0;i<m_modules.size();i++){ + SerialIF::setChannelInMask(1<<m_modules[i]->getInLink()); + m_modules[i]->configureHW(); + } + disableAllInChannels(); +} + +void ModuleGroup::resetFE(){ + for (unsigned int i=0;i<m_modules.size();i++){ + SerialIF::setChannelInMask(1<<m_modules[i]->getInLink()); + m_modules[i]->resetFE(); + } + disableAllInChannels(); +} + +void ModuleGroup::enableDataTakingHW(){ + //std::cout<<"ConfigIF enabled data taking"<<std::endl; + for (unsigned int i=0;i<m_modules.size();i++){ + SerialIF::setChannelInMask(1<<m_modules[i]->getInLink()); + m_modules[i]->enableDataTakingHW(); + } + disableAllInChannels(); +} + +int ModuleGroup::verifyModuleConfigHW(){ + return 0; // does not exist for FEI3 +} +void ModuleGroup::resetErrorCountersHW(){ + //does not exist for FEI3 +} + +int ModuleGroup::configureScan(boost::property_tree::ptree *scanOptions){ + int retval=0; + for (unsigned int i=0;i<m_modules.size();i++){ + retval+=m_modules[i]->configureScan(scanOptions); + } + return retval; +} + +} diff --git a/rce/rcecalib/config/FEI3/ModuleGroup.hh b/rce/rcecalib/config/FEI3/ModuleGroup.hh new file mode 100644 index 00000000..1c164730 --- /dev/null +++ b/rce/rcecalib/config/FEI3/ModuleGroup.hh @@ -0,0 +1,33 @@ +#ifndef MODULEGROUPFEI3_HH +#define MODULEGROUPFEI3_HH +#include "rcecalib/config/AbsModuleGroup.hh" +#include <boost/property_tree/ptree_fwd.hpp> +#include <vector> + +namespace FEI3{ + + class Module; + +class ModuleGroup: public AbsModuleGroup{ +public: + ModuleGroup():AbsModuleGroup(){}; + virtual ~ModuleGroup(){} + void addModule(Module* module); + void deleteModules(); + int setupParameterHW(const char* name, int val, bool bcok); + int setupMaskStageHW(int stage); + void configureModulesHW(); + int verifyModuleConfigHW(); + void resetErrorCountersHW(); + int configureScan(boost::property_tree::ptree *scanOptions); + void resetFE(); + void enableDataTakingHW(); + unsigned getNmodules(){return m_modules.size();} +private: + void switchToConfigModeHW(); + std::vector<Module*> m_modules; + +}; +} + +#endif diff --git a/rce/rcecalib/config/FEI3/PixelRegister.cc b/rce/rcecalib/config/FEI3/PixelRegister.cc new file mode 100644 index 00000000..2c0886c2 --- /dev/null +++ b/rce/rcecalib/config/FEI3/PixelRegister.cc @@ -0,0 +1,25 @@ +#include "rcecalib/config/FEI3/PixelRegister.hh" + +namespace FEI3{ + std::string PixelRegister::m_cachedName; + PixelRegister::Field PixelRegister::m_cachedField(not_found); + std::map<std::string, PixelRegister::Field> PixelRegister::m_parameters; + bool PixelRegister::m_initialized = false; + void PixelRegister::initialize(){ + // Translation from scan parameter to Global register field + m_parameters["TDACS"]=tdac; + m_parameters["FDACS"]=fdac; + m_initialized=true; + } + PixelRegister::Field PixelRegister::lookupParameter(const char* name){ + // check if this is the last name used, return cached value + if(std::string(name)==m_cachedName)return m_cachedField; + // Now check if we can translate the name to a field name + if(m_parameters.find(name)!=m_parameters.end()){ + //cache result + m_cachedName=name; + m_cachedField=m_parameters[name]; + return m_cachedField; + }else return not_found; + } +} diff --git a/rce/rcecalib/config/FEI3/PixelRegister.hh b/rce/rcecalib/config/FEI3/PixelRegister.hh new file mode 100644 index 00000000..9ca12110 --- /dev/null +++ b/rce/rcecalib/config/FEI3/PixelRegister.hh @@ -0,0 +1,56 @@ +#ifndef PIXEL_REGISTER_FEI3_HH +#define PIXEL_REGISTER_FEI3_HH + +#include <string> +#include <map> + + +namespace FEI3{ + + static const unsigned fieldPos[]={0,1,2,3,10,13}; + static const unsigned fieldMask[]={1,1,1,0x7f,0x7,1}; + + class PixelRegister{ + public: + enum Field{hitbus, select, enable, tdac, fdac, kill, Nfields, not_found}; + PixelRegister(): m_register(0){ + if(!m_initialized)initialize(); + } + unsigned getBit(unsigned i){ + return (m_register>>i)&0x1; + } + void setBit(unsigned i, bool val){ + if(val){ + m_register|=(1<<i); + } else{ + m_register&=~(1<<i); + } + } + void setField(Field f, unsigned val){ + m_register&=~(fieldMask[f]<<fieldPos[f]); //clear + m_register|=(fieldMask[f]&val)<<fieldPos[f]; //set + } + unsigned getField(Field f){ + return (m_register>>fieldPos[f])&fieldMask[f]; + } + unsigned short get(){ + return m_register; + } + void set(unsigned short val){ + m_register=val; + } + + static Field lookupParameter(const char* name); + + private: + unsigned short m_register; + static std::string m_cachedName; + static Field m_cachedField; + static std::map<std::string, Field> m_parameters; + static bool m_initialized; + static void initialize(); + }; + +}; + +#endif diff --git a/rce/rcecalib/config/FEI3/RegularMaskStaging.cc b/rce/rcecalib/config/FEI3/RegularMaskStaging.cc new file mode 100644 index 00000000..d648c7fc --- /dev/null +++ b/rce/rcecalib/config/FEI3/RegularMaskStaging.cc @@ -0,0 +1,34 @@ +#include "rcecalib/config/FEI3/RegularMaskStaging.hh" +#include "rcecalib/config/FEI3/Module.hh" + +namespace FEI3{ + + RegularMaskStaging::RegularMaskStaging(FEI3::Module* mod, Masks masks, std::string type) + :MaskStaging<FEI3::Module>(mod, masks, type){ + m_nStages=strtoul(type.substr(6).c_str(),0,10); + } + + void RegularMaskStaging::setupMaskStageHW(int maskStage){ + if(maskStage==0){ + clearBitsHW(); + for (int i=0;i<Module::N_FRONTENDS;i++){ + int nPixelsPerChip = Frontend::N_ROWS * Frontend::N_COLS; + for(int index=maskStage;index<nPixelsPerChip;index+=m_nStages){ + int row = (int) index % Frontend::N_ROWS; + int col = (int) index / Frontend::N_ROWS; + if( col%2 ) row = 159 - row; + PixelRegister *pixel=m_module->frontend(i)->getPixelRegister(col,row); + pixel->set(pixel->get() | m_masks.iMask); + } + } + m_module->configureHW(); + }else{ + m_module->resetHW(false); // only reset MCC, not FE + m_module->mcc()->configureHW(); + //std::cout<<"Shifting enables"<<std::endl; + for (int i=0;i<Module::N_FRONTENDS;i++){ + m_module->frontend(i)->shiftEnablesHW(m_masks.iMask); + } + } + } +} diff --git a/rce/rcecalib/config/FEI3/RegularMaskStaging.hh b/rce/rcecalib/config/FEI3/RegularMaskStaging.hh new file mode 100644 index 00000000..ba6d4a5a --- /dev/null +++ b/rce/rcecalib/config/FEI3/RegularMaskStaging.hh @@ -0,0 +1,19 @@ +#ifndef FEI3REGULARMASKSTAGING_HH +#define FEI3REGULARMASKSTAGING_HH + +#include "rcecalib/config/Masks.hh" +#include "rcecalib/config/MaskStaging.hh" + +namespace FEI3{ + class Module; + + class RegularMaskStaging: public MaskStaging<FEI3::Module>{ + public: + RegularMaskStaging(FEI3::Module* module, Masks masks, std::string type); + void setupMaskStageHW(int maskStage); + private: + int m_nStages; + }; + +} +#endif diff --git a/rce/rcecalib/config/FEI4/AnalogColpr2MaskStagingFei4a.cc b/rce/rcecalib/config/FEI4/AnalogColpr2MaskStagingFei4a.cc new file mode 100644 index 00000000..6c4b360c --- /dev/null +++ b/rce/rcecalib/config/FEI4/AnalogColpr2MaskStagingFei4a.cc @@ -0,0 +1,43 @@ +#include "rcecalib/config/FEI4/AnalogColpr2MaskStagingFei4a.hh" +#include "rcecalib/config/FEI4/Module.hh" + +namespace FEI4{ + + AnalogColpr2MaskStagingFei4a::AnalogColpr2MaskStagingFei4a(FEI4::Module* mod, Masks masks, std::string type) + :MaskStaging<FEI4::Module>(mod, masks, type){ + if(type=="FEI4_COLPR2x6")m_nStages=6; + else m_nStages=1; + } + + void AnalogColpr2MaskStagingFei4a::setupMaskStageHW(int maskStage){ + if(m_initialized==false || maskStage==0){ + clearBitsHW(); + m_initialized=true; + } + const int nColStages=14; + PixelRegister* pixel=m_module->pixel(); + GlobalRegister* global=m_module->global(); + unsigned dcolStage=maskStage%nColStages; + unsigned stage=maskStage/nColStages; + if((maskStage+nColStages)/nColStages!=(maskStage+nColStages-1)/nColStages){ //need to set up pixel mask + global->setField("Colpr_Mode", 3, GlobalRegister::SW); + for(int i=0;i<PixelRegister::N_PIXEL_REGISTER_BITS;i++){ + if(m_masks.iMask&(1<<i)){ + pixel->setupMaskStage(i, stage, m_nStages); + m_module->writeDoubleColumnHW(i, i, 0, 0); + } + } + } + // stage 0-5: colpr_mode=2, colpr_addr= 1, 2, 3, 4, 5, 6 + // stage 6-9: colpr_mode=0, colpr_addr= 8, 16, 24, 32 + // stage 10-13: colpr_mode=0, colpr_addr= 7, 15, 23, 31 + if(dcolStage<6){ + global->setField("Colpr_Mode", 2, GlobalRegister::SW); + global->setField("Colpr_Addr", dcolStage+1, GlobalRegister::HW); + }else { + global->setField("Colpr_Mode", 0, GlobalRegister::SW); + int addr= dcolStage<10? (dcolStage-6)*8+8 : (dcolStage-10)*8+7; + global->setField("Colpr_Addr", addr , GlobalRegister::HW); + } + } +} diff --git a/rce/rcecalib/config/FEI4/AnalogColpr2MaskStagingFei4a.hh b/rce/rcecalib/config/FEI4/AnalogColpr2MaskStagingFei4a.hh new file mode 100644 index 00000000..a5fa001a --- /dev/null +++ b/rce/rcecalib/config/FEI4/AnalogColpr2MaskStagingFei4a.hh @@ -0,0 +1,20 @@ +#ifndef FEI4ANALOGCOLPR2MASKSTAGINGFEI4A_HH +#define FEI4ANALOGCOLPR2MASKSTAGINGFEI4A_HH + +#include "rcecalib/config/Masks.hh" +#include "rcecalib/config/MaskStaging.hh" + +namespace FEI4{ + + class Module; + + class AnalogColpr2MaskStagingFei4a: public MaskStaging<FEI4::Module>{ + public: + AnalogColpr2MaskStagingFei4a(FEI4::Module* module, Masks masks, std::string type); + void setupMaskStageHW(int maskStage); + private: + int m_nStages; + }; + +} +#endif diff --git a/rce/rcecalib/config/FEI4/AnalogColprMaskStaging.cc b/rce/rcecalib/config/FEI4/AnalogColprMaskStaging.cc new file mode 100644 index 00000000..f23e25a3 --- /dev/null +++ b/rce/rcecalib/config/FEI4/AnalogColprMaskStaging.cc @@ -0,0 +1,51 @@ +#include "rcecalib/config/FEI4/AnalogColprMaskStaging.hh" +#include "rcecalib/config/FEI4/Module.hh" + +namespace FEI4{ + + AnalogColprMaskStaging::AnalogColprMaskStaging(FEI4::Module* mod, Masks masks, std::string type) + :MaskStaging<FEI4::Module>(mod, masks, type), m_oldDcolStage(-1){ + m_nStages=strtoul(type.substr(12).c_str(),0,10); + m_colpr_mode=strtoul(type.substr(10,1).c_str(),0,10); + if(m_colpr_mode==0)m_nColStages=40; + else if(m_colpr_mode==1)m_nColStages=4; + else if(m_colpr_mode==2)m_nColStages=8; + else m_nColStages=1; + std::cout<<"Set up COLPR mask staging with "<<m_nColStages<<" col stages and "<< m_nStages<<" row stages"<<std::endl; + } + + void AnalogColprMaskStaging::setupMaskStageHW(int maskStage){ + int dcolStage=maskStage/m_nStages; + unsigned stage=maskStage%m_nStages; + if(m_initialized==false || maskStage==0 || dcolStage!=m_oldDcolStage){ + clearBitsHW(); + m_initialized=true; + m_oldDcolStage=dcolStage; + } + PixelRegister* pixel=m_module->pixel(); + GlobalRegister* global=m_module->global(); + global->setField("Colpr_Mode", m_colpr_mode, GlobalRegister::SW); + for(int i=0;i<PixelRegister::N_PIXEL_REGISTER_BITS;i++){ + if(m_masks.iMask&(1<<i)){ + pixel->setupMaskStageCol(dcolStage*2+1, i, stage, m_nStages); + m_module->writeDoubleColumnHW(i, i, dcolStage, dcolStage); + int seconddcol=dcolStage-1<0? m_nColStages-1 : dcolStage-1; + pixel->setupMaskStageCol(seconddcol*2+2, i, stage, m_nStages); + m_module->writeDoubleColumnHW(i, i, seconddcol, seconddcol); + if(dcolStage==0 || dcolStage==m_nColStages-1){ + if(dcolStage==0){ + pixel->setBitCol(80, i, 0); + }else{ + pixel->setupMaskStageCol(79, i, stage, m_nStages); + pixel->setupMaskStageCol(80, i, stage, m_nStages); + } + global->setField("Colpr_Mode", 0, GlobalRegister::SW); + m_module->writeDoubleColumnHW(i, i, 39, 39); + global->setField("Colpr_Mode", m_colpr_mode, GlobalRegister::SW); + } + } + } + global->setField("Colpr_Mode", m_colpr_mode, GlobalRegister::SW); + global->setField("Colpr_Addr", dcolStage, GlobalRegister::HW); + } +} diff --git a/rce/rcecalib/config/FEI4/AnalogColprMaskStaging.hh b/rce/rcecalib/config/FEI4/AnalogColprMaskStaging.hh new file mode 100644 index 00000000..e8074e63 --- /dev/null +++ b/rce/rcecalib/config/FEI4/AnalogColprMaskStaging.hh @@ -0,0 +1,23 @@ +#ifndef FEI4ANALOGCOLPRMASKSTAGING_HH +#define FEI4ANALOGCOLPRMASKSTAGING_HH + +#include "rcecalib/config/Masks.hh" +#include "rcecalib/config/MaskStaging.hh" + +namespace FEI4{ + + class Module; + + class AnalogColprMaskStaging: public MaskStaging<FEI4::Module>{ + public: + AnalogColprMaskStaging(FEI4::Module* module, Masks masks, std::string type); + void setupMaskStageHW(int maskStage); + private: + int m_nStages; + int m_nColStages; + int m_colpr_mode; + int m_oldDcolStage; + }; + +} +#endif diff --git a/rce/rcecalib/config/FEI4/AnalogMaskStaging.cc b/rce/rcecalib/config/FEI4/AnalogMaskStaging.cc new file mode 100644 index 00000000..c03faa97 --- /dev/null +++ b/rce/rcecalib/config/FEI4/AnalogMaskStaging.cc @@ -0,0 +1,36 @@ +#include "rcecalib/config/FEI4/AnalogMaskStaging.hh" +#include "rcecalib/config/FEI4/Module.hh" + +namespace FEI4{ + + AnalogMaskStaging::AnalogMaskStaging(FEI4::Module* mod, Masks masks, std::string type) + :MaskStaging<FEI4::Module>(mod, masks, type), m_oldDcolStage(-1){ + if(type=="FEI4_COL_ANL_40x8")m_nStages=6; + else m_nStages=3; + } + + void AnalogMaskStaging::setupMaskStageHW(int maskStage){ + int dcolStage=maskStage/m_nStages; + int stage=maskStage%m_nStages; + if(m_initialized==false || maskStage==0 || dcolStage!=m_oldDcolStage){ + clearBitsHW(); + m_initialized=true; + m_oldDcolStage=dcolStage; + } + PixelRegister* pixel=m_module->pixel(); + GlobalRegister* global=m_module->global(); + global->setField("Colpr_Mode", 0, GlobalRegister::SW); + for(int i=0;i<PixelRegister::N_PIXEL_REGISTER_BITS;i++){ + if(m_masks.iMask&(1<<i)){ + pixel->setupMaskStageCol(dcolStage*2+1, i, stage, m_nStages); + if(dcolStage==39)pixel->setupMaskStageCol(80, i, stage, m_nStages); + m_module->writeDoubleColumnHW(i, i, dcolStage, dcolStage); + if(dcolStage!=0){ + pixel->setupMaskStageCol(dcolStage*2, i, stage, m_nStages); + m_module->writeDoubleColumnHW(i, i, dcolStage-1, dcolStage-1); + global->setField("Colpr_Addr", dcolStage, GlobalRegister::HW); + } + } + } + } +} diff --git a/rce/rcecalib/config/FEI4/AnalogMaskStaging.hh b/rce/rcecalib/config/FEI4/AnalogMaskStaging.hh new file mode 100644 index 00000000..592a6280 --- /dev/null +++ b/rce/rcecalib/config/FEI4/AnalogMaskStaging.hh @@ -0,0 +1,21 @@ +#ifndef FEI4ANALOGMASKSTAGING_HH +#define FEI4ANALOGMASKSTAGING_HH + +#include "rcecalib/config/Masks.hh" +#include "rcecalib/config/MaskStaging.hh" + +namespace FEI4{ + + class Module; + + class AnalogMaskStaging: public MaskStaging<FEI4::Module>{ + public: + AnalogMaskStaging(FEI4::Module* module, Masks masks, std::string type); + void setupMaskStageHW(int maskStage); + private: + int m_oldDcolStage; + int m_nStages; + }; + +} +#endif diff --git a/rce/rcecalib/config/FEI4/AnalogSimpleColprMaskStaging.cc b/rce/rcecalib/config/FEI4/AnalogSimpleColprMaskStaging.cc new file mode 100644 index 00000000..e98d254e --- /dev/null +++ b/rce/rcecalib/config/FEI4/AnalogSimpleColprMaskStaging.cc @@ -0,0 +1,38 @@ +#include "rcecalib/config/FEI4/AnalogSimpleColprMaskStaging.hh" +#include "rcecalib/config/FEI4/Module.hh" + +namespace FEI4{ + + AnalogSimpleColprMaskStaging::AnalogSimpleColprMaskStaging(FEI4::Module* mod, Masks masks, std::string type) + :MaskStaging<FEI4::Module>(mod, masks, type){ + m_nStages=strtoul(type.substr(12).c_str(),0,10); + m_colpr_mode=strtoul(type.substr(10,1).c_str(),0,10); + if(m_colpr_mode==0)m_nColStages=40; + else if(m_colpr_mode==1)m_nColStages=4; + else if(m_colpr_mode==2)m_nColStages=8; + else m_nColStages=1; + std::cout<<"Set up COLPR mask staging with "<<m_nColStages<<" col stages and "<< m_nStages<<" row stages"<<std::endl; + } + + void AnalogSimpleColprMaskStaging::setupMaskStageHW(int maskStage){ + if(m_initialized==false || maskStage==0){ + clearBitsHW(); + m_initialized=true; + } + PixelRegister* pixel=m_module->pixel(); + GlobalRegister* global=m_module->global(); + unsigned dcolStage=maskStage%m_nColStages; + unsigned stage=maskStage/m_nColStages; + if((maskStage+m_nColStages)/m_nColStages!=(maskStage+m_nColStages-1)/m_nColStages){ //need to set up pixel mask + global->setField("Colpr_Mode", 3, GlobalRegister::SW); + for(int i=0;i<PixelRegister::N_PIXEL_REGISTER_BITS;i++){ + if(m_masks.iMask&(1<<i)){ + pixel->setupMaskStage(i, stage, m_nStages); + m_module->writeDoubleColumnHW(i, i, 0, 0); + } + } + } + global->setField("Colpr_Mode", m_colpr_mode, GlobalRegister::SW); + global->setField("Colpr_Addr", dcolStage+1, GlobalRegister::HW); + } +} diff --git a/rce/rcecalib/config/FEI4/AnalogSimpleColprMaskStaging.hh b/rce/rcecalib/config/FEI4/AnalogSimpleColprMaskStaging.hh new file mode 100644 index 00000000..244b7294 --- /dev/null +++ b/rce/rcecalib/config/FEI4/AnalogSimpleColprMaskStaging.hh @@ -0,0 +1,22 @@ +#ifndef FEI4ANALOGSIMPLECOLPRMASKSTAGING_HH +#define FEI4ANALOGSIMPLECOLPRMASKSTAGING_HH + +#include "rcecalib/config/Masks.hh" +#include "rcecalib/config/MaskStaging.hh" + +namespace FEI4{ + + class Module; + + class AnalogSimpleColprMaskStaging: public MaskStaging<FEI4::Module>{ + public: + AnalogSimpleColprMaskStaging(FEI4::Module* module, Masks masks, std::string type); + void setupMaskStageHW(int maskStage); + private: + int m_nStages; + int m_nColStages; + int m_colpr_mode; + }; + +} +#endif diff --git a/rce/rcecalib/config/FEI4/AnalogSingleMaskStaging.cc b/rce/rcecalib/config/FEI4/AnalogSingleMaskStaging.cc new file mode 100644 index 00000000..17ce6727 --- /dev/null +++ b/rce/rcecalib/config/FEI4/AnalogSingleMaskStaging.cc @@ -0,0 +1,19 @@ +#include "rcecalib/config/FEI4/AnalogSingleMaskStaging.hh" +#include "rcecalib/config/FEI4/Module.hh" + +namespace FEI4{ + + AnalogSingleMaskStaging::AnalogSingleMaskStaging(FEI4::Module* mod, Masks masks, std::string type) + :MaskStaging<FEI4::Module>(mod, masks, type){ + } + + void AnalogSingleMaskStaging::setupMaskStageHW(int maskStage){ + if(m_initialized==false || maskStage==0){ + clearBitsHW(); + m_initialized=true; + } + GlobalRegister* global=m_module->global(); + global->setField("Colpr_Mode", 0, GlobalRegister::SW); + global->setField("Colpr_Addr", maskStage, GlobalRegister::HW); + } +} diff --git a/rce/rcecalib/config/FEI4/AnalogSingleMaskStaging.hh b/rce/rcecalib/config/FEI4/AnalogSingleMaskStaging.hh new file mode 100644 index 00000000..4cfa4728 --- /dev/null +++ b/rce/rcecalib/config/FEI4/AnalogSingleMaskStaging.hh @@ -0,0 +1,18 @@ +#ifndef FEI4ANALOGSINGLEMASKSTAGING_HH +#define FEI4ANALOGSINGLEMASKSTAGING_HH + +#include "rcecalib/config/Masks.hh" +#include "rcecalib/config/MaskStaging.hh" + +namespace FEI4{ + + class Module; + + class AnalogSingleMaskStaging: public MaskStaging<FEI4::Module>{ + public: + AnalogSingleMaskStaging(FEI4::Module* module, Masks masks, std::string type); + void setupMaskStageHW(int maskStage); + }; + +} +#endif diff --git a/rce/rcecalib/config/FEI4/CrosstalkFastMaskStaging.cc b/rce/rcecalib/config/FEI4/CrosstalkFastMaskStaging.cc new file mode 100644 index 00000000..416c75e1 --- /dev/null +++ b/rce/rcecalib/config/FEI4/CrosstalkFastMaskStaging.cc @@ -0,0 +1,106 @@ +#include "rcecalib/config/FEI4/CrosstalkFastMaskStaging.hh" +#include "rcecalib/config/FEI4/Module.hh" + +namespace FEI4{ + + CrosstalkFastMaskStaging::CrosstalkFastMaskStaging(FEI4::Module* mod, Masks masks, std::string type) + :MaskStaging<FEI4::Module>(mod, masks, type){ + m_nStages=8; + } + + void CrosstalkFastMaskStaging::setupMaskStageHW(int maskStage){ + if(m_initialized==false || maskStage==0){ + clearBitsHW(); + m_initialized=true; + } + PixelRegister* pixel=m_module->pixel(); + GlobalRegister* global=m_module->global(); + unsigned rowstage=maskStage%m_nStages; + unsigned dcolstage=maskStage/m_nStages; + + global->setField("Colpr_Mode", 0, GlobalRegister::SW); + + // std::cout<<"stage = "<<maskStage<<" : dcol = "<<dcolstage<<" ; rowgroup = "<<rowstage<<std::endl; + + for(int i=0;i<PixelRegister::N_PIXEL_REGISTER_BITS;i++){ + + if(m_masks.xtalk_on&(1<<i)){ + //this is for the pixel we are reading out, this should set the "enable" bit + + pixel->setupMaskStageCol(2*dcolstage+1, i, rowstage, m_nStages); //this sets bits starting in rowstage+1 + if(dcolstage==39)pixel->setupMaskStageCol(80, i, rowstage, m_nStages); + m_module->writeDoubleColumnHW(i, i, dcolstage, dcolstage); + + if(dcolstage!=0){ + if(rowstage==0)pixel->setBitCol(dcolstage*2-1, i, 0); //disable previous column + pixel->setupMaskStageCol(dcolstage*2, i, rowstage, m_nStages); + m_module->writeDoubleColumnHW(i, i, dcolstage-1, dcolstage-1); + if(dcolstage>1){ + if(rowstage==0)pixel->setBitCol(dcolstage*2-2, i, 0); //disable previous-previous column + m_module->writeDoubleColumnHW(i, i, dcolstage-2, dcolstage-2); + } + } + + + } + if(m_masks.xtalk_off&(1<<i)){ + //this is for the pixel we are strobing + + if(rowstage>0){ + pixel->setupMaskStageCol(2*dcolstage+1, i, rowstage-1, m_nStages); //this sets bits starting in rowstage + } + else{ + pixel->setupMaskStageCol(2*dcolstage+1, i, rowstage+m_nStages-1, m_nStages); //this sets bits starting in rowstage+m_nStages + } + //we have to set the bits for rowstage+2 by hand, since setupMaskStageCol clears the bits each time it's called + for(int krow=rowstage+2;krow<=PixelRegister::N_ROWS;krow+=m_nStages){ + pixel->setBit(i, krow, 2*dcolstage+1, 1); + } + + if(dcolstage==39){ + + if(rowstage>0){ + pixel->setupMaskStageCol(80, i, rowstage-1, m_nStages); //this sets bits starting in rowstage + } + else{ + pixel->setupMaskStageCol(80, i, rowstage+m_nStages-1, m_nStages); //this sets bits starting in rowstage+m_nStages + } + //we have to set the bits for rowstage+2 by hand, since setupMaskStageCol clears the bits each time it's called + for(int krow=rowstage+2;krow<=PixelRegister::N_ROWS;krow+=m_nStages){ + pixel->setBit(i, krow, 80, 1); + } + + } + m_module->writeDoubleColumnHW(i, i, dcolstage, dcolstage); + + if(dcolstage!=0){ + if(rowstage==0)pixel->setBitCol(dcolstage*2-1, i, 0); //disable previous column + + if(rowstage>0){ + pixel->setupMaskStageCol(2*dcolstage, i, rowstage-1, m_nStages); //this sets bits starting in rowstage + } + else{ + pixel->setupMaskStageCol(2*dcolstage, i, rowstage+m_nStages-1, m_nStages); //this sets bits starting in rowstage+m_nStages + } + + //we have to set the bits for rowstage+2 by hand, since setupMaskStageCol clears the bits each time it's called + for(int krow=rowstage+2;krow<=PixelRegister::N_ROWS;krow+=m_nStages){ + pixel->setBit(i, krow, 2*dcolstage, 1); + } + m_module->writeDoubleColumnHW(i, i, dcolstage-1, dcolstage-1); + + if(dcolstage>1){ + if(rowstage==0)pixel->setBitCol(dcolstage*2-2, i, 0); //disable previous-previous column + m_module->writeDoubleColumnHW(i, i, dcolstage-2, dcolstage-2); + } + + } + + } //end if(m_masks.xtalk_off&(1<<i)) + + } //end for-loop over pixel register bits + + global->setField("Colpr_Addr", dcolstage, GlobalRegister::HW); + + } +} diff --git a/rce/rcecalib/config/FEI4/CrosstalkFastMaskStaging.hh b/rce/rcecalib/config/FEI4/CrosstalkFastMaskStaging.hh new file mode 100644 index 00000000..19152410 --- /dev/null +++ b/rce/rcecalib/config/FEI4/CrosstalkFastMaskStaging.hh @@ -0,0 +1,19 @@ +#ifndef CROSSTALKFASTMASKSTAGING_HH +#define CROSSTALKFASTMASKSTAGING_HH + +#include "rcecalib/config/Masks.hh" +#include "rcecalib/config/MaskStaging.hh" + +namespace FEI4{ + class Module; + + class CrosstalkFastMaskStaging: public MaskStaging<FEI4::Module>{ + public: + CrosstalkFastMaskStaging(FEI4::Module* module, Masks masks, std::string type); + void setupMaskStageHW(int maskStage); + private: + int m_nStages; +}; + +} +#endif diff --git a/rce/rcecalib/config/FEI4/CrosstalkMaskStaging.cc b/rce/rcecalib/config/FEI4/CrosstalkMaskStaging.cc new file mode 100644 index 00000000..cb8e7638 --- /dev/null +++ b/rce/rcecalib/config/FEI4/CrosstalkMaskStaging.cc @@ -0,0 +1,44 @@ +#include "rcecalib/config/FEI4/CrosstalkMaskStaging.hh" +#include "rcecalib/config/FEI4/Module.hh" + +namespace FEI4{ + + CrosstalkMaskStaging::CrosstalkMaskStaging(FEI4::Module* mod, Masks masks, std::string type) + :MaskStaging<FEI4::Module>(mod, masks, type){ + m_nStages=PixelRegister::N_ROWS*PixelRegister::N_COLS; + } + + void CrosstalkMaskStaging::setupMaskStageHW(int maskStage){ + if(m_initialized==false || maskStage==0){ + clearBitsHW(); + m_initialized=true; + } + PixelRegister* pixel=m_module->pixel(); + GlobalRegister* global=m_module->global(); + unsigned rowstage=maskStage%PixelRegister::N_ROWS; + unsigned colstage=maskStage/PixelRegister::N_ROWS; + global->setField("Colpr_Mode", 0, GlobalRegister::SW); + for(int i=0;i<PixelRegister::N_PIXEL_REGISTER_BITS;i++){ + if(m_masks.xtalk_on&(1<<i)){ + pixel->setupMaskStageCol(colstage+1, i, rowstage, PixelRegister::N_ROWS); + m_module->writeDoubleColumnHW(i, i, colstage/2, colstage/2); + } + if(m_masks.xtalk_off&(1<<i)){ + pixel->setBitCol(colstage+1, i, 0); + if(rowstage>0)pixel->setBit(i, rowstage, colstage+1, 1); + if(rowstage+1<PixelRegister::N_ROWS)pixel->setBit(i, rowstage+2, colstage+1, 1); + m_module->writeDoubleColumnHW(i, i, colstage/2, colstage/2); + } + //clear previous column + if(((m_masks.xtalk_off | m_masks.xtalk_on)&(1<<i)) && rowstage==0&&colstage!=0){ + pixel->setBitCol(colstage, i, 0); + m_module->writeDoubleColumnHW(i, i, (colstage-1)/2, (colstage-1)/2); + } + } + if(colstage!=79) { + global->setField("Colpr_Addr", (colstage+1)/2, GlobalRegister::HW); + } else { + global->setField("Colpr_Addr", 39, GlobalRegister::HW); + } + } +} diff --git a/rce/rcecalib/config/FEI4/CrosstalkMaskStaging.hh b/rce/rcecalib/config/FEI4/CrosstalkMaskStaging.hh new file mode 100644 index 00000000..c305cdb6 --- /dev/null +++ b/rce/rcecalib/config/FEI4/CrosstalkMaskStaging.hh @@ -0,0 +1,19 @@ +#ifndef CROSSTALKMASKSTAGING_HH +#define CROSSTALKMASKSTAGING_HH + +#include "rcecalib/config/Masks.hh" +#include "rcecalib/config/MaskStaging.hh" + +namespace FEI4{ + class Module; + + class CrosstalkMaskStaging: public MaskStaging<FEI4::Module>{ + public: + CrosstalkMaskStaging(FEI4::Module* module, Masks masks, std::string type); + void setupMaskStageHW(int maskStage); + private: + int m_nStages; +}; + +} +#endif diff --git a/rce/rcecalib/config/FEI4/DiffusionMaskStaging.cc b/rce/rcecalib/config/FEI4/DiffusionMaskStaging.cc new file mode 100644 index 00000000..e020b501 --- /dev/null +++ b/rce/rcecalib/config/FEI4/DiffusionMaskStaging.cc @@ -0,0 +1,28 @@ +#include "rcecalib/config/FEI4/DiffusionMaskStaging.hh" +#include "rcecalib/config/FEI4/Module.hh" + +namespace FEI4{ + + DiffusionMaskStaging::DiffusionMaskStaging(FEI4::Module* mod, Masks masks, std::string type) + :MaskStaging<FEI4::Module>(mod, masks, type){ + m_nStages=16; + } + + void DiffusionMaskStaging::setupMaskStageHW(int maskStage){ + + // std::cout<<"diffusion stage = "<<maskStage<<std::endl; + + GlobalRegister* global=m_module->global(); + + //std::cout<<"Setting colpr_mode to 3"<<std::endl; + global->setField("Colpr_Mode", 3, GlobalRegister::SW); + + //the "double column" for enabling strobe, which has skewed addressing + //the strobe double columns 0,1,2.....38,39 correspond to columns: + //(0),(1,2),(3,4).....(75,76),(77,78,79) + int strobeDCol = 39; //it doesn't matter what value we set this to, but we do need to set it. + global->setField("Colpr_Addr", strobeDCol, GlobalRegister::HW); + + } + +} diff --git a/rce/rcecalib/config/FEI4/DiffusionMaskStaging.hh b/rce/rcecalib/config/FEI4/DiffusionMaskStaging.hh new file mode 100644 index 00000000..b0c7f0da --- /dev/null +++ b/rce/rcecalib/config/FEI4/DiffusionMaskStaging.hh @@ -0,0 +1,19 @@ +#ifndef DIFFUSIONMASKSTAGING_HH +#define DIFFUSIONMASKSTAGING_HH + +#include "rcecalib/config/Masks.hh" +#include "rcecalib/config/MaskStaging.hh" + +namespace FEI4{ + class Module; + + class DiffusionMaskStaging: public MaskStaging<FEI4::Module>{ + public: + DiffusionMaskStaging(FEI4::Module* module, Masks masks, std::string type); + void setupMaskStageHW(int maskStage); + private: + int m_nStages; +}; + +} +#endif diff --git a/rce/rcecalib/config/FEI4/DigStepMaskStaging.cc b/rce/rcecalib/config/FEI4/DigStepMaskStaging.cc new file mode 100644 index 00000000..d1ccd2d9 --- /dev/null +++ b/rce/rcecalib/config/FEI4/DigStepMaskStaging.cc @@ -0,0 +1,29 @@ +#include "rcecalib/config/FEI4/DigStepMaskStaging.hh" +#include "rcecalib/config/FEI4/Module.hh" + +namespace FEI4{ + + DigStepMaskStaging::DigStepMaskStaging(FEI4::Module* mod, Masks masks, std::string type) + :MaskStaging<FEI4::Module>(mod, masks, type){ + m_nStages=strtoul(type.substr(6).c_str(),0,10); + } + + void DigStepMaskStaging::setupMaskStageHW(int maskStage){ + if(m_initialized==false || maskStage==0){ + clearBitsHW(); + m_initialized=true; + } + PixelRegister* pixel=m_module->pixel(); + GlobalRegister* global=m_module->global(); + global->setField("Colpr_Addr", 0, GlobalRegister::SW); + global->setField("Colpr_Mode", 3, GlobalRegister::SW); + for(int i=0;i<PixelRegister::N_PIXEL_REGISTER_BITS;i++){ + if(m_masks.iMask&(1<<i)){ + pixel->setupMaskStage(i, maskStage, m_nStages); + m_module->writeDoubleColumnHW(i, i, 0, 0); //stage 0 writes all bits (below) + } + } + // enable all pixels for charge injection + global->setField("Colpr_Mode", 3, GlobalRegister::HW); + } +} diff --git a/rce/rcecalib/config/FEI4/DigStepMaskStaging.hh b/rce/rcecalib/config/FEI4/DigStepMaskStaging.hh new file mode 100644 index 00000000..dcb4a024 --- /dev/null +++ b/rce/rcecalib/config/FEI4/DigStepMaskStaging.hh @@ -0,0 +1,19 @@ +#ifndef FEI4DIGITALSTEPSMASKSTAGING_HH +#define FEI4DIGITALSTEPSMASKSTAGING_HH + +#include "rcecalib/config/Masks.hh" +#include "rcecalib/config/MaskStaging.hh" + +namespace FEI4{ + class Module; + + class DigStepMaskStaging: public MaskStaging<FEI4::Module>{ + public: + DigStepMaskStaging(FEI4::Module* module, Masks masks, std::string type); + void setupMaskStageHW(int maskStage); + private: + int m_nStages; +}; + +} +#endif diff --git a/rce/rcecalib/config/FEI4/DigitalMaskStaging.cc b/rce/rcecalib/config/FEI4/DigitalMaskStaging.cc new file mode 100644 index 00000000..2f9087ed --- /dev/null +++ b/rce/rcecalib/config/FEI4/DigitalMaskStaging.cc @@ -0,0 +1,28 @@ +#include "rcecalib/config/FEI4/DigitalMaskStaging.hh" +#include "rcecalib/config/FEI4/Module.hh" + +namespace FEI4{ + + DigitalMaskStaging::DigitalMaskStaging(FEI4::Module* mod, Masks masks, std::string type) + :MaskStaging<FEI4::Module>(mod, masks, type){ + } + + void DigitalMaskStaging::setupMaskStageHW(int maskStage){ + if(m_initialized==false || maskStage==0){ + clearBitsHW(); + m_initialized=true; + } + PixelRegister* pixel=m_module->pixel(); + GlobalRegister* global=m_module->global(); + // Digital injection dcol by dcol + global->setField("Colpr_Mode", 0, GlobalRegister::SW); + for(int i=0;i<PixelRegister::N_PIXEL_REGISTER_BITS;i++){ + if(m_masks.iMask&(1<<i)){ + pixel->setBitDcol(maskStage, i, 1); //enable bit in double column + pixel->setBitDcol(maskStage-1, i, 0); //disable previous column + m_module->writeDoubleColumnHW(i, i, maskStage-1, maskStage); + global->setField("Colpr_Addr", maskStage, GlobalRegister::HW); + } + } + } +} diff --git a/rce/rcecalib/config/FEI4/DigitalMaskStaging.hh b/rce/rcecalib/config/FEI4/DigitalMaskStaging.hh new file mode 100644 index 00000000..84fe445b --- /dev/null +++ b/rce/rcecalib/config/FEI4/DigitalMaskStaging.hh @@ -0,0 +1,17 @@ +#ifndef FEI4DIGITALMASKSTAGING_HH +#define FEI4DIGITALMASKSTAGING_HH + +#include "rcecalib/config/Masks.hh" +#include "rcecalib/config/MaskStaging.hh" + +namespace FEI4{ + class Module; + + class DigitalMaskStaging: public MaskStaging<FEI4::Module>{ + public: + DigitalMaskStaging(FEI4::Module* module, Masks masks, std::string type); + void setupMaskStageHW(int maskStage); + }; + +} +#endif diff --git a/rce/rcecalib/config/FEI4/FECommands.cc b/rce/rcecalib/config/FEI4/FECommands.cc new file mode 100644 index 00000000..aa4598fd --- /dev/null +++ b/rce/rcecalib/config/FEI4/FECommands.cc @@ -0,0 +1,61 @@ + +#include "rcecalib/config/FEI4/FECommands.hh" + +namespace FEI4{ + + void FECommands::writeGlobalRegister(BitStream *bs, int reg, unsigned short value){ + unsigned cmd=0x5a0800; /* header (10110) + field2 (1000) + field3 (0010) */; + cmd|=((m_chipAddr|m_broadcasting)&0xf)<<6; // chip id + cmd|=reg&0x3f; // register address + bs->push_back(cmd); + bs->push_back(value<<16); // 16 bit register value + bs->push_back(0); // padding a la NewDsp + } + void FECommands::readGlobalRegister(BitStream *bs, int reg){ + unsigned cmd=0x5a0400; /* header (10110) + field2 (1000) + field3 (0001) */; + cmd|=((m_chipAddr|m_broadcasting)&0xf)<<6; // chip id + cmd|=reg&0x3f; // register address + bs->push_back(cmd); + bs->push_back(0); // padding a la NewDsp + } + void FECommands::globalReset(BitStream *bs){ + unsigned cmd=0x16880; + cmd|=(m_chipAddr|m_broadcasting)&0xf; + bs->push_back(cmd); + bs->push_back(0); // padding a la NewDsp + } + void FECommands::globalPulse(BitStream *bs, unsigned width) { + unsigned cmd=0x5a2400; /* header (10110) + field2 (1000) + field3 (1001) */; + cmd|=((m_chipAddr|m_broadcasting)&0xf)<<6; // chip id + cmd|=width&0x3f; // pulse width + bs->push_back(cmd); + bs->push_back(0); + } + void FECommands::switchMode(BitStream *bs, MODE m) { + unsigned cmd=0x5a2800; /* header (10110) + field2 (1000) + field3 (1010) */; + cmd|=((m_chipAddr|m_broadcasting)&0xf)<<6; // chip id + cmd|=m&0x3f; // mode (conf or run) + bs->push_back(cmd); + bs->push_back(0); + } + void FECommands::L1A(BitStream *bs){ + bs->push_back(0xE8000000); + } + void FECommands::sendECR(BitStream *bs){ + bs->push_back(0); + bs->push_back(0x00162000); /* MCC ECR command */ + bs->push_back(0); + } + void FECommands::sendBCR(BitStream *bs){ + bs->push_back(0); + bs->push_back(0x00161000); /* MCC BCR command */ + bs->push_back(0); + } + void FECommands::feWriteCommand(BitStream *bs){ + bs->push_back(0); + unsigned cmd=0x5a1000; + cmd|=((m_chipAddr|m_broadcasting)&0xf)<<6; + bs->push_back(cmd); + } + +}; diff --git a/rce/rcecalib/config/FEI4/FECommands.hh b/rce/rcecalib/config/FEI4/FECommands.hh new file mode 100644 index 00000000..f6632470 --- /dev/null +++ b/rce/rcecalib/config/FEI4/FECommands.hh @@ -0,0 +1,35 @@ +#ifndef FECOMMANDS_FEI4_HH +#define FECOMMANDS_FEI4_HH + +#include "rcecalib/HW/BitStream.hh" + +namespace FEI4{ + + class FECommands{ + public: + enum MODE {CONF=0x7, RUN=0x38}; + enum {PULSE_WIDTH=1}; + FECommands():m_chipAddr(0), m_broadcasting(0){} + void writeGlobalRegister(BitStream* bs, int reg, unsigned short value); + void readGlobalRegister(BitStream* bs, int reg); + void globalReset(BitStream* bs); + void globalPulse(BitStream* bs, unsigned width); + void switchMode(BitStream *bs, MODE m); + void L1A(BitStream *bs); + void sendECR(BitStream *bs); + void sendBCR(BitStream *bs); + void feWriteCommand(BitStream* bs); + void setAddr(unsigned addr){m_chipAddr=addr;} + void setBroadcast(bool bc){ + if(bc)m_broadcasting=0x8; + else m_broadcasting=0; + } + bool broadcasting(){return (m_broadcasting!=0);} + private: + unsigned m_chipAddr; + unsigned m_broadcasting; + }; + +}; +#endif + diff --git a/rce/rcecalib/config/FEI4/FEI4AFormatter.cc b/rce/rcecalib/config/FEI4/FEI4AFormatter.cc new file mode 100644 index 00000000..74e0f4b7 --- /dev/null +++ b/rce/rcecalib/config/FEI4/FEI4AFormatter.cc @@ -0,0 +1,100 @@ +#include "rcecalib/config/FEI4/FEI4AFormatter.hh" +#include "rcecalib/config/FEI4/FEI4ARecord.hh" +#include "rcecalib/config/FormattedRecord.hh" +#include "rcecalib/scanctrl/RceCallback.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/util/exceptions.hh" +#include "ers/ers.h" +#include <iostream> +#include <stdio.h> + +FEI4AFormatter::FEI4AFormatter(int id): + AbsFormatter(id, "FEI4A"), m_hitDiscCnfg(0){ + char name[128], title[128]; + sprintf(name, "Mod_%d_FEI4_Errors", id); + sprintf(title, "Module %d FEI4 Errors", id); + m_errhist=new RceHisto1d<int, int>(name, title, 32, -.5, 31.5); +} +FEI4AFormatter::~FEI4AFormatter(){ + delete m_errhist; + +} +void FEI4AFormatter::configure(boost::property_tree::ptree* config){ + try{ + std::cout<<"hitdiscconfig was "<<m_hitDiscCnfg<<std::endl; + m_hitDiscCnfg=config->get<int>("HitDiscCnfg"); + std::cout<<"Setting hitdiscconfig to "<<m_hitDiscCnfg<<std::endl; + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + } + m_errhist->clear(); +} + +int FEI4AFormatter::decode (const unsigned int *buffer, int buflen, unsigned* parsedData, int &parsedsize, int &nL1A){ + if(buflen==0)return FEI4::FEI4ARecord::Empty; + unsigned char* bytepointer=(unsigned char*)buffer; + unsigned char* last=bytepointer+buflen*sizeof(unsigned)-3; + FEI4::FEI4ARecord rec; + //bool header=false; + while(bytepointer<=last){ + rec.setRecord(bytepointer); + if (rec.isEmptyRecord()){ + //header=false; + }else if(rec.isData()){ + //if(header==false)return FEI4::FEI4ARecord::NoHeader; + //there are potentially 2 hits in one data record + if(rec.getTotBottom()<0xe || (m_hitDiscCnfg!=0 && rec.getTotBottom()==0xe)){ //above threshold + FormattedRecord fr(FormattedRecord::DATA); + fr.setToT(decodeToT(rec.getTotBottom())); + fr.setCol(rec.getColumn()-1); + fr.setRow(rec.getRow()-1); + parsedData[parsedsize++]=fr.getWord(); + } + if(rec.getTotTop()<0xe || (m_hitDiscCnfg!=0 && rec.getTotTop()==0xe)){ //above threshold + FormattedRecord fr(FormattedRecord::DATA); + fr.setToT(decodeToT(rec.getTotTop())); + fr.setCol(rec.getColumn()-1); + fr.setRow(rec.getRow()); + parsedData[parsedsize++]=fr.getWord(); + } + // std::cout<<std::hex<<rec.getHeader()<<std::endl; + }else if(rec.isDataHeader()){ + //header=true; + nL1A++; + FormattedRecord fr(FormattedRecord::HEADER); + //printf("Formatter word %x\n",rec.getValue()); + fr.setL1id((rec.getL1id()+1)&0x7f); //make l1id compatible with FEI3 where the first l1id is 1 not 0 + fr.setBxid(rec.getBxid()); + parsedData[parsedsize++]=fr.getWord(); + }else if(rec.isServiceRecord()){ + printf("Service record FE %d. Error code: %d. Count: %d \n", + getId(), rec.getErrorCode(), rec.getErrorCount()); + if(rec.getErrorCode()<32)m_errhist->fill(rec.getErrorCode(), rec.getErrorCount()); + //header=false; + }else if(rec.isValueRecord()){ //val rec without addr rec + //printf("Value record: %04x.\n",rec.getValue()); + if(m_rb)m_rb->push_back(rec.getValue()); + //header=false; + }else if(rec.isAddressRecord()){ // address record + std::cout<<"Address record for "; + if(rec.isGlobal())std::cout<<" global register "; + else std::cout<<" shift register "; + std::cout<<rec.getAddress()<<std::endl; + //if(m_rb)m_rb->push_back(rec.getAddress()); + //header=false; + }else{ + std::cout<<"FE "<<getId()<<": Unexpected record type: "<<std::hex<<rec.getUnsigned()<<std::dec<<std::endl; + return FEI4::FEI4ARecord::BadRecord; + } + bytepointer+=3; + } + return FEI4::FEI4ARecord::OK; +} + +//FEI4 encodes TOT information +int FEI4AFormatter::decodeToT(int raw){ + if(raw==0xe)return 1; + else return raw+m_hitDiscCnfg+1; +} diff --git a/rce/rcecalib/config/FEI4/FEI4AFormatter.hh b/rce/rcecalib/config/FEI4/FEI4AFormatter.hh new file mode 100644 index 00000000..ae3ca5d2 --- /dev/null +++ b/rce/rcecalib/config/FEI4/FEI4AFormatter.hh @@ -0,0 +1,19 @@ +#ifndef FEI4AFORMATTER_HH +#define FEI4AFORMATTER_HH + +#include "rcecalib/config/AbsFormatter.hh" +#include "rcecalib/util/RceHisto1d.cc" + +class FEI4AFormatter:public AbsFormatter{ +public: + FEI4AFormatter(int id); + virtual ~FEI4AFormatter(); + int decode(const unsigned* data, int size, unsigned* parsedData, int &parsedsize, int &nL1A); + void configure(boost::property_tree::ptree* scanOptions); + int decodeToT(int rawTot); + +private: + int m_hitDiscCnfg; + RceHisto1d<int, int>* m_errhist; +}; +#endif diff --git a/rce/rcecalib/config/FEI4/FEI4AGlobalRegister.cc b/rce/rcecalib/config/FEI4/FEI4AGlobalRegister.cc new file mode 100644 index 00000000..39765a59 --- /dev/null +++ b/rce/rcecalib/config/FEI4/FEI4AGlobalRegister.cc @@ -0,0 +1,295 @@ + +#include "rcecalib/config/FEI4/FEI4AGlobalRegister.hh" +#include "rcecalib/config/FEI4/FECommands.hh" +#include "rcecalib/config/FEI4/Utils.hh" +#include "rcecalib/HW/SerialIF.hh" +#include <iostream> +#include "ers/ers.h" +#include <stdio.h> +#include "rcecalib/profiler/Profiler.hh" + +namespace FEI4{ + + RegisterDef FEI4AGlobalRegister::m_def; + bool FEI4AGlobalRegister::m_initialized=false; + + FEI4AGlobalRegister::FEI4AGlobalRegister(FECommands* commands): + GlobalRegister(commands) { + m_rd=&m_def; + m_def.LOW_REG=2; + m_def.N_REG_REGS=36; + m_def.N_W_REGS=36; + m_def.N_R_REGS=43; + m_def.SRAB_BITS=288; + m_def.SRC_BITS=144; + // initialize static field dictionary + if(!m_initialized)initialize(); + //set up size parameters + + //create registers + m_regw=new unsigned short[m_def.N_W_REGS]; + m_regr=new unsigned short[m_def.N_R_REGS]; + m_srab=new unsigned short[m_def.SRAB_BITS/16]; + m_src=new unsigned short[m_def.SRC_BITS/16]; + //Clear all registers + for(int i=0;i<m_def.N_W_REGS;i++)m_regw[i]=0; + for(int i=0;i<m_def.N_R_REGS;i++)m_regr[i]=0; + for(int i=0;i<m_def.SRAB_BITS/16;i++)m_srab[i]=0; + for(int i=0;i<m_def.SRC_BITS/16;i++)m_src[i]=0; + } + FEI4AGlobalRegister::~FEI4AGlobalRegister(){ + delete [] m_regw; + delete [] m_regr; + delete [] m_srab; + delete [] m_src; + } + + void FEI4AGlobalRegister::initialize(){ + addField("TrigCnt", 2, 12, -1, -1, 4, false); + addField("Conf_AddrEnable", 2, 11, -1, -1, 1, false); + addField("Reg2Spare", 2, 0, -1, -1, 11, false); + addField("ErrMask0", 3, 0, -1, -1, 16, false); + addField("ErrMask1", 4, 0, -1, -1, 16, false); + addField("PrmpVbpRight", 5, 8, 152, -1, 8, true); + addField("Vthin", 5, 0, 144, -1, 8, true); + addField("DisVbn_CPPM", 6, 8, 168, -1, 8, true); + addField("PrmpVbp", 6, 0, 160, -1, 8, true); + addField("TdacVbp", 7, 8, 184, -1, 8, true); + addField("DisVbn", 7, 0, 176, -1, 8, true); + addField("Amp2Vbn", 8, 8, 200, -1, 8, true); + addField("Amp2VbpFol", 8,0,192, -1, 8, true); + addField("PrmpVbpTop", 9, 8, 216, -1, 8, true); + addField("Amp2Vbp", 9, 0, 208, -1, 8, true); + addField("FdacVbn", 10, 8, 232, -1, 8, true); + addField("Amp2Vbpf", 10, 0, 224, -1, 8, true); + addField("PrmpVbnFol", 11, 8, 248, -1, 8, true); + addField("PrmpVbpLeft", 11, 0, 240, -1, 8, true); + addField("PrmpVbpf", 12, 8, 264, -1, 8, true); + addField("PrmpVbnLcc", 12, 0, 256, -1, 8, true); + addField("Reg13Spare", 13, 0, -1, -1, 1, false); + addField("PxStrobes", 13, 1, 273, -1, 13, true); + addField("S0", 13, 14, 286, -1, 1, false); + addField("S1", 13, 15, 287, -1, 1, false); + addField("LVDSDrvIref", 14, 8, 8, -1, 8, true); + addField("BonnDac", 14, 0, 0, -1, 8, true); + addField("PllIbias", 15, 8, 24, -1, 8, true); + addField("LVDSDrvVos", 15, 0, 16, -1, 8, true); + addField("TempSensBias", 16, 8, 40, -1, 8, true); + addField("PllIcp", 16, 0, 32, -1, 8, true); + addField("Reg17Spare", 17, 8, 56, -1, 8, true); + addField("PlsrIdacRamp", 17, 0, 48, -1, 8, true); + addField("Reg18Spare", 18, 8, 72, -1, 8, true); + addField("PlsrVgOPamp", 18, 0, 64, -1, 8, true); + addField("PlsrDacBias", 19, 8, 88, -1, 8, true); + addField("Reg19Spare", 19, 0, 80, -1, 8, true); + addField("Vthin_AltCoarse", 20, 8, 104, -1, 8, true); + addField("Vthin_AltFine", 20, 0, 96, -1, 8, true); + addField("PlsrDAC", 21, 0, 112, -1, 10, true); + addField("DIGHITIN_Sel", 21, 10, 138, -1, 1, false); + addField("DINJ_Override", 21, 11, 139, -1, 1, false); + addField("HITLD_In", 21, 12, 140, -1, 1, false); + addField("Reg21Spare", 21, 13, -1, -1, 3, false); + addField("Reg22Spare2", 22, 0, -1, -1, 2, false); + addField("Colpr_Addr", 22, 2, 124, -1, 6, true); + addField("Colpr_Mode", 22, 8, 130, -1, 2, true); + addField("Reg22Spare1", 22, 10, -1, -1, 6, false); + addField("DisableColumnCnfg0", 23, 0, -1, 0, 16, false); + addField("DisableColumnCnfg1", 24, 0, -1, 16, 16, false); + addField("DisableColumnCnfg2", 25, 0, -1, 32, 8, false); + addField("TrigLat", 25, 8, -1, 40, 8, false); + addField("CMDcnt", 26, 3, -1, 51, 14, false); + addField("StopModeCnfg", 26, 2, -1, 50, 1, false); + addField("HitDiscCnfg", 26, 0, -1, 48, 2, false); + addField("EN_PLL", 27, 15, -1, 79, 1, false); + addField("Efuse_sense", 27, 14, -1, 78, 1, false); + addField("Stop_Clk", 27, 13, -1, 77, 1, false); + addField("ReadErrorReq", 27, 12, -1, 76, 1, false); + addField("ReadSkipped", 27, 11, -1, 75, 1, false); + addField("Reg27Spare", 27, 6, -1, -1, 5, false); + addField("GateHitOr", 27, 5, -1, 69, 1, false); + addField("CalEn", 27, 4, -1, 68, 1, false); + addField("SR_clr", 27, 3, -1, 67, 1, false); + addField("Latch_en", 27, 2, -1, 66, 1, false); + addField("SR_Clock", 27, 1, -1, 65, 1, false); + addField("LVDSDrvSet06", 28, 15, -1, 95, 1, false); + addField("Reg28Spare", 28, 10, -1, -1, 5, false); + addField("EN40M", 28, 9, -1, 89, 1, false); + addField("EN80M", 28, 8, -1, 88, 1, false); + addField("CLK1", 28, 5, -1, 85, 3, false); + addField("CLK0", 28, 2, -1, 82, 3, false); + addField("EN160M", 28, 1, -1, 81, 1, false); + addField("EN320M", 28, 0, -1, 80, 1, false); + addField("Reg29Spare1", 29, 14, -1, -1, 2, false); + addField("no8b10b", 29, 13, -1, 109, 1, false); + addField("Clk2OutCnfg", 29, 12, -1, 108, 1, false); + addField("EmptyRecord", 29, 4, -1, 100, 8, true); + addField("Reg29Spare2", 29, 3, -1, -1, 1, false); + addField("LVDSDrvEn", 29, 2, -1, 98, 1, false); + addField("LVDSDrvSet30", 29, 1, -1, 97, 1, false); + addField("LVDSDrvSet12", 29, 0, -1, 96, 1, false); + addField("PlsrRiseUpTau", 31, 13, -1, 141, 3, false); + addField("PlsrPwr", 31, 12, -1, 140, 1, false); + addField("PlsrDelay", 31, 6, -1, 134, 6, true); + addField("ExtDigCalSW", 31, 5, -1, 133, 1, false); + addField("ExtAnaCalSW", 31, 4, -1, 132, 1, false); + addField("Reg31Spare", 31, 0, -1, -1, 4, false); + addField("SELB0", 32, 0, -1, -1, 16, false); + addField("SELB1", 33, 0, -1, -1, 16, false); + addField("SELB2", 34, 8, -1, -1, 8, false); + addField("EfuseCref", 34, 0, -1, -1, 4, false); + addField("EfuseVref", 34, 4, -1, -1, 4, false); + addField("Chip_SN", 35, 0, -1, -1, 16, false); + + // alternative definitions + addField("CMDcnt_width", 26, 3, -1, 51, 8, false); + addField("CMDcnt_delay", 26, 11, -1, 59, 6, false); + addField("ERRORMASK", 3, 0, -1, -1, 32, false); + addField("DisableColumnCnfg01", 23, 0, -1, 0, 32, false); + addField("SELB01", 32, 0, -1, -1, 32, false); + addField("CLK0_S2", 28, 2, -1, 82, 1, false); + addField("CLK0_S1", 28, 3, -1, 83, 1, false); + addField("CLK0_S0", 28, 4, -1, 84, 1, false); + addField("CLK1_S2", 28, 5, -1, 85, 1, false); + addField("CLK1_S1", 28, 6, -1, 86, 1, false); + addField("CLK1_S0", 28, 7, -1, 87, 1, false); + + + // Translation from scan parameter to Global register field + addParameter("LATENCY", "TrigLat"); + addParameter("GDAC", "Vthin_AltFine"); + addParameter("GDAC_COARSE", "Vthin_AltCoarse"); + addParameter("VCAL", "PlsrDAC"); + addParameter("STROBE_DELAY", "PlsrDelay"); + addParameter("IF", "PrmpVbpf"); + + //Translation from CLKx_S012 parameter to transmission rate + m_def.m_rate[0]=SerialIF::M40; + m_def.m_rate[4]=SerialIF::M320; + m_def.m_rate[2]=SerialIF::M40; + m_def.m_rate[6]=SerialIF::M320; + m_def.m_rate[1]=SerialIF::M160; + m_def.m_rate[5]=SerialIF::M80; + m_def.m_rate[3]=SerialIF::M40; + m_def.m_rate[7]=SerialIF::M160; //Aux clk + + m_def.m_params8b10b=m_def.m_fields["no8b10b"]; + m_def.m_paramsDrate=m_def.m_fields["CLK0"]; + m_def.m_colpr_reg=m_def.m_fields["Colpr_Addr"].reg; + m_def.m_colpr_disable=5<<2; + + m_initialized=true; + } + void FEI4AGlobalRegister::printFields(std::ostream &os){ + os<<"Global Register Fields"<<std::endl; + os<<"======================"<<std::endl; + os<<"TrigCnt "<<getField("TrigCnt")<<std::endl; + os<<"Conf_AddrEnable "<<getField("Conf_AddrEnable")<<std::endl; + os<<"Reg2Spare "<<getField("Reg2Spare")<<std::endl; + os<<"ErrMask0 "<<getField("ErrMask0")<<std::endl; + os<<"ErrMask1 "<<getField("ErrMask1")<<std::endl; + os<<"PrmpVbpRight "<<getField("PrmpVbpRight")<<std::endl; + os<<"Vthin "<<getField("Vthin")<<std::endl; + os<<"DisVbn_CPPM "<<getField("DisVbn_CPPM")<<std::endl; + os<<"PrmpVbp "<<getField("PrmpVbp")<<std::endl; + os<<"TdacVbp "<<getField("TdacVbp")<<std::endl; + os<<"DisVbn "<<getField("DisVbn")<<std::endl; + os<<"Amp2Vbn "<<getField("Amp2Vbn")<<std::endl; + os<<"Amp2VbpFol "<<getField("Amp2VbpFol")<<std::endl; + os<<"PrmpVbpTop "<<getField("PrmpVbpTop")<<std::endl; + os<<"Amp2Vbp "<<getField("Amp2Vbp")<<std::endl; + os<<"FdacVbn "<<getField("FdacVbn")<<std::endl; + os<<"Amp2Vbpf "<<getField("Amp2Vbpf")<<std::endl; + os<<"PrmpVbnFol "<<getField("PrmpVbnFol")<<std::endl; + os<<"PrmpVbpLeft "<<getField("PrmpVbpLeft")<<std::endl; + os<<"PrmpVbpf "<<getField("PrmpVbpf")<<std::endl; + os<<"PrmpVbnLcc "<<getField("PrmpVbnLcc")<<std::endl; + os<<"Reg13Spare "<<getField("Reg13Spare")<<std::endl; + os<<"PxStrobes "<<getField("PxStrobes")<<std::endl; + os<<"S0 "<<getField("S0")<<std::endl; + os<<"S1 "<<getField("S1")<<std::endl; + os<<"LVDSDrvIref "<<getField("LVDSDrvIref")<<std::endl; + os<<"BonnDac "<<getField("BonnDac")<<std::endl; + os<<"PllIbias "<<getField("PllIbias")<<std::endl; + os<<"LVDSDrvVos "<<getField("LVDSDrvVos")<<std::endl; + os<<"TempSensBias "<<getField("TempSensBias")<<std::endl; + os<<"PllIcp "<<getField("PllIcp")<<std::endl; + os<<"Reg17Spare "<<getField("Reg17Spare")<<std::endl; + os<<"PlsrIdacRamp "<<getField("PlsrIdacRamp")<<std::endl; + os<<"Reg18Spare "<<getField("Reg18Spare")<<std::endl; + os<<"PlsrVgOPamp "<<getField("PlsrVgOPamp")<<std::endl; + os<<"PlsrDacBias "<<getField("PlsrDacBias")<<std::endl; + os<<"Reg19Spare "<<getField("Reg19Spare")<<std::endl; + os<<"Vthin_AltCoarse "<<getField("Vthin_AltCoarse")<<std::endl; + os<<"Vthin_AltFine "<<getField("Vthin_AltFine")<<std::endl; + os<<"PlsrDAC "<<getField("PlsrDAC")<<std::endl; + os<<"DIGHITIN_Sel "<<getField("DIGHITIN_Sel")<<std::endl; + os<<"DINJ_Override "<<getField("DINJ_Override")<<std::endl; + os<<"HITLD_In "<<getField("HITLD_In")<<std::endl; + os<<"Reg21Spare "<<getField("Reg21Spare")<<std::endl; + os<<"Reg22Spare2 "<<getField("Reg22Spare2")<<std::endl; + os<<"Colpr_Addr "<<getField("Colpr_Addr")<<std::endl; + os<<"Colpr_Mode "<<getField("Colpr_Mode")<<std::endl; + os<<"Reg22Spare1 "<<getField("Reg22Spare1")<<std::endl; + os<<"DisableColumnCnfg0 "<<getField("DisableColumnCnfg0")<<std::endl; + os<<"DisableColumnCnfg1 "<<getField("DisableColumnCnfg1")<<std::endl; + os<<"DisableColumnCnfg2 "<<getField("DisableColumnCnfg2")<<std::endl; + os<<"TrigLat "<<getField("TrigLat")<<std::endl; + os<<"StopModeCnfg "<<getField("StopModeCnfg")<<std::endl; + os<<"HitDiscCnfg "<<getField("HitDiscCnfg")<<std::endl; + os<<"CMDcnt12 "<<getField("CMDcnt12")<<std::endl; + os<<"EN_PLL "<<getField("EN_PLL")<<std::endl; + os<<"Efuse_sense "<<getField("Efuse_sense")<<std::endl; + os<<"Stop_Clk "<<getField("Stop_Clk")<<std::endl; + os<<"ReadErrorReq "<<getField("ReadErrorReq")<<std::endl; + os<<"ReadSkipped "<<getField("ReadSkipped")<<std::endl; + os<<"Reg27Spare "<<getField("Reg27Spare")<<std::endl; + os<<"GateHitOr "<<getField("GateHitOr")<<std::endl; + os<<"CalEn "<<getField("CalEn")<<std::endl; + os<<"SR_clr "<<getField("SR_clr")<<std::endl; + os<<"Latch_en "<<getField("Latch_en")<<std::endl; + os<<"SR_Clock "<<getField("SR_Clock")<<std::endl; + os<<"LVDSDrvSet06 "<<getField("LVDSDrvSet06")<<std::endl; + os<<"Reg28Spare "<<getField("Reg28Spare")<<std::endl; + os<<"EN40M "<<getField("EN40M")<<std::endl; + os<<"EN80M "<<getField("EN80M")<<std::endl; + os<<"CLK1 "<<getField("CLK1")<<std::endl; + os<<"CLK0 "<<getField("CLK0")<<std::endl; + os<<"EN160M "<<getField("EN160M")<<std::endl; + os<<"EN320M "<<getField("EN320M")<<std::endl; + os<<"Reg29Spare1 "<<getField("Reg29Spare1")<<std::endl; + os<<"no8b10b "<<getField("no8b10b")<<std::endl; + os<<"Clk2OutCnfg "<<getField("Clk2OutCnfg")<<std::endl; + os<<"EmptyRecord "<<getField("EmptyRecord")<<std::endl; + os<<"Reg29Spare2 "<<getField("Reg29Spare2")<<std::endl; + os<<"LVDSDrvEn "<<getField("LVDSDrvEn")<<std::endl; + os<<"LVDSDrvSet30 "<<getField("LVDSDrvSet30")<<std::endl; + os<<"LVDSDrvSet12 "<<getField("LVDSDrvSet12")<<std::endl; + os<<"PlsrRiseUpTau "<<getField("PlsrRiseUpTau")<<std::endl; + os<<"PlsrPwr "<<getField("PlsrPwr")<<std::endl; + os<<"PlsrDelay "<<getField("PlsrDelay")<<std::endl; + os<<"ExtDigCalSW "<<getField("ExtDigCalSW")<<std::endl; + os<<"ExtAnaCalSW "<<getField("ExtAnaCalSW")<<std::endl; + os<<"Reg31Spare "<<getField("Reg31Spare")<<std::endl; + os<<"SELB0 "<<getField("SELB0")<<std::endl; + os<<"SELB1 "<<getField("SELB1")<<std::endl; + os<<"SELB2 "<<getField("SELB2")<<std::endl; + os<<"Efuse_Cref "<<getField("Efuse_Cref")<<std::endl; + os<<"Efuse_Vref "<<getField("Efuse_Vref")<<std::endl; + os<<"Chip_SN "<<getField("Chip_SN")<<std::endl; + + os<<"Alternative Field definitions:"<<std::endl; + // alternative definitions + os<<"CMDcnt_width "<<getField("CMDcnt_width")<<std::endl; + os<<"CMDcnt_delay "<<getField("CMDcnt_delay")<<std::endl; + os<<"ERRORMASK "<<getField("ERRORMASK")<<std::endl; + os<<"DisableColumnCnfg01 "<<getField("DisableColumnCnfg01")<<std::endl; + os<<"SELB01 "<<getField("SELB01")<<std::endl; + os<<"CLK0_S2 "<<getField("CLK0_S2")<<std::endl; + os<<"CLK0_S1 "<<getField("CLK0_S1")<<std::endl; + os<<"CLK0_S0 "<<getField("CLK0_S0")<<std::endl; + os<<"CLK1_S2 "<<getField("CLK1_S2")<<std::endl; + os<<"CLK1_S1 "<<getField("CLK1_S1")<<std::endl; + os<<"CLK1_S0 "<<getField("CLK1_S0")<<std::endl; + } + +}; diff --git a/rce/rcecalib/config/FEI4/FEI4AGlobalRegister.hh b/rce/rcecalib/config/FEI4/FEI4AGlobalRegister.hh new file mode 100644 index 00000000..115142d3 --- /dev/null +++ b/rce/rcecalib/config/FEI4/FEI4AGlobalRegister.hh @@ -0,0 +1,31 @@ +#ifndef FEI4AGLOBALREGISTER_FEI4_HH +#define FEI4AGLOBALREGISTER_FEI4_HH + +#include <map> +#include <string> +#include <vector> +#include "rcecalib/HW/SerialIF.hh" +#include "rcecalib/config/FEI4/GlobalRegister.hh" + + +namespace FEI4{ + +class FECommands; + + class FEI4AGlobalRegister: public GlobalRegister{ + public: + FEI4AGlobalRegister(FECommands* commands); + virtual ~FEI4AGlobalRegister(); + void printFields(std::ostream &os); + private: + void initialize(); + static RegisterDef m_def; + static bool m_initialized; + RegisterDef* getDef(){return &m_def;} + + + }; + +}; + +#endif diff --git a/rce/rcecalib/config/FEI4/FEI4AModule.cc b/rce/rcecalib/config/FEI4/FEI4AModule.cc new file mode 100644 index 00000000..6b74f7ed --- /dev/null +++ b/rce/rcecalib/config/FEI4/FEI4AModule.cc @@ -0,0 +1,107 @@ +#include "rcecalib/config/FEI4/FEI4AModule.hh" +#include "rcecalib/config/FEI4/FEI4AGlobalRegister.hh" +#include "rcecalib/HW/BitStream.hh" +#include "rcecalib/config/FEI4/FECommands.hh" +#include "rcecalib/config/MaskStageFactory.hh" +#include "rcecalib/HW/SerialIF.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/util/VerifyErrors.hh" +#include <iostream> +#include <fstream> +#include "ers/ers.h" +#include <stdio.h> + +namespace FEI4{ + + + FEI4AModule::FEI4AModule(const char* name, unsigned id, unsigned inlink, unsigned outlink, AbsFormatter* fmt): + Module(name, id, inlink, outlink, fmt){ + // std::cout<<"Module"<<std::endl; + m_commands=new FECommands; + m_global=new FEI4AGlobalRegister(m_commands); + m_pixel=new PixelRegister(m_commands); + m_pixel_readback=new PixelRegister(m_commands); + } + FEI4AModule::~FEI4AModule(){ + delete m_global; + delete m_pixel; + delete m_pixel_readback; + delete m_commands; + //m_timer.Print("Module"); + } + void FEI4AModule::setupGlobalPulseHW(int pulsereg){ + m_global->setField("Efuse_sense",(pulsereg&GlobalRegister::Efuse_sense)!=0, GlobalRegister::SW); + m_global->setField("Stop_Clk",(pulsereg&GlobalRegister::Stop_Clk)!=0, GlobalRegister::SW); + m_global->setField("ReadErrorReq",(pulsereg&GlobalRegister::ReadErrorReq)!=0, GlobalRegister::SW); + m_global->setField("ReadSkipped",(pulsereg&GlobalRegister::ReadSkipped)!=0, GlobalRegister::SW); + m_global->setField("CalEn",(pulsereg&GlobalRegister::CalEn)!=0, GlobalRegister::SW); + m_global->setField("SR_clr",(pulsereg&GlobalRegister::SR_clr)!=0, GlobalRegister::SW); + m_global->setField("Latch_en",(pulsereg&GlobalRegister::Latch_en)!=0, GlobalRegister::SW); + m_global->setField("SR_Clock",(pulsereg&GlobalRegister::SR_Clock)!=0, GlobalRegister::HW); //do one HW write for all fields + } + + // void Frontend::pixelUsrToRaw(BitStream *bs, unsigned bit){ + // } + + void FEI4AModule::resetHW(){ + BitStream *bs=new BitStream; + BitStreamUtils::prependZeros(bs); + m_commands->globalReset(bs); + SerialIF::send(bs); + delete bs; + } + + + int FEI4AModule::verifyModuleConfigHW(){ + int retval=0; + SerialIF::setChannelInMask(1<<m_inLink); + SerialIF::setChannelOutMask(1<<m_outLink); + std::vector <unsigned> readback; + if(m_formatter){ + // global register + m_formatter->setReadbackPointer(&readback); + std::cout<<"***FE "<<m_id<<"***"<<std::endl; + retval=m_global->verifyConfigHW(readback); + /* + // pixel registers + m_global->setField("Colpr_Mode", 0, GlobalRegister::SW); // only write to 1 column pair + BitStream *bs=new BitStream; + bs->push_back(0); + m_commands->globalPulse(bs, FECommands::PULSE_WIDTH); + int ngoodcol=13; + const int goodcol[]={0,1,2,30,31,32,33,34,35,36,37,38,39}; + for (int dcoli=0;dcoli<ngoodcol;dcoli++){ + int dcol=goodcol[dcoli]; + for (int bit=PixelRegister::N_PIXEL_REGISTER_BITS-1;bit>=0;bit--){ + m_global->setField("Colpr_Addr", dcol, GlobalRegister::HW); + if(bit!=PixelRegister::N_PIXEL_REGISTER_BITS-1){//shift register is last latch bit + setupS0S1HitldHW(1, 1, 0); + setupGlobalPulseHW(GlobalRegister::SR_Clock); //SR clock + //set up strobe bit + setupPixelStrobesHW(1<<bit); + SerialIF::send(bs, SerialIF::DONT_CLEAR); //global pulse + } + setupS0S1HitldHW(0, 0, 0); + retval|=m_pixel->verifyDoubleColumnHW(bit, dcol, readback); //check double column + } + } + setupGlobalPulseHW(0); //clear + setupPixelStrobesHW(0); //clear + delete bs; + */ + m_formatter->setReadbackPointer(0); + }else{ + retval=ModuleVerify::NO_FORMATTER; + } + return retval; + } + + + void FEI4AModule::destroy(){ + delete this; + } + + +}; + diff --git a/rce/rcecalib/config/FEI4/FEI4AModule.hh b/rce/rcecalib/config/FEI4/FEI4AModule.hh new file mode 100644 index 00000000..e2025bc0 --- /dev/null +++ b/rce/rcecalib/config/FEI4/FEI4AModule.hh @@ -0,0 +1,25 @@ +#ifndef FEI4__FEI4AMODULE_HH +#define FEI4__FEI4AMODULE_HH + +#include "rcecalib/config/FEI4/Module.hh" +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/profiler/Profiler.hh" +#include <string> + +class AbsFormatter; + +namespace FEI4{ + + class FEI4AModule: public Module{ + public: + FEI4AModule(const char* name, unsigned id, unsigned inLink, unsigned outLink, AbsFormatter *fmt); + virtual ~FEI4AModule(); + void resetHW(); + int verifyModuleConfigHW(); + virtual void destroy(); + void setupGlobalPulseHW(int pulsereg); + +}; + +}; +#endif diff --git a/rce/rcecalib/config/FEI4/FEI4ARecord.hh b/rce/rcecalib/config/FEI4/FEI4ARecord.hh new file mode 100644 index 00000000..67eabacf --- /dev/null +++ b/rce/rcecalib/config/FEI4/FEI4ARecord.hh @@ -0,0 +1,246 @@ +#ifndef FEI4RECORD_HH +#define FEI4RECORD_HH + +#include "rcecalib/config/Endianness.hh" +namespace FEI4{ + + +namespace Size +{ + enum Size + { + UNUSED = 8, + HEADER = 8, + RTYPE = 1, + ADDR = 15, + VALUE = 16, + ERRCODE = 6, + ERRCOUNT = 10, + REMAINDER = 16, + FLAG = 1, + LV1ID = 7, + BXID = 8, + COL = 7, + ROW = 9, + TOT = 4 + }; +} +namespace Key +{ + enum Key + { + ADDR = 0xea, + VALUE = 0xec, + SERVICE = 0xef, + HEADER = 0xe9, + EMPTY = 0x0, + GLOBAL = 0, + SHIFT = 1 + }; +} +/* ---------------------------------------------------------------------- */ + + struct Generic + { +#if ENDIANNESS_IS_BIG + + unsigned int unused: Size::UNUSED; + unsigned int header: Size::HEADER; + unsigned int remainder: Size::REMAINDER; + +#elif ENDIANNESS_IS_LITTLE + + unsigned int remainder: Size:: REMAINDER; + unsigned int header: Size::HEADER; + unsigned int unused: Size::UNUSED; + +#else + +#error ENDIANNESS is not defined +#endif + }; + struct Address + { +#if ENDIANNESS_IS_BIG + + unsigned int unused: Size::UNUSED; + unsigned int header: Size::HEADER; + unsigned int rtype: Size:: RTYPE; + unsigned int address: Size::ADDR; + +#elif ENDIANNESS_IS_LITTLE + + unsigned int address: Size::ADDR; + unsigned int rtype: Size:: RTYPE; + unsigned int header: Size::HEADER; + unsigned int unused: Size::UNUSED; + +#else + +#error ENDIANNESS is not defined +#endif + }; + + struct Value + { +#if ENDIANNESS_IS_BIG + + unsigned int unused: Size::UNUSED; + unsigned int header: Size::HEADER; + unsigned int value: Size::VALUE; + +#elif ENDIANNESS_IS_LITTLE + + unsigned int value: Size::VALUE; + unsigned int header: Size::HEADER; + unsigned int unused: Size::UNUSED; + +#else +#error ENDIANNESS is not defined +#endif + }; + + struct Service + { +#if ENDIANNESS_IS_BIG + + unsigned int unused: Size::UNUSED; + unsigned int header: Size::HEADER; + unsigned int errcode: Size::ERRCODE; + unsigned int errcount: Size::ERRCOUNT; + +#elif ENDIANNESS_IS_LITTLE + + unsigned int errcount: Size::ERRCOUNT; + unsigned int errcode: Size::ERRCODE; + unsigned int header: Size::HEADER; + unsigned int unused: Size::UNUSED; + +#else + +#error ENDIANNESS is not defined +#endif + }; + + struct DataHeader + { +#if ENDIANNESS_IS_BIG + + unsigned int unused: Size::UNUSED; + unsigned int header: Size::HEADER; + unsigned int flag: Size::FLAG; + unsigned int lv1id: Size::LV1ID; + unsigned int bxid: Size::BXID; + +#elif ENDIANNESS_IS_LITTLE + + unsigned int bxid: Size::BXID; + unsigned int lv1id: Size::LV1ID; + unsigned int flag: Size::FLAG; + unsigned int header: Size::HEADER; + unsigned int unused: Size::UNUSED; + +#else + +#error ENDIANNESS is not defined +#endif + }; + + struct Data + { +#if ENDIANNESS_IS_BIG + + unsigned int unused: Size::UNUSED; + unsigned int col: Size::COL; + unsigned int row: Size::ROW; + unsigned int totbottom: Size::TOT; + unsigned int tottop: Size::TOT; + +#elif ENDIANNESS_IS_LITTLE + + unsigned int tottop: Size::TOT; + unsigned int totbottom: Size::TOT; + unsigned int row: Size::ROW; + unsigned int col: Size::COL; + unsigned int unused: Size::UNUSED; + +#else + +#error ENDIANNESS is not defined +#endif + }; + + + union Record + { + unsigned int ui; + Generic ge; + Address ad; + Value va; + Service se; + DataHeader he; + Data da; + }; + + + class FEI4ARecord{ + public: + enum Status + { + OK = 0, /*!< Clean finish */ + Empty = 1, /*!< Buffer does not contain any record */ + NotGlobal = 2, /*!< Address record is not a global register record */ + WrongAddress = 3, /*!< Address record does not contain the expected address */ + BadAddrValSeq = 4, /*!< Address record not immediately followed by value record */ + NoValue = 5, /*!< Value record missing. */ + NotShift = 6, /*!< Address record is not a shift register record */ + OddNwords = 7, /*!< Odd number of 16 bit words in shift register readback */ + NoHeader = 8, /*!< Data word without a previous header word*/ + BadRecord = 9 /*!< Unknown record type */ + }; + + bool isAddressRecord(){return m_record.ge.header==Key::ADDR;} + bool isValueRecord(){return m_record.ge.header==Key::VALUE;} + bool isServiceRecord(){return m_record.ge.header==Key::SERVICE;} + bool isEmptyRecord(){return m_record.ge.header==Key::EMPTY;} + bool isDataHeader(){return m_record.ge.header==Key::HEADER;} + bool isData(){return (m_record.ge.header&0xc0)!=0xc0;} + unsigned getHeader(){return m_record.ge.header;} + unsigned getAddress(){return m_record.ad.address;} + unsigned getRegisterType(){return m_record.ad.rtype;} + unsigned isGlobal(){return m_record.ad.rtype==Key::GLOBAL;} + unsigned isShift(){return m_record.ad.rtype==Key::SHIFT;} + unsigned getValue(){return m_record.va.value;} + unsigned getUnsigned(){return m_record.ui;} + unsigned getColumn(){return m_record.da.col;} + unsigned getL1id(){return m_record.he.lv1id;} + unsigned getBxid(){return m_record.he.bxid;} + unsigned getRow(){return m_record.da.row;} + unsigned getTotTop(){return m_record.da.tottop;} + unsigned getTotBottom(){return m_record.da.totbottom;} + unsigned getErrorCode(){return m_record.se.errcode;} + unsigned getErrorCount(){return m_record.se.errcount;} +#if ENDIANNESS_IS_BIG + void setRecord(const unsigned char* bytepointer){ + unsigned char* rec=(unsigned char*)&m_record; + rec[1]=*bytepointer; + rec[2]=*(bytepointer+1); + rec[3]=*(bytepointer+2); + } +#elif ENDIANNESS_IS_LITTLE + void setRecord(const unsigned char* bytepointer){ + unsigned char* rec=(unsigned char*)&m_record; + rec[2]=*bytepointer; + rec[1]=*(bytepointer+1); + rec[0]=*(bytepointer+2); + } +#else +#error ENDIANNESS is not defined +#endif + + private: + Record m_record; + }; + +} +#endif diff --git a/rce/rcecalib/config/FEI4/FEI4BFormatter.cc b/rce/rcecalib/config/FEI4/FEI4BFormatter.cc new file mode 100644 index 00000000..3b759c62 --- /dev/null +++ b/rce/rcecalib/config/FEI4/FEI4BFormatter.cc @@ -0,0 +1,117 @@ +#include "rcecalib/config/FEI4/FEI4BFormatter.hh" +#include "rcecalib/config/FEI4/FEI4BRecord.hh" +#include "rcecalib/config/FormattedRecord.hh" +#include "rcecalib/scanctrl/RceCallback.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/util/exceptions.hh" +#include "ers/ers.h" +#include <iostream> +#include <stdio.h> + +FEI4BFormatter::FEI4BFormatter(int id): + AbsFormatter(id, "FEI4B"), m_hitDiscCnfg(0), m_sr_bcid(0), m_sr_l1id(0){ + char name[128], title[128]; + sprintf(name, "Mod_%d_FEI4_Errors", id); + sprintf(title, "Module %d FEI4 Errors", id); + m_errhist=new RceHisto1d<int, int>(name, title, 32, -.5, 31.5); +} +FEI4BFormatter::~FEI4BFormatter(){ + delete m_errhist; + +} +void FEI4BFormatter::configure(boost::property_tree::ptree* config){ + m_sr_bcid=0; + m_sr_l1id=0; + try{ + std::cout<<"hitdiscconfig was "<<m_hitDiscCnfg<<std::endl; + m_hitDiscCnfg=config->get<int>("HitDiscCnfg"); + std::cout<<"Setting hitdiscconfig to "<<m_hitDiscCnfg<<std::endl; + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + } + m_errhist->clear(); +} + +int FEI4BFormatter::decode (const unsigned int *buffer, int buflen, unsigned* parsedData, int &parsedsize, int &nL1A){ + if(buflen==0)return FEI4::FEI4BRecord::Empty; + unsigned char* bytepointer=(unsigned char*)buffer; + unsigned char* last=bytepointer+buflen*sizeof(unsigned)-3; + FEI4::FEI4BRecord rec; + bool header=false; + while(bytepointer<=last){ + rec.setRecord(bytepointer); + if (rec.isEmptyRecord()){ + //header=false; + }else if(rec.isData()){ + //if(header==false)return FEI4::FEI4BRecord::NoHeader; + //there are potentially 2 hits in one data record + if(rec.getTotBottom()<0xe || (m_hitDiscCnfg!=0 && rec.getTotBottom()==0xe)){ //above threshold + FormattedRecord fr(FormattedRecord::DATA); + fr.setToT(decodeToT(rec.getTotBottom())); + fr.setCol(rec.getColumn()-1); + fr.setRow(rec.getRow()-1); + parsedData[parsedsize++]=fr.getWord(); + } + if(rec.getTotTop()<0xe || (m_hitDiscCnfg!=0 && rec.getTotTop()==0xe)){ //above threshold + FormattedRecord fr(FormattedRecord::DATA); + fr.setToT(decodeToT(rec.getTotTop())); + fr.setCol(rec.getColumn()-1); + fr.setRow(rec.getRow()); + parsedData[parsedsize++]=fr.getWord(); + } + // std::cout<<std::hex<<rec.getHeader()<<std::endl; + }else if(rec.isDataHeader()){ + header=true; + nL1A++; + FormattedRecord fr(FormattedRecord::HEADER); + //printf("Formatter word %x\n",rec.getValue()); + fr.setL1id(((rec.getL1id()|(m_sr_l1id<<5))+1)&0xfff); //make l1id compatible with FEI3 where the first l1id is 1 not 0 + fr.setBxid(rec.getBxid()|(m_sr_bcid<<10)); + m_bxidraw=rec.getBxid(); + m_l1idraw=rec.getL1id(); + //std::cout<<"Raw: "<<rec.getL1id()<<" "<<rec.getBxid()<<std::endl; + //std::cout<<"For: "<<fr.getL1id()<<" "<<fr.getBxid()<<std::endl; + parsedData[parsedsize++]=fr.getWord(); + }else if(rec.isServiceRecord()){ + if(rec.getErrorCode()==14){//BCID & L1ID + m_sr_l1id=rec.getErrorCount()>>3; + m_sr_bcid=rec.getErrorCount()&0x7; + //Update current header + if(header==false)std::cout<<"Service record without header"<<std::endl; + else{ + FormattedRecord fr(parsedData[parsedsize-1]); + fr.setL1id(((m_l1idraw|(m_sr_l1id<<5))+1)&0xfff); //make l1id compatible with FEI3 where the first l1id is 1 not 0 + fr.setBxid(m_bxidraw|(m_sr_bcid<<10)); + //std::cout<<"Updated For: "<<fr.getL1id()<<" "<<fr.getBxid()<<std::endl; + } + } + if(rec.getErrorCode()!=14)printf("Service record FE %d. Error code: %d. Count: %d \n", + getId(), rec.getErrorCode(), rec.getErrorCount()); + if(rec.getErrorCode()<32)m_errhist->fill(rec.getErrorCode(), rec.getErrorCount()); + }else if(rec.isValueRecord()){ //val rec without addr rec + //printf("Value record: %04x.\n",rec.getValue()); + if(m_rb)m_rb->push_back(rec.getValue()); + //header=false; + }else if(rec.isAddressRecord()){ // address record + //std::cout<<"Address record for "; + //if(rec.isGlobal())std::cout<<" global register "; + //else std::cout<<" shift register "; + //std::cout<<rec.getAddress()<<std::endl; + //if(m_rb)m_rb->push_back(rec.getAddress()); + //header=false; + }else{ + std::cout<<"FE "<<getId()<<": Unexpected record type: "<<std::hex<<rec.getUnsigned()<<std::dec<<std::endl; + return FEI4::FEI4BRecord::BadRecord; + } + bytepointer+=3; + } + return FEI4::FEI4BRecord::OK; +} + +//FEI4 encodes TOT information +int FEI4BFormatter::decodeToT(int raw){ + if(raw==0xe)return 1; + else return raw+m_hitDiscCnfg+1; +} diff --git a/rce/rcecalib/config/FEI4/FEI4BFormatter.hh b/rce/rcecalib/config/FEI4/FEI4BFormatter.hh new file mode 100644 index 00000000..afe75ccc --- /dev/null +++ b/rce/rcecalib/config/FEI4/FEI4BFormatter.hh @@ -0,0 +1,23 @@ +#ifndef FEI4BFORMATTER_HH +#define FEI4BFORMATTER_HH + +#include "rcecalib/config/AbsFormatter.hh" +#include "rcecalib/util/RceHisto1d.cc" + +class FEI4BFormatter:public AbsFormatter{ +public: + FEI4BFormatter(int id); + virtual ~FEI4BFormatter(); + int decode(const unsigned* data, int size, unsigned* parsedData, int &parsedsize, int &nL1A); + void configure(boost::property_tree::ptree* scanOptions); + int decodeToT(int rawTot); + +private: + int m_hitDiscCnfg; + RceHisto1d<int, int>* m_errhist; + unsigned m_sr_bcid; + unsigned m_sr_l1id; + unsigned m_bxidraw; + unsigned m_l1idraw; +}; +#endif diff --git a/rce/rcecalib/config/FEI4/FEI4BGlobalRegister.cc b/rce/rcecalib/config/FEI4/FEI4BGlobalRegister.cc new file mode 100644 index 00000000..904d8b30 --- /dev/null +++ b/rce/rcecalib/config/FEI4/FEI4BGlobalRegister.cc @@ -0,0 +1,300 @@ + +#include "rcecalib/config/FEI4/FEI4BGlobalRegister.hh" +#include "rcecalib/config/FEI4/FECommands.hh" +#include "rcecalib/config/FEI4/Utils.hh" +#include "rcecalib/HW/SerialIF.hh" +#include <iostream> +#include "ers/ers.h" +#include <stdio.h> +#include "rcecalib/profiler/Profiler.hh" + +namespace FEI4{ + + RegisterDef FEI4BGlobalRegister::m_def; + bool FEI4BGlobalRegister::m_initialized=false; + + FEI4BGlobalRegister::FEI4BGlobalRegister(FECommands* commands): + GlobalRegister(commands) { + m_rd=&m_def; + m_def.LOW_REG=1; + m_def.N_REG_REGS=36; + m_def.N_W_REGS=36; + m_def.N_R_REGS=43; + m_def.SRAB_BITS=288; + m_def.SRC_BITS=144; + // initialize static field dictionary + if(!m_initialized)initialize(); + //set up size parameters + + //create registers + m_regw=new unsigned short[m_def.N_W_REGS]; + m_regr=new unsigned short[m_def.N_R_REGS]; + m_srab=new unsigned short[m_def.SRAB_BITS/16]; + m_src=new unsigned short[m_def.SRC_BITS/16]; + //Clear all registers + for(int i=0;i<m_def.N_W_REGS;i++)m_regw[i]=0; + for(int i=0;i<m_def.N_R_REGS;i++)m_regr[i]=0; + for(int i=0;i<m_def.SRAB_BITS/16;i++)m_srab[i]=0; + for(int i=0;i<m_def.SRC_BITS/16;i++)m_src[i]=0; + } + FEI4BGlobalRegister::~FEI4BGlobalRegister(){ + delete [] m_regw; + delete [] m_regr; + delete [] m_srab; + delete [] m_src; + } + + void FEI4BGlobalRegister::initialize(){ + addField("TrigCnt", 2, 12, -1, -1, 4, false); + addField("Conf_AddrEnable", 2, 11, -1, -1, 1, false); + addField("Reg2Spare", 2, 0, -1, -1, 11, false); + addField("ErrMask0", 3, 0, -1, -1, 16, false); + addField("ErrMask1", 4, 0, -1, -1, 16, false); + addField("PrmpVbpRight", 5, 8, 152, -1, 8, true); + addField("BufVgOpAmp", 5, 0, 144, -1, 8, true); + addField("Reg6Spare", 6, 8, -1, -1, 8, true); + addField("PrmpVbp", 6, 0, 160, -1, 8, true); + addField("TdacVbp", 7, 8, 184, -1, 8, true); + addField("DisVbn", 7, 0, 176, -1, 8, true); + addField("Amp2Vbn", 8, 8, 200, -1, 8, true); + addField("Amp2VbpFol", 8,0,192, -1, 8, true); + addField("Reg9Spare", 9, 8, -1, -1, 8, true); + addField("Amp2Vbp", 9, 0, 208, -1, 8, true); + addField("FdacVbn", 10, 8, 232, -1, 8, true); + addField("Amp2Vbpf", 10, 0, 224, -1, 8, true); + addField("PrmpVbnFol", 11, 8, 248, -1, 8, true); + addField("PrmpVbpLeft", 11, 0, 240, -1, 8, true); + addField("PrmpVbpf", 12, 8, 264, -1, 8, true); + addField("PrmpVbnLcc", 12, 0, 256, -1, 8, true); + addField("Reg13Spare", 13, 0, -1, -1, 1, false); + addField("PxStrobes", 13, 1, 274, -1, 13, true); + addField("S0", 13, 14, 273, -1, 1, false); + addField("S1", 13, 15, 272, -1, 1, false); + addField("LVDSDrvIref", 14, 8, 8, -1, 8, true); + addField("GADCOpAmp", 14, 0, 0, -1, 8, true); + addField("PllIbias", 15, 8, 24, -1, 8, true); + addField("LVDSDrvVos", 15, 0, 16, -1, 8, true); + addField("TempSensBias", 16, 8, 40, -1, 8, true); + addField("PllIcp", 16, 0, 32, -1, 8, true); + addField("Reg17Spare", 17, 8, -1, -1, 8, true); + addField("PlsrIdacRamp", 17, 0, 48, -1, 8, true); + addField("VrefDigTune", 18, 8, 72, -1, 8, true); + addField("PlsrVgOPamp", 18, 0, 64, -1, 8, true); + addField("PlsrDacBias", 19, 8, 88, -1, 8, true); + addField("VrefAnTune", 19, 0, 80, -1, 8, true); + addField("Vthin_AltCoarse", 20, 8, 104, -1, 8, true); + addField("Vthin_AltFine", 20, 0, 96, -1, 8, true); + addField("PlsrDAC", 21, 0, 112, -1, 10, true); + addField("DIGHITIN_Sel", 21, 10, 143, -1, 1, false); + addField("DINJ_Override", 21, 11, 142, -1, 1, false); + addField("HITLD_In", 21, 12, 141, -1, 1, false); + addField("Reg21Spare", 21, 13, -1, -1, 3, false); + addField("Reg22Spare2", 22, 0, -1, -1, 2, false); + addField("Colpr_Addr", 22, 2, 130, -1, 6, true); + addField("Colpr_Mode", 22, 8, 128, -1, 2, true); + addField("Reg22Spare1", 22, 10, -1, -1, 6, false); + addField("DisableColumnCnfg0", 23, 0, -1, 0, 16, false); + addField("DisableColumnCnfg1", 24, 0, -1, 16, 16, false); + addField("DisableColumnCnfg2", 25, 0, -1, 32, 8, false); + addField("TrigLat", 25, 8, -1, 40, 8, false); + addField("CMDcnt", 26, 3, -1, 51, 14, false); + addField("StopModeCnfg", 26, 2, -1, 50, 1, false); + addField("HitDiscCnfg", 26, 0, -1, 48, 2, false); + addField("EN_PLL", 27, 15, -1, 79, 1, false); + addField("Efuse_sense", 27, 14, -1, 78, 1, false); + addField("Stop_Clk", 27, 13, -1, 77, 1, false); + addField("ReadErrorReq", 27, 12, -1, 76, 1, false); + addField("Reg27Spare1", 27, 11, -1, -1, 1, false); + addField("GADC_Enable", 27, 10, -1, 74, 1, false); + addField("ShiftReadBack", 27, 9, -1, 73, 1, false); + addField("Reg27Spare2", 27, 6, -1, -1, 3, false); + addField("GateHitOr", 27, 5, -1, 69, 1, false); + addField("CalEn", 27, 4, -1, 68, 1, false); + addField("SR_clr", 27, 3, -1, 67, 1, false); + addField("Latch_en", 27, 2, -1, 66, 1, false); + addField("SR_Clock", 27, 1, -1, 65, 1, false); + addField("LVDSDrvSet06", 28, 15, -1, 95, 1, false); + addField("Reg28Spare", 28, 10, -1, -1, 5, false); + addField("EN40M", 28, 9, -1, 89, 1, false); + addField("EN80M", 28, 8, -1, 88, 1, false); + addField("CLK1", 28, 5, -1, 85, 3, false); + addField("CLK0", 28, 2, -1, 82, 3, false); + addField("EN160M", 28, 1, -1, 81, 1, false); + addField("EN320M", 28, 0, -1, 80, 1, false); + addField("Reg29Spare1", 29, 14, -1, -1, 2, false); + addField("no8b10b", 29, 13, -1, 109, 1, false); + addField("Clk2OutCnfg", 29, 12, -1, 108, 1, false); + addField("EmptyRecord", 29, 4, -1, 100, 8, true); + addField("Reg29Spare2", 29, 3, -1, -1, 1, false); + addField("LVDSDrvEn", 29, 2, -1, 98, 1, false); + addField("LVDSDrvSet30", 29, 1, -1, 97, 1, false); + addField("LVDSDrvSet12", 29, 0, -1, 96, 1, false); + addField("TempSensDiodeSel", 30, 14, -1, 126, 2, true); + addField("TempSensDisable", 30, 13, -1, 125, 1, false); + addField("IleakRange", 30, 12, -1, 124, 1, false); + addField("Reg30Spare", 30, 0, -1, -1, 12, false); + addField("PlsrRiseUpTau", 31, 13, -1, 141, 3, false); + addField("PlsrPwr", 31, 12, -1, 140, 1, false); + addField("PlsrDelay", 31, 6, -1, 134, 6, true); + addField("ExtDigCalSW", 31, 5, -1, 133, 1, false); + addField("ExtAnaCalSW", 31, 4, -1, 132, 1, false); + addField("Reg31Spare", 31, 3, -1, -1, 1, false); + addField("GADCSel", 31, 3, -1, 128, 1, false); + addField("SELB0", 32, 0, -1, -1, 16, false); + addField("SELB1", 33, 0, -1, -1, 16, false); + addField("SELB2", 34, 8, -1, -1, 8, false); + addField("Reg34Spare1", 34, 5, -1, -1, 3, false); + addField("PrmpVbpMsnEn", 34, 4, -1, -1, 1, false); + addField("Reg34Spare2", 34, 0, -1, -1, 4, false); + addField("Chip_SN", 35, 0, -1, -1, 16, false); + addField("Reg1Spare", 1, 9, -1, -1, 7, false); + addField("SmallHitErase", 1, 8, -1, -1, 1, false); + addField("Eventlimit", 1, 0, -1, -1, 8, true); + + // alternative definitions + addField("CMDcnt_width", 26, 3, -1, 51, 8, false); + addField("CMDcnt_delay", 26, 11, -1, 59, 6, false); + addField("ERRORMASK", 3, 0, -1, -1, 32, false); + addField("DisableColumnCnfg01", 23, 0, -1, 0, 32, false); + addField("SELB01", 32, 0, -1, -1, 32, false); + addField("CLK0_S2", 28, 2, -1, 82, 1, false); + addField("CLK0_S1", 28, 3, -1, 83, 1, false); + addField("CLK0_S0", 28, 4, -1, 84, 1, false); + addField("CLK1_S2", 28, 5, -1, 85, 1, false); + addField("CLK1_S1", 28, 6, -1, 86, 1, false); + addField("CLK1_S0", 28, 7, -1, 87, 1, false); + + + // Translation from scan parameter to Global register field + addParameter("LATENCY", "TrigLat"); + addParameter("GDAC", "Vthin_AltFine"); + addParameter("GDAC_COARSE", "Vthin_AltCoarse"); + addParameter("VCAL", "PlsrDAC"); + addParameter("STROBE_DELAY", "PlsrDelay"); + addParameter("IF", "PrmpVbpf"); + addParameter("TEMP", "TempSensDiodeSel"); + + //Translation from CLKx_S012 parameter to transmission rate + m_def.m_rate[0]=SerialIF::M40; + m_def.m_rate[4]=SerialIF::M320; + m_def.m_rate[2]=SerialIF::M40; + m_def.m_rate[6]=SerialIF::M320; + m_def.m_rate[1]=SerialIF::M160; + m_def.m_rate[5]=SerialIF::M80; + m_def.m_rate[3]=SerialIF::M40; + m_def.m_rate[7]=SerialIF::M160; //Aux clk + + m_def.m_params8b10b=m_def.m_fields["no8b10b"]; + m_def.m_paramsDrate=m_def.m_fields["CLK0"]; + m_def.m_colpr_reg=m_def.m_fields["Colpr_Addr"].reg; + m_def.m_colpr_disable=5<<2; + + m_initialized=true; + } + void FEI4BGlobalRegister::printFields(std::ostream &os){ + os<<"Global Register Fields"<<std::endl; + os<<"======================"<<std::endl; + os<<"TrigCnt "<<getField("TrigCnt")<<std::endl; + os<<"Conf_AddrEnable "<<getField("Conf_AddrEnable")<<std::endl; + os<<"ErrMask0 "<<getField("ErrMask0")<<std::endl; + os<<"ErrMask1 "<<getField("ErrMask1")<<std::endl; + os<<"PrmpVbpRight "<<getField("PrmpVbpRight")<<std::endl; + os<<"BufVgOpAmp "<<getField("BufVgOpAmp")<<std::endl; + os<<"PrmpVbp "<<getField("PrmpVbp")<<std::endl; + os<<"TdacVbp "<<getField("TdacVbp")<<std::endl; + os<<"DisVbn "<<getField("DisVbn")<<std::endl; + os<<"Amp2Vbn "<<getField("Amp2Vbn")<<std::endl; + os<<"Amp2VbpFol "<<getField("Amp2VbpFol")<<std::endl; + os<<"Amp2Vbp "<<getField("Amp2Vbp")<<std::endl; + os<<"FdacVbn "<<getField("FdacVbn")<<std::endl; + os<<"Amp2Vbpf "<<getField("Amp2Vbpf")<<std::endl; + os<<"PrmpVbnFol "<<getField("PrmpVbnFol")<<std::endl; + os<<"PrmpVbpLeft "<<getField("PrmpVbpLeft")<<std::endl; + os<<"PrmpVbpf "<<getField("PrmpVbpf")<<std::endl; + os<<"PrmpVbnLcc "<<getField("PrmpVbnLcc")<<std::endl; + os<<"PxStrobes "<<getField("PxStrobes")<<std::endl; + os<<"S0 "<<getField("S0")<<std::endl; + os<<"S1 "<<getField("S1")<<std::endl; + os<<"LVDSDrvIref "<<getField("LVDSDrvIref")<<std::endl; + os<<"GADCOpAmp "<<getField("GADCOpAmp")<<std::endl; + os<<"PllIbias "<<getField("PllIbias")<<std::endl; + os<<"LVDSDrvVos "<<getField("LVDSDrvVos")<<std::endl; + os<<"TempSensBias "<<getField("TempSensBias")<<std::endl; + os<<"PllIcp "<<getField("PllIcp")<<std::endl; + os<<"PlsrIdacRamp "<<getField("PlsrIdacRamp")<<std::endl; + os<<"VrefDigTune "<<getField("VrefDigTune")<<std::endl; + os<<"PlsrVgOPamp "<<getField("PlsrVgOPamp")<<std::endl; + os<<"PlsrDacBias "<<getField("PlsrDacBias")<<std::endl; + os<<"VrefAnTune "<<getField("VrefAnTune")<<std::endl; + os<<"Vthin_AltCoarse "<<getField("Vthin_AltCoarse")<<std::endl; + os<<"Vthin_AltFine "<<getField("Vthin_AltFine")<<std::endl; + os<<"PlsrDAC "<<getField("PlsrDAC")<<std::endl; + os<<"DIGHITIN_Sel "<<getField("DIGHITIN_Sel")<<std::endl; + os<<"DINJ_Override "<<getField("DINJ_Override")<<std::endl; + os<<"HITLD_In "<<getField("HITLD_In")<<std::endl; + os<<"Colpr_Addr "<<getField("Colpr_Addr")<<std::endl; + os<<"Colpr_Mode "<<getField("Colpr_Mode")<<std::endl; + os<<"DisableColumnCnfg0 "<<getField("DisableColumnCnfg0")<<std::endl; + os<<"DisableColumnCnfg1 "<<getField("DisableColumnCnfg1")<<std::endl; + os<<"DisableColumnCnfg2 "<<getField("DisableColumnCnfg2")<<std::endl; + os<<"TrigLat "<<getField("TrigLat")<<std::endl; + os<<"CMDcnt "<<getField("CMDcnt")<<std::endl; + os<<"StopModeCnfg "<<getField("StopModeCnfg")<<std::endl; + os<<"HitDiscCnfg "<<getField("HitDiscCnfg")<<std::endl; + os<<"EN_PLL "<<getField("EN_PLL")<<std::endl; + os<<"Efuse_sense "<<getField("Efuse_sense")<<std::endl; + os<<"Stop_Clk "<<getField("Stop_Clk")<<std::endl; + os<<"ReadErrorReq "<<getField("ReadErrorReq")<<std::endl; + os<<"GADC_Enable "<<getField("GADC_Enable")<<std::endl; + os<<"ShiftReadBack "<<getField("ShiftReadBack")<<std::endl; + os<<"GateHitOr "<<getField("GateHitOr")<<std::endl; + os<<"CalEn "<<getField("CalEn")<<std::endl; + os<<"SR_clr "<<getField("SR_clr")<<std::endl; + os<<"Latch_en "<<getField("Latch_en")<<std::endl; + os<<"SR_Clock "<<getField("SR_Clock")<<std::endl; + os<<"LVDSDrvSet06 "<<getField("LVDSDrvSet06")<<std::endl; + os<<"EN40M "<<getField("EN40M")<<std::endl; + os<<"EN80M "<<getField("EN80M")<<std::endl; + os<<"CLK1 "<<getField("CLK1")<<std::endl; + os<<"CLK0 "<<getField("CLK0")<<std::endl; + os<<"EN160M "<<getField("EN160M")<<std::endl; + os<<"EN320M "<<getField("EN320M")<<std::endl; + os<<"no8b10b "<<getField("no8b10b")<<std::endl; + os<<"Clk2OutCnfg "<<getField("Clk2OutCnfg")<<std::endl; + os<<"EmptyRecord "<<getField("EmptyRecord")<<std::endl; + os<<"LVDSDrvEn "<<getField("LVDSDrvEn")<<std::endl; + os<<"LVDSDrvSet30 "<<getField("LVDSDrvSet30")<<std::endl; + os<<"LVDSDrvSet12 "<<getField("LVDSDrvSet12")<<std::endl; + os<<"TempSensDiodeSel "<<getField("TempSensDiodeSel")<<std::endl; + os<<"TempSensDisable "<<getField("TempSensDisable")<<std::endl; + os<<"IleakRange "<<getField("IleakRange")<<std::endl; + os<<"PlsrRiseUpTau "<<getField("PlsrRiseUpTau")<<std::endl; + os<<"PlsrPwr "<<getField("PlsrPwr")<<std::endl; + os<<"PlsrDelay "<<getField("PlsrDelay")<<std::endl; + os<<"ExtDigCalSW "<<getField("ExtDigCalSW")<<std::endl; + os<<"ExtAnaCalSW "<<getField("ExtAnaCalSW")<<std::endl; + os<<"GADCSel "<<getField("GADCSel")<<std::endl; + os<<"SELB0 "<<getField("SELB0")<<std::endl; + os<<"SELB1 "<<getField("SELB1")<<std::endl; + os<<"SELB2 "<<getField("SELB2")<<std::endl; + os<<"PrmpVbpMsnEn "<<getField("PrmpVbpMsnEn")<<std::endl; + os<<"Chip_SN "<<getField("Chip_SN")<<std::endl; + os<<"SmallHitErase "<<getField("SmallHitErase")<<std::endl; + os<<"Eventlimit "<<getField("Eventlimit")<<std::endl; + + os<<"Alternative Field definitions:"<<std::endl; + // alternative definitions + os<<"CMDcnt_width "<<getField("CMDcnt_width")<<std::endl; + os<<"CMDcnt_delay "<<getField("CMDcnt_delay")<<std::endl; + os<<"ERRORMASK "<<getField("ERRORMASK")<<std::endl; + os<<"DisableColumnCnfg01 "<<getField("DisableColumnCnfg01")<<std::endl; + os<<"SELB01 "<<getField("SELB01")<<std::endl; + os<<"CLK0_S2 "<<getField("CLK0_S2")<<std::endl; + os<<"CLK0_S1 "<<getField("CLK0_S1")<<std::endl; + os<<"CLK0_S0 "<<getField("CLK0_S0")<<std::endl; + os<<"CLK1_S2 "<<getField("CLK1_S2")<<std::endl; + os<<"CLK1_S1 "<<getField("CLK1_S1")<<std::endl; + os<<"CLK1_S0 "<<getField("CLK1_S0")<<std::endl; + } + +}; diff --git a/rce/rcecalib/config/FEI4/FEI4BGlobalRegister.hh b/rce/rcecalib/config/FEI4/FEI4BGlobalRegister.hh new file mode 100644 index 00000000..0cdbd823 --- /dev/null +++ b/rce/rcecalib/config/FEI4/FEI4BGlobalRegister.hh @@ -0,0 +1,31 @@ +#ifndef FEI4BGLOBALREGISTER_FEI4_HH +#define FEI4BGLOBALREGISTER_FEI4_HH + +#include <map> +#include <string> +#include <vector> +#include "rcecalib/HW/SerialIF.hh" +#include "rcecalib/config/FEI4/GlobalRegister.hh" + + +namespace FEI4{ + +class FECommands; + + class FEI4BGlobalRegister: public GlobalRegister{ + public: + FEI4BGlobalRegister(FECommands* commands); + virtual ~FEI4BGlobalRegister(); + void printFields(std::ostream &os); + private: + void initialize(); + static RegisterDef m_def; + static bool m_initialized; + RegisterDef* getDef(){return &m_def;} + + + }; + +}; + +#endif diff --git a/rce/rcecalib/config/FEI4/FEI4BModule.cc b/rce/rcecalib/config/FEI4/FEI4BModule.cc new file mode 100644 index 00000000..a9900845 --- /dev/null +++ b/rce/rcecalib/config/FEI4/FEI4BModule.cc @@ -0,0 +1,104 @@ +#include "rcecalib/config/FEI4/FEI4BModule.hh" +#include "rcecalib/config/FEI4/FEI4BGlobalRegister.hh" +#include "rcecalib/HW/BitStream.hh" +#include "rcecalib/config/FEI4/FECommands.hh" +#include "rcecalib/config/MaskStageFactory.hh" +#include "rcecalib/HW/SerialIF.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/util/VerifyErrors.hh" +#include <iostream> +#include <fstream> +#include "ers/ers.h" +#include <stdio.h> + +namespace FEI4{ + + + FEI4BModule::FEI4BModule(const char* name, unsigned id, unsigned inlink, unsigned outlink, AbsFormatter* fmt): + Module(name, id, inlink, outlink, fmt){ + // std::cout<<"Module"<<std::endl; + m_commands=new FECommands; + m_global=new FEI4BGlobalRegister(m_commands); + m_pixel=new PixelRegister(m_commands); + m_pixel_readback=new PixelRegister(m_commands); + } + FEI4BModule::~FEI4BModule(){ + delete m_global; + delete m_pixel; + delete m_pixel_readback; + delete m_commands; + //m_timer.Print("Module"); + } + void FEI4BModule::setupGlobalPulseHW(int pulsereg){ + m_global->setField("Efuse_sense",(pulsereg&GlobalRegister::Efuse_sense)!=0, GlobalRegister::SW); + m_global->setField("Stop_Clk",(pulsereg&GlobalRegister::Stop_Clk)!=0, GlobalRegister::SW); + m_global->setField("ReadErrorReq",(pulsereg&GlobalRegister::ReadErrorReq)!=0, GlobalRegister::SW); + m_global->setField("CalEn",(pulsereg&GlobalRegister::CalEn)!=0, GlobalRegister::SW); + m_global->setField("SR_clr",(pulsereg&GlobalRegister::SR_clr)!=0, GlobalRegister::SW); + m_global->setField("Latch_en",(pulsereg&GlobalRegister::Latch_en)!=0, GlobalRegister::SW); + m_global->setField("GADC_Enable",(pulsereg&GlobalRegister::GADC_Start)!=0, GlobalRegister::SW); + m_global->setField("ShiftReadBack",(pulsereg&GlobalRegister::SR_Read)!=0, GlobalRegister::SW); + m_global->setField("SR_Clock",(pulsereg&GlobalRegister::SR_Clock)!=0, GlobalRegister::HW); //do one HW write for all fields + } + + // void Frontend::pixelUsrToRaw(BitStream *bs, unsigned bit){ + // } + + void FEI4BModule::resetHW(){ + BitStream *bs=new BitStream; + BitStreamUtils::prependZeros(bs); + m_commands->globalReset(bs); + SerialIF::send(bs); + delete bs; + resetErrorCountersHW(); + } + + + int FEI4BModule::verifyModuleConfigHW(){ + int retval=0; + SerialIF::setChannelInMask(1<<m_inLink); + SerialIF::setChannelOutMask(1<<m_outLink); + std::vector <unsigned> readback; + if(m_formatter){ + // global register + std::cout<<"***FE "<<m_id<<"***"<<std::endl; + m_formatter->setReadbackPointer(&readback); + retval=m_global->verifyConfigHW(readback); + // pixel registers + m_global->setField("Colpr_Mode", 0, GlobalRegister::SW); // only write to 1 column pair + BitStream *bs=new BitStream; + bs->push_back(0); + m_commands->globalPulse(bs, FECommands::PULSE_WIDTH); + for (int dcol=0;dcol<PixelRegister::N_COLS/2;dcol++){ + for (int bit=0;bit<PixelRegister::N_PIXEL_REGISTER_BITS-1;bit++){ + m_global->setField("Colpr_Addr", dcol, GlobalRegister::HW); + setupS0S1HitldHW(1, 1, 0); + setupGlobalPulseHW(GlobalRegister::SR_Clock); //SR clock + //set up strobe bit + setupPixelStrobesHW(1<<bit); + SerialIF::send(bs, SerialIF::DONT_CLEAR); //global pulse + setupS0S1HitldHW(0, 0, 0); + m_global->setField("ShiftReadBack",1, GlobalRegister::HW); //setupGlobalPulse does the HW write for that register + retval|=m_pixel->verifyDoubleColumnHW(bit, dcol, readback); //check double column + m_global->setField("ShiftReadBack",0, GlobalRegister::SW); //setupGlobalPulse does the HW write for that register + } + } + setupGlobalPulseHW(0); //clear + setupPixelStrobesHW(0); //clear + delete bs; + m_formatter->setReadbackPointer(0); + }else{ + retval=ModuleVerify::NO_FORMATTER; + } + return retval; + } + + + void FEI4BModule::destroy(){ + delete this; + } + + +}; + diff --git a/rce/rcecalib/config/FEI4/FEI4BModule.hh b/rce/rcecalib/config/FEI4/FEI4BModule.hh new file mode 100644 index 00000000..0df855da --- /dev/null +++ b/rce/rcecalib/config/FEI4/FEI4BModule.hh @@ -0,0 +1,25 @@ +#ifndef FEI4__FEI4BMODULE_HH +#define FEI4__FEI4BMODULE_HH + +#include "rcecalib/config/FEI4/Module.hh" +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/profiler/Profiler.hh" +#include <string> + +class AbsFormatter; + +namespace FEI4{ + + class FEI4BModule: public Module{ + public: + FEI4BModule(const char* name, unsigned id, unsigned inLink, unsigned outLink, AbsFormatter *fmt); + virtual ~FEI4BModule(); + void resetHW(); + int verifyModuleConfigHW(); + virtual void destroy(); + void setupGlobalPulseHW(int pulsereg); + +}; + +}; +#endif diff --git a/rce/rcecalib/config/FEI4/FEI4BRecord.hh b/rce/rcecalib/config/FEI4/FEI4BRecord.hh new file mode 100644 index 00000000..879dfc69 --- /dev/null +++ b/rce/rcecalib/config/FEI4/FEI4BRecord.hh @@ -0,0 +1,246 @@ +#ifndef FEI4BRECORD_HH +#define FEI4BRECORD_HH + +#include "rcecalib/config/Endianness.hh" +namespace FEI4{ + + +namespace Size +{ + enum Size + { + UNUSED = 8, + HEADER = 8, + RTYPE = 1, + ADDR = 15, + VALUE = 16, + ERRCODE = 6, + ERRCOUNT = 10, + REMAINDER = 16, + FLAG = 1, + LV1ID = 5, + BXID = 10, + COL = 7, + ROW = 9, + TOT = 4 + }; +} +namespace Key +{ + enum Key + { + ADDR = 0xea, + VALUE = 0xec, + SERVICE = 0xef, + HEADER = 0xe9, + EMPTY = 0x0, + GLOBAL = 0, + SHIFT = 1 + }; +} +/* ---------------------------------------------------------------------- */ + + struct Generic + { +#if ENDIANNESS_IS_BIG + + unsigned int unused: Size::UNUSED; + unsigned int header: Size::HEADER; + unsigned int remainder: Size::REMAINDER; + +#elif ENDIANNESS_IS_LITTLE + + unsigned int remainder: Size:: REMAINDER; + unsigned int header: Size::HEADER; + unsigned int unused: Size::UNUSED; + +#else + +#error ENDIANNESS is not defined +#endif + }; + struct Address + { +#if ENDIANNESS_IS_BIG + + unsigned int unused: Size::UNUSED; + unsigned int header: Size::HEADER; + unsigned int rtype: Size:: RTYPE; + unsigned int address: Size::ADDR; + +#elif ENDIANNESS_IS_LITTLE + + unsigned int address: Size::ADDR; + unsigned int rtype: Size:: RTYPE; + unsigned int header: Size::HEADER; + unsigned int unused: Size::UNUSED; + +#else + +#error ENDIANNESS is not defined +#endif + }; + + struct Value + { +#if ENDIANNESS_IS_BIG + + unsigned int unused: Size::UNUSED; + unsigned int header: Size::HEADER; + unsigned int value: Size::VALUE; + +#elif ENDIANNESS_IS_LITTLE + + unsigned int value: Size::VALUE; + unsigned int header: Size::HEADER; + unsigned int unused: Size::UNUSED; + +#else +#error ENDIANNESS is not defined +#endif + }; + + struct Service + { +#if ENDIANNESS_IS_BIG + + unsigned int unused: Size::UNUSED; + unsigned int header: Size::HEADER; + unsigned int errcode: Size::ERRCODE; + unsigned int errcount: Size::ERRCOUNT; + +#elif ENDIANNESS_IS_LITTLE + + unsigned int errcount: Size::ERRCOUNT; + unsigned int errcode: Size::ERRCODE; + unsigned int header: Size::HEADER; + unsigned int unused: Size::UNUSED; + +#else + +#error ENDIANNESS is not defined +#endif + }; + + struct DataHeader + { +#if ENDIANNESS_IS_BIG + + unsigned int unused: Size::UNUSED; + unsigned int header: Size::HEADER; + unsigned int flag: Size::FLAG; + unsigned int lv1id: Size::LV1ID; + unsigned int bxid: Size::BXID; + +#elif ENDIANNESS_IS_LITTLE + + unsigned int bxid: Size::BXID; + unsigned int lv1id: Size::LV1ID; + unsigned int flag: Size::FLAG; + unsigned int header: Size::HEADER; + unsigned int unused: Size::UNUSED; + +#else + +#error ENDIANNESS is not defined +#endif + }; + + struct Data + { +#if ENDIANNESS_IS_BIG + + unsigned int unused: Size::UNUSED; + unsigned int col: Size::COL; + unsigned int row: Size::ROW; + unsigned int totbottom: Size::TOT; + unsigned int tottop: Size::TOT; + +#elif ENDIANNESS_IS_LITTLE + + unsigned int tottop: Size::TOT; + unsigned int totbottom: Size::TOT; + unsigned int row: Size::ROW; + unsigned int col: Size::COL; + unsigned int unused: Size::UNUSED; + +#else + +#error ENDIANNESS is not defined +#endif + }; + + + union Record + { + unsigned int ui; + Generic ge; + Address ad; + Value va; + Service se; + DataHeader he; + Data da; + }; + + + class FEI4BRecord{ + public: + enum Status + { + OK = 0, /*!< Clean finish */ + Empty = 1, /*!< Buffer does not contain any record */ + NotGlobal = 2, /*!< Address record is not a global register record */ + WrongAddress = 3, /*!< Address record does not contain the expected address */ + BadAddrValSeq = 4, /*!< Address record not immediately followed by value record */ + NoValue = 5, /*!< Value record missing. */ + NotShift = 6, /*!< Address record is not a shift register record */ + OddNwords = 7, /*!< Odd number of 16 bit words in shift register readback */ + NoHeader = 8, /*!< Data word without a previous header word*/ + BadRecord = 9 /*!< Unknown record type */ + }; + + bool isAddressRecord(){return m_record.ge.header==Key::ADDR;} + bool isValueRecord(){return m_record.ge.header==Key::VALUE;} + bool isServiceRecord(){return m_record.ge.header==Key::SERVICE;} + bool isEmptyRecord(){return m_record.ge.header==Key::EMPTY;} + bool isDataHeader(){return m_record.ge.header==Key::HEADER;} + bool isData(){return (m_record.ge.header&0xc0)!=0xc0;} + unsigned getHeader(){return m_record.ge.header;} + unsigned getAddress(){return m_record.ad.address;} + unsigned getRegisterType(){return m_record.ad.rtype;} + unsigned isGlobal(){return m_record.ad.rtype==Key::GLOBAL;} + unsigned isShift(){return m_record.ad.rtype==Key::SHIFT;} + unsigned getValue(){return m_record.va.value;} + unsigned getUnsigned(){return m_record.ui;} + unsigned getColumn(){return m_record.da.col;} + unsigned getL1id(){return m_record.he.lv1id;} + unsigned getBxid(){return m_record.he.bxid;} + unsigned getRow(){return m_record.da.row;} + unsigned getTotTop(){return m_record.da.tottop;} + unsigned getTotBottom(){return m_record.da.totbottom;} + unsigned getErrorCode(){return m_record.se.errcode;} + unsigned getErrorCount(){return m_record.se.errcount;} +#if ENDIANNESS_IS_BIG + void setRecord(const unsigned char* bytepointer){ + unsigned char* rec=(unsigned char*)&m_record; + rec[1]=*bytepointer; + rec[2]=*(bytepointer+1); + rec[3]=*(bytepointer+2); + } +#elif ENDIANNESS_IS_LITTLE + void setRecord(const unsigned char* bytepointer){ + unsigned char* rec=(unsigned char*)&m_record; + rec[2]=*bytepointer; + rec[1]=*(bytepointer+1); + rec[0]=*(bytepointer+2); + } +#else +#error ENDIANNESS is not defined +#endif + + private: + Record m_record; + }; + +} +#endif diff --git a/rce/rcecalib/config/FEI4/FEI4HitorFormatter.cc b/rce/rcecalib/config/FEI4/FEI4HitorFormatter.cc new file mode 100644 index 00000000..8bb0c8cf --- /dev/null +++ b/rce/rcecalib/config/FEI4/FEI4HitorFormatter.cc @@ -0,0 +1,63 @@ +#include "rcecalib/config/FEI4/FEI4HitorFormatter.hh" +#include "rcecalib/config/FEI4/FEI4ARecord.hh" +#include "rcecalib/config/FormattedRecord.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/util/exceptions.hh" +#include "ers/ers.h" +#include <iostream> +#include <stdio.h> + +FEI4HitorFormatter::FEI4HitorFormatter(int id): + AbsFormatter(id){ +} +FEI4HitorFormatter::~FEI4HitorFormatter(){ + +} +void FEI4HitorFormatter::configure(boost::property_tree::ptree* config){ +} + +int FEI4HitorFormatter::decode (const unsigned int *buffer, int buflen, unsigned* parsedData, int &parsedsize, int &nL1A){ + if(buflen==0)return FEI4::FEI4ARecord::Empty; + unsigned char* bytepointer=(unsigned char*)buffer; + unsigned char* last=bytepointer+buflen*sizeof(unsigned)-3; + FEI4::FEI4ARecord rec; + bool header=false; + nL1A=0; + while(bytepointer<=last){ + rec.setRecord(bytepointer); + if(rec.isDataHeader()){ + header=true; + //printf("Formatter word %x\n",rec.getValue()); + //printf("FEI %d Header.\n",getId()); + }else if (rec.isEmptyRecord()){ + header=false; + }else if(rec.isData()){ + //printf("FEI %d Data.\n",getId()); + if(header==false)return FEI4::FEI4ARecord::NoHeader; + // std::cout<<std::hex<<rec.getHeader()<<std::endl; + }else if(rec.isServiceRecord()){ + //printf("Service record FEI %d. Error code: %d. Count: %d \n", getId(), rec.getErrorCode(), rec.getErrorCount()); + unsigned code=rec.getErrorCode(); + unsigned count=rec.getErrorCount(); + if(code==10){ //HitOr + //printf("Service record FEI %d. Error code: %d. Count: %d \n", getId(), rec.getErrorCode(), rec.getErrorCount()); + nL1A=1; //pretend all triggers came in + if(count>0)parsedData[parsedsize++]=1; //pixel is stuck + return FEI4::FEI4ARecord::OK; + } + header=false; + }else if(rec.isValueRecord()){ //val rec without addr rec + //printf("FEI %d: Value record: %04x.\n",getId(), rec.getValue()); + header=false; + }else if(rec.isAddressRecord()){ // address record + //printf("FEI %d: Address record\n",getId()); + header=false; + }else{ + std::cout<<"Unexpected record type: "<<std::hex<<rec.getUnsigned()<<std::dec<<std::endl; + return FEI4::FEI4ARecord::BadRecord; + } + bytepointer+=3; + } + return FEI4::FEI4ARecord::OK; +} + diff --git a/rce/rcecalib/config/FEI4/FEI4HitorFormatter.hh b/rce/rcecalib/config/FEI4/FEI4HitorFormatter.hh new file mode 100644 index 00000000..2b0a89a8 --- /dev/null +++ b/rce/rcecalib/config/FEI4/FEI4HitorFormatter.hh @@ -0,0 +1,14 @@ +#ifndef FEI4HITORFORMATTER_HH +#define FEI4HITORFORMATTER_HH + +#include "rcecalib/config/AbsFormatter.hh" + +class FEI4HitorFormatter:public AbsFormatter{ +public: + FEI4HitorFormatter(int id); + virtual ~FEI4HitorFormatter(); + int decode(const unsigned* data, int size, unsigned* parsedData, int &parsedsize, int &nL1A); + void configure(boost::property_tree::ptree* scanOptions); + +}; +#endif diff --git a/rce/rcecalib/config/FEI4/FEI4OccFormatter.cc b/rce/rcecalib/config/FEI4/FEI4OccFormatter.cc new file mode 100644 index 00000000..5896dc7b --- /dev/null +++ b/rce/rcecalib/config/FEI4/FEI4OccFormatter.cc @@ -0,0 +1,82 @@ +#include "rcecalib/config/FEI4/FEI4OccFormatter.hh" +#include "rcecalib/config/FEI4/FEI4ARecord.hh" +#include "rcecalib/config/FormattedRecord.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/util/exceptions.hh" +#include "ers/ers.h" +#include <iostream> +#include <stdio.h> +#include "rcecalib/profiler/Profiler.hh" + +FEI4OccFormatter::FEI4OccFormatter(int id): + AbsFormatter(id){ + char name[128], title[128]; + sprintf(name, "Mod_%d_FEI4_Errors", id); + sprintf(title, "Module %d FEI4 Errors", id); + m_errhist=new RceHisto1d<int, int>(name, title, 32, -.5, 31.5); +} +FEI4OccFormatter::~FEI4OccFormatter(){ + delete m_errhist; + //m_timer.Print("FEI4OccupancyFormatter"); + +} +void FEI4OccFormatter::configure(boost::property_tree::ptree* config){ + m_errhist->clear(); + //m_timer.Reset(); +} + +int FEI4OccFormatter::decode (const unsigned int *buffer, int buflen, unsigned* parsedData, int &parsedsize, int &nL1A){ + if(buflen==0)return FEI4::FEI4ARecord::Empty; + //m_timer.Start(); + unsigned char* bytepointer=(unsigned char*)buffer; + unsigned char* last=bytepointer+buflen*sizeof(unsigned)-3; + FEI4::FEI4ARecord rec; + bool header=false; + while(bytepointer<=last){ + rec.setRecord(bytepointer); + if (rec.isEmptyRecord()){ + header=false; + }else if(rec.isData()){ + if(header==false)return FEI4::FEI4ARecord::NoHeader; + //there are potentially 2 hits in one data record + if(((rec.getTotBottom())>>1)!=0x7){ //above threshold + FormattedRecord fr(FormattedRecord::DATA); + fr.setCol(rec.getColumn()-1); + fr.setRow(rec.getRow()-1); + parsedData[parsedsize++]=fr.getWord(); + + } + if(((rec.getTotTop())>>1)!=0x7){ //above threshold + FormattedRecord fr(FormattedRecord::DATA); + fr.setCol(rec.getColumn()-1); + fr.setRow(rec.getRow()); + parsedData[parsedsize++]=fr.getWord(); + } + } else if(rec.isDataHeader()){ + header=true; + nL1A++; + }else if(rec.isServiceRecord()){ + printf("Service record FE %d. Error code: %d. Count: %d \n", + getId(), rec.getErrorCode(), rec.getErrorCount()); + if( rec.getErrorCode()<32)m_errhist->fill(rec.getErrorCode(), rec.getErrorCount()); + header=false; + }else if(rec.isValueRecord()){ //val rec without addr rec + // printf("Value record: %04x.\n",rec.getValue()); + header=false; + }else if(rec.isAddressRecord()){ // address record + std::cout<<"Address record for "; + if(rec.isGlobal())std::cout<<" global register "; + else std::cout<<" shift register "; + std::cout<<rec.getAddress()<<std::endl; + std::cout<<"This should not happen."<<std::endl; + header=false; + }else{ + std::cout<<"Unexpected record type: "<<std::hex<<rec.getUnsigned()<<std::dec<<std::endl; + return FEI4::FEI4ARecord::BadRecord; + } + bytepointer+=3; + } + // m_timer.Stop(); + return FEI4::FEI4ARecord::OK; +} + diff --git a/rce/rcecalib/config/FEI4/FEI4OccFormatter.hh b/rce/rcecalib/config/FEI4/FEI4OccFormatter.hh new file mode 100644 index 00000000..7d9e267d --- /dev/null +++ b/rce/rcecalib/config/FEI4/FEI4OccFormatter.hh @@ -0,0 +1,19 @@ +#ifndef FEI4OCCFORMATTER_HH +#define FEI4OCCFORMATTER_HH + +#include "rcecalib/config/AbsFormatter.hh" +#include "rcecalib/util/RceHisto1d.cc" +#include "rcecalib/profiler/Profiler.hh" + +class FEI4OccFormatter:public AbsFormatter{ +public: + FEI4OccFormatter(int id); + virtual ~FEI4OccFormatter(); + int decode(const unsigned* data, int size, unsigned* parsedData, int &parsedsize, int &nL1A); + void configure(boost::property_tree::ptree* scanOptions); + +private: + RceHisto1d<int, int>* m_errhist; + Profiler::Timer m_timer; +}; +#endif diff --git a/rce/rcecalib/config/FEI4/FastAnalogMaskStaging.cc b/rce/rcecalib/config/FEI4/FastAnalogMaskStaging.cc new file mode 100644 index 00000000..ac0577e1 --- /dev/null +++ b/rce/rcecalib/config/FEI4/FastAnalogMaskStaging.cc @@ -0,0 +1,37 @@ +#include "rcecalib/config/FEI4/FastAnalogMaskStaging.hh" +#include "rcecalib/config/FEI4/Module.hh" + +namespace FEI4{ + + FastAnalogMaskStaging::FastAnalogMaskStaging(FEI4::Module* mod, Masks masks, std::string type) + :MaskStaging<FEI4::Module>(mod, masks, type){ + if(type=="FEI4_COL_ANL_40x8")m_nStages=6; + else m_nStages=3; + } + + void FastAnalogMaskStaging::setupMaskStageHW(int maskStage){ + if(m_initialized==false || maskStage==0){ + clearBitsHW(); + m_initialized=true; + } + const int nColStages=40; + PixelRegister* pixel=m_module->pixel(); + GlobalRegister* global=m_module->global(); + unsigned dcolStage=maskStage%nColStages; + unsigned stage=maskStage/nColStages; + if((maskStage+nColStages)/nColStages!=(maskStage+nColStages-1)/nColStages){ //need to set up pixel mask + global->setField("Colpr_Mode", 3, GlobalRegister::SW); + for(int i=0;i<PixelRegister::N_PIXEL_REGISTER_BITS;i++){ + if(m_masks.iMask&(1<<i)){ + pixel->setupMaskStage(i, stage, m_nStages); + m_module->writeDoubleColumnHW(i, i, 0, 0); + } + } + } + // stage 0-5: colpr_mode=2, colpr_addr= 1, 2, 3, 4, 5, 6 + // stage 6-9: colpr_mode=0, colpr_addr= 8, 16, 24, 32 + // stage 10-13: colpr_mode=0, colpr_addr= 7, 15, 23, 31 + global->setField("Colpr_Mode", 0, GlobalRegister::SW); + global->setField("Colpr_Addr", dcolStage , GlobalRegister::HW); +} +}; diff --git a/rce/rcecalib/config/FEI4/FastAnalogMaskStaging.hh b/rce/rcecalib/config/FEI4/FastAnalogMaskStaging.hh new file mode 100644 index 00000000..2ebc5dc9 --- /dev/null +++ b/rce/rcecalib/config/FEI4/FastAnalogMaskStaging.hh @@ -0,0 +1,20 @@ +#ifndef FEI4FASTANALOGMASKSTAGING_HH +#define FEI4FASTANALOGMASKSTAGING_HH + +#include "rcecalib/config/Masks.hh" +#include "rcecalib/config/MaskStaging.hh" + +namespace FEI4{ + + class Module; + + class FastAnalogMaskStaging: public MaskStaging<FEI4::Module>{ + public: + FastAnalogMaskStaging(FEI4::Module* module, Masks masks, std::string type); + void setupMaskStageHW(int maskStage); + private: + int m_nStages; + }; + +} +#endif diff --git a/rce/rcecalib/config/FEI4/Fei4RegisterTestTrigger.cc b/rce/rcecalib/config/FEI4/Fei4RegisterTestTrigger.cc new file mode 100644 index 00000000..497466a9 --- /dev/null +++ b/rce/rcecalib/config/FEI4/Fei4RegisterTestTrigger.cc @@ -0,0 +1,97 @@ + +#include "rcecalib/config/FEI4/Fei4RegisterTestTrigger.hh" +#include "rcecalib/config/FEI4/FECommands.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/HW/SerialIF.hh" +#include "rcecalib/profiler/Profiler.hh" + +namespace FEI4{ + + Fei4RegisterTestTrigger::Fei4RegisterTestTrigger():AbsTrigger(){ + } + Fei4RegisterTestTrigger::~Fei4RegisterTestTrigger(){ + } + int Fei4RegisterTestTrigger::configureScan(boost::property_tree::ptree* scanOptions){ + int retval=0; + m_i=0; //reset the number of triggers + try{ + // int calL1ADelay = scanOptions->get<int>("trigOpt.CalL1ADelay"); + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + retval=1; + } + return retval; + } + int Fei4RegisterTestTrigger::setupParameter(const char* name, int val){ + return 0; + } + + + int Fei4RegisterTestTrigger::sendTrigger(){ + m_triggerStream.clear(); + FECommands commands; + commands.setBroadcast(true); + int triggersPerStage=13*40; + int maskstage=m_i/triggersPerStage; + if(maskstage<2){ //pixel register test + int trigger=m_i%triggersPerStage; + int dcol=trigger/13; + int dcolrev=((dcol&1)<<5) | ((dcol&2)<<3) | ((dcol&4)<<1) | ((dcol&8)>>1) | ((dcol&16)>>3) | ((dcol&32)>>5); + int bit=trigger%13; + dcolrev=dcolrev<<2; + commands.switchMode(&m_triggerStream, FECommands::CONF); + m_triggerStream.push_back(0); + //colpr mode and addr + commands.writeGlobalRegister(&m_triggerStream, 22, dcolrev); + m_triggerStream.push_back(0); + //SR clock + commands.writeGlobalRegister(&m_triggerStream, 27, 0x8002); + m_triggerStream.push_back(0); + //set up strobe bit + commands.writeGlobalRegister(&m_triggerStream, 13, 0xc000|(1<<(13-bit))); + m_triggerStream.push_back(0); + commands.globalPulse(&m_triggerStream, FECommands::PULSE_WIDTH); + SerialIF::send(&m_triggerStream, SerialIF::WAITFORDATA); //global pulse + //clear strobe/S0S1 + commands.writeGlobalRegister(&m_triggerStream, 13, 0); + //setup shift readback + commands.writeGlobalRegister(&m_triggerStream, 27, 0x8200); + m_triggerStream.push_back(0); + commands.feWriteCommand(&m_triggerStream); + for(int i=0;i<21;i++)m_triggerStream.push_back(0); // refill with 0 + m_triggerStream.push_back(0); + commands.writeGlobalRegister(&m_triggerStream, 27, 0x8000); //shift readback to 0 + m_triggerStream.push_back(0); + SerialIF::send(&m_triggerStream, SerialIF::WAITFORDATA); + }else{ //global register readback + commands.switchMode(&m_triggerStream, FECommands::CONF); + m_triggerStream.push_back(0); + for (int i=1;i<=42;i++){ //Has to be 42 because 42 triggers are expected. + int reg=i; + if(reg>35)reg=35; + commands.readGlobalRegister(&m_triggerStream, reg); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + } + SerialIF::send(&m_triggerStream, SerialIF::WAITFORDATA); + + } + + m_i++; + return 0; + } + + int Fei4RegisterTestTrigger::enableTrigger(bool on){ + return SerialIF::enableTrigger(on); + return 0; + } + int Fei4RegisterTestTrigger::resetCounters(){ + return 0; + } +}; diff --git a/rce/rcecalib/config/FEI4/Fei4RegisterTestTrigger.hh b/rce/rcecalib/config/FEI4/Fei4RegisterTestTrigger.hh new file mode 100644 index 00000000..0e3d02a9 --- /dev/null +++ b/rce/rcecalib/config/FEI4/Fei4RegisterTestTrigger.hh @@ -0,0 +1,25 @@ +#ifndef FEI4REGISTERTESTTRIGGER_HH +#define FEI4REGISTERTESTTRIGGER_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/config/AbsTrigger.hh" +#include "rcecalib/HW/BitStream.hh" + +namespace FEI4{ + + class Fei4RegisterTestTrigger: public AbsTrigger{ + public: + Fei4RegisterTestTrigger(); + ~Fei4RegisterTestTrigger(); + int configureScan(boost::property_tree::ptree* scanOptions); + int setupParameter(const char* name, int val); + int sendTrigger(); + int enableTrigger(bool on); + int resetCounters(); + private: + BitStream m_triggerStream; + }; + +}; + +#endif diff --git a/rce/rcecalib/config/FEI4/GlobalRegister.cc b/rce/rcecalib/config/FEI4/GlobalRegister.cc new file mode 100644 index 00000000..85cd884e --- /dev/null +++ b/rce/rcecalib/config/FEI4/GlobalRegister.cc @@ -0,0 +1,273 @@ + +#include "rcecalib/config/FEI4/GlobalRegister.hh" +#include "rcecalib/config/FEI4/FECommands.hh" +#include "rcecalib/config/FEI4/FEI4ARecord.hh" +#include "rcecalib/config/FEI4/Utils.hh" +#include "rcecalib/HW/SerialIF.hh" +#include <iostream> +#include "ers/ers.h" +#include <stdio.h> +#include "rcecalib/profiler/Profiler.hh" +#include "rcecalib/util/VerifyErrors.hh" + +namespace FEI4{ + + GlobalRegister::GlobalRegister(FECommands* commands): m_clkOutMode(false), m_commands(commands){ + } + GlobalRegister::~GlobalRegister(){ + } + void GlobalRegister::writeHW(){ + for(int i=m_rd->N_REG_REGS-1;i>=m_rd->LOW_REG;i--){ +// for(int i=LOW_REG;i<N_REG_REGS;i++){ + if(i==20)continue; //threshold register at the end + assert(writeRegisterHW(i, m_regw[i])==0); + } + } + void GlobalRegister::writeRegisterHW(int i){ + assert(writeRegisterHW(i, m_regw[i])==0); + } + void GlobalRegister::disableThresholdHW(bool dis){ + BitStream *bs=new BitStream; + unsigned short val= dis? 0xffff : m_regw[20]; + m_commands->writeGlobalRegister(bs, 20, val); + SerialIF::send(bs, SerialIF::WAITFORDATA); //Write register + delete bs; + } + + void GlobalRegister::enableSrHW(bool on){ + unsigned short val; + if(on)val=m_regw[m_rd->m_colpr_reg]; + else val=m_rd->m_colpr_disable; + BitStream *bs=new BitStream; + m_commands->writeGlobalRegister(bs, m_rd->m_colpr_reg, val); + SerialIF::send(bs, SerialIF::WAITFORDATA); //Write register + delete bs; + } + + unsigned GlobalRegister::writeRegisterHW(int i, unsigned short val){ + unsigned retval=0; + if(i<0 || i>=m_rd->N_W_REGS){ + retval=1; + }else { + m_regw[i]=val; // set register content + + BitStream *bs=new BitStream; + m_commands->writeGlobalRegister(bs, i, val); + + SerialIF::send(bs, SerialIF::WAITFORDATA); //Write register + if (i==m_rd->m_params8b10b.reg || i==m_rd->m_paramsDrate.reg){ + if(i==m_rd->m_paramsDrate.reg){ + SerialIF::setDataRate(m_rd->m_rate[getField("CLK0")]); + } + if(getField("Clk2OutCnfg")==0){ //chip is not in clk output mode + bool mode=getField("no8b10b"); + std::cout<<"Mode is "<<mode<<std::endl; + SerialIF::setOutputMode(mode); + m_clkOutMode=false; + }else{ + m_clkOutMode=true; + } + } + delete bs; + } + return retval; + } + + unsigned GlobalRegister::readRegisterHW(int i, unsigned short& val){ + unsigned retval=0; + if(m_clkOutMode==true){ + retval=11; + }else if(i>=0 && i<m_rd->N_R_REGS){ + BitStream *bs=new BitStream; + std::vector<unsigned> retvec; + m_commands->readGlobalRegister(bs, i); + // SerialIF::send(bs); + std::cout<<"Size "<<retvec.size()<<std::endl; + retval=SerialIF::readBlockData(*bs, retvec); + std::cout<<"Size "<<retvec.size()<<std::endl; + if(retval==0){ + retval=decodeGlobalRecord(retvec,i,val); + } + delete bs; + }else{ + retval=10; + } + return retval; + } + void GlobalRegister::readRegisterHW(int i){ + if(i>=0 && i<m_rd->N_R_REGS){ + BitStream *bs=new BitStream; + m_commands->readGlobalRegister(bs, i); + SerialIF::send(bs, SerialIF::WAITFORDATA); + delete bs; + } + } + int GlobalRegister::verifyConfigHW(std::vector<unsigned> & readback){ + int retval=0; + for(int i=m_rd->LOW_REG;i<m_rd->N_REG_REGS;i++){ + if (i==22)continue; // reg 22 is colpr_mode and colpr_addr. Used to set up pixel reg => will be different in readback + readback.clear(); + readRegisterHW(i); + usleep(100); + if(readback.size()==0){ + std::cout<<"Failed to read back register "<<std::dec<<i<<std::endl; + retval|=ModuleVerify::GLOBAL_READBACK_FAILED; + } else { + m_regr[i]=readback[0]; + if(m_regw[i]!=m_regr[i]){ + std::cout<<"Bad global register readback for register "<<std::dec<<i + <<": Read "<<std::hex<<m_regr[i]<<" should be "<<m_regw[i]<<std::dec<<std::endl; + retval|=ModuleVerify::GLOBAL_READBACK_DIFFERENT; + } + } + } + return retval; + } + + void GlobalRegister::setField(const char* name, unsigned vali, mode t){ + char msg[128]; + sprintf(msg,"parameter %s is invalid",name); + ERS_ASSERT_MSG(m_rd->m_fields.find(name)!=m_rd->m_fields.end(),msg); + FieldParams params=m_rd->m_fields[name]; + // set the proper register first + unsigned val; + if(params.reverse==true)val=flipBits(params.width, vali); + else val=vali; + setFieldFun(&m_regw[params.reg], params.bitpos, params.width, val); + if(t==HW){ + writeRegisterHW(params.reg); + if(params.bitpos+params.width>16)writeRegisterHW(params.reg+1); + } + //if(params.SRABbitpos!=-1) // AB shadow register + // setFieldFun(&m_srab[params.SRABbitpos/16], params.SRABbitpos%16, params.width, val); + //if(params.SRCbitpos!=-1) // C shadow register + // setFieldFun(&m_src[params.SRCbitpos/16], params.SRCbitpos%16, params.width, val); + } + void GlobalRegister::setFieldFun(unsigned short* reg, int bitpos, int width, unsigned val){ + int pwidth=bitpos+width<=16 ? width : 16 - bitpos; + unsigned short mask=(1<<pwidth)-1; + *reg&=~(mask<<bitpos); + *reg|=(val&mask)<<bitpos; + if(pwidth!=width){ // extends over next register + int rwidth=width-pwidth; + mask=(1<<rwidth)-1; + *(reg+1)&=~mask; + *(reg+1)|=(val>>pwidth)&mask; + } + } + + unsigned GlobalRegister::getField(const char* name){ + ERS_ASSERT_MSG(m_rd->m_fields.find(name)!=m_rd->m_fields.end(),"parameter name is invalid"); + FieldParams params=m_rd->m_fields[name]; + unsigned retval=0; + int pwidth=params.bitpos+params.width<=16 ? params.width : 16 - params.bitpos; + unsigned short mask=(1<<pwidth)-1; + retval=(m_regw[params.reg]>>params.bitpos)&mask; + if(pwidth!=params.width){ // extends over next register + int rwidth=params.width-pwidth; + mask=(1<<rwidth)-1; + retval|=(m_regw[params.reg+1]&mask)<<pwidth; + } + if(params.reverse==false) + return retval; + else + return flipBits(params.width, retval); + } + + std::string GlobalRegister::lookupParameter(const char* name){ + // check if this is the last name used, return cached value + if(std::string(name)==m_rd->m_cachedName)return m_rd->m_cachedField; + // Now check if we can translate the name to a field name + if(m_rd->m_parameters.find(name)!=m_rd->m_parameters.end()){ + //cache result + m_rd->m_cachedName=name; + m_rd->m_cachedField=m_rd->m_parameters[name]; + return m_rd->m_cachedField; + // maybe it's a proper field name? + } else if (m_rd->m_fields.find(name)!=m_rd->m_fields.end()){ + m_rd->m_cachedName=name; + m_rd->m_cachedField=name; + return m_rd->m_cachedField; + } + // not found. + else return ""; + } + void GlobalRegister::addParameter(const char* name, const char* field){ + m_rd->m_parameters[name]=field; + } + void GlobalRegister::addField(const char* name, int reg, int bitpos, int srab, int src, int width, bool reverse){ + FieldParams temp; + temp.reg=reg; + temp.bitpos=bitpos; + temp.SRABbitpos=srab; + temp.SRCbitpos=src; + temp.width=width; + temp.reverse=reverse; + m_rd->m_fields[name]=temp; + } + + void GlobalRegister::printRegisters(std::ostream &os){ + os<<"Global Registers:"<<std::endl; + os<<"================="<<std::endl; + char line[128]; + for (int i=0;i<m_rd->N_W_REGS;i++){ + sprintf(line, "Register %d: %04x\n",i, m_regw[i]); + os<<line; + } + } + void GlobalRegister::printShadowRegisterAB(std::ostream &os){ + os<<"Shadow Register AB:"<<std::endl; + os<<"==================="<<std::endl; + char line[128]; + for (int i=0;i<m_rd->SRAB_BITS/16;i++){ + sprintf(line, "Bit %d - Bit %d: %04x\n",i*16+15, i*16, m_srab[i]); + os<<line; + } + } + void GlobalRegister::printShadowRegisterC(std::ostream &os){ + os<<"Shadow Register C:"<<std::endl; + os<<"==================="<<std::endl; + char line[128]; + for (int i=0;i<m_rd->SRC_BITS/16;i++){ + sprintf(line, "Bit %d - Bit %d: %04x\n",i*16+15, i*16, m_src[i]); + os<<line; + } + } + + unsigned GlobalRegister::decodeGlobalRecord(std::vector<unsigned> inpvec, int i, unsigned short& val){ + if(inpvec.size()==0)return FEI4ARecord::Empty; + unsigned char* bytepointer=(unsigned char*)&inpvec[0]; + size_t size=inpvec.size()*sizeof(unsigned); + unsigned char* last=bytepointer+size-3; + val=0xffff; + FEI4ARecord rec; + bool addrrec=false; + while(bytepointer<=last){ + rec.setRecord(bytepointer); + if(rec.isAddressRecord()){ // address record + if(!rec.isGlobal())return FEI4ARecord::NotGlobal; + if(rec.getAddress()!=(unsigned)i)return FEI4ARecord::WrongAddress; + std::cout<<"Read address record"<<std::endl; + addrrec=true; + }else if(addrrec==true){ + if(!rec.isValueRecord())return FEI4ARecord::BadAddrValSeq; // addr not immediately followed by val + std::cout<<"Value Record"<<std::endl; + val=rec.getValue(); + addrrec=false; + }else if(rec.isValueRecord()){ //val rec without addr rec + printf("Value record: %08x\n",rec.getUnsigned()); + val=rec.getValue(); + }else if(rec.isServiceRecord()){ + printf("Service record. Error code: %d. Count: %d \n",rec.getErrorCode(), rec.getErrorCount()); + }else if(rec.isEmptyRecord()){ + // do nothing + }else{ + std::cout<<"Unexpected record type."<<std::endl; + } + bytepointer+=3; + } + if(val==0xffff)return FEI4ARecord::NoValue; // no value record found. + return FEI4ARecord::OK; + } + +}; diff --git a/rce/rcecalib/config/FEI4/GlobalRegister.hh b/rce/rcecalib/config/FEI4/GlobalRegister.hh new file mode 100644 index 00000000..ec44033a --- /dev/null +++ b/rce/rcecalib/config/FEI4/GlobalRegister.hh @@ -0,0 +1,61 @@ +#ifndef GLOBALREGISTER_FEI4_HH +#define GLOBALREGISTER_FEI4_HH + +#include <map> +#include <string> +#include <vector> +#include "rcecalib/HW/SerialIF.hh" +#include "rcecalib/config/FEI4/RegisterDef.hh" + +namespace FEI4{ + +class FECommands; + + class GlobalRegister{ + public: + enum PulseReg{Efuse_sense=0x1, Stop_Clk=0x2, ReadErrorReq=0x4, ReadSkipped=0x8, + CalEn=0x20, SR_clr=0x40, Latch_en=0x80, SR_Clock=0x100, GADC_Start=0x200, SR_Read=0x400}; + enum mode{SW, HW}; + GlobalRegister(FECommands* commands); + virtual ~GlobalRegister(); + void setField(const char* name, unsigned val, mode t); + void setFieldFun(unsigned short* reg, int bitpos, int width, unsigned val); + unsigned getField(const char* name); + int getRegisterNumber(const char* name){ + if(m_rd->m_fields.find("name")==m_rd->m_fields.end())return -1; + return m_rd->m_fields[name].reg; + } + void writeHW(); + void writeRegisterHW(int i); + unsigned writeRegisterHW(int i, unsigned short val); + void disableThresholdHW(bool dis); + unsigned readRegisterHW(int i, unsigned short &val); + void readRegisterHW(int i); + int verifyConfigHW(std::vector<unsigned> &inpvec); + unsigned decodeGlobalRecord(std::vector<unsigned> inpvec, int i, unsigned short& val); + virtual void printFields(std::ostream &os)=0; + void printRegisters(std::ostream &os); + void printShadowRegisterAB(std::ostream &os); + void printShadowRegisterC(std::ostream &os); + void addField(const char* name, int reg, int bitpos, int srab, int src, int width, bool reverse); + void addParameter(const char* name, const char* field); + void enableSrHW(bool on); + std::string lookupParameter(const char* name); + // accessor function for daughter class's static members + virtual RegisterDef* getDef()=0; + + protected: + unsigned m_chipId; + bool m_clkOutMode; + FECommands* m_commands; + RegisterDef *m_rd; + unsigned short *m_regw;// write registers + unsigned short *m_regr;// readback + unsigned short *m_srab;//shadow register AB + unsigned short *m_src;// shadow register C + + }; + +}; + +#endif diff --git a/rce/rcecalib/config/FEI4/IPCFEI4AModule.cc b/rce/rcecalib/config/FEI4/IPCFEI4AModule.cc new file mode 100644 index 00000000..9c434d94 --- /dev/null +++ b/rce/rcecalib/config/FEI4/IPCFEI4AModule.cc @@ -0,0 +1,314 @@ +#ifndef FEI4__IPCMODULE_CC +#define FEI4__IPCMODULE_CC +#include "rcecalib/util/RceName.hh" +#include "rcecalib/config/FEI4/IPCFEI4AModule.hh" +#include "rcecalib/config/FEI4/FECommands.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/HW/SerialIF.hh" +#include "ipc/partition.h" +#include "ers/ers.h" +#include <boost/lexical_cast.hpp> + +namespace FEI4{ + +template <class TP> +IPCFEI4AModule<TP>::IPCFEI4AModule(IPCPartition & p, const char * name, unsigned id, unsigned inLink, unsigned outLink, AbsFormatter* fmt): + IPCNamedObject<POA_ipc::IPCFEI4AAdapter, TP>( p, std::string(boost::lexical_cast<std::string>(id)+"_RCE"+boost::lexical_cast<std::string>(RceName::getRceNumber())).c_str()) , + FEI4AModule(name, id, inLink, outLink, fmt){ + // std::cout<<"IPCFEI4AModule"<<std::endl; + try { + IPCNamedObject<POA_ipc::IPCFEI4AAdapter,TP>::publish(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } +} + +template <class TP> +IPCFEI4AModule<TP>::~IPCFEI4AModule(){ + try { + IPCNamedObject<POA_ipc::IPCFEI4AAdapter,TP>::withdraw(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::warning( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } +} + +template <class TP> +void IPCFEI4AModule<TP>::IPCsetChipAddress(CORBA::ULong addr){ + m_commands->setAddr(addr); +} +template <class TP> +CORBA::Long IPCFEI4AModule<TP>::IPCverifyModuleConfigHW(){ + return verifyModuleConfigHW(); +} +template <class TP> +CORBA::Long IPCFEI4AModule<TP>::IPCdownloadConfig(const ipc::PixelFEI4AConfig &config){ + // geographical address + m_gAddr=config.FECommand.address; + m_commands->setAddr(m_gAddr); + + + const ipc::PixelFEI4AGlobal *cfg=&config.FEGlobal; + // global register + m_global->setField("TrigCnt", cfg->TrigCnt , GlobalRegister::SW); + m_global->setField("Conf_AddrEnable", cfg->Conf_AddrEnable , GlobalRegister::SW); + m_global->setField("Reg2Spare", cfg->Reg2Spare , GlobalRegister::SW); + m_global->setField("ErrMask0", cfg->ErrMask0 , GlobalRegister::SW); + m_global->setField("ErrMask1", cfg->ErrMask1 , GlobalRegister::SW); + m_global->setField("PrmpVbpRight", cfg->PrmpVbpRight , GlobalRegister::SW); + m_global->setField("Vthin", cfg->Vthin , GlobalRegister::SW); + m_global->setField("DisVbn_CPPM", cfg->DisVbn_CPPM , GlobalRegister::SW); + m_global->setField("PrmpVbp", cfg->PrmpVbp , GlobalRegister::SW); + m_global->setField("TdacVbp", cfg->TdacVbp , GlobalRegister::SW); + m_global->setField("DisVbn", cfg->DisVbn , GlobalRegister::SW); + m_global->setField("Amp2Vbn", cfg->Amp2Vbn , GlobalRegister::SW); + m_global->setField("Amp2VbpFol", cfg->Amp2VbpFol , GlobalRegister::SW); + m_global->setField("PrmpVbpTop", cfg->PrmpVbpTop , GlobalRegister::SW); + m_global->setField("Amp2Vbp", cfg->Amp2Vbp , GlobalRegister::SW); + m_global->setField("FdacVbn", cfg->FdacVbn , GlobalRegister::SW); + m_global->setField("Amp2Vbpf", cfg->Amp2Vbpf , GlobalRegister::SW); + m_global->setField("PrmpVbnFol", cfg->PrmpVbnFol , GlobalRegister::SW); + m_global->setField("PrmpVbpLeft", cfg->PrmpVbpLeft , GlobalRegister::SW); + m_global->setField("PrmpVbpf", cfg->PrmpVbpf , GlobalRegister::SW); + m_global->setField("PrmpVbnLcc", cfg->PrmpVbnLcc , GlobalRegister::SW); + m_global->setField("PxStrobes", cfg->PxStrobes , GlobalRegister::SW); + m_global->setField("S0", cfg->S0 , GlobalRegister::SW); + m_global->setField("S1", cfg->S1 , GlobalRegister::SW); + m_global->setField("LVDSDrvIref", cfg->LVDSDrvIref , GlobalRegister::SW); + m_global->setField("BonnDac", cfg->BonnDac , GlobalRegister::SW); + m_global->setField("PllIbias", cfg->PllIbias , GlobalRegister::SW); + m_global->setField("LVDSDrvVos", cfg->LVDSDrvVos , GlobalRegister::SW); + m_global->setField("TempSensBias", cfg->TempSensBias , GlobalRegister::SW); + m_global->setField("PllIcp", cfg->PllIcp , GlobalRegister::SW); + m_global->setField("Reg17Spare", cfg->Reg17Spare , GlobalRegister::SW); + m_global->setField("PlsrIdacRamp", cfg->PlsrIdacRamp , GlobalRegister::SW); + m_global->setField("Reg18Spare", cfg->Reg18Spare , GlobalRegister::SW); + m_global->setField("PlsrVgOPamp", cfg->PlsrVgOPamp , GlobalRegister::SW); + m_global->setField("PlsrDacBias", cfg->PlsrDacBias , GlobalRegister::SW); + m_global->setField("Reg19Spare", cfg->Reg19Spare , GlobalRegister::SW); + m_global->setField("Vthin_AltCoarse", cfg->Vthin_AltCoarse , GlobalRegister::SW); + m_global->setField("Vthin_AltFine", cfg->Vthin_AltFine , GlobalRegister::SW); + m_global->setField("PlsrDAC", cfg->PlsrDAC , GlobalRegister::SW); + m_global->setField("DIGHITIN_Sel", cfg->DIGHITIN_Sel , GlobalRegister::SW); + m_global->setField("DINJ_Override", cfg->DINJ_Override , GlobalRegister::SW); + m_global->setField("HITLD_In", cfg->HITLD_In , GlobalRegister::SW); + m_global->setField("Reg21Spare", cfg->Reg21Spare , GlobalRegister::SW); + m_global->setField("Reg22Spare2", cfg->Reg22Spare2 , GlobalRegister::SW); + m_global->setField("Colpr_Addr", cfg->Colpr_Addr , GlobalRegister::SW); + m_global->setField("Colpr_Mode", cfg->Colpr_Mode , GlobalRegister::SW); + m_global->setField("DisableColumnCnfg0", cfg->DisableColumnCnfg0 , GlobalRegister::SW); + m_global->setField("DisableColumnCnfg1", cfg->DisableColumnCnfg1 , GlobalRegister::SW); + m_global->setField("DisableColumnCnfg2", cfg->DisableColumnCnfg2 , GlobalRegister::SW); + m_global->setField("TrigLat", cfg->TrigLat , GlobalRegister::SW); + m_global->setField("CMDcnt", cfg->CMDcnt , GlobalRegister::SW); + m_global->setField("StopModeCnfg", cfg->StopModeCnfg , GlobalRegister::SW); + m_global->setField("HitDiscCnfg", cfg->HitDiscCnfg , GlobalRegister::SW); + m_global->setField("EN_PLL", cfg->EN_PLL , GlobalRegister::SW); + m_global->setField("Efuse_sense", cfg->Efuse_sense , GlobalRegister::SW); + m_global->setField("Stop_Clk", cfg->Stop_Clk , GlobalRegister::SW); + m_global->setField("ReadErrorReq", cfg->ReadErrorReq , GlobalRegister::SW); + m_global->setField("ReadSkipped", cfg->ReadSkipped , GlobalRegister::SW); + m_global->setField("Reg27Spare", cfg->Reg27Spare , GlobalRegister::SW); + m_global->setField("GateHitOr", cfg->GateHitOr , GlobalRegister::SW); + m_global->setField("CalEn", cfg->CalEn , GlobalRegister::SW); + m_global->setField("SR_clr", cfg->SR_clr , GlobalRegister::SW); + m_global->setField("Latch_en", cfg->Latch_en , GlobalRegister::SW); + m_global->setField("SR_Clock", cfg->SR_Clock , GlobalRegister::SW); + m_global->setField("LVDSDrvSet06", cfg->LVDSDrvSet06 , GlobalRegister::SW); + m_global->setField("Reg28Spare", cfg->Reg28Spare , GlobalRegister::SW); + m_global->setField("EN40M", cfg->EN40M , GlobalRegister::SW); + m_global->setField("EN80M", cfg->EN80M , GlobalRegister::SW); + m_global->setField("CLK1", cfg->CLK1 , GlobalRegister::SW); + m_global->setField("CLK0", cfg->CLK0 , GlobalRegister::SW); + m_global->setField("EN160M", cfg->EN160M , GlobalRegister::SW); + m_global->setField("EN320M", cfg->EN320M , GlobalRegister::SW); + m_global->setField("Reg29Spare1", cfg->Reg29Spare1 , GlobalRegister::SW); + m_global->setField("no8b10b", cfg->no8b10b , GlobalRegister::SW); + m_global->setField("Clk2OutCnfg", cfg->Clk2OutCnfg , GlobalRegister::SW); + m_global->setField("EmptyRecord", cfg->EmptyRecord , GlobalRegister::SW); + m_global->setField("Reg29Spare2", cfg->Reg29Spare2 , GlobalRegister::SW); + m_global->setField("LVDSDrvEn", cfg->LVDSDrvEn , GlobalRegister::SW); + m_global->setField("LVDSDrvSet30", cfg->LVDSDrvSet30 , GlobalRegister::SW); + m_global->setField("LVDSDrvSet12", cfg->LVDSDrvSet12 , GlobalRegister::SW); + m_global->setField("PlsrRiseUpTau", cfg->PlsrRiseUpTau , GlobalRegister::SW); + m_global->setField("PlsrPwr", cfg->PlsrPwr , GlobalRegister::SW); + m_global->setField("PlsrDelay", cfg->PlsrDelay , GlobalRegister::SW); + m_global->setField("ExtDigCalSW", cfg->ExtDigCalSW , GlobalRegister::SW); + m_global->setField("ExtAnaCalSW", cfg->ExtAnaCalSW , GlobalRegister::SW); + m_global->setField("Reg31Spare", cfg->Reg31Spare , GlobalRegister::SW); + m_global->setField("SELB0", cfg->SELB0 , GlobalRegister::SW); + m_global->setField("SELB1", cfg->SELB1 , GlobalRegister::SW); + m_global->setField("SELB2", cfg->SELB2 , GlobalRegister::SW); + m_global->setField("EfuseCref", cfg->EfuseCref , GlobalRegister::SW); + m_global->setField("Chip_SN", cfg->Chip_SN , GlobalRegister::SW); + + setVcalCoeff(0, config.FECalib.vcalCoeff[0]); + setVcalCoeff(1, config.FECalib.vcalCoeff[1]); + setVcalCoeff(2, config.FECalib.vcalCoeff[2]); + setVcalCoeff(3, config.FECalib.vcalCoeff[3]); + setCapVal(0, config.FECalib.cinjLo); + setCapVal(1, config.FECalib.cinjHi); + + + for(int i=0;i<ipc::IPC_N_I4_PIXEL_COLUMNS;i++){ + for(int j=0;j<ipc::IPC_N_I4_PIXEL_ROWS;j++){ + //Pixel DACs + m_pixel->setField(PixelRegister::tdac, j+1, i+1, config.FETrims.dacThresholdTrim[i][j]); + m_pixel->setField(PixelRegister::fdac, j+1, i+1, config.FETrims.dacFeedbackTrim[i][j]); + //Mask bits + m_pixel->setField(PixelRegister::enable, j+1, i+1, config.FEMasks[i][j]>>ipc::enable); + m_pixel->setField(PixelRegister::largeCap, j+1, i+1, config.FEMasks[i][j]>>ipc::largeCap); + m_pixel->setField(PixelRegister::smallCap, j+1, i+1, config.FEMasks[i][j]>>ipc::smallCap); + m_pixel->setField(PixelRegister::hitbus, j+1, i+1, config.FEMasks[i][j]>>ipc::hitbus); + } + } + // Configure the formatter + boost::property_tree::ptree *pt=new boost::property_tree::ptree; + pt->put("HitDiscCnfg",cfg->HitDiscCnfg); + AbsFormatter* fmt=getFormatter(); + if(fmt){ + std::cout<<"%%%%%%%%% Configuring Formatter"<<std::endl; + fmt->configure(pt); + } + delete pt; + + std::cout<<"Configure done"<<std::endl; + //dumpConfig(); + return 0; +} + +template <class TP> +CORBA::ULong IPCFEI4AModule<TP>::IPCwriteHWglobalRegister(CORBA::Long reg, CORBA::UShort val){ + switchModeHW(FECommands::CONF); + SerialIF::setChannelInMask(1<<getInLink()); + SerialIF::setChannelOutMask(1<<getOutLink()); + return m_global->writeRegisterHW(reg, val); +} + +template <class TP> +CORBA::ULong IPCFEI4AModule<TP>::IPCreadHWglobalRegister(CORBA::Long reg, CORBA::UShort &val){ + SerialIF::setChannelInMask(1<<getInLink()); + SerialIF::setChannelOutMask(1<<getOutLink()); + return m_global->readRegisterHW(reg, val); +} +template <class TP> +CORBA::ULong IPCFEI4AModule<TP>::IPCclearPixelLatches(){ + SerialIF::setChannelInMask(1<<getInLink()); + // choose double column + m_global->setField("Colpr_Addr", 0, GlobalRegister::SW); + m_global->setField("Colpr_Mode", 3, GlobalRegister::HW); // all columns + setupS0S1HitldHW(0, 0, 0); + setupGlobalPulseHW(GlobalRegister::SR_clr); //latch enable + BitStream *bs=new BitStream; + m_commands->globalPulse(bs, FECommands::PULSE_WIDTH); + bs->push_back(0); + SerialIF::send(bs, SerialIF::DONT_CLEAR); //global pulse + //now clear latches + setupGlobalPulseHW(GlobalRegister::Latch_en); //latch enable + setupPixelStrobesHW(0x1fff); + SerialIF::send(bs, SerialIF::DONT_CLEAR); //global pulse + setupPixelStrobesHW(0);//clear register + setupGlobalPulseHW(0); //clear register + delete bs; + return 0; +} + + // Function to be called directly from Linux for debugging purposes. +template <class TP> +CORBA::ULong IPCFEI4AModule<TP>::IPCwriteDoubleColumnHW(CORBA::ULong bit, CORBA::ULong dcol, const ipc::uvec & data, ipc::uvec_out retv){ + // clear pixel latches + //IPCclearPixelLatches(); + //retv=new ipc::uvec; + //return 0; + SerialIF::setChannelInMask(1<<getInLink()); + SerialIF::setChannelOutMask(1<<getOutLink()); + std::vector<unsigned> retvec; + + if(data.length()!=PixelRegister::DROW_WORDS)return BAD_SIZE; //wrong amount of data + if(bit>=PixelRegister::N_PIXEL_REGISTER_BITS)return BAD_PIXREG; + + switchModeHW(FECommands::CONF); + + // choose double column + m_global->setField("Colpr_Addr", dcol, GlobalRegister::SW); + m_global->setField("Colpr_Mode", 0, GlobalRegister::HW); // only write to 1 column pair + setupS0S1HitldHW(0, 0, 0); + unsigned stat=m_pixel->writeDoubleColumnHW((const unsigned*)&data[0], retvec); + if(bit!=PixelRegisterFields::fieldPos[PixelRegister::diginj]){ //no latching for diginj + setupGlobalPulseHW(GlobalRegister::Latch_en); //latch enable + //set up strobe bit + setupPixelStrobesHW(1<<bit); + BitStream *bs=new BitStream; + m_commands->globalPulse(bs, FECommands::PULSE_WIDTH); + bs->push_back(0); + SerialIF::send(bs); //global pulse + delete bs; + setupGlobalPulseHW(0); //clear + setupPixelStrobesHW(0); //clear + } + retv=new ipc::uvec; + retv->length(retvec.size()); + for(size_t i=0;i<retvec.size();i++)retv[i]=(CORBA::ULong)retvec[i]; + return stat; +} + + // Function to be called directly from Linux for debugging purposes. +template <class TP> +CORBA::ULong IPCFEI4AModule<TP>::IPCreadDoubleColumnHW(CORBA::ULong bit, CORBA::ULong dcol, ipc::uvec_out retv){ + SerialIF::setChannelInMask(1<<getInLink()); + SerialIF::setChannelOutMask(1<<getOutLink()); + std::vector<unsigned> retvec; + if(bit>=PixelRegister::N_PIXEL_REGISTER_BITS)return BAD_PIXREG; + if(dcol>=PixelRegister::N_COLS/2)return BAD_DCOL; + // set config mode + switchModeHW(FECommands::CONF); + // choose double column + m_global->setField("Colpr_Addr", dcol, GlobalRegister::SW); + m_global->setField("Colpr_Mode", 0, GlobalRegister::HW); // only write to 1 column pair + if(bit!=PixelRegisterFields::fieldPos[PixelRegister::diginj]){ //no latching for diginj + setupS0S1HitldHW(1, 1, 0); + setupGlobalPulseHW(GlobalRegister::SR_Clock); //SR clock + //set up strobe bit + setupPixelStrobesHW(1<<bit); + BitStream *bs=new BitStream; + bs->push_back(0); + m_commands->globalPulse(bs, FECommands::PULSE_WIDTH); + SerialIF::send(bs); //global pulse + delete bs; + } + //shift out bits and refill with config register. + setupGlobalPulseHW(0); //clear + setupPixelStrobesHW(0); //clear + setupS0S1HitldHW(0, 0, 0); + unsigned stat=m_pixel->writeDoubleColumnHW((const unsigned*)m_pixel->getDoubleColumn(bit, dcol), retvec); + retv=new ipc::uvec; + retv->length(retvec.size()); + for(size_t i=0;i<retvec.size();i++)retv[i]=(CORBA::ULong)retvec[i]; + return stat; +} + +template <class TP> +void IPCFEI4AModule<TP>::shutdown(){ + std::cout<<"Shutdown"<<std::endl; +} + +template <class TP> +void IPCFEI4AModule<TP>::destroy(){ + this->_destroy(); +} + + + +}; + +#endif diff --git a/rce/rcecalib/config/FEI4/IPCFEI4AModule.hh b/rce/rcecalib/config/FEI4/IPCFEI4AModule.hh new file mode 100644 index 00000000..5df47ea3 --- /dev/null +++ b/rce/rcecalib/config/FEI4/IPCFEI4AModule.hh @@ -0,0 +1,32 @@ +#ifndef IPCFEI4AMODULE_HH +#define IPCFEI4AMODULE_HH + +#include "rcecalib/config/FEI4/FEI4AModule.hh" +#include "ipc/object.h" +#include "IPCFEI4AAdapter.hh" + +class IPCPartition; +class AbsFormatter; + +namespace FEI4{ +template <class TP = ipc::single_thread> +class IPCFEI4AModule: public IPCNamedObject<POA_ipc::IPCFEI4AAdapter,TP>, public FEI4::FEI4AModule { +public: + IPCFEI4AModule(IPCPartition & p, const char * name, unsigned id, unsigned inLink, unsigned outLink, AbsFormatter* fmt); + ~IPCFEI4AModule(); + CORBA::Long IPCdownloadConfig(const ipc::PixelFEI4AConfig &config); + void IPCsetChipAddress(CORBA::ULong addr); + CORBA::ULong IPCwriteHWglobalRegister(CORBA::Long reg, CORBA::UShort val); + CORBA::ULong IPCreadHWglobalRegister(CORBA::Long reg, CORBA::UShort &val); + CORBA::ULong IPCwriteDoubleColumnHW(CORBA::ULong bit, CORBA::ULong dcol, const ipc::uvec & data, ipc::uvec_out retv); + CORBA::ULong IPCreadDoubleColumnHW(CORBA::ULong bit, CORBA::ULong dcol, ipc::uvec_out retv); + CORBA::ULong IPCclearPixelLatches(); + CORBA::Long IPCverifyModuleConfigHW(); + void shutdown(); + void destroy(); + +}; +}; + + +#endif diff --git a/rce/rcecalib/config/FEI4/IPCFEI4BModule.cc b/rce/rcecalib/config/FEI4/IPCFEI4BModule.cc new file mode 100644 index 00000000..e8cbe8d0 --- /dev/null +++ b/rce/rcecalib/config/FEI4/IPCFEI4BModule.cc @@ -0,0 +1,331 @@ +#ifndef FEI4__FEI4BIPCMODULE_CC +#define FEI4__FEI4BIPCMODULE_CC +#include "rcecalib/util/RceName.hh" +#include "rcecalib/config/FEI4/IPCFEI4BModule.hh" +#include "rcecalib/config/FEI4/FECommands.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/HW/SerialIF.hh" +#include "ipc/partition.h" +#include "ers/ers.h" +#include <boost/lexical_cast.hpp> + + +namespace FEI4{ + +template <class TP> +IPCFEI4BModule<TP>::IPCFEI4BModule(IPCPartition & p, const char * name, unsigned id, unsigned inLink, unsigned outLink, AbsFormatter* fmt): + IPCNamedObject<POA_ipc::IPCFEI4BAdapter, TP>( p, std::string(boost::lexical_cast<std::string>(id)+"_RCE"+boost::lexical_cast<std::string>(RceName::getRceNumber())).c_str()) , + FEI4BModule(name, id, inLink, outLink, fmt){ + // std::cout<<"IPCFEI4BModule"<<std::endl; + try { + IPCNamedObject<POA_ipc::IPCFEI4BAdapter,TP>::publish(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } +} + +template <class TP> +IPCFEI4BModule<TP>::~IPCFEI4BModule(){ + try { + IPCNamedObject<POA_ipc::IPCFEI4BAdapter,TP>::withdraw(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::warning( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } +} + +template <class TP> +void IPCFEI4BModule<TP>::IPCsetChipAddress(CORBA::ULong addr){ + m_commands->setAddr(addr); +} +template <class TP> +CORBA::Long IPCFEI4BModule<TP>::IPCverifyModuleConfigHW(){ + return verifyModuleConfigHW(); +} +template <class TP> +CORBA::Long IPCFEI4BModule<TP>::IPCdownloadConfig(const ipc::PixelFEI4BConfig &config){ + // geographical address + m_gAddr=config.FECommand.address; + m_commands->setAddr(m_gAddr); + + const ipc::PixelFEI4BGlobal *cfg=&config.FEGlobal; + // global register + m_global->setField("TrigCnt", cfg->TrigCnt , GlobalRegister::SW); + m_global->setField("Conf_AddrEnable", cfg->Conf_AddrEnable , GlobalRegister::SW); + m_global->setField("Reg2Spare", cfg->Reg2Spare , GlobalRegister::SW); + m_global->setField("ErrMask0", cfg->ErrMask0 , GlobalRegister::SW); + m_global->setField("ErrMask1", cfg->ErrMask1 , GlobalRegister::SW); + m_global->setField("PrmpVbpRight", cfg->PrmpVbpRight , GlobalRegister::SW); + m_global->setField("BufVgOpAmp", cfg->BufVgOpAmp , GlobalRegister::SW); + m_global->setField("Reg6Spare", cfg->Reg6Spare , GlobalRegister::SW); + m_global->setField("PrmpVbp", cfg->PrmpVbp , GlobalRegister::SW); + m_global->setField("TdacVbp", cfg->TdacVbp , GlobalRegister::SW); + m_global->setField("DisVbn", cfg->DisVbn , GlobalRegister::SW); + m_global->setField("Amp2Vbn", cfg->Amp2Vbn , GlobalRegister::SW); + m_global->setField("Amp2VbpFol", cfg->Amp2VbpFol , GlobalRegister::SW); + m_global->setField("Reg9Spare", cfg->Reg9Spare , GlobalRegister::SW); + m_global->setField("Amp2Vbp", cfg->Amp2Vbp , GlobalRegister::SW); + m_global->setField("FdacVbn", cfg->FdacVbn , GlobalRegister::SW); + m_global->setField("Amp2Vbpf", cfg->Amp2Vbpf , GlobalRegister::SW); + m_global->setField("PrmpVbnFol", cfg->PrmpVbnFol , GlobalRegister::SW); + m_global->setField("PrmpVbpLeft", cfg->PrmpVbpLeft , GlobalRegister::SW); + m_global->setField("PrmpVbpf", cfg->PrmpVbpf , GlobalRegister::SW); + m_global->setField("PrmpVbnLcc", cfg->PrmpVbnLcc , GlobalRegister::SW); + m_global->setField("Reg13Spare", cfg->Reg13Spare , GlobalRegister::SW); + m_global->setField("PxStrobes", cfg->PxStrobes , GlobalRegister::SW); + m_global->setField("S0", cfg->S0 , GlobalRegister::SW); + m_global->setField("S1", cfg->S1 , GlobalRegister::SW); + m_global->setField("LVDSDrvIref", cfg->LVDSDrvIref , GlobalRegister::SW); + m_global->setField("GADCOpAmp", cfg->GADCOpAmp , GlobalRegister::SW); + m_global->setField("PllIbias", cfg->PllIbias , GlobalRegister::SW); + m_global->setField("LVDSDrvVos", cfg->LVDSDrvVos , GlobalRegister::SW); + m_global->setField("TempSensBias", cfg->TempSensBias , GlobalRegister::SW); + m_global->setField("PllIcp", cfg->PllIcp , GlobalRegister::SW); + m_global->setField("Reg17Spare", cfg->Reg17Spare , GlobalRegister::SW); + m_global->setField("PlsrIdacRamp", cfg->PlsrIdacRamp , GlobalRegister::SW); + m_global->setField("VrefDigTune", cfg->VrefDigTune , GlobalRegister::SW); + m_global->setField("PlsrVgOPamp", cfg->PlsrVgOPamp , GlobalRegister::SW); + m_global->setField("PlsrDacBias", cfg->PlsrDacBias , GlobalRegister::SW); + m_global->setField("VrefAnTune", cfg->VrefAnTune , GlobalRegister::SW); + m_global->setField("Vthin_AltCoarse", cfg->Vthin_AltCoarse , GlobalRegister::SW); + m_global->setField("Vthin_AltFine", cfg->Vthin_AltFine , GlobalRegister::SW); + m_global->setField("PlsrDAC", cfg->PlsrDAC , GlobalRegister::SW); + m_global->setField("DIGHITIN_Sel", cfg->DIGHITIN_Sel , GlobalRegister::SW); + m_global->setField("DINJ_Override", cfg->DINJ_Override , GlobalRegister::SW); + m_global->setField("HITLD_In", cfg->HITLD_In , GlobalRegister::SW); + m_global->setField("Reg21Spare", cfg->Reg21Spare , GlobalRegister::SW); + m_global->setField("Reg22Spare2", cfg->Reg22Spare2 , GlobalRegister::SW); + m_global->setField("Colpr_Addr", cfg->Colpr_Addr , GlobalRegister::SW); + m_global->setField("Colpr_Mode", cfg->Colpr_Mode , GlobalRegister::SW); + m_global->setField("Reg22Spare1", cfg->Reg22Spare1 , GlobalRegister::SW); + m_global->setField("DisableColumnCnfg0", cfg->DisableColumnCnfg0 , GlobalRegister::SW); + m_global->setField("DisableColumnCnfg1", cfg->DisableColumnCnfg1 , GlobalRegister::SW); + m_global->setField("DisableColumnCnfg2", cfg->DisableColumnCnfg2 , GlobalRegister::SW); + m_global->setField("TrigLat", cfg->TrigLat , GlobalRegister::SW); + m_global->setField("CMDcnt", cfg->CMDcnt , GlobalRegister::SW); + m_global->setField("StopModeCnfg", cfg->StopModeCnfg , GlobalRegister::SW); + m_global->setField("HitDiscCnfg", cfg->HitDiscCnfg , GlobalRegister::SW); + m_global->setField("EN_PLL", cfg->EN_PLL , GlobalRegister::SW); + m_global->setField("Efuse_sense", cfg->Efuse_sense , GlobalRegister::SW); + m_global->setField("Stop_Clk", cfg->Stop_Clk , GlobalRegister::SW); + m_global->setField("ReadErrorReq", cfg->ReadErrorReq , GlobalRegister::SW); + m_global->setField("Reg27Spare1", cfg->Reg27Spare1 , GlobalRegister::SW); + m_global->setField("GADC_Enable", cfg->GADC_Enable , GlobalRegister::SW); + m_global->setField("ShiftReadBack", cfg->ShiftReadBack , GlobalRegister::SW); + m_global->setField("Reg27Spare2", cfg->Reg27Spare2 , GlobalRegister::SW); + m_global->setField("GateHitOr", cfg->GateHitOr , GlobalRegister::SW); + m_global->setField("CalEn", cfg->CalEn , GlobalRegister::SW); + m_global->setField("SR_clr", cfg->SR_clr , GlobalRegister::SW); + m_global->setField("Latch_en", cfg->Latch_en , GlobalRegister::SW); + m_global->setField("SR_Clock", cfg->SR_Clock , GlobalRegister::SW); + m_global->setField("LVDSDrvSet06", cfg->LVDSDrvSet06 , GlobalRegister::SW); + m_global->setField("Reg28Spare", cfg->Reg28Spare , GlobalRegister::SW); + m_global->setField("EN40M", cfg->EN40M , GlobalRegister::SW); + m_global->setField("EN80M", cfg->EN80M , GlobalRegister::SW); + m_global->setField("CLK1", cfg->CLK1 , GlobalRegister::SW); + m_global->setField("CLK0", cfg->CLK0 , GlobalRegister::SW); + m_global->setField("EN160M", cfg->EN160M , GlobalRegister::SW); + m_global->setField("EN320M", cfg->EN320M , GlobalRegister::SW); + m_global->setField("Reg29Spare1", cfg->Reg29Spare1 , GlobalRegister::SW); + m_global->setField("no8b10b", cfg->no8b10b , GlobalRegister::SW); + m_global->setField("Clk2OutCnfg", cfg->Clk2OutCnfg , GlobalRegister::SW); + m_global->setField("EmptyRecord", cfg->EmptyRecord , GlobalRegister::SW); + m_global->setField("Reg29Spare2", cfg->Reg29Spare2 , GlobalRegister::SW); + m_global->setField("LVDSDrvEn", cfg->LVDSDrvEn , GlobalRegister::SW); + m_global->setField("LVDSDrvSet30", cfg->LVDSDrvSet30 , GlobalRegister::SW); + m_global->setField("LVDSDrvSet12", cfg->LVDSDrvSet12 , GlobalRegister::SW); + m_global->setField("TempSensDiodeSel", cfg->TempSensDiodeSel , GlobalRegister::SW); + m_global->setField("TempSensDisable", cfg->TempSensDisable , GlobalRegister::SW); + m_global->setField("IleakRange", cfg->IleakRange , GlobalRegister::SW); + m_global->setField("Reg30Spare", cfg->Reg30Spare , GlobalRegister::SW); + m_global->setField("PlsrRiseUpTau", cfg->PlsrRiseUpTau , GlobalRegister::SW); + m_global->setField("PlsrPwr", cfg->PlsrPwr , GlobalRegister::SW); + m_global->setField("PlsrDelay", cfg->PlsrDelay , GlobalRegister::SW); + m_global->setField("ExtDigCalSW", cfg->ExtDigCalSW , GlobalRegister::SW); + m_global->setField("ExtAnaCalSW", cfg->ExtAnaCalSW , GlobalRegister::SW); + m_global->setField("Reg31Spare", cfg->Reg31Spare , GlobalRegister::SW); + m_global->setField("GADCSel", cfg->GADCSel , GlobalRegister::SW); + m_global->setField("SELB0", cfg->SELB0 , GlobalRegister::SW); + m_global->setField("SELB1", cfg->SELB1 , GlobalRegister::SW); + m_global->setField("SELB2", cfg->SELB2 , GlobalRegister::SW); + m_global->setField("Reg34Spare1", cfg->Reg34Spare1 , GlobalRegister::SW); + m_global->setField("PrmpVbpMsnEn", cfg->PrmpVbpMsnEn , GlobalRegister::SW); + m_global->setField("Reg34Spare2", cfg->Reg34Spare2 , GlobalRegister::SW); + m_global->setField("Chip_SN", cfg->Chip_SN , GlobalRegister::SW); + m_global->setField("Reg1Spare", cfg->Reg1Spare , GlobalRegister::SW); + m_global->setField("SmallHitErase", cfg->SmallHitErase , GlobalRegister::SW); + m_global->setField("Eventlimit", cfg->Eventlimit , GlobalRegister::SW); + + setVcalCoeff(0, config.FECalib.vcalCoeff[0]); + setVcalCoeff(1, config.FECalib.vcalCoeff[1]); + setVcalCoeff(2, config.FECalib.vcalCoeff[2]); + setVcalCoeff(3, config.FECalib.vcalCoeff[3]); + setCapVal(0, config.FECalib.cinjLo); + setCapVal(1, config.FECalib.cinjHi); + + + for(int i=0;i<ipc::IPC_N_I4_PIXEL_COLUMNS;i++){ + for(int j=0;j<ipc::IPC_N_I4_PIXEL_ROWS;j++){ + //Pixel DACs + m_pixel->setField(PixelRegister::tdac, j+1, i+1, config.FETrims.dacThresholdTrim[i][j]); + m_pixel->setField(PixelRegister::fdac, j+1, i+1, config.FETrims.dacFeedbackTrim[i][j]); + //Mask bits + m_pixel->setField(PixelRegister::enable, j+1, i+1, config.FEMasks[i][j]>>ipc::enable); + m_pixel->setField(PixelRegister::largeCap, j+1, i+1, config.FEMasks[i][j]>>ipc::largeCap); + m_pixel->setField(PixelRegister::smallCap, j+1, i+1, config.FEMasks[i][j]>>ipc::smallCap); + m_pixel->setField(PixelRegister::hitbus, j+1, i+1, config.FEMasks[i][j]>>ipc::hitbus); + } + } + // Configure the formatter + AbsFormatter* fmt=getFormatter(); + if(fmt){ + std::cout<<"%%%%%%%%% Configuring Formatter"<<std::endl; + boost::property_tree::ptree *pt=new boost::property_tree::ptree; + pt->put("HitDiscCnfg",cfg->HitDiscCnfg); + fmt->configure(pt); + delete pt; + } + + std::cout<<"Configure done"<<std::endl; + //dumpConfig(std::cout); + return 0; +} + +template <class TP> +CORBA::ULong IPCFEI4BModule<TP>::IPCwriteHWglobalRegister(CORBA::Long reg, CORBA::UShort val){ + switchModeHW(FECommands::CONF); + SerialIF::setChannelInMask(1<<getInLink()); + SerialIF::setChannelOutMask(1<<getOutLink()); + return m_global->writeRegisterHW(reg, val); +} + +template <class TP> +CORBA::ULong IPCFEI4BModule<TP>::IPCreadHWglobalRegister(CORBA::Long reg, CORBA::UShort &val){ + SerialIF::setChannelInMask(1<<getInLink()); + SerialIF::setChannelOutMask(1<<getOutLink()); + return m_global->readRegisterHW(reg, val); +} +template <class TP> +CORBA::ULong IPCFEI4BModule<TP>::IPCclearPixelLatches(){ + SerialIF::setChannelInMask(1<<getInLink()); + // choose double column + m_global->setField("Colpr_Addr", 0, GlobalRegister::SW); + m_global->setField("Colpr_Mode", 3, GlobalRegister::HW); // all columns + setupS0S1HitldHW(0, 0, 0); + setupGlobalPulseHW(GlobalRegister::SR_clr); //latch enable + BitStream *bs=new BitStream; + m_commands->globalPulse(bs, FECommands::PULSE_WIDTH); + bs->push_back(0); + SerialIF::send(bs, SerialIF::DONT_CLEAR); //global pulse + //now clear latches + setupGlobalPulseHW(GlobalRegister::Latch_en); //latch enable + setupPixelStrobesHW(0x1fff); + SerialIF::send(bs, SerialIF::DONT_CLEAR); //global pulse + setupPixelStrobesHW(0);//clear register + setupGlobalPulseHW(0); //clear register + delete bs; + return 0; +} + + // Function to be called directly from Linux for debugging purposes. +template <class TP> +CORBA::ULong IPCFEI4BModule<TP>::IPCwriteDoubleColumnHW(CORBA::ULong bit, CORBA::ULong dcol, const ipc::uvec & data, ipc::uvec_out retv){ + // clear pixel latches + //IPCclearPixelLatches(); + //retv=new ipc::uvec; + //return 0; + SerialIF::setChannelInMask(1<<getInLink()); + SerialIF::setChannelOutMask(1<<getOutLink()); + std::vector<unsigned> retvec; + + if(data.length()!=PixelRegister::DROW_WORDS)return BAD_SIZE; //wrong amount of data + if(bit>=PixelRegister::N_PIXEL_REGISTER_BITS)return BAD_PIXREG; + + switchModeHW(FECommands::CONF); + + // choose double column + m_global->setField("Colpr_Addr", dcol, GlobalRegister::SW); + m_global->setField("Colpr_Mode", 0, GlobalRegister::HW); // only write to 1 column pair + m_global->setField("ShiftReadBack",0, GlobalRegister::HW); + setupS0S1HitldHW(0, 0, 0); + unsigned stat=m_pixel->writeDoubleColumnHW((const unsigned*)&data[0], retvec); + if(bit!=PixelRegisterFields::fieldPos[PixelRegister::diginj]){ //no latching for diginj + setupGlobalPulseHW(GlobalRegister::Latch_en); //latch enable + //set up strobe bit + setupPixelStrobesHW(1<<bit); + BitStream *bs=new BitStream; + m_commands->globalPulse(bs, FECommands::PULSE_WIDTH); + bs->push_back(0); + SerialIF::send(bs); //global pulse + delete bs; + setupGlobalPulseHW(0); //clear + setupPixelStrobesHW(0); //clear + } + retv=new ipc::uvec; + retv->length(retvec.size()); + for(size_t i=0;i<retvec.size();i++)retv[i]=(CORBA::ULong)retvec[i]; + return stat; +} + + // Function to be called directly from Linux for debugging purposes. +template <class TP> +CORBA::ULong IPCFEI4BModule<TP>::IPCreadDoubleColumnHW(CORBA::ULong bit, CORBA::ULong dcol, ipc::uvec_out retv){ + SerialIF::setChannelInMask(1<<getInLink()); + SerialIF::setChannelOutMask(1<<getOutLink()); + std::vector<unsigned> retvec; + if(bit>=PixelRegister::N_PIXEL_REGISTER_BITS)return BAD_PIXREG; + if(dcol>=PixelRegister::N_COLS/2)return BAD_DCOL; + // set config mode + switchModeHW(FECommands::CONF); + // choose double column + m_global->setField("Colpr_Addr", dcol, GlobalRegister::SW); + m_global->setField("Colpr_Mode", 0, GlobalRegister::HW); // only write to 1 column pair + m_global->setField("ShiftReadBack",1, GlobalRegister::HW); //enable readback + if(bit!=PixelRegisterFields::fieldPos[PixelRegister::diginj]){ //no latching for diginj + setupS0S1HitldHW(1, 1, 0); + setupGlobalPulseHW(GlobalRegister::SR_Clock); //SR clock + //set up strobe bit + setupPixelStrobesHW(1<<bit); + BitStream *bs=new BitStream; + bs->push_back(0); + m_commands->globalPulse(bs, FECommands::PULSE_WIDTH); + SerialIF::send(bs); //global pulse + delete bs; + } + //shift out bits and refill with config register. + m_global->setField("ShiftReadBack",0, GlobalRegister::SW); //setupGlobalPulse does the HW write for that register + setupGlobalPulseHW(0); //clear + setupPixelStrobesHW(0); //clear + setupS0S1HitldHW(0, 0, 0); + unsigned stat=m_pixel->writeDoubleColumnHW((const unsigned*)m_pixel->getDoubleColumn(bit, dcol), retvec); + retv=new ipc::uvec; + retv->length(retvec.size()); + for(size_t i=0;i<retvec.size();i++)retv[i]=(CORBA::ULong)retvec[i]; + return stat; +} + +template <class TP> +void IPCFEI4BModule<TP>::shutdown(){ + std::cout<<"Shutdown"<<std::endl; +} + +template <class TP> +void IPCFEI4BModule<TP>::destroy(){ + this->_destroy(); +} + + + +}; + +#endif diff --git a/rce/rcecalib/config/FEI4/IPCFEI4BModule.hh b/rce/rcecalib/config/FEI4/IPCFEI4BModule.hh new file mode 100644 index 00000000..d521b276 --- /dev/null +++ b/rce/rcecalib/config/FEI4/IPCFEI4BModule.hh @@ -0,0 +1,32 @@ +#ifndef IPCFEI4BMODULE_HH +#define IPCFEI4BMODULE_HH + +#include "rcecalib/config/FEI4/FEI4BModule.hh" +#include "ipc/object.h" +#include "IPCFEI4BAdapter.hh" + +class IPCPartition; +class AbsFormatter; + +namespace FEI4{ +template <class TP = ipc::single_thread> +class IPCFEI4BModule: public IPCNamedObject<POA_ipc::IPCFEI4BAdapter,TP>, public FEI4::FEI4BModule { +public: + IPCFEI4BModule(IPCPartition & p, const char * name, unsigned id, unsigned inLink, unsigned outLink, AbsFormatter* fmt); + ~IPCFEI4BModule(); + CORBA::Long IPCdownloadConfig(const ipc::PixelFEI4BConfig &config); + void IPCsetChipAddress(CORBA::ULong addr); + CORBA::ULong IPCwriteHWglobalRegister(CORBA::Long reg, CORBA::UShort val); + CORBA::ULong IPCreadHWglobalRegister(CORBA::Long reg, CORBA::UShort &val); + CORBA::ULong IPCwriteDoubleColumnHW(CORBA::ULong bit, CORBA::ULong dcol, const ipc::uvec & data, ipc::uvec_out retv); + CORBA::ULong IPCreadDoubleColumnHW(CORBA::ULong bit, CORBA::ULong dcol, ipc::uvec_out retv); + CORBA::ULong IPCclearPixelLatches(); + CORBA::Long IPCverifyModuleConfigHW(); + void shutdown(); + void destroy(); + +}; +}; + + +#endif diff --git a/rce/rcecalib/config/FEI4/MaskStageFactory.cc b/rce/rcecalib/config/FEI4/MaskStageFactory.cc new file mode 100644 index 00000000..1f34bc28 --- /dev/null +++ b/rce/rcecalib/config/FEI4/MaskStageFactory.cc @@ -0,0 +1,149 @@ +#include "rcecalib/config/MaskStageFactory.hh" +#include "rcecalib/config/FEI4/Module.hh" +#include "rcecalib/config/FEI4/PixelRegister.hh" +#include "rcecalib/config/FEI4/AnalogMaskStaging.hh" +#include "rcecalib/config/FEI4/FastAnalogMaskStaging.hh" +#include "rcecalib/config/FEI4/AnalogSingleMaskStaging.hh" +#include "rcecalib/config/FEI4/AnalogColprMaskStaging.hh" +#include "rcecalib/config/FEI4/AnalogSimpleColprMaskStaging.hh" +#include "rcecalib/config/FEI4/AnalogColpr2MaskStagingFei4a.hh" +#include "rcecalib/config/FEI4/DigitalMaskStaging.hh" +#include "rcecalib/config/FEI4/DigStepMaskStaging.hh" +#include "rcecalib/config/FEI4/CrosstalkMaskStaging.hh" +#include "rcecalib/config/FEI4/CrosstalkFastMaskStaging.hh" +#include "rcecalib/config/FEI4/NoiseMaskStaging.hh" +#include "rcecalib/config/FEI4/DiffusionMaskStaging.hh" +#include "rcecalib/config/FEI4/ModuleCrosstalkMaskStaging.hh" +#include "rcecalib/config/FEI4/MaskStaging26880.hh" +#include "rcecalib/config/FEI4/PatternMaskStaging.hh" +#include "rcecalib/config/Masks.hh" +#include <assert.h> +#include <string> + +using namespace FEI4; + +template<> Masks MaskStageFactory::createIOmasks<FEI4::Module>(const char* maskStagingMode){ + Masks m; + m.oMask=m.iMask=m.xtalk_on=m.xtalk_off=m.crosstalking=0; + std::string stagingMode(maskStagingMode); + if(stagingMode=="FEI4_ENA_NOCAP"){ + m.oMask=(1<<PixelRegisterFields::fieldPos[PixelRegister::enable]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::largeCap]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::smallCap]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::diginj]); + + m.iMask=(1<<PixelRegisterFields::fieldPos[PixelRegister::enable]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::diginj]); + } else if(std::string(stagingMode)=="FEI4_ENA_SCAP"){ + m.oMask=(1<<PixelRegisterFields::fieldPos[PixelRegister::enable]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::diginj]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::smallCap]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::largeCap]); + + m.iMask=(1<<PixelRegisterFields::fieldPos[PixelRegister::enable]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::smallCap]); + } else if(std::string(stagingMode)=="FEI4_ENA_LCAP"){ + m.oMask=(1<<PixelRegisterFields::fieldPos[PixelRegister::enable]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::diginj]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::smallCap]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::largeCap]); + + m.iMask=(1<<PixelRegisterFields::fieldPos[PixelRegister::enable]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::largeCap]); + } else if(std::string(stagingMode)=="FEI4_ENA_BCAP"){ + m.oMask=(1<<PixelRegisterFields::fieldPos[PixelRegister::enable]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::diginj]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::smallCap]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::largeCap]); + + m.iMask=(1<<PixelRegisterFields::fieldPos[PixelRegister::enable]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::smallCap]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::largeCap]); + } else if(std::string(stagingMode)=="FEI4_ENA_HITBUS_DIG"){ + PixelRegister::setHitBusMode(1); + m.oMask=(1<<PixelRegisterFields::fieldPos[PixelRegister::enable]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::largeCap]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::smallCap]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::diginj]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::hitbus]); + + m.iMask=(1<<PixelRegisterFields::fieldPos[PixelRegister::enable]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::diginj]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::hitbus]); + } else if(std::string(stagingMode)=="FEI4_ENA_HITBUS"){ + PixelRegister::setHitBusMode(1); + m.oMask=(1<<PixelRegisterFields::fieldPos[PixelRegister::enable]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::diginj]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::hitbus]); + + m.iMask=(1<<PixelRegisterFields::fieldPos[PixelRegister::enable]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::hitbus]); + } else if(std::string(stagingMode)=="FEI4_MONLEAK"){ + PixelRegister::setHitBusMode(0); + m.oMask=(1<<PixelRegisterFields::fieldPos[PixelRegister::enable]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::diginj]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::hitbus]); + + m.iMask=(1<<PixelRegisterFields::fieldPos[PixelRegister::enable]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::hitbus]); + } else if(std::string(stagingMode)=="FEI4_XTALK"){ + m.crosstalking = 1; + m.oMask=(1<<PixelRegisterFields::fieldPos[PixelRegister::enable]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::diginj]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::hitbus]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::smallCap]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::largeCap]); + + m.xtalk_off=(1<<PixelRegisterFields::fieldPos[PixelRegister::smallCap]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::largeCap]); + m.xtalk_on=(1<<PixelRegisterFields::fieldPos[PixelRegister::enable]); + } else if(std::string(stagingMode)=="FEI4_NOISE"){ + m.oMask=(1<<PixelRegisterFields::fieldPos[PixelRegister::enable]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::largeCap]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::smallCap]) + | (1<<PixelRegisterFields::fieldPos[PixelRegister::diginj]); + + m.iMask=(1<<PixelRegisterFields::fieldPos[PixelRegister::enable]); + }else{ + std::cout<<"Mask stage mode "<<stagingMode<<" does not exist."<<std::endl; + m.oMask=0; + m.iMask=0; + } + return m; +} + +template<> +MaskStaging<FEI4::Module>* MaskStageFactory::createMaskStaging(FEI4::Module* mod, const char* maskStagingType, const char* maskStagingMode){ + Masks iomask=createIOmasks<FEI4::Module>(maskStagingMode); + std::string stagingType(maskStagingType); + if(stagingType=="FEI4_COL_ANL_40" || stagingType=="FEI4_COL_ANL_40x8") + return new FEI4::AnalogMaskStaging(mod, iomask, stagingType); + else if(stagingType=="FEI4_COL_DIG_40") + return new FEI4::DigitalMaskStaging(mod, iomask, stagingType); + else if(stagingType=="FEI4_26880") + return new FEI4::MaskStaging26880(mod, iomask, stagingType); + else if(stagingType.substr(0,6)=="STEPS_") + return new FEI4::DigStepMaskStaging(mod, iomask, stagingType); + else if(stagingType=="FEI4_XTALK_26880") + return new FEI4::CrosstalkMaskStaging(mod, iomask, stagingType); + else if(stagingType=="FEI4_XTALK_40x8") + return new FEI4::CrosstalkFastMaskStaging(mod, iomask, stagingType); + else if(stagingType=="FEI4_DIFFUSION") + return new FEI4::DiffusionMaskStaging(mod, iomask, stagingType); + else if(stagingType=="FEI4_ALLCOLS") + return new FEI4::NoiseMaskStaging(mod, iomask, stagingType); + else if(stagingType=="FEI4_COL_ANL_1") + return new FEI4::AnalogSingleMaskStaging(mod, iomask, stagingType); + else if(stagingType=="FEI4_COLPR2x6FEI4A") + return new FEI4::AnalogColpr2MaskStagingFei4a(mod, iomask, stagingType); + else if(stagingType.substr(0,10)=="FEI4_COLPR") + return new FEI4::AnalogColprMaskStaging(mod, iomask, stagingType); + else if(stagingType=="FEI4_MODULECROSSTALK") + return new FEI4::ModuleCrosstalkMaskStaging(mod, iomask, stagingType); + else if(stagingType=="FEI4_PATTERN") + return new FEI4::PatternMaskStaging(mod, iomask, stagingType); + else{ + std::cout<<"Wrong staging type "<<stagingType<<std::endl; + assert(0); + } +} diff --git a/rce/rcecalib/config/FEI4/MaskStaging.cc b/rce/rcecalib/config/FEI4/MaskStaging.cc new file mode 100644 index 00000000..3b69ae25 --- /dev/null +++ b/rce/rcecalib/config/FEI4/MaskStaging.cc @@ -0,0 +1,27 @@ +#include "rcecalib/config/MaskStaging.hh" +#include "rcecalib/config/FEI4/Module.hh" + +using namespace FEI4; + +template<> bool MaskStaging<FEI4::Module>::cLow(){ + if (m_masks.crosstalking==0) + return (m_masks.iMask&(1<<FEI4::PixelRegisterFields::fieldPos[FEI4::PixelRegister::smallCap]))!=0; + else + return (m_masks.xtalk_off&(1<<FEI4::PixelRegisterFields::fieldPos[FEI4::PixelRegister::smallCap]))!=0; +} +template<> bool MaskStaging<FEI4::Module>::cHigh(){ + if(m_masks.crosstalking==0) + return (m_masks.iMask&(1<<FEI4::PixelRegisterFields::fieldPos[FEI4::PixelRegister::largeCap]))!=0; + else + return (m_masks.xtalk_off&(1<<FEI4::PixelRegisterFields::fieldPos[FEI4::PixelRegister::largeCap]))!=0; +} + +template<> void MaskStaging<FEI4::Module>::clearBitsHW(){ + m_module->global()->setField("Colpr_Mode", 3, GlobalRegister::SW); + for(int i=0;i<PixelRegister::N_PIXEL_REGISTER_BITS;i++){ + if(m_masks.oMask&(1<<i)){ + m_module->pixel()->setBitAll(i,0); + m_module->writeDoubleColumnHW(i,i,0,0); + } + } +} diff --git a/rce/rcecalib/config/FEI4/MaskStaging26880.cc b/rce/rcecalib/config/FEI4/MaskStaging26880.cc new file mode 100644 index 00000000..0834ba1e --- /dev/null +++ b/rce/rcecalib/config/FEI4/MaskStaging26880.cc @@ -0,0 +1,33 @@ +#include "rcecalib/config/FEI4/MaskStaging26880.hh" +#include "rcecalib/config/FEI4/Module.hh" + +namespace FEI4{ + + MaskStaging26880::MaskStaging26880(FEI4::Module* mod, Masks masks, std::string type) + :MaskStaging<FEI4::Module>(mod, masks, type){ + } + + void MaskStaging26880::setupMaskStageHW(int maskStage){ + if(m_initialized==false || maskStage==0){ + clearBitsHW(); + m_initialized=true; + } + PixelRegister* pixel=m_module->pixel(); + GlobalRegister* global=m_module->global(); + unsigned rowstage=maskStage%PixelRegister::N_ROWS; + unsigned colstage=maskStage/PixelRegister::N_ROWS; + global->setField("Colpr_Mode", 0, GlobalRegister::SW); + for(int i=0;i<PixelRegister::N_PIXEL_REGISTER_BITS;i++){ + if(m_masks.iMask&(1<<i)){ + if(rowstage==0&&colstage!=0){ + pixel->setBitCol(colstage, i, 0); + m_module->writeDoubleColumnHW(i, i, (colstage-1)/2, (colstage-1)/2); + } + pixel->setupMaskStageCol(colstage+1, i, rowstage, PixelRegister::N_ROWS); + // m_pixel->dumpDoubleColumn(i,colstage/2,std::cout); + m_module->writeDoubleColumnHW(i, i, colstage/2, colstage/2); + } + } + global->setField("Colpr_Mode", 3, GlobalRegister::SW); + } +} diff --git a/rce/rcecalib/config/FEI4/MaskStaging26880.hh b/rce/rcecalib/config/FEI4/MaskStaging26880.hh new file mode 100644 index 00000000..0961badc --- /dev/null +++ b/rce/rcecalib/config/FEI4/MaskStaging26880.hh @@ -0,0 +1,16 @@ +#ifndef FEI426880MASKSTAGING_HH +#define FEI426880MASKSTAGING_HH + +#include "rcecalib/config/Masks.hh" +#include "rcecalib/config/MaskStaging.hh" + +namespace FEI4{ + class Module; + class MaskStaging26880: public MaskStaging<FEI4::Module>{ + public: + MaskStaging26880(FEI4::Module* module, Masks masks, std::string type); + void setupMaskStageHW(int maskStage); + }; + +} +#endif diff --git a/rce/rcecalib/config/FEI4/Module.cc b/rce/rcecalib/config/FEI4/Module.cc new file mode 100644 index 00000000..8b84e4e8 --- /dev/null +++ b/rce/rcecalib/config/FEI4/Module.cc @@ -0,0 +1,332 @@ +#include "rcecalib/config/FEI4/Module.hh" +#include "rcecalib/HW/BitStream.hh" +#include "rcecalib/config/FEI4/FECommands.hh" +#include "rcecalib/config/MaskStageFactory.hh" +#include "rcecalib/HW/SerialIF.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/util/exceptions.hh" +#include <iostream> +#include <fstream> +#include "ers/ers.h" +#include <stdio.h> + +namespace FEI4{ + + Module::Module(const char* name, unsigned id, unsigned inlink, unsigned outlink, AbsFormatter* fmt): + AbsModule(name, id, inlink, outlink, fmt), m_mode(FRAMED), m_maskStaging(0), m_gAddr(-1), m_oneByOne(false){ + // std::cout<<"Module"<<std::endl; + } + Module::~Module(){ + delete m_maskStaging; + //m_timer.Print("Module"); + } + void Module::setupS0S1HitldHW(int s0, int s1, int hitld){ + m_global->setField("S0",s0, GlobalRegister::SW); + m_global->setField("S1",s1, GlobalRegister::HW); //S0 is in the same register + if(m_oneByOne)m_global->setField("HITLD_In",hitld, GlobalRegister::HW); + } + + void Module::setupPixelStrobesHW(unsigned bitmask){ + m_global->setField("PxStrobes",bitmask, GlobalRegister::HW); + } + + // void Frontend::pixelUsrToRaw(BitStream *bs, unsigned bit){ + // } + void Module::setVcalCoeff(unsigned i, float val){ + if(i<4)m_vcalCoeff[i]=val; + } + void Module::setCapVal(unsigned i, float val){ + if(i<2)m_capVal[i]=val; + } + float Module::getVcalCoeff(unsigned i){ + if(i<4)return m_vcalCoeff[i]; + else return -999; + } + float Module::getCapVal(unsigned i){ + if(i<2)return m_capVal[i]; + else return -999; + } + + // TODO: get rid of float + const float Module::dacToElectrons(int fe, int dac){ + if(fe!=0)return -1; + float capacity=6241 * (m_capVal[1]*m_maskStaging->cHigh() + m_capVal[0]*m_maskStaging->cLow()); + float fldac=(float)dac; + //std::cout<<"dac "<<dac<<" electrons "<<capacity*(m_vcalCoeff[0] + (m_vcalCoeff[1] + (m_vcalCoeff[2] + m_vcalCoeff[3]*fldac)*fldac)*fldac)<<std::endl; + return capacity*(m_vcalCoeff[0] + (m_vcalCoeff[1] + (m_vcalCoeff[2] + m_vcalCoeff[3]*fldac)*fldac)*fldac); + } + const int Module::electronsToDac(float ne) { + float min=10000.; + int mini=-1; + for(int i=0;i<1024;i++) { + float diff=(ne-dacToElectrons(0, i)); + if(diff<0.) diff=-diff; + if(diff<min) { + min=diff;mini=i; + } + } + if(mini==-1){ + std::cout<<"WARNING: electronsToDac returning -1 !!"<<std::endl; + } + return mini; + } + + void Module::enableSrHW(bool on){ + //std::cout<<"Switched SR to "<<on<<" for FE "<<getId()<<std::endl; + m_global->enableSrHW(on); + } + + void Module::configureHW(){ + //std::cout<<"Configured HW FE "<<getId()<<std::endl; + // m_global->printFields(std::cout); + resetHW(); + m_global->disableThresholdHW(true); + m_global->writeHW(); + m_global->setField("Colpr_Mode", 0, GlobalRegister::SW); // only write to 1 column pair at a time + writeDoubleColumnHW(0, PixelRegister::N_PIXEL_REGISTER_BITS-1, 0, PixelRegister::N_COLS/2-1); + m_global->disableThresholdHW(false); + //std::ofstream dump("/nfs/cosmicData/out.log"); + //dumpConfig(dump); + //dump.close(); + //SerialIF::writeRegister(13,1); + } + + void Module::resetFE(){ + resetHW(); + } + void Module::resetErrorCountersHW(){ + //std::cout<<"Reset error counters FE "<<getId()<<std::endl; + BitStream *bs=new BitStream; + m_commands->globalPulse(bs, FECommands::PULSE_WIDTH); + setupGlobalPulseHW(GlobalRegister::ReadErrorReq); //Read and clear errors + SerialIF::send(bs, SerialIF::WAITFORDATA); //global pulse + setupGlobalPulseHW(0); //Clear + delete bs; + } + + void Module::enableDataTakingHW(){ + //std::cout<<"Enabled data taking FE "<<getId()<<std::endl; + BitStream *bs=new BitStream; + BitStreamUtils::prependZeros(bs); + m_commands->switchMode(bs, FECommands::RUN); + m_commands->sendECR(bs); + m_commands->sendBCR(bs); + SerialIF::send(bs); + delete bs; + } + + void Module::switchToConfigModeHW(){ + //std::cout<<"Switched to Config Mode FE "<<getId()<<std::endl; + switchModeHW(FECommands::CONF); + } + + void Module::switchModeHW(FECommands::MODE mode){ + BitStream *bs=new BitStream; + m_commands->switchMode(bs, mode); + bs->push_back(0); + SerialIF::send(bs, SerialIF::WAITFORDATA); + delete bs; + } + + void Module::writeDoubleColumnHW(unsigned bitLow, unsigned bitHigh, unsigned dcolLow, unsigned dcolHigh){ + BitStream *bs=new BitStream; + m_commands->globalPulse(bs, FECommands::PULSE_WIDTH); + setupS0S1HitldHW(0, 0, 0); + setupGlobalPulseHW(GlobalRegister::Latch_en); //latch enable + for (unsigned i=bitLow; i<=bitHigh;i++){ + //set up strobe bit + setupPixelStrobesHW(1<<i); + for(unsigned j=dcolLow; j<=dcolHigh; j++){ + // std::cout<<"Dcol "<<j<<std::endl; + //set up dcol + m_global->setField("Colpr_Addr", j, GlobalRegister::HW); + m_commands->setAddr(m_gAddr|0x8); + m_pixel->writeDoubleColumnHW(i, j); + m_commands->setAddr(m_gAddr); + if(i!=PixelRegisterFields::fieldPos[PixelRegister::diginj]){ //no latching for diginj + SerialIF::send(bs, SerialIF::DONT_CLEAR|SerialIF::WAITFORDATA); //global pulse + } + } + } + setupGlobalPulseHW(0); //clear + setupPixelStrobesHW(0); //clear + + delete bs; + } + + + void Module::setupMaskStageHW(int maskStage) { + //std::cout<<"Mask stage "<<maskStage<<" FE "<<getId()<<std::endl; + if(m_oneByOne==false && maskStage==0 && m_global->getField("HITLD_In")==1){ //HITLD_In is a problem with broadcast + std::cout<<"Module with ID="<<m_id<<" has HITLD_In enabled. Either disable the field or run in one-by-one mode."<<std::endl; + assert(0); + } + //m_global->disableThresholdHW(true); + m_maskStaging->setupMaskStageHW(maskStage); + //m_global->disableThresholdHW(false); + + } + + //set the value in the register but not in the frontend + Module::PAR Module::setParameter(const char* name, int val, GlobalRegister::mode t){ + std::string par=m_global->lookupParameter(name); + if(par!=""){ //it's a global variable + m_global->setField(par.c_str(), val, t); + return GLOBAL; + } + PixelRegister::Field fpar=PixelRegister::lookupParameter(name); + if(fpar!=PixelRegister::not_found){ //it's a pixel variable + setPixelRegisterParameterHW(fpar, val, t); + return PIXEL; + } + if(std::string(name)=="CHARGE"){ + m_global->setField("PlsrDAC", electronsToDac(val), t); + return SPECIAL; + } + if (std::string(name)=="NO_PAR"){ + return SPECIAL; + } + //we have tested all options + char error_message[128]; + sprintf(error_message, "parameter %s was not found.",name); + ERS_ASSERT_MSG(666==NOT_FOUND, error_message); + return NOT_FOUND; + } + + void Module::setPixelRegisterParameterHW(PixelRegister::Field field, unsigned val, GlobalRegister::mode t){ + m_pixel->setFieldAll(field, val); + if(t==GlobalRegister::HW){ + unsigned mode=m_global->getField("Colpr_Mode"); + unsigned addr=m_global->getField("Colpr_Addr"); + m_global->setField("Colpr_Mode", 3, GlobalRegister::SW); // all double columns have the same value, write all at once + writeDoubleColumnHW(PixelRegisterFields::fieldPos[field], PixelRegisterFields::fieldPos[field+1]-1, 0, 0); + m_global->setField("Colpr_Mode", mode, GlobalRegister::SW); + m_global->setField("Colpr_Addr", addr, GlobalRegister::SW); + } + } + + // set a parameter (global or MCC) in the frontend + int Module::setupParameterHW(const char* name, int val){ + //std::cout<<"Setup parameter "<<name<<" val="<<val<<" FE "<<getId()<<std::endl; + //m_timer.Start(); + int retval=0; + PAR rv; + //m_global->disableThresholdHW(true); + rv=setParameter(name, val, GlobalRegister::HW); + //m_global->disableThresholdHW(false); + if(rv==NOT_FOUND)retval=-1; + //m_timer.Stop(); + return retval; + } + + int Module::configureScan(boost::property_tree::ptree *scanOptions){ + int retval=0; + //m_timer.Reset(); + bool isTel=false; + if(getName().substr(0,9)=="Telescope"){ + std::cout<<"Module "<<getId()<<" is a telescope module"<<std::endl; + isTel=true; + } + try{ + // trigger mode + std::string triggerMode=scanOptions->get<std::string>("trigOpt.triggerMode"); + //std::cout<<"trigger Mode is "<<triggerMode<<std::endl; + int xselftrg=0; // 1 for module crosstalk + if(triggerMode=="MIXED"){ + int moduleTrgMask=scanOptions->get<int>("trigOpt.moduleTrgMask"); + xselftrg=(moduleTrgMask&(1<<getOutLink()))!=0; + std::cout<<"xselftrg "<<xselftrg<<" "<<moduleTrgMask<<" "<<getOutLink()<<std::endl; + setParameter("GateHitOr",xselftrg,GlobalRegister::SW); + if(xselftrg==1)std::cout<<"Configuring module "<<getId()<<" with SELFTRIGGER"<<std::endl; + else std::cout<<"Configuring module "<<getId()<<" with regular trigger"<<std::endl; + } else if(triggerMode=="INTERNAL_SELF") setParameter("GateHitOr",1,GlobalRegister::SW); + else setParameter("GateHitOr",0,GlobalRegister::SW); + int diginject=scanOptions->get("trigOpt.optionsMask.DIGITAL_INJECT", 0); + if(diginject)setParameter("DIGHITIN_Sel",1,GlobalRegister::SW); + else setParameter("DIGHITIN_Sel",0,GlobalRegister::SW); + + std::string type = scanOptions->get<std::string>("scanType"); + int override = scanOptions->get("trigOpt.optionsMask.OVERRIDE_LATENCY", 0); + if(type!="CosmicData" || override==true){ //For cosmic data the latency comes from a file unless override is set. + if(!xselftrg) { + if(isTel)setParameter("TrigLat",scanOptions->get<int>("trigOpt.Lvl1_Latency_Secondary"),GlobalRegister::SW); + else setParameter("TrigLat",scanOptions->get<int>("trigOpt.Lvl1_Latency"),GlobalRegister::SW); + } else { + setParameter("TrigLat",scanOptions->get<int>("trigOpt.Lvl1_Latency_Secondary"),GlobalRegister::SW); + std::cout<<"Configured with secondary latency "<<scanOptions->get<int>("trigOpt.Lvl1_Latency_Secondary")<<std::endl; + } + int nev; + if(isTel)nev=scanOptions->get<int>("trigOpt.nTriggersPerGroup"); + else nev=scanOptions->get<int>("trigOpt.nL1AperEvent"); + if(nev==16)nev=0; + setParameter("TrigCnt",nev ,GlobalRegister::SW); + if(override==true){ + if(isTel){ + std::cout<<"Module "<<getId()<<": Overriding latency with "<< + scanOptions->get<int>("trigOpt.Lvl1_Latency_Secondary")<<std::endl; + std::cout<<"Module "<<getId()<<": Overriding conseq triggers with "<< + scanOptions->get<int>("trigOpt.nTriggersPerGroup")<<std::endl; + }else{ + std::cout<<"Module "<<getId()<<": Overriding latency with "<< + scanOptions->get<int>("trigOpt.Lvl1_Latency")<<std::endl; + std::cout<<"Module "<<getId()<<": Overriding conseq triggers with "<< + scanOptions->get<int>("trigOpt.nL1AperEvent")<<std::endl; + } + } + } + setParameter("CMDcnt_delay",scanOptions->get<int>("trigOpt.strobeMCCDelay"),GlobalRegister::SW); + setParameter("CMDcnt_width",scanOptions->get<int>("trigOpt.strobeDuration"),GlobalRegister::SW); + //setParameter("enables",0xffff); + // Global regs + std::string stagingMode=scanOptions->get<std::string>("stagingMode"); + std::string maskStages=scanOptions->get<std::string>("maskStages"); + MaskStageFactory msf; + delete m_maskStaging; + m_maskStaging=msf.createMaskStaging(this, maskStages.c_str(), stagingMode.c_str()); + // set Vcal + std::string par="PlsrDAC"; + if(scanOptions->get("trigOpt.optionsMask.SPECIFY_CHARGE_NOT_VCAL", 0)==1)par="CHARGE"; + setParameter(par.c_str(),scanOptions->get<int>("trigOpt.vcal_charge"),GlobalRegister::SW); + m_oneByOne=scanOptions->get("trigOpt.optionsMask.ONE_BY_ONE", 0); + if(scanOptions->get("trigOpt.optionsMask.SETUP_THRESHOLD", 0)==1){ + unsigned short threshold=scanOptions->get<int>("trigOpt.threshold"); + std::cout<<"Setting threshold to "<<threshold<<std::endl; + setParameter("Vthin_AltFine", threshold, GlobalRegister::SW); + } + if(scanOptions->get<std::string>("DataProc")=="RawFei4Occupancy"){ + std::cout<<m_id<<": RawFei4Occupancy dataproc. Setting HitDiscCnfg to 0"<<std::endl; + setParameter("HitDiscCnfg", 0, GlobalRegister::SW); + } + if(scanOptions->get("trigOpt.optionsMask.CLEAR_MASKS", 0)==1){ + m_pixel->setBitAll(PixelRegister::enable, 1); + m_pixel->setBitAll(PixelRegister::hitbus, 1); + } + } + catch(boost::property_tree::ptree_bad_path ex){ + retval=1; + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + } + return retval; + } + + + ModuleInfo Module::getModuleInfo(){ + return ModuleInfo(m_name, m_id,m_inLink, m_outLink,Module::N_FRONTENDS,PixelRegister::N_ROWS,PixelRegister::N_COLS, m_formatter); + } + + void Module::dumpConfig(std::ostream &os){ + m_global->printFields(os); + m_pixel->dumpPixelRegister(os); + os<<"Charge injection parameters:"<<std::endl; + os<<"----------------------------"<<std::endl; + os<<"vcalCoeff[0]: "<<getVcalCoeff(0)<<std::endl; + os<<"vcalCoeff[1]: "<<getVcalCoeff(1)<<std::endl; + os<<"vcalCoeff[2]: "<<getVcalCoeff(2)<<std::endl; + os<<"vcalCoeff[3]: "<<getVcalCoeff(3)<<std::endl; + os<<"capValLo: "<<getCapVal(0)<<std::endl; + os<<"capValHi: "<<getCapVal(1)<<std::endl; + } + +}; + diff --git a/rce/rcecalib/config/FEI4/Module.hh b/rce/rcecalib/config/FEI4/Module.hh new file mode 100644 index 00000000..6ec6c75d --- /dev/null +++ b/rce/rcecalib/config/FEI4/Module.hh @@ -0,0 +1,73 @@ +#ifndef FEI4__MODULE_HH +#define FEI4__MODULE_HH + +#include "rcecalib/config/AbsModule.hh" +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/config/FEI4/GlobalRegister.hh" +#include "rcecalib/config/FEI4/FECommands.hh" +#include "rcecalib/config/FEI4/PixelRegister.hh" +#include "rcecalib/config/MaskStaging.hh" +#include "rcecalib/profiler/Profiler.hh" +#include <string> + +class AbsFormatter; + +namespace FEI4{ + + class Module: public AbsModule{ + public: + Module(const char* name, unsigned id, unsigned inLink, unsigned outLink, AbsFormatter *fmt); + virtual ~Module(); + enum {N_FRONTENDS=1}; + enum PAR {NOT_FOUND, GLOBAL, PIXEL, SPECIAL}; + enum READOUT_MODE {RAW, FRAMED}; + enum Errors{BAD_SIZE=222, BAD_PIXREG=333, BAD_DCOL=444}; + void configureHW(); + virtual void resetHW()=0; + void resetFE(); + void setupMaskStageHW(int stage); + void setupMaskStageInjHW(int stage); + void enableSrHW(bool on); + void setPixelRegisterParameterHW(PixelRegister::Field field, unsigned val, GlobalRegister::mode t); + void enableDataTakingHW(); + void resetErrorCountersHW(); + virtual int verifyModuleConfigHW()=0; + void switchModeHW(FECommands::MODE mode); + void switchToConfigModeHW(); + int setupParameterHW(const char* name, int val); //HW setup + PAR setParameter(const char* name, int val, GlobalRegister::mode t); // HW or SW + int configureScan(boost::property_tree::ptree* scanOptions); + ModuleInfo getModuleInfo(); + const float dacToElectrons(int fe, int dac); + const int electronsToDac(float ne); + virtual void destroy()=0; + void setVcalCoeff(unsigned i, float val); + void setCapVal(unsigned i, float val); + float getVcalCoeff(unsigned i); + float getCapVal(unsigned i); + void writeDoubleColumnHW(unsigned bitLow, unsigned bitHigh, unsigned dcolLow, unsigned dcolHigh); + void writeGlobalRegisterHW(); + void setupS0S1HitldHW(int s0, int s1, int hitld); + virtual void setupGlobalPulseHW(int pulsereg)=0; + void setupPixelStrobesHW(unsigned bitmask); + void dumpConfig(std::ostream &os); + PixelRegister* pixel(){return m_pixel;} + GlobalRegister* global(){return m_global;} + void setBroadcast(bool on){m_commands->setBroadcast(on);} + +protected: + READOUT_MODE m_mode; + GlobalRegister *m_global; + PixelRegister *m_pixel; + PixelRegister *m_pixel_readback; + FECommands *m_commands; + float m_vcalCoeff[4]; + float m_capVal[2]; + MaskStaging<FEI4::Module> *m_maskStaging; + Profiler::Timer m_timer; + int m_gAddr; + int m_oneByOne; +}; + +}; +#endif diff --git a/rce/rcecalib/config/FEI4/ModuleCrosstalkMaskStaging.cc b/rce/rcecalib/config/FEI4/ModuleCrosstalkMaskStaging.cc new file mode 100644 index 00000000..17203cec --- /dev/null +++ b/rce/rcecalib/config/FEI4/ModuleCrosstalkMaskStaging.cc @@ -0,0 +1,50 @@ +#include "rcecalib/config/FEI4/ModuleCrosstalkMaskStaging.hh" +#include "rcecalib/config/FEI4/Module.hh" + +namespace FEI4{ + + ModuleCrosstalkMaskStaging::ModuleCrosstalkMaskStaging(FEI4::Module* mod, Masks masks, std::string type) + :MaskStaging<FEI4::Module>(mod, masks, type){ + m_nStages=3; + } + + void ModuleCrosstalkMaskStaging::setupMaskStageHW(int maskStage){ + PixelRegister* pixel=m_module->pixel(); + GlobalRegister* global=m_module->global(); + // std::cout<<"Setting up mask stage "<<maskStage<<std::endl; + if(global->getField("GateHitOr")==1){ + //std::cout<<"Disabling injection "<<std::endl; + global->setField("Colpr_Mode", 0, GlobalRegister::SW); + global->setField("Colpr_Addr", 40, GlobalRegister::SW); // switch off injection into module + return; + } + //std::cout<<"Injecting "<<std::endl; + if(m_initialized==false || maskStage==0){ + clearBitsHW(); + m_initialized=true; + } + unsigned dcolStage=maskStage/m_nStages; + unsigned stage=maskStage%m_nStages; + global->setField("Colpr_Mode", 0, GlobalRegister::SW); + for(int i=0;i<PixelRegister::N_PIXEL_REGISTER_BITS;i++){ + if(m_masks.iMask&(1<<i)){ + pixel->setupMaskStageCol(dcolStage*2+1, i, stage, m_nStages); + if(dcolStage==39)pixel->setupMaskStageCol(80, i, stage, m_nStages); + m_module->writeDoubleColumnHW(i, i, dcolStage, dcolStage); + //m_pixel->setBitCol(maskStage*2+1, i, 1); //enable bit in double column + if(dcolStage!=0){ + if(stage==0)pixel->setBitCol(dcolStage*2-1, i, 0); //disable previous column + //m_pixel->setBitCol(maskStage*2, i, 1); //enable bit in double column + pixel->setupMaskStageCol(dcolStage*2, i, stage, m_nStages); + //if(maskStage==39)m_pixel->setBitCol(80, i, 1); //column 80 is special + m_module->writeDoubleColumnHW(i, i, dcolStage-1, dcolStage-1); + if(dcolStage>1){ + if(stage==0)pixel->setBitCol(dcolStage*2-2, i, 0); + m_module->writeDoubleColumnHW(i, i, dcolStage-2, dcolStage-2); + } + global->setField("Colpr_Addr", dcolStage, GlobalRegister::HW); + } + } + } + } +} diff --git a/rce/rcecalib/config/FEI4/ModuleCrosstalkMaskStaging.hh b/rce/rcecalib/config/FEI4/ModuleCrosstalkMaskStaging.hh new file mode 100644 index 00000000..940685b4 --- /dev/null +++ b/rce/rcecalib/config/FEI4/ModuleCrosstalkMaskStaging.hh @@ -0,0 +1,20 @@ +#ifndef FEI4MODULECROSSTALKMASKSTAGING_HH +#define FEI4MODULECROSSTALKMASKSTAGING_HH + +#include "rcecalib/config/Masks.hh" +#include "rcecalib/config/MaskStaging.hh" + +namespace FEI4{ + + class Module; + + class ModuleCrosstalkMaskStaging: public MaskStaging<FEI4::Module>{ + public: + ModuleCrosstalkMaskStaging(FEI4::Module* module, Masks masks, std::string type); + void setupMaskStageHW(int maskStage); + private: + int m_nStages; + }; + +} +#endif diff --git a/rce/rcecalib/config/FEI4/ModuleGroup.cc b/rce/rcecalib/config/FEI4/ModuleGroup.cc new file mode 100644 index 00000000..146bef85 --- /dev/null +++ b/rce/rcecalib/config/FEI4/ModuleGroup.cc @@ -0,0 +1,210 @@ + +#include <boost/property_tree/ptree.hpp> +#include <stdio.h> +#include "rcecalib/config/FEI4/Module.hh" +#include "rcecalib/config/FEI4/ModuleGroup.hh" +#include "rcecalib/util/exceptions.hh" +#include "ers/ers.h" +#include "rcecalib/HW/SerialIF.hh" + +namespace FEI4{ + +void ModuleGroup::addModule(Module* module){ + m_modules.push_back(module); + m_channelInMask|=1<<module->getInLink(); + m_channelOutMask|=1<<module->getOutLink(); +} + +void ModuleGroup::deleteModules(){ + for (unsigned i=0; i<m_modules.size();i++){ + //cannot call delete directly because IPC modules need to call _destroy() instead. + m_modules[i]->destroy(); + } + m_modules.clear(); + m_channelInMask=0; + m_channelOutMask=0; +} + +int ModuleGroup::setupParameterHW(const char* name, int val, bool bcOK){ + int retval=0; + int oneByOne=m_oneByOne; + if(bcOK==false)m_oneByOne=true; //always go one by one in certain cases + bool pixelReg=(PixelRegister::lookupParameter(name)!=PixelRegister::not_found); + if(m_oneByOne==false){ + m_modules[0]->setBroadcast(true); + setChannelInMask(); + } + switchToConfigModeHW(); + if(pixelReg==true){ + enableSrHW(false); //disable SR in case it's a pixel reg parameter + }else if(m_oneByOne==false){ + m_modules[0]->setBroadcast(false); + } + if(pixelReg==false || m_oneByOne==true){ // one by one + for (unsigned int i=0;i<m_modules.size();i++){ + SerialIF::setChannelInMask(1<<m_modules[i]->getInLink()); + retval+=m_modules[i]->setupParameterHW(name,val); + } + }else{ //it's a pixel param and oneByOne is false => broadcast + m_modules[0]->setupParameterHW(name,val); + } + if(pixelReg==true){ + enableSrHW(true); //enable + if(m_oneByOne==false)m_modules[0]->setBroadcast(false); + } + disableAllInChannels(); + if(bcOK==false)m_oneByOne=oneByOne; //restore value + return retval; +} + +int ModuleGroup::setupMaskStageHW(int stage){ + if(m_oneByOne==false){ + m_modules[0]->setBroadcast(true); + setChannelInMask(); + } + switchToConfigModeHW(); + if(m_oneByOne==true){ + enableSrHW(false); //disable + for (unsigned int i=0;i<m_modules.size();i++){ + SerialIF::setChannelInMask(1<<m_modules[i]->getInLink()); + m_modules[i]->setupMaskStageHW(stage); + m_modules[i]->enableSrHW(false); + } + enableSrHW(true);//enable + }else{ //broadcast + m_modules[0]->setupMaskStageHW(stage); + m_modules[0]->setBroadcast(false); + } + if(stage==0)SerialIF::sendCommand(0x10); //phase calibration + disableAllInChannels(); + return 0; +} + +void ModuleGroup::configureModulesHW(){ + //std::cout<<"Configure Modules HW"<<std::endl; + if(m_oneByOne==false){ + m_modules[0]->setBroadcast(true); + setChannelInMask(); + } + switchToConfigModeHW(); + enableSrHW(false); //disable + if(m_oneByOne==false)m_modules[0]->setBroadcast(false); + for (unsigned int i=0;i<m_modules.size();i++){ + SerialIF::setChannelInMask(1<<m_modules[i]->getInLink()); + m_modules[i]->configureHW(); + m_modules[i]->enableSrHW(false); //disable SR + } + SerialIF::sendCommand(0x10); //phase calibration + disableAllInChannels(); +} + +int ModuleGroup::verifyModuleConfigHW(){ + int retval=0; + bool oneByOne=m_oneByOne; + m_oneByOne=true; // always go one by one + switchToConfigModeHW(); + enableSrHW(false); //disable + for (unsigned int i=0;i<m_modules.size();i++){ + std::cout<<"Frontend with outlink "<<m_modules[i]->getOutLink()<<std::endl; + SerialIF::setChannelInMask(1<<m_modules[i]->getInLink()); + retval|=m_modules[i]->verifyModuleConfigHW(); + m_modules[i]->enableSrHW(false); //disable SR + } + m_oneByOne=oneByOne; //restore value + return retval; +} + +void ModuleGroup::resetFE(){ + if(m_oneByOne==false){ + m_modules[0]->setBroadcast(true); + setChannelInMask(); + } + switchToConfigModeHW(); + if(m_oneByOne==true){ + for (unsigned int i=0;i<m_modules.size();i++){ + SerialIF::setChannelInMask(1<<m_modules[i]->getInLink()); + m_modules[i]->resetFE(); + } + }else{ //broadcast + m_modules[0]->resetFE(); + m_modules[0]->setBroadcast(false); + } + disableAllInChannels(); +} + +void ModuleGroup::resetErrorCountersHW(){ + if(m_oneByOne==false){ + m_modules[0]->setBroadcast(true); + setChannelInMask(); + } + switchToConfigModeHW(); + if(m_oneByOne==true){ + for (unsigned int i=0;i<m_modules.size();i++){ + SerialIF::setChannelInMask(1<<m_modules[i]->getInLink()); + m_modules[i]->resetErrorCountersHW(); + } + }else{ //broadcast + m_modules[0]->resetErrorCountersHW(); + m_modules[0]->setBroadcast(false); + } + //disableAllInChannels(); +} + +void ModuleGroup::enableDataTakingHW(){ + //std::cout<<"ConfigIF enabled data taking"<<std::endl; + if(m_oneByOne==false){ + m_modules[0]->setBroadcast(true); + setChannelInMask(); + } + if(m_oneByOne==true){ + for (unsigned int i=0;i<m_modules.size();i++){ + SerialIF::setChannelInMask(1<<m_modules[i]->getInLink()); + m_modules[i]->enableDataTakingHW(); + } + }else{ //broadcast + m_modules[0]->enableDataTakingHW(); + m_modules[0]->setBroadcast(false); + } + disableAllInChannels(); +} + +void ModuleGroup::switchToConfigModeHW(){ + //std::cout<<"ConfigIF switch config mode"<<std::endl; + if(m_oneByOne == true){ + for (unsigned int i=0;i<m_modules.size();i++){ + SerialIF::setChannelInMask(1<<m_modules[i]->getInLink()); + m_modules[i]->switchToConfigModeHW(); + } + }else{ //broadcast + m_modules[0]->switchToConfigModeHW(); + } +} + +void ModuleGroup::enableSrHW(bool on){ //not used in broadcast mode + //std::cout<<"ConfigIF switch config mode"<<std::endl; + if(m_oneByOne == true){ + for (unsigned int i=0;i<m_modules.size();i++){ + SerialIF::setChannelInMask(1<<m_modules[i]->getInLink()); + m_modules[i]->enableSrHW(on); + } + }else{ //broadcast + m_modules[0]->enableSrHW(on); + } +} + +int ModuleGroup::configureScan(boost::property_tree::ptree *scanOptions){ + int retval=0; + try{ + m_oneByOne=scanOptions->get("trigOpt.optionsMask.ONE_BY_ONE", 0); + for (unsigned int i=0;i<m_modules.size();i++){ + retval+=m_modules[i]->configureScan(scanOptions); + } + } catch(boost::property_tree::ptree_bad_path ex){ + retval=1; + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + } + return retval; +} + +} diff --git a/rce/rcecalib/config/FEI4/ModuleGroup.hh b/rce/rcecalib/config/FEI4/ModuleGroup.hh new file mode 100644 index 00000000..f917921d --- /dev/null +++ b/rce/rcecalib/config/FEI4/ModuleGroup.hh @@ -0,0 +1,35 @@ +#ifndef MODULEGROUPFEI4_HH +#define MODULEGROUPFEI4_HH +#include "rcecalib/config/AbsModuleGroup.hh" +#include <boost/property_tree/ptree_fwd.hpp> +#include <vector> + +namespace FEI4{ + + class Module; + +class ModuleGroup: public AbsModuleGroup{ +public: + ModuleGroup():AbsModuleGroup(), m_oneByOne(false){}; + virtual ~ModuleGroup(){} + void addModule(FEI4::Module* module); + void deleteModules(); + int setupParameterHW(const char* name, int val, bool bcok); + int setupMaskStageHW(int stage); + void configureModulesHW(); + int verifyModuleConfigHW(); + void resetErrorCountersHW(); + int configureScan(boost::property_tree::ptree *scanOptions); + void resetFE(); + void enableDataTakingHW(); + unsigned getNmodules(){return m_modules.size();} +private: + void enableSrHW(bool on); + void switchToConfigModeHW(); + std::vector<FEI4::Module*> m_modules; + bool m_oneByOne; + +}; +} + +#endif diff --git a/rce/rcecalib/config/FEI4/MonleakTrigger.cc b/rce/rcecalib/config/FEI4/MonleakTrigger.cc new file mode 100644 index 00000000..27fefe1a --- /dev/null +++ b/rce/rcecalib/config/FEI4/MonleakTrigger.cc @@ -0,0 +1,77 @@ + +#include "rcecalib/config/FEI4/MonleakTrigger.hh" +#include "rcecalib/config/FEI4/FECommands.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/HW/SerialIF.hh" +#include "rcecalib/profiler/Profiler.hh" + +namespace FEI4{ + + MonleakTrigger::MonleakTrigger():AbsTrigger(){ + } + MonleakTrigger::~MonleakTrigger(){ + } + int MonleakTrigger::configureScan(boost::property_tree::ptree* scanOptions){ + int retval=0; + m_i=0; //reset the number of triggers + try{ + // int calL1ADelay = scanOptions->get<int>("trigOpt.CalL1ADelay"); + setupTriggerStream(); + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + retval=1; + } + return retval; + } + int MonleakTrigger::setupParameter(const char* name, int val){ + return 0; + } + + void MonleakTrigger::setupTriggerStream(){ + m_triggerStream.clear(); + FECommands commands; + commands.setBroadcast(true); + + commands.switchMode(&m_triggerStream, FECommands::CONF); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + //Set GADCSel to 7, which indicates that GADC will return the leakage current + //Also sets PlsrRiseUpTau to 7 and enables PlsrPwr + commands.writeGlobalRegister(&m_triggerStream, 31, 0xf007); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + //enables GADCStart, which means that when a GlobalPulse is sent, it will be sent + //to the GADC. Also, enables EN_PLL bit. + commands.writeGlobalRegister(&m_triggerStream, 27, 0x8400); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + commands.globalPulse(&m_triggerStream, 63); + for(int i=0;i<16;i++)m_triggerStream.push_back(0); + //readout GADC value. + commands.readGlobalRegister(&m_triggerStream, 40); + } + + int MonleakTrigger::sendTrigger(){ + SerialIF::send(&m_triggerStream,SerialIF::DONT_CLEAR|SerialIF::WAITFORDATA); + m_i++; + return 0; + } + + int MonleakTrigger::enableTrigger(bool on){ + return SerialIF::enableTrigger(on); + return 0; + } + int MonleakTrigger::resetCounters(){ + return 0; + } +}; diff --git a/rce/rcecalib/config/FEI4/MonleakTrigger.hh b/rce/rcecalib/config/FEI4/MonleakTrigger.hh new file mode 100644 index 00000000..1f44e42f --- /dev/null +++ b/rce/rcecalib/config/FEI4/MonleakTrigger.hh @@ -0,0 +1,26 @@ +#ifndef MONLEAKTRIGGER_HH +#define MONLEAKTRIGGER_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/config/AbsTrigger.hh" +#include "rcecalib/HW/BitStream.hh" + +namespace FEI4{ + + class MonleakTrigger: public AbsTrigger{ + public: + MonleakTrigger(); + ~MonleakTrigger(); + int configureScan(boost::property_tree::ptree* scanOptions); + int setupParameter(const char* name, int val); + int sendTrigger(); + int enableTrigger(bool on); + int resetCounters(); + void setupTriggerStream(); + private: + BitStream m_triggerStream; + }; + +}; + +#endif diff --git a/rce/rcecalib/config/FEI4/NoiseMaskStaging.cc b/rce/rcecalib/config/FEI4/NoiseMaskStaging.cc new file mode 100644 index 00000000..65d424a9 --- /dev/null +++ b/rce/rcecalib/config/FEI4/NoiseMaskStaging.cc @@ -0,0 +1,54 @@ +#include "rcecalib/config/FEI4/NoiseMaskStaging.hh" +#include "rcecalib/config/FEI4/Module.hh" + +namespace FEI4{ + + NoiseMaskStaging::NoiseMaskStaging(FEI4::Module* mod, Masks masks, std::string type) + :MaskStaging<FEI4::Module>(mod, masks, type){ + } + + void NoiseMaskStaging::setupMaskStageHW(int maskStage){ + if(m_initialized==false || maskStage==0){ + clearBitsHW(); + m_initialized=true; + } + PixelRegister* pixel=m_module->pixel(); + GlobalRegister* global=m_module->global(); + global->setField("Colpr_Mode", 0, GlobalRegister::SW); + + /* + this is the code to reset bits. Don't understand everything it's doing + m_module->global()->setField("Colpr_Mode", 3, GlobalRegister::SW); + for(int i=0;i<PixelRegister::N_PIXEL_REGISTER_BITS;i++){ + if(m_masks.oMask&(1<<i)){ + m_module->pixel()->setBitAll(i,0); + m_module->writeDoubleColumnHW(i,i,0,0); + } + } + */ + + + for(int i=0;i<PixelRegister::N_PIXEL_REGISTER_BITS;i++){ + if(m_masks.iMask&(1<<i)){ + + //turn on this bit for every pixel on the FE + for(int dcolStage=0; dcolStage<40; dcolStage++){ + + pixel->setupMaskStageCol(dcolStage*2+1, i, 0, 1); + if(dcolStage==39)pixel->setupMaskStageCol(80, i, 0, 1); + + m_module->writeDoubleColumnHW(i, i, dcolStage, dcolStage); + + if(dcolStage!=0){ + pixel->setupMaskStageCol(dcolStage*2, i, 0, 1); + m_module->writeDoubleColumnHW(i, i, dcolStage-1, dcolStage-1); + global->setField("Colpr_Addr", dcolStage, GlobalRegister::HW); //this line not necessary, since not injecting + } + } + + } //end if(m_masks.iMask&(1<<i)) + } //end for(int i=0;i<PixelRegister::N_PIXEL_REGISTER_BITS;i++) + + } + +} diff --git a/rce/rcecalib/config/FEI4/NoiseMaskStaging.hh b/rce/rcecalib/config/FEI4/NoiseMaskStaging.hh new file mode 100644 index 00000000..55994204 --- /dev/null +++ b/rce/rcecalib/config/FEI4/NoiseMaskStaging.hh @@ -0,0 +1,20 @@ +#ifndef FEI4NOISEMASKSTAGING_HH +#define FEI4NOISEMASKSTAGING_HH + +#include "rcecalib/config/Masks.hh" +#include "rcecalib/config/MaskStaging.hh" + +namespace FEI4{ + + class Module; + + class NoiseMaskStaging: public MaskStaging<FEI4::Module>{ + public: + NoiseMaskStaging(FEI4::Module* module, Masks masks, std::string type); + void setupMaskStageHW(int maskStage); + private: + + }; + +} +#endif diff --git a/rce/rcecalib/config/FEI4/PatternMaskStaging.cc b/rce/rcecalib/config/FEI4/PatternMaskStaging.cc new file mode 100644 index 00000000..310e778b --- /dev/null +++ b/rce/rcecalib/config/FEI4/PatternMaskStaging.cc @@ -0,0 +1,23 @@ +#include "rcecalib/config/FEI4/PatternMaskStaging.hh" +#include "rcecalib/config/FEI4/Module.hh" + +namespace FEI4{ + + PatternMaskStaging::PatternMaskStaging(FEI4::Module* mod, Masks masks, std::string type) + :MaskStaging<FEI4::Module>(mod, masks, type){ + std::cout<<"Set up pattern mask staging"<<std::endl; + PixelRegister::setHitBusMode(1); + } + + void PatternMaskStaging::setupMaskStageHW(int maskStage){ + PixelRegister* pixel=m_module->pixel(); + GlobalRegister* global=m_module->global(); + global->setField("Conf_AddrEnable", 1, GlobalRegister::HW); + global->setField("Colpr_Mode", 3, GlobalRegister::SW); + for(int i=0;i<PixelRegister::N_PIXEL_REGISTER_BITS;i++){ + int thestage= (unsigned)i==PixelRegisterFields::fieldPos[PixelRegister::hitbus]? maskStage : 1-maskStage; + pixel->setupMaskStage(i, thestage, 2); + m_module->writeDoubleColumnHW(i, i, 0, 0); + } + } +} diff --git a/rce/rcecalib/config/FEI4/PatternMaskStaging.hh b/rce/rcecalib/config/FEI4/PatternMaskStaging.hh new file mode 100644 index 00000000..f2c906b2 --- /dev/null +++ b/rce/rcecalib/config/FEI4/PatternMaskStaging.hh @@ -0,0 +1,18 @@ +#ifndef FEI4PATTERNMASKSTAGING_HH +#define FEI4PATTERNMASKSTAGING_HH + +#include "rcecalib/config/Masks.hh" +#include "rcecalib/config/MaskStaging.hh" + +namespace FEI4{ + + class Module; + + class PatternMaskStaging: public MaskStaging<FEI4::Module>{ + public: + PatternMaskStaging(FEI4::Module* module, Masks masks, std::string type); + void setupMaskStageHW(int maskStage); + }; + +} +#endif diff --git a/rce/rcecalib/config/FEI4/PixelRegister.cc b/rce/rcecalib/config/FEI4/PixelRegister.cc new file mode 100644 index 00000000..a3257212 --- /dev/null +++ b/rce/rcecalib/config/FEI4/PixelRegister.cc @@ -0,0 +1,261 @@ +#include "rcecalib/config/FEI4/PixelRegister.hh" +#include "rcecalib/HW/SerialIF.hh" +#include "rcecalib/config/FEI4/FECommands.hh" +#include "rcecalib/config/FEI4/FEI4ARecord.hh" +#include "rcecalib/util/VerifyErrors.hh" +//#include "PixelRegister.hh" +#include <iostream> +#include <stdio.h> +#include <unistd.h> /* for usleep */ + +namespace FEI4{ + std::string PixelRegister::m_cachedName; + PixelRegister::Field PixelRegister::m_cachedField(not_found); + std::map<std::string, PixelRegister::Field> PixelRegister::m_parameters; + bool PixelRegister::m_initialized = false; + int PixelRegister::m_hitbusMode = 0; + + PixelRegister::PixelRegister(FECommands* commands):m_commands(commands){ + // initialize static field dictionay + if(!m_initialized)initialize(); + //Clear all registers + for (int i=0;i<N_PIXEL_REGISTER_BITS;i++){ + for(int k=0;k<N_COLS/2;k++){ + for (int j=0;j<DROW_WORDS;j++){ + m_pixreg[i][k][j]=0; + } + } + } + } + PixelRegister::~PixelRegister(){ + } + void PixelRegister::initialize(){ + // Translation from scan parameter to Global register field + m_parameters["TDACS"]=tdac; + m_parameters["FDACS"]=fdac; + m_initialized=true; + } + + + void PixelRegister::setDoubleColumn(unsigned bit, unsigned dcol, unsigned *data){ + if(bit<N_PIXEL_REGISTER_BITS && dcol<N_COLS/2){ + for(int i=0;i<DROW_WORDS;i++){ + m_pixreg[bit][dcol][i]=data[i]; + } + } + } + void PixelRegister::setFieldAll(Field field, unsigned val){ + unsigned bitpos=PixelRegisterFields::fieldPos[field]; + unsigned mask=PixelRegisterFields::fieldMask[field]; + unsigned v=val; + if(field==tdac)v=flipBits(5, val);// tdac has reverse bit order + while(mask&1){ + setBitAll(bitpos, v&0x1); + mask>>=1; + v>>=1; + bitpos++; + } + } + + void PixelRegister::setBitAll(int bit, int on){ + if( (unsigned)bit==PixelRegisterFields::fieldPos[hitbus] && m_hitbusMode==1)on=!on; + unsigned setword=0; + if(on)setword=0xffffffff; + for (int j=0;j<N_COLS/2;j++){ + for(int k=0;k<DROW_WORDS;k++){ + m_pixreg[bit][j][k]=setword; + } + } + } + void PixelRegister::setBitDcol(unsigned dcol, int bit, int on){ + if((unsigned)bit==PixelRegisterFields::fieldPos[hitbus] && m_hitbusMode==1)on=!on; + if(dcol>=N_COLS/2){ + std::cout<<"Error: Trying to set double column "<<dcol<<std::endl; + return; + } + unsigned setword=0; + if(on)setword=0xffffffff; + for(int k=0;k<DROW_WORDS;k++){ + m_pixreg[bit][dcol][k]=setword; + } + } + void PixelRegister::setBitCol(unsigned col, int bit, int on){ + if((unsigned)bit==PixelRegisterFields::fieldPos[hitbus] && m_hitbusMode==1)on=!on; + if(col>N_COLS || col==0){ + std::cout<<"Error: Trying to set column "<<col<<std::endl; + return; + } + unsigned dcol=(col-1)/2; + unsigned setword=0; + if(on)setword=0xffffffff; + unsigned offset=0; + if(col%2==1)offset=DROW_WORDS/2+1; + for(unsigned k=offset;k<offset+DROW_WORDS/2;k++){ + m_pixreg[bit][dcol][k]=setword; + } + unsigned mask=0x0000ffff; + if(col%2==0)mask=0xffff0000; + if(on)m_pixreg[bit][dcol][10]|=mask; + else m_pixreg[bit][dcol][10]&=~mask; + } + + + void PixelRegister::setupMaskStage(int bit, int maskStage, unsigned nMaskStages){ + setBitAll(bit, 0); //clear the bit + int on=1; + if((unsigned)bit==PixelRegisterFields::fieldPos[hitbus] && m_hitbusMode==1)on=0; + for (int j=1;j<=N_COLS;j++){ + for(int k=maskStage+1;k<=N_ROWS;k+=nMaskStages){ + setBit(bit, k, j, on); + } + } + } + void PixelRegister::setupMaskStageCol(unsigned col, int bit, int maskStage, unsigned nMaskStages){ + setBitCol(col, bit, 0); //clear the bit + int on=1; + if((unsigned)bit==PixelRegisterFields::fieldPos[hitbus] && m_hitbusMode==1)on=0; + for(int k=maskStage+1;k<=N_ROWS;k+=nMaskStages){ + setBit(bit, k, col, on); + } + } + void PixelRegister::dumpPixelRegister(std::ostream &os){ + char line[512]; + for (int i=0;i<N_PIXEL_REGISTER_BITS;i++){ + sprintf(line, "BIT %d:\n",i); + os<<line; + for (int j=0;j<N_COLS/2;j++){ + sprintf(line, "Double Col: %02d: ", j); + os<<line; + for(int k=0;k<DROW_WORDS;k++){ + sprintf (line, "%08x ",m_pixreg[i][j][k]); + os<<line; + } + os<<std::endl; + } + } + } + + void PixelRegister::dumpDoubleColumn(unsigned bit, unsigned dcol, std::ostream &os){ + char line[512]; + sprintf(line, "BIT %d:\n",bit); + os<<line; + sprintf(line, "Double Col: %02d: ", dcol); + os<<line; + for(int k=0;k<DROW_WORDS;k++){ + sprintf (line, "%08x ",m_pixreg[bit][dcol][k]); + os<<line; + } + os<<std::endl; + } + + int PixelRegister::verifyDoubleColumnHW(int bit, unsigned dcol, std::vector<unsigned> &readback){ + readback.clear(); + BitStream *bs=new BitStream; + m_commands->feWriteCommand(bs); + for(int i=0;i<DROW_WORDS;i++)bs->push_back(0); // refill with 0 + bs->push_back(0); + SerialIF::send(bs, SerialIF::WAITFORDATA); + delete bs; + usleep(100); + if(readback.size()!=2*DROW_WORDS){ + std::cout<<std::dec<<"Dcol "<<dcol<<" bit "<<bit<<" Expecting 42 val records, received "<<readback.size()<<std::endl; + return ModuleVerify::PIXEL_WRONG_N_WORDS; + }else{ + for(int i=0;i<2*DROW_WORDS;i++){ + if(((~readback[i])&0xffff)!=((m_pixreg[bit][dcol][i/2]>>(16*((i+1)%2)))&0xffff)){ + std::cout<<std::dec<<"Dcol "<<dcol<<" bit "<<bit<<" bad readback "<<std::endl; + std::cout<<std::hex<<"Is "<<((~readback[i])&0xffff)<<" should be "<<((m_pixreg[bit][dcol][i/2]>>(16*((i+1)%2)))&0xffff)<<std::dec<<std::endl; + return ModuleVerify::PIXEL_READBACK_DIFFERENT; + } + } + } + return 0; + } + unsigned PixelRegister::writeDoubleColumnHW(unsigned bit, unsigned dcol){ + BitStream *bs=new BitStream; + m_commands->feWriteCommand(bs); + for(int i=0;i<DROW_WORDS;i++)bs->push_back(m_pixreg[bit][dcol][i]); + bs->push_back(0); + // for(size_t i=0;i<bs->size();i++)std::cout<<"input "<<std::hex<<(*bs)[i]<<std::dec<<std::endl; + SerialIF::send(bs, SerialIF::WAITFORDATA); + delete bs; + return 0; + } + unsigned PixelRegister::writeDoubleColumnHW(const unsigned* data, std::vector<unsigned>& readback){ + BitStream *bs=new BitStream; + m_commands->feWriteCommand(bs); + for(int i=0;i<DROW_WORDS;i++)bs->push_back(data[i]); + bs->push_back(0); + //for(size_t i=0;i<bs->size();i++)std::cout<<"input "<<std::hex<<(*bs)[i]<<std::dec<<std::endl; + std::vector<unsigned char> shiftin; + unsigned stat=SerialIF::writeBlockData(*bs); + usleep(1000); + stat=SerialIF::readBuffers(shiftin); + std::cout<<"Stat "<<stat<<" size "<<shiftin.size()<<std::endl; + + if (stat>0)stat=decodePixelRecord(shiftin, readback); + /* + if(stat>0){ + while (shiftin.size()%4!=0)shiftin.push_back(0); + for(int i=0;i<shiftin.size();i+=4){ + readback.push_back(shiftin[i]<<24|shiftin[i+1]<<16|shiftin[i+2]<<8|shiftin[i+3]); + std::cout<<std::hex<<readback[readback.size()-1]<<std::dec<<" "<<std::endl; + } + std::cout<<std::endl; + } + */ + delete bs; + return stat; + } + + unsigned PixelRegister::decodePixelRecord(std::vector<unsigned char>& shiftin, std::vector<unsigned>& readback){ + if(shiftin.size()==0)return FEI4ARecord::Empty; + unsigned char* bytepointer=(unsigned char*)&shiftin[0]; + size_t size=shiftin.size(); + unsigned char* last=bytepointer+size-3; + FEI4ARecord rec; + bool odd=true; + while(bytepointer<=last){ + rec.setRecord(bytepointer); + printf("Record: %08x\n",rec.getUnsigned()&0xffffff); + if(rec.isServiceRecord()){ // service record + printf("Service record. Error code: %d. Count: %d \n",rec.getErrorCode(), rec.getErrorCount()); + } else if(rec.isAddressRecord()){ // address record + if(!rec.isShift())return FEI4ARecord::NotShift; + std::cout<<"Read address record with address "<<rec.getAddress()<<std::endl; + } else if(rec.isValueRecord()){ // value record + unsigned val; + printf("Value record: %08x\n",rec.getUnsigned()&0xffffff); + if(odd==true)val=rec.getValue()<<16; + else { + val|=rec.getValue(); + readback.push_back(val); + } + odd=!odd; + } + bytepointer+=3; + } + std::cout<<"Return vector"<<std::endl; + for(size_t i=0;i<readback.size();i++)std::cout<<std::hex<<readback[i]<<std::dec<<std::endl; + if(!odd)return FEI4ARecord::OddNwords; + return FEI4ARecord::OK; + } + + PixelRegister::Field PixelRegister::lookupParameter(const char* name){ + // check if this is the last name used, return cached value + if(std::string(name)==m_cachedName)return m_cachedField; + // Now check if we can translate the name to a field name + if(m_parameters.find(name)!=m_parameters.end()){ + //cache result + m_cachedName=name; + m_cachedField=m_parameters[name]; + return m_cachedField; + }else return not_found; + } + + void PixelRegister::setHitBusMode(int value){ + m_hitbusMode=value; + std::cout<<"Set HitBus mode to "<<m_hitbusMode<<std::endl; + } + +} diff --git a/rce/rcecalib/config/FEI4/PixelRegister.hh b/rce/rcecalib/config/FEI4/PixelRegister.hh new file mode 100644 index 00000000..2ceb7c78 --- /dev/null +++ b/rce/rcecalib/config/FEI4/PixelRegister.hh @@ -0,0 +1,106 @@ +#ifndef PIXEL_REGISTER_FEI4_HH +#define PIXEL_REGISTER_FEI4_HH + +#include <vector> +#include <map> +#include "rcecalib/config/FEI4/Utils.hh" +#include <iostream> + +namespace FEI4{ + class FECommands; + + namespace PixelRegisterFields{ + static const unsigned fieldPos[]={0,1,6,7,8,9,13,14}; + static const unsigned fieldMask[]={1,0x1f,1,1,1,0xf,1}; + } + class PixelRegister{ + public: + enum{N_COLS=80, N_ROWS=336 ,N_PIXEL_REGISTER_BITS=14, DROW_WORDS=N_ROWS*2/32}; + enum Field{enable, tdac, largeCap, smallCap, hitbus, fdac, diginj, Nfields, not_found}; + PixelRegister(FECommands* commands); + ~PixelRegister(); + unsigned getBit(unsigned bit, unsigned row, unsigned col){ + int drow; + int dcol=(col-1)/2;// column numbering starts with 1, array with 0. dcol is double column + if(col%2==0){ + drow = row+335; + }else{ + drow = 336-row; + } + return (m_pixreg[bit][dcol][DROW_WORDS-1-drow/32] >> (drow%32))&0x1; + } + + void setBit(unsigned bit, unsigned row, unsigned col, bool val){ + int drow; + int dcol=(col-1)/2;// column numbering starts with 1, array with 0. Array is by double columns. + if(col%2==0){ + drow = row+335; //even column is in forward order 336 - 671 + }else{ + drow = 336-row; //odd column is in backward order 0 - 335 + } + if(val){ + m_pixreg[bit][dcol][DROW_WORDS-1-drow/32] |= (1<<(drow%32)); + }else{ + m_pixreg[bit][dcol][DROW_WORDS-1-drow/32] &= ~(1<<(drow%32)); + } + } + void setFieldAll(Field f, unsigned val); + void setField(Field f, unsigned row, unsigned col, unsigned val){ + unsigned bitpos=PixelRegisterFields::fieldPos[f]; + unsigned mask=PixelRegisterFields::fieldMask[f]; + unsigned v=val; + if(f==tdac)v=flipBits(5, val);// tdac has reverse bit order + while(mask&1){ + setBit(bitpos, row, col, v&0x1); + mask>>=1; + v>>=1; + bitpos++; + } + } + unsigned getField(Field f, unsigned row, unsigned col){ + unsigned bitpos=PixelRegisterFields::fieldPos[f+1]-1; + unsigned mask=PixelRegisterFields::fieldMask[f]; + unsigned val=0; + while(mask&1){ + unsigned bit=getBit(bitpos, row, col); + mask>>=1; + val<<=1; + val|=bit; + bitpos--; + } + if(f==tdac)return flipBits(5, val); // word is flipped, reverse for fdac + else return val; + } + unsigned *getDoubleColumn(unsigned bit, unsigned dcol){ + if(bit<N_PIXEL_REGISTER_BITS && dcol<N_COLS/2)return m_pixreg[bit][dcol]; + else return 0; + } + void setDoubleColumn(unsigned bit, unsigned dcol, unsigned* data); + unsigned writeDoubleColumnHW(unsigned bit, unsigned dcol); + unsigned writeDoubleColumnHW(const unsigned *data, std::vector<unsigned>& readback); + void dumpPixelRegister(std::ostream &os); + void dumpDoubleColumn(unsigned bit, unsigned dcol, std::ostream &os); + unsigned decodePixelRecord(std::vector<unsigned char>& shiftin, std::vector<unsigned>& readback); + int verifyDoubleColumnHW(int bit, unsigned dcol, std::vector<unsigned>& readback); + void setBitAll(int bit, int on); + void setBitDcol(unsigned dcol, int bit, int on); + void setBitCol(unsigned col, int bit, int on); + void setupMaskStage(int bit, int maskStage, unsigned nMaskStages); + void setupMaskStageCol(unsigned col, int bit, int maskStage, unsigned nMaskStages); + static Field lookupParameter(const char* name); + static void setHitBusMode(int value); + + private: + static std::string m_cachedName; + static Field m_cachedField; + static std::map<std::string, Field> m_parameters; + static bool m_initialized; + static void initialize(); + static int m_hitbusMode; //0 for monleak scan, 1 for hitbus scan + FECommands* m_commands; + unsigned m_pixreg[N_PIXEL_REGISTER_BITS][N_COLS/2][DROW_WORDS]; // by double column + }; + +}; + +#endif diff --git a/rce/rcecalib/config/FEI4/RegisterDef.hh b/rce/rcecalib/config/FEI4/RegisterDef.hh new file mode 100644 index 00000000..1cd30a4f --- /dev/null +++ b/rce/rcecalib/config/FEI4/RegisterDef.hh @@ -0,0 +1,29 @@ +#ifndef FEI4__REGISTERDEF_HH +#define FEI4__REGISTERDEF_HH + +namespace FEI4{ + + struct FieldParams{ + int reg; + int bitpos; + int SRABbitpos; + int SRCbitpos; + int width; + bool reverse; + }; + + struct RegisterDef{ + int LOW_REG, N_REG_REGS, N_W_REGS, N_R_REGS, SRAB_BITS, SRC_BITS; + std::map<std::string, FieldParams> m_fields; + std::map<std::string, std::string> m_parameters; + std::string m_cachedName, m_cachedField; + std::map<int, SerialIF::Rate> m_rate; + FieldParams m_params8b10b; + FieldParams m_paramsDrate; + int m_colpr_reg; + unsigned short m_colpr_disable; + }; +} + + +#endif diff --git a/rce/rcecalib/config/FEI4/SNTrigger.cc b/rce/rcecalib/config/FEI4/SNTrigger.cc new file mode 100644 index 00000000..ccea7e7c --- /dev/null +++ b/rce/rcecalib/config/FEI4/SNTrigger.cc @@ -0,0 +1,67 @@ + +#include "rcecalib/config/FEI4/SNTrigger.hh" +#include "rcecalib/config/FEI4/FECommands.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/HW/SerialIF.hh" +#include "rcecalib/profiler/Profiler.hh" + +namespace FEI4{ + + SNTrigger::SNTrigger():AbsTrigger(){ + } + SNTrigger::~SNTrigger(){ + } + int SNTrigger::configureScan(boost::property_tree::ptree* scanOptions){ + int retval=0; + m_i=0; //reset the number of triggers + try{ + // int calL1ADelay = scanOptions->get<int>("trigOpt.CalL1ADelay"); + setupTriggerStream(); + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + retval=1; + } + return retval; + } + int SNTrigger::setupParameter(const char* name, int val){ + return 0; + } + + void SNTrigger::setupTriggerStream(){ + m_triggerStream.clear(); + FECommands commands; + commands.setBroadcast(true); + + commands.switchMode(&m_triggerStream, FECommands::CONF); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + commands.writeGlobalRegister(&m_triggerStream, 27, 0xc000); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + commands.globalPulse(&m_triggerStream, 63); + for(int i=0;i<128;i++)m_triggerStream.push_back(0); + commands.readGlobalRegister(&m_triggerStream, 35); + } + + int SNTrigger::sendTrigger(){ + SerialIF::send(&m_triggerStream,SerialIF::DONT_CLEAR|SerialIF::WAITFORDATA); + m_i++; + return 0; + } + + int SNTrigger::enableTrigger(bool on){ + return SerialIF::enableTrigger(on); + return 0; + } + int SNTrigger::resetCounters(){ + return 0; + } +}; diff --git a/rce/rcecalib/config/FEI4/SNTrigger.hh b/rce/rcecalib/config/FEI4/SNTrigger.hh new file mode 100644 index 00000000..1312044d --- /dev/null +++ b/rce/rcecalib/config/FEI4/SNTrigger.hh @@ -0,0 +1,26 @@ +#ifndef SNTRIGGER_HH +#define SNTRIGGER_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/config/AbsTrigger.hh" +#include "rcecalib/HW/BitStream.hh" + +namespace FEI4{ + + class SNTrigger: public AbsTrigger{ + public: + SNTrigger(); + ~SNTrigger(); + int configureScan(boost::property_tree::ptree* scanOptions); + int setupParameter(const char* name, int val); + int sendTrigger(); + int enableTrigger(bool on); + int resetCounters(); + void setupTriggerStream(); + private: + BitStream m_triggerStream; + }; + +}; + +#endif diff --git a/rce/rcecalib/config/FEI4/TemperatureTrigger.cc b/rce/rcecalib/config/FEI4/TemperatureTrigger.cc new file mode 100644 index 00000000..4f1c8f7a --- /dev/null +++ b/rce/rcecalib/config/FEI4/TemperatureTrigger.cc @@ -0,0 +1,72 @@ + +#include "rcecalib/config/FEI4/TemperatureTrigger.hh" +#include "rcecalib/config/FEI4/FECommands.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/HW/SerialIF.hh" +#include "rcecalib/profiler/Profiler.hh" + +namespace FEI4{ + + TemperatureTrigger::TemperatureTrigger():AbsTrigger(){ + } + TemperatureTrigger::~TemperatureTrigger(){ + } + int TemperatureTrigger::configureScan(boost::property_tree::ptree* scanOptions){ + int retval=0; + m_i=0; //reset the number of triggers + try{ + // int calL1ADelay = scanOptions->get<int>("trigOpt.CalL1ADelay"); + setupTriggerStream(); + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + retval=1; + } + return retval; + } + int TemperatureTrigger::setupParameter(const char* name, int val){ + return 0; + } + + void TemperatureTrigger::setupTriggerStream(){ + m_triggerStream.clear(); + FECommands commands; + commands.setBroadcast(true); + + commands.switchMode(&m_triggerStream, FECommands::CONF); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + commands.writeGlobalRegister(&m_triggerStream, 31, 0xf000); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + commands.writeGlobalRegister(&m_triggerStream, 27, 0x8400); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + m_triggerStream.push_back(0); + commands.globalPulse(&m_triggerStream, 63); + for(int i=0;i<128;i++)m_triggerStream.push_back(0); + commands.readGlobalRegister(&m_triggerStream, 40); + } + + int TemperatureTrigger::sendTrigger(){ + SerialIF::send(&m_triggerStream,SerialIF::DONT_CLEAR|SerialIF::WAITFORDATA); + m_i++; + return 0; + } + + int TemperatureTrigger::enableTrigger(bool on){ + return SerialIF::enableTrigger(on); + return 0; + } + int TemperatureTrigger::resetCounters(){ + return 0; + } +}; diff --git a/rce/rcecalib/config/FEI4/TemperatureTrigger.hh b/rce/rcecalib/config/FEI4/TemperatureTrigger.hh new file mode 100644 index 00000000..7f40397c --- /dev/null +++ b/rce/rcecalib/config/FEI4/TemperatureTrigger.hh @@ -0,0 +1,26 @@ +#ifndef TEMPERATURETRIGGER_HH +#define TEMPERATURETRIGGER_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/config/AbsTrigger.hh" +#include "rcecalib/HW/BitStream.hh" + +namespace FEI4{ + + class TemperatureTrigger: public AbsTrigger{ + public: + TemperatureTrigger(); + ~TemperatureTrigger(); + int configureScan(boost::property_tree::ptree* scanOptions); + int setupParameter(const char* name, int val); + int sendTrigger(); + int enableTrigger(bool on); + int resetCounters(); + void setupTriggerStream(); + private: + BitStream m_triggerStream; + }; + +}; + +#endif diff --git a/rce/rcecalib/config/FEI4/Utils.hh b/rce/rcecalib/config/FEI4/Utils.hh new file mode 100644 index 00000000..0ce31e10 --- /dev/null +++ b/rce/rcecalib/config/FEI4/Utils.hh @@ -0,0 +1,14 @@ +#ifndef UTILS_HH +#define UTILS_HH + +inline unsigned flipBits(int nbits, unsigned val){ + unsigned tmp=0; + unsigned old=val; + for (int i=0;i<nbits;i++){ + tmp|=(old&0x1)<<(nbits-i-1); + old>>=1; + } + return tmp; +} + +#endif diff --git a/rce/rcecalib/config/FormattedRecord.hh b/rce/rcecalib/config/FormattedRecord.hh new file mode 100644 index 00000000..111ff8bf --- /dev/null +++ b/rce/rcecalib/config/FormattedRecord.hh @@ -0,0 +1,158 @@ +#ifndef FORMATTEDRECORD_HH +#define FORMATTEDRECORD_HH + +#include "rcecalib/config/Endianness.hh" + + +/* ---------------------------------------------------------------------- */ + + class FormattedRecord{ + public: + struct Generic + { +#if ENDIANNESS_IS_BIG + + unsigned int datakey: 1; + unsigned int headertwokey: 1; + unsigned int headerkey: 1; + unsigned int unused2: 29; + +#elif ENDIANNESS_IS_LITTLE + + unsigned int unused2: 29; + unsigned int headerkey: 1; + unsigned int headertwokey: 1; + unsigned int datakey: 1; + +#else + +#error ENDIANNESS is not defined +#endif + }; + struct Header + { +#if ENDIANNESS_IS_BIG + + unsigned int unused1: 2; + unsigned int key: 1; + unsigned int link: 4; + unsigned int l1id: 12; + unsigned int bxid: 13; + +#elif ENDIANNESS_IS_LITTLE + + unsigned int bxid: 13; + unsigned int l1id: 12; + unsigned int link: 4; + unsigned int key: 1; + unsigned int unused1: 2; + +#else + +#error ENDIANNESS is not defined +#endif + }; + + + struct HeaderTwo + { +#if ENDIANNESS_IS_BIG + + unsigned int unused1: 1; + unsigned int key: 1; + unsigned int unused2: 22; + unsigned int rce: 8; + +#elif ENDIANNESS_IS_LITTLE + + unsigned int rce: 8; + unsigned int unused2: 22; + unsigned int key: 1; + unsigned int unused1: 1; + +#else + +#error ENDIANNESS is not defined +#endif + }; + + + struct Data + { +#if ENDIANNESS_IS_BIG + + unsigned int key: 1; + unsigned int unused1: 2; + unsigned int dataflag: 1; + unsigned int fe: 4; + unsigned int tot: 8; + unsigned int col: 7; + unsigned int row: 9; + +#elif ENDIANNESS_IS_LITTLE + + unsigned int row: 9; + unsigned int col: 7; + unsigned int tot: 8; + unsigned int fe: 4; + unsigned int dataflag: 1; + unsigned int unused1: 2; + unsigned int key: 1; + +#else + +#error ENDIANNESS is not defined +#endif + }; + + + union Record + { + unsigned int ui; + Generic ge; + Header he; + Data da; + HeaderTwo ht; + }; + + enum type{HEADER=0x20000000, HEADERTWO=0x40000000, DATA=0x80000000}; + + FormattedRecord(FormattedRecord::type ty){ + m_record.ui=ty; + } + FormattedRecord(unsigned& wd){ + m_record.ui=wd; + } + + bool isHeader(){return m_record.ge.headerkey;} + bool isHeaderTwo(){return m_record.ge.headertwokey;} + bool isData(){return m_record.ge.datakey;} + + unsigned getLink(){return m_record.he.link;} + void setLink(unsigned link){m_record.he.link=link;} + unsigned getBxid(){return m_record.he.bxid;} + void setBxid(unsigned bxid){m_record.he.bxid=bxid;} + unsigned getL1id(){return m_record.he.l1id;} + void setL1id(unsigned l1id){m_record.he.l1id=l1id;} + + unsigned getRCE(){return m_record.ht.rce;} + void setRCE(unsigned rce){m_record.ht.rce=rce;} + + unsigned getFE(){return m_record.da.fe;} + void setFE(unsigned fe){m_record.da.fe=fe;} + unsigned getToT(){return m_record.da.tot;} + void setToT(unsigned tot){m_record.da.tot=tot;} + unsigned getCol(){return m_record.da.col;} + void setCol(unsigned col){m_record.da.col=col;} + unsigned getRow(){return m_record.da.row;} + void setRow(unsigned row){m_record.da.row=row;} + unsigned getDataflag(){return m_record.da.dataflag;} + void setDataflag(unsigned fl){m_record.da.dataflag=fl;} + + unsigned getWord(){return m_record.ui;} + + private: + Record m_record; + }; + +#endif diff --git a/rce/rcecalib/config/HitorTrigger.cc b/rce/rcecalib/config/HitorTrigger.cc new file mode 100644 index 00000000..060f3c03 --- /dev/null +++ b/rce/rcecalib/config/HitorTrigger.cc @@ -0,0 +1,29 @@ + +#include "rcecalib/config/HitorTrigger.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/HW/BitStream.hh" +#include "rcecalib/config/ConfigIF.hh" +#include "rcecalib/config/FEI4/FECommands.hh" +#include "rcecalib/util/exceptions.hh" +#include <iostream> +#include <fstream> +#include <stdlib.h> + + +HitorTrigger::HitorTrigger(ConfigIF* cif):AbsTrigger(), m_configIF(cif){ + //std::cout<<"Hitor trigger"<<std::endl; + } + +int HitorTrigger::configureScan(boost::property_tree::ptree* scanOptions){ + return 0; +} + +int HitorTrigger::sendTrigger(){ + + // read errors + m_configIF->resetErrorCountersHW(); + m_i++; + return 0; +} + + diff --git a/rce/rcecalib/config/HitorTrigger.hh b/rce/rcecalib/config/HitorTrigger.hh new file mode 100644 index 00000000..81b46f7d --- /dev/null +++ b/rce/rcecalib/config/HitorTrigger.hh @@ -0,0 +1,22 @@ +#ifndef HITORTRIGGER_HH +#define HITORTRIGGER_HH + +#include "rcecalib/config/AbsTrigger.hh" +#include <boost/property_tree/ptree_fwd.hpp> +#include <string> + +class ConfigIF; + + class HitorTrigger: public AbsTrigger{ + public: + HitorTrigger(ConfigIF* cif); + ~HitorTrigger(){}; + int sendTrigger(); + int enableTrigger(bool on){return 0;} + int configureScan(boost::property_tree::ptree* scanOptions); + private: + ConfigIF* m_configIF; + }; + + +#endif diff --git a/rce/rcecalib/config/IPCConfigIF.cc b/rce/rcecalib/config/IPCConfigIF.cc new file mode 100644 index 00000000..ac9b9e06 --- /dev/null +++ b/rce/rcecalib/config/IPCConfigIF.cc @@ -0,0 +1,140 @@ +#ifndef IPCCONFIGIF_CC +#define IPCCONFIGIF_CC + +#include "rcecalib/config/IPCConfigIF.hh" + +template <class TP> +IPCConfigIF<TP>::IPCConfigIF(IPCPartition & p, const char * name, ModuleFactory* mf): + IPCNamedObject<POA_ipc::IPCConfigIFAdapter, TP>( p, name ) , ConfigIF(mf){ + try { + IPCNamedObject<POA_ipc::IPCConfigIFAdapter,TP>::publish(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } +} + +template <class TP> +IPCConfigIF<TP>::~IPCConfigIF(){ + try { + IPCNamedObject<POA_ipc::IPCConfigIFAdapter,TP>::withdraw(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::warning( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } +} + +//template <class TP> +//void IPCConfigIF<TP>::IPCsetupParameter(const char* name, CORBA::Long val){ +// setupParameter(name, val); +//} +template <class TP> +CORBA::ULong IPCConfigIF<TP>::IPCsetupParameter(const char* name, CORBA::Long val){ + setupParameter(name, val, false); //do not enable data taking because chip may be unconfigured + return 0; +} +template <class TP> +void IPCConfigIF<TP>::IPCsetupMaskStage(CORBA::Long stage){ + setupMaskStage(stage); +} +template <class TP> +void IPCConfigIF<TP>::IPCsendTrigger(){ + sendTrigger(); +} +template <class TP> +void IPCConfigIF<TP>::IPCenableTrigger(){ + enableTrigger(); +} +template <class TP> +void IPCConfigIF<TP>::IPCdisableTrigger(){ + disableTrigger(); +} +template <class TP> +void IPCConfigIF<TP>::IPCresetFE(){ + resetFE(); +} +template <class TP> +void IPCConfigIF<TP>::IPCconfigureModulesHW(){ + configureModulesHW(); +} +template <class TP> +CORBA::Long IPCConfigIF<TP>::IPCverifyModuleConfigHW(CORBA::Long id){ + return verifyModuleConfigHW(id); +} +template <class TP> +CORBA::ULong IPCConfigIF<TP>::IPCwriteHWregister(CORBA::ULong addr, CORBA::ULong val){ + return writeHWregister(addr,val); +} + +template <class TP> +CORBA::ULong IPCConfigIF<TP>::IPCreadHWregister(CORBA::ULong addr, CORBA::ULong& val){ + return readHWregister(addr, (unsigned int&)val); +} + +template <class TP> +CORBA::ULong IPCConfigIF<TP>::IPCsendHWcommand(CORBA::Octet opcode){ + return sendHWcommand(opcode); +} + +template <class TP> +CORBA::ULong IPCConfigIF<TP>::IPCwriteHWblockData(const ipc::blockdata& data){ + std::vector<unsigned> bldat; + for(size_t i=0;i<data.length();i++)bldat.push_back(data[i]); + return writeHWblockData(bldat); +} + +template <class TP> +CORBA::ULong IPCConfigIF<TP>::IPCreadHWblockData(const ipc::blockdata& data, ipc::blockdata_out retv){ + std::vector<unsigned> bldat; + for(size_t i=0;i<data.length();i++)bldat.push_back(data[i]); + std::vector<unsigned> retvec; + unsigned retval=readHWblockData(bldat, retvec); + retv=new ipc::blockdata; + retv->length(retvec.size()); + for(size_t i=0;i<retvec.size();i++)retv[i]=(CORBA::ULong)retvec[i]; + return retval; +} +template <class TP> +CORBA::ULong IPCConfigIF<TP>::IPCreadHWbuffers(ipc::chardata_out retv){ + std::vector<unsigned char> retvec; + unsigned retval=readHWbuffers(retvec); + retv=new ipc::chardata; + retv->length(retvec.size()); + for(size_t i=0;i<retvec.size();i++)retv[i]=(CORBA::Octet)retvec[i]; + return retval; +} + +template <class TP> +CORBA::Long IPCConfigIF<TP>::IPCnTrigger(){ + return nTrigger(); +} +template <class TP> +CORBA::Long IPCConfigIF<TP>::IPCsetupTriggerIF(const char* type){ + setupTriggerIF(type); + return 0; +} +template <class TP> +CORBA::Long IPCConfigIF<TP>::IPCsetupModule(const char* name, const char* type, const ipc::ModSetup& par, const char* formatter){ + //std::cout<<"IPCsetupModule"<<std::endl; + return setupModule(name, type, par.id, par.inLink, par.outLink, formatter); +} +template <class TP> +CORBA::Long IPCConfigIF<TP>::IPCdeleteModules(){ + deleteModules(); + return 0; +} +template <class TP> +void IPCConfigIF<TP>::shutdown(){ + std::cout<<"Shutdown"<<std::endl; +} + +#endif diff --git a/rce/rcecalib/config/IPCConfigIF.hh b/rce/rcecalib/config/IPCConfigIF.hh new file mode 100644 index 00000000..eb9f8d3f --- /dev/null +++ b/rce/rcecalib/config/IPCConfigIF.hh @@ -0,0 +1,41 @@ +#ifndef IPCCONFIGIF_HH +#define IPCCONFIGIF_HH + +#include "IPCConfigIFAdapter.hh" +#include "ipc/object.h" +#include "rcecalib/config/ConfigIF.hh" +#include "rcecalib/config/ModuleFactory.hh" +#include <omnithread.h> + +class IPCPartition; + +template <class TP = ipc::single_thread> +class IPCConfigIF: public IPCNamedObject<POA_ipc::IPCConfigIFAdapter,TP>, public ConfigIF { +public: + IPCConfigIF(IPCPartition & p, const char * name, ModuleFactory* mf); + ~IPCConfigIF(); + void IPCsendTrigger(); + //void IPCsetupParameter(const char* name, CORBA::Long val); + CORBA::ULong IPCsetupParameter(const char* name, CORBA::Long val); + void IPCsetupMaskStage(CORBA::Long stage); + void IPCenableTrigger(); + void IPCdisableTrigger(); + void IPCresetFE(); + void IPCconfigureModulesHW(); + CORBA::Long IPCverifyModuleConfigHW(CORBA::Long id); + CORBA::ULong IPCwriteHWregister(CORBA::ULong addr, CORBA::ULong val); + CORBA::ULong IPCsendHWcommand(CORBA::Octet opcode); + CORBA::ULong IPCwriteHWblockData(const ipc::blockdata& data); + CORBA::ULong IPCreadHWblockData(const ipc::blockdata & data, ipc::blockdata_out retv); + CORBA::ULong IPCreadHWbuffers(ipc::chardata_out retv); + CORBA::ULong IPCreadHWregister(CORBA::ULong addr, CORBA::ULong &val); + CORBA::Long IPCdeleteModules(); + CORBA::Long IPCnTrigger(); + CORBA::Long IPCsetupTriggerIF(const char* type); + CORBA::Long IPCsetupModule(const char* name, const char* type, const ipc::ModSetup& par, const char* formatter); + void shutdown(); + +}; + + +#endif diff --git a/rce/rcecalib/config/IPCModuleFactory.cc b/rce/rcecalib/config/IPCModuleFactory.cc new file mode 100644 index 00000000..52598994 --- /dev/null +++ b/rce/rcecalib/config/IPCModuleFactory.cc @@ -0,0 +1,146 @@ +#include "rcecalib/config/IPCModuleFactory.hh" +#include "rcecalib/config/DummyFormatter.hh" +#include "rcecalib/config/FEI3/JJFormatter.hh" +#include "rcecalib/config/FEI4/FEI4AFormatter.hh" +#include "rcecalib/config/FEI4/FEI4BFormatter.hh" +#include "rcecalib/config/FEI4/FEI4HitorFormatter.hh" +#include "rcecalib/config/FEI4/FEI4OccFormatter.hh" +#include "rcecalib/config/FEI3/Module.hh" +#include "rcecalib/config/FEI3/IPCModule.cc" +#include "rcecalib/config/FEI4/IPCFEI4AModule.cc" +#include "rcecalib/config/FEI4/IPCFEI4BModule.cc" +#include "rcecalib/config/hitbus/IPCModule.cc" +#include "rcecalib/config/afp-hptdc/IPCModule.cc" +#include "rcecalib/config/afp-hptdc/AFPHPTDCFormatter.hh" +#include "rcecalib/config/Trigger.hh" +#include "rcecalib/config/MultiTrigger.hh" +#include "rcecalib/config/EventFromFileTrigger.hh" +#include "rcecalib/config/MeasurementTrigger.hh" +#include "rcecalib/config/MultiShotTrigger.hh" +#include "rcecalib/config/HitorTrigger.hh" +#include "rcecalib/config/FEI4/TemperatureTrigger.hh" +#include "rcecalib/config/FEI4/MonleakTrigger.hh" +#include "rcecalib/config/FEI4/SNTrigger.hh" +#include "rcecalib/config/FEI4/Fei4RegisterTestTrigger.hh" +#include "rcecalib/util/exceptions.hh" +#include "stdio.h" +#include <iostream> + +IPCModuleFactory::IPCModuleFactory(IPCPartition& p):ModuleFactory(),m_partition(p){ + m_modulegroups.push_back(&m_modgroupi3); + m_modulegroups.push_back(&m_modgroupi4a); + m_modulegroups.push_back(&m_modgroupi4b); + m_modulegroups.push_back(&m_modgrouphitbus); + m_modulegroups.push_back(&m_modgroupafphptdc); +} + + +AbsFormatter* IPCModuleFactory::createFormatter(const char* formatter, int id){ + + // create formatter first + if(std::string(formatter)=="JJ") + return new JJFormatter(id); + else if(std::string(formatter)=="") + return 0; + else if(std::string(formatter)=="FEI4A") + return new FEI4AFormatter(id); + else if(std::string(formatter)=="FEI4B") + return new FEI4BFormatter(id); + else if(std::string(formatter)=="FEI4Hitor") + return new FEI4HitorFormatter(id); + else if(std::string(formatter)=="FEI4Occ") + return new FEI4OccFormatter(id); + else if(std::string(formatter)=="AFPHPTDC") + return new AFPHPTDCFormatter(id); + else if(std::string(formatter)=="Dummy") + return new DummyFormatter(id); + else{ + std::cout<<"Unknown formatter "<<formatter<<std::endl; + assert(0); + } +} + +AbsModule* IPCModuleFactory::createModule(const char* name, const char* type, unsigned id, unsigned inLink, unsigned outLink, const char* formatter){ + AbsFormatter* theformatter=createFormatter(formatter, id); + if(std::string(type)=="FEI3"){ + FEI3::Module *mod= new FEI3::Module(name, id, inLink, outLink, theformatter); + m_modgroupi3.addModule(mod); + return mod; + } + if(std::string(type)=="IPC_FEI3_singleThread"){ + FEI3::Module *mod= new FEI3::IPCModule<ipc::single_thread>(m_partition, name,id, inLink, outLink, theformatter); + m_modgroupi3.addModule(mod); + return mod; + } + if(std::string(type)=="IPC_FEI3_multiThread"){ + FEI3::Module *mod= new FEI3::IPCModule<ipc::multi_thread>(m_partition, name,id, inLink, outLink, theformatter); + m_modgroupi3.addModule(mod); + return mod; + } + if(std::string(type)=="IPC_FEI4A_singleThread"){ + FEI4::Module *mod= new FEI4::IPCFEI4AModule<ipc::single_thread>(m_partition, name,id, inLink, outLink, theformatter); + m_modgroupi4a.addModule(mod); + return mod; + } + if(std::string(type)=="IPC_FEI4A_multiThread"){ + FEI4::Module *mod= new FEI4::IPCFEI4AModule<ipc::multi_thread>(m_partition, name,id, inLink, outLink, theformatter); + m_modgroupi4a.addModule(mod); + return mod; + } + if(std::string(type)=="IPC_FEI4B_singleThread"){ + FEI4::Module *mod= new FEI4::IPCFEI4BModule<ipc::single_thread>(m_partition, name,id, inLink, outLink, theformatter); + m_modgroupi4b.addModule(mod); + return mod; + } + if(std::string(type)=="IPC_FEI4B_multiThread"){ + FEI4::Module *mod= new FEI4::IPCFEI4BModule<ipc::multi_thread>(m_partition, name,id, inLink, outLink, theformatter); + m_modgroupi4b.addModule(mod); + return mod; + } + if(std::string(type)=="IPC_Hitbus_singleThread"){ + Hitbus::Module *mod= new Hitbus::IPCModule<ipc::single_thread>(m_partition, name,id, inLink, outLink, theformatter); + m_modgrouphitbus.addModule(mod); + return mod; + } + if(std::string(type)=="IPC_Hitbus_multiThread"){ + Hitbus::Module *mod= new Hitbus::IPCModule<ipc::multi_thread>(m_partition, name,id, inLink, outLink, theformatter); + m_modgrouphitbus.addModule(mod); + return mod; + } + if(std::string(type)=="IPC_AFPHPTDC_singleThread"){ + afphptdc::Module *mod= new afphptdc::IPCModule<ipc::single_thread>(m_partition, name,id, inLink, outLink, theformatter); + m_modgroupafphptdc.addModule(mod); + return mod; + } + if(std::string(type)=="IPC_AFPHPTDC_multiThread"){ + std::cout<<"Adding module"<<std::endl; + afphptdc::Module *mod= new afphptdc::IPCModule<ipc::multi_thread>(m_partition, name,id, inLink, outLink, theformatter); + std::cout<<"Added module"<<std::endl; + m_modgroupafphptdc.addModule(mod); + return mod; + } + std::cout<<"Unknown module type "<<type<<std::endl; + rcecalib::Unknown_Module_Type issue(ERS_HERE,type); + throw issue; + return 0; +} + +AbsTrigger* IPCModuleFactory::createTriggerIF(const char* type, ConfigIF* cif){ + // std::cout << "Creating trigger of type " << type << std::endl; + if(std::string(type)=="default") return new FEI3::Trigger; + else if(std::string(type)=="FEI3")return new FEI3::Trigger; + else if(std::string(type)=="EventFromFile")return new EventFromFileTrigger; + else if(std::string(type)=="MultiShot")return new MultiShotTrigger; + else if(std::string(type)=="MultiTrigger")return new MultiTrigger; + else if(std::string(type)=="Hitor")return new HitorTrigger(cif); + else if(std::string(type)=="Temperature")return new FEI4::TemperatureTrigger; + else if(std::string(type)=="Monleak")return new FEI4::MonleakTrigger; + else if(std::string(type)=="SerialNumber")return new FEI4::SNTrigger; + else if(std::string(type)=="Fei4RegisterTest")return new FEI4::Fei4RegisterTestTrigger; +#ifdef __rtems__ + else if(std::string(type)=="Measurement")return new MeasurementTrigger; +#endif + char msg[128]; + sprintf(msg, "No Trigger type %s",type); + ERS_ASSERT_MSG(0,msg); +} diff --git a/rce/rcecalib/config/IPCModuleFactory.hh b/rce/rcecalib/config/IPCModuleFactory.hh new file mode 100644 index 00000000..3b593aa3 --- /dev/null +++ b/rce/rcecalib/config/IPCModuleFactory.hh @@ -0,0 +1,32 @@ +#ifndef IPCMODULEFACTORY_HH +#define IPCMODULEFACTORY_HH + +#include "ipc/partition.h" + +#include "rcecalib/config/ModuleFactory.hh" +#include "rcecalib/config/FEI3/ModuleGroup.hh" +#include "rcecalib/config/FEI4/ModuleGroup.hh" +#include "rcecalib/config/hitbus/ModuleGroup.hh" +#include "rcecalib/config/afp-hptdc/ModuleGroup.hh" + +class ConfigIF; +class AbsFormatter; + +class IPCModuleFactory: public ModuleFactory { +public: + IPCModuleFactory(IPCPartition &p); + AbsModule* createModule(const char* name, const char* type, unsigned id, unsigned inpos, unsigned outPos, const char* formatter); + AbsFormatter* createFormatter(const char* formatter, int id); + AbsTrigger* createTriggerIF(const char* type, ConfigIF* cif); +private: + IPCPartition &m_partition; + FEI3::ModuleGroup m_modgroupi3; + FEI4::ModuleGroup m_modgroupi4a; + FEI4::ModuleGroup m_modgroupi4b; + Hitbus::ModuleGroup m_modgrouphitbus; + afphptdc::ModuleGroup m_modgroupafphptdc; + +}; + + +#endif diff --git a/rce/rcecalib/config/Makefile b/rce/rcecalib/config/Makefile new file mode 100644 index 00000000..c73fd5ec --- /dev/null +++ b/rce/rcecalib/config/Makefile @@ -0,0 +1,20 @@ +# Package level makefile +# ---------------------- +%.mk:; + +# Checks +# ------ +# Check release location variables +ifeq ($(RELEASE_DIR),) +export RELEASE_DIR := $(PWD)/../.. +endif + +include $(RELEASE_DIR)/make/share/setup.mk +include ../flags.mk + +ifndef PREMAKE_DONE +include $(RELEASE_DIR)/make/share/premake.mk +else +include constituents.mk +include $(RELEASE_DIR)/make/sw/package.mk +endif diff --git a/rce/rcecalib/config/MaskStageFactory.hh b/rce/rcecalib/config/MaskStageFactory.hh new file mode 100644 index 00000000..1bb714f1 --- /dev/null +++ b/rce/rcecalib/config/MaskStageFactory.hh @@ -0,0 +1,17 @@ +#ifndef MASKSTAGEFACTORY_HH +#define MASKSTAGEFACTORY_HH + +#include "rcecalib/config/Masks.hh" +#include "rcecalib/config/MaskStaging.hh" + +class MaskStageFactory{ +public: + MaskStageFactory(){} + ~MaskStageFactory(){} + template <typename T> + MaskStaging<T>* createMaskStaging(T* mod, const char* maskStagingType, const char* maskStagingMode); + template <typename T> + Masks createIOmasks(const char* maskStagingMode); +}; + +#endif diff --git a/rce/rcecalib/config/MaskStaging.hh b/rce/rcecalib/config/MaskStaging.hh new file mode 100644 index 00000000..f4e7a787 --- /dev/null +++ b/rce/rcecalib/config/MaskStaging.hh @@ -0,0 +1,29 @@ +#ifndef MASKSTAGING_HH +#define MASKSTAGING_HH + +#include "rcecalib/config/Masks.hh" +#include <string> + +template <typename T> +class MaskStaging{ +public: + MaskStaging(T *module, Masks masks, std::string stagingType): + m_masks(masks), m_module(module), m_type(stagingType), m_initialized(false){} + virtual void setupMaskStageHW(int maskStage)=0; + virtual void clearBitsHW(); + virtual bool cLow(); + virtual bool cHigh(); + void setClow(bool i){m_clow=i;} + void setChigh(bool i){m_chigh=i;} + bool initialized(){return m_initialized;} +protected: + Masks m_masks; + T* m_module; + std::string m_type; + bool m_clow; + bool m_chigh; + bool m_initialized; +}; + + +#endif diff --git a/rce/rcecalib/config/Masks.hh b/rce/rcecalib/config/Masks.hh new file mode 100644 index 00000000..13af206c --- /dev/null +++ b/rce/rcecalib/config/Masks.hh @@ -0,0 +1,12 @@ +#ifndef MASKS_HH +#define MASKS_HH + + struct Masks{ + unsigned short oMask; + unsigned short iMask; + unsigned short xtalk_on; + unsigned short xtalk_off; + bool crosstalking; + }; + +#endif diff --git a/rce/rcecalib/config/MeasurementTrigger.cc b/rce/rcecalib/config/MeasurementTrigger.cc new file mode 100644 index 00000000..77630777 --- /dev/null +++ b/rce/rcecalib/config/MeasurementTrigger.cc @@ -0,0 +1,29 @@ + +#include "rcecalib/config/MeasurementTrigger.hh" +#include <boost/property_tree/ptree.hpp> +#include <boost/regex.hpp> +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/config/TriggerReceiverIF.hh" +#include <iostream> +#include <fstream> +#include <stdlib.h> + + +MeasurementTrigger::MeasurementTrigger():AbsTrigger(){ + //std::cout<<"Measurement trigger"<<std::endl; + } + +int MeasurementTrigger::configureScan(boost::property_tree::ptree* scanOptions){ + // number of triggers + m_i=0; + return 0; +} + +int MeasurementTrigger::sendTrigger(){ + //trigger the measurement + TriggerReceiverIF::receive(0, 0); + m_i++; + return 0; +} + + diff --git a/rce/rcecalib/config/MeasurementTrigger.hh b/rce/rcecalib/config/MeasurementTrigger.hh new file mode 100644 index 00000000..bc4e7447 --- /dev/null +++ b/rce/rcecalib/config/MeasurementTrigger.hh @@ -0,0 +1,18 @@ +#ifndef MEASUREMENTTRIGGER_HH +#define MEASUREMENTTRIGGER_HH + +#include "rcecalib/config/AbsTrigger.hh" +#include <boost/property_tree/ptree_fwd.hpp> +#include <string> + + class MeasurementTrigger: public AbsTrigger{ + public: + MeasurementTrigger(); + ~MeasurementTrigger(){}; + int sendTrigger(); + int enableTrigger(bool on){return 0;} + int configureScan(boost::property_tree::ptree* scanOptions); + }; + + +#endif diff --git a/rce/rcecalib/config/ModuleFactory.hh b/rce/rcecalib/config/ModuleFactory.hh new file mode 100644 index 00000000..9b01340a --- /dev/null +++ b/rce/rcecalib/config/ModuleFactory.hh @@ -0,0 +1,22 @@ +#ifndef MODULEFACTORY_HH +#define MODULEFACTORY_HH + +#include "rcecalib/config/AbsModule.hh" +#include "rcecalib/config/AbsModuleGroup.hh" +#include "rcecalib/config/AbsTrigger.hh" + +class ConfigIF; + +class ModuleFactory{ +public: + ModuleFactory(){}; + virtual ~ModuleFactory(){}; + virtual AbsModule* createModule(const char* name, const char* type, unsigned id, unsigned inlink, unsigned outlink, const char* formatter)=0; + virtual AbsTrigger* createTriggerIF(const char* type, ConfigIF* cif)=0; + std::vector<AbsModuleGroup*> &getModuleGroups(){return m_modulegroups;} +protected: + std::vector<AbsModuleGroup*> m_modulegroups; +}; + + +#endif diff --git a/rce/rcecalib/config/ModuleInfo.hh b/rce/rcecalib/config/ModuleInfo.hh new file mode 100644 index 00000000..4cd1f5de --- /dev/null +++ b/rce/rcecalib/config/ModuleInfo.hh @@ -0,0 +1,32 @@ +#ifndef MODULEINFO_HH +#define MODULEINFO_HH + +class AbsFormatter; + +class ModuleInfo{ +public: + ModuleInfo(std::string name, int id, int inLink, int outLink, + int nFE, int nRow, int nCol, AbsFormatter* fmt): + m_name(name), m_id(id),m_inLink(inLink),m_outLink(outLink), + m_nFE(nFE), m_nRow(nRow), m_nCol(nCol), m_formatter(fmt){} + std::string getName(){return m_name;} + int getId(){return m_id;} + int getInLink(){return m_inLink;} + int getOutLink(){return m_outLink;} + int getNFrontends(){return m_nFE;} + int getNRows(){return m_nRow;} + int getNColumns(){return m_nCol;} + AbsFormatter* getFormatter(){return m_formatter;} + +private: + std::string m_name; + int m_id; + int m_inLink; + int m_outLink; + int m_nFE; + int m_nRow; + int m_nCol; + AbsFormatter* m_formatter; +}; + +#endif diff --git a/rce/rcecalib/config/MultiShotTrigger.cc b/rce/rcecalib/config/MultiShotTrigger.cc new file mode 100644 index 00000000..8a791940 --- /dev/null +++ b/rce/rcecalib/config/MultiShotTrigger.cc @@ -0,0 +1,78 @@ + +#include "rcecalib/config/MultiShotTrigger.hh" +#include "rcecalib/config/FEI3/FECommands.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/HW/SerialIF.hh" + + +MultiShotTrigger::MultiShotTrigger():AbsTrigger(),m_ntrig(0), m_interval(0){ + m_parameters.push_back("TRIGGER_DELAY"); +} +int MultiShotTrigger::configureScan(boost::property_tree::ptree* scanOptions){ + int retval=0; + m_i=0; //reset the number of triggers + try{ + m_ntrig = scanOptions->get<int>("trigOpt.nTriggersPerGroup"); + m_leading0 = scanOptions->get<int>("trigOpt.CalL1ADelay"); + m_interval=scanOptions->get<int>("trigOpt.Lvl1_Latency_Secondary"); + std::cout<<"Setting up "<<m_ntrig<<" Triggers with an interval of "<<m_interval<<std::endl; + setupTriggerStream(); + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + retval=1; + } + return retval; +} +int MultiShotTrigger::setupParameter(const char* name, int val){ + return 0; +} + +void MultiShotTrigger::setupTriggerStream(){ + m_triggerStream.clear(); + int totallength=m_leading0+m_ntrig*5+(m_ntrig-1)*(m_interval-5); + for(int i=0;i<totallength/32;i++)m_triggerStream.push_back(0); + if(totallength%32!=0)m_triggerStream.push_back(0); + for(int i=0;i<5;i++){ + if(i==3)continue; + for(int j=0;j<m_ntrig;j++){ + int bit=m_leading0+i+j*m_interval; + setBit(m_triggerStream,bit); + } + } + SerialIF::writeRegister(19,0); + for (size_t i=0;i<m_triggerStream.size();i++){ + SerialIF::writeRegister(18,m_triggerStream[i]); + std::cout<<std::hex<<m_triggerStream[i]<<std::dec<<std::endl; + } + SerialIF::writeRegister(27,1); +} +void MultiShotTrigger::setBit(std::vector<unsigned> &vec, int bit){ + int wordpos=bit/32; + int bitpos=31-bit%32; + if(vec.size()<=(unsigned)wordpos)return; + vec[wordpos]|=1<<bitpos; +} + +int MultiShotTrigger::sendTrigger(){ + //std::cout<<"Trigger::Trigger "<<m_i<<std::endl; + SerialIF::send(&m_triggerStream,SerialIF::DONT_CLEAR|SerialIF::WAITFORDATA); + m_i++; + return 0; +} + +int MultiShotTrigger::enableTrigger(bool on){ + return SerialIF::enableTrigger(on); + return 0; +} +int MultiShotTrigger::resetCounters(){ + BitStream *bs=new BitStream; + BitStreamUtils::prependZeros(bs); + FEI3::FECommands::sendECR(bs); + FEI3::FECommands::sendBCR(bs); + SerialIF::send(bs,SerialIF::WAITFORDATA); + delete bs; + return 0; +} diff --git a/rce/rcecalib/config/MultiShotTrigger.hh b/rce/rcecalib/config/MultiShotTrigger.hh new file mode 100644 index 00000000..e669397c --- /dev/null +++ b/rce/rcecalib/config/MultiShotTrigger.hh @@ -0,0 +1,28 @@ +#ifndef MULTISHOTTRIGGER_HH +#define MULTISHOTTRIGGER_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/config/AbsTrigger.hh" +#include "rcecalib/HW/BitStream.hh" + + + class MultiShotTrigger: public AbsTrigger{ + public: + MultiShotTrigger(); + ~MultiShotTrigger(){}; + int configureScan(boost::property_tree::ptree* scanOptions); + int setupParameter(const char* name, int val); + int sendTrigger(); + int enableTrigger(bool on); + int resetCounters(); + void setupTriggerStream(); + void setBit(std::vector<unsigned> &vec, int bit); + private: + BitStream m_triggerStream; + int m_ntrig; + int m_interval; + int m_leading0; + }; + + +#endif diff --git a/rce/rcecalib/config/MultiTrigger.cc b/rce/rcecalib/config/MultiTrigger.cc new file mode 100644 index 00000000..c87bd2f4 --- /dev/null +++ b/rce/rcecalib/config/MultiTrigger.cc @@ -0,0 +1,277 @@ + +#include "rcecalib/config/MultiTrigger.hh" +#include "rcecalib/config/FEI3/FECommands.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/HW/SerialIF.hh" +#include "rcecalib/profiler/Profiler.hh" +#ifdef __rtems__ +#include "rcecalib/HW/Headers.hh" +#include "rcecalib/HW/RCDImaster.hh" +#ifdef RCE_V2 +#include "datCode.hh" +#include DAT_PUBLIC( oldPpi, pic, Tds.hh) +#include DAT_PUBLIC( oldPpi, pic, Pool.hh) +#include DAT_PUBLIC( oldPpi, pgp, Driver.hh) +#include DAT_PUBLIC( oldPpi, pgp, DriverList.hh) +#else +#include "rce/pic/Pool.hh" +#include "rce/pgp/Driver.hh" +#include "rce/pgp/DriverList.hh" +#include "rce/pic/Tds.hh" +#endif +#include "namespace_aliases.hh" +using namespace PgpTrans; +#endif + + + MultiTrigger::MultiTrigger():AbsTrigger(), + m_calL1ADelay(-1),m_repetitions(0),m_interval(0),m_nIntervals(0),m_injectForTrigger(1){ + m_parameters.push_back("TRIGGER_DELAY"); + m_parameters.push_back("MULTITRIG_INTERVAL"); +#ifdef __rtems__ + const RcePic::Params Tx = { + RcePic::NonContiguous, + 16, // Header + 64*132, // Payload + 1 // Number of buffers + }; + + m_pool = new RcePic::Pool::Pool(Tx); + m_tds=m_pool->allocate(); + assert (m_tds!=0); + char* header=(char*)m_tds->header(); + int headersize=m_tds->headersize(); + for (int i=0;i<headersize;i++)header[i]=0; + new(m_tds->header())BlockWriteTxHeader(0); +#endif + } + MultiTrigger::~MultiTrigger(){ +#ifdef __rtems__ + m_pool->deallocate(m_tds); + delete m_pool; +#endif + } + int MultiTrigger::configureScan(boost::property_tree::ptree* scanOptions){ + int retval=0; + m_i=0; //reset the number of triggers + try{ + m_calL1ADelay = scanOptions->get<int>("trigOpt.CalL1ADelay"); + m_repetitions = scanOptions->get<int>("trigOpt.nTriggersPerGroup"); + m_injectForTrigger = scanOptions->get<int>("trigOpt.injectForTrigger"); + + std::cout<<"I'm here right?"<<std::endl; + m_nIntervals = scanOptions->get<int>("scanLoop_0.nPoints"); + std::cout<<"intervals = "<<m_nIntervals<<std::endl; + m_intervals.clear(); + + /* + char pointname[100]; + for(int ii=0; ii<m_nIntervals; ii++){ + sprintf(pointname,"scanLoop_1.dataPoints.P_%d",ii); + int interval = scanOptions->get<int>(pointname); + m_intervals.push_back(interval); + std::cout<<"interval_"<<ii<<" = "<<interval<<std::endl; + } + */ + + m_interval = 241; // m_intervals[0]; + std::cout<<"interval = "<<m_interval<<std::endl; + + setupTriggerStream(); + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + retval=1; + } + return retval; + } + + int MultiTrigger::setupParameter(const char* name, int val){ + + if(std::string(name)=="MULTITRIG_INTERVAL"){ + if(val!=m_interval){ // have to redo trigger stream + std::cout<<"Remaking trigger stream with interval "<<val<<std::endl; + m_interval=val; + setupTriggerStream(); + } + } + else if(std::string(name)=="TRIGGER_DELAY"){ + if(val!=m_calL1ADelay){ // have to redo trigger stream + // std::cout<<"Setting up trigger stream. Delay is "<<val<<std::endl; + m_calL1ADelay=val; + setupTriggerStream(); + } + } + return 0; + } + + void MultiTrigger::setupTriggerStream(){ +#ifdef __rtems__ + unsigned* payload=(unsigned*)m_tds->payload(); +#endif + m_triggerStream.clear(); + //prepend 4 zeroes a la NewDsp + BitStreamUtils::prependZeros(&m_triggerStream); + std::vector<char> bytestream; + + /*Create trigger stream */ + /*m_repetitions number of CAL commands, each separated by m_interval zeros. */ + /*Then there is a delay, followed by m_repetitions number of L1A commands. */ + /*The L1A commands are separated by (m_interval+4) zeros, since the L1A commands */ + /*are shorter than CAL commands. */ + /*The delay between the CAL commands and the L1A commands is set by m_calL1ADelay, */ + /*which is the delay between end of the first CAL and end of the first L1A command. */ + /* CAL is a slow command with 9 bits 101100100, L1A is 5 bits 11101*/ + + /*This code only works for m_repetitions=2. */ + + /*WARNING: If m_interval has the wrong value, then */ + /*trigger stream won't make sense, because the CAL command will overlap */ + /*with the L1A's command */ + /*For two-trigger case, this means*/ + /*m_interval <= (m_calL1ADelay-14) or m_interval >= m_calL1ADelay. */ + + std::cout<<"MultiTrigger setup: calL1ADelay = "<<m_calL1ADelay<<" ; interval = "<<m_interval<<" ; repetitions = "<<m_repetitions<<std::endl; + + if(m_repetitions!=2){ + std::cout<<"MultiTrigger currently only implemented for two-trigger case. Ignoring m_repetitions = "<<m_repetitions<<std::endl; + } + + if(m_interval>m_calL1ADelay-14 && m_interval < m_calL1ADelay){ + std::cout<<"ERROR in MultiTrigger.cc: m_interval = "<<m_interval<<" has a forbidden value!"<<std::endl; + std::cout<<"Cannot allow CAL commands and L1A commands to overlap!"<<std::endl; + } + + + int totalLen = 16 + m_interval + 9 + m_calL1ADelay; + int numChars = totalLen/8; + if(totalLen%8 !=0){ + numChars++; + } + + std::cout<<"Making bytestream "<<numChars<<" bytes long."<<std::endl; + + std::vector<char> bytestream1(numChars, 0); + std::vector<char> bytestream2(numChars, 0); + std::vector<char> bytestream3(numChars, 0); + std::vector<char> bytestream4(numChars, 0); + + //m_injectForTrigger is a bit mask. if bit 0 is enabled, then inject on first trigger. + //if bit 1 is enabled, then inject on second trigger. + + if( m_injectForTrigger&1 ){ + //do a pulse injection for the first trigger + createByteStream(bytestream1,0x0164,9,7); /* 101100100 (9bits) = CAL */ + } + // else{ + // //don't do a pulse injection for the first trigger + // createByteStream(bytestream1,0x0000,9,7); + // } + + if( m_injectForTrigger&2 ){ + //do a pulse injection for the second trigger + createByteStream(bytestream2,0x0164,9,16+m_interval); //2nd CAL command + } + + createByteStream(bytestream3,0x1d,5,16+m_calL1ADelay-5); /* 11101 (5bits) = L1A */ + createByteStream(bytestream4,0x1d,5,16+m_interval+9+m_calL1ADelay-5); //2nd L1A command + + + //The overall bytestream is the logical OR of each of the individual bytestreams + for(int ibyte=0; ibyte<numChars; ibyte++){ + + char finalByte = bytestream1[ibyte]; + finalByte = finalByte | bytestream2[ibyte]; + finalByte = finalByte | bytestream3[ibyte]; + finalByte = finalByte | bytestream4[ibyte]; + + bytestream.push_back(finalByte); + } + + while(bytestream.size()%4!=0)bytestream.push_back(0); + + + // for (size_t i=0;i<bytestream.size();i++)std::cout<<std::hex<<(unsigned)bytestream[i]<<std::dec<<std::endl; + // std::cout<<"byte stream size is "<<bytestream.size()<<std::endl; + + for(unsigned int i=0;i<bytestream.size()/4;i++){ + unsigned word=0; + for (int j=0;j<4;j++){ + word<<=8; + word|=bytestream[i*4+j]; + } + m_triggerStream.push_back(word); + } + + + //std::cout<<"Length of trigger stream is "<<m_triggerStream.size()<<std::endl; + //for(size_t i=0; i<m_triggerStream.size(); i++){ + // std::cout<<std::hex<<(unsigned)m_triggerStream[i]<<std::dec<<std::endl; + //} + + + //SerialIF::writeRegister(19,0); + //for (size_t i=0;i<m_triggerStream.size();i++)SerialIF::writeRegister(18,m_triggerStream[i]); +#ifdef __rtems__ + for (size_t i=0;i<m_triggerStream.size();i++)payload[i]=m_triggerStream[i]; + m_tds->payloadsize(m_triggerStream.size()*sizeof(unsigned)); + m_tds->flush(true); +#endif + } + + int MultiTrigger::sendTrigger(){ +#ifdef __rtems__ + RCDImaster::instance()->blockWrite(m_tds); + //SerialIF::sendCommand(0xa); +#else + SerialIF::send(&m_triggerStream,SerialIF::DONT_CLEAR|SerialIF::WAITFORDATA); +#endif + m_i++; + return 0; + } + + int MultiTrigger::enableTrigger(bool on){ + return SerialIF::enableTrigger(on); + return 0; + } + int MultiTrigger::resetCounters(){ + BitStream *bs=new BitStream; + BitStreamUtils::prependZeros(bs); + FEI3::FECommands::sendECR(bs); + FEI3::FECommands::sendBCR(bs); + SerialIF::send(bs,SerialIF::WAITFORDATA); + delete bs; + return 0; + } + +void MultiTrigger::createByteStream(std::vector<char>& stream, unsigned int command, unsigned int len, unsigned int offset){ + + // std::cout<<"byte stream "<<command<<" length = "<<len<<" offset = "<<offset<<std::endl; + + assert(len<=9); //if len>9, some parts of function would have to change + + int shift = 16 - len; + command = (command<<shift); + + unsigned int numChars = offset/8; + offset = offset%8; + + //if len>9, then the following command could potentially erase bits, which we don't want + command = (command>>offset); + char byte1 = (command >> 8 ) & 0xff; + char byte2 = command & 0xff; + + stream[numChars] = byte1; + if( (offset+len)>8 ){ + stream[numChars+1] = byte2; + } + + + // for(size_t i=0; i<stream.size(); i++){ + // std::cout<<std::hex<<(unsigned)stream[i]<<std::dec<<std::endl; + // } + // std::cout<<std::endl<<std::endl; + +} diff --git a/rce/rcecalib/config/MultiTrigger.hh b/rce/rcecalib/config/MultiTrigger.hh new file mode 100644 index 00000000..cca02d68 --- /dev/null +++ b/rce/rcecalib/config/MultiTrigger.hh @@ -0,0 +1,36 @@ +#ifndef MULTITRIGGER_HH +#define MULTITRIGGER_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/config/AbsTrigger.hh" +#include "rcecalib/HW/BitStream.hh" +#include "namespace_aliases.hh" + + + + + class MultiTrigger: public AbsTrigger{ + public: + MultiTrigger(); + ~MultiTrigger(); + int configureScan(boost::property_tree::ptree* scanOptions); + int setupParameter(const char* name, int val); + int sendTrigger(); + int enableTrigger(bool on); + int resetCounters(); + void setupTriggerStream(); + private: + void createByteStream(std::vector<char>& stream, unsigned int command, unsigned int len, unsigned int offset); + BitStream m_triggerStream; + int m_calL1ADelay; + int m_repetitions; + int m_interval; + int m_nIntervals; + std::vector<int> m_intervals; + int m_injectForTrigger; + RcePic::Tds* m_tds; + RcePic::Pool *m_pool; + }; + + +#endif diff --git a/rce/rcecalib/config/Trigger.cc b/rce/rcecalib/config/Trigger.cc new file mode 100644 index 00000000..cdde49f9 --- /dev/null +++ b/rce/rcecalib/config/Trigger.cc @@ -0,0 +1,154 @@ + +#include "rcecalib/config/Trigger.hh" +#include "rcecalib/config/FEI3/FECommands.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/HW/SerialIF.hh" +#include "rcecalib/profiler/Profiler.hh" +#ifdef __rtems__ +#include "rcecalib/HW/Headers.hh" +#include "rcecalib/HW/RCDImaster.hh" +#ifdef RCE_V2 +#include "datCode.hh" +#include DAT_PUBLIC( oldPpi, pic, Tds.hh) +#include DAT_PUBLIC( oldPpi, pic, Pool.hh) +#include DAT_PUBLIC( oldPpi, pgp, Driver.hh) +#include DAT_PUBLIC( oldPpi, pgp, DriverList.hh) +#else +#include "rce/pic/Pool.hh" +#include "rce/pgp/Driver.hh" +#include "rce/pgp/DriverList.hh" +#include "rce/pic/Tds.hh" +#endif +#include "namespace_aliases.hh" +using namespace PgpTrans; +#endif + +namespace FEI3{ + + Trigger::Trigger():AbsTrigger(),m_calL1ADelay(-1){ + m_parameters.push_back("TRIGGER_DELAY"); +#ifdef __rtems__ + const RcePic::Params Tx = { + RcePic::NonContiguous, + 16, // Header + 64*132, // Payload + 1 // Number of buffers + }; + + m_pool = new RcePic::Pool::Pool(Tx); + m_tds=m_pool->allocate(); + assert (m_tds!=0); + char* header=(char*)m_tds->header(); + int headersize=m_tds->headersize(); + for (int i=0;i<headersize;i++)header[i]=0; + new(m_tds->header())BlockWriteTxHeader(0); +#endif + } + Trigger::~Trigger(){ +#ifdef __rtems__ + m_pool->deallocate(m_tds); + delete m_pool; +#endif + } + int Trigger::configureScan(boost::property_tree::ptree* scanOptions){ + int retval=0; + m_i=0; //reset the number of triggers + try{ + int calL1ADelay = scanOptions->get<int>("trigOpt.CalL1ADelay"); + if(calL1ADelay==-1 || calL1ADelay!=m_calL1ADelay){ // have to redo trigger stream + m_calL1ADelay=calL1ADelay; + setupTriggerStream(); + } + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + retval=1; + } + return retval; + } + int Trigger::setupParameter(const char* name, int val){ + if(std::string(name)=="TRIGGER_DELAY"){ + if(val!=m_calL1ADelay){ // have to redo trigger stream + // std::cout<<"Setting up trigger stream. Delay is "<<val<<std::endl; + m_calL1ADelay=val; + setupTriggerStream(); + } + } + return 0; + } + + void Trigger::setupTriggerStream(){ +#ifdef __rtems__ + unsigned* payload=(unsigned*)m_tds->payload(); +#endif + m_triggerStream.clear(); + //prepend 4 zeroes a la NewDsp + BitStreamUtils::prependZeros(&m_triggerStream); + std::vector<char> bytestream; + /* calculate the size required for this stream */ + /*trigger delay is between end of CAL and L1A command */ + /* CAL is a slow command with 9 bits 101100100, L1A is 5 bits 11101*/ + /* form the trigger stream */ + bytestream.push_back(0x01); + bytestream.push_back(0x64); /* 101100100 (9bits) = CAL */ + /* at this point, still have to provide (delay - 5) zero bits */ + if(m_calL1ADelay!=0xffff){ + int nBits = m_calL1ADelay - 5; + int nBytes = nBits >> 3; + for(int k=0;k<nBytes;++k) bytestream.push_back(0); + unsigned short t = (0xE800 >> (nBits & 0x7)); + bytestream.push_back((t >> 8) & 0xff); + bytestream.push_back(t & 0xff); + }else{ + std::cout<<"CAL strobe only."<<std::endl; + } + while(bytestream.size()%4!=0)bytestream.push_back(0); + //for (size_t i=0;i<bytestream.size();i++)std::cout<<std::hex<<(unsigned)bytestream[i]<<std::dec<<std::endl; + //std::cout<<"Size is "<<bytestream.size()<<std::endl; + for(unsigned int i=0;i<bytestream.size()/4;i++){ + unsigned word=0; + for (int j=0;j<4;j++){ + word<<=8; + word|=bytestream[i*4+j]; + } + m_triggerStream.push_back(word); + } + m_triggerStream.push_back(0); + std::cout<<"Size of trigger stream is "<<m_triggerStream.size()*4<<" bytes"<<std::endl; + SerialIF::writeRegister(19,0); + //for (size_t i=0;i<m_triggerStream.size();i++)SerialIF::writeRegister(18,m_triggerStream[i]); +#ifdef __rtems__ + for (size_t i=0;i<m_triggerStream.size();i++)payload[i]=m_triggerStream[i]; + m_tds->payloadsize(m_triggerStream.size()*sizeof(unsigned)); + m_tds->flush(true); +#endif + } + + int Trigger::sendTrigger(){ + //std::cout<<"Trigger "<<m_i<<std::endl; +#ifdef __rtems__ + RCDImaster::instance()->blockWrite(m_tds); + //SerialIF::sendCommand(0xa); +#else + SerialIF::send(&m_triggerStream,SerialIF::DONT_CLEAR|SerialIF::WAITFORDATA); +#endif + m_i++; + return 0; + } + + int Trigger::enableTrigger(bool on){ + return SerialIF::enableTrigger(on); + return 0; + } + int Trigger::resetCounters(){ + BitStream *bs=new BitStream; + BitStreamUtils::prependZeros(bs); + FECommands::sendECR(bs); + FECommands::sendBCR(bs); + SerialIF::send(bs,SerialIF::WAITFORDATA); + delete bs; + return 0; + } +}; diff --git a/rce/rcecalib/config/Trigger.hh b/rce/rcecalib/config/Trigger.hh new file mode 100644 index 00000000..68135ea8 --- /dev/null +++ b/rce/rcecalib/config/Trigger.hh @@ -0,0 +1,31 @@ +#ifndef FEI3__TRIGGER_HH +#define FEI3__TRIGGER_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/config/AbsTrigger.hh" +#include "rcecalib/HW/BitStream.hh" +#include "namespace_aliases.hh" + + +namespace FEI3{ + + class Trigger: public AbsTrigger{ + public: + Trigger(); + ~Trigger(); + int configureScan(boost::property_tree::ptree* scanOptions); + int setupParameter(const char* name, int val); + int sendTrigger(); + int enableTrigger(bool on); + int resetCounters(); + void setupTriggerStream(); + private: + BitStream m_triggerStream; + int m_calL1ADelay; + RcePic::Tds* m_tds; + RcePic::Pool *m_pool; + }; + +}; + +#endif diff --git a/rce/rcecalib/config/TriggerReceiverIF.cc b/rce/rcecalib/config/TriggerReceiverIF.cc new file mode 100644 index 00000000..68db9d0c --- /dev/null +++ b/rce/rcecalib/config/TriggerReceiverIF.cc @@ -0,0 +1,15 @@ +#include "rcecalib/config/TriggerReceiverIF.hh" +#include <assert.h> + +TriggerReceiverIF::TriggerReceiverIF(){ + s_rec=this; +} +TriggerReceiverIF::~TriggerReceiverIF(){ + s_rec=0; +} +void TriggerReceiverIF::receive(unsigned *data, int size){ + assert(s_rec); + s_rec->Receive(data, size); +} + +TriggerReceiverIF* TriggerReceiverIF::s_rec=0; diff --git a/rce/rcecalib/config/TriggerReceiverIF.hh b/rce/rcecalib/config/TriggerReceiverIF.hh new file mode 100644 index 00000000..2ef1c66c --- /dev/null +++ b/rce/rcecalib/config/TriggerReceiverIF.hh @@ -0,0 +1,13 @@ +#ifndef TRIGGERRECEIVERIF_HH +#define TRIGGERRECEIVERIF_HH + +class TriggerReceiverIF{ +public: + TriggerReceiverIF(); + virtual ~TriggerReceiverIF(); + static void receive(unsigned *data, int size); + virtual void Receive(unsigned* data, int size)=0; +private: + static TriggerReceiverIF* s_rec; +}; +#endif diff --git a/rce/rcecalib/config/afp-hptdc/AFPHPTDCFormatter.cc b/rce/rcecalib/config/afp-hptdc/AFPHPTDCFormatter.cc new file mode 100644 index 00000000..593a95e4 --- /dev/null +++ b/rce/rcecalib/config/afp-hptdc/AFPHPTDCFormatter.cc @@ -0,0 +1,81 @@ +#include "rcecalib/config/afp-hptdc/AFPHPTDCFormatter.hh" +#include "rcecalib/config/FormattedRecord.hh" +#include "rcecalib/config/afp-hptdc/AFPHPTDCRecord.hh" +#include "rcecalib/config/FEI4/FEI4BRecord.hh" +#include "rcecalib/scanctrl/RceCallback.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/util/exceptions.hh" +#include "ers/ers.h" +#include <iostream> +#include <stdio.h> + +AFPHPTDCFormatter::AFPHPTDCFormatter(int id): AbsFormatter(id, "AFPHPTDC"){ +} +AFPHPTDCFormatter::~AFPHPTDCFormatter(){ +} +void AFPHPTDCFormatter::configure(boost::property_tree::ptree* config){ + try{ + for(int i=0;i<2;i++){ + for(int j=0;j<12;j++){ + for(int k=0;k<1024;k++){ + char name[32]; + sprintf(name, "c_%d_%d_%d", i, j, k); + m_calib[i][j][k]=config->get<float>(name); + } + } + } + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + } +} + +int AFPHPTDCFormatter::decode (const unsigned int *buffer, int buflen, unsigned* parsedData, int &parsedsize, int &nL1A){ + if(buflen==0)return FEI4::FEI4BRecord::Empty; + for(int i=0;i<buflen;i++){ + //std::cout<<"Raw word: "<<std::hex<<buffer[i]<<std::dec<<std::endl; + afphptdc::AFPHPTDCRecord rec(buffer[i]); + if(rec.isHeader()){ + FormattedRecord fr(FormattedRecord::HEADER); + fr.setL1id(rec.getL1id()); + fr.setBxid(rec.getBxid()); + parsedData[parsedsize++]=fr.getWord(); + nL1A++; + //std::cout<<"Header L1id="<<rec.getL1id()<<" bxid="<<rec.getBxid()<<std::endl; + }else if(rec.isData()){ + unsigned dataword=FormattedRecord::DATA; + unsigned tdcid=rec.getTDCid(); + dataword|=tdcid<<24; + unsigned chan=rec.getChannel(); + dataword|=chan<<22; + unsigned edge=rec.getEdge(); + dataword|=edge<<28; + unsigned data=rec.getData(); + if(tdcid>=0xa && tdcid<=0xc){ //TDC id should be 0xa, 0xb, or 0xc + int chanid=(tdcid-0xa)*4+chan; + //applying Inl calibration constants here. + data=(data-(unsigned)m_calib[0][chanid][data&0x3FF])&0x1FFFFF; + }else{ + std::cout<<"Bad TDC id "<<tdcid<<std::endl; + } + dataword|=data; + //std::cout<<"Data TDC id="<<rec.getTDCid()<<" Channel="<<rec.getChannel()<<" Data="<<rec.getData()<<std::endl; + FormattedRecord fr(dataword); + //fr.setDataflag(1); // flags HPTDC data + parsedData[parsedsize++]=fr.getWord(); + }else if(rec.isServiceRecord()){ + //std::cout<<"Received service record with code "<<rec.getErrorCode()<<" and error count "<<rec.getErrorCount()<<std::endl; + }else if(rec.isTdcError()){ + int tdcNum = rec.getTDCid()-0xA; + std::cout<<"Received TDC error for TDC id "<<tdcNum<<" with code 0x"<<std::hex<<rec.getTdcErrorCode()<<std::dec<<std::endl; + }else if(rec.isEmptyRecord()){ + //std::cout<<"Empty record"<<std::endl; + }else{ + std::cout<<"FE "<<getId()<<": Unexpected record type: "<<std::hex<<buffer[i]<<std::dec<<std::endl; + return FEI4::FEI4BRecord::BadRecord; + } + } + return FEI4::FEI4BRecord::OK; +} + diff --git a/rce/rcecalib/config/afp-hptdc/AFPHPTDCFormatter.hh b/rce/rcecalib/config/afp-hptdc/AFPHPTDCFormatter.hh new file mode 100644 index 00000000..262a9618 --- /dev/null +++ b/rce/rcecalib/config/afp-hptdc/AFPHPTDCFormatter.hh @@ -0,0 +1,16 @@ +#ifndef AFPHPTDCFORMATTER_HH +#define AFPHPTDCFORMATTER_HH + +#include "rcecalib/config/AbsFormatter.hh" + +class AFPHPTDCFormatter:public AbsFormatter{ +public: + AFPHPTDCFormatter(int id); + virtual ~AFPHPTDCFormatter(); + int decode(const unsigned* data, int size, unsigned* parsedData, int &parsedsize, int &nL1A); + void configure(boost::property_tree::ptree* scanOptions); + +private: + float m_calib[2][12][1024]; +}; +#endif diff --git a/rce/rcecalib/config/afp-hptdc/AFPHPTDCRecord.hh b/rce/rcecalib/config/afp-hptdc/AFPHPTDCRecord.hh new file mode 100644 index 00000000..0d473b0b --- /dev/null +++ b/rce/rcecalib/config/afp-hptdc/AFPHPTDCRecord.hh @@ -0,0 +1,30 @@ +#ifndef AFPHPTDC__RECORD_HH +#define AFPHPTDC__RECORD_HH + +namespace afphptdc{ + + class AFPHPTDCRecord{ + public: + AFPHPTDCRecord(unsigned word){(m_record=word);} + virtual ~AFPHPTDCRecord(){}; + bool isData(){return ((m_record>>29)==0x2);} + bool isTdcError(){return ((m_record>>28)==0x6);} + bool isHeader(){return ((m_record>>16)==0xe9);} + bool isServiceRecord(){return ((m_record>>16)==0xef);} + bool isEmptyRecord(){return (m_record==0);} + int getTdcErrorCode(){return m_record&0x7FFF;} + int getL1id(){return (m_record>>8)&0x7f;} + int getBxid(){return m_record&0xff;} + int getEdge(){return (m_record>>28)&0x1;} + int getTDCid(){return (m_record>>24)&0xf;} + int getChannel(){return (m_record>>22)&0x3;} + int getData(){return ((m_record>>19)&0x3) | ((m_record&0x7ffff)<<2);} + int getErrorCode(){return (m_record>>10)&0x3f;} + int getErrorCount(){return m_record&0x3ff;} + private: + unsigned m_record; + +}; + +}; +#endif diff --git a/rce/rcecalib/config/afp-hptdc/IPCModule.cc b/rce/rcecalib/config/afp-hptdc/IPCModule.cc new file mode 100644 index 00000000..cecc67f2 --- /dev/null +++ b/rce/rcecalib/config/afp-hptdc/IPCModule.cc @@ -0,0 +1,184 @@ +#ifndef AFPHPTDC__IPCMODULE_CC +#define AFPHPTDC__IPCMODULE_CC +#include "rcecalib/util/RceName.hh" +#include "rcecalib/config/afp-hptdc/IPCModule.hh" +#include "ipc/partition.h" +#include "ers/ers.h" +#include <boost/lexical_cast.hpp> + +namespace afphptdc{ + +template <class TP> +IPCModule<TP>::IPCModule(IPCPartition & p, const char * name, unsigned id, unsigned inlink, unsigned outlink, AbsFormatter* fmt): + IPCNamedObject<POA_ipc::IPCAFPHPTDCAdapter, TP>( p, std::string(boost::lexical_cast<std::string>(id)+"_RCE"+boost::lexical_cast<std::string>(RceName::getRceNumber())).c_str()) , + Module(name, id, inlink, outlink, fmt){ + // std::cout<<"IPCModule"<<std::endl; + try { + IPCNamedObject<POA_ipc::IPCAFPHPTDCAdapter,TP>::publish(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } +} + +template <class TP> +IPCModule<TP>::~IPCModule(){ + try { + IPCNamedObject<POA_ipc::IPCAFPHPTDCAdapter,TP>::withdraw(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::warning( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } +} + +template <class TP> +CORBA::Long IPCModule<TP>::IPCdownloadConfig(const ipc::AFPHPTDCModuleConfig &config){ + setFpgaField("test", config.test); + setFpgaField("tdcControl", config.tdcControl); + setFpgaField("run", config.run); + setFpgaField("bypassLut", config.bypassLut); + setFpgaField("localClockEn", config.localClockEn); + setFpgaField("calClockEn", config.calClockEn); + setFpgaField("refEn", config.refEn); + setFpgaField("hitTestEn", config.hitTestEn); + setFpgaField("inputSel", config.inputSel); + setFpgaField("address", config.address); + setFpgaField("fanspeed", config.fanspeed); + setFpgaField("channelEn", config.channelEn); + + for(int i=0;i<3;i++){ + for (int j=31;j>=0;j--){ + char offs[32]; + sprintf(offs, "offset%d", j); + setTdcField(offs, i, config.offset[j][i]); + } + setTdcField("test_select", i, config.test_select[i]); + setTdcField("enable_error_mark", i, config.enable_error_mark[i]); + setTdcField("enable_error_bypass", i, config.enable_error_bypass[i]); + setTdcField("enable_error", i, config.enable_error[i]); + setTdcField("readout_single_cycle_speed", i, config.readout_single_cycle_speed[i]); + setTdcField("serial_delay", i, config.serial_delay[i]); + setTdcField("strobe_select", i, config.strobe_select[i]); + setTdcField("readout_speed_select", i, config.readout_speed_select[i]); + setTdcField("token_delay", i, config.token_delay[i]); + setTdcField("enable_local_trailer", i, config.enable_local_trailer[i]); + setTdcField("enable_local_header", i, config.enable_local_header[i]); + setTdcField("enable_global_trailer", i, config.enable_global_trailer[i]); + setTdcField("enable_global_header", i, config.enable_global_header[i]); + setTdcField("keep_token", i, config.keep_token[i]); + setTdcField("master", i, config.master[i]); + setTdcField("enable_bytewise", i, config.enable_bytewise[i]); + setTdcField("enable_serial", i, config.enable_serial[i]); + setTdcField("enable_jtag_readout", i, config.enable_jtag_readout[i]); + setTdcField("tdc_id", i, config.tdc_id[i]); + setTdcField("select_bypass_inputs", i, config.select_bypass_inputs[i]); + setTdcField("readout_fifo_size", i, config.readout_fifo_size[i]); + setTdcField("reject_count_offset", i, config.reject_count_offset[i]); + setTdcField("search_window", i, config.search_window[i]); + setTdcField("match_window", i, config.match_window[i]); + setTdcField("leading_resolution", i, config.leading_resolution[i]); + setTdcField("fixed_pattern", i, config.fixed_pattern[i]); + setTdcField("enable_fixed_pattern", i, config.enable_fixed_pattern[i]); + setTdcField("max_event_size", i, config.max_event_size[i]); + setTdcField("reject_readout_fifo_full", i, config.reject_readout_fifo_full[i]); + setTdcField("enable_readout_occupancy", i, config.enable_readout_occupancy[i]); + setTdcField("enable_readout_separator", i, config.enable_readout_separator[i]); + setTdcField("enable_overflow_detect", i, config.enable_overflow_detect[i]); + setTdcField("enable_relative", i, config.enable_relative[i]); + setTdcField("enable_automatic_reject", i, config.enable_automatic_reject[i]); + setTdcField("event_count_offset", i, config.event_count_offset[i]); + setTdcField("trigger_count_offset", i, config.trigger_count_offset[i]); + setTdcField("enable_set_counters_on_bunch_reset", i, config.enable_set_counters_on_bunch_reset[i]); + setTdcField("enable_master_reset_code", i, config.enable_master_reset_code[i]); + setTdcField("enable_master_reset_code_on_event_reset", i, config.enable_master_reset_code_on_event_reset[i]); + setTdcField("enable_reset_channel_buffer_when_separator", i, config.enable_reset_channel_buffer_when_separator[i]); + setTdcField("enable_separator_on_event_reset", i, config.enable_separator_on_event_reset[i]); + setTdcField("enable_separator_on_bunch_reset", i, config.enable_separator_on_bunch_reset[i]); + setTdcField("enable_direct_event_reset", i, config.enable_direct_event_reset[i]); + setTdcField("enable_direct_bunch_reset", i, config.enable_direct_bunch_reset[i]); + setTdcField("enable_direct_trigger", i, config.enable_direct_trigger[i]); + setTdcField("coarse_count_offset", i, config.coarse_count_offset[i]); + setTdcField("dll_tap_adjust3_0", i, config.dll_tap_adjust3_0[i]); + setTdcField("dll_tap_adjust7_4", i, config.dll_tap_adjust7_4[i]); + setTdcField("dll_tap_adjust11_8", i, config.dll_tap_adjust11_8[i]); + setTdcField("dll_tap_adjust15_12", i, config.dll_tap_adjust15_12[i]); + setTdcField("dll_tap_adjust19_16", i, config.dll_tap_adjust19_16[i]); + setTdcField("dll_tap_adjust23_20", i, config.dll_tap_adjust23_20[i]); + setTdcField("dll_tap_adjust27_24", i, config.dll_tap_adjust27_24[i]); + setTdcField("dll_tap_adjust31_28", i, config.dll_tap_adjust31_28[i]); + setTdcField("rc_adjust", i, config.rc_adjust[i]); + setTdcField("not_used", i, config.not_used[i]); + setTdcField("low_power_mode", i, config.low_power_mode[i]); + setTdcField("width_select", i, config.width_select[i]); + setTdcField("vernier_offset", i, config.vernier_offset[i]); + setTdcField("dll_control", i, config.dll_control[i]); + setTdcField("dead_time", i, config.dead_time[i]); + setTdcField("test_invert", i, config.test_invert[i]); + setTdcField("test_mode", i, config.test_mode[i]); + setTdcField("enable_trailing", i, config.enable_trailing[i]); + setTdcField("enable_leading", i, config.enable_leading[i]); + setTdcField("mode_rc_compression", i, config.mode_rc_compression[i]); + setTdcField("mode_rc", i, config.mode_rc[i]); + setTdcField("dll_mode", i, config.dll_mode[i]); + setTdcField("pll_control", i, config.pll_control[i]); + setTdcField("serial_clock_delay", i, config.serial_clock_delay[i]); + setTdcField("io_clock_delay", i, config.io_clock_delay[i]); + setTdcField("core_clock_delay", i, config.core_clock_delay[i]); + setTdcField("dll_clock_delay", i, config.dll_clock_delay[i]); + setTdcField("serial_clock_source", i, config.serial_clock_source[i]); + setTdcField("io_clock_source", i, config.io_clock_source[i]); + setTdcField("core_clock_source", i, config.core_clock_source[i]); + setTdcField("dll_clock_source", i, config.dll_clock_source[i]); + setTdcField("roll_over", i, config.roll_over[i]); + setTdcField("enable_matching", i, config.enable_matching[i]); + setTdcField("enable_pair", i, config.enable_pair[i]); + setTdcField("enable_ttl_serial", i, config.enable_ttl_serial[i]); + setTdcField("enable_ttl_control", i, config.enable_ttl_control[i]); + setTdcField("enable_ttl_reset", i, config.enable_ttl_reset[i]); + setTdcField("enable_ttl_clock", i, config.enable_ttl_clock[i]); + setTdcField("enable_ttl_hit", i, config.enable_ttl_hit[i]); + } + AbsFormatter* fmt=getFormatter(); + if(fmt){ + // configure the formatter with the calibration constants + boost::property_tree::ptree *pt=new boost::property_tree::ptree; + for(int i=0;i<2;i++){ + for(int j=0;j<12;j++){ + for(int k=0;k<1024;k++){ + char name[32]; + sprintf(name, "c_%d_%d_%d", i, j, k); + pt->put(name, config.calib[i][j][k]); + } + } + } + std::cout<<"%%%%%%%%% Configuring HPTDC Formatter"<<std::endl; + fmt->configure(pt); + delete pt; + } + return 0; +} + +template <class TP> +void IPCModule<TP>::shutdown(){ + std::cout<<"Shutdown"<<std::endl; +} + +template <class TP> +void IPCModule<TP>::destroy(){ + this->_destroy(); +} + + + +}; + +#endif diff --git a/rce/rcecalib/config/afp-hptdc/IPCModule.hh b/rce/rcecalib/config/afp-hptdc/IPCModule.hh new file mode 100644 index 00000000..2751b293 --- /dev/null +++ b/rce/rcecalib/config/afp-hptdc/IPCModule.hh @@ -0,0 +1,26 @@ +#ifndef IPCAFPHPTDCMODULE_HH +#define IPCAFPHPTDCMODULE_HH + +#include "rcecalib/config/afp-hptdc/Module.hh" +#include "ipc/object.h" +#include "AFPHPTDCModuleConfig.hh" +#include "IPCAFPHPTDCAdapter.hh" + +class IPCPartition; +class AbsFormatter; + +namespace afphptdc{ +template <class TP = ipc::single_thread> +class IPCModule: public IPCNamedObject<POA_ipc::IPCAFPHPTDCAdapter,TP>, public afphptdc::Module { +public: + IPCModule(IPCPartition & p, const char * name, unsigned id, unsigned inlink, unsigned outlink, AbsFormatter* fmt); + ~IPCModule(); + CORBA::Long IPCdownloadConfig(const ipc::AFPHPTDCModuleConfig &config); + void shutdown(); + void destroy(); + +}; +}; + + +#endif diff --git a/rce/rcecalib/config/afp-hptdc/Module.cc b/rce/rcecalib/config/afp-hptdc/Module.cc new file mode 100644 index 00000000..364f7c9f --- /dev/null +++ b/rce/rcecalib/config/afp-hptdc/Module.cc @@ -0,0 +1,321 @@ +#include "rcecalib/HW/BitStream.hh" +#include "rcecalib/config/afp-hptdc/Module.hh" +#include "rcecalib/config/FEI4/FECommands.hh" +#include "rcecalib/HW/SerialIF.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/util/exceptions.hh" +#include <iostream> +#include "ers/ers.h" +#include <stdio.h> + +namespace afphptdc{ + + Module::Module(const char* name, unsigned id, unsigned inLink, unsigned outLink, AbsFormatter* fmt) + :AbsModule(name, id,inLink, outLink, fmt){ + //std::cout<<"Module"<<std::endl; + if(!m_initialized)initialize(); + for(int i=0;i<N_FPGA_REGS;i++)m_fpga_registers[i]=0; + for(int j=0;j<3;j++) + for(int i=0;i<N_TDC_REGS;i++) + m_tdc_registers[j][i]=0; + m_commands=new FEI4::FECommands; + } + Module::~Module(){ + delete m_commands; + } + void Module::writeHW(){ + //FPGA registers + for(std::map<int, int>::const_iterator it=m_used_regs.begin(); it!=m_used_regs.end(); it++){ + writeRegisterRawHW(it->first, (unsigned short)m_fpga_registers[it->first]); + } + for(int i=0;i<3;i++){ + writeTdcBitstreamHW(i); + } + } + void Module::writeTdcBitstreamHW(int i){ + // calculate parity; + int parity=0; + for(int j=0;j<=m_regpos;j++){ + for(int k= j==m_regpos? m_bitpos+1 : 0;k<32;k++){ + parity^=(m_tdc_registers[i][j]>>k)&0x1; + } + } + setTdcField("parity", i, parity); + BitStream *bs=new BitStream; + m_commands->feWriteCommand(bs); + (*bs)[bs->size()-1]|=i; //bitstream address + for(int j=0;j<N_TDC_REGS;j++){ + bs->push_back(m_tdc_registers[i][j]); + } + SerialIF::send(bs); //Write bitstream + delete bs; + } + unsigned Module::writeRegisterHW(int i, unsigned short val){ + // i is position in vector, not actual address + /* + m_regw[i]=val; // set register content + int addr=m_registers[i].reg; + int rval=val&((1<<m_registers[i].width)-1); + writeRegisterRawHW(addr, rval); + */ + return 0; + } + void Module::writeRegisterRawHW(int i, unsigned short val){ + BitStream *bs=new BitStream; + m_commands->writeGlobalRegister(bs, i, val); + SerialIF::send(bs); //Write register + delete bs; + } + + void Module::configureHW(){ + std::cout<<"Configuring HPTDC"<<std::endl; + resetFE(); + SerialIF::setDataRate(SerialIF::M160); + writeHW(); + //printRegisters(std::cout); + } + void Module::enableDataTakingHW(){ + std::cout<<"AFPHPTDC Enabled data taking Board "<<getId()<<std::endl; + BitStream *bs=new BitStream; + BitStreamUtils::prependZeros(bs); + m_commands->switchMode(bs, FEI4::FECommands::RUN); + m_commands->sendECR(bs); + m_commands->sendBCR(bs); + SerialIF::send(bs); + delete bs; + } + void Module::switchToConfigModeHW(){ + std::cout<<"AFPHPTDC Switched to Config Mode Board "<<getId()<<std::endl; + BitStream *bs=new BitStream; + m_commands->switchMode(bs, FEI4::FECommands::CONF); + bs->push_back(0); + SerialIF::send(bs, SerialIF::WAITFORDATA); + delete bs; + } + + void Module::resetFE(){ + BitStream *bs=new BitStream; + m_commands->globalReset(bs); + delete bs; + } + + // set a parameter (global or MCC) in the frontend + int Module::setupParameterHW(const char* name, int val){ + int retval=1; + /* + if(m_parameters.find(name)!=m_parameters.end()){ + retval=0; + writeRegisterHW(m_parameters[name], val); + } + */ + return retval; + } + + int Module::configureScan(boost::property_tree::ptree *scanOptions){ + int retval=0; + // do nothing for now + return retval; + } + void Module::destroy(){ + delete this; + } + ModuleInfo Module::getModuleInfo(){ + return ModuleInfo(m_name, m_id,m_inLink, m_outLink, 1, 12, 1, m_formatter); + } + + void Module::printRegisters(std::ostream &os){ + std::cout<<"FPGA Registers"<<std::endl; + for(std::map<int, int>::const_iterator it=m_used_regs.begin(); it!=m_used_regs.end(); it++){ + os<<"Address = "<<it->first<<" Value = 0x"<<std::hex<<m_fpga_registers[it->first]<<std::dec<<std::endl; + } + for (int i=0;i<3;i++){ + std::cout<<"TDC Registers Bitstream "<<i<<std::endl; + for(int j=0;j<N_TDC_REGS;j++){ + std::cout<<std::hex<<m_tdc_registers[i][j]<<std::dec<<std::endl; + } + } + } + + //static functions + //void Module::addParameter(const char* name, const char* field){ +// int regnum=findRegister(field); +// assert(regnum>-1); +// m_parameters[name]=regnum; + //} + void Module::setFpgaField(const char* name, unsigned val){ + char msg[128]; + sprintf(msg,"parameter %s is invalid",name); + ERS_ASSERT_MSG(m_fpga_fields.find(name)!=m_fpga_fields.end(),msg); + assert(m_fpga_fields.find(name)!=m_fpga_fields.end()); + FieldParams params=m_fpga_fields[name]; + setFieldFun(&m_fpga_registers[params.reg], params.pos, params.width, val); + } + void Module::setTdcField(const char* name, int index, unsigned val){ + char msg[128]; + sprintf(msg,"parameter %s is invalid",name); + //ERS_ASSERT_MSG(m_tdc_fields.find(name)!=m_tdc_fields.end(),msg); + assert(m_tdc_fields.find(name)!=m_tdc_fields.end()); + FieldParams params=m_tdc_fields[name]; + //reverse bit order of fields + unsigned valRev = 0; + for (int i=0;i<params.width;i++){ + valRev <<= 1; + valRev |= val & 1; + val >>= 1; + } + setFieldFun(&m_tdc_registers[index][params.reg], params.pos, params.width, valRev); + } + void Module::setFieldFun(unsigned *reg, int bitpos, int width, unsigned val){ + int pwidth=bitpos+width<=32 ? width : 32 - bitpos; + unsigned mask=(1<<width)-1; + mask=(1<<pwidth)-1; + *reg&=~(mask<<bitpos); + *reg|=(val&mask)<<bitpos; + if(pwidth!=width){ // extends over next register + int rwidth=width-pwidth; + mask=(1<<rwidth)-1; + *(reg-1)&=~mask; + *(reg-1)|=(val>>pwidth); + } + } + + void Module::addFpgaField(const char* name, int reg, int width, int pos){ + FieldParams temp; + temp.reg=reg; + temp.width=width; + temp.pos=pos; + m_fpga_fields[name]=temp; + } + void Module::addTdcField(const char* name, int width){ + m_bitpos-=width; + if(m_bitpos<0){ + m_bitpos+=32; + m_regpos+=1; + } + FieldParams temp; + temp.reg=m_regpos; + temp.width=width; + temp.pos=m_bitpos; + m_tdc_fields[name]=temp; + } + std::map<std::string, FieldParams> Module::m_fpga_fields; + std::map<std::string, FieldParams> Module::m_tdc_fields; + std::map<int, int> Module::m_used_regs; + bool Module::m_initialized = false; + int Module::m_regpos=0; + int Module::m_bitpos=32; + + void Module::initialize(){ + addFpgaField("test", 32, 16, 0); + addFpgaField("tdcControl", 28, 4, 0); + addFpgaField("run", 29, 1, 0); + addFpgaField("bypassLut", 29, 1, 2); + addFpgaField("localClockEn", 29, 1, 3); + addFpgaField("calClockEn", 29, 1, 4); + addFpgaField("refEn", 29, 1, 5); + addFpgaField("hitTestEn", 29, 1, 6); + addFpgaField("inputSel", 29, 3, 8); + addFpgaField("address", 20, 8, 0); + addFpgaField("fanspeed", 27, 8, 0); + addFpgaField("channelEn", 26, 12, 0); + + for(std::map<std::string, FieldParams>::const_iterator it=m_fpga_fields.begin(); it!=m_fpga_fields.end(); it++){ + FieldParams p=it->second; + m_used_regs[p.reg]=1; + } + addTdcField("test_select", 4); + addTdcField("enable_error_mark", 1); + addTdcField("enable_error_bypass", 1); + addTdcField("enable_error", 11); + addTdcField("readout_single_cycle_speed", 3); + addTdcField("serial_delay", 4); + addTdcField("strobe_select", 2); + addTdcField("readout_speed_select", 1); + addTdcField("token_delay", 4); + addTdcField("enable_local_trailer", 1); + addTdcField("enable_local_header", 1); + addTdcField("enable_global_trailer", 1); + addTdcField("enable_global_header", 1); + addTdcField("keep_token", 1); + addTdcField("master", 1); + addTdcField("enable_bytewise", 1); + addTdcField("enable_serial", 1); + addTdcField("enable_jtag_readout", 1); + addTdcField("tdc_id", 4); + addTdcField("select_bypass_inputs", 1); + addTdcField("readout_fifo_size", 3); + addTdcField("reject_count_offset", 12); + addTdcField("search_window", 12); + addTdcField("match_window", 12); + addTdcField("leading_resolution", 3); + addTdcField("fixed_pattern", 28); + addTdcField("enable_fixed_pattern", 1); + addTdcField("max_event_size", 4); + addTdcField("reject_readout_fifo_full", 1); + addTdcField("enable_readout_occupancy", 1); + addTdcField("enable_readout_separator", 1); + addTdcField("enable_overflow_detect", 1); + addTdcField("enable_relative", 1); + addTdcField("enable_automatic_reject", 1); + addTdcField("event_count_offset", 12); + addTdcField("trigger_count_offset", 12); + addTdcField("enable_set_counters_on_bunch_reset", 1); + addTdcField("enable_master_reset_code", 1); + addTdcField("enable_master_reset_code_on_event_reset", 1); + addTdcField("enable_reset_channel_buffer_when_separator", 1); + addTdcField("enable_separator_on_event_reset", 1); + addTdcField("enable_separator_on_bunch_reset", 1); + addTdcField("enable_direct_event_reset", 1); + addTdcField("enable_direct_bunch_reset", 1); + addTdcField("enable_direct_trigger", 1); + for (int j=31;j>=0;j--){ + char offs[32]; + sprintf(offs, "offset%d", j); + addTdcField(offs, 9); + } + addTdcField("coarse_count_offset", 12); + addTdcField("dll_tap_adjust3_0", 12); + addTdcField("dll_tap_adjust7_4", 12); + addTdcField("dll_tap_adjust11_8", 12); + addTdcField("dll_tap_adjust15_12", 12); + addTdcField("dll_tap_adjust19_16", 12); + addTdcField("dll_tap_adjust23_20", 12); + addTdcField("dll_tap_adjust27_24", 12); + addTdcField("dll_tap_adjust31_28", 12); + addTdcField("rc_adjust", 12); + addTdcField("not_used", 3); + addTdcField("low_power_mode", 1); + addTdcField("width_select", 4); + addTdcField("vernier_offset", 5); + addTdcField("dll_control", 4); + addTdcField("dead_time", 2); + addTdcField("test_invert", 1); + addTdcField("test_mode", 1); + addTdcField("enable_trailing", 1); + addTdcField("enable_leading", 1); + addTdcField("mode_rc_compression", 1); + addTdcField("mode_rc", 1); + addTdcField("dll_mode", 2); + addTdcField("pll_control", 8); + addTdcField("serial_clock_delay", 4); + addTdcField("io_clock_delay", 4); + addTdcField("core_clock_delay", 4); + addTdcField("dll_clock_delay", 4); + addTdcField("serial_clock_source", 2); + addTdcField("io_clock_source", 2); + addTdcField("core_clock_source", 2); + addTdcField("dll_clock_source", 3); + addTdcField("roll_over", 12); + addTdcField("enable_matching", 1); + addTdcField("enable_pair", 1); + addTdcField("enable_ttl_serial", 1); + addTdcField("enable_ttl_control", 1); + addTdcField("enable_ttl_reset", 1); + addTdcField("enable_ttl_clock", 1); + addTdcField("enable_ttl_hit", 1); + addTdcField("parity", 1); + m_initialized=true; + std::cout<<"Regpos "<<m_regpos<<std::endl; + std::cout<<"Bitpos "<<m_bitpos<<std::endl; + } +} diff --git a/rce/rcecalib/config/afp-hptdc/Module.hh b/rce/rcecalib/config/afp-hptdc/Module.hh new file mode 100644 index 00000000..d2702757 --- /dev/null +++ b/rce/rcecalib/config/afp-hptdc/Module.hh @@ -0,0 +1,64 @@ +#ifndef AFPHPTDC__MODULE_HH +#define AFPHPTDC__MODULE_HH + +#include "rcecalib/config/AbsModule.hh" +#include <boost/property_tree/ptree_fwd.hpp> +#include <map> +#include <string> + +class AbsFormatter; +namespace FEI4{ + class FECommands; +}; + +namespace afphptdc{ + + struct FieldParams{ + int reg; + int width; + int pos; + }; + + class Module: public AbsModule{ + public: + Module(const char* name, unsigned id, unsigned inLink, unsigned outLink, AbsFormatter* fmt); + virtual ~Module(); + enum {N_FPGA_REGS=40, N_TDC_REGS=21}; + void configureHW(); + void resetFE(); + void setupMaskStageHW(int stage){}; + void enableDataTakingHW(); + void switchToConfigModeHW(); + int setupParameterHW(const char* name, int val); //HW setup + int configureScan(boost::property_tree::ptree* scanOptions); + ModuleInfo getModuleInfo(); + const float dacToElectrons(int fe, int dac){return 0;} + void printRegisters(std::ostream &os); + unsigned writeRegisterHW(int i, unsigned short val); + void writeRegisterRawHW(int i, unsigned short val); + void writeHW(); + void writeTdcBitstreamHW(int i); + void setFieldFun(unsigned *reg, int bitpos, int width, unsigned val); + void setFpgaField(const char* name, unsigned val); + void setTdcField(const char* name, int index, unsigned val); + virtual void destroy(); + private: + FEI4::FECommands* m_commands; + static void addFpgaField(const char* name, int reg, int width, int pos); + static void addTdcField(const char* name, int width); + //static void addParameter(const char* name, const char* field); + static void initialize(); + unsigned m_fpga_registers[N_FPGA_REGS]; + unsigned m_tdc_registers[3][N_TDC_REGS]; + static std::map<std::string, FieldParams> m_fpga_fields; + static std::map<int, int> m_used_regs; + static std::map<std::string, FieldParams> m_tdc_fields; + //static std::map<std::string, int> m_parameters; + static bool m_initialized; + static int m_regpos; + static int m_bitpos; + +}; + +}; +#endif diff --git a/rce/rcecalib/config/afp-hptdc/ModuleGroup.cc b/rce/rcecalib/config/afp-hptdc/ModuleGroup.cc new file mode 100644 index 00000000..ab57464a --- /dev/null +++ b/rce/rcecalib/config/afp-hptdc/ModuleGroup.cc @@ -0,0 +1,86 @@ + +#include <boost/property_tree/ptree.hpp> +#include <stdio.h> +#include "rcecalib/config/afp-hptdc/Module.hh" +#include "rcecalib/config/afp-hptdc/ModuleGroup.hh" +#include "rcecalib/util/exceptions.hh" +#include "ers/ers.h" +#include "rcecalib/HW/SerialIF.hh" + +namespace afphptdc{ + +void ModuleGroup::addModule(Module* module){ + m_modules.push_back(module); + m_channelInMask|=1<<module->getInLink(); + m_channelOutMask=0; +} + +void ModuleGroup::deleteModules(){ + for (unsigned i=0; i<m_modules.size();i++){ + //cannot call delete directly because IPC modules need to call _destroy() instead. + m_modules[i]->destroy(); + } + m_modules.clear(); + m_channelInMask=0; + m_channelOutMask=0; +} + +int ModuleGroup::setupParameterHW(const char* name, int val, bool bcOK){ + int retval=0; + for (unsigned int i=0;i<m_modules.size();i++){ + SerialIF::setChannelInMask(1<<m_modules[i]->getInLink()); + retval+=m_modules[i]->setupParameterHW(name,val); + } + disableAllInChannels(); + return retval; +} + +int ModuleGroup::setupMaskStageHW(int stage){ + // no mask staging for the HPTDC chip. + return 0; +} + +void ModuleGroup::configureModulesHW(){ + //std::cout<<"Configure Modules HW"<<std::endl; + for (unsigned int i=0;i<m_modules.size();i++){ + SerialIF::setChannelInMask(1<<m_modules[i]->getInLink()); + std::cout<<"Setting channel in mask for inlink "<<m_modules[i]->getInLink()<<std::endl; + m_modules[i]->switchToConfigModeHW(); + m_modules[i]->configureHW(); + } + SerialIF::sendCommand(0x10); //phase calibration + disableAllInChannels(); +} + +void ModuleGroup::resetFE(){ + for (unsigned int i=0;i<m_modules.size();i++){ + SerialIF::setChannelInMask(1<<m_modules[i]->getInLink()); + m_modules[i]->resetFE(); + } + disableAllInChannels(); +} + +void ModuleGroup::enableDataTakingHW(){ + for (unsigned int i=0;i<m_modules.size();i++){ + SerialIF::setChannelInMask(1<<m_modules[i]->getInLink()); + m_modules[i]->enableDataTakingHW(); + } + disableAllInChannels(); +} + +int ModuleGroup::verifyModuleConfigHW(){ + return 0; // does not exist for HPTDC +} +void ModuleGroup::resetErrorCountersHW(){ + //does not exist for HPTDC +} + +int ModuleGroup::configureScan(boost::property_tree::ptree *scanOptions){ + int retval=0; + for (unsigned int i=0;i<m_modules.size();i++){ + retval+=m_modules[i]->configureScan(scanOptions); + } + return retval; +} + +} diff --git a/rce/rcecalib/config/afp-hptdc/ModuleGroup.hh b/rce/rcecalib/config/afp-hptdc/ModuleGroup.hh new file mode 100644 index 00000000..b9e0f8ec --- /dev/null +++ b/rce/rcecalib/config/afp-hptdc/ModuleGroup.hh @@ -0,0 +1,33 @@ +#ifndef MODULEGROUPAFPHPTDC_HH +#define MODULEGROUPAFPHPTDC_HH +#include "rcecalib/config/AbsModuleGroup.hh" +#include <boost/property_tree/ptree_fwd.hpp> +#include <vector> + +namespace afphptdc{ + + class Module; + +class ModuleGroup: public AbsModuleGroup{ +public: + ModuleGroup():AbsModuleGroup(){}; + virtual ~ModuleGroup(){} + void addModule(Module* module); + void deleteModules(); + int setupParameterHW(const char* name, int val, bool bcok); + int setupMaskStageHW(int stage); + void configureModulesHW(); + int verifyModuleConfigHW(); + void resetErrorCountersHW(); + int configureScan(boost::property_tree::ptree *scanOptions); + void resetFE(); + void enableDataTakingHW(); + unsigned getNmodules(){return m_modules.size();} +private: + void switchToConfigModeHW(); + std::vector<Module*> m_modules; + +}; +} + +#endif diff --git a/rce/rcecalib/config/constituents.mk b/rce/rcecalib/config/constituents.mk new file mode 100644 index 00000000..251fcbda --- /dev/null +++ b/rce/rcecalib/config/constituents.mk @@ -0,0 +1,90 @@ + +ifneq ($(findstring linux,$(tgt_os)),) +libnames := rceconfig +endif +ifneq ($(findstring ppc-rtems-rce,$(tgt_arch)),) + modlibnames := rceconfig +endif +ifeq ($(profiler),y) +CPPFLAGS+='-D__PROFILER_ENABLED__' +endif + +libsrcs_rceconfig := AbsTrigger.cc \ + AbsModuleGroup.cc \ + ConfigIF.cc \ + EventFromFileTrigger.cc \ + TriggerReceiverIF.cc \ + MultiShotTrigger.cc \ + HitorTrigger.cc \ + IPCModuleFactory.cc \ + DummyFormatter.cc \ + Trigger.cc \ + MultiTrigger.cc \ + FEI3/MaskStageFactory.cc \ + FEI3/MaskStaging.cc \ + FEI3/RegularMaskStaging.cc \ + FEI3/CrosstalkMaskStaging.cc \ + FEI3/FECommands.cc \ + FEI3/Frontend.cc \ + FEI3/GlobalRegister.cc \ + FEI3/PixelRegister.cc \ + FEI3/Mcc.cc \ + FEI3/ModuleGroup.cc \ + FEI3/Module.cc \ + FEI3/JJFormatter.cc \ + FEI4/FECommands.cc \ + FEI4/PixelRegister.cc \ + FEI4/GlobalRegister.cc \ + FEI4/FEI4AGlobalRegister.cc \ + FEI4/FEI4BGlobalRegister.cc \ + FEI4/FEI4AFormatter.cc \ + FEI4/FEI4BFormatter.cc \ + FEI4/FEI4HitorFormatter.cc \ + FEI4/FEI4OccFormatter.cc \ + FEI4/MaskStageFactory.cc \ + FEI4/MaskStaging.cc \ + FEI4/AnalogMaskStaging.cc \ + FEI4/FastAnalogMaskStaging.cc \ + FEI4/AnalogSingleMaskStaging.cc \ + FEI4/AnalogColprMaskStaging.cc \ + FEI4/AnalogSimpleColprMaskStaging.cc \ + FEI4/AnalogColpr2MaskStagingFei4a.cc \ + FEI4/DigitalMaskStaging.cc \ + FEI4/DigStepMaskStaging.cc \ + FEI4/MaskStaging26880.cc \ + FEI4/AnalogMaskStaging.cc \ + FEI4/CrosstalkMaskStaging.cc \ + FEI4/CrosstalkFastMaskStaging.cc \ + FEI4/DiffusionMaskStaging.cc \ + FEI4/NoiseMaskStaging.cc \ + FEI4/ModuleCrosstalkMaskStaging.cc \ + FEI4/PatternMaskStaging.cc \ + FEI4/FEI4AModule.cc \ + FEI4/FEI4BModule.cc \ + FEI4/ModuleGroup.cc \ + FEI4/Module.cc \ + FEI4/TemperatureTrigger.cc \ + FEI4/MonleakTrigger.cc \ + FEI4/SNTrigger.cc \ + FEI4/Fei4RegisterTestTrigger.cc \ + hitbus/ModuleGroup.cc \ + hitbus/Module.cc \ + afp-hptdc/AFPHPTDCFormatter.cc \ + afp-hptdc/ModuleGroup.cc \ + afp-hptdc/Module.cc + +ifneq ($(findstring ppc-rtems-rce,$(tgt_arch)),) + libsrcs_rceconfig += MeasurementTrigger.cc +endif + + +libincs_rceconfig := rcecalib \ + $(ers_include_path) \ + $(owl_include_path) \ + $(ipc_include_path) \ + $(is_include_path) \ + $(oh_include_path) \ + $(boost_include_path) \ + $(omniorb_include_path) + + diff --git a/rce/rcecalib/config/hitbus/IPCModule.cc b/rce/rcecalib/config/hitbus/IPCModule.cc new file mode 100644 index 00000000..73ee2562 --- /dev/null +++ b/rce/rcecalib/config/hitbus/IPCModule.cc @@ -0,0 +1,74 @@ +#ifndef HITBUS__IPCMODULE_CC +#define HITBUS__IPCMODULE_CC +#include "rcecalib/util/RceName.hh" +#include "rcecalib/config/hitbus/IPCModule.hh" +#include "ipc/partition.h" +#include "ers/ers.h" +#include <boost/lexical_cast.hpp> + +namespace Hitbus{ + +template <class TP> +IPCModule<TP>::IPCModule(IPCPartition & p, const char * name, unsigned id, unsigned inlink, unsigned outlink, AbsFormatter* fmt): + IPCNamedObject<POA_ipc::IPCHitbusAdapter, TP>( p, std::string(boost::lexical_cast<std::string>(id)+"_RCE"+boost::lexical_cast<std::string>(RceName::getRceNumber())).c_str()) , + Module(name, id, inlink, outlink, fmt){ + // std::cout<<"IPCModule"<<std::endl; + try { + IPCNamedObject<POA_ipc::IPCHitbusAdapter,TP>::publish(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } +} + +template <class TP> +IPCModule<TP>::~IPCModule(){ + try { + IPCNamedObject<POA_ipc::IPCHitbusAdapter,TP>::withdraw(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::warning( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } +} + +template <class TP> +CORBA::Long IPCModule<TP>::IPCdownloadConfig(const ipc::HitbusModuleConfig &config){ + setRegister("bpm", config.bpm); + setRegister("delay_tam1", config.delay_tam1); + setRegister("delay_tam2", config.delay_tam2); + setRegister("delay_tam3", config.delay_tam3); + setRegister("delay_tbm1", config.delay_tbm1); + setRegister("delay_tbm2", config.delay_tbm2); + setRegister("delay_tbm3", config.delay_tbm3); + setRegister("bypass_delay", config.bypass_delay); + setRegister("clock", config.clock); + setRegister("function_A", config.function_A); + setRegister("function_B", config.function_B); + std::cout<<"Configure done"<<std::endl; + return 0; +} + +template <class TP> +void IPCModule<TP>::shutdown(){ + std::cout<<"Shutdown"<<std::endl; +} + +template <class TP> +void IPCModule<TP>::destroy(){ + this->_destroy(); +} + + + +}; + +#endif diff --git a/rce/rcecalib/config/hitbus/IPCModule.hh b/rce/rcecalib/config/hitbus/IPCModule.hh new file mode 100644 index 00000000..f5819096 --- /dev/null +++ b/rce/rcecalib/config/hitbus/IPCModule.hh @@ -0,0 +1,26 @@ +#ifndef IPCHITBUSMODULE_HH +#define IPCHITBUSMODULE_HH + +#include "rcecalib/config/hitbus/Module.hh" +#include "ipc/object.h" +#include "HitbusModuleConfig.hh" +#include "IPCHitbusAdapter.hh" + +class IPCPartition; +class AbsFormatter; + +namespace Hitbus{ +template <class TP = ipc::single_thread> +class IPCModule: public IPCNamedObject<POA_ipc::IPCHitbusAdapter,TP>, public Hitbus::Module { +public: + IPCModule(IPCPartition & p, const char * name, unsigned id, unsigned inlink, unsigned outlink, AbsFormatter* fmt); + ~IPCModule(); + CORBA::Long IPCdownloadConfig(const ipc::HitbusModuleConfig &config); + void shutdown(); + void destroy(); + +}; +}; + + +#endif diff --git a/rce/rcecalib/config/hitbus/Module.cc b/rce/rcecalib/config/hitbus/Module.cc new file mode 100644 index 00000000..0f3f4d92 --- /dev/null +++ b/rce/rcecalib/config/hitbus/Module.cc @@ -0,0 +1,129 @@ +#include "rcecalib/HW/BitStream.hh" +#include "rcecalib/config/hitbus/Module.hh" +#include "rcecalib/config/FEI4/FECommands.hh" +#include "rcecalib/HW/SerialIF.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/util/exceptions.hh" +#include <iostream> +#include "ers/ers.h" +#include <stdio.h> + +namespace Hitbus{ + + Module::Module(const char* name, unsigned id, unsigned inLink, unsigned outLink, AbsFormatter* fmt) + :AbsModule(name, id,inLink, outLink, fmt){ + // std::cout<<"Module"<<std::endl; + if(!m_initialized)initialize(); + m_regw=new unsigned short[m_registers.size()]; + for(size_t i=0;i<m_registers.size();i++)m_regw[i]=0; + m_commands=new FEI4::FECommands; + } + Module::~Module(){ + delete [] m_regw; + delete m_commands; + } + void Module::writeHW(){ + for(size_t i=0;i<m_registers.size();i++){ + assert(writeRegisterHW(i, m_regw[i])==0); + } + } + unsigned Module::writeRegisterHW(int i, unsigned short val){ + // i is position in vector, not actual address + m_regw[i]=val; // set register content + int addr=m_registers[i].reg; + int rval=val&((1<<m_registers[i].width)-1); + writeRegisterRawHW(addr, rval); + return 0; + } + void Module::writeRegisterRawHW(int i, unsigned short val){ + BitStream *bs=new BitStream; + m_commands->writeGlobalRegister(bs, 47, (i<<8) | val); + SerialIF::send(bs, SerialIF::WAITFORDATA); //Write register + delete bs; + } + + void Module::configureHW(){ + std::cout<<"Configuring hitbus"<<std::endl; + printRegisters(std::cout); + resetFE(); + writeHW(); + } + + void Module::resetFE(){ + writeRegisterRawHW(0x94, 0xcd); //pulse clear + writeRegisterRawHW(1, 1); // core reset on + writeRegisterRawHW(1, 0); // core reset off + } + + // set a parameter (global or MCC) in the frontend + int Module::setupParameterHW(const char* name, int val){ + int retval=1; + if(m_parameters.find(name)!=m_parameters.end()){ + retval=0; + writeRegisterHW(m_parameters[name], val); + } + return retval; + } + + int Module::configureScan(boost::property_tree::ptree *scanOptions){ + int retval=0; + // do nothing for now + return retval; + } + void Module::destroy(){ + delete this; + } + ModuleInfo Module::getModuleInfo(){ + return ModuleInfo(m_name, m_id,m_inLink, m_outLink, N_FRONTENDS, N_ROWS, N_COLS, m_formatter); + } + + void Module::printRegisters(std::ostream &os){ + for(size_t i=0;i<m_registers.size();i++){ + os<<m_registers[i].name<<": Address="<<m_registers[i].reg<<" Value="<<m_regw[i]<<std::endl; + } + } + void Module::setRegister(const char* name, unsigned short val){ + int reg=findRegister(name); + if(reg!=-1)m_regw[reg]=val; + } + + //static functions + void Module::addParameter(const char* name, const char* field){ + int regnum=findRegister(field); + assert(regnum>-1); + m_parameters[name]=regnum; + } + int Module::findRegister(const char* name){ + for(size_t i=0;i<m_registers.size();i++){ + if(m_registers[i].name==name)return i; + } + return -1; + } + void Module::addRegister(const char* name, int reg, unsigned width){ + RegParams temp; + temp.reg=reg; + temp.width=width; + temp.name=name; + m_registers.push_back(temp); + } + std::vector<RegParams> Module::m_registers; + std::map<std::string, int> Module::m_parameters; + bool Module::m_initialized = false; + + void Module::initialize(){ + addRegister("bpm", 2, 1); + addRegister("delay_tam1", 5, 7); + addRegister("delay_tam2", 6, 7); + addRegister("delay_tam3", 7, 7); + addRegister("delay_tbm1", 8, 7); + addRegister("delay_tbm2", 9, 7); + addRegister("delay_tbm3", 10, 7); + addRegister("bypass_delay", 17, 1); + addRegister("clock", 21, 8); + addRegister("function_A", 18, 8); + addRegister("function_B", 19, 8); + + m_initialized=true; + } +}; + diff --git a/rce/rcecalib/config/hitbus/Module.hh b/rce/rcecalib/config/hitbus/Module.hh new file mode 100644 index 00000000..f11e5e27 --- /dev/null +++ b/rce/rcecalib/config/hitbus/Module.hh @@ -0,0 +1,55 @@ +#ifndef HITBUS__MODULE_HH +#define HITBUS__MODULE_HH + +#include "rcecalib/config/AbsModule.hh" +#include <boost/property_tree/ptree_fwd.hpp> +#include <map> +#include <string> + +class AbsFormatter; +namespace FEI4{ + class FECommands; +}; + +namespace Hitbus{ + + struct RegParams{ + int reg; + int width; + std::string name; + }; + + class Module: public AbsModule{ + public: + Module(const char* name, unsigned id, unsigned inLink, unsigned outLink, AbsFormatter* fmt); + virtual ~Module(); + enum {N_FRONTENDS=0, N_ROWS=0, N_COLS=0}; + void configureHW(); + void resetFE(); + void setupMaskStageHW(int stage){}; + void enableDataTakingHW(){}; + void setRegister(const char* name, unsigned short val); + int setupParameterHW(const char* name, int val); //HW setup + int configureScan(boost::property_tree::ptree* scanOptions); + ModuleInfo getModuleInfo(); + const float dacToElectrons(int fe, int dac){return 0;} + void printRegisters(std::ostream &os); + unsigned writeRegisterHW(int i, unsigned short val); + void writeRegisterRawHW(int i, unsigned short val); + void writeHW(); + virtual void destroy(); + private: + FEI4::FECommands* m_commands; + unsigned short *m_regw;// write registers + static void addRegister(const char* name, int reg, unsigned width); + static void addParameter(const char* name, const char* field); + static int findRegister(const char* name); + static void initialize(); + static std::vector<RegParams> m_registers; + static std::map<std::string, int> m_parameters; + static bool m_initialized; + +}; + +}; +#endif diff --git a/rce/rcecalib/config/hitbus/ModuleGroup.cc b/rce/rcecalib/config/hitbus/ModuleGroup.cc new file mode 100644 index 00000000..3e888cb4 --- /dev/null +++ b/rce/rcecalib/config/hitbus/ModuleGroup.cc @@ -0,0 +1,81 @@ + +#include <boost/property_tree/ptree.hpp> +#include <stdio.h> +#include "rcecalib/config/hitbus/Module.hh" +#include "rcecalib/config/hitbus/ModuleGroup.hh" +#include "rcecalib/util/exceptions.hh" +#include "ers/ers.h" +#include "rcecalib/HW/SerialIF.hh" + +namespace Hitbus{ + +void ModuleGroup::addModule(Module* module){ + m_modules.push_back(module); + m_channelInMask|=1<<module->getInLink(); + m_channelOutMask=0; +} + +void ModuleGroup::deleteModules(){ + for (unsigned i=0; i<m_modules.size();i++){ + //cannot call delete directly because IPC modules need to call _destroy() instead. + m_modules[i]->destroy(); + } + m_modules.clear(); + m_channelInMask=0; + m_channelOutMask=0; +} + +int ModuleGroup::setupParameterHW(const char* name, int val, bool bcOK){ + int retval=0; + for (unsigned int i=0;i<m_modules.size();i++){ + SerialIF::setChannelInMask(1<<m_modules[i]->getInLink()); + retval+=m_modules[i]->setupParameterHW(name,val); + } + disableAllInChannels(); + return retval; +} + +int ModuleGroup::setupMaskStageHW(int stage){ + // no mask staging for the hitbus chip. + return 0; +} + +void ModuleGroup::configureModulesHW(){ + //std::cout<<"Configure Modules HW"<<std::endl; + for (unsigned int i=0;i<m_modules.size();i++){ + SerialIF::setChannelInMask(1<<m_modules[i]->getInLink()); + std::cout<<"Setting channel in mask for inlink "<<m_modules[i]->getInLink()<<std::endl; + m_modules[i]->configureHW(); + } + SerialIF::sendCommand(0x10); //phase calibration + disableAllInChannels(); +} + +void ModuleGroup::resetFE(){ + for (unsigned int i=0;i<m_modules.size();i++){ + SerialIF::setChannelInMask(1<<m_modules[i]->getInLink()); + m_modules[i]->resetFE(); + } + disableAllInChannels(); +} + +void ModuleGroup::enableDataTakingHW(){ + // do nothing +} + +int ModuleGroup::verifyModuleConfigHW(){ + return 0; // does not exist for Hitbus +} +void ModuleGroup::resetErrorCountersHW(){ + //does not exist for Hitbus +} + +int ModuleGroup::configureScan(boost::property_tree::ptree *scanOptions){ + int retval=0; + for (unsigned int i=0;i<m_modules.size();i++){ + retval+=m_modules[i]->configureScan(scanOptions); + } + return retval; +} + +} diff --git a/rce/rcecalib/config/hitbus/ModuleGroup.hh b/rce/rcecalib/config/hitbus/ModuleGroup.hh new file mode 100644 index 00000000..2fc5158c --- /dev/null +++ b/rce/rcecalib/config/hitbus/ModuleGroup.hh @@ -0,0 +1,33 @@ +#ifndef MODULEGROUPHITBUS_HH +#define MODULEGROUPHITBUS_HH +#include "rcecalib/config/AbsModuleGroup.hh" +#include <boost/property_tree/ptree_fwd.hpp> +#include <vector> + +namespace Hitbus{ + + class Module; + +class ModuleGroup: public AbsModuleGroup{ +public: + ModuleGroup():AbsModuleGroup(){}; + virtual ~ModuleGroup(){} + void addModule(Module* module); + void deleteModules(); + int setupParameterHW(const char* name, int val, bool bcok); + int setupMaskStageHW(int stage); + void configureModulesHW(); + int verifyModuleConfigHW(); + void resetErrorCountersHW(); + int configureScan(boost::property_tree::ptree *scanOptions); + void resetFE(); + void enableDataTakingHW(); + unsigned getNmodules(){return m_modules.size();} +private: + void switchToConfigModeHW(); + std::vector<Module*> m_modules; + +}; +} + +#endif diff --git a/rce/rcecalib/dataproc/AbsDataHandler.hh b/rce/rcecalib/dataproc/AbsDataHandler.hh new file mode 100644 index 00000000..17a91ac4 --- /dev/null +++ b/rce/rcecalib/dataproc/AbsDataHandler.hh @@ -0,0 +1,23 @@ +#ifndef ABSDATAHANDLER_HH +#define ABSDATAHANDLER_HH + +#include <vector> +#include <assert.h> +#include "rcecalib/util/DataCond.hh" + +class AbsDataProc; +class ConfigIF; + +class AbsDataHandler{ +public: + AbsDataHandler(AbsDataProc* dataproc, DataCond& datacond, ConfigIF* cif) + :m_dataProc(dataproc), m_dataCond(datacond), m_configIF(cif){} + virtual ~AbsDataHandler(){}; + virtual void handle(unsigned link, unsigned* data, int size)=0; + virtual void timeoutOccurred(){} +protected: + AbsDataProc* m_dataProc; + DataCond& m_dataCond; + ConfigIF* m_configIF; +}; +#endif diff --git a/rce/rcecalib/dataproc/AbsDataProc.cc b/rce/rcecalib/dataproc/AbsDataProc.cc new file mode 100644 index 00000000..4240295d --- /dev/null +++ b/rce/rcecalib/dataproc/AbsDataProc.cc @@ -0,0 +1,47 @@ +#include "rcecalib/dataproc/AbsDataProc.hh" +#include "rcecalib/config/ConfigIF.hh" +#include <stdio.h> +#include "ers/ers.h" + +AbsDataProc::AbsDataProc(ConfigIF* cif):m_configIF(cif){ + m_currentMaskStage=0; + m_currentBin=0; + m_info.clear(); + int maxlink=0; + m_nEvents=0; + for (unsigned int i=0;i<m_configIF->getNmodules();i++){ + m_info.push_back(m_configIF->getModuleInfo(i)); + if(m_info[i].getOutLink()>maxlink)maxlink=m_info[i].getOutLink(); + } + maxlink++; + m_linkToIndex=new int[maxlink]; + for (unsigned int i=0;i<m_configIF->getNmodules();i++){ + m_linkToIndex[m_info[i].getOutLink()]=i; + } + +} + +AbsDataProc::~AbsDataProc(){ + delete [] m_linkToIndex; +} +int AbsDataProc::changeBin(int i){ + m_currentBin=i; + ERS_DEBUG(2,"Change bin"); + return 0; +} + +int AbsDataProc::fit(std::string fitfunc){ + ERS_DEBUG(2,"fit"); + return 0; +} +int AbsDataProc::setMaskStage(int stage){ + m_currentMaskStage=stage; + ERS_DEBUG(2,"setMaskStage"); + return 0; +} + +int AbsDataProc::processData(unsigned link, unsigned* data, int size){ + ERS_DEBUG (2,"processing data"); + return 0; +} + diff --git a/rce/rcecalib/dataproc/AbsDataProc.hh b/rce/rcecalib/dataproc/AbsDataProc.hh new file mode 100644 index 00000000..4e3a77b8 --- /dev/null +++ b/rce/rcecalib/dataproc/AbsDataProc.hh @@ -0,0 +1,30 @@ +#ifndef ABSDATAPROC_HH +#define ABSDATAPROC_HH + +#include <string> +#include <vector> +#include <map> +#include "rcecalib/config/ModuleInfo.hh" + +class ConfigIF; +class Scan; + +class AbsDataProc{ +public: + AbsDataProc(ConfigIF* cif); + virtual ~AbsDataProc(); + virtual int changeBin(int i); + virtual int setMaskStage(int stage); + virtual int processData(unsigned link, unsigned *data, int size); + virtual int fit(std::string fitfun); + virtual unsigned nEvents(){return m_nEvents;} +protected: + ConfigIF* m_configIF; + std::vector<ModuleInfo> m_info; + int *m_linkToIndex; + int m_currentMaskStage; + int m_currentBin; + unsigned m_nEvents; +}; + +#endif diff --git a/rce/rcecalib/dataproc/AbsReceiver.hh b/rce/rcecalib/dataproc/AbsReceiver.hh new file mode 100644 index 00000000..c5376712 --- /dev/null +++ b/rce/rcecalib/dataproc/AbsReceiver.hh @@ -0,0 +1,15 @@ +#ifndef ABSRECEIVER_HH +#define ABSRECEIVER_HH + +#include "rcecalib/dataproc/AbsDataHandler.hh" + +class AbsReceiver{ +public: + AbsReceiver(AbsDataHandler* handler):m_handler(handler){} + virtual ~AbsReceiver(){} + virtual void resynch(){} +protected: + AbsDataHandler* m_handler; + +}; +#endif diff --git a/rce/rcecalib/dataproc/BcidDataProc.cc b/rce/rcecalib/dataproc/BcidDataProc.cc new file mode 100644 index 00000000..405005f5 --- /dev/null +++ b/rce/rcecalib/dataproc/BcidDataProc.cc @@ -0,0 +1,155 @@ +#include <stdio.h> +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/dataproc/BcidDataProc.hh" +#include "rcecalib/config/ConfigIF.hh" +#include "rcecalib/config/FormattedRecord.hh" +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/dataproc/fit/FitFactory.cc" +#include "rcecalib/dataproc/fit/CalculateMeanSigma.cc" + + +int BcidDataProc::fit(std::string fitfun) { + std::cout << "Running: " << fitfun << std::endl; + if(fitfun=="CALCULATE_MEAN_SIGMA" && m_nPoints!=0) { + calculateMeanSigma(m_histo_occ, m_histo_bcid, m_histo_bcid2, m_histo_bcid_mean, m_histo_bcid_sigma); + } + return 0; +} + +int BcidDataProc::processData(unsigned link, unsigned *data, int size){ + // std::cout<<"Process data"<<std::endl; + for (int i=0;i<size;i++){ + int module=m_linkToIndex[link]; // will be different when parser is fully there + FormattedRecord current(data[i]); + if (current.isHeader()){ + l1id = current.getL1id(); + bcid = current.getBxid(); + //printf("bcid : %x \n", bcid); + //printf("l1id : %x \n", l1id); + if (l1id != l1id_last) + { + l1id_last = l1id; + bcid_ref = bcid; + } + bcid = bcid-bcid_ref; + // printf("bcidafter : %x \n", bcid); + } + if (current.isData()){ + unsigned int chip=current.getFE(); + //unsigned int tot=current.getToT(); + unsigned int col=current.getCol(); + unsigned int row=current.getRow(); + //printf("Hit col=%d row=%d tot=%d\n",col, row, tot); + m_histo_occ[module][m_currentBin]->increment(chip*m_info[module].getNColumns()+col,row); + m_histo_bcid[module][m_currentBin]->fill(chip*m_info[module].getNColumns()+col,row,(unsigned int)bcid); + m_histo_bcid2[module][m_currentBin]->fill(chip*m_info[module].getNColumns()+col,row,(unsigned int)bcid*bcid); + //printf("bcidafter : %x \n", bcid); + } + } + return 0; +} + +BcidDataProc::BcidDataProc(ConfigIF* cif, boost::property_tree::ptree* scanOptions) + :AbsDataProc(cif) { + try{ //catch bad scan option parameters + m_nLoops = scanOptions->get<int>("nLoops"); + /* there is at least one parameter loop */ + /* TODO: fix in scan control */ + m_nPoints=1; + if(m_nLoops>0){ + m_nPoints=scanOptions->get<int>("scanLoop_0.nPoints"); + for(int i=0;i<m_nPoints;i++) { + char pointname[10]; + sprintf(pointname,"P_%d",i); + int vcal=scanOptions->get<int>(std::string("scanLoop_0.dataPoints.")+pointname); + //std::cout << "point vcal " << vcal << std::endl; + m_vcal.push_back(vcal); + } + } + m_nTrigger=scanOptions->get<int>("trigOpt.nEvents"); + bcid_ref = 0; + l1id_last = 0; + bcid = 0; + l1id = 0; + + for (unsigned int module=0;module<m_configIF->getNmodules();module++){ + std::vector<RceHisto2d<short, short>* > vh; + std::vector<RceHisto2d<char, char>* > vhc; + m_histo_occ.push_back(vhc); + m_histo_bcid.push_back(vh); + m_histo_bcid2.push_back(vh); + m_histo_bcid_sigma.push_back(vh); + m_histo_bcid_mean.push_back(vh); + char name[128]; + char title[128]; + RceHisto2d<short, short> *histo; + RceHisto2d<char, char> *histoc; + unsigned int cols=m_info[module].getNColumns()*m_info[module].getNFrontends(); + unsigned int rows=m_info[module].getNRows(); + unsigned int moduleId=m_info[module].getId(); + std::string moduleName=m_info[module].getName(); + /* retrieve scan points - Vcal steps in this case */ + for (int point=0;point<m_nPoints;point++){ + sprintf(title,"OCCUPANCY Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_Occupancy_Point_%03d", moduleId,point); + histoc=new RceHisto2d<char, char>(name,title,cols,0,cols,rows,0,rows); + if(m_info[module].getNFrontends()==1)histoc->setAxisTitle(0,"Column"); + else histoc->setAxisTitle(0,"FE*N_COL+Column"); + histoc->setAxisTitle(1, "Row"); + m_histo_occ[module].push_back(histoc); + sprintf(title,"BCID Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_BCID_Point_%03d", moduleId,point); + histo=new RceHisto2d<short, short>(name,title,cols,0,cols,rows,0,rows); + if(m_info[module].getNFrontends()==1)histo->setAxisTitle(0,"Column"); + else histo->setAxisTitle(0,"FE*N_COL+Column"); + histo->setAxisTitle(1, "Row"); + m_histo_bcid[module].push_back(histo); + + sprintf(title,"BCID2 Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_BCID2_Point_%03d", moduleId,point); + histo=new RceHisto2d<short, short>(name,title,cols,0,cols,rows,0,rows); + if(m_info[module].getNFrontends()==1)histo->setAxisTitle(0,"Column"); + else histo->setAxisTitle(0,"FE*N_COL+Column"); + histo->setAxisTitle(1, "Row"); + m_histo_bcid2[module].push_back(histo); + + sprintf(title,"BCID_MEAN Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_BCIDmean_Point_%03d", moduleId,point); + histo=new RceHisto2d<short, short>(name,title,cols,0,cols,rows,0,rows); + if(m_info[module].getNFrontends()==1)histo->setAxisTitle(0,"Column"); + else histo->setAxisTitle(0,"FE*N_COL+Column"); + histo->setAxisTitle(1, "Row"); + m_histo_bcid_mean[module].push_back(histo); + + sprintf(title,"BCID_SIGMA Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_BCIDsigma_Point_%03d", moduleId,point); + histo=new RceHisto2d<short, short>(name,title,cols,0,cols,rows,0,rows); + if(m_info[module].getNFrontends()==1)histo->setAxisTitle(0,"Column"); + else histo->setAxisTitle(0,"FE*N_COL+Column"); + histo->setAxisTitle(1, "Row"); + m_histo_bcid_sigma[module].push_back(histo); + } + } + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + ERS_ASSERT(0); + } +} + +BcidDataProc::~BcidDataProc(){ + for (size_t module=0;module<m_histo_bcid.size();module++) + for(size_t i=0;i<m_histo_bcid[module].size();i++)delete m_histo_bcid[module][i]; + for (size_t module=0;module<m_histo_bcid2.size();module++) + for(size_t i=0;i<m_histo_bcid2[module].size();i++)delete m_histo_bcid2[module][i]; + for (size_t module=0;module<m_histo_bcid_sigma.size();module++) + for(size_t i=0;i<m_histo_bcid_sigma[module].size();i++)delete m_histo_bcid_sigma[module][i]; + for (size_t module=0;module<m_histo_bcid_mean.size();module++) + for(size_t i=0;i<m_histo_bcid_mean[module].size();i++)delete m_histo_bcid_mean[module][i]; + for (size_t module=0;module<m_histo_occ.size();module++) + for(size_t i=0;i<m_histo_occ[module].size();i++)delete m_histo_occ[module][i]; + +} + + diff --git a/rce/rcecalib/dataproc/BcidDataProc.hh b/rce/rcecalib/dataproc/BcidDataProc.hh new file mode 100644 index 00000000..d0ab3c7b --- /dev/null +++ b/rce/rcecalib/dataproc/BcidDataProc.hh @@ -0,0 +1,33 @@ +#ifndef BCIDDATAPROC_HH +#define BCIDDATAPROC_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/dataproc/AbsDataProc.hh" +#include <vector> +#include "rcecalib/util/RceHisto2d.cc" + +class BcidDataProc: public AbsDataProc{ +public: + BcidDataProc(ConfigIF* cif,boost::property_tree::ptree* scanOptions ); + virtual ~BcidDataProc(); + int processData(unsigned link, unsigned *data, int size); + int fit(std::string fitfun); + +protected: + + std::vector<std::vector<RceHisto2d<short, short>*> > m_histo_bcid; + std::vector<std::vector<RceHisto2d<short, short>*> > m_histo_bcid2; + std::vector<std::vector<RceHisto2d<short, short>*> > m_histo_bcid_sigma; + std::vector<std::vector<RceHisto2d<short, short>*> > m_histo_bcid_mean; + std::vector<std::vector<RceHisto2d<char, char>*> > m_histo_occ; + std::vector<int> m_vcal; + int m_nTrigger; + int m_nLoops; + int m_nPoints; + unsigned int bcid_ref; + unsigned int l1id_last; + unsigned int bcid; + unsigned int l1id; +}; + +#endif diff --git a/rce/rcecalib/dataproc/Channeldefs.hh b/rce/rcecalib/dataproc/Channeldefs.hh new file mode 100644 index 00000000..bf2fad0c --- /dev/null +++ b/rce/rcecalib/dataproc/Channeldefs.hh @@ -0,0 +1,7 @@ +#ifndef CHANNELDEFS_HH +#define CHANNELDEFS_HH + +enum channeldefs {ADCREADOUT=29, TDCREADOUT=30, PGPACK=31}; +enum shiftdefs {MARKERPOS=7, RCEPOS=8, LINKMASK=0x7f, RCEMASK=0xff}; + +#endif diff --git a/rce/rcecalib/dataproc/ClusterProc.cc b/rce/rcecalib/dataproc/ClusterProc.cc new file mode 100644 index 00000000..16a9d7cf --- /dev/null +++ b/rce/rcecalib/dataproc/ClusterProc.cc @@ -0,0 +1,154 @@ +#include "rcecalib/dataproc/ClusterProc.hh" +#include <stdio.h> + +ClusterProc::ClusterProc() { + cluster_id = 0; + // Safety cuts + max_hits_in_cluster = 20; + max_hits = 3000; + // Cluster cuts + bcidCut = 3; + colCut = 1; + rowCut = 1; +} + +ClusterProc::ClusterProc(RceHisto1d<int, int> *histo_hits, RceHisto1d<int, int> *histo_tot, RceHisto2d<int, int> *histo_tot_size) { + cluster_id = 0; + // Safety cuts + max_hits_in_cluster = 20; + max_hits = 3000; + // Cluster cuts + bcidCut = 3; + colCut = 1; + rowCut = 1; + m_histo_hits = histo_hits; + m_histo_tot = histo_tot; + m_histo_tot_size = histo_tot_size; +} + +ClusterProc::~ClusterProc() { + colVec.clear(); + rowVec.clear(); + totVec.clear(); + bcidVec.clear(); + + tot_in_cluster.clear(); + hits_in_cluster.clear(); + cluster_with_overflow.clear(); +} + +void ClusterProc::assignHitHisto(RceHisto1d<int, int> *histo_hits) { + m_histo_hits = histo_hits; +} + +void ClusterProc::assignToTHisto(RceHisto1d<int, int> *histo_tot) { + m_histo_tot = histo_tot; +} + +void ClusterProc::assignToTClusterSizeHisto(RceHisto2d<int, int> *histo_tot_size) { + m_histo_tot_size = histo_tot_size; +} + +void ClusterProc::addHit(unsigned int col, unsigned int row, unsigned int tot, unsigned int bcid) { + colVec.push_back(col); + rowVec.push_back(row); + totVec.push_back(tot); + bcidVec.push_back(bcid); +} + +void ClusterProc::iterativeSeek(unsigned int this_cluster) { + // not yet implemented +} + +void ClusterProc::recursiveSeek(unsigned int this_cluster, unsigned int col, unsigned int row, unsigned int bcid) { + for(unsigned int i=0; i<colVec.size(); i++) { + // Safety if for too big clusters + if (hits_in_cluster[this_cluster] > max_hits_in_cluster) return; + + // Check if hit is in the cluster range and in time + if ((abs((int)(colVec[i]-col)) <= colCut) && + (abs((int)(rowVec[i]-row)) <= rowCut) && + (abs((int)(bcidVec[i]-bcid)) <= bcidCut)) { + // Add it + unsigned int new_col = colVec[i]; + unsigned int new_row = rowVec[i]; + unsigned int new_bcid = bcidVec[i]; + hits_in_cluster[this_cluster]++; + tot_in_cluster[this_cluster] += totVec[i]; + if (totVec[i]>13) cluster_with_overflow[this_cluster] = true; + + // Erase hit + colVec.erase(colVec.begin()+i); + rowVec.erase(rowVec.begin()+i); + totVec.erase(totVec.begin()+i); + bcidVec.erase(bcidVec.begin()+i); + + // Search from here (questionable which bcid to pick) + this->recursiveSeek(this_cluster, new_col, new_row, new_bcid); + } + } +} + +void ClusterProc::clusterize() { + unsigned int safety_cnt = 0; + while((!colVec.empty()) && (safety_cnt < max_hits)) { + // New cluster + unsigned int this_cluster = cluster_id; + hits_in_cluster.push_back(0); + tot_in_cluster.push_back(0); + cluster_with_overflow.push_back(false); + + // Insert first hit + unsigned int col = colVec[0]; + unsigned int row = rowVec[0]; + unsigned int bcid = bcidVec[0]; + hits_in_cluster[this_cluster]++; + tot_in_cluster[this_cluster] += totVec[0]; + + // Dismiss clusters with overflow ToT + if(totVec[0] > 13) cluster_with_overflow[this_cluster] = true; + + // Erase hit + colVec.erase(colVec.begin()); + rowVec.erase(rowVec.begin()); + totVec.erase(totVec.begin()); + bcidVec.erase(bcidVec.begin()); + + // Search for more hits + this->recursiveSeek(this_cluster, col, row, bcid); + //printf("New cluster with #%d hits and %d total ToT\n", hits_in_cluster[this_cluster], tot_in_cluster[this_cluster]); + // Next cluster + cluster_id++; + safety_cnt++; + } + // Fill the histograms + this->fillHistos(); + + // Reset all vectors for the next event + this->reset(); +} + +void ClusterProc::fillHistos() { + if (m_histo_hits != NULL && m_histo_tot != NULL) { + for (unsigned int i=0; i<hits_in_cluster.size(); i++) { + if (!cluster_with_overflow[i]) { + if (m_histo_hits) m_histo_hits->increment(hits_in_cluster[i]); + if (m_histo_tot) m_histo_tot->increment(tot_in_cluster[i]); + if (m_histo_tot_size) m_histo_tot_size->increment(tot_in_cluster[i], hits_in_cluster[i]); + } + } + } +} + +void ClusterProc::reset() { + cluster_id = 0; + + colVec.clear(); + rowVec.clear(); + totVec.clear(); + + tot_in_cluster.clear(); + hits_in_cluster.clear(); + cluster_with_overflow.clear(); +} + diff --git a/rce/rcecalib/dataproc/ClusterProc.hh b/rce/rcecalib/dataproc/ClusterProc.hh new file mode 100644 index 00000000..d5e91e55 --- /dev/null +++ b/rce/rcecalib/dataproc/ClusterProc.hh @@ -0,0 +1,61 @@ +#ifndef CLUSTERPROC_HH +#define CLUSTERPROC_HH + +#include <stdio.h> +#include <vector> +#include "rcecalib/util/RceHisto1d.cc" +#include "rcecalib/util/RceHisto2d.cc" +#include "rcecalib/util/RceMath.hh" + +class ClusterProc { +public: + ClusterProc(); + ClusterProc(RceHisto1d<int, int> *histo_hits, RceHisto1d<int, int> *histo_tot, RceHisto2d<int, int> *histo_tot_size); + ~ClusterProc(); + + void assignHitHisto(RceHisto1d<int, int> *histo_hits); + void assignToTHisto(RceHisto1d<int, int> *histo_tot); + void assignToTClusterSizeHisto(RceHisto2d<int, int> *histo_tot_size); + + void addHit(unsigned int col, unsigned int row, unsigned int tot, unsigned int bcid); + + void clusterize(); + void recursiveSeek(unsigned int this_cluster, unsigned int col, unsigned int row, unsigned int bcid); + void iterativeSeek(unsigned int this_cluster); + + void reset(); + void fillHistos(); +private: + // Histograms + RceHisto1d<int, int> *m_histo_hits; + RceHisto1d<int, int> *m_histo_tot; + RceHisto2d<int, int> *m_histo_tot_size; + RceHisto1d<int, int> *m_histo_col_rms; + RceHisto1d<int, int> *m_histo_row_rms; + RceHisto2d<int, int> *m_histo_col_row_rms; + + // Cluster counter + unsigned int cluster_id; + + // To prevent calling the function too often + unsigned int max_hits_in_cluster; + unsigned int max_hits; + + // Cluster cuts + int bcidCut; + int colCut; + int rowCut; + + // Raw data + std::vector<unsigned int> colVec; + std::vector<unsigned int> rowVec; + std::vector<unsigned int> totVec; + std::vector<unsigned int> bcidVec; + + // Clustered data + std::vector<unsigned int> tot_in_cluster; + std::vector<unsigned int> hits_in_cluster; + std::vector<bool> cluster_with_overflow; +}; + +#endif diff --git a/rce/rcecalib/dataproc/CosmicDataHandler.cc b/rce/rcecalib/dataproc/CosmicDataHandler.cc new file mode 100644 index 00000000..6fd7af58 --- /dev/null +++ b/rce/rcecalib/dataproc/CosmicDataHandler.cc @@ -0,0 +1,59 @@ +#include "rcecalib/dataproc/CosmicDataHandler.hh" +#include "rcecalib/dataproc/AbsDataProc.hh" +#include "rcecalib/config/AbsFormatter.hh" +#include "rcecalib/config/DummyFormatter.hh" +#include "rcecalib/config/ConfigIF.hh" +#include "rcecalib/util/DataCond.hh" +#include <boost/property_tree/ptree.hpp> +#include <iostream> + +CosmicDataHandler::CosmicDataHandler(AbsDataProc* dataproc, + DataCond& datacond, + ConfigIF* cif, + boost::property_tree::ptree* scanOptions) + :AbsDataHandler(dataproc, datacond, cif){ + std::cout<<"Cosmic data handler"<<std::endl; + m_nModules=m_configIF->getNmodules(); + for (int i=0;i<m_nModules;i++){ + m_formatter.push_back(m_configIF->getModuleInfo(i).getFormatter()); + } + m_dummy=new DummyFormatter(0); + m_formatter.push_back(m_dummy); + m_linkToIndex=new int[MAXMODULES]; + for(int i=0;i<MAXMODULES;i++)m_linkToIndex[i]=m_nModules; //point to dummy formatter + //now configure existing module formatters + for (int i=0;i<m_nModules;i++){ + m_linkToIndex[m_configIF->getModuleInfo(i).getOutLink()]=i; + } + m_parsedData=new unsigned[16384]; +} + +CosmicDataHandler::~CosmicDataHandler(){ + delete [] m_parsedData; + delete [] m_linkToIndex; + delete m_dummy; +} + +void CosmicDataHandler::handle(unsigned desc, unsigned *data, int size){ + // nL1A contains the number of L1A in the data chunk + unsigned link=desc&0xf; + int parsedsize=0; + //std::cout<<"Data for link "<<link<<std::endl; + unsigned *thedata; + if((link)==10){ + thedata=data; + parsedsize=size; + } else { + thedata=m_parsedData; + int nL1A=0; + int retval=m_formatter[m_linkToIndex[link]]->decode(data,size,m_parsedData, parsedsize, nL1A); + //std::cout<<"parser"<<retval<<" "<<size<<std::endl; + if(retval!=0){ + std::cout<<"Parser error for link "<<link<<": Data size "<<size<<" number of triggers "<<nL1A<<std::endl; + for (int i=0;i<(size<100?size:100);i++)std::cout<<std::hex<<data[i]<<std::endl; + } + } + if(parsedsize>0){ + m_dataProc->processData(desc, thedata, parsedsize); + } +} diff --git a/rce/rcecalib/dataproc/CosmicDataHandler.hh b/rce/rcecalib/dataproc/CosmicDataHandler.hh new file mode 100644 index 00000000..aa3a62f4 --- /dev/null +++ b/rce/rcecalib/dataproc/CosmicDataHandler.hh @@ -0,0 +1,27 @@ +#ifndef COSMICDATAHANDLER_HH +#define COSMICDATAHANDLER_HH + +#include <vector> +#include <map> +#include <assert.h> + +#include "rcecalib/dataproc/AbsDataHandler.hh" +#include <boost/property_tree/ptree_fwd.hpp> + +class AbsFormatter; +class DataCond; + +class CosmicDataHandler: public AbsDataHandler{ +public: + CosmicDataHandler(AbsDataProc* dataproc, DataCond &datacond, ConfigIF* cif, boost::property_tree::ptree* scanOptions); + virtual ~CosmicDataHandler(); + void handle(unsigned desc, unsigned* data, int size); + enum MD{MAXMODULES=16}; +protected: + int m_nModules; + int *m_linkToIndex; + unsigned *m_parsedData; + std::vector<AbsFormatter*> m_formatter; + AbsFormatter * m_dummy; +}; +#endif diff --git a/rce/rcecalib/dataproc/CosmicDataProc.cc b/rce/rcecalib/dataproc/CosmicDataProc.cc new file mode 100644 index 00000000..9eb78485 --- /dev/null +++ b/rce/rcecalib/dataproc/CosmicDataProc.cc @@ -0,0 +1,264 @@ +#include <boost/property_tree/ptree.hpp> +#include <boost/regex.hpp> +#include <boost/algorithm/string.hpp> +#include "rcecalib/dataproc/CosmicDataProc.hh" +#include "rcecalib/config/ConfigIF.hh" +#include "rcecalib/config/FormattedRecord.hh" +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/dataproc/DataProcFactory.hh" +#include "rcecalib/dataproc/CosmicEvent.hh" +#include "rcecalib/dataproc/CosmicEventIterator.hh" +#include "eudaq/Event.hh" +#include "eudaq/DataSender.hh" +#include "eudaq/DataSenderIF.hh" +#include "eudaq/DetectorEvent.hh" +#include "eudaq/RawDataEvent.hh" +#include "eudaq/counted_ptr.hh" +#include <iomanip> +#include <iostream> +#include <stdlib.h> + + +int CosmicDataProc::fit(std::string command){ + if(command=="CloseFile"){ + std::cout<<"Number of fragments processed: "<<m_nfrag<<std::endl; + if(m_file!=0){ + sleep(1); // wait for any left over data to trickle in + eudaq::DetectorEvent dev(m_runNo,m_nEvents,0); + dev.SetFlags(eudaq::Event::FLAG_EORE); + eudaq::RawDataEvent *revc=new eudaq::RawDataEvent(eudaq::RawDataEvent::EORE("CTEL",m_runNo,m_nEvents)); + counted_ptr<eudaq::Event> cpc(revc); + dev.AddEvent(cpc); + eudaq::RawDataEvent *revd=new eudaq::RawDataEvent(eudaq::RawDataEvent::EORE("APIX-CT",m_runNo,m_nEvents)); + counted_ptr<eudaq::Event> cpd(revd); + dev.AddEvent(cpd); + dev.Serialize(*m_file); + delete m_file; + m_file=0; + } + // m_file.close(); + std::cout<<"close file called"<<std::endl; + } + return 0; +} + +int CosmicDataProc::processData(unsigned rlink, unsigned *data, int size){ + m_nfrag++; + if((m_nfrag&0xffff)==0)usleep(1); //give external commands a chance to execute from time to time + int link=rlink&0xf; + bool marker=((rlink&0x10)==0x10); + m_hits=0; + // std::cout<<"DataProc Link "<<link<<" size "<<size<<std::endl; + // if synching throw away fragments until we find the marker + if(m_linksynch[link]==true) { + if (marker==false){ + if(m_print>0){ + if(link==10)std::cout<<"Ignoring Link 10 L1A: "<<(data[1]>>24)<<std::endl; + else { + FormattedRecord fr(data[0]); + std::cout<<"Ignoring Link "<<link<<" L1A: "<<fr.getL1id()<<" bxid: "<<fr.getBxid()<<std::endl; + } + m_print--; + } + m_tossed[link]++; + return 0; + } + m_linksynch[link]=false; + //if(marker)std::cout<<"Markerevent"<<std::endl; + std::cout<<"Tossed "<<m_tossed[link]<<" fragments for link "<<link<<std::endl; + } + if (link==10){ + // unsigned trgtime1=data[3]; + // unsigned trgtime2=data[4]; + // unsigned long long trgtime=trgtime1; + // trgtime=(trgtime<<32) | trgtime2; + + // std::cout<<"Trigger time: "<<std::hex<<trgtime<<std::dec<<std::endl; + // std::cout<<"Link 10 L1id "<<((data[0]>>24)&0xf)<<std::endl; + //This doesn't work with multiple RCE's yet--BL + bool success=m_iterator->setTdcData(data,0); + if(success==false){ + resynch(); + return 0; + } + }else{ + int module=m_linkToIndex[link]; //map link onto module index + unsigned int l1id=99; + int ntrg=0; + int bxfirst=-666; + int bxlast=-555; + int start=0; + do{ //possibly we must split the data because it belongs to 2 triggers. + //if(start!=0)std::cout<<"Newstart "<<start<<std::endl; + int newstart=processModuleData(&data[start],size-start,link, l1id,bxfirst,bxlast,ntrg); + //if(m_hits>0) std::cout<<"Link "<<link<<" had "<<m_hits<<" hits."<<std::endl; + // std::cout<<"Data from module "<<module<<" link="<<link<<" with l1id="<<l1id<<" ntrg="<<ntrg<<std::endl; + bool isdut=((link<9) || (m_file==0)); //all data is DUT when running as a producer (m_file==0) + + //This doesn't work with multiple RCE's yet--BL + bool success=m_iterator->addPixelData(module,l1id, bxfirst, bxlast, ntrg, 0, isdut,&data[start],newstart); + if(success==false){ + resynch(); + return 0; + } + start+=newstart; + }while(start<size); + } + return 0; +} + +int CosmicDataProc::processModuleData(unsigned* udata,int size, int link, unsigned& l1id, int& bxfirst, int &bxlast, int &ntrg){ + FormattedRecord* data=(FormattedRecord*)udata; + if(!data[0].isHeader()){ + std::cout<<"Module data not starting with 0x2xxxxxxx"<<std::endl; + return -1; + } + //int bx; + ntrg=1; + data[0].setLink(link); + bxfirst=data[0].getBxid()&0xff; + bxlast=bxfirst; + l1id=data[0].getL1id()&0xf; + //std::cout<<"Link "<<link<<" l1a "<<l1id<<" bx "<<bx<<std::endl; + unsigned l1a; + for (int i=1;i<size;i++){ + if (data[i].isHeader()){ + data[i].setLink(link); + l1a=data[i].getL1id()&0xf; + bxlast=data[i].getBxid(); + //std::cout<<"Link "<<link<<" l1a "<<l1a<<" bx "<<bx<<std::endl; + if(l1id!=l1a)return i; + ntrg++; + } + //}else if(data[i]&0x80000000){ + // //m_hits++; + // int chip=(data[i]>>24)&0xf; + // int tot=(data[i]>>16)&0xff; + // int col=(data[i]>>8)&0x1f; + // int row=data[i]&0xff; + // int tr=bx-bxfirst; + // if (tr<0)tr+=256; + //if(row<156 && tot > 6) + // std::cout<<"Link "<<link<<" Trigger "<<tr<<" Chip "<<chip<<" row "<<row<<" col "<<col<<" tot "<<tot<<std::endl; + // } + } + return size; +} + + +void CosmicDataProc::resynch(){ + std::cout<<"Resynchronizing"<<std::endl; + int serstat; + serstat=m_configIF->sendHWcommand(4);//pause run + assert(serstat==0); + // set synch flags for everybody + for (int i=0;i<16;i++)m_linksynch[i]=true; + for (int i=0;i<16;i++)m_tossed[i]=0; + m_print=0; + m_configIF->resetCountersHW();//send ECR and BCR + m_iterator->resynch(); + serstat=m_configIF->sendHWcommand(7);//resume run and post marker + assert(serstat==0); +} + +CosmicDataProc::CosmicDataProc(ConfigIF* cif, boost::property_tree::ptree* scanOptions) + :AbsDataProc(cif) { + std::cout<<"Start CosmicDataProc Constructor"<<std::endl; + try{ //catch bad scan option parameters + m_nModules=m_configIF->getNmodules(); + + for (int i=0;i<16;i++)m_linksynch[i]=false; + m_nfrag=0; + m_print=0; + m_nL1AperEv=scanOptions->get<int>("trigOpt.nL1AperEvent"); + std::string name=scanOptions->get<std::string>("Name"); + std::cout<<"CosmicDataProc name "<<name<<std::endl; + m_runNo=0; + + std::string prefix("CosmicGui"); + if (name.compare(0, prefix.size(), prefix) == 0) + { + // CosmicGui asks to send back over TCP + // parse string of form: CosmicGui|01168|tcp://127.56.2.6:4500 + std::vector<std::string> strs; + boost::split(strs, name, boost::is_any_of("|")); + m_runNo=atoi(strs[1].c_str()); + name = strs[2]; + + std::cout<<"TCP to " << name << " instead of file"<<std::endl; + m_file = 0; + eudaq::DataSender * ds = new eudaq::DataSender(std::string("DataSender"), std::string("CosmicGuiDataSender")); + DataSenderIF::setDataSender(ds); + try + { + ds->Connect(name); + } + catch (const std::exception & ex) + { + // Need to do sensible things here, maybe catch different types of exceptions. + std::cout << "DataSender could not connect. Exception says: \n " << ex.what() << std::endl; + } + + } + else + { + boost::cmatch matches; + boost::regex re("(\\d+)"); + if(boost::regex_search(name.c_str(), matches, re)){ + if(matches.size()>1){ + std::string match(matches[1].first, matches[1].second); + m_runNo=strtoul(match.c_str(),0,10); + } + } + + boost::regex r1("TCP"); + if(boost::regex_search(name,r1)==0) + { + // Write file to NFS + std::string path="/nfs/cosmicData/"; + std::string fullpath=path+name+".raw"; + // m_file.open(fullpath.c_str()); + m_file=new eudaq::FileSerializer(fullpath.c_str()); + eudaq::DetectorEvent dev(m_runNo,0,0); + dev.SetFlags(eudaq::Event::FLAG_BORE); + dev.SetTag("CONFIG", "Name = Test"); + eudaq::RawDataEvent *revc=new eudaq::RawDataEvent(eudaq::RawDataEvent::BORE("CTEL",m_runNo)); + counted_ptr<eudaq::Event> cpc(revc); + dev.AddEvent(cpc); + eudaq::RawDataEvent *revd=new eudaq::RawDataEvent(eudaq::RawDataEvent::BORE("APIX-CT",m_runNo)); + counted_ptr<eudaq::Event> cpd(revd); + dev.AddEvent(cpd); + dev.Serialize(*m_file); + } + else + { + // Don't write to file. Send events to Eudaq instead. + m_file=0; + } + + + } + std::cout<<"Run number "<<m_runNo<<std::endl; + + // create the event iterator class which does all the work + //This doesn't work with multiple RCE's yet--BL + std::vector<int> rces; + rces.push_back(0); + m_iterator=new CosmicEventIterator(false, m_file, 0, m_runNo,m_nModules,rces); + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + ERS_ASSERT(0); + } +} + +CosmicDataProc::~CosmicDataProc(){ + + delete m_file; + delete m_iterator; +} + +unsigned CosmicDataProc::nEvents(){ + return m_iterator->nEvents(); +} diff --git a/rce/rcecalib/dataproc/CosmicDataProc.hh b/rce/rcecalib/dataproc/CosmicDataProc.hh new file mode 100644 index 00000000..c0884184 --- /dev/null +++ b/rce/rcecalib/dataproc/CosmicDataProc.hh @@ -0,0 +1,39 @@ +#ifndef COSMICDATAPROC_HH +#define COSMICDATAPROC_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/dataproc/AbsDataProc.hh" +#include "rcecalib/eudaq/FileSerializer.hh" +#include <list> +#include <fstream> +#include <fstream> + +class CosmicEvent; +class CosmicEventIterator; + +class CosmicDataProc: public AbsDataProc{ +public: + CosmicDataProc(ConfigIF* cif,boost::property_tree::ptree* scanOptions ); + virtual ~CosmicDataProc(); + int processData(unsigned link, unsigned *data, int size); + int fit(std::string); + unsigned nEvents(); +protected: + void resynch(); + inline int processModuleData(unsigned* data,int size, int link, unsigned& l1id, int& bxfirst, int& bxlast, int &ntrg); + + int m_nL1AperEv; + int m_nModules; + bool m_linksynch[16]; + int m_tossed[16]; + unsigned m_runNo; + eudaq::FileSerializer *m_file; + //std::ofstream m_file; + int m_nfrag; + CosmicEventIterator* m_iterator; + int m_print; + int m_hits; + +}; + +#endif diff --git a/rce/rcecalib/dataproc/CosmicEvent.cc b/rce/rcecalib/dataproc/CosmicEvent.cc new file mode 100644 index 00000000..58b3c1fe --- /dev/null +++ b/rce/rcecalib/dataproc/CosmicEvent.cc @@ -0,0 +1,302 @@ +#include "rcecalib/dataproc/CosmicEvent.hh" +#include "rcecalib/eudaq/FileSerializer.hh" +#include "rcecalib/eudaq/Event.hh" +#include "rcecalib/eudaq/RawDataEvent.hh" +#include "rcecalib/eudaq/DetectorEvent.hh" +#include "rcecalib/eudaq/ProducerIF.hh" +#include "rcecalib/eudaq/DataSenderIF.hh" +#include "rcecalib/dataproc/CosmicEventReceiver.hh" + +bool CosmicEvent::m_synch=false; +int CosmicEvent::m_lastTLU=0; + +CosmicEvent::CosmicEvent(unsigned runno, unsigned l1a, unsigned nMod, std::vector<int>& rces): + m_tdctrig(false), m_l1a(l1a), m_nMod(nMod), + m_runno(runno), m_rces(rces){ + + for (unsigned int i=0;i<nMod;i++){ + m_ntrig.push_back(0); + m_bx.push_back(999); + m_bxlast.push_back(999); + m_modRceIndex.push_back(9999); + } + + m_nRce = m_rces.size(); + for(unsigned int i=0; i<m_nRce; i++){ + m_timestamp.push_back(0); + m_tdcbx.push_back(999); + } + + m_ctel=new eudaq::RawDataEvent("CTEL",m_runno,0); + m_ctel->AddBlock(0); + m_dut=new eudaq::RawDataEvent("APIX-CT",m_runno,0); + m_dut->AddBlock(0); + + for(unsigned int iRce=0; iRce<m_nRce; iRce++){ + m_dut->AddBlock(iRce+1); + unsigned rceNum = m_rces[iRce]; + rceNum |= 0x40000000; //HeaderTwo format + m_dut->AppendBlock(iRce+1,(char*)&rceNum,sizeof(unsigned)); + } + +} + +CosmicEvent::~CosmicEvent(){ + delete m_dut; + delete m_ctel; +} +void CosmicEvent::setTdcData(unsigned firstword, unsigned* data, unsigned rceIndex){ + m_tdctrig=true; + + unsigned rceNum = m_rces[rceIndex]; + + //std::cout<<"Appending TDC data: "<<std::endl; + //std::cout<<std::hex<<rceNum<<std::dec<<std::endl; + //std::cout<<std::hex<<firstword<<std::dec<<std::endl; + //for(unsigned int i=0; i<8; i++){ + // std::cout<<std::hex<<data[i]<<std::dec<<" "<<std::endl; + //} + + m_dut->AppendBlock(0,(char*)&rceNum,sizeof(unsigned)); + m_dut->AppendBlock(0,(char*)&firstword,sizeof(unsigned)); + m_dut->AppendBlock(0,(char*)data,8*sizeof(unsigned)); + + //timestamp is a 32 bit number giving the time of arrival of the trigger, in + //units of clock ticks (25 ns) + m_timestamp[rceIndex]=data[3]; + m_timestamp[rceIndex]<<=32; + m_timestamp[rceIndex] |= data[4]; + m_tdcbx[rceIndex] = data[4]&0xff; +} + +void CosmicEvent::appendCtelData(unsigned* data, unsigned size){ + m_ctel->AppendBlock(0,(char*)data,size*sizeof(unsigned)); +} + +void CosmicEvent::appendDutData(unsigned* data, unsigned size, unsigned rceIndex){ + + //unsigned rceNum = m_rces[rceIndex]; + //std::cout<<"Appending dut data for rce "<<rceNum<<" :"<<std::endl; + //for(unsigned int i=0; i<size; i++){ + // std::cout<<std::hex<<data[i]<<std::dec<<" "<<std::endl; + //} + + m_dut->AppendBlock(rceIndex+1,(char*)data,size*sizeof(unsigned)); +} + +void CosmicEvent::incrementTrigger(unsigned mod, int ntrgin, unsigned bxfirst, unsigned bxlast, unsigned rceIndex){ + if(m_modRceIndex[mod]>m_nRce){ + m_modRceIndex[mod]=rceIndex; + } + if(m_ntrig[mod]==0)m_bx[mod]=bxfirst; + m_bxlast[mod]=bxlast; + m_ntrig[mod]+=ntrgin; +} + +bool CosmicEvent::consistent(CosmicEvent* ref){ + for (unsigned i=0;i<m_nMod;i++){ + // Check that all modules have the correct number of triggers + if(m_ntrig[i]!=ref->m_ntrig[i]){ + std::cout<<"Module "<<i<<" has "<<m_ntrig[i]<<" triggers instead of "<<ref->m_ntrig[i]<<std::endl; + return false; + } + //Check that first and last bxid are consistent with the number of triggers. + int diffbx=(m_bxlast[i]+1-m_bx[i])%256; + if(diffbx!=m_ntrig[i]){ + std::cout<<"Bad Module "<<i<<" firstbx "<<m_bx[i]<<" lastbx "<<m_bxlast[i]<< " ntrig "<<m_ntrig[i]<<std::endl; + return false; + } + } + if(this==ref){ //Reference event only + //Make sure that every module from the same RCE has the same first bx number + //It's OK if the bx numbers for different RCE's are different + std::cout<<"Now checking reference event"<<std::endl; + for(unsigned int j_rce=0; j_rce<m_nRce; j_rce++){ + std::cout<<"Module "<<j_rce<<" has "<<m_ntrig[j_rce]<<" triggers."<<std::endl; + int modIndex = getFirstModWithRceIndex(j_rce); + for (unsigned int i_mod=modIndex+1; i_mod<m_nMod; i_mod++){ + if(m_modRceIndex[i_mod]==j_rce && m_bx[i_mod]!=m_bx[modIndex]){ + std::cout<<"Module "<<i_mod<<" on RCE "<<j_rce<<" has BXID "<<m_bx[i_mod]<<" while module " + <<modIndex<<" has BXID "<<m_bx[modIndex]<<std::endl; + return false; + } + } + } + } + //Make sure that the BXID dfference between this event and the reference event agrees for all RCEs and all modules. + int bxiddiff=0; + for(unsigned int j_rce=0; j_rce<m_nRce; j_rce++){ + int difftdc=(m_tdcbx[j_rce] - ref->m_tdcbx[j_rce])%256; + if(j_rce==0){ //use RCE 0 as the reference for the difference + bxiddiff=difftdc; + }else{ //check the other RCEs + if(difftdc!=bxiddiff){ + std::cout<<"Events between different RCEs are inconsistent."<<std::endl; + return false; + } + } + } + //Check module BXID differences against RCEs + for(unsigned int i=0;i<m_nMod;i++){ + int diffmod=(m_bx[i]-ref->m_bx[i])%256; + if(diffmod!=bxiddiff){ + std::cout<<"Module "<<i<<" has a BXID difference of "<<diffmod<<", the TDC difference is "<<bxiddiff<<std::endl; + return false; + } + } + return true; +} + +void CosmicEvent::writeEvent(bool monitor, eudaq::FileSerializer* efile, std::ofstream* pfile, unsigned &evtno){ + + if(monitor==true){ + unsigned long long firstTimeStamp = m_timestamp[0]; + for(unsigned i_rce=1; i_rce<m_nRce; i_rce++){ + if(m_timestamp[i_rce]<firstTimeStamp){ + firstTimeStamp = m_timestamp[i_rce]; + } + } + + eudaq::DetectorEvent *dev=new eudaq::DetectorEvent(m_runno,evtno,firstTimeStamp); + counted_ptr<eudaq::Event> ev(dev); + m_ctel->SetEventNumber(evtno); + counted_ptr<eudaq::Event> cpc(m_ctel); + dev->AddEvent(cpc); + m_dut->SetEventNumber(evtno); + counted_ptr<eudaq::Event> cpd(m_dut); + dev->AddEvent(cpd); + if(efile!=0)dev->Serialize(*efile); + if(pfile!=0){ + const unsigned char* block0=&m_dut->GetBlock(0)[0]; + size_t lenTdc=m_dut->GetBlock(0).size(); + + unsigned totalsize=8+lenTdc; + + for(unsigned iRce=0; iRce<m_nRce; iRce++){ + size_t lenPix=m_dut->GetBlock(iRce+1).size(); + totalsize += lenPix; + } + + pfile->write((char*)&totalsize, 4); + pfile->write((char*)&evtno, 4); + pfile->write((const char*)block0, lenTdc); + + for(unsigned iRce=0; iRce<m_nRce; iRce++){ + size_t lenPix=m_dut->GetBlock(iRce+1).size(); + const unsigned char* blockRce=&m_dut->GetBlock(iRce+1)[0]; + pfile->write((const char*)blockRce, lenPix); + } + + } + CosmicEventReceiver::receiveEvent(ev); //this function adds event to monitoring GUI + m_ctel=0; + m_dut=0; + evtno++; + }else if (DataSenderIF::hasInstance()) { + // sending event to CosmicGui + // K. Barry + + // Code for when CosmicGui is receiving events via TCP. + // This code assumes that the DUT and CTEL data have + // been kept separate. It amalgamates them into one + // DetectorEvent and sends that. This is to be + // consistent with the way the data is written to file + // in file-ouput mode of running. + + m_ctel->SetEventNumber(evtno); + counted_ptr<eudaq::Event> cpc(m_ctel); + m_dut->SetEventNumber(evtno); + counted_ptr<eudaq::Event> cpd(m_dut); + + // Need to modify this to include the whole event -- DONE already? + // DataSenderIF::SendEvent(m_dut); + + unsigned long long firstTimeStamp = m_timestamp[0]; + for(unsigned i_rce=1; i_rce<m_nRce; i_rce++){ + if(m_timestamp[i_rce]<firstTimeStamp){ + firstTimeStamp = m_timestamp[i_rce]; + } + } + + eudaq::DetectorEvent dev(m_runno, evtno, firstTimeStamp); + dev.AddEvent(cpc); + dev.AddEvent(cpd); + DataSenderIF::SendEvent(&dev); + + m_ctel = 0; + m_dut = 0; + evtno++; + } else { + // send event to eudaq + //std::cout<<"Sending Eudet event."<<std::endl; + int tlu=(m_dut->GetBlock(0)[37]<<8)|m_dut->GetBlock(0)[36]; + //if(!m_synch&&tlu-1!=m_lastTLU)std::cout<<"Bad tlu "<<tlu<<" last "<<m_lastTLU<<std::endl; + if(m_synch&&(tlu-1!=m_lastTLU && (tlu!=0 || m_lastTLU!=32767))){ + if(tlu<m_lastTLU)tlu+=32768; + std::cout<<"Inserting "<<tlu-m_lastTLU<<" events. TLU id="<<tlu<<" old tlu="<<m_lastTLU<<std::endl; + for(int i=m_lastTLU+1;i<tlu;i++){ + CosmicEvent *ev=makeDummyEvent(m_runno, i, evtno++); + ProducerIF::sendEvent(ev->m_dut); + delete ev; + } + m_synch=false; + std::cout<<"Done inserting events."<<std::endl; + } + m_lastTLU=tlu; + m_dut->SetEventNumber(evtno++); + ProducerIF::sendEvent(m_dut); + } + + +} + +CosmicEvent* CosmicEvent::makeDummyEvent(int runno, int tlu, int evtno){ + std::vector<int> bla; + bla.push_back(0); + CosmicEvent* ev=new CosmicEvent(runno,0,0,bla); + unsigned block[8]={0,0,0,0,0,0,0,0}; + unsigned char* bc=(unsigned char*)block; + bc[29]=(tlu&0x7f00)>>8; + bc[28]=tlu&0xff; + ev->setTdcData(0,block, 0); + ev->m_dut->SetEventNumber(evtno); + return ev; +} + + +void CosmicEvent::print(){ + std::cout<<"Event printout"<<std::endl; + std::cout<<"=============="<<std::endl; + std::cout<<"L1A: "<<m_l1a<<std::endl; + std::cout<<"Event with "<<m_nRce<<" RCEs."<<std::endl; + std::cout<<"RCE's: "; + for (unsigned int i=0;i<m_nRce;i++){ + std::cout<<"RCE "<<m_rces[i]<<": Timestamp: "<<std::hex<<m_timestamp[i] + <<std::dec<<" , TDC BX: "<<m_tdcbx[i]<<std::endl; + } + + if(m_nMod>(16*m_nRce))std::cout<<"ERROR: Number of modules is "<<m_nMod<<std::endl; + else{ + for (unsigned int i=0;i<m_nMod;i++){ + std::cout<<"Module "<<i<<" BX: "<<m_bx[i]<<std::endl; + } + std::cout<<std::endl; + } +} + +unsigned CosmicEvent::getFirstModWithRceIndex(unsigned rceIndex){ + + for(unsigned i=0; i<m_nMod; i++){ + + if(m_modRceIndex[i] == rceIndex){ + return i; + } + + } + + //No module found with the given rce index. Return invalid index. + return m_nMod+1; + +} + +CosmicEventReceiver* CosmicEventReceiver::s_receiver=0; diff --git a/rce/rcecalib/dataproc/CosmicEvent.hh b/rce/rcecalib/dataproc/CosmicEvent.hh new file mode 100644 index 00000000..ca7ba9b9 --- /dev/null +++ b/rce/rcecalib/dataproc/CosmicEvent.hh @@ -0,0 +1,58 @@ +#ifndef COSMICEVENT_HH +#define COSMICEVENT_HH + +#include <vector> +#include <stdlib.h> +#include <iostream> +#include <fstream> + +namespace eudaq{ + class DetectorEvent; + class RawDataEvent; + class FileSerializer; +} + +class CosmicEvent{ +public: + CosmicEvent(unsigned runno, unsigned l1a, unsigned nMod, std::vector<int>& rces); + ~CosmicEvent(); + void appendCtelData(unsigned *data, unsigned size); + void appendDutData(unsigned *data, unsigned size, unsigned rceIndex); + void setTdcData(unsigned firstword, unsigned *data, unsigned rceIndex); + void incrementTrigger(unsigned mod, int ntrg, unsigned bxfirst, unsigned bxlast, unsigned rceIndex); + + bool consistent(CosmicEvent* ev); + + unsigned getL1A(){return m_l1a;} + int getNmod(){ return m_nMod;} + unsigned getRunNo(){ return m_runno;} + unsigned getFirstModWithRceIndex(unsigned rceIndex); + + + CosmicEvent* makeDummyEvent(int runno, int tlu, int evtno); + void writeEvent(bool monitor, eudaq::FileSerializer *efile, std::ofstream* pfile, unsigned& evtno); + void print(); + static void synch(bool on){m_synch=on;}; + +private: + + bool m_tdctrig; + std::vector<int> m_ntrig; + std::vector<unsigned> m_bx; + std::vector<unsigned> m_bxlast; + std::vector<unsigned> m_modRceIndex; + eudaq::RawDataEvent* m_ctel; + eudaq::RawDataEvent* m_dut; + unsigned m_l1a; + unsigned m_nMod; + std::vector<unsigned long long> m_timestamp; + std::vector<unsigned> m_tdcbx; + unsigned m_runno; + std::vector<int> m_rces; + unsigned m_nRce; + static int m_lastTLU; + static bool m_synch; + +}; + +#endif diff --git a/rce/rcecalib/dataproc/CosmicEventIterator.cc b/rce/rcecalib/dataproc/CosmicEventIterator.cc new file mode 100644 index 00000000..46a5d97e --- /dev/null +++ b/rce/rcecalib/dataproc/CosmicEventIterator.cc @@ -0,0 +1,177 @@ + +#include "rcecalib/dataproc/CosmicEventIterator.hh" +#include "rcecalib/dataproc/CosmicEvent.hh" +#include <iostream> + +namespace{ + int badEventThreshold = 3; +} + +CosmicEventIterator::CosmicEventIterator(bool monitor, eudaq::FileSerializer* fs, std::ofstream *pfile, unsigned runno, int nMod, std::vector<int> rces) + : m_runNo(runno), m_nMod(nMod), m_rces(rces), m_monitor(monitor), m_file(fs), m_pfile(pfile), + m_99(true), m_101(false), m_badEvents(0), m_nEvents(1){ + for(int i=0;i<m_nMod;i++) { + m_modit.push_back(std::list<CosmicEvent*>::iterator()); + } + + m_nRce = m_rces.size(); + for(int i=0;i<m_nRce;i++) { + m_tdcit.push_back(std::list<CosmicEvent*>::iterator()); + } + + m_refevent=new CosmicEvent(m_runNo,1,m_nMod,m_rces); // 1 is the first L1id + m_events.push_back(m_refevent); + set(m_events.begin()); + CosmicEvent::synch(false); +} + +CosmicEventIterator::~CosmicEventIterator(){ + if((*(m_events.begin()))!=m_refevent)delete m_refevent; + std::list<CosmicEvent*>::iterator it; + for(it=m_events.begin();it!=m_events.end();it++){ + delete (*it); + } +} + +void CosmicEventIterator::resynch(){ + std::cout<<"CosmicEventIterator::resynch()"<<std::endl; + CosmicEvent::synch(true); + if((*(m_events.begin()))!=m_refevent){ + delete m_refevent; + std::cout<<"First event is not refevent"<<std::endl; + } + std::list<CosmicEvent*>::iterator it; + int i=0; + for(it=m_events.begin();it!=m_events.end();it++){ + std::cout<<"Tossing event with L1A id="<<(*it)->getL1A()<<std::endl; + //(*it)->print(); + delete (*it); + i++; + } + std::cout<<"CosmicEventIterator: Tossed "<<i<<" events."<<std::endl; + m_events.clear(); + m_refevent=new CosmicEvent(m_runNo,1,m_nMod,m_rces); // 1 is the first L1id + m_events.push_back(m_refevent); + set(m_events.begin()); +} +inline void CosmicEventIterator::set(std::list<CosmicEvent*>::iterator it){ + for(int i=0;i<m_nRce;i++)m_tdcit[i]=it; + for(int i=0;i<m_nMod;i++)m_modit[i]=it; +} + +bool CosmicEventIterator::setTdcData(unsigned *data, int rceIndex){ + //return false: indicates that resynching is necessary + + unsigned current=data[0]>>16; // l1id + //unsigned bxid=current&0xff; + unsigned l1id=(current>>8)&0xf; + current|=0x200a0000; //link 10 and header word marker + unsigned l1a=(*m_tdcit[rceIndex])->getL1A(); + if(l1a!=l1id){ + std::cout<<"TDC Event missing. Got L1id "<<l1id<<", was expecting "<<l1a<<std::endl; + return false; + } + + (*m_tdcit[rceIndex])->setTdcData(current, &data[0], rceIndex); + bool success=checkForNewEvent(l1id,m_tdcit[rceIndex]); + if(success==false)return false; + m_tdcit[rceIndex]++; + return checkForWrite(); +} + +bool CosmicEventIterator::addPixelData(int mod, unsigned l1id, int bxfirst, int bxlast, int ntrg, int rceIndex, + bool isdut, unsigned* data, unsigned size){ + CosmicEvent *ev=*m_modit[mod]; + unsigned l1a=ev->getL1A(); + if(l1a!=l1id){ + if((l1id==0&&l1a==15) || (l1id==l1a+1)){ + bool success=checkForNewEvent(l1a,m_modit[mod]); + if(success==false){ + std::cout<<"bad check"<<std::endl; + return false; + } + m_modit[mod]++; + ev=*m_modit[mod]; + if(checkForWrite()==false)return false; + }else{ + std::cout<<"Module "<<mod<<" Event missing. Got L1id "<<l1id<<", was expecting "<<l1a<<std::endl; + return false; + } + } + if(ntrg>0)ev->incrementTrigger(mod, ntrg, bxfirst, bxlast, rceIndex); + if(isdut==true)ev->appendDutData(data,size,rceIndex); + else ev->appendCtelData(data,size); + return true; +} +void CosmicEventIterator::flushEvents(){ + int eventswritten=0; + int badevents=0; + while(!m_events.empty()){ + CosmicEvent* ev=m_events.front(); + m_events.pop_front(); + if(ev->consistent(m_refevent)){ + std::cout<<"Flushing event with L1id="<<ev->getL1A()<<std::endl; + ev->writeEvent(m_monitor, m_file, m_pfile, m_nEvents); + eventswritten++; + }else{ + badevents++; + } + if(ev!=m_refevent)delete ev; + } + std::cout<<"Wrote "<<eventswritten<<" events and discarded "<<badevents<<std::endl; +} + +inline bool CosmicEventIterator::checkForWrite(){ + bool retval=true; + while(!m_events.empty() && inUse(m_events.begin())==false){ + CosmicEvent* ev=m_events.front(); + m_events.pop_front(); + if(ev->consistent(m_refevent)){ + //ev->print(); + ev->writeEvent(m_monitor, m_file, m_pfile, m_nEvents); + m_badEvents=0; + }else{ //inconsistent event. + m_badEvents++; + if(m_badEvents>badEventThreshold){ + m_badEvents=0; + retval=false; + ev->print(); + std::cout<<"Bad consistency for more than "<<badEventThreshold<<" events in a row. Resynchronizing"<<std::endl; + } else{ + ev->print(); + std::cout<<"Bad consistency for "<<m_badEvents<<" events in a row. Tossing event."<<std::endl; + } + } + if(ev!=m_refevent)delete ev; + } + return retval; +} + +inline bool CosmicEventIterator::inUse(std::list<CosmicEvent*>::iterator it){ + + for (int i=0;i<m_nRce;i++){ + if(m_tdcit[i]==it){ + return true; + } + } + for (int i=0;i<m_nMod;i++){ + if(m_modit[i]==it){ + return true; + } + } + return false; +} + +inline bool CosmicEventIterator::checkForNewEvent(unsigned l1a, std::list<CosmicEvent*>::iterator it){ + //return false only if we need to create new event AND we don't have room to store it + it++; + if(it==m_events.end()){ // need new event + unsigned nextl1a= l1a==15 ? 0 : l1a+1; + m_events.push_back(new CosmicEvent(m_runNo, nextl1a, m_nMod, m_rces)); + if(m_events.size()==1001){ + std::cout<<"Now exceeding 1000 events in list. Resynching."<<std::endl; + return false; + } + } + return true; +} diff --git a/rce/rcecalib/dataproc/CosmicEventIterator.hh b/rce/rcecalib/dataproc/CosmicEventIterator.hh new file mode 100644 index 00000000..15b6887d --- /dev/null +++ b/rce/rcecalib/dataproc/CosmicEventIterator.hh @@ -0,0 +1,44 @@ +#ifndef COSMICEVENTITERATOR_HH +#define COSMICEVENTITERATOR_HH + +#include <vector> +#include <list> +#include <fstream> + +class CosmicEvent; +namespace eudaq{ + class FileSerializer; +} + +class CosmicEventIterator{ +public: + CosmicEventIterator(bool monitor, eudaq::FileSerializer *fs, std::ofstream *pf, unsigned runno, + int nMod, std::vector<int> rces); + ~CosmicEventIterator(); + void resynch(); + bool setTdcData(unsigned* data, int rceIndex); + bool checkForWrite(); + bool inUse(std::list<CosmicEvent*>::iterator it); + void flushEvents(); + int nEvents(){return m_nEvents;} + inline bool checkForNewEvent(unsigned l1a, std::list<CosmicEvent*>::iterator it); + bool addPixelData(int mod, unsigned l1id, int bxfirst, int bxlast, int ntrg, int rceIndex, + bool isdut, unsigned* data, unsigned size); + CosmicEvent* m_refevent; +private: + void set(std::list<CosmicEvent*>::iterator it); + unsigned m_runNo; + int m_nMod; + std::vector<int> m_rces; + int m_nRce; + std::list<CosmicEvent*> m_events; + std::vector<std::list<CosmicEvent*>::iterator> m_modit; + std::vector<std::list<CosmicEvent*>::iterator> m_tdcit; + bool m_monitor; + eudaq::FileSerializer *m_file; + std::ofstream *m_pfile; + bool m_99, m_101; + int m_badEvents; + unsigned int m_nEvents; +}; +#endif diff --git a/rce/rcecalib/dataproc/CosmicEventReceiver.hh b/rce/rcecalib/dataproc/CosmicEventReceiver.hh new file mode 100644 index 00000000..0020db6b --- /dev/null +++ b/rce/rcecalib/dataproc/CosmicEventReceiver.hh @@ -0,0 +1,17 @@ +#ifndef COSMICEVENTRECEIVER_HH +#define COSMICEVENTRECEIVER_HH + +#include "rcecalib/eudaq/Event.hh" + +class CosmicEventReceiver{ +public: + CosmicEventReceiver(){s_receiver=this;} + virtual ~CosmicEventReceiver(){} + virtual void OnReceive(counted_ptr<eudaq::Event> ev)=0; + static void receiveEvent(counted_ptr<eudaq::Event> ev){ + if(s_receiver!=0)s_receiver->OnReceive(ev); + } + static CosmicEventReceiver* s_receiver; +}; + +#endif diff --git a/rce/rcecalib/dataproc/DataProcFactory.cc b/rce/rcecalib/dataproc/DataProcFactory.cc new file mode 100644 index 00000000..1ac99e7a --- /dev/null +++ b/rce/rcecalib/dataproc/DataProcFactory.cc @@ -0,0 +1,114 @@ +#include "util/DataCond.hh" +#include "dataproc/DataProcFactory.hh" +#include "dataproc/OccupancyDataProc.hh" +#include "dataproc/RawFei4OccupancyDataProc.hh" +#include "dataproc/NoiseOccupancyDataProc.hh" +#include "dataproc/TotDataProc.hh" +#include "dataproc/TotCalibDataProc.hh" +#include "dataproc/BcidDataProc.hh" +#include "dataproc/SelftriggerDataProc.hh" +#include "dataproc/MultiTrigOccupancyDataProc.hh" +#include "dataproc/MultiTrigNoiseDataProc.hh" +#include "dataproc/MeasurementDataProc.hh" +#include "dataproc/HitorDataProc.hh" +#include "dataproc/CosmicDataProc.hh" +#include "dataproc/DelayScanDataProc.hh" +#include "dataproc/DelayScanDataHandler.hh" +#include "dataproc/CosmicDataHandler.hh" +#include "dataproc/SimpleDataHandler.hh" +#include "dataproc/RegularScanDataHandler.hh" +#include "dataproc/RegularScanRawDataHandler.hh" +#include "dataproc/ModuleCrosstalkRawDataHandler.hh" +#include "dataproc/SimpleReceiver.hh" +#include "dataproc/MeasurementReceiver.hh" +#include "dataproc/PgpReceiver.hh" +#include "dataproc/PgpCosmicReceiver.hh" +#include "dataproc/PgpCosmicNwReceiver.hh" +#include "dataproc/TemperatureDataProc.hh" +#include "dataproc/MonleakDataProc.hh" +#include "dataproc/SNDataProc.hh" +#include "dataproc/Fei4RegisterTestDataProc.hh" + +#ifdef __rtems__ +#include <boost/property_tree/ptree.hpp> +#endif +#include <iostream> + + +AbsDataProc* DataProcFactory::createDataProcessor(const char* type, ConfigIF* cif, + boost::property_tree::ptree* scanOptions){ + if(std::string(type)=="OCCUPANCY") + return new OccupancyDataProc(cif, scanOptions); + if(std::string(type)=="RawFei4Occupancy") + return new RawFei4OccupancyDataProc(cif, scanOptions); + if(std::string(type)=="Noisescan") + return new NoiseOccupancyDataProc(cif, scanOptions); + if(std::string(type)=="TOT") + return new TotDataProc(cif, scanOptions); + if(std::string(type)=="TOTCALIB") + return new TotCalibDataProc(cif, scanOptions); + if(std::string(type)=="BCID") + return new BcidDataProc(cif, scanOptions); + if(std::string(type)=="Delay") + return new DelayScanDataProc(cif, scanOptions); + if(std::string(type)=="CosmicData") + return new CosmicDataProc(cif, scanOptions); + if(std::string(type)=="Measurement") + return new MeasurementDataProc(cif, scanOptions); + if(std::string(type)=="Selftrigger") + return new SelftriggerDataProc(cif, scanOptions); + if(std::string(type)=="MultiTrigOccupancy") + return new MultiTrigOccupancyDataProc(cif, scanOptions); + if(std::string(type)=="MultiTrigNoise") + return new MultiTrigNoiseDataProc(cif, scanOptions); + if(std::string(type)=="Hitor") + return new HitorDataProc(cif, scanOptions); + if(std::string(type)=="Temperature") + return new TemperatureDataProc(cif, scanOptions); + if(std::string(type)=="Monleak") + return new MonleakDataProc(cif, scanOptions); + if(std::string(type)=="SerialNumber") + return new SNDataProc(cif, scanOptions); + if(std::string(type)=="Fei4RegisterTest") + return new Fei4RegisterTestDataProc(cif, scanOptions); + else + return 0; +} + + +AbsDataHandler* DataProcFactory::createDataHandler(const char* type, AbsDataProc *dataproc, DataCond& datacond, + ConfigIF* cif, boost::property_tree::ptree* scanOptions){ + if(std::string(type)=="RegularScan") + return new RegularScanDataHandler(dataproc, datacond, cif, scanOptions); + else if(std::string(type)=="RegularScanRaw") + return new RegularScanRawDataHandler(dataproc, datacond, cif, scanOptions); + else if(std::string(type)=="ModuleCrosstalkRaw") + return new ModuleCrosstalkRawDataHandler(dataproc, datacond, cif, scanOptions); + else if(std::string(type)=="Simple") + return new SimpleDataHandler(dataproc, datacond); + else if(std::string(type)=="DelayScan") + return new DelayScanDataHandler(dataproc, datacond); + else if(std::string(type)=="CosmicData") + return new CosmicDataHandler(dataproc, datacond, cif, scanOptions); + else + return 0; +} + +AbsReceiver* DataProcFactory::createReceiver(const char* type, AbsDataHandler* handler, boost::property_tree::ptree* scanOptions) { + std::cout<<"Creating receiver of type "<<type<<std::endl; + if(std::string(type)=="Simple") + return new SimpleReceiver(handler); +#ifdef __rtems__ + else if(std::string(type)=="Pgp") + return new PgpReceiver(handler); + else if(std::string(type)=="PgpCosmic") + return new PgpCosmicReceiver(handler); + else if(std::string(type)=="PgpCosmicNw") + return new PgpCosmicNwReceiver(handler, scanOptions); + else if(std::string(type)=="Measurement") + return new MeasurementReceiver(handler, scanOptions); +#endif + else + return 0; +} + diff --git a/rce/rcecalib/dataproc/DataProcFactory.hh b/rce/rcecalib/dataproc/DataProcFactory.hh new file mode 100644 index 00000000..c98f7e96 --- /dev/null +++ b/rce/rcecalib/dataproc/DataProcFactory.hh @@ -0,0 +1,24 @@ +#ifndef DATAPROCFACTORY_HH +#define DATAPROCFACTORY_HH + +#include "rcecalib/dataproc/AbsDataProc.hh" +#include "rcecalib/dataproc/AbsReceiver.hh" +#include "rcecalib/dataproc/AbsDataHandler.hh" +#include "rcecalib/config/ConfigIF.hh" +#include <boost/property_tree/ptree_fwd.hpp> + +class DataCond; + +class DataProcFactory{ +public: + DataProcFactory(){}; + AbsDataProc* createDataProcessor(const char* type, ConfigIF* cif, boost::property_tree::ptree* scanOptions); + AbsDataHandler* createDataHandler(const char* type, AbsDataProc *dataproc, DataCond& datacond, + ConfigIF* cif, boost::property_tree::ptree* scanOptions); + AbsReceiver *createReceiver(const char* type, AbsDataHandler* handler, boost::property_tree::ptree* scanOptions); + + +}; + + +#endif diff --git a/rce/rcecalib/dataproc/DelayScanDataHandler.cc b/rce/rcecalib/dataproc/DelayScanDataHandler.cc new file mode 100644 index 00000000..037938f5 --- /dev/null +++ b/rce/rcecalib/dataproc/DelayScanDataHandler.cc @@ -0,0 +1,15 @@ +#include "rcecalib/dataproc/DelayScanDataHandler.hh" +#include "rcecalib/dataproc/AbsDataProc.hh" +#include "rcecalib/config/ConfigIF.hh" +#include "rcecalib/util/DataCond.hh" +#include <boost/property_tree/ptree.hpp> +#include <iostream> + +DelayScanDataHandler::DelayScanDataHandler(AbsDataProc* dataproc, DataCond& datacond) + :AbsDataHandler(dataproc, datacond, 0 ){} + + +void DelayScanDataHandler::handle(unsigned link, unsigned *data, int size){ + assert(link==10); + m_dataProc->processData(link, data, size); +} diff --git a/rce/rcecalib/dataproc/DelayScanDataHandler.hh b/rce/rcecalib/dataproc/DelayScanDataHandler.hh new file mode 100644 index 00000000..3e679086 --- /dev/null +++ b/rce/rcecalib/dataproc/DelayScanDataHandler.hh @@ -0,0 +1,19 @@ +#ifndef DELAYSCANDATAHANDLER_HH +#define DELAYSCANDATAHANDLER_HH + +#include <vector> +#include <map> +#include <assert.h> + +#include "rcecalib/dataproc/AbsDataHandler.hh" +#include <boost/property_tree/ptree_fwd.hpp> +class DataCond; + + +class DelayScanDataHandler: public AbsDataHandler{ +public: + DelayScanDataHandler(AbsDataProc* dataproc, DataCond& datacond); + virtual ~DelayScanDataHandler(){} + void handle(unsigned link, unsigned* data, int size); +}; +#endif diff --git a/rce/rcecalib/dataproc/DelayScanDataProc.cc b/rce/rcecalib/dataproc/DelayScanDataProc.cc new file mode 100644 index 00000000..d0fe654e --- /dev/null +++ b/rce/rcecalib/dataproc/DelayScanDataProc.cc @@ -0,0 +1,43 @@ +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/dataproc/DelayScanDataProc.hh" +#include "rcecalib/config/ConfigIF.hh" +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/dataproc/DataProcFactory.hh" +#include <assert.h> +#include <stdio.h> + + +int DelayScanDataProc::processData(unsigned link, unsigned *data, int size){ + printf("Coincidence\n"); + m_histo[0][0]->increment(m_currentBin); + return 0; +} + +DelayScanDataProc::DelayScanDataProc(ConfigIF* cif, boost::property_tree::ptree* scanOptions) + :AbsDataProc(cif) { + try{ //catch bad scan option parameters + int nLoops = scanOptions->get<int>("nLoops"); + assert (nLoops>0); + int nPoints=1; + nPoints=scanOptions->get<int>("scanLoop_0.nPoints"); + assert(nPoints>1); + int p0=scanOptions->get<int>("scanLoop_0.dataPoints.P_0"); + char pointname[10]; + sprintf(pointname,"P_%d",nPoints-1); + int pn=scanOptions->get<int>(std::string("scanLoop_0.dataPoints.")+pointname); + std::vector<RceHisto1d<short, short>*> vh; + std::cout<<"DelayScanDataProc"<<std::endl; + m_histo.push_back(vh); + int overlap = (pn-p0)/(nPoints-1)/2; + m_histo[0].push_back(new RceHisto1d<short, short>("delhisto","DISC 1 - DISC 0",nPoints, p0-overlap, pn+overlap)); + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + ERS_ASSERT(0); + } +} + +DelayScanDataProc::~DelayScanDataProc(){ + delete m_histo[0][0]; +} diff --git a/rce/rcecalib/dataproc/DelayScanDataProc.hh b/rce/rcecalib/dataproc/DelayScanDataProc.hh new file mode 100644 index 00000000..14819f31 --- /dev/null +++ b/rce/rcecalib/dataproc/DelayScanDataProc.hh @@ -0,0 +1,19 @@ +#ifndef DELAYSCANDATAPROC_HH +#define DELAYSCANDATAPROC_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/dataproc/AbsDataProc.hh" +#include <vector> +#include "rcecalib/util/RceHisto1d.cc" + +class DelayScanDataProc: public AbsDataProc{ +public: + DelayScanDataProc(ConfigIF* cif,boost::property_tree::ptree* scanOptions ); + virtual ~DelayScanDataProc(); + int processData(unsigned link, unsigned *data, int size); +private: + std::vector<std::vector<RceHisto1d<short, short>*> > m_histo; + +}; + +#endif diff --git a/rce/rcecalib/dataproc/Fei4RegisterTestDataProc.cc b/rce/rcecalib/dataproc/Fei4RegisterTestDataProc.cc new file mode 100644 index 00000000..bbfe5f89 --- /dev/null +++ b/rce/rcecalib/dataproc/Fei4RegisterTestDataProc.cc @@ -0,0 +1,145 @@ +#include <stdio.h> +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/dataproc/Fei4RegisterTestDataProc.hh" +#include "rcecalib/config/ConfigIF.hh" +#include "rcecalib/config/FormattedRecord.hh" +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/profiler/Profiler.hh" +#include "rcecalib/config/FEI4/FEI4ARecord.hh" + +int Fei4RegisterTestDataProc::fit(std::string fitfun) { + return 0; +} + +int Fei4RegisterTestDataProc::processData(unsigned link, unsigned *buffer, int buflen){ + //m_timer.Start(); + if(buflen==0)return 0; + int nL1A=0; + int module=m_linkToIndex[link]; + unsigned char* bytepointer=(unsigned char*)buffer; + unsigned char* last=bytepointer+buflen*sizeof(unsigned)-3; + FEI4::FEI4ARecord rec; + int address=-1; + int row=0, col=0; + while(bytepointer<=last){ + rec.setRecord(bytepointer); + if(rec.isEmptyRecord()){ //includes empty record type + // do nothing + }else if(rec.isData()){ //includes empty record type + std::cout<<"Data"<<std::endl; + } else if(rec.isDataHeader()){ + //nL1A++; + std::cout<<"Data Header"<<std::endl; + }else if(rec.isServiceRecord()){ + //unsigned int moduleId=m_info[module].getId(); + //if(rec.getErrorCode()!=10 && (rec.getErrorCode()!=16 || (rec.getErrorCount()&0x200)) ) + // printf("Service record FE %d . Error code: %d. Count: %d \n", moduleId, rec.getErrorCode(), rec.getErrorCount()); + //if( rec.getErrorCode()<32)m_errhist[module]->fill(rec.getErrorCode(), rec.getErrorCount()); + //header=false; + }else if(rec.isValueRecord()){ //val rec without addr rec + nL1A++; + //printf("Value record: %04x.\n",rec.getValue()); + if(address==-1)std::cout<<"Address record missing"<<std::endl; + if(m_currentMaskStage<2){ //Pixel register + if(address==15)m_counter[module]++; //new bit or dcol + int dcol=m_counter[module]/13; + int bit=m_counter[module]%13; + for (int i=0;i<16;i++){ + if(address>335){ + row=address-i-336; + col=dcol*2; + }else{ + row=335-address+i; + col=dcol*2+1; + } + int oldval=(*m_pix[module])(row, col); + oldval&=0x1fff; // clear initial setting to show that the value was read + int val=rec.getValue()&(1<<i); + bool bad=false; + if(m_currentMaskStage==(row%2)){ + if(!val)bad=true; + }else{ + if(val)bad=true; + } + if(bad){ + oldval|=1<<bit; + } + m_pix[module]->set(row,col, oldval); + } + }else{ //global register + if(address>=0&&address<=35){ + m_glob[module]->set(address, rec.getValue()); + } + } + }else if(rec.isAddressRecord()){ // address record + //std::cout<<"FE "<<m_info[module].getId()<<": Address record for "; + //if(rec.isGlobal())std::cout<<" global register "; + //else std::cout<<" shift register "; + //std::cout<<rec.getAddress()<<std::endl; + address=rec.getAddress(); + }else{ + std::cout<<"FE "<<m_info[module].getId()<<": Unexpected record type: "<<std::hex<<rec.getUnsigned()<<std::dec<<std::endl; + //return FEI4::FEI4ARecord::BadRecord; + return 0; + } + bytepointer+=3; + } + //m_timer.Stop(); + return nL1A; +} + +Fei4RegisterTestDataProc::Fei4RegisterTestDataProc(ConfigIF* cif, boost::property_tree::ptree* scanOptions) + :AbsDataProc(cif) { + std::cout<<"Register Test Data Proc"<<std::endl; + m_counter.clear(); + try{ //catch bad scan option parameters + for (unsigned int module=0;module<m_configIF->getNmodules();module++){ + char name[128]; + char title[128]; + RceHisto2d<int, int> *histo; + RceHisto1d<int, int> *histo1d; + unsigned int cols=m_info[module].getNColumns()*m_info[module].getNFrontends(); + unsigned int rows=m_info[module].getNRows(); + unsigned int moduleId=m_info[module].getId(); + std::string moduleName=m_info[module].getName(); + sprintf(title,"Pixel Register Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_Pixel_Reg", moduleId); + histo=new RceHisto2d<int, int>(name,title,rows,0,rows,cols,0,cols, true); + histo->setAxisTitle(1,"Column"); + histo->setAxisTitle(0, "Row"); + //initialize to non-zero value + for(unsigned int i=0;i<rows;i++){ + for(unsigned int j=0;j<cols;j++){ + histo->set(i, j, 1<<13); + } + } + m_pix.push_back(histo); + m_counter.push_back(-1); + sprintf(title,"Global Register Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_Global_Reg", moduleId); + histo1d=new RceHisto1d<int, int>(name,title,36, -0.5, 35.5); + histo1d->setAxisTitle(0, "Register"); + m_glob.push_back(histo1d); + } + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + ERS_ASSERT(0); + } + //m_timer.Reset(); +} + +Fei4RegisterTestDataProc::~Fei4RegisterTestDataProc(){ + for (size_t module=0;module<m_pix.size();module++){ + delete m_pix[module]; + delete m_glob[module]; + } +} + +int Fei4RegisterTestDataProc::setMaskStage(int stage){ + m_currentMaskStage=stage; + for(unsigned i=0;i<m_counter.size();i++)m_counter[i]=-1; + return 0; +} + diff --git a/rce/rcecalib/dataproc/Fei4RegisterTestDataProc.hh b/rce/rcecalib/dataproc/Fei4RegisterTestDataProc.hh new file mode 100644 index 00000000..e3e1f8c9 --- /dev/null +++ b/rce/rcecalib/dataproc/Fei4RegisterTestDataProc.hh @@ -0,0 +1,26 @@ +#ifndef FEI4REGISTERTESTDATAPROC_HH +#define FEI4REGISTERTESTDATAPROC_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/dataproc/AbsDataProc.hh" +#include <vector> +#include "rcecalib/util/RceHisto2d.cc" +#include "rcecalib/util/RceHisto1d.cc" +#include "rcecalib/profiler/Profiler.hh" + +class Fei4RegisterTestDataProc: public AbsDataProc{ +public: + Fei4RegisterTestDataProc(ConfigIF* cif,boost::property_tree::ptree* scanOptions ); + virtual ~Fei4RegisterTestDataProc(); + int processData(unsigned link, unsigned *data, int size); + int fit(std::string fitfun); + int setMaskStage(int stage); + +protected: + enum FEI4{N_ROW=336, N_COL=80}; + std::vector<RceHisto2d<int, int>*> m_pix; + std::vector<RceHisto1d<int, int>*>m_glob; + std::vector<int> m_counter; +}; + +#endif diff --git a/rce/rcecalib/dataproc/HitorDataProc.cc b/rce/rcecalib/dataproc/HitorDataProc.cc new file mode 100644 index 00000000..01976845 --- /dev/null +++ b/rce/rcecalib/dataproc/HitorDataProc.cc @@ -0,0 +1,56 @@ +#include <stdio.h> +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/dataproc/HitorDataProc.hh" +#include "rcecalib/config/ConfigIF.hh" +#include "rcecalib/config/FormattedRecord.hh" +#include "rcecalib/util/exceptions.hh" + + +int HitorDataProc::processData(unsigned link, unsigned *data, int size){ + // std::cout<<"Process data"<<std::endl; + int module=m_linkToIndex[link]; + int col=m_currentMaskStage/m_info[module].getNRows(); + int row=m_currentMaskStage%m_info[module].getNRows(); + m_histo_occ[module][0]->increment(col,row); + return 0; +} + +HitorDataProc::HitorDataProc(ConfigIF* cif, boost::property_tree::ptree* scanOptions) + :AbsDataProc(cif){ + std::cout<<"Hitor Data Proc"<<std::endl; + try{ //catch bad scan option parameters + + for (unsigned int module=0;module<m_configIF->getNmodules();module++){ + std::vector<RceHisto2d<short, short>* > vh; + m_histo_occ.push_back(vh); + char name[128]; + char title[128]; + RceHisto2d<short, short> *histo; + unsigned int cols=m_info[module].getNColumns()*m_info[module].getNFrontends(); + unsigned int rows=m_info[module].getNRows(); + unsigned int moduleId=m_info[module].getId(); + std::string moduleName=m_info[module].getName(); + std::cout<<"Creating Hitor histograms."<<std::endl; + sprintf(title,"OCCUPANCY Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_Hitor", moduleId); + histo=new RceHisto2d<short, short>(name,title,cols,0,cols,rows,0,rows); + if(m_info[module].getNFrontends()==1)histo->setAxisTitle(0,"Column"); + else histo->setAxisTitle(0,"FE*N_COL+Column"); + histo->setAxisTitle(1, "Row"); + m_histo_occ[module].push_back(histo); + } + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + ERS_ASSERT(0); + } +} + +HitorDataProc::~HitorDataProc(){ + for (size_t module=0;module<m_histo_occ.size();module++) + for(size_t i=0;i<m_histo_occ[module].size();i++)delete m_histo_occ[module][i]; + +} + + diff --git a/rce/rcecalib/dataproc/HitorDataProc.hh b/rce/rcecalib/dataproc/HitorDataProc.hh new file mode 100644 index 00000000..6e261f54 --- /dev/null +++ b/rce/rcecalib/dataproc/HitorDataProc.hh @@ -0,0 +1,21 @@ +#ifndef HITORDATAPROC_HH +#define HITORDATAPROC_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/dataproc/AbsDataProc.hh" +#include "rcecalib/dataproc/fit/AbsFit.hh" +#include <vector> +#include "rcecalib/util/RceHisto2d.cc" + +class HitorDataProc: public AbsDataProc{ +public: + HitorDataProc(ConfigIF* cif,boost::property_tree::ptree* scanOptions ); + virtual ~HitorDataProc(); + int processData(unsigned link, unsigned *data, int size); + +protected: + + std::vector<std::vector<RceHisto2d<short, short>*> > m_histo_occ; +}; + +#endif diff --git a/rce/rcecalib/dataproc/Makefile b/rce/rcecalib/dataproc/Makefile new file mode 100644 index 00000000..c73fd5ec --- /dev/null +++ b/rce/rcecalib/dataproc/Makefile @@ -0,0 +1,20 @@ +# Package level makefile +# ---------------------- +%.mk:; + +# Checks +# ------ +# Check release location variables +ifeq ($(RELEASE_DIR),) +export RELEASE_DIR := $(PWD)/../.. +endif + +include $(RELEASE_DIR)/make/share/setup.mk +include ../flags.mk + +ifndef PREMAKE_DONE +include $(RELEASE_DIR)/make/share/premake.mk +else +include constituents.mk +include $(RELEASE_DIR)/make/sw/package.mk +endif diff --git a/rce/rcecalib/dataproc/MeasurementDataProc.cc b/rce/rcecalib/dataproc/MeasurementDataProc.cc new file mode 100644 index 00000000..beda83dd --- /dev/null +++ b/rce/rcecalib/dataproc/MeasurementDataProc.cc @@ -0,0 +1,74 @@ +#include <stdio.h> +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/dataproc/MeasurementDataProc.hh" +#include "rcecalib/config/ConfigIF.hh" +#include "rcecalib/util/exceptions.hh" +#include "math.h" + +int MeasurementDataProc::fit(std::string fitfun) { + std::cout << "Running: " << fitfun << std::endl; + if(fitfun=="NORMALIZE" && m_nTrigger>0) { + float n=(float)m_nTrigger; + for(int j=0;j<m_nPoints;j++){ + float mean=(*m_histo)(j)/n; + m_histo->set(j, mean); + float err=(m_err[j]/n-mean*mean)/n; + if(err<0)err=0; //prevent rounding errors + m_histo->setBinError(j, err); + // std::cout<<"Bin content is "<<(*m_histo[module][i])(j)<<std::endl; + //std::cout<<"Bin error is "<<m_histo[module][i]->getBinError(j)<<std::endl; + } + } + return 0; +} + +int MeasurementDataProc::processData(unsigned link, unsigned *data, int size){ + // std::cout<<"Process data"<<std::endl; + float val=*((float*)data); + //std::cout<<"Measured value "<<val<<std::endl; + m_histo->fill(m_currentBin, val); + m_err[m_currentBin]+= val*val; + return 0; +} + +MeasurementDataProc::MeasurementDataProc(ConfigIF* cif, boost::property_tree::ptree* scanOptions) + :AbsDataProc(cif){ + try{ //catch bad scan option parameters + m_nLoops = scanOptions->get<int>("nLoops"); + /* there is at least one parameter loop */ + /* TODO: fix in scan control */ + m_nPoints=1; + if(m_nLoops>0){ + m_nPoints=scanOptions->get<int>("scanLoop_0.nPoints"); + for(int i=0;i<m_nPoints;i++) { + char pointname[10]; + sprintf(pointname,"P_%d",i); + int vcal=scanOptions->get<int>(std::string("scanLoop_0.dataPoints.")+pointname); + //std::cout << "point vcal " << vcal << std::endl; + m_vcal.push_back(vcal); + } + } + m_nTrigger=scanOptions->get<int>("trigOpt.nEvents"); + + double width=1; + if(m_nPoints>1)width=double(m_vcal[m_nPoints-1]-m_vcal[0])/(double)(m_nPoints-1)*0.5; + m_histo=new RceHisto1d<float, float>("Measurement","Measurement",m_nPoints,m_vcal[0]-width,m_vcal[m_nPoints-1]+width); + m_histo->setAxisTitle(0,"DAC"); + + //error array + m_err=new float[m_nPoints]; + for(int i=0;i<m_nPoints;i++)m_err[i]=0; + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + ERS_ASSERT(0); + } +} + +MeasurementDataProc::~MeasurementDataProc(){ + delete m_histo; + delete [] m_err; +} + + diff --git a/rce/rcecalib/dataproc/MeasurementDataProc.hh b/rce/rcecalib/dataproc/MeasurementDataProc.hh new file mode 100644 index 00000000..40474687 --- /dev/null +++ b/rce/rcecalib/dataproc/MeasurementDataProc.hh @@ -0,0 +1,28 @@ +#ifndef MEASUREMENTDATAPROC_HH +#define MEASUREMENTDATAPROC_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/dataproc/AbsDataProc.hh" +#include "rcecalib/dataproc/fit/AbsFit.hh" +#include <vector> +#include "rcecalib/util/RceHisto1d.cc" + +class MeasurementDataProc: public AbsDataProc{ +public: + MeasurementDataProc(ConfigIF* cif,boost::property_tree::ptree* scanOptions ); + virtual ~MeasurementDataProc(); + int processData(unsigned link, unsigned *data, int size); + int fit(std::string fitfun); + +protected: + + RceHisto1d<float, float>* m_histo; + std::vector<int> m_vcal; + float *m_err; + int m_nTrigger; + int m_nLoops; + int m_nPoints; + int m_nMaskStages; +}; + +#endif diff --git a/rce/rcecalib/dataproc/MeasurementReceiver.cc b/rce/rcecalib/dataproc/MeasurementReceiver.cc new file mode 100644 index 00000000..8669a552 --- /dev/null +++ b/rce/rcecalib/dataproc/MeasurementReceiver.cc @@ -0,0 +1,101 @@ +#ifdef RCE_V2 +#include "datCode.hh" +#include DAT_PUBLIC( oldPpi, net, Error.hh) +#include DAT_PUBLIC( oldPpi, net, SocketTcp.hh) +#ifndef __rtems__ +#include DAT_PUBLIC( oldPpi, net, GetAddr.hh) +#endif +#else +#include "rce/net/Error.hh" +#include "rce/net/Getaddr.hh" +#include "rce/net/SocketTcp.hh" +#endif +#include "namespace_aliases.hh" +#include <stdio.h> +#include <stdlib.h> +#include <iostream> +#include <string.h> +#include "rcecalib/HW/RCDImaster.hh" +#include <boost/regex.hpp> +#include <boost/property_tree/ptree.hpp> + +#include <arpa/inet.h> // for htonl + +#include "rcecalib/dataproc/MeasurementReceiver.hh" + + +MeasurementReceiver::MeasurementReceiver(AbsDataHandler* handler, boost::property_tree::ptree* scanOptions): + PgpReceiver(handler), TriggerReceiverIF(){ + PgpTrans::RCDImaster::instance()->setReceiver(this); + + //the name is "ipAddr:port" + std::string name=scanOptions->get<std::string>("Name"); + boost::cmatch matches; + boost::regex re("(^.*):(\\d+)"); + std::string ipaddr, port; + if(boost::regex_search(name.c_str(), matches, re)){ + assert(matches.size()>2); + ipaddr=std::string(matches[1].first, matches[1].second); + port=std::string(matches[2].first, matches[2].second); + }else{ + std::cout<<"No ip addr:port given"<<std::endl; + assert(0); + } +#ifdef __rtems__ + // construct address from string with dots + boost::regex re2("(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)"); + unsigned address; + if(boost::regex_search(ipaddr.c_str(), matches, re2)){ + assert(matches.size()>4); + address=atoi(std::string(matches[1].first, matches[1].second).c_str())<<24; + address|=atoi(std::string(matches[2].first, matches[2].second).c_str())<<16; + address|=atoi(std::string(matches[3].first, matches[3].second).c_str())<<8; + address|=atoi(std::string(matches[4].first, matches[4].second).c_str()); + }else{ + std::cout<<"bad ip address given"<<std::endl; + assert(0); + } +#else + unsigned address = RceNet::getaddr(ipaddr.c_str()); +#endif + std::cout<<"Ip address is "<<std::hex<<address<<std::dec<<std::endl; + int porti=atoi(port.c_str()); + m_addr=RceNet::IpAddress(address, porti); + m_ipname=ipaddr; + + std::cout<<"Created Measurement receiver"<<std::endl; + +} + + +void MeasurementReceiver::Receive(unsigned *data, int size){ + std::string vals=sendCommand("measure", m_addr, m_ipname.c_str()); + float val; + char* end; + val=strtof(vals.c_str(), &end); + if(end-vals.c_str()!=(int)vals.size()){ + std::cout<<"Bad value "<<vals<<std::endl; + assert(0); + } + m_handler->handle(0, (unsigned*)&val, 1); + return; +} +const char* MeasurementReceiver::sendCommand(std::string inpline, RceNet::IpAddress dst, const char* rce){ + RceNet::SocketTcp socket; + socket.connect(dst); + socket.send(inpline.c_str(), inpline.size()); + int timeout= 10000; + static char line[128]; + try{ + socket.setrcvtmo(timeout); + int bytes=socket.recv(line,128); + line[bytes]=0; + } + catch (...){ + std::cout<<"Network error. Exiting."<<std::endl; + assert(0); + } + socket.close(); + return line; +} + diff --git a/rce/rcecalib/dataproc/MeasurementReceiver.hh b/rce/rcecalib/dataproc/MeasurementReceiver.hh new file mode 100644 index 00000000..d3933043 --- /dev/null +++ b/rce/rcecalib/dataproc/MeasurementReceiver.hh @@ -0,0 +1,24 @@ +#ifndef MEASUREMENTRECEIVER_HH +#define MEASUREMENTRECEIVER_HH + +#include "rcecalib/dataproc/PgpReceiver.hh" +#include "rcecalib/config/TriggerReceiverIF.hh" +#ifdef RCE_V2 +#include "datCode.hh" +#include DAT_PUBLIC( oldPpi, net, IpAddress.hh) +#else +#include "rce/net/IpAddress.hh" +#endif +#include <boost/property_tree/ptree_fwd.hpp> +#include "namespace_aliases.hh" +class MeasurementReceiver: public PgpReceiver, public TriggerReceiverIF{ +public: + MeasurementReceiver(AbsDataHandler* handler, boost::property_tree::ptree* scanOptions); + void Receive(unsigned *data, int size); + void receive(PgpTrans::PgpData* pgpdata){}; //pgp dummy + const char* sendCommand(std::string inpline, RceNet::IpAddress address, const char* rce); +private: + RceNet::IpAddress m_addr; + std::string m_ipname; +}; +#endif diff --git a/rce/rcecalib/dataproc/ModuleCrosstalkRawDataHandler.cc b/rce/rcecalib/dataproc/ModuleCrosstalkRawDataHandler.cc new file mode 100644 index 00000000..e720d4a3 --- /dev/null +++ b/rce/rcecalib/dataproc/ModuleCrosstalkRawDataHandler.cc @@ -0,0 +1,85 @@ +#include "rcecalib/dataproc/ModuleCrosstalkRawDataHandler.hh" +#include "rcecalib/dataproc/AbsDataProc.hh" +#include "rcecalib/config/AbsFormatter.hh" +#include "rcecalib/config/ConfigIF.hh" +#include <boost/property_tree/ptree.hpp> +#include <iostream> +#include "rcecalib/profiler/Profiler.hh" +#include "rcecalib/util/DataCond.hh" + +ModuleCrosstalkRawDataHandler::ModuleCrosstalkRawDataHandler(AbsDataProc* dataproc, + DataCond& datacond, + ConfigIF* cif, + boost::property_tree::ptree* scanOptions) + :AbsDataHandler(dataproc, datacond, cif){ + std::cout<<"Regular raw data handler"<<std::endl; + m_nL1AperEv=scanOptions->get<int>("trigOpt.nL1AperEvent"); + int ntrigpergroup=scanOptions->get<int>("trigOpt.nTriggersPerGroup"); + if(ntrigpergroup!=0)m_nL1AperEv*=ntrigpergroup; + std::cout<<"Number of expected triggers is "<<m_nL1AperEv<<std::endl; + int maxlink=0; + m_nModules=m_configIF->getNmodules(); + m_L1Acounters=new int[m_nModules]; + m_outlinkMask=new int[m_nModules]; + m_moduleTrgMask=scanOptions->get<int>("trigOpt.moduleTrgMask"); + resetL1counters(); + for (int i=0;i<m_nModules;i++){ + m_outlinkMask[i]=1<<m_configIF->getModuleInfo(i).getOutLink(); + if(m_configIF->getModuleInfo(i).getOutLink()>maxlink)maxlink=m_configIF->getModuleInfo(i).getOutLink(); + } + maxlink++; + m_linkToIndex=new int[maxlink]; + for (unsigned int i=0;i<m_configIF->getNmodules();i++){ + m_linkToIndex[m_configIF->getModuleInfo(i).getOutLink()]=i; + } + //m_timer.Reset(); + m_counter=0; +} + +ModuleCrosstalkRawDataHandler::~ModuleCrosstalkRawDataHandler(){ + delete [] m_L1Acounters; + delete [] m_outlinkMask; + delete [] m_linkToIndex; + // m_timer.Print("ModuleCrosstalkRawDataHandler"); +} + +void ModuleCrosstalkRawDataHandler::timeoutOccurred(){ + resetL1counters(); +} + +void ModuleCrosstalkRawDataHandler::resetL1counters(){ + for (int i=0;i<m_nModules;i++){ + m_L1Acounters[i]=0; + } +} + +void ModuleCrosstalkRawDataHandler::handle(unsigned link, unsigned *data, int size){ + // nL1A contains the number of L1A in the data chunk + //std::cout<<"Data from Link "<<link<<std::endl; + //m_timer.Start(); + int nL1A= m_dataProc->processData(link, data, size); + //m_timer.Stop(); + //std::cout<<nL1A<<" events."<<std::endl; + // std::cout<<"Expecting "<<m_nL1AperEv<<std::endl; + //for (int i=size-4;i<size;i++)std::cout<<std::hex<<data[i]<<std::endl; + m_L1Acounters[m_linkToIndex[link]]+=nL1A; + // std::cout<<m_L1Acounters[m_linkToIndex[link]]<<" events so far."<<std::endl; + bool done=true; + //check if the event is complete. + for (int i=0;i<m_nModules;i++){ + //if(m_L1Acounters[i]>m_nL1AperEv)std::cout<<m_L1Acounters[i]<<" L1Atriggers"<<std::endl; + if(m_outlinkMask[i]&m_moduleTrgMask)continue; + if (m_L1Acounters[i]<m_nL1AperEv){ + done=false; + break; + } + } + if(done){ + //std::cout<<"Restarting scan "<<std::endl; + resetL1counters(); + // Next trigger + omni_mutex_lock pl( m_dataCond.mutex ); + if(m_dataCond.waitingForData==true)m_dataCond.cond.signal(); + else std::cout<<"Scan was not waiting for data!"<<std::endl; + } +} diff --git a/rce/rcecalib/dataproc/ModuleCrosstalkRawDataHandler.hh b/rce/rcecalib/dataproc/ModuleCrosstalkRawDataHandler.hh new file mode 100644 index 00000000..83a22cc9 --- /dev/null +++ b/rce/rcecalib/dataproc/ModuleCrosstalkRawDataHandler.hh @@ -0,0 +1,31 @@ +#ifndef MODULECROSSTALKRAWDATAHANDLER_HH +#define MODULECROSSTALKRAWDATAHANDLER_HH + +#include <omnithread.h> +#include <assert.h> + +#include "rcecalib/dataproc/AbsDataHandler.hh" +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/profiler/Profiler.hh" + +class AbsFormatter; +class DataCond; + +class ModuleCrosstalkRawDataHandler: public AbsDataHandler{ +public: + ModuleCrosstalkRawDataHandler(AbsDataProc* dataproc, DataCond& datacond, ConfigIF* cif, boost::property_tree::ptree* scanOptions); + virtual ~ModuleCrosstalkRawDataHandler(); + inline void handle(unsigned link, unsigned* data, int size); + void timeoutOccurred(); + inline void resetL1counters(); +protected: + int m_nL1AperEv; + int* m_L1Acounters; + int m_nModules; + int *m_linkToIndex; + int m_moduleTrgMask; + int* m_outlinkMask; + Profiler::Timer m_timer; + int m_counter; +}; +#endif diff --git a/rce/rcecalib/dataproc/MonleakDataProc.cc b/rce/rcecalib/dataproc/MonleakDataProc.cc new file mode 100644 index 00000000..9ea94a0c --- /dev/null +++ b/rce/rcecalib/dataproc/MonleakDataProc.cc @@ -0,0 +1,192 @@ +#include <stdio.h> +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/dataproc/MonleakDataProc.hh" +#include "rcecalib/config/ConfigIF.hh" +#include "rcecalib/config/FormattedRecord.hh" +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/profiler/Profiler.hh" +#include "rcecalib/config/FEI4/FEI4BRecord.hh" +#include "rcecalib/config/FEI4/PixelRegister.hh" +using namespace FEI4; + +int MonleakDataProc::fit(std::string fitfun) { + std::cout << "Running: " << fitfun << std::endl; + if(fitfun=="NORMALIZE") { + for (unsigned int module=0;module<m_configIF->getNmodules();module++){ + for(int j=0;j<m_nPoints;j++){ + // float n=(float)(*m_histo_occ[module])(j); + std::cout<<"Fit function currently not working, will need to change eventually to work with 2d histos"<<std::endl; + // float n=1; + // float mean=0; + + /* + if(n>0)mean=(float)(*m_histo_adc[module])(j)/n; + m_histo_norm[module]->set(j, mean); + float err=0; + if(n>0)err=((*m_histo_adc2[module])(j)/n-mean*mean)/n; //error^2 on mean + if(err<0)err=0; //prevent rounding errors + m_histo_norm[module]->setBinError(j, err); + // std::cout<<"Bin content is "<<(*m_histo[module][i])(j)<<std::endl; + //std::cout<<"Bin error is "<<m_histo[module][i]->getBinError(j)<<std::endl; + */ + + } + } + } + return 0; +} + +int MonleakDataProc::processData(unsigned link, unsigned *buffer, int buflen){ + //m_timer.Start(); + if(buflen==0)return 0; + int nL1A=0; + int module=m_linkToIndex[link]; + unsigned char* bytepointer=(unsigned char*)buffer; + unsigned char* last=bytepointer+buflen*sizeof(unsigned)-3; + FEI4::FEI4BRecord rec; + while(bytepointer<=last){ + rec.setRecord(bytepointer); + if(rec.isData()){ //includes empty record type + //should not happen + } else if(rec.isDataHeader()){ + //should not happen, either + }else if(rec.isServiceRecord()){ + //no service records + }else if(rec.isValueRecord()){ //val rec without addr rec + int value=rec.getValue()>>4; + + //std::cout<<"Link "<<link<<" value record! Value="<<std::hex<<rec.getValue()<<std::dec<<std::endl; + + fillHistogram(m_histo_occ[module], m_currentMaskStage, 1); + fillHistogram(m_histo_adc[module], m_currentMaskStage, value); + fillHistogram(m_histo_adc2[module], m_currentMaskStage, value*value); + + nL1A++; + }else if(rec.isAddressRecord()){ // address record + // Ignore address records + //std::cout<<"FE "<<m_info[module].getId()<<": Address record for "; + //if(rec.isGlobal())std::cout<<" global register "; + //else std::cout<<" shift register "; + //std::cout<<rec.getAddress()<<std::endl; + //std::cout<<"This should not happen."<<std::endl; + }else{ + std::cout<<"FE "<<m_info[module].getId()<<": Unexpected record type: "<<std::hex<<rec.getUnsigned()<<std::dec<<std::endl; + //return FEI4::FEI4ARecord::BadRecord; + return 0; + } + bytepointer+=3; + } + //m_timer.Stop(); + return nL1A; +} + +MonleakDataProc::MonleakDataProc(ConfigIF* cif, boost::property_tree::ptree* scanOptions) + :AbsDataProc(cif),m_fit(0) { + std::cout<<"Monleak Data Proc"<<std::endl; + try{ //catch bad scan option parameters + m_nLoops = scanOptions->get<int>("nLoops"); + /* there is at least one parameter loop */ + m_nPoints=1; + if(m_nLoops>0){ + m_nPoints=scanOptions->get<int>("scanLoop_0.nPoints"); + for(int i=0;i<m_nPoints;i++) { + char pointname[10]; + sprintf(pointname,"P_%d",i); + int vcal=scanOptions->get<int>(std::string("scanLoop_0.dataPoints.")+pointname); + //std::cout << "point vcal " << vcal << std::endl; + m_vcal.push_back(vcal); + } + } + m_nTrigger=scanOptions->get<int>("trigOpt.nEvents"); + + m_maskstageType=scanOptions->get<std::string>("maskStages"); //this is m_maskStageTotalSteps from PixScanBase_presetRCE.h + + std::cout<<"Initializing MonleakDataProc with maskstagetype = "<<m_maskstageType<<std::endl; + + + for (unsigned int module=0;module<m_configIF->getNmodules();module++){ + char name[128]; + char title[128]; + + unsigned int moduleId=m_info[module].getId(); + std::string moduleName=m_info[module].getName(); + + RceHisto2d<int, int> *histoOcc; + RceHisto2d<int, int> *histoAdc; + RceHisto2d<int, int> *histoAdc2; + unsigned int cols=m_info[module].getNColumns()*m_info[module].getNFrontends(); + unsigned int rows=m_info[module].getNRows(); + + /* retrieve scan points - Vcal steps in this case */ + sprintf(name, "Mod_%d_nEvents", moduleId); + sprintf(title, "Module %d at %s Number of events", moduleId, moduleName.c_str()); + histoOcc=new RceHisto2d<int, int>(name,title,rows,0,rows,cols,0,cols, true); + + sprintf(name, "Mod_%d_ADC", moduleId); + sprintf(title, "Module %d at %s ADC", moduleId, moduleName.c_str()); + histoAdc=new RceHisto2d<int, int>(name,title,rows,0,rows,cols,0,cols, true); + + sprintf(name, "Mod_%d_ADC2", moduleId); + sprintf(title, "Module %d at %s ADC^2", moduleId, moduleName.c_str()); + histoAdc2=new RceHisto2d<int, int>(name,title,rows,0,rows,cols,0,cols, true); + + if(m_info[module].getNFrontends()==1){ + histoOcc->setAxisTitle(1,"Column"); + histoAdc->setAxisTitle(1,"Column"); + histoAdc2->setAxisTitle(1,"Column"); + } + else{ + histoOcc->setAxisTitle(1,"FE*N_COL+Column"); + histoAdc->setAxisTitle(1,"FE*N_COL+Column"); + histoAdc2->setAxisTitle(1,"FE*N_COL+Column"); + } + histoOcc->setAxisTitle(0, "Row"); + histoAdc->setAxisTitle(0, "Row"); + histoAdc2->setAxisTitle(0, "Row"); + m_histo_occ.push_back(histoOcc); + m_histo_adc.push_back(histoAdc); + m_histo_adc2.push_back(histoAdc2); + + sprintf(name, "Mod_%d_Voltage", moduleId); + sprintf(title, "Module %d at %s Voltage", moduleId, moduleName.c_str()); + m_histo_norm.push_back(new RceHisto1d<float, float>(name, title, m_nPoints, 0, m_nPoints, true)); + m_histo_norm.back()->setAxisTitle(0, "Set point"); + } + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + ERS_ASSERT(0); + } +} + +MonleakDataProc::~MonleakDataProc(){ + for (size_t module=0;module<m_histo_occ.size();module++){ + delete m_histo_occ[module]; + delete m_histo_adc[module]; + delete m_histo_adc2[module]; + delete m_histo_norm[module]; + } + +} + + +int MonleakDataProc::fillHistogram(RceHisto2d<int, int>* hist, int maskStage, int value){ + + if(m_maskstageType=="FEI4_26880"){ + int row = maskStage%PixelRegister::N_ROWS; + int col = maskStage/PixelRegister::N_ROWS; + + //now I need to write code to translate maskStage into row and col + //std::cout<<"I'm filling histogram row,col = "<<row<<" , "<<col<<" with val = "<<value<<std::endl; + hist->fill(row,col,value); + + } + else{ + return 0; + } + + return 1; + +} + diff --git a/rce/rcecalib/dataproc/MonleakDataProc.hh b/rce/rcecalib/dataproc/MonleakDataProc.hh new file mode 100644 index 00000000..a4c584cc --- /dev/null +++ b/rce/rcecalib/dataproc/MonleakDataProc.hh @@ -0,0 +1,32 @@ +#ifndef MONLEAKDATAPROC_HH +#define MONLEAKDATAPROC_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/dataproc/AbsDataProc.hh" +#include "rcecalib/dataproc/fit/AbsFit.hh" +#include <vector> +#include "rcecalib/util/RceHisto1d.cc" +#include "rcecalib/util/RceHisto2d.cc" + +class MonleakDataProc: public AbsDataProc{ +public: + MonleakDataProc(ConfigIF* cif,boost::property_tree::ptree* scanOptions ); + virtual ~MonleakDataProc(); + int processData(unsigned link, unsigned *data, int size); + int fit(std::string fitfun); + +protected: + int fillHistogram(RceHisto2d<int, int>* hist, int maskStage, int value); + std::vector<RceHisto2d<int, int>*> m_histo_occ; + std::vector<RceHisto2d<int, int>*> m_histo_adc; + std::vector<RceHisto2d<int, int>*> m_histo_adc2; + std::vector<RceHisto1d<float, float>*> m_histo_norm; + AbsFit *m_fit; + std::vector<int> m_vcal; + int m_nTrigger; + int m_nLoops; + int m_nPoints; + std::string m_maskstageType; +}; + +#endif diff --git a/rce/rcecalib/dataproc/MultiTrigNoiseDataProc.cc b/rce/rcecalib/dataproc/MultiTrigNoiseDataProc.cc new file mode 100644 index 00000000..662cf607 --- /dev/null +++ b/rce/rcecalib/dataproc/MultiTrigNoiseDataProc.cc @@ -0,0 +1,219 @@ +#include <stdio.h> +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/dataproc/MultiTrigNoiseDataProc.hh" +#include "rcecalib/config/ConfigIF.hh" +#include "rcecalib/config/FormattedRecord.hh" +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/util/RceName.hh" +#include "rcecalib/dataproc/fit/FitFactory.cc" +#include "rcecalib/profiler/Profiler.hh" + + +int MultiTrigNoiseDataProc::fit(std::string fitfun) { + FitFactory<int, int> dfac; //template parameters are the type of the histogram and error + std::cout << "Running: " << fitfun << std::endl; + if(fitfun.size()>=6 && fitfun.substr(0,6)=="SCURVE") { + // m_fit=dfac.createFit("ScurveLikelihoodFloat",m_configIF, m_histo_occ,m_vcal,m_nTrigger); + m_fit0=dfac.createFit("ScurveLikelihoodFastInt",m_configIF, m_histo_occ0,m_vcal,m_nTrigger, "Trig0"); + int opt=0; + if(fitfun.size()>=13&&fitfun.substr(7,6)=="NOCONV")opt=AbsFit::NOCONV; + if(fitfun.size()>=12&&fitfun.substr(7,5)=="XTALK")opt=AbsFit::XTALK; + m_fit0->doFit(opt); + + m_fit1=dfac.createFit("ScurveLikelihoodFastInt",m_configIF, m_histo_occ1,m_vcal,m_nTrigger, "Trig1"); + opt=0; + if(fitfun.size()>=13&&fitfun.substr(7,6)=="NOCONV")opt=AbsFit::NOCONV; + if(fitfun.size()>=12&&fitfun.substr(7,5)=="XTALK")opt=AbsFit::XTALK; + m_fit1->doFit(opt); + } + return 0; +} + +int MultiTrigNoiseDataProc::processData(unsigned link, unsigned *data, int size){ + m_timer.Start(); + // std::cout<<"Process data with size = "<<size<<std::endl; + int module=m_linkToIndex[link]; + + int l1id = 0; + int bcid = 0; + + for (int i=0;i<size;i++){ + FormattedRecord current(data[i]); + + + if (current.isHeader()){ + l1id = current.getL1id(); + bcid = current.getBxid(); + + + //old code for deciding which trigger data belongs to. Unfortunately, we've seen cases + //where the l1id order gets messed up, in which case this doesn't work. + /* + if (l1id != m_l1id_prev) { + // std::cout<<"new l1id = "<<l1id<<std::endl; + + if (m_nbcid!=m_nbcid_total){ + std::cout<<"VERY BAD last l1id had m_nbcid = "<<m_nbcid<<std::endl; + } + + m_l1id_which++; + if(m_l1id_which>=2){ + m_l1id_which=0; + } + + // m_l1id_prev = l1id; + // m_bcid_prev = bcid; + m_nbcid=0; + } + else{ + int exp_bcid = m_bcid_prev+1; + exp_bcid = exp_bcid%256; + if ( (bcid%256) != exp_bcid) { + std::cout<<"SCREAM! bcid changed from "<<m_bcid_prev<<" to "<<bcid<<std::endl; + } + } + */ + + //assume l1id starts counting from 1. Empirically, this seems to work. + if((l1id%2)==0){ + m_l1id_which=1; + } + else{ + m_l1id_which=0; + } + + + //printf("bcid : %d , l1id : %d , l1id_which: %d\n", bcid,l1id,m_l1id_which); + + // bcid = bcid-bcid_ref; + m_nbcid++; + //if( (bcid+1) != m_nbcid || m_nbcid > m_nbcid_total || bcid >= m_nbcid_total){ + // std::cout<<"SCREAM bcid = "<<bcid<<" ; m_nbcid = "<<m_nbcid<<std::endl; + // } + m_bcid_prev = bcid; + m_l1id_prev = l1id; + + } //if(isHeader) + + if (current.isData()){ + unsigned int chip=current.getFE(); + unsigned int col=current.getCol(); + unsigned int row=current.getRow(); + // unsigned int tot=current.getToT(); + // if(col==10 && row==10){ + // printf("Hit col=%d row=%d tot=%d\n",col, row, tot); + // } + if((row<(unsigned)m_info[module].getNRows()) && (col<(unsigned)m_info[module].getNColumns())) { + + RceHisto2d<int, int>* histo(0); + + if(m_l1id_which==0){ + histo = m_histo_occ0[module][m_currentBin]; + } + else if(m_l1id_which==1){ + histo = m_histo_occ1[module][m_currentBin]; + } + else{ + std::cout<<"This can't happen!"<<std::endl; + } + + if (chip==0) histo->incrementFast(row,col); + else if (chip<(unsigned)m_info[module].getNFrontends()) histo->incrementFast(row, chip*m_info[module].getNColumns()+col); + } + + } //if(isData) + + } //end for(int i=0; i<size; i++) + + m_timer.Stop(); + return 0; +} + +MultiTrigNoiseDataProc::MultiTrigNoiseDataProc(ConfigIF* cif, boost::property_tree::ptree* scanOptions) + :AbsDataProc(cif),m_fit0(0),m_fit1(0),m_l1id_prev(-1),m_bcid_prev(0),m_nbcid(0),m_nbcid_total(0),m_l1id_which(-1) { + std::cout<<"MultiTrigNoise Data Proc"<<std::endl; + std::cout<<"Rce Number is "<<RceName::getRceNumber()<<std::endl; + try{ //catch bad scan option parameters + m_nLoops = scanOptions->get<int>("nLoops"); + /* there is at least one parameter loop */ + /* TODO: fix in scan control */ + m_nPoints=1; + if(m_nLoops>0){ + m_nPoints=scanOptions->get<int>("scanLoop_0.nPoints"); + for(int i=0;i<m_nPoints;i++) { + char pointname[10]; + sprintf(pointname,"P_%d",i); + int vcal=scanOptions->get<int>(std::string("scanLoop_0.dataPoints.")+pointname); + //std::cout << "point vcal " << vcal << std::endl; + m_vcal.push_back(vcal); + } + } + m_nTrigger=scanOptions->get<int>("trigOpt.nEvents"); + m_nbcid_total = scanOptions->get<int>("trigOpt.nL1AperEvent"); + m_nbcid = m_nbcid_total; + + for (unsigned int module=0;module<m_configIF->getNmodules();module++){ + std::vector<RceHisto2d<int, int>* > vh; + m_histo_occ0.push_back(vh); + m_histo_occ1.push_back(vh); + + char name[128]; + char title[128]; + RceHisto2d<int, int> *histo0; + RceHisto2d<int, int> *histo1; + + unsigned int cols=m_info[module].getNColumns()*m_info[module].getNFrontends(); + unsigned int rows=m_info[module].getNRows(); + unsigned int moduleId=m_info[module].getId(); + std::string moduleName=m_info[module].getName(); + /* retrieve scan points - Vcal steps in this case */ + std::cout<<"Creating Occupancy histograms."<<std::endl; + for (int point=0;point<m_nPoints;point++){ + sprintf(title,"OCCUPANCY Mod %d at %s", moduleId, moduleName.c_str()); + + sprintf(name,"Mod_%d_Trig0_Occupancy_Point_%03d", moduleId,point); + histo0=new RceHisto2d<int, int>(name,title,rows,0,rows,cols,0,cols, true, false); + + sprintf(name,"Mod_%d_Trig1_Occupancy_Point_%03d", moduleId,point); + histo1=new RceHisto2d<int, int>(name,title,rows,0,rows,cols,0,cols, true, false); + + if(m_info[module].getNFrontends()==1){ + histo0->setAxisTitle(0,"Column"); + histo1->setAxisTitle(0,"Column"); + } + else{ + histo0->setAxisTitle(0,"FE*N_COL+Column"); + histo1->setAxisTitle(0,"FE*N_COL+Column"); + } + histo0->setAxisTitle(1, "Row"); + histo1->setAxisTitle(1, "Row"); + + m_histo_occ0[module].push_back(histo0); + m_histo_occ1[module].push_back(histo1); + + } + } + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + ERS_ASSERT(0); + } + m_timer.Reset(); +} + +MultiTrigNoiseDataProc::~MultiTrigNoiseDataProc(){ + if(m_fit0) delete m_fit0; + if(m_fit1) delete m_fit1; + + for (size_t module=0;module<m_histo_occ0.size();module++){ + for(size_t i=0;i<m_histo_occ0[module].size();i++){ + delete m_histo_occ0[module][i]; + delete m_histo_occ1[module][i]; + } + } + + m_timer.Print("MultiTrigNoiseDataProc"); +} + + diff --git a/rce/rcecalib/dataproc/MultiTrigNoiseDataProc.hh b/rce/rcecalib/dataproc/MultiTrigNoiseDataProc.hh new file mode 100644 index 00000000..b5ffb894 --- /dev/null +++ b/rce/rcecalib/dataproc/MultiTrigNoiseDataProc.hh @@ -0,0 +1,40 @@ +#ifndef MULTITRIGNOISEDATAPROC_HH +#define MULTITRIGNOISEDATAPROC_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/dataproc/AbsDataProc.hh" +#include "rcecalib/dataproc/fit/AbsFit.hh" +#include <vector> +#include "rcecalib/util/RceHisto2d.cc" +#include "rcecalib/profiler/Profiler.hh" + +class MultiTrigNoiseDataProc: public AbsDataProc{ +public: + MultiTrigNoiseDataProc(ConfigIF* cif,boost::property_tree::ptree* scanOptions ); + virtual ~MultiTrigNoiseDataProc(); + int processData(unsigned link, unsigned *data, int size); + int fit(std::string fitfun); + +protected: + + std::vector<std::vector<RceHisto2d<int, int>*> > m_histo_occ0; + std::vector<std::vector<RceHisto2d<int, int>*> > m_histo_occ1; + + AbsFit *m_fit0; + AbsFit *m_fit1; + + std::vector<int> m_vcal; + int m_nTrigger; + int m_nLoops; + int m_nPoints; + + int m_l1id_prev; + int m_bcid_prev; + int m_nbcid; + int m_nbcid_total; + int m_l1id_which; + + Profiler::Timer m_timer; +}; + +#endif diff --git a/rce/rcecalib/dataproc/MultiTrigOccupancyDataProc.cc b/rce/rcecalib/dataproc/MultiTrigOccupancyDataProc.cc new file mode 100644 index 00000000..0002abbf --- /dev/null +++ b/rce/rcecalib/dataproc/MultiTrigOccupancyDataProc.cc @@ -0,0 +1,219 @@ +#include <stdio.h> +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/dataproc/MultiTrigOccupancyDataProc.hh" +#include "rcecalib/config/ConfigIF.hh" +#include "rcecalib/config/FormattedRecord.hh" +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/util/RceName.hh" +#include "rcecalib/dataproc/fit/FitFactory.cc" +#include "rcecalib/profiler/Profiler.hh" + + +int MultiTrigOccupancyDataProc::fit(std::string fitfun) { + FitFactory<char, char> dfac; //template parameters are the type of the histogram and error + std::cout << "Running: " << fitfun << std::endl; + if(fitfun.size()>=6 && fitfun.substr(0,6)=="SCURVE") { + // m_fit=dfac.createFit("ScurveLikelihoodFloat",m_configIF, m_histo_occ,m_vcal,m_nTrigger); + m_fit0=dfac.createFit("ScurveLikelihoodFastInt",m_configIF, m_histo_occ0,m_vcal,m_nTrigger, "Trig0"); + int opt=0; + if(fitfun.size()>=13&&fitfun.substr(7,6)=="NOCONV")opt=AbsFit::NOCONV; + if(fitfun.size()>=12&&fitfun.substr(7,5)=="XTALK")opt=AbsFit::XTALK; + m_fit0->doFit(opt); + + m_fit1=dfac.createFit("ScurveLikelihoodFastInt",m_configIF, m_histo_occ1,m_vcal,m_nTrigger, "Trig1"); + opt=0; + if(fitfun.size()>=13&&fitfun.substr(7,6)=="NOCONV")opt=AbsFit::NOCONV; + if(fitfun.size()>=12&&fitfun.substr(7,5)=="XTALK")opt=AbsFit::XTALK; + m_fit1->doFit(opt); + } + return 0; +} + +int MultiTrigOccupancyDataProc::processData(unsigned link, unsigned *data, int size){ + m_timer.Start(); + // std::cout<<"Process data with size = "<<size<<std::endl; + int module=m_linkToIndex[link]; + + int l1id = 0; + int bcid = 0; + + for (int i=0;i<size;i++){ + FormattedRecord current(data[i]); + + + if (current.isHeader()){ + l1id = current.getL1id(); + bcid = current.getBxid(); + + + //old code for deciding which trigger data belongs to. Unfortunately, we've seen cases + //where the l1id order gets messed up, in which case this doesn't work. + /* + if (l1id != m_l1id_prev) { + // std::cout<<"new l1id = "<<l1id<<std::endl; + + if (m_nbcid!=m_nbcid_total){ + std::cout<<"VERY BAD last l1id had m_nbcid = "<<m_nbcid<<std::endl; + } + + m_l1id_which++; + if(m_l1id_which>=2){ + m_l1id_which=0; + } + + // m_l1id_prev = l1id; + // m_bcid_prev = bcid; + m_nbcid=0; + } + else{ + int exp_bcid = m_bcid_prev+1; + exp_bcid = exp_bcid%256; + if ( (bcid%256) != exp_bcid) { + std::cout<<"SCREAM! bcid changed from "<<m_bcid_prev<<" to "<<bcid<<std::endl; + } + } + */ + + //assume l1id starts counting from 1. Empirically, this seems to work. + if((l1id%2)==0){ + m_l1id_which=1; + } + else{ + m_l1id_which=0; + } + + + //printf("bcid : %d , l1id : %d , l1id_which: %d\n", bcid,l1id,m_l1id_which); + + // bcid = bcid-bcid_ref; + m_nbcid++; + //if( (bcid+1) != m_nbcid || m_nbcid > m_nbcid_total || bcid >= m_nbcid_total){ + // std::cout<<"SCREAM bcid = "<<bcid<<" ; m_nbcid = "<<m_nbcid<<std::endl; + // } + m_bcid_prev = bcid; + m_l1id_prev = l1id; + + } //if(isHeader) + + if (current.isData()){ + unsigned int chip=current.getFE(); + unsigned int col=current.getCol(); + unsigned int row=current.getRow(); + // unsigned int tot=current.getToT(); + // if(col==10 && row==10){ + // printf("Hit col=%d row=%d tot=%d\n",col, row, tot); + // } + if((row<(unsigned)m_info[module].getNRows()) && (col<(unsigned)m_info[module].getNColumns())) { + + RceHisto2d<char, char>* histo(0); + + if(m_l1id_which==0){ + histo = m_histo_occ0[module][m_currentBin]; + } + else if(m_l1id_which==1){ + histo = m_histo_occ1[module][m_currentBin]; + } + else{ + std::cout<<"This can't happen!"<<std::endl; + } + + if (chip==0) histo->incrementFast(row,col); + else if (chip<(unsigned)m_info[module].getNFrontends()) histo->incrementFast(row, chip*m_info[module].getNColumns()+col); + } + + } //if(isData) + + } //end for(int i=0; i<size; i++) + + m_timer.Stop(); + return 0; +} + +MultiTrigOccupancyDataProc::MultiTrigOccupancyDataProc(ConfigIF* cif, boost::property_tree::ptree* scanOptions) + :AbsDataProc(cif),m_fit0(0),m_fit1(0),m_l1id_prev(-1),m_bcid_prev(0),m_nbcid(0),m_nbcid_total(0),m_l1id_which(-1) { + std::cout<<"MultiTrigOccupancy Data Proc"<<std::endl; + std::cout<<"Rce Number is "<<RceName::getRceNumber()<<std::endl; + try{ //catch bad scan option parameters + m_nLoops = scanOptions->get<int>("nLoops"); + /* there is at least one parameter loop */ + /* TODO: fix in scan control */ + m_nPoints=1; + if(m_nLoops>0){ + m_nPoints=scanOptions->get<int>("scanLoop_0.nPoints"); + for(int i=0;i<m_nPoints;i++) { + char pointname[10]; + sprintf(pointname,"P_%d",i); + int vcal=scanOptions->get<int>(std::string("scanLoop_0.dataPoints.")+pointname); + //std::cout << "point vcal " << vcal << std::endl; + m_vcal.push_back(vcal); + } + } + m_nTrigger=scanOptions->get<int>("trigOpt.nEvents"); + m_nbcid_total = scanOptions->get<int>("trigOpt.nL1AperEvent"); + m_nbcid = m_nbcid_total; + + for (unsigned int module=0;module<m_configIF->getNmodules();module++){ + std::vector<RceHisto2d<char, char>* > vh; + m_histo_occ0.push_back(vh); + m_histo_occ1.push_back(vh); + + char name[128]; + char title[128]; + RceHisto2d<char, char> *histo0; + RceHisto2d<char, char> *histo1; + + unsigned int cols=m_info[module].getNColumns()*m_info[module].getNFrontends(); + unsigned int rows=m_info[module].getNRows(); + unsigned int moduleId=m_info[module].getId(); + std::string moduleName=m_info[module].getName(); + /* retrieve scan points - Vcal steps in this case */ + std::cout<<"Creating Occupancy histograms."<<std::endl; + for (int point=0;point<m_nPoints;point++){ + sprintf(title,"OCCUPANCY Mod %d at %s", moduleId, moduleName.c_str()); + + sprintf(name,"Mod_%d_Trig0_Occupancy_Point_%03d", moduleId,point); + histo0=new RceHisto2d<char, char>(name,title,rows,0,rows,cols,0,cols, true, false); + + sprintf(name,"Mod_%d_Trig1_Occupancy_Point_%03d", moduleId,point); + histo1=new RceHisto2d<char, char>(name,title,rows,0,rows,cols,0,cols, true, false); + + if(m_info[module].getNFrontends()==1){ + histo0->setAxisTitle(0,"Column"); + histo1->setAxisTitle(0,"Column"); + } + else{ + histo0->setAxisTitle(0,"FE*N_COL+Column"); + histo1->setAxisTitle(0,"FE*N_COL+Column"); + } + histo0->setAxisTitle(1, "Row"); + histo1->setAxisTitle(1, "Row"); + + m_histo_occ0[module].push_back(histo0); + m_histo_occ1[module].push_back(histo1); + + } + } + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + ERS_ASSERT(0); + } + m_timer.Reset(); +} + +MultiTrigOccupancyDataProc::~MultiTrigOccupancyDataProc(){ + if(m_fit0) delete m_fit0; + if(m_fit1) delete m_fit1; + + for (size_t module=0;module<m_histo_occ0.size();module++){ + for(size_t i=0;i<m_histo_occ0[module].size();i++){ + delete m_histo_occ0[module][i]; + delete m_histo_occ1[module][i]; + } + } + + m_timer.Print("MultiTrigOccupancyDataProc"); +} + + diff --git a/rce/rcecalib/dataproc/MultiTrigOccupancyDataProc.hh b/rce/rcecalib/dataproc/MultiTrigOccupancyDataProc.hh new file mode 100644 index 00000000..28bf2136 --- /dev/null +++ b/rce/rcecalib/dataproc/MultiTrigOccupancyDataProc.hh @@ -0,0 +1,40 @@ +#ifndef MULTITRIGOCCUPANCYDATAPROC_HH +#define MULTITRIGOCCUPANCYDATAPROC_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/dataproc/AbsDataProc.hh" +#include "rcecalib/dataproc/fit/AbsFit.hh" +#include <vector> +#include "rcecalib/util/RceHisto2d.cc" +#include "rcecalib/profiler/Profiler.hh" + +class MultiTrigOccupancyDataProc: public AbsDataProc{ +public: + MultiTrigOccupancyDataProc(ConfigIF* cif,boost::property_tree::ptree* scanOptions ); + virtual ~MultiTrigOccupancyDataProc(); + int processData(unsigned link, unsigned *data, int size); + int fit(std::string fitfun); + +protected: + + std::vector<std::vector<RceHisto2d<char, char>*> > m_histo_occ0; + std::vector<std::vector<RceHisto2d<char, char>*> > m_histo_occ1; + + AbsFit *m_fit0; + AbsFit *m_fit1; + + std::vector<int> m_vcal; + int m_nTrigger; + int m_nLoops; + int m_nPoints; + + int m_l1id_prev; + int m_bcid_prev; + int m_nbcid; + int m_nbcid_total; + int m_l1id_which; + + Profiler::Timer m_timer; +}; + +#endif diff --git a/rce/rcecalib/dataproc/NoiseOccupancyDataProc.cc b/rce/rcecalib/dataproc/NoiseOccupancyDataProc.cc new file mode 100644 index 00000000..99a1076c --- /dev/null +++ b/rce/rcecalib/dataproc/NoiseOccupancyDataProc.cc @@ -0,0 +1,94 @@ +#include <stdio.h> +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/dataproc/NoiseOccupancyDataProc.hh" +#include "rcecalib/config/ConfigIF.hh" +#include "rcecalib/config/FormattedRecord.hh" +#include "rcecalib/util/exceptions.hh" + + +int NoiseOccupancyDataProc::processData(unsigned link, unsigned *data, int size){ + //std::cout<<"Process data of size "<<size<<std::endl; + if(m_counter++==0)usleep(1); + int module=m_linkToIndex[link]; + for (int i=0;i<size;i++){ + FormattedRecord current(data[i]); + if (current.isHeader()){ + unsigned l1id = current.getL1id(); + //printf("bcid : %x \n", bcid); + //printf("l1id : %x \n", l1id); + if (l1id != m_l1id_last[module]) + { + m_l1id_last[module] = l1id; + m_histo_eventCount[module]->incrementFast(0); + } + //printf("bcidafter : %x \n", bcid); + } + if (current.isData()){ + unsigned int chip=current.getFE(); + unsigned int col=current.getCol(); + unsigned int row=current.getRow(); + //unsigned int tot=current.getToT(); + //printf("Hit col=%d row=%d tot=%d\n",col, row, tot); + if(chip==0){ + if((row<(unsigned)m_info[module].getNRows()) && (col<(unsigned)m_info[module].getNColumns())) { + m_histo_occ[module]->incrementFast(col,row); + } + }else{ + if(chip<(unsigned)m_info[module].getNFrontends() && + (row<(unsigned)m_info[module].getNRows()) && + (col<(unsigned)m_info[module].getNColumns())) { + m_histo_occ[module]->incrementFast(chip*m_info[module].getNColumns()+col,row); + } + } + } + } + return 0; +} + +NoiseOccupancyDataProc::NoiseOccupancyDataProc(ConfigIF* cif, boost::property_tree::ptree* scanOptions) + :AbsDataProc(cif), m_counter(0) { + std::cout<<"Occupancy Data Proc"<<std::endl; + try{ //catch bad scan option parameters + m_l1id_last = new unsigned[m_configIF->getNmodules()]; + for(unsigned i=0;i<m_configIF->getNmodules();i++)m_l1id_last[i]=0xffff; + + for (unsigned int module=0;module<m_configIF->getNmodules();module++){ + char name[128]; + char title[128]; + RceHisto2d<int, int> *histo; + RceHisto1d<int, int> *histo_ec; + unsigned int cols=m_info[module].getNColumns()*m_info[module].getNFrontends(); + unsigned int rows=m_info[module].getNRows(); + unsigned int moduleId=m_info[module].getId(); + std::string moduleName=m_info[module].getName(); + std::cout<<"Creating Occupancy histograms."<<std::endl; + sprintf(title,"OCCUPANCY Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_NoiseOccupancy", moduleId); + histo=new RceHisto2d<int, int>(name,title,cols,0,cols,rows,0,rows); + if(m_info[module].getNFrontends()==1)histo->setAxisTitle(0,"Column"); + else histo->setAxisTitle(0,"FE*N_COL+Column"); + histo->setAxisTitle(1, "Row"); + m_histo_occ.push_back(histo); + + sprintf(title,"Number of Events Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_nEvents", moduleId); + histo_ec=new RceHisto1d<int,int>(name, title, 1,0,1); + histo_ec->setAxisTitle(0, "n Event Bin"); + m_histo_eventCount.push_back(histo_ec); + } + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + ERS_ASSERT(0); + } +} + +NoiseOccupancyDataProc::~NoiseOccupancyDataProc(){ + delete [] m_l1id_last; + for (size_t module=0;module<m_histo_occ.size();module++)delete m_histo_occ[module]; + for (size_t module=0;module<m_histo_occ.size();module++)delete m_histo_eventCount[module]; + +} + + diff --git a/rce/rcecalib/dataproc/NoiseOccupancyDataProc.hh b/rce/rcecalib/dataproc/NoiseOccupancyDataProc.hh new file mode 100644 index 00000000..4bac9302 --- /dev/null +++ b/rce/rcecalib/dataproc/NoiseOccupancyDataProc.hh @@ -0,0 +1,25 @@ +#ifndef NOISEOCCUPANCYDATAPROC_HH +#define NOISEOCCUPANCYDATAPROC_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/dataproc/AbsDataProc.hh" +#include "rcecalib/dataproc/fit/AbsFit.hh" +#include <vector> +#include "rcecalib/util/RceHisto2d.cc" +#include "rcecalib/util/RceHisto1d.cc" + +class NoiseOccupancyDataProc: public AbsDataProc{ +public: + NoiseOccupancyDataProc(ConfigIF* cif,boost::property_tree::ptree* scanOptions ); + virtual ~NoiseOccupancyDataProc(); + int processData(unsigned link, unsigned *data, int size); + +protected: + + std::vector<RceHisto2d<int, int>*> m_histo_occ; + std::vector<RceHisto1d<int, int>*> m_histo_eventCount; + unsigned int *m_l1id_last; + unsigned short m_counter; +}; + +#endif diff --git a/rce/rcecalib/dataproc/OccupancyDataProc.cc b/rce/rcecalib/dataproc/OccupancyDataProc.cc new file mode 100644 index 00000000..7a9226b6 --- /dev/null +++ b/rce/rcecalib/dataproc/OccupancyDataProc.cc @@ -0,0 +1,121 @@ +#include <stdio.h> +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/dataproc/OccupancyDataProc.hh" +#include "rcecalib/config/ConfigIF.hh" +#include "rcecalib/config/FormattedRecord.hh" +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/dataproc/fit/FitFactory.cc" +#include "rcecalib/profiler/Profiler.hh" + + +int OccupancyDataProc::fit(std::string fitfun) { + FitFactory<char, char> dfac; //template parameters are the type of the histogram and error + std::cout << "Running: " << fitfun << std::endl; + if(fitfun.size()>=6 && fitfun.substr(0,6)=="SCURVE") { + // m_fit=dfac.createFit("ScurveLikelihoodFloat",m_configIF, m_histo_occ,m_vcal,m_nTrigger); + m_fit=dfac.createFit("ScurveLikelihoodFastInt",m_configIF, m_histo_occ,m_vcal,m_nTrigger); + int opt=0; + if(fitfun.size()>=13&&fitfun.substr(7,6)=="NOCONV")opt=AbsFit::NOCONV; + if(fitfun.size()>=12&&fitfun.substr(7,5)=="XTALK")opt=AbsFit::XTALK; + m_fit->doFit(opt); + } + return 0; +} + +int OccupancyDataProc::processData(unsigned link, unsigned *data, int size){ + m_timer.Start(); + // std::cout<<"Process data"<<std::endl; + int module=m_linkToIndex[link]; + RceHisto2d<char, char>* histo=m_histo_occ[module][m_currentBin]; + for (int i=0;i<size;i++){ + FormattedRecord current(data[i]); + /* + if (current.isHeader()){ + l1id = current.getL1id(); + bcid = current.getBxid(); + //printf("bcid : %x \n", bcid); + //printf("l1id : %x \n", l1id); + if (l1id != l1id_last) + { + l1id_last = l1id; + bcid_ref = bcid; + } + bcid = bcid-bcid_ref; + //printf("bcidafter : %x \n", bcid); + } + */ + if (current.isData()){ + unsigned int chip=current.getFE(); + unsigned int col=current.getCol(); + unsigned int row=current.getRow(); + //unsigned int tot=current.getToT(); + //printf("Hit col=%d row=%d tot=%d\n",col, row, tot); + if((row<(unsigned)m_info[module].getNRows()) && (col<(unsigned)m_info[module].getNColumns())) { + if(chip==0)histo->incrementFast(row,col); + else if(chip<(unsigned)m_info[module].getNFrontends())histo->incrementFast(row, chip*m_info[module].getNColumns()+col); + } + } + } + m_timer.Stop(); + return 0; +} + +OccupancyDataProc::OccupancyDataProc(ConfigIF* cif, boost::property_tree::ptree* scanOptions) + :AbsDataProc(cif),m_fit(0) { + std::cout<<"Occupancy Data Proc"<<std::endl; + try{ //catch bad scan option parameters + m_nLoops = scanOptions->get<int>("nLoops"); + /* there is at least one parameter loop */ + /* TODO: fix in scan control */ + m_nPoints=1; + if(m_nLoops>0){ + m_nPoints=scanOptions->get<int>("scanLoop_0.nPoints"); + for(int i=0;i<m_nPoints;i++) { + char pointname[10]; + sprintf(pointname,"P_%d",i); + int vcal=scanOptions->get<int>(std::string("scanLoop_0.dataPoints.")+pointname); + //std::cout << "point vcal " << vcal << std::endl; + m_vcal.push_back(vcal); + } + } + m_nTrigger=scanOptions->get<int>("trigOpt.nEvents"); + + for (unsigned int module=0;module<m_configIF->getNmodules();module++){ + std::vector<RceHisto2d<char, char>* > vh; + m_histo_occ.push_back(vh); + char name[128]; + char title[128]; + RceHisto2d<char, char> *histo; + unsigned int cols=m_info[module].getNColumns()*m_info[module].getNFrontends(); + unsigned int rows=m_info[module].getNRows(); + unsigned int moduleId=m_info[module].getId(); + /* retrieve scan points - Vcal steps in this case */ + std::cout<<"Creating Occupancy histograms."<<std::endl; + for (int point=0;point<m_nPoints;point++){ + sprintf(title,"OCCUPANCY"); + sprintf(name,"Mod_%d_Occupancy_Point_%03d", moduleId,point); + histo=new RceHisto2d<char, char>(name,title,rows,0,rows,cols,0,cols, true, false); + if(m_info[module].getNFrontends()==1)histo->setAxisTitle(1,"Column"); + else histo->setAxisTitle(1,"FE*N_COL+Column"); + histo->setAxisTitle(0, "Row"); + m_histo_occ[module].push_back(histo); + } + } + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + ERS_ASSERT(0); + } + m_timer.Reset(); +} + +OccupancyDataProc::~OccupancyDataProc(){ + if(m_fit) delete m_fit; + for (size_t module=0;module<m_histo_occ.size();module++) + for(size_t i=0;i<m_histo_occ[module].size();i++)delete m_histo_occ[module][i]; + + m_timer.Print("OccupancyDataProc"); +} + + diff --git a/rce/rcecalib/dataproc/OccupancyDataProc.hh b/rce/rcecalib/dataproc/OccupancyDataProc.hh new file mode 100644 index 00000000..5398a0a5 --- /dev/null +++ b/rce/rcecalib/dataproc/OccupancyDataProc.hh @@ -0,0 +1,29 @@ +#ifndef OCCUPANCYDATAPROC_HH +#define OCCUPANCYDATAPROC_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/dataproc/AbsDataProc.hh" +#include "rcecalib/dataproc/fit/AbsFit.hh" +#include <vector> +#include "rcecalib/util/RceHisto2d.cc" +#include "rcecalib/profiler/Profiler.hh" + +class OccupancyDataProc: public AbsDataProc{ +public: + OccupancyDataProc(ConfigIF* cif,boost::property_tree::ptree* scanOptions ); + virtual ~OccupancyDataProc(); + int processData(unsigned link, unsigned *data, int size); + int fit(std::string fitfun); + +protected: + + std::vector<std::vector<RceHisto2d<char, char>*> > m_histo_occ; + AbsFit *m_fit; + std::vector<int> m_vcal; + int m_nTrigger; + int m_nLoops; + int m_nPoints; + Profiler::Timer m_timer; +}; + +#endif diff --git a/rce/rcecalib/dataproc/PgpCosmicNwReceiver.cc b/rce/rcecalib/dataproc/PgpCosmicNwReceiver.cc new file mode 100644 index 00000000..a07b9e07 --- /dev/null +++ b/rce/rcecalib/dataproc/PgpCosmicNwReceiver.cc @@ -0,0 +1,145 @@ +#include "dataproc/PgpCosmicNwReceiver.hh" +#include "dataproc/Channeldefs.hh" +#include "HW/RCDImaster.hh" +#include "eudaq/DataSender.hh" +#include "eudaq/DataSenderIF.hh" +//#include "rce/service/Cache.hh" +using namespace PgpTrans; + +#include <iostream> +#include "HW/Headers.hh" +#include <stdlib.h> +#include <boost/property_tree/ptree.hpp> +#include <boost/algorithm/string.hpp> +#include "HW/SerialIF.hh" +#include "config/FEI3/FECommands.hh" +#include "util/RceName.hh" + +PgpCosmicNwReceiver::PgpCosmicNwReceiver(AbsDataHandler* handler, boost::property_tree::ptree* scanOptions) + :AbsReceiver(handler),Receiver(), m_print(0), m_abs_sec(0), + m_bufferssend(0), m_senddiff(0){ + m_bad=0; + for (int i=0;i<32;i++)m_linksynch[i]=false; + RCDImaster::instance()->setReceiver(this); + std::cout<<"Created pgp cosmic network receiver"<<std::endl; + m_counter=0; + std::string name=scanOptions->get<std::string>("Name"); + std::cout<<"CosmicDataProc name "<<name<<std::endl; + std::string prefix("CosmicGui"); + assert(name.compare(0, prefix.size(), prefix) == 0) ; + // CosmicGui asks to send back over TCP + // parse string of form: CosmicGui|01168|tcp://127.56.2.6:4500 + std::vector<std::string> strs; + boost::split(strs, name, boost::is_any_of("|")); + //m_runNo=atoi(strs[1].c_str()); + name = strs[2]; + std::cout<<"TCP to " << name <<std::endl; + m_ds = new eudaq::DataSender(std::string("DataSender"), std::string("CosmicGuiDataSender")); + DataSenderIF::setDataSender(m_ds); + try + { + m_ds->Connect(name); + } + catch (const std::exception & ex) + { + // Need to do sensible things here, maybe catch different types of exceptions. + std::cout << "DataSender could not connect. Exception says: \n " << ex.what() << std::endl; + } + m_sendbuffer=new unsigned char[1024*1024]; + m_bufferpointer=0; +} +PgpCosmicNwReceiver::~PgpCosmicNwReceiver(){ + std::cout<<"Received "<<std::dec<<m_counter<<" buffers in previous run."<<std::endl; + std::cout<<"Sent "<<std::dec<<m_bufferssend<<" buffers in previous run."<<std::endl; + delete m_ds; + delete [] m_sendbuffer; + } +void PgpCosmicNwReceiver::receive(PgpTrans::PgpData *pgpdata){ + int link=pgpdata->header[2]; + if(link==PGPACK){ + if(m_bufferpointer>0){ //sweep + DataSenderIF::SendEvent(m_sendbuffer, m_bufferpointer); + m_abs_sec=(unsigned int)time(0); + m_bufferpointer=0; + } + return; + } + m_counter++; + if((m_counter&0xffff)==0)usleep(1); //give external commands a chance to execute from time to time + unsigned size=pgpdata->payloadSize; + unsigned* data=pgpdata->payload; + //std::cout<<"Link "<<link<<" Size ="<<size<<std::endl; + bool marker=pgpdata->header[6]&0x80; + if(m_linksynch[link]==true) { + if (marker==false){ + if(m_print>0){ + if(link==TDCREADOUT)std::cout<<"Ignoring TDC link L1A: "<<(data[1]>>24)<<std::endl; + else { + std::cout<<"Ignoring Link "<<link<<std::endl; + } + m_print--; + } + m_tossed[link]++; + return ; + } + m_linksynch[link]=false; + //if(marker)std::cout<<"Markerevent"<<std::endl; + std::cout<<"Tossed "<<m_tossed[link]<<" fragments for link "<<link<<std::endl; + } + if(marker){ + link|=1<<MARKERPOS; + } + + int rce = RceName::getRceNumber(); + rce=rce&RCEMASK; + //std::cout<<"link without rce = "<<link<<std::endl; + link |= (rce << RCEPOS); + //std::cout<<"link with rce = "<<link<<std::endl; + + //link is a 16-bit number with the following format: + //xxxxrrrr rrrmllll + //where the x's are currently unused, rrrrrrr is the rce number, + //m is a marker (used for resynching), and llll is the outlink number + + //std::cout<<"Payloadsize "<<payloadSize<<std::endl; + unsigned short* se=(unsigned short*)&m_sendbuffer[m_bufferpointer]; + int bytesize=size*sizeof(unsigned); + se[0]=bytesize; + se[1]=link; +#ifdef __rtems__ //swap + se[0]=se[0]<<8|se[0]>>8; + se[1]=se[1]<<8|se[1]>>8; +#endif + memcpy(&m_sendbuffer[m_bufferpointer+4], data, bytesize); + m_bufferpointer+=bytesize+4; + unsigned abs_sec=(int)time(0); + if(m_bufferpointer>9000 || abs_sec>m_abs_sec){ //send data if buffer full or timeout or link==9(sweep) + DataSenderIF::SendEvent(m_sendbuffer, m_bufferpointer); + m_abs_sec=abs_sec; + m_bufferpointer=0; + } +} +void PgpCosmicNwReceiver::resynch(){ + std::cout<<"Resynchronizing"<<std::endl; + int serstat; + serstat=SerialIF::sendCommand(4);//pause run + assert(serstat==0); + usleep(100000); + // set synch flags for everybody + for (int i=0;i<32;i++)m_linksynch[i]=true; + for (int i=0;i<32;i++)m_tossed[i]=0; + m_print=0; + //ECR/BCR + BitStream *bs=new BitStream; + BitStreamUtils::prependZeros(bs); + FEI3::FECommands::sendECR(bs); + FEI3::FECommands::sendBCR(bs); + SerialIF::send(bs,SerialIF::WAITFORDATA); + delete bs; + //clear send buffer + m_abs_sec=(unsigned int)time(0); + m_bufferpointer=0; + serstat=SerialIF::sendCommand(7);//resume run and post marker + assert(serstat==0); + std::cout<<"Resumed"<<std::endl; +} diff --git a/rce/rcecalib/dataproc/PgpCosmicNwReceiver.hh b/rce/rcecalib/dataproc/PgpCosmicNwReceiver.hh new file mode 100644 index 00000000..b76f877c --- /dev/null +++ b/rce/rcecalib/dataproc/PgpCosmicNwReceiver.hh @@ -0,0 +1,33 @@ +#ifndef PGPCOSMICNWRECEIVER_HH +#define PGPCOSMICNWRECEIVER_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "dataproc/AbsReceiver.hh" +#include "HW/Receiver.hh" +#include <iostream> + + +namespace eudaq{ + class DataSender; +} + +class PgpCosmicNwReceiver: public AbsReceiver, public PgpTrans::Receiver{ +public: + PgpCosmicNwReceiver(AbsDataHandler* handler, boost::property_tree::ptree* scanOptions); + virtual ~PgpCosmicNwReceiver(); + void receive(PgpTrans::PgpData *pgpdata); + void resynch(); +private: + unsigned* m_buffer; + unsigned m_counter; + bool m_linksynch[32]; + int m_tossed[32]; + int m_print; + eudaq::DataSender *m_ds; + unsigned char *m_sendbuffer; + int m_bufferpointer; + unsigned m_abs_sec; + unsigned m_bufferssend, m_senddiff; + unsigned m_oldl1, m_oldbx, m_firstbx, m_bad; +}; +#endif diff --git a/rce/rcecalib/dataproc/PgpCosmicReceiver.cc b/rce/rcecalib/dataproc/PgpCosmicReceiver.cc new file mode 100644 index 00000000..fdaaef91 --- /dev/null +++ b/rce/rcecalib/dataproc/PgpCosmicReceiver.cc @@ -0,0 +1,63 @@ +#include "rcecalib/dataproc/PgpCosmicReceiver.hh" +#include "rcecalib/HW/RCDImaster.hh" +#include <iostream> +#include "rcecalib/HW/Headers.hh" +#include "namespace_aliases.hh" + +PgpCosmicReceiver::PgpCosmicReceiver(AbsDataHandler* handler):AbsReceiver(handler),PgpTrans::Receiver(){ + PgpTrans::RCDImaster::instance()->setReceiver(this); + std::cout<<"Created pgp cosmic receiver"<<std::endl; + m_buffer=new unsigned[2048]; + m_counter=0; +} + +void PgpCosmicReceiver::receive(PgpTrans::PgpData *pgpdata){ + int link=pgpdata->header[2]&0xf; + if(link==9)return; + m_counter++; + //std::cout<<"Received data from link "<<link<<std::endl; + //printf("Link %d Payloadsize %d Headersize headerSize %d\n",link, payloadSize,headerSize); + unsigned size=pgpdata->payloadSize; + if (size==0)return; //typically handshake from serialization command + if(size>4096)std::cout<<"Large payload "<<size<<std::endl; + unsigned* data; + // if(link==10&&payloadSize!=0)std::cout<<"Channel 10 payloadsize= "<<payloadSize<<std::endl; + //if(link!=10){ + //data=(unsigned*)tds->header(); + //size=headerSize/sizeof(unsigned); + //for (int i=0;i<size;i++){ + //std::cout<<"Header "<<i<<": "<<std::hex<<data[i]<<std::dec<<", "; + //} + //std::cout<<std::endl; + //data=(unsigned*)tds->payload(); + //size=payloadSize/sizeof(unsigned)+ (payloadSize%4!=0); + //for (int i=0;i<size;i++){ + // std::cout<<"Data "<<i<<": "<<std::hex<<data[i]<<std::dec<<std::endl; + //} + //return; + data=pgpdata->payload; + bool marker=pgpdata->header[6]&0x80; + if(marker){ + link|=1<<4; + } + //std::cout<<"Payloadsize "<<payloadSize<<std::endl; + //unsigned char* payloadc=(unsigned char*)tds->payload(); +#ifdef SWAP_DATA + //byte swap data + unsigned* ptr = data; + unsigned* end = ptr+size; + unsigned *swapped=new(m_buffer) unsigned[size]; + unsigned *sw=swapped; + //for (int i=0;i<8;i++)std::cout<<std::hex<<header[i]<<std::endl; + while (ptr<end) { + unsigned tmp = *ptr; + *sw = (tmp<<16) | (tmp >>16); + ptr++; + sw++; + } + m_handler->handle(link,swapped,size); + #else + m_handler->handle(link,data,size); + //std::cout<<"Parsing done"<<std::endl; + #endif +} diff --git a/rce/rcecalib/dataproc/PgpCosmicReceiver.hh b/rce/rcecalib/dataproc/PgpCosmicReceiver.hh new file mode 100644 index 00000000..34bef068 --- /dev/null +++ b/rce/rcecalib/dataproc/PgpCosmicReceiver.hh @@ -0,0 +1,21 @@ +#ifndef PGPCOSMICRECEIVER_HH +#define PGPCOSMICRECEIVER_HH + +#include "rcecalib/dataproc/AbsReceiver.hh" +#include "rcecalib/HW/Receiver.hh" +#include <iostream> +#include "namespace_aliases.hh" + +class PgpCosmicReceiver: public AbsReceiver, public PgpTrans::Receiver{ +public: + PgpCosmicReceiver(AbsDataHandler* handler); + virtual ~PgpCosmicReceiver(){ + std::cout<<"Received "<<std::dec<<m_counter<<" buffers in previous run."<<std::endl; + delete [] m_buffer; + } + void receive(PgpTrans::PgpData *pgpdata); +private: + unsigned* m_buffer; + unsigned m_counter; +}; +#endif diff --git a/rce/rcecalib/dataproc/PgpReceiver.cc b/rce/rcecalib/dataproc/PgpReceiver.cc new file mode 100644 index 00000000..153b82df --- /dev/null +++ b/rce/rcecalib/dataproc/PgpReceiver.cc @@ -0,0 +1,54 @@ +#include "rcecalib/dataproc/PgpReceiver.hh" +#include "rcecalib/HW/RCDImaster.hh" +#include <iostream> +#include "rcecalib/HW/Headers.hh" +#include "namespace_aliases.hh" + +PgpReceiver::PgpReceiver(AbsDataHandler* handler):AbsReceiver(handler),PgpTrans::Receiver(){ + PgpTrans::RCDImaster::instance()->setReceiver(this); + std::cout<<"Created pgp receiver"<<std::endl; + m_buffer=new unsigned[2048]; + m_counter=0; + m_timer.Reset(); +} +PgpReceiver::~PgpReceiver(){ + delete [] m_buffer; + std::cout<<"Received "<<m_counter<<" buffers in previous run"<<std::endl; + // m_timer.Print("PgpReceiver"); +} + +void PgpReceiver::receive(PgpTrans::PgpData *pgpdata){ + //int link=0; + int link=pgpdata->header[2]&0xf; + //std::cout<<"Link is "<<link<<std::endl; + int size=pgpdata->payloadSize; + if (size==0)return; //handshake from serialization command + //printf("Payloadsize %d Headersize %d\n",pgpdata->payloadSize,pgpdata->headerSize); + unsigned* data; + data=pgpdata->payload; + +#ifdef SWAP_DATA + //byte swap data + #warning Data swapping turned on + unsigned* ptr = data; + unsigned* end = ptr+size; + unsigned *swapped=new(m_buffer) unsigned[size]; + unsigned *sw=swapped; + //for (int i=0;i<8;i++)std::cout<<std::hex<<header[i]<<std::endl; + while (ptr<end) { + unsigned tmp = *ptr; + *sw = (tmp<<16) | (tmp >>16); + //*ptr = (tmp<<16) | (tmp >>16); + ptr++; + sw++; + } + m_handler->handle(link,swapped,size); +#else + m_counter++; + //m_timer.Start(); + m_handler->handle(link,data,size); + //m_timer.Stop(); +#endif + + //std::cout<<"Parsing done"<<std::endl; +} diff --git a/rce/rcecalib/dataproc/PgpReceiver.hh b/rce/rcecalib/dataproc/PgpReceiver.hh new file mode 100644 index 00000000..19afbd7b --- /dev/null +++ b/rce/rcecalib/dataproc/PgpReceiver.hh @@ -0,0 +1,20 @@ +#ifndef PGPRECEIVER_HH +#define PGPRECEIVER_HH + +#include "rcecalib/dataproc/AbsReceiver.hh" +#include "rcecalib/HW/Receiver.hh" +#include "rcecalib/profiler/Profiler.hh" + + + +class PgpReceiver: public AbsReceiver, public PgpTrans::Receiver{ +public: + PgpReceiver(AbsDataHandler* handler); + virtual ~PgpReceiver(); + void receive(PgpTrans::PgpData* pgpdata); +private: + unsigned* m_buffer; + unsigned m_counter; + Profiler::Timer m_timer; +}; +#endif diff --git a/rce/rcecalib/dataproc/ProducerIF.hh b/rce/rcecalib/dataproc/ProducerIF.hh new file mode 100644 index 00000000..8696fe80 --- /dev/null +++ b/rce/rcecalib/dataproc/ProducerIF.hh @@ -0,0 +1,18 @@ +#ifndef PRODUCERIF_HH +#define PRODUCERIF_HH + +namespace eudaq{ + class Event; + class Producer; +} + +class ProducerIF{ +public: + static void SendEvent(eudaq::Event *ev); + static void setProducer(eudaq::Producer* producer); +private: + eudaq::Producer *m_producer; + +}; + +#endif diff --git a/rce/rcecalib/dataproc/RawFei4OccupancyDataProc.cc b/rce/rcecalib/dataproc/RawFei4OccupancyDataProc.cc new file mode 100644 index 00000000..b4511804 --- /dev/null +++ b/rce/rcecalib/dataproc/RawFei4OccupancyDataProc.cc @@ -0,0 +1,154 @@ +#include <stdio.h> +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/dataproc/RawFei4OccupancyDataProc.hh" +#include "rcecalib/config/ConfigIF.hh" +#include "rcecalib/config/FormattedRecord.hh" +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/dataproc/fit/FitFactory.cc" +#include "rcecalib/profiler/Profiler.hh" +#include "rcecalib/config/FEI4/FEI4ARecord.hh" + +int RawFei4OccupancyDataProc::fit(std::string fitfun) { + + FitFactory<char, char> dfac; //template parameters are the type of the histogram and error + std::cout << "Running: " << fitfun << std::endl; + if(fitfun.size()>=6 && fitfun.substr(0,6)=="SCURVE") { + // m_fit=dfac.createFit("ScurveLikelihoodFloat",m_configIF, m_histo_occ,m_vcal,m_nTrigger); + m_fit=dfac.createFit("ScurveLikelihoodFastInt",m_configIF, m_histo_occ,m_vcal,m_nTrigger); + int opt=0; + if(fitfun.size()>=13&&fitfun.substr(7,6)=="NOCONV")opt=AbsFit::NOCONV; + if(fitfun.size()>=12&&fitfun.substr(7,5)=="XTALK")opt=AbsFit::XTALK; + std::cout<<"Scurve option is "<<opt<<std::endl; + m_fit->doFit(opt); + } + return 0; +} + +int RawFei4OccupancyDataProc::processData(unsigned link, unsigned *buffer, int buflen){ + //m_timer.Start(); + if(m_counter++==0)usleep(1); + if(buflen==0)return 0; + int nL1A=0; + int module=m_linkToIndex[link]; + RceHisto2d<char, char>* histo=m_histo_occ[module][m_currentBin]; + unsigned char* bytepointer=(unsigned char*)buffer; + unsigned char* last=bytepointer+buflen*sizeof(unsigned)-3; + FEI4::FEI4ARecord rec; + while(bytepointer<=last){ + rec.setRecord(bytepointer); + if(rec.isData()){ //includes empty record type + //there are potentially 2 hits in one data record + //fprintf(m_flog, "%x\n", rec.getUnsigned()); + if(((rec.getTotBottom())>>1)!=0x7){ //above threshold + unsigned int row=rec.getRow()-1; + unsigned int col=rec.getColumn()-1; + if(row<N_ROW && col<N_COL) { + histo->incrementFast(row,col); + //std::cout<<"Hit at "<<row<<" "<<col<<std::endl; + } + } + if(((rec.getTotTop())>>1)!=0x7){ //above threshold + unsigned int row=rec.getRow(); + unsigned int col=rec.getColumn()-1; + if(row<N_ROW && col<N_COL) { + histo->incrementFast(row,col); + //std::cout<<"Hit at "<<row<<" "<<col<<std::endl; + } + } + } else if(rec.isDataHeader()){ + //fprintf(m_flog, "%x\n", rec.getUnsigned()); + nL1A++; + }else if(rec.isServiceRecord()){ + unsigned int moduleId=m_info[module].getId(); + //if(rec.getErrorCode()!=10 && (rec.getErrorCode()!=16 || (rec.getErrorCount()&0x200)) ) + printf("Service record FE %d . Error code: %d. Count: %d \n", moduleId, rec.getErrorCode(), rec.getErrorCount()); + if( rec.getErrorCode()<32)m_errhist[module]->fill(rec.getErrorCode(), rec.getErrorCount()); + //header=false; + }else if(rec.isValueRecord()){ //val rec without addr rec + // printf("Value record: %04x.\n",rec.getValue()); + }else if(rec.isAddressRecord()){ // address record + std::cout<<"FE "<<m_info[module].getId()<<": Address record for "; + if(rec.isGlobal())std::cout<<" global register "; + else std::cout<<" shift register "; + std::cout<<rec.getAddress()<<std::endl; + std::cout<<"This should not happen."<<std::endl; + }else{ + std::cout<<"FE "<<m_info[module].getId()<<": Unexpected record type: "<<std::hex<<rec.getUnsigned()<<std::dec<<std::endl; + //return FEI4::FEI4ARecord::BadRecord; + return 0; + } + bytepointer+=3; + } + //m_timer.Stop(); + return nL1A; +} + +RawFei4OccupancyDataProc::RawFei4OccupancyDataProc(ConfigIF* cif, boost::property_tree::ptree* scanOptions) + :AbsDataProc(cif),m_fit(0), m_counter(0) { + std::cout<<"Raw FEI4 Occupancy Data Proc"<<std::endl; + //m_flog=fopen("/nfs/dbg.txt","w"); + try{ //catch bad scan option parameters + m_nLoops = scanOptions->get<int>("nLoops"); + /* there is at least one parameter loop */ + /* TODO: fix in scan control */ + m_nPoints=1; + if(m_nLoops>0){ + m_nPoints=scanOptions->get<int>("scanLoop_0.nPoints"); + for(int i=0;i<m_nPoints;i++) { + char pointname[10]; + sprintf(pointname,"P_%d",i); + int vcal=scanOptions->get<int>(std::string("scanLoop_0.dataPoints.")+pointname); + //std::cout << "point vcal " << vcal << std::endl; + m_vcal.push_back(vcal); + } + } + m_nTrigger=scanOptions->get<int>("trigOpt.nEvents"); + + for (unsigned int module=0;module<m_configIF->getNmodules();module++){ + std::vector<RceHisto2d<char, char>* > vh; + m_histo_occ.push_back(vh); + char name[128]; + char title[128]; + RceHisto2d<char, char> *histo; + unsigned int cols=m_info[module].getNColumns()*m_info[module].getNFrontends(); + unsigned int rows=m_info[module].getNRows(); + unsigned int moduleId=m_info[module].getId(); + std::string moduleName=m_info[module].getName(); + /* retrieve scan points - Vcal steps in this case */ + sprintf(name, "Mod_%d_FEI4_Errors_Proc", moduleId); + sprintf(title, "Module %d at %s FEI4 Errors", moduleId, moduleName.c_str()); + m_errhist.push_back(new RceHisto1d<int, int>(name, title, 32, -.5, 31.5)); + std::cout<<"Creating Occupancy histograms."<<std::endl; + for (int point=0;point<m_nPoints;point++){ + sprintf(title,"OCCUPANCY Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_Occupancy_Point_%03d", moduleId,point); + histo=new RceHisto2d<char, char>(name,title,rows,0,rows,cols,0,cols, true); + if(m_info[module].getNFrontends()==1)histo->setAxisTitle(1,"Column"); + else histo->setAxisTitle(1,"FE*N_COL+Column"); + histo->setAxisTitle(0, "Row"); + m_histo_occ[module].push_back(histo); + } + } + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + ERS_ASSERT(0); + } + //m_timer.Reset(); +} + +RawFei4OccupancyDataProc::~RawFei4OccupancyDataProc(){ + //fclose(m_flog); + if(m_fit) delete m_fit; + for (size_t module=0;module<m_histo_occ.size();module++){ + delete m_errhist[module]; + for(size_t i=0;i<m_histo_occ[module].size();i++){ + delete m_histo_occ[module][i]; + } + } + + //m_timer.Print("RawFei4OccupancyDataProc"); +} + + diff --git a/rce/rcecalib/dataproc/RawFei4OccupancyDataProc.hh b/rce/rcecalib/dataproc/RawFei4OccupancyDataProc.hh new file mode 100644 index 00000000..52989c32 --- /dev/null +++ b/rce/rcecalib/dataproc/RawFei4OccupancyDataProc.hh @@ -0,0 +1,34 @@ +#ifndef RAWFEI4OCCUPANCYDATAPROC_HH +#define RAWFEI4OCCUPANCYDATAPROC_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/dataproc/AbsDataProc.hh" +#include "rcecalib/dataproc/fit/AbsFit.hh" +#include <vector> +#include "rcecalib/util/RceHisto2d.cc" +#include "rcecalib/util/RceHisto1d.cc" +#include "rcecalib/profiler/Profiler.hh" +#include <stdio.h> + +class RawFei4OccupancyDataProc: public AbsDataProc{ +public: + RawFei4OccupancyDataProc(ConfigIF* cif,boost::property_tree::ptree* scanOptions ); + virtual ~RawFei4OccupancyDataProc(); + int processData(unsigned link, unsigned *data, int size); + int fit(std::string fitfun); + +protected: + enum FEI4{N_ROW=336, N_COL=80}; + std::vector<std::vector<RceHisto2d<char, char>*> > m_histo_occ; + std::vector<RceHisto1d<int, int>*> m_errhist; + AbsFit *m_fit; + std::vector<int> m_vcal; + int m_nTrigger; + int m_nLoops; + int m_nPoints; + Profiler::Timer m_timer; + unsigned short m_counter; + //FILE* m_flog; +}; + +#endif diff --git a/rce/rcecalib/dataproc/RegularScanDataHandler.cc b/rce/rcecalib/dataproc/RegularScanDataHandler.cc new file mode 100644 index 00000000..f2842498 --- /dev/null +++ b/rce/rcecalib/dataproc/RegularScanDataHandler.cc @@ -0,0 +1,108 @@ +#include "rcecalib/dataproc/RegularScanDataHandler.hh" +#include "rcecalib/dataproc/AbsDataProc.hh" +#include "rcecalib/config/AbsFormatter.hh" +#include "rcecalib/config/ConfigIF.hh" +#include <boost/property_tree/ptree.hpp> +#include <iostream> +#include "rcecalib/profiler/Profiler.hh" +#include "rcecalib/util/DataCond.hh" + +RegularScanDataHandler::RegularScanDataHandler(AbsDataProc* dataproc, + DataCond& datacond, + ConfigIF* cif, + boost::property_tree::ptree* scanOptions) + :AbsDataHandler(dataproc, datacond, cif){ + m_nL1AperEv=scanOptions->get<int>("trigOpt.nL1AperEvent"); + int ntrigpergroup=scanOptions->get<int>("trigOpt.nTriggersPerGroup"); + if(ntrigpergroup!=0)m_nL1AperEv*=ntrigpergroup; + std::cout<<"Number of expected triggers is "<<m_nL1AperEv<<std::endl; + m_L1Acounters.clear(); + int maxlink=0; + m_nModules=m_configIF->getNmodules(); + for (int i=0;i<m_nModules;i++){ + m_L1Acounters.push_back(0); + if(m_configIF->getModuleInfo(i).getOutLink()>maxlink)maxlink=m_configIF->getModuleInfo(i).getOutLink(); + m_formatter.push_back(m_configIF->getModuleInfo(i).getFormatter()); + } + maxlink++; + m_linkToIndex=new int[maxlink]; + for (unsigned int i=0;i<m_configIF->getNmodules();i++){ + m_linkToIndex[m_configIF->getModuleInfo(i).getOutLink()]=i; + } + m_parsedData=new unsigned[16384]; + //m_timer.Reset(); +} + +RegularScanDataHandler::~RegularScanDataHandler(){ + delete [] m_parsedData; + delete [] m_linkToIndex; + // m_timer.Print("RegularScanDataHandler"); +} + +void RegularScanDataHandler::timeoutOccurred(){ + //print out which modules timed out + for (int i=0;i<m_nModules;i++){ + if (m_L1Acounters[i]<m_nL1AperEv){ + std::cout<<m_configIF->getModuleInfo(i).getId()<<std::endl; + } + } + resetL1counters(); +} + +void RegularScanDataHandler::resetL1counters(){ + assert(m_nModules==(int)m_L1Acounters.size()); + for (int i=0;i<m_nModules;i++){ + m_L1Acounters[i]=0; + } +} + +void RegularScanDataHandler::handle(unsigned link, unsigned *data, int size){ + // nL1A contains the number of L1A in the data chunk + //std::cout<<"Data from Link "<<link<<std::endl; + int nL1A=0; + int parsedsize=0; + int retval=m_formatter[m_linkToIndex[link]]->decode(data,size,m_parsedData, parsedsize, nL1A); + //std::cout<<"parser"<<retval<<" "<<size<<std::endl; + //if(size==448){ + if(retval!=0){ + std::cout<<"Parser error for link "<<link<<": Data size "<<size<<" number of triggers "<<nL1A<<std::endl; + // if(nL1A==16){ + for (int i=0;i<size;i++)std::cout<<std::hex<<data[i]<<std::endl; + std::cout<<std::dec; + // m_scan->pause(); + //} + } + if(parsedsize!=0){ + m_dataProc->processData(link, m_parsedData, parsedsize); + } + // std::cout<<nL1A<<" events."<<std::endl; + // std::cout<<"Expecting "<<m_nL1AperEv<<std::endl; + //for (int i=size-4;i<size;i++)std::cout<<std::hex<<data[i]<<std::endl; + //m_timer.Start(); + if(nL1A!=0){ + omni_mutex_lock ml(m_nL1Alock); + //assert(m_linkToIndex[link]<m_L1Acounters.size()); + m_L1Acounters[m_linkToIndex[link]]+=nL1A; + // std::cout<<m_L1Acounters[m_linkToIndex[link]]<<" events so far."<<std::endl; + bool done=true; + //check if the event is complete. + for (int i=0;i<m_nModules;i++){ + //assert(m_L1Acounters[i]<=m_nL1AperEv); + if(m_L1Acounters[i]>m_nL1AperEv)std::cout<<m_L1Acounters[i]<<" L1Atriggers"<<std::endl; + if (m_L1Acounters[i]<m_nL1AperEv){ + done=false; + break; + } + } + if(done==true){ + //std::cout<<"Restarting scan "<<std::endl; + resetL1counters(); + // Next trigger + // m_scan->stopWaiting(); + omni_mutex_lock pl( m_dataCond.mutex ); + if(m_dataCond.waitingForData==true)m_dataCond.cond.signal(); + else std::cout<<"Scan was not waiting for data!"<<std::endl; + } + } + //m_timer.Stop(); +} diff --git a/rce/rcecalib/dataproc/RegularScanDataHandler.hh b/rce/rcecalib/dataproc/RegularScanDataHandler.hh new file mode 100644 index 00000000..82199400 --- /dev/null +++ b/rce/rcecalib/dataproc/RegularScanDataHandler.hh @@ -0,0 +1,31 @@ +#ifndef REGULARSCANDATAHANDLER_HH +#define REGULARSCANDATAHANDLER_HH + +#include <vector> +#include <assert.h> + +#include "rcecalib/dataproc/AbsDataHandler.hh" +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/profiler/Profiler.hh" + +class AbsFormatter; +class DataCond; + +class RegularScanDataHandler: public AbsDataHandler{ +public: + RegularScanDataHandler(AbsDataProc* dataproc, DataCond& datacond, ConfigIF* cif, boost::property_tree::ptree* scanOptions); + virtual ~RegularScanDataHandler(); + void handle(unsigned link, unsigned* data, int size); + void timeoutOccurred(); + void resetL1counters(); +protected: + int m_nL1AperEv; + omni_mutex m_nL1Alock; + std::vector<int> m_L1Acounters; + int m_nModules; + int *m_linkToIndex; + unsigned *m_parsedData; + std::vector<AbsFormatter*> m_formatter; + Profiler::Timer m_timer; +}; +#endif diff --git a/rce/rcecalib/dataproc/RegularScanRawDataHandler.cc b/rce/rcecalib/dataproc/RegularScanRawDataHandler.cc new file mode 100644 index 00000000..03061b1e --- /dev/null +++ b/rce/rcecalib/dataproc/RegularScanRawDataHandler.cc @@ -0,0 +1,91 @@ +#include "rcecalib/dataproc/RegularScanRawDataHandler.hh" +#include "rcecalib/dataproc/AbsDataProc.hh" +#include "rcecalib/config/AbsFormatter.hh" +#include "rcecalib/config/ConfigIF.hh" +#include <boost/property_tree/ptree.hpp> +#include <iostream> +#include "rcecalib/profiler/Profiler.hh" +#include "rcecalib/util/DataCond.hh" + +RegularScanRawDataHandler::RegularScanRawDataHandler(AbsDataProc* dataproc, + DataCond& datacond, + ConfigIF* cif, + boost::property_tree::ptree* scanOptions) + :AbsDataHandler(dataproc, datacond, cif){ + std::cout<<"Regular raw data handler"<<std::endl; + m_nL1AperEv=scanOptions->get<int>("trigOpt.nL1AperEvent"); + int ntrigpergroup=scanOptions->get<int>("trigOpt.nTriggersPerGroup"); + if(ntrigpergroup!=0)m_nL1AperEv*=ntrigpergroup; + std::cout<<"Number of expected triggers is "<<m_nL1AperEv<<std::endl; + int maxlink=0; + m_nModules=m_configIF->getNmodules(); + m_L1Acounters=new int[m_nModules]; + resetL1counters(); + for (int i=0;i<m_nModules;i++){ + if(m_configIF->getModuleInfo(i).getOutLink()>maxlink)maxlink=m_configIF->getModuleInfo(i).getOutLink(); + } + maxlink++; + m_linkToIndex=new int[maxlink]; + for (unsigned int i=0;i<m_configIF->getNmodules();i++){ + m_linkToIndex[m_configIF->getModuleInfo(i).getOutLink()]=i; + } + //m_timer.Reset(); + m_counter=0; +} + +RegularScanRawDataHandler::~RegularScanRawDataHandler(){ + delete [] m_L1Acounters; + delete [] m_linkToIndex; + // m_timer.Print("RegularScanRawDataHandler"); +} + +void RegularScanRawDataHandler::timeoutOccurred(){ + //print out which modules timed out + for (int i=0;i<m_nModules;i++){ + if (m_L1Acounters[i]<m_nL1AperEv){ + std::cout<<m_configIF->getModuleInfo(i).getId()<<std::endl; + } + } + resetL1counters(); +} + +void RegularScanRawDataHandler::resetL1counters(){ + for (int i=0;i<m_nModules;i++){ + m_L1Acounters[i]=0; + } +} + +void RegularScanRawDataHandler::handle(unsigned link, unsigned *data, int size){ + // nL1A contains the number of L1A in the data chunk + //std::cout<<"Data from Link "<<link<<std::endl; + //m_timer.Start(); + int nL1A= m_dataProc->processData(link, data, size); + //if(nL1A==0){ + // std::cout<<"Size is "<<size<<std::endl; + // int msize=size>100? 100 : size; + // for(int a=0;a<msize;a++)printf("%08x\n",data[a]); + //} + //m_timer.Stop(); + //std::cout<<nL1A<<" events."<<std::endl; + // std::cout<<"Expecting "<<m_nL1AperEv<<std::endl; + //for (int i=size-4;i<size;i++)std::cout<<std::hex<<data[i]<<std::endl; + m_L1Acounters[m_linkToIndex[link]]+=nL1A; + // std::cout<<m_L1Acounters[m_linkToIndex[link]]<<" events so far."<<std::endl; + bool done=true; + //check if the event is complete. + for (int i=0;i<m_nModules;i++){ + //if(m_L1Acounters[i]>m_nL1AperEv)std::cout<<m_L1Acounters[i]<<" L1Atriggers"<<std::endl; + if (m_L1Acounters[i]<m_nL1AperEv){ + done=false; + break; + } + } + if(done){ + //std::cout<<"Restarting scan "<<std::endl; + resetL1counters(); + // Next trigger + omni_mutex_lock pl( m_dataCond.mutex ); + if(m_dataCond.waitingForData==true)m_dataCond.cond.signal(); + else std::cout<<"Scan was not waiting for data!"<<std::endl; + } +} diff --git a/rce/rcecalib/dataproc/RegularScanRawDataHandler.hh b/rce/rcecalib/dataproc/RegularScanRawDataHandler.hh new file mode 100644 index 00000000..6bef5f87 --- /dev/null +++ b/rce/rcecalib/dataproc/RegularScanRawDataHandler.hh @@ -0,0 +1,29 @@ +#ifndef REGULARSCANRAWDATAHANDLER_HH +#define REGULARSCANRAWDATAHANDLER_HH + +#include <omnithread.h> +#include <assert.h> + +#include "rcecalib/dataproc/AbsDataHandler.hh" +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/profiler/Profiler.hh" + +class AbsFormatter; +class DataCond; + +class RegularScanRawDataHandler: public AbsDataHandler{ +public: + RegularScanRawDataHandler(AbsDataProc* dataproc, DataCond& datacond, ConfigIF* cif, boost::property_tree::ptree* scanOptions); + virtual ~RegularScanRawDataHandler(); + inline void handle(unsigned link, unsigned* data, int size); + void timeoutOccurred(); + inline void resetL1counters(); +protected: + int m_nL1AperEv; + int* m_L1Acounters; + int m_nModules; + int *m_linkToIndex; + Profiler::Timer m_timer; + int m_counter; +}; +#endif diff --git a/rce/rcecalib/dataproc/SNDataProc.cc b/rce/rcecalib/dataproc/SNDataProc.cc new file mode 100644 index 00000000..68f55d4b --- /dev/null +++ b/rce/rcecalib/dataproc/SNDataProc.cc @@ -0,0 +1,82 @@ +#include <stdio.h> +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/dataproc/SNDataProc.hh" +#include "rcecalib/config/ConfigIF.hh" +#include "rcecalib/config/FormattedRecord.hh" +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/profiler/Profiler.hh" +#include "rcecalib/config/FEI4/FEI4BRecord.hh" + +int SNDataProc::fit(std::string fitfun) { + return 0; +} + +int SNDataProc::processData(unsigned link, unsigned *buffer, int buflen){ + //m_timer.Start(); + if(buflen==0)return 0; + int nL1A=0; + int module=m_linkToIndex[link]; + unsigned char* bytepointer=(unsigned char*)buffer; + unsigned char* last=bytepointer+buflen*sizeof(unsigned)-3; + FEI4::FEI4BRecord rec; + while(bytepointer<=last){ + rec.setRecord(bytepointer); + if(rec.isData()){ //includes empty record type + //should not happen + } else if(rec.isDataHeader()){ + //should not happen, either + }else if(rec.isServiceRecord()){ + //no service records + }else if(rec.isValueRecord()){ //val rec without addr rec + int value=rec.getValue(); + std::cout<<"Value record! Value="<<rec.getValue()<<std::endl; + m_histo_occ[module]->set(0, value); + nL1A++; + }else if(rec.isAddressRecord()){ // address record + // Ignore address records + //std::cout<<"FE "<<m_info[module].getId()<<": Address record for "; + //if(rec.isGlobal())std::cout<<" global register "; + //else std::cout<<" shift register "; + //std::cout<<rec.getAddress()<<std::endl; + //std::cout<<"This should not happen."<<std::endl; + }else{ + std::cout<<"FE "<<m_info[module].getId()<<": Unexpected record type: "<<std::hex<<rec.getUnsigned()<<std::dec<<std::endl; + //return FEI4::FEI4ARecord::BadRecord; + return 0; + } + bytepointer+=3; + } + //m_timer.Stop(); + return nL1A; +} + +SNDataProc::SNDataProc(ConfigIF* cif, boost::property_tree::ptree* scanOptions) + :AbsDataProc(cif) { + std::cout<<"SN Data Proc"<<std::endl; + try{ //catch bad scan option parameters + for (unsigned int module=0;module<m_configIF->getNmodules();module++){ + char name[128]; + char title[128]; + unsigned int moduleId=m_info[module].getId(); + std::string moduleName=m_info[module].getName(); + /* retrieve scan points - Vcal steps in this case */ + sprintf(name, "Mod_%d_SN", moduleId); + sprintf(title, "Module %d at %s Serial Number", moduleId, moduleName.c_str()); + m_histo_occ.push_back(new RceHisto1d<int, int>(name, title, 1, 0, 1)); + } + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + ERS_ASSERT(0); + } +} + +SNDataProc::~SNDataProc(){ + for (size_t module=0;module<m_histo_occ.size();module++){ + delete m_histo_occ[module]; + } + +} + + diff --git a/rce/rcecalib/dataproc/SNDataProc.hh b/rce/rcecalib/dataproc/SNDataProc.hh new file mode 100644 index 00000000..f178b346 --- /dev/null +++ b/rce/rcecalib/dataproc/SNDataProc.hh @@ -0,0 +1,21 @@ +#ifndef SNDATAPROC_HH +#define SNDATAPROC_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/dataproc/AbsDataProc.hh" +#include "rcecalib/dataproc/fit/AbsFit.hh" +#include <vector> +#include "rcecalib/util/RceHisto1d.cc" + +class SNDataProc: public AbsDataProc{ +public: + SNDataProc(ConfigIF* cif,boost::property_tree::ptree* scanOptions ); + virtual ~SNDataProc(); + int processData(unsigned link, unsigned *data, int size); + int fit(std::string fitfun); + +protected: + std::vector<RceHisto1d<int, int>*> m_histo_occ; +}; + +#endif diff --git a/rce/rcecalib/dataproc/SelftriggerDataProc.cc b/rce/rcecalib/dataproc/SelftriggerDataProc.cc new file mode 100644 index 00000000..c5c6d93a --- /dev/null +++ b/rce/rcecalib/dataproc/SelftriggerDataProc.cc @@ -0,0 +1,393 @@ +#include <stdio.h> +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/dataproc/SelftriggerDataProc.hh" +#include "rcecalib/config/ConfigIF.hh" +#include "rcecalib/config/FormattedRecord.hh" +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/util/RceName.hh" + +int SelftriggerDataProc::fit(std::string fitfun){ + if(m_file){ + std::cout<<"Closing file."<<std::endl; + m_file->close(); + } + return 0; +} + +int SelftriggerDataProc::processData(unsigned link, unsigned *data, int size){ + if(m_counter++==0)usleep(1); + if(m_link10DataOn && link==10){ + //std::cout<<"Found link=10 for Trigger data, moving on"<<std::endl; + unsigned trgtime1=data[3]; + unsigned trgtime2=data[4]; + m_trgtime=trgtime1; + m_trgtime=(m_trgtime<<32) | trgtime2; + + unsigned int link10_l1id = ((data[0]>>24)&0xf); + + if(!m_trgtime_initial_set){ + m_trgtime_initial_set=true; + m_trgtime_initial=m_trgtime; + } + + int trigtimeDiff = (m_trgtime&0xff) - (m_trgtime_initial&0xff); + if(trigtimeDiff<0) trigtimeDiff+=256; + + m_trigtimeDiff_index_l1id[link10_l1id]= trigtimeDiff; + m_trigtime_index_l1id[link10_l1id]= (m_trgtime); + return 0; + } + + // std::cout<<"Process data"<<std::endl; + for (int i=0;i<size;i++) + { + int module=m_linkToIndex[link]; + FormattedRecord current(data[i]); + + if (current.isHeader()) + { + m_l1id[module] = current.getL1id(); + m_bcid[module] = current.getBxid(); + //printf("bcid : %x \n", bcid); + //printf("module %d l1id : %x \n", module, m_l1id[module]); + + if(m_link10DataOn && !m_bcid_initial_set[module]){ + m_bcid_initial_set[module]=true; + m_bcid_initial[module]=m_bcid[module]; + } + + if (m_l1id[module] != m_l1id_last[module]) + { + if(m_l1id_last[module]==0xffffffff) + //std::cout<<"Initial L1ID: m_l1id="<<m_l1id[module]<<" "<< (m_l1id[module]&0xf) <<" m_l1id_last="<<m_l1id_last[module]<<" "<<(m_l1id_last[module]&0xf)<<std::endl; + + if(m_l1id_last[module]!=0xffffffff){ + ///l1id skipping //// + int l1idDiff = (m_l1id[module]&0xf) - (m_l1id_last[module]&0xf); + if(l1idDiff<0) l1idDiff+=16; + if(l1idDiff!=1){ + //std::cout<<"L1ID Skip: m_l1id="<<m_l1id[module]<<" "<< (m_l1id[module]&0xf) <<" m_l1id_last="<<m_l1id_last[module]<<" "<<(m_l1id_last[module]&0xf)<<" l1idDiff="<<l1idDiff<<std::endl; + m_histo_l1idDiff[module]->increment(l1idDiff); + } + ///////////////////// + + + if(m_totev[module]>31) + m_totev[module]=31; //last bin is overflow + if(m_nhit[module]>15) + m_nhit[module]=15; //last bin is overflow + m_histo_totev[module]->increment(m_totev[module]); + m_histo_nhit[module]->increment(m_nhit[module]); + m_totev[module]=0; + m_nhit[module]=0; + + // Cluster Magic + m_cluster_proc[module].clusterize(); + } + m_l1id_last[module] = m_l1id[module]; + m_bcid_ref[module] = m_bcid[module]; + m_l1idchanged[module]=1; + + + //BCID skipping////////// + if(false&&m_link10DataOn) + { + int module_BCID_diff = (m_bcid_ref[module]&0xff) - (m_bcid_initial[module]&0xff); + if(module_BCID_diff<0) module_BCID_diff+=256; + + m_bcidDiff_index_l1id_vs_module[ m_l1id[module]&0xf ][module] = module_BCID_diff; + m_bcidDiff_index_l1id_vs_module_isSet[ m_l1id[module]&0xf ][module] = true; + + //check if all datat for event has arrived + bool all_arrived = true; + for(unsigned int imod=0; imod<nmod; imod++){ + all_arrived = all_arrived && m_bcidDiff_index_l1id_vs_module_isSet[ m_l1id[module]&0xf ][imod]; + } + if(all_arrived){ + for(unsigned int imod=0; imod<nmod; imod++){ + int event_diff = (m_bcidDiff_index_l1id_vs_module[ m_l1id[module]&0xf ][imod] & 0xff) - (m_trigtimeDiff_index_l1id[ m_l1id[module]&0xf ] & 0xff); + if(event_diff < 0) event_diff += 256; + + //if diff found, fill histo, and reset initial diff for module + if(event_diff>0){ + //std::cout<<"event "<< n_evt_skip<<" L1ID="<<(m_l1id[module]&0xf)<<" EVENT DIFF="<<event_diff<<" Mod="<<imod<<" BCID diff="<< (m_bcidDiff_index_l1id_vs_module[ m_l1id[module]&0xf ][imod] & 0xff )<<" BCID="<<(m_bcid_ref[module]&0xff)<<" BCID init="<<(m_bcid_initial[module]& 0xff)<<" Trig time="<< (m_trigtime_index_l1id[ m_l1id[module]&0xf ] & 0xff)<<" Trig diff="<< (m_trigtimeDiff_index_l1id[ m_l1id[module]&0xf ] & 0xff )<<" Trig init="<<(m_trgtime_initial & 0xff)<<std::endl; + + m_histo_bcidDiff[imod]->increment(event_diff); + + m_bcid_initial[imod] = ( (m_bcid_initial[imod] + (event_diff & 0xff)) & 0xff ); + + } + + m_bcidDiff_index_l1id_vs_module_isSet[ m_l1id[module]&0xf ][imod] = false; + } + } + } + //end BCID skipping///////// + + }//end L1ID != last L1ID + + if(m_bcid[module]>=m_bcid_ref[module]) + m_bcid[module] = m_bcid[module]-m_bcid_ref[module]; + else + m_bcid[module] = m_bcid[module] + (0xff - (0xff&m_bcid_ref[module]) ) ; //BCID counter rollover + + // printf("bcidafter : %x \n", bcid); + + }//end header check + else if (current.isData()) + { + unsigned int chip=current.getFE(); + unsigned int tot=current.getToT(); + unsigned int col=current.getCol(); + unsigned int row=current.getRow(); + if(m_file){ + if(m_l1idchanged[module]==1){ + m_l1idchanged[module]=0; + m_hiteventid[module]++; + } + unsigned word=((link&0xf)<<28)|((m_l1id[module]&0xf)<<24)|(tot<<16)|(row<<7)|col; + m_file->write((char*)&word, 4); + } + //printf("Hit col=%d row=%d tot=%d\n",col, row, tot); + + m_histo_occ[module]->increment(chip*m_info[module].getNColumns()+col,row); + m_histo_tot2d[module]->fill(chip*m_info[module].getNColumns()+col,row, tot); + m_histo_tot[module]->increment(tot); + m_histo_timing[module]->increment(m_bcid[module]); + m_totev[module]+=tot; + m_nhit[module]++; + + // Clustering (exclude ToT 14 hits) + m_cluster_proc[module].addHit(col, row, tot, m_bcid[module]); + + //printf("bcidafter : %x \n", bcid); + }//end data check + }//end for loop + return 0; +} + +SelftriggerDataProc::SelftriggerDataProc(ConfigIF* cif, boost::property_tree::ptree* scanOptions) + :AbsDataProc(cif), m_file(0), m_counter(0){ + + nmod=m_configIF->getNmodules(); + m_l1id_last = new unsigned int[nmod]; + m_l1id = new unsigned int[nmod]; + m_bcid_ref = new unsigned int[nmod]; + m_bcid = new unsigned int[nmod]; + m_totev=new int[nmod]; + m_nhit=new int[nmod]; + + + m_hiteventid = new unsigned int[nmod]; + m_l1idchanged = new unsigned int[nmod]; + + ///BCID skipping + m_link10DataOn = (bool) scanOptions->get<int>("trigOpt.triggerDataOn"); + + if(m_link10DataOn) + { + m_bcid_initial_set = new bool[nmod]; + m_bcid_initial = new unsigned int[nmod]; + + m_trgtime_initial_set=false; + m_trgtime_initial=(unsigned long long)(-1); + + + m_bcidDiff_index_l1id_vs_module = new unsigned int*[16]; + m_bcidDiff_index_l1id_vs_module_isSet = new bool*[16]; + for (int i=0;i<16;i++){ + m_bcidDiff_index_l1id_vs_module[i] = new unsigned int[nmod]; + m_bcidDiff_index_l1id_vs_module_isSet[i] = new bool[nmod]; + + for(unsigned int j=0; j<nmod; j++) + m_bcidDiff_index_l1id_vs_module_isSet[i][j] = false; + } + m_trigtimeDiff_index_l1id = new unsigned long long[16]; + m_trigtime_index_l1id = new unsigned long long[16]; + } + //// + + + m_cluster_proc = new ClusterProc[nmod]; + + try{ + std::string name=scanOptions->get<std::string>("Name"); + if(name!="Scan"){ + if(name.find("RUNNUM")!=std::string::npos){ //replace RUNNUM macro with run number + char runns[12]; + sprintf(runns, "%06d", scanOptions->get<int>("runNumber")); + name.replace(name.find("RUNNUM"), 6, runns); + } + std::string path="/nfs/"; + char rcename[32]; + sprintf(rcename, "_RCE_%d.", RceName::getRceNumber()); + if(name.find(".")!=std::string::npos){ + name.replace(name.find("."), 1, rcename); + }else{ + name+=rcename; + } + path+=name; + std::cout<<"Opening file "<<path<<std::endl; + m_file=new std::ofstream(path.c_str(), std::ios::binary); + } + for (unsigned int module=0;module<nmod;module++){ + m_l1id_last[module] = 0xffffffff; + m_l1id[module] = 0; + m_bcid_ref[module] = 0; + m_bcid[module] = 0; + m_totev[module] = 0; + m_nhit[module] = 0; + + m_hiteventid[module]=0; + m_l1idchanged[module]=0; + + if(m_link10DataOn){ + m_bcid_initial_set[module]=false; + m_bcid_initial[module]=0xffffffff; + } + + char name[128]; + char title[128]; + RceHisto2d<int, int> *histo; + RceHisto1d<int, int> *histoTot; + unsigned int cols=m_info[module].getNColumns()*m_info[module].getNFrontends(); + unsigned int rows=m_info[module].getNRows(); + unsigned int moduleId=m_info[module].getId(); + std::string moduleName=m_info[module].getName(); + + /* retrieve scan points - Vcal steps in this case */ + std::cout<<"Creating Occupancy histograms."<<std::endl; + std::cout<<"Creating ToT spectrum histograms."<<std::endl; + + sprintf(title,"OCCUPANCY Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_Selftrigger_Occupancy",moduleId); + histo=new RceHisto2d<int, int>(name,title,cols,0,cols,rows,0,rows); + if(m_info[module].getNFrontends()==1)histo->setAxisTitle(0,"Column"); + else histo->setAxisTitle(0,"FE*N_COL+Column"); + histo->setAxisTitle(1, "Row"); + m_histo_occ.push_back(histo); + + sprintf(title,"ToT 2d Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_Selftrigger_Occupancy_2d",moduleId); + histo=new RceHisto2d<int, int>(name,title,cols,0,cols,rows,0,rows); + if(m_info[module].getNFrontends()==1)histo->setAxisTitle(0,"Column"); + else histo->setAxisTitle(0,"FE*N_COL+Column"); + histo->setAxisTitle(1, "Row"); + m_histo_tot2d.push_back(histo); + + sprintf(title,"ToT Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_Selftrigger_ToT",moduleId); + histoTot=new RceHisto1d<int, int>(name,title,16,-.5,15.5); + histoTot->setAxisTitle(0,"ToT"); + m_histo_tot.push_back(histoTot); + + sprintf(title,"ToT per event Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_Selftrigger_ToT_event",moduleId); + histoTot=new RceHisto1d<int, int>(name,title,32,-.5,31.5); + histoTot->setAxisTitle(0,"ToT"); + m_histo_totev.push_back(histoTot); + + sprintf(title,"Number of hits per event Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_Selftrigger_nhits",moduleId); + histoTot=new RceHisto1d<int, int>(name,title,16,-.5,15.5); + histoTot->setAxisTitle(0,"Number of hits"); + m_histo_nhit.push_back(histoTot); + + sprintf(title,"Timing of bunch per event Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_Selftrigger_timing",moduleId); + histoTot=new RceHisto1d<int, int>(name,title,16,-.5,15.5); + histoTot->setAxisTitle(0,"Hit timing"); + m_histo_timing.push_back(histoTot); + + sprintf(title,"Hits per cluster Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_Selftrigger_nhits_cluster",moduleId); + histoTot=new RceHisto1d<int, int>(name,title,20,-.5,19.5); + histoTot->setAxisTitle(0,"Hits per cluster"); + m_histo_nhits_cluster.push_back(histoTot) ; + m_cluster_proc[module].assignHitHisto(histoTot); + + sprintf(title,"Clustered ToT Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_Selftrigger_tot_cluster",moduleId); + histoTot=new RceHisto1d<int, int>(name,title,32,-.5,31.5); + histoTot->setAxisTitle(0,"Clustered ToT"); + m_histo_tot_cluster.push_back(histoTot) ; + m_cluster_proc[module].assignToTHisto(histoTot); + + sprintf(title,"Clustered ToT per Cluster Size Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_Selftrigger_tot_per_clustersize",moduleId); + histo=new RceHisto2d<int, int>(name,title,32,-.5,31.5,20,-.5,19.5); + histo->setAxisTitle(0,"Clustered ToT"); + histo->setAxisTitle(1,"Cluster Size"); + m_histo_tot_size.push_back(histo); + m_cluster_proc[module].assignToTClusterSizeHisto(histo); + + sprintf(title,"L1ID difference per event Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_Selftrigger_L1IDdiff",moduleId); + histoTot=new RceHisto1d<int, int>(name,title,16,-0.5,15.5); + histoTot->setAxisTitle(0,"L1ID difference"); + m_histo_l1idDiff.push_back(histoTot); + + if(m_link10DataOn) + { + sprintf(title,"BCID difference per event Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_Selftrigger_BCIDdiff",moduleId); + histoTot=new RceHisto1d<int, int>(name,title,256,-0.5,255.5); + histoTot->setAxisTitle(0,"BCID difference"); + m_histo_bcidDiff.push_back(histoTot); + } + + } + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + ERS_ASSERT(0); + } +} + +SelftriggerDataProc::~SelftriggerDataProc(){ + delete m_file; + for (size_t module=0;module<m_histo_tot.size();module++){ + delete m_histo_tot[module]; + delete m_histo_totev[module]; + delete m_histo_nhit[module]; + delete m_histo_occ[module]; + delete m_histo_tot2d[module]; + delete m_histo_timing[module]; + delete m_histo_tot_cluster[module]; + delete m_histo_nhits_cluster[module]; + delete m_histo_tot_size[module]; + delete m_histo_l1idDiff[module]; + if(m_link10DataOn) + delete m_histo_bcidDiff[module]; + } + delete [] m_totev; + delete [] m_nhit; + delete [] m_bcid_ref; + delete [] m_bcid; + delete [] m_l1id_last; + delete [] m_l1id; + delete [] m_cluster_proc; + + + delete [] m_l1idchanged; + delete [] m_hiteventid; + + if(m_link10DataOn) + { + delete [] m_bcid_initial_set; + delete [] m_bcid_initial; + + for (int i=0;i<16;i++){ + delete [] m_bcidDiff_index_l1id_vs_module[i]; + delete [] m_bcidDiff_index_l1id_vs_module_isSet[i]; + } + delete [] m_bcidDiff_index_l1id_vs_module; + delete [] m_bcidDiff_index_l1id_vs_module_isSet; + + delete [] m_trigtimeDiff_index_l1id; + delete [] m_trigtime_index_l1id; + } +} + + diff --git a/rce/rcecalib/dataproc/SelftriggerDataProc.hh b/rce/rcecalib/dataproc/SelftriggerDataProc.hh new file mode 100644 index 00000000..0a46eaf5 --- /dev/null +++ b/rce/rcecalib/dataproc/SelftriggerDataProc.hh @@ -0,0 +1,70 @@ +#ifndef SELFTRIGGERDATAPROC_HH +#define SELFTRIGGERDATAPROC_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/dataproc/AbsDataProc.hh" +#include "rcecalib/dataproc/fit/AbsFit.hh" +#include "rcecalib/dataproc/ClusterProc.hh" +#include <vector> +#include "rcecalib/util/RceHisto2d.cc" +#include "rcecalib/util/RceHisto1d.cc" +#include <fstream> + +class SelftriggerDataProc: public AbsDataProc{ +public: + SelftriggerDataProc(ConfigIF* cif,boost::property_tree::ptree* scanOptions ); + virtual ~SelftriggerDataProc(); + int processData(unsigned link, unsigned *data, int size); + int fit(std::string fitfun); + +protected: + + std::vector<RceHisto2d<int, int>*> m_histo_occ; + std::vector<RceHisto2d<int, int>*> m_histo_tot2d; + std::vector<RceHisto1d<int, int>*> m_histo_tot; + std::vector<RceHisto1d<int, int>*> m_histo_nhit; + std::vector<RceHisto1d<int, int>*> m_histo_totev; + std::vector<RceHisto1d<int, int>*> m_histo_timing; + std::vector<RceHisto1d<int, int>*> m_histo_nhits_cluster; + std::vector<RceHisto1d<int, int>*> m_histo_tot_cluster; + std::vector<RceHisto2d<int, int>*> m_histo_tot_size; + std::vector<RceHisto1d<int, int>*> m_histo_bcidDiff; + std::vector<RceHisto1d<int, int>*> m_histo_l1idDiff; + + + //unsigned int m_bcid_ref; + //unsigned int m_bcid; + unsigned int* m_bcid_ref; + unsigned int* m_bcid; + unsigned int* m_l1id; + unsigned int* m_l1id_last; + int *m_totev, *m_nhit; + std::ofstream* m_file; + //bool m_occ, m_tot, m_bcid; + unsigned short m_counter; + + //BCID skipping stuff + bool* m_bcid_initial_set; + unsigned int* m_bcid_initial; + unsigned int* m_hiteventid; + unsigned int* m_l1idchanged; + + unsigned long long m_trgtime; //BCID coming from link-10 (tig info link) + bool m_trgtime_initial_set; + unsigned long long m_trgtime_initial; + + unsigned int ** m_bcidDiff_index_l1id_vs_module; + bool ** m_bcidDiff_index_l1id_vs_module_isSet; + + unsigned long long * m_trigtimeDiff_index_l1id; + unsigned long long * m_trigtime_index_l1id; + + unsigned int nmod; + + bool m_link10DataOn; + + // Clustering + ClusterProc *m_cluster_proc; +}; + +#endif diff --git a/rce/rcecalib/dataproc/SimpleDataHandler.hh b/rce/rcecalib/dataproc/SimpleDataHandler.hh new file mode 100644 index 00000000..447ed84d --- /dev/null +++ b/rce/rcecalib/dataproc/SimpleDataHandler.hh @@ -0,0 +1,24 @@ +#ifndef SIMPLEDATAHANDLER_HH +#define SIMPLEDATAHANDLER_HH + +#include "rcecalib/dataproc/AbsDataHandler.hh" +#include "rcecalib/util/DataCond.hh" + +class SimpleDataHandler:public AbsDataHandler{ +public: + SimpleDataHandler(AbsDataProc* proc, DataCond& datacond): + AbsDataHandler(proc, datacond, 0){ + } + virtual ~SimpleDataHandler(){ + } + void handle(unsigned link, unsigned* data, int size) { + if(size>0){ + m_dataProc->processData(link, data, size); + } + //m_scan->stopWaiting(); + omni_mutex_lock pl( m_dataCond.mutex ); + if(m_dataCond.waitingForData==true)m_dataCond.cond.signal(); + }; + +}; +#endif diff --git a/rce/rcecalib/dataproc/SimpleReceiver.cc b/rce/rcecalib/dataproc/SimpleReceiver.cc new file mode 100644 index 00000000..adf6bd35 --- /dev/null +++ b/rce/rcecalib/dataproc/SimpleReceiver.cc @@ -0,0 +1,6 @@ +#include "rcecalib/dataproc/SimpleReceiver.hh" + +void SimpleReceiver::Receive(unsigned *data, int size){ + m_handler->handle(0, data,size); + return; +} diff --git a/rce/rcecalib/dataproc/SimpleReceiver.hh b/rce/rcecalib/dataproc/SimpleReceiver.hh new file mode 100644 index 00000000..4509c837 --- /dev/null +++ b/rce/rcecalib/dataproc/SimpleReceiver.hh @@ -0,0 +1,12 @@ +#ifndef SIMPLERECEIVER_HH +#define SIMPLERECEIVER_HH + +#include "rcecalib/dataproc/AbsReceiver.hh" +#include "rcecalib/config/TriggerReceiverIF.hh" + +class SimpleReceiver: public AbsReceiver, public TriggerReceiverIF{ +public: + SimpleReceiver(AbsDataHandler* handler):AbsReceiver(handler), TriggerReceiverIF(){} + void Receive(unsigned *data, int size); +}; +#endif diff --git a/rce/rcecalib/dataproc/TemperatureDataProc.cc b/rce/rcecalib/dataproc/TemperatureDataProc.cc new file mode 100644 index 00000000..7a62c7fa --- /dev/null +++ b/rce/rcecalib/dataproc/TemperatureDataProc.cc @@ -0,0 +1,132 @@ +#include <stdio.h> +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/dataproc/TemperatureDataProc.hh" +#include "rcecalib/config/ConfigIF.hh" +#include "rcecalib/config/FormattedRecord.hh" +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/profiler/Profiler.hh" +#include "rcecalib/config/FEI4/FEI4BRecord.hh" + +int TemperatureDataProc::fit(std::string fitfun) { + std::cout << "Running: " << fitfun << std::endl; + if(fitfun=="NORMALIZE") { + for (unsigned int module=0;module<m_configIF->getNmodules();module++){ + for(int j=0;j<m_nPoints;j++){ + float n=(float)(*m_histo_occ[module])(j); + float mean=0; + if(n>0)mean=(float)(*m_histo_adc[module])(j)/n; + m_histo_norm[module]->set(j, mean); + float err=0; + if(n>0)err=((*m_histo_adc2[module])(j)/n-mean*mean)/n; //error^2 on mean + if(err<0)err=0; //prevent rounding errors + m_histo_norm[module]->setBinError(j, err); + // std::cout<<"Bin content is "<<(*m_histo[module][i])(j)<<std::endl; + //std::cout<<"Bin error is "<<m_histo[module][i]->getBinError(j)<<std::endl; + } + } + } + return 0; +} + +int TemperatureDataProc::processData(unsigned link, unsigned *buffer, int buflen){ + //m_timer.Start(); + if(buflen==0)return 0; + int nL1A=0; + int module=m_linkToIndex[link]; + unsigned char* bytepointer=(unsigned char*)buffer; + unsigned char* last=bytepointer+buflen*sizeof(unsigned)-3; + FEI4::FEI4BRecord rec; + while(bytepointer<=last){ + rec.setRecord(bytepointer); + if(rec.isData()){ //includes empty record type + //should not happen + } else if(rec.isDataHeader()){ + //should not happen, either + }else if(rec.isServiceRecord()){ + //no service records + }else if(rec.isValueRecord()){ //val rec without addr rec + int value=rec.getValue()>>4; + //std::cout<<"Link "<<link<<" value record! Value="<<std::hex<<rec.getValue()<<std::dec<<std::endl; + m_histo_occ[module]->increment(m_currentBin); + m_histo_adc[module]->fill(m_currentBin, value); + m_histo_adc2[module]->fill(m_currentBin, value*value); + nL1A++; + }else if(rec.isAddressRecord()){ // address record + // Ignore address records + //std::cout<<"FE "<<m_info[module].getId()<<": Address record for "; + //if(rec.isGlobal())std::cout<<" global register "; + //else std::cout<<" shift register "; + //std::cout<<rec.getAddress()<<std::endl; + //std::cout<<"This should not happen."<<std::endl; + }else{ + std::cout<<"FE "<<m_info[module].getId()<<": Unexpected record type: "<<std::hex<<rec.getUnsigned()<<std::dec<<std::endl; + //return FEI4::FEI4ARecord::BadRecord; + return 0; + } + bytepointer+=3; + } + //m_timer.Stop(); + return nL1A; +} + +TemperatureDataProc::TemperatureDataProc(ConfigIF* cif, boost::property_tree::ptree* scanOptions) + :AbsDataProc(cif),m_fit(0) { + std::cout<<"Temperature Data Proc"<<std::endl; + try{ //catch bad scan option parameters + m_nLoops = scanOptions->get<int>("nLoops"); + /* there is at least one parameter loop */ + m_nPoints=1; + if(m_nLoops>0){ + m_nPoints=scanOptions->get<int>("scanLoop_0.nPoints"); + for(int i=0;i<m_nPoints;i++) { + char pointname[10]; + sprintf(pointname,"P_%d",i); + int vcal=scanOptions->get<int>(std::string("scanLoop_0.dataPoints.")+pointname); + //std::cout << "point vcal " << vcal << std::endl; + m_vcal.push_back(vcal); + } + } + m_nTrigger=scanOptions->get<int>("trigOpt.nEvents"); + + for (unsigned int module=0;module<m_configIF->getNmodules();module++){ + char name[128]; + char title[128]; + unsigned int moduleId=m_info[module].getId(); + std::string moduleName=m_info[module].getName(); + /* retrieve scan points - Vcal steps in this case */ + sprintf(name, "Mod_%d_nEvents", moduleId); + sprintf(title, "Module %d at %s Number of events", moduleId, moduleName.c_str()); + m_histo_occ.push_back(new RceHisto1d<int, int>(name, title, m_nPoints, 0, m_nPoints)); + m_histo_occ.back()->setAxisTitle(0, "Set point"); + sprintf(name, "Mod_%d_ADC", moduleId); + sprintf(title, "Module %d at %s ADC", moduleId, moduleName.c_str()); + m_histo_adc.push_back(new RceHisto1d<int, int>(name, title, m_nPoints, 0, m_nPoints)); + m_histo_adc.back()->setAxisTitle(0, "Set point"); + sprintf(name, "Mod_%d_ADC2", moduleId); + sprintf(title, "Module %d at %s ADC^2", moduleId, moduleName.c_str()); + m_histo_adc2.push_back(new RceHisto1d<int, int>(name, title, m_nPoints, 0, m_nPoints)); + m_histo_adc2.back()->setAxisTitle(0, "Set point"); + sprintf(name, "Mod_%d_Voltage", moduleId); + sprintf(title, "Module %d at %s Voltage", moduleId, moduleName.c_str()); + m_histo_norm.push_back(new RceHisto1d<float, float>(name, title, m_nPoints, 0, m_nPoints, true)); + m_histo_norm.back()->setAxisTitle(0, "Set point"); + } + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + ERS_ASSERT(0); + } +} + +TemperatureDataProc::~TemperatureDataProc(){ + for (size_t module=0;module<m_histo_occ.size();module++){ + delete m_histo_occ[module]; + delete m_histo_adc[module]; + delete m_histo_adc2[module]; + delete m_histo_norm[module]; + } + +} + + diff --git a/rce/rcecalib/dataproc/TemperatureDataProc.hh b/rce/rcecalib/dataproc/TemperatureDataProc.hh new file mode 100644 index 00000000..4cb1d264 --- /dev/null +++ b/rce/rcecalib/dataproc/TemperatureDataProc.hh @@ -0,0 +1,29 @@ +#ifndef TEMPERATUREDATAPROC_HH +#define TEMPERATUREDATAPROC_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/dataproc/AbsDataProc.hh" +#include "rcecalib/dataproc/fit/AbsFit.hh" +#include <vector> +#include "rcecalib/util/RceHisto1d.cc" + +class TemperatureDataProc: public AbsDataProc{ +public: + TemperatureDataProc(ConfigIF* cif,boost::property_tree::ptree* scanOptions ); + virtual ~TemperatureDataProc(); + int processData(unsigned link, unsigned *data, int size); + int fit(std::string fitfun); + +protected: + std::vector<RceHisto1d<int, int>*> m_histo_occ; + std::vector<RceHisto1d<int, int>*> m_histo_adc; + std::vector<RceHisto1d<int, int>*> m_histo_adc2; + std::vector<RceHisto1d<float, float>*> m_histo_norm; + AbsFit *m_fit; + std::vector<int> m_vcal; + int m_nTrigger; + int m_nLoops; + int m_nPoints; +}; + +#endif diff --git a/rce/rcecalib/dataproc/TotCalibDataProc.cc b/rce/rcecalib/dataproc/TotCalibDataProc.cc new file mode 100644 index 00000000..a153349c --- /dev/null +++ b/rce/rcecalib/dataproc/TotCalibDataProc.cc @@ -0,0 +1,79 @@ +#include <stdio.h> +#include <boost/property_tree/ptree.hpp> +#include "dataproc/TotCalibDataProc.hh" +#include "config/ConfigIF.hh" +#include "config/FormattedRecord.hh" +#include "dataproc/fit/CalculateMeanSigma.cc" + +int TotCalibDataProc::fit(std::string fitfun) { +#ifdef RCEPIXLIB + std::cout << "Running: " << fitfun << std::endl; + // if(fitfun=="CALCULATE_MEAN_SIGMA" && m_nPoints!=0) { + // calculateMeanSigma(m_histo_occ, m_histo_tot, m_histo_tot2, m_histo_tot_mean, m_histo_tot_sigma); + } +#endif + return 0; +} + +int TotCalibDataProc::processData(unsigned link, unsigned *data, int size){ + // std::cout<<"Process data"<<std::endl; + for (int i=0;i<size;i++){ + int module=m_linkToIndex[link]; // will be different when parser is fully there + FormattedRecord current(data[i]); + // if (current.isHeader()){ + // l1id = current.getL1id(); + // bcid = current.getBxid(); + //printf("bcid : %x \n", bcid); + //printf("l1id : %x \n", l1id); + // if (l1id != l1id_last) + //{ + // l1id_last = l1id; + // bcid_ref = bcid; + //} + // bcid = bcid-bcid_ref; + // printf("bcidafter : %x \n", bcid); + //} + if (current.isData()){ + unsigned int tot=current.getToT(); + unsigned int col=current.getCol(); + unsigned int row=current.getRow(); + if((row<(unsigned)m_info[module].getNRows()) && (col<(unsigned)m_info[module].getNColumns()) && tot<15 && tot!=0) { + m_histo_tot[module][tot-1]->incrementFast(col,row); + } + } + } + return 0; +} + +TotCalibDataProc::TotCalibDataProc(ConfigIF* cif, boost::property_tree::ptree* scanOptions) + :AbsDataProc(cif) { + + for (unsigned int module=0;module<m_configIF->getNmodules();module++){ + std::vector<RceHisto2d<char, char>* > vhcc; + m_histo_tot.push_back(vhcc); + char name[128]; + char title[128]; + RceHisto2d<char, char> *histoc; + unsigned int cols=m_info[module].getNColumns()*m_info[module].getNFrontends(); + unsigned int rows=m_info[module].getNRows(); + unsigned int moduleId=m_info[module].getId(); + std::string moduleName=m_info[module].getName(); + for(int i=1;i<15;i++){ //ToT loop + /* retrieve scan points - Vcal steps in this case */ + sprintf(title,"OCCUPANCY Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_Occupancy_ToT_%02d", moduleId, i); + histoc=new RceHisto2d<char, char>(name,title,cols,0,cols,rows,0,rows); + histoc->setAxisTitle(0,"Column"); + histoc->setAxisTitle(1, "Row"); + m_histo_tot[module].push_back(histoc); + } + } +} + + +TotCalibDataProc::~TotCalibDataProc(){ + for (size_t module=0;module<m_histo_tot.size();module++) + for(size_t i=0;i<m_histo_tot[module].size();i++)delete m_histo_tot[module][i]; +} + + diff --git a/rce/rcecalib/dataproc/TotCalibDataProc.hh b/rce/rcecalib/dataproc/TotCalibDataProc.hh new file mode 100644 index 00000000..9f1ac6ef --- /dev/null +++ b/rce/rcecalib/dataproc/TotCalibDataProc.hh @@ -0,0 +1,26 @@ +#ifndef TOTCALIBDATAPROC_HH +#define TOTCALIBDATAPROC_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "dataproc/AbsDataProc.hh" +#include <vector> +#include "util/RceHisto2d.cc" + +class TotCalibDataProc: public AbsDataProc{ +public: + TotCalibDataProc(ConfigIF* cif,boost::property_tree::ptree* scanOptions ); + + virtual ~TotCalibDataProc(); + int processData(unsigned link, unsigned *data, int size); + int fit(std::string fitfun); +protected: + + std::vector<std::vector<RceHisto2d<char, char>*> > m_histo_tot; + + std::vector<int> m_vcal; + int m_nTrigger; + int m_nLoops; + int m_nPoints; +}; + +#endif diff --git a/rce/rcecalib/dataproc/TotDataProc.cc b/rce/rcecalib/dataproc/TotDataProc.cc new file mode 100644 index 00000000..47bdf8e6 --- /dev/null +++ b/rce/rcecalib/dataproc/TotDataProc.cc @@ -0,0 +1,162 @@ +#include <stdio.h> +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/dataproc/TotDataProc.hh" +#include "rcecalib/config/ConfigIF.hh" +#include "rcecalib/config/FormattedRecord.hh" +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/dataproc/fit/CalculateMeanSigma.cc" + +int TotDataProc::fit(std::string fitfun) { +#ifdef RCEPIXLIB + std::cout << "Running: " << fitfun << std::endl; + if(fitfun=="CALCULATE_MEAN_SIGMA" && m_nPoints!=0) { + calculateMeanSigma(m_histo_occ, m_histo_tot, m_histo_tot2, m_histo_tot_mean, m_histo_tot_sigma); + } +#endif + return 0; +} + +int TotDataProc::processData(unsigned link, unsigned *data, int size){ + // std::cout<<"Process data"<<std::endl; + for (int i=0;i<size;i++){ + int module=m_linkToIndex[link]; // will be different when parser is fully there + FormattedRecord current(data[i]); + // if (current.isHeader()){ + // l1id = current.getL1id(); + // bcid = current.getBxid(); + //printf("bcid : %x \n", bcid); + //printf("l1id : %x \n", l1id); + // if (l1id != l1id_last) + //{ + // l1id_last = l1id; + // bcid_ref = bcid; + //} + // bcid = bcid-bcid_ref; + // printf("bcidafter : %x \n", bcid); + //} + if (current.isData()){ + unsigned int chip=current.getFE(); + unsigned int tot=current.getToT(); + unsigned int col=current.getCol(); + unsigned int row=current.getRow(); + if((row<(unsigned)m_info[module].getNRows()) && (col<(unsigned)m_info[module].getNColumns())) { + if(chip==0){ //gives better performance for FEI4 + m_histo_occ[module][m_currentBin]->incrementFast(col,row); + m_histo_tot[module][m_currentBin]->fillFast(col,row,(unsigned int)tot); + m_histo_tot2[module][m_currentBin]->fillFast(col,row,(unsigned int)(tot*tot)); + }else if(chip<(unsigned)m_info[module].getNFrontends()){ + m_histo_occ[module][m_currentBin]->incrementFast(chip*m_info[module].getNColumns()+col,row); + m_histo_tot[module][m_currentBin]->fillFast(chip*m_info[module].getNColumns()+col,row,(unsigned int)tot); + m_histo_tot2[module][m_currentBin]->fillFast(chip*m_info[module].getNColumns()+col,row,(unsigned int)(tot*tot)); + } + } + } + } + return 0; +} + +TotDataProc::TotDataProc(ConfigIF* cif, boost::property_tree::ptree* scanOptions) + :AbsDataProc(cif) { + try{ //catch bad scan option parameters + m_nLoops = scanOptions->get<int>("nLoops"); + /* there is at least one parameter loop */ + /* TODO: fix in scan control */ + m_nPoints=1; + if(m_nLoops>0){ + m_nPoints=scanOptions->get<int>("scanLoop_0.nPoints"); + for(int i=0;i<m_nPoints;i++) { + char pointname[10]; + sprintf(pointname,"P_%d",i); + int vcal=scanOptions->get<int>(std::string("scanLoop_0.dataPoints.")+pointname); + //std::cout << "point vcal " << vcal << std::endl; + m_vcal.push_back(vcal); + } + } + m_nTrigger=scanOptions->get<int>("trigOpt.nEvents"); + + for (unsigned int module=0;module<m_configIF->getNmodules();module++){ + std::vector<RceHisto2d<char, char>* > vhc; + std::vector<RceHisto2d<short, short>* > vh; + m_histo_occ.push_back(vhc); + m_histo_tot.push_back(vh); + m_histo_tot2.push_back(vh); + m_histo_tot_sigma.push_back(vh); + m_histo_tot_mean.push_back(vh); + char name[128]; + char title[128]; + RceHisto2d<short, short> *histo; + RceHisto2d<char, char> *histoc; + unsigned int cols=m_info[module].getNColumns()*m_info[module].getNFrontends(); + unsigned int rows=m_info[module].getNRows(); + unsigned int moduleId=m_info[module].getId(); + std::string moduleName=m_info[module].getName(); + /* retrieve scan points - Vcal steps in this case */ + for (int point=0;point<m_nPoints;point++){ + sprintf(title,"OCCUPANCY Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_Occupancy_Point_%03d", moduleId,point); + histoc=new RceHisto2d<char, char>(name,title,cols,0,cols,rows,0,rows); + if(m_info[module].getNFrontends()==1)histoc->setAxisTitle(0,"Column"); + else histoc->setAxisTitle(0,"FE*N_COL+Column"); + histoc->setAxisTitle(1, "Row"); + m_histo_occ[module].push_back(histoc); + sprintf(title,"ToT Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_ToT_Point_%03d", moduleId,point); + histo=new RceHisto2d<short, short>(name,title,cols,0,cols,rows,0,rows); + if(m_info[module].getNFrontends()==1)histo->setAxisTitle(0,"Column"); + else histo->setAxisTitle(0,"FE*N_COL+Column"); + histo->setAxisTitle(1, "Row"); + m_histo_tot[module].push_back(histo); + + sprintf(title,"ToT2 Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_ToT2_Point_%03d", moduleId,point); + histo=new RceHisto2d<short, short>(name,title,cols,0,cols,rows,0,rows); + if(m_info[module].getNFrontends()==1)histo->setAxisTitle(0,"Column"); + else histo->setAxisTitle(0,"FE*N_COL+Column"); + histo->setAxisTitle(1, "Row"); + m_histo_tot2[module].push_back(histo); + +#ifdef RCEPIXLIB + sprintf(title,"ToT_MEAN Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_ToTmean_Point_%03d", moduleId,point); + histo=new RceHisto2d<short, short>(name,title,cols,0,cols,rows,0,rows); + if(m_info[module].getNFrontends()==1)histo->setAxisTitle(0,"Column"); + else histo->setAxisTitle(0,"FE*N_COL+Column"); + histo->setAxisTitle(1, "Row"); + m_histo_tot_mean[module].push_back(histo); + + sprintf(title,"ToT_SIGMA Mod %d at %s", moduleId, moduleName.c_str()); + sprintf(name,"Mod_%d_ToTsigma_Point_%03d", moduleId,point); + histo=new RceHisto2d<short, short>(name,title,cols,0,cols,rows,0,rows); + if(m_info[module].getNFrontends()==1)histo->setAxisTitle(0,"Column"); + else histo->setAxisTitle(0,"FE*N_COL+Column"); + histo->setAxisTitle(1, "Row"); + m_histo_tot_sigma[module].push_back(histo); +#endif + } + } + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + ERS_ASSERT(0); + } +} + + +TotDataProc::~TotDataProc(){ + for (size_t module=0;module<m_histo_tot.size();module++) + for(size_t i=0;i<m_histo_tot[module].size();i++)delete m_histo_tot[module][i]; + for (size_t module=0;module<m_histo_tot2.size();module++) + for(size_t i=0;i<m_histo_tot2[module].size();i++)delete m_histo_tot2[module][i]; + for (size_t module=0;module<m_histo_occ.size();module++) + for(size_t i=0;i<m_histo_occ[module].size();i++)delete m_histo_occ[module][i]; +#ifdef RCEPIXLIB + for (size_t module=0;module<m_histo_tot_mean.size();module++) + for(size_t i=0;i<m_histo_tot_mean[module].size();i++)delete m_histo_tot_mean[module][i]; + for (size_t module=0;module<m_histo_tot_sigma.size();module++) + for(size_t i=0;i<m_histo_tot_sigma[module].size();i++)delete m_histo_tot_sigma[module][i]; +#endif + +} + + diff --git a/rce/rcecalib/dataproc/TotDataProc.hh b/rce/rcecalib/dataproc/TotDataProc.hh new file mode 100644 index 00000000..4247e600 --- /dev/null +++ b/rce/rcecalib/dataproc/TotDataProc.hh @@ -0,0 +1,30 @@ +#ifndef TOTDATAPROC_HH +#define TOTDATAPROC_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/dataproc/AbsDataProc.hh" +#include <vector> +#include "rcecalib/util/RceHisto2d.cc" + +class TotDataProc: public AbsDataProc{ +public: + TotDataProc(ConfigIF* cif,boost::property_tree::ptree* scanOptions ); + + virtual ~TotDataProc(); + int processData(unsigned link, unsigned *data, int size); + int fit(std::string fitfun); +protected: + + std::vector<std::vector<RceHisto2d<short, short>*> > m_histo_tot; + std::vector<std::vector<RceHisto2d<short, short>*> > m_histo_tot2; + std::vector<std::vector<RceHisto2d<char, char>*> > m_histo_occ; + std::vector<std::vector<RceHisto2d<short, short>*> > m_histo_tot_sigma; + std::vector<std::vector<RceHisto2d<short, short>*> > m_histo_tot_mean; + + std::vector<int> m_vcal; + int m_nTrigger; + int m_nLoops; + int m_nPoints; +}; + +#endif diff --git a/rce/rcecalib/dataproc/constituents.mk b/rce/rcecalib/dataproc/constituents.mk new file mode 100644 index 00000000..6c699252 --- /dev/null +++ b/rce/rcecalib/dataproc/constituents.mk @@ -0,0 +1,99 @@ + +ifdef SWAP_DATA +CPPFLAGS += '-DSWAP_DATA' +endif +ifeq ($(profiler),y) +CPPFLAGS+='-D__PROFILER_ENABLED__' +endif + +ifneq ($(findstring ppc-rtems-rce,$(tgt_arch)),) +modlibnames := dataproc +libsrcs_dataproc := AbsDataProc.cc \ + RegularScanDataHandler.cc \ + RegularScanRawDataHandler.cc \ + ModuleCrosstalkRawDataHandler.cc \ + DelayScanDataHandler.cc \ + CosmicDataHandler.cc \ + DataProcFactory.cc \ + OccupancyDataProc.cc \ + RawFei4OccupancyDataProc.cc \ + NoiseOccupancyDataProc.cc \ + TotDataProc.cc \ + TotCalibDataProc.cc \ + BcidDataProc.cc \ + SelftriggerDataProc.cc \ + HitorDataProc.cc \ + CosmicDataProc.cc \ + CosmicEvent.cc \ + CosmicEventIterator.cc \ + DelayScanDataProc.cc \ + SimpleReceiver.cc \ + MeasurementReceiver.cc \ + MeasurementDataProc.cc \ + PgpReceiver.cc \ + PgpCosmicReceiver.cc \ + PgpCosmicNwReceiver.cc \ + fit/FitData.cc \ + MultiTrigOccupancyDataProc.cc \ + MultiTrigNoiseDataProc.cc \ + TemperatureDataProc.cc \ + MonleakDataProc.cc \ + SNDataProc.cc\ + Fei4RegisterTestDataProc.cc\ + ClusterProc.cc + +libincs_dataproc := rcecalib \ + $(ers_include_path) \ + $(owl_include_path) \ + $(ipc_include_path) \ + $(is_include_path) \ + $(oh_include_path) \ + $(boost_include_path) \ + $(omniorb_include_path) + + +endif + +ifneq ($(findstring linux,$(tgt_os)),) +libnames := dataproc +libsrcs_dataproc := AbsDataProc.cc \ + RegularScanDataHandler.cc \ + RegularScanRawDataHandler.cc \ + ModuleCrosstalkRawDataHandler.cc \ + DelayScanDataHandler.cc \ + CosmicDataHandler.cc \ + DataProcFactory.cc \ + NoiseOccupancyDataProc.cc \ + OccupancyDataProc.cc \ + RawFei4OccupancyDataProc.cc \ + TotDataProc.cc \ + TotCalibDataProc.cc \ + BcidDataProc.cc \ + SelftriggerDataProc.cc \ + HitorDataProc.cc \ + CosmicDataProc.cc \ + CosmicEvent.cc \ + CosmicEventIterator.cc \ + DelayScanDataProc.cc \ + SimpleReceiver.cc \ + MeasurementDataProc.cc \ + fit/FitData.cc \ + MultiTrigOccupancyDataProc.cc \ + MultiTrigNoiseDataProc.cc \ + TemperatureDataProc.cc \ + MonleakDataProc.cc \ + SNDataProc.cc\ + Fei4RegisterTestDataProc.cc\ + ClusterProc.cc + +libincs_dataproc := rcecalib \ + $(ers_include_path) \ + $(owl_include_path) \ + $(ipc_include_path) \ + $(is_include_path) \ + $(oh_include_path) \ + $(boost_include_path) \ + $(omniorb_include_path) + + +endif diff --git a/rce/rcecalib/dataproc/fit/AbsFit.hh b/rce/rcecalib/dataproc/fit/AbsFit.hh new file mode 100644 index 00000000..14e0de1f --- /dev/null +++ b/rce/rcecalib/dataproc/fit/AbsFit.hh @@ -0,0 +1,24 @@ +#ifndef ABSFIT_HH +#define ABSFIT_HH + +#include <string> +#include <vector> +#include "rcecalib/config/ModuleInfo.hh" + +class ConfigIF; + + +class AbsFit { +public: + enum FitOpt {NOCONV=0x1,XTALK=0x2}; + AbsFit(ConfigIF *cif,std::vector<int> &vcal,int nTrigger):m_config(cif),m_vcal(vcal),m_nTrigger(nTrigger){}; + virtual ~AbsFit(){}; + virtual int doFit(int fitopt=0) = 0; + +protected: + ConfigIF *m_config; + std::vector<int> m_vcal; + int m_nTrigger; +}; + +#endif diff --git a/rce/rcecalib/dataproc/fit/CalculateMeanSigma.cc b/rce/rcecalib/dataproc/fit/CalculateMeanSigma.cc new file mode 100644 index 00000000..b02a6769 --- /dev/null +++ b/rce/rcecalib/dataproc/fit/CalculateMeanSigma.cc @@ -0,0 +1,73 @@ + +namespace{ + + int SquareRootFunc(int variance) + { + int op, res, one; + op = variance; + res = 0; + + // "one" starts at the highest power of four <= than the argument. + // if this value is decreased, a smaller range of values is allowed. needs to be an even number + one = 1 << 30; + while (one > op) { + one >>= 2; + } + while (one != 0) { + if (op >= res + one) { + op = op - (res + one); + res = res + (one<<1); + } + res >>= 1; + one >>= 2; + } + return res; + } +} +template<typename H, typename HE> +int calculateMeanSigma( std::vector<std::vector<RceHisto2d<H, HE>*> > &histo_occ, std::vector<std::vector<RceHisto2d<short, short>*> > &hvalue, std::vector<std::vector<RceHisto2d<short, short>*> > &hvalue2, std::vector<std::vector<RceHisto2d<short, short>*> > &hmean, std::vector<std::vector<RceHisto2d<short, short>*> > &hsigma ) +{ + + unsigned int numberofmodules =histo_occ.size(); + + for(unsigned module=0;module<numberofmodules;module++) { + for(unsigned int bin=0;bin<histo_occ[module].size();bin++) { + for(int col=0;col<histo_occ[module][bin]->nBin(0);col++) { + for(int row=0;row<histo_occ[module][bin]->nBin(1);row++) { + int counting =(int) (*histo_occ[module][bin])(col,row); + int toting = (int)(*hvalue[module][bin])(col,row); + int tot2ing = (int)(*hvalue2[module][bin])(col,row); + int mean=0; + int variance=0; + if(counting>0)mean=(toting<<7)/counting; + if(mean>0) { + hmean[module][bin]->set(col,row,mean); + } + else { + if (counting>0) { + hmean[module][bin]->set(col,row,1); + } + else { + hmean[module][bin]->set(col,row,0); + } + } + + if(counting>1) variance= (((tot2ing<<14)/(counting))-mean*mean); + if(variance >0) { + int sigma = SquareRootFunc(variance); + hsigma[module][bin]->set(col,row,sigma); + } else{ + + if(counting>1) { + hsigma[module][bin]->set(col,row,1); + } + else { + hsigma[module][bin]->set(col,row,0); + } + } + } //rows + } //columns + } // bins + }//modules + return 0; +} diff --git a/rce/rcecalib/dataproc/fit/FitData.cc b/rce/rcecalib/dataproc/fit/FitData.cc new file mode 100644 index 00000000..1040b1ed --- /dev/null +++ b/rce/rcecalib/dataproc/fit/FitData.cc @@ -0,0 +1,35 @@ +#include "rcecalib/dataproc/fit/FitData.hh" + +const int FitDataInt::binomial_weight[WEIGHT_LUT_LENGTH]={ +#include "rcecalib/dataproc/fit/binomial_weight_int.dat" +}; +const int FitDataInt::data_logx[2*LUT_LENGTH]={ +#include "rcecalib/dataproc/fit/logx_ext_int.dat" +}; +const int FitDataInt::data_errf[LUT_LENGTH]={ +#include "errf_ext_int.dat" +}; + +const int FitDataFastInt::binomial_weight[WEIGHT_LUT_LENGTH]={ +#include "rcecalib/dataproc/fit/binomial_weight_int.dat" +}; +const int FitDataFastInt::data_logx[2*FAST_LUT_LENGTH]={ +#include "rcecalib/dataproc/fit/logx_ext_fastint.dat" +}; +const int FitDataFastInt::data_errf[FAST_LUT_LENGTH]={ +#include "errf_ext_fastint.dat" +}; + +#ifdef INCLUDE_FLOAT_FIT +const float FitDataFloat::binomial_weight[WEIGHT_LUT_LENGTH]={ +#include "rcecalib/dataproc/fit/binomial_weight.dat" +}; +const float FitDataFloat::data_logx[2*LUT_LENGTH]={ +#include "rcecalib/dataproc/fit/logx_ext.dat" +}; +const float FitDataFloat::data_errf[LUT_LENGTH]={ +#include "errf_ext.dat" +}; +#endif + + diff --git a/rce/rcecalib/dataproc/fit/FitData.hh b/rce/rcecalib/dataproc/fit/FitData.hh new file mode 100644 index 00000000..b04b9021 --- /dev/null +++ b/rce/rcecalib/dataproc/fit/FitData.hh @@ -0,0 +1,34 @@ +#ifndef FITDATA_HH +#define FITDATA_HH +#define WEIGHT_LUT_LENGTH 1001 +#define LUT_WIDTH 3500 +#define LUT_LENGTH (2*LUT_WIDTH+1) +#define FAST_LUT_WIDTH 4095 +#define FAST_LUT_LENGTH (2*FAST_LUT_WIDTH+1) +#define inverse_lut_interval 1000.f +#define inverse_weight_lut_interval 1000.f +class FitDataInt +{ +public: + static const int binomial_weight[]; + static const int data_logx[]; + static const int data_errf[]; +}; +class FitDataFastInt +{ +public: + static const int binomial_weight[]; + static const int data_logx[]; + static const int data_errf[]; +}; +#ifdef INCLUDE_FLOAT_FIT +class FitDataFloat +{ +public: + static const float binomial_weight[]; + static const float data_logx[]; + static const float data_errf[]; +}; +#endif + +#endif diff --git a/rce/rcecalib/dataproc/fit/FitFactory.cc b/rce/rcecalib/dataproc/fit/FitFactory.cc new file mode 100644 index 00000000..5c621f6b --- /dev/null +++ b/rce/rcecalib/dataproc/fit/FitFactory.cc @@ -0,0 +1,28 @@ +#ifndef FITFACTORY_CC +#define FITFACTORY_CC + +#include "rcecalib/dataproc/fit/FitFactory.hh" + +#ifdef INCLUDE_FLOAT_FIT +#include "rcecalib/dataproc/fit/FitScurveLikelihoodFloat.cc" +#endif +#include "rcecalib/dataproc/fit/FitScurveLikelihoodInt.cc" +#include "rcecalib/dataproc/fit/FitScurveLikelihoodFastInt.cc" + +template<typename H, typename HE> +AbsFit *FitFactory<H, HE>::createFit(const char * type,ConfigIF *cif, std::vector<std::vector<RceHisto2d<H, HE>*> > &histo, std::vector<int> &vcal,int nTrigger, const char* name) +{ +#ifdef INCLUDE_FLOAT_FIT + if(std::string(type)=="ScurveLikelihoodFloat") return new FitScurveLikelihoodFloat<H, HE>(cif,histo,vcal,nTrigger); +#endif + if(std::string(type)=="ScurveLikelihoodFastInt") return new FitScurveLikelihoodFastInt<H, HE>(cif,histo,vcal,nTrigger,name); + else if (std::string(type)=="ScurveLikelihoodInt") return new FitScurveLikelihoodInt<H, HE>(cif,histo,vcal,nTrigger,name); + else + return 0; +} +template<typename H, typename HE> +AbsFit *FitFactory<H, HE>::createFit(const char * type,ConfigIF *cif, std::vector<std::vector<RceHisto1d<H, HE>*> > &histo, std::vector<int> &vcal,int nTrigger, const char* name){ + return 0; +} + +#endif diff --git a/rce/rcecalib/dataproc/fit/FitFactory.hh b/rce/rcecalib/dataproc/fit/FitFactory.hh new file mode 100644 index 00000000..64c8e004 --- /dev/null +++ b/rce/rcecalib/dataproc/fit/FitFactory.hh @@ -0,0 +1,18 @@ +#ifndef FITFACTORY_HH +#define FITFACTORY_HH + +#include "rcecalib/dataproc/fit/AbsFit.hh" +#include "rcecalib/util/RceHisto2d.cc" +#include "rcecalib/util/RceHisto1d.cc" + + +template<typename H, typename HE> +class FitFactory{ +public: + FitFactory(){} + + AbsFit *createFit(const char *type,ConfigIF *cif,std::vector<std::vector<RceHisto2d<H, HE>*> > &histo,std::vector<int> &vcal,int nTrigger,const char* name=""); + AbsFit *createFit(const char *type,ConfigIF *cif,std::vector<std::vector<RceHisto1d<H, HE>*> > &histo,std::vector<int> &vcal,int nTrigger,const char* name=""); + +}; +#endif diff --git a/rce/rcecalib/dataproc/fit/FitScurveLikelihoodFastInt.cc b/rce/rcecalib/dataproc/fit/FitScurveLikelihoodFastInt.cc new file mode 100644 index 00000000..8d5e9d60 --- /dev/null +++ b/rce/rcecalib/dataproc/fit/FitScurveLikelihoodFastInt.cc @@ -0,0 +1,822 @@ +#include "rcecalib/dataproc/fit/FitScurveLikelihoodFastInt.hh" +#include "rcecalib/dataproc/fit/FitData.hh" +#include "rcecalib/config/ConfigIF.hh" +#include <iostream> +#include <stdio.h> +#include "namespace_aliases.hh" +template<typename TP, typename TE> +FitScurveLikelihoodFastInt<TP, TE>::FitScurveLikelihoodFastInt(ConfigIF *cif,std::vector<std::vector<RceHisto2d<TP, TE>*> > &histo,std::vector<int> &vcal,int nTrigger,const char* name):AbsFit(cif,vcal,nTrigger),m_histo(histo),m_name(name) { + initFit(&m_fit); +} + +template<typename TP, typename TE> +FitScurveLikelihoodFastInt<TP, TE>::~FitScurveLikelihoodFastInt(){ + for(unsigned int module=0;module<m_fithisto.size();module++) { + for(size_t i=0;i<m_fithisto[module].size();i++){ + delete m_fithisto[module][i]; + } + } +} + + +template<typename TP, typename TE> +int FitScurveLikelihoodFastInt<TP, TE>::doFit(int fitopt) { + FitData pfdi,pfdo; + GaussianCurve gc; +#if 0 + clock_t starttime,endtime; + starttime= RceSvc::ticks(); +#endif + int nBins=m_vcal.size(); + if(!nBins) return -1; + m_x=new UINT32[nBins]; + m_y=new UINT8[nBins]; + + for(unsigned int module=0;module<m_config->getNmodules();module++) { + int nRows= m_config->getModuleInfo(module).getNRows(); + int nCols=m_config->getModuleInfo(module).getNColumns(); + //int nHistos=m_histo[module].size(); + std::cout << "nTrigger " << m_nTrigger << std::endl; + for(int chip=0;chip<m_config->getModuleInfo(module).getNFrontends();chip++) { + if((fitopt&NOCONV)==0) { + /* apply dac to electron calibration */ + for(int bin=0;bin<nBins;bin++) { + /* for now we use float here */ + m_x[bin]=(UINT32)(m_config->dacToElectrons(module,chip,m_vcal[bin])*10); + } + } else { + for(int bin=0;bin<nBins;bin++) { + /* for now we use float here */ + m_x[bin]=m_vcal[bin]*10; + } + } + for(int col=0;col<nCols;col++) { + for(int row=0;row<nRows;row++) { + // extract S-Curve + for(int bin=0;bin<nBins;bin++) { + m_y[bin]=(UINT8)(*m_histo[module][bin])(row, chip*nCols+col); + } + pfdi.n=nBins; + pfdi.x=&m_x[0]; + pfdi.y=&m_y[0]; + + int goodBins = extractGoodData(&pfdi,&pfdo,m_nTrigger); + int maxVal = m_nTrigger; + + if(goodBins<2){ + if(fitopt&XTALK){ + goodBins = roughFitRange(&pfdi,&pfdo,maxVal); + } + } + if(goodBins<2){ + continue; + } + + if(goodBins<5){ + m_fit.curve=&gc; + m_fit.maxIters=100; + int result = sGuess(&pfdo,&m_fit); + + if(!result) { + + int lastbin = pfdi.n-1; + float fitmu = (float)gc.mu/10.f; + float fitsigma = (float)gc.sigma/1000.f; + //exclude extreme fit results from the histograms + if(10*fitmu < 2*pfdi.x[lastbin] && 10*fitsigma < 2*(pfdi.x[lastbin]-pfdi.x[0])){ + + //std::cout<<"we guess mu = "<<(float)gc.mu/10.f<<" ; sigma = "<<(float)gc.sigma/1000.f<<std::endl; + m_fithisto[module][0]->set(chip*nCols+col,row,(float)gc.mu/10.f); + m_fithisto[module][1]->set(chip*nCols+col,row,(float)gc.sigma/1000.f); + m_fithisto[module][2]->set(chip*nCols+col,row,(float) m_fit.chi2/(float) (m_fit.ndf* 100)); + m_fithisto[module][3]->set(chip*nCols+col,row,(float) m_fit.nIters); + + } + + } + + } + else{ + + m_fit.curve=&gc; + m_fit.maxIters=100; + gc.a0=maxVal; + int result=fitPixel(&pfdo,&m_fit); + if(!result) { + int lastbin = pfdi.n-1; + float fitmu = (float)gc.mu/10.f; + float fitsigma = (float)4634050/(float) gc.sigma; + //exclude extreme fit results from the histograms + if(10*fitmu < 2*pfdi.x[lastbin] && 10*fitsigma < 2*(pfdi.x[lastbin]-pfdi.x[0])){ + // printf("%d %d %d %d %f %f %f %d\n",gc.a0,chip,col,row,gc.mu/10000.,4634040./gc.sigma,m_fit.chi2/100.,m_fit.nIters); + m_fithisto[module][0]->set(chip*nCols+col,row,(float)gc.mu/10.f); + m_fithisto[module][1]->set(chip*nCols+col,row,(float) 4634050/(float) gc.sigma); + m_fithisto[module][2]->set(chip*nCols+col,row,(float) m_fit.chi2/(float) (m_fit.ndf* 100)); + m_fithisto[module][3]->set(chip*nCols+col,row,(float) m_fit.nIters); + } + + } + } + + } //rows + } //columns + } //chips + } // modules + delete [] m_x; + delete [] m_y; +#if 0 + endtime= RceSvc::ticks(); + printf("total fit time %f\n",(float)(endtime-starttime)/350.); +#endif + return 0; +} + +template<typename TP, typename TE> +typename FitScurveLikelihoodFastInt<TP, TE>::INT32 *FitScurveLikelihoodFastInt<TP, TE>::log_ext(INT32 x, INT32 mu,INT32 sigma) { + INT32 u; + + u=(x - mu)*sigma + sc_lut_width; //may be negative and larger than lut length + if(u<0) u=0; + if(u > sc_lut_length) u = sc_lut_length; //trancate + u>>=15; + u&=0xfffe; // we need the index should always be even + return (INT32*) &FitDataFastInt::data_logx[u]; +} + + + +template<typename TP, typename TE> +typename FitScurveLikelihoodFastInt<TP, TE>::UINT32 FitScurveLikelihoodFastInt<TP, TE>::errf_ext(INT32 x, GaussianCurve *psp) { + INT32 u; + u=(x - psp->mu)*psp->sigma + sc_lut_width; //it may be negative and may exceed LUT length + if(u < 0) u=0; + if(u > sc_lut_length) u=sc_lut_length; + u>>=16; + return FitDataFastInt::data_errf[u]; +} + +template<typename TP, typename TE> +typename FitScurveLikelihoodFastInt<TP, TE>::UINT32 FitScurveLikelihoodFastInt<TP, TE>::logLikelihood(FitData *pfd, GaussianCurve *s) { + INT32 N; + UINT32 *x; + UINT8 *y; + UINT32 acc; + INT32 *p; + UINT32 k; + INT32 mu,sigma; + mu=s->mu; + sigma=s->sigma; + + x = pfd->x; + y = pfd->y; + acc = 0; + N = s->a0; + for(k=0; k<pfd->n; ++k) + { + p = log_ext(*x++,mu,sigma); /* pointer to log(probability) */ + acc -= ((s->a0-(*y))*(*(p+1))+(*y)*(*p)); + y++; + } + return acc; +} + +template<typename TP, typename TE> +int FitScurveLikelihoodFastInt<TP, TE>::initFit(Fit *pFit) { + pFit->maxIters = 100; + pFit->muEpsilon = 50; /* 0.01% */ + pFit->sigmaEpsilon = 50; /* 0.01% */ + for (unsigned int i=0;i<m_config->getNmodules();i++){ + std::vector<RceHisto2d<float, float>*> vh; + m_fithisto.push_back(vh); + char name[128]; + char title[128]; + char suffix[128]=""; + if(std::string(m_name)!=""){ + sprintf(suffix,"%s_",m_name); + } + + int rows=m_config->getModuleInfo(i).getNRows(); + int cols=m_config->getModuleInfo(i).getNColumns()*m_config->getModuleInfo(i).getNFrontends(); + int id=m_config->getModuleInfo(i).getId(); + std::string modName=m_config->getModuleInfo(i).getName(); + sprintf(name,"Mod_%d_%sMean", id, suffix); + sprintf(title,"MOD %d %s at %s SCURVE MEAN", id, suffix, modName.c_str()); + m_fithisto[i].push_back(new RceHisto2d<float, float>(name,title,cols,0,cols,rows, 0, rows)); + sprintf(title,"MOD %d %s at %s SCURVE SIGMA", id, suffix, modName.c_str()); + sprintf(name,"Mod_%d_%sSigma", id, suffix); + m_fithisto[i].push_back(new RceHisto2d<float, float>(name,title,cols,0,cols,rows, 0, rows)); + sprintf(title,"MOD %d %s at %s SCURVE CHI2", id, suffix, modName.c_str()); + sprintf(name,"Mod_%d_%sChiSquare", id, suffix); + m_fithisto[i].push_back(new RceHisto2d<float, float>(name,title,cols,0,cols,rows, 0, rows)); + sprintf(title,"MOD %d %s at %s SCURVE ITER", id, suffix, modName.c_str()); + sprintf(name,"Mod_%d_%sIter", id, suffix); + m_fithisto[i].push_back(new RceHisto2d<float, float>(name,title,cols,0,cols,rows, 0, rows)); + } + return 0; +} + +template<typename TP, typename TE> +int FitScurveLikelihoodFastInt<TP, TE>::extractGoodData(FitData *pfdi,FitData *pfdo, UINT32 nTriggers) { + int hitsStart, hitsEnd, nBins; + UINT32 a0; + UINT8 *y; + + nBins = pfdi->n; + y = pfdi->y; + + //new method to find hitsStart + + for(hitsStart = nBins-1;hitsStart >= 0; --hitsStart) + if(y[hitsStart] == 0) break; + + if(hitsStart ==0) + return 0; + if(hitsStart == nBins) + return 0; + + a0 = y[nBins - 1]; // last bin has at least 90% hits + if(a0*999 < nTriggers*900) + return 0; + //failure mode, never reaches A0 + + //dan's new method + for(hitsEnd = hitsStart; hitsEnd < nBins; ++hitsEnd) + if(y[hitsEnd] >= a0) break; + + // add 2 for old method or 1 for new method + // 1 because of where we start comparing and + // 1 because we want to include one instance of the maximum + nBins = 1 + hitsEnd - hitsStart; + + if(hitsStart < 0) hitsStart =0; + + if(hitsStart == hitsEnd) return 0; + + if(nBins < 2) { + return 0; + //failure mode :: not enough data points + } + if(nBins < 0) nBins = 0; + pfdo->n = nBins; + pfdo->y = &y[hitsStart]; + pfdo->x = &pfdi->x[hitsStart]; + return nBins; +} + + +template<typename TP, typename TE> +int FitScurveLikelihoodFastInt<TP, TE>::initialGuess(FitData *pfd, GaussianCurve *pSParams) { + + + UINT32 pt1, pt2, pt3; + UINT8 *pdlo; + UINT32 y_lo, sigma; + UINT32 *x; + UINT8 *y; + UINT32 a0; + UINT32 minSigma; + UINT32 k, n, lo1, lo2, lo3, status; + UINT32 x1,x2,x3; + INT32 xdiff; + + n = pfd->n; + if(n<5) return 1; + pSParams->a0 = pfd->y[pfd->n-1]; // assumes last data point sets plateau + a0 = pSParams->a0; + xdiff=pfd->x[1] - pfd->x[0]; + minSigma = (xdiff*2897)>>12; //This is actually division by sqrt of 2 + x = pfd->x; y = pfd->y; + pt1 = (16* a0)/100; + pt2 = (50* a0)/100; + pt3 = (84* a0)/100; + // find the range over which the data crosses the 16%, 50% and 84% points + lo1 = lo2 = lo3 = 0; // invalid values + pdlo = &y[0]; // y + for(k=0;k<n;++pdlo) + { + y_lo = *pdlo; + if(!lo1 && (y_lo >= pt1)) lo1 = k; + if(!lo2 && (y_lo >= pt2)) lo2 = k; + if(!lo3 && (y_lo >= pt3)) lo3 = k; + ++k; + } +// printf("sGuess lo1=%d lo2=%d lo3=%d \n",lo1,lo2,lo3); + x1 = (x[lo1] + x[lo1-1]) >> 1; + x2 = (x[lo2] + x[lo2-1]) >> 1; + x3 = (x[lo3] + x[lo3-1]) >> 1; +// printf("sGuess x1 x2 x3 %d %d %d\n",x1, x2,x3); + + // mu = threshold + + pSParams->mu = (UINT32) x2; + xdiff=(x3 - x1); + sigma = (xdiff*2897)>>12; //This is actually division by sqrt of 2 + if(sigma < minSigma) { + sigma = minSigma; + } + // change for inv sigma + pSParams->sigma=65536000/sigma; // do division *here* for speed; use large factor to prevent truncation; unclear this is large enough + status = 0; + return status; + +} +#define DMUMUL 50 +#define DSIGMUL 200 +template<typename TP, typename TE> +int FitScurveLikelihoodFastInt<TP, TE>::fitPixel(FitData *pfd,void *vpfit) { + INT32 deltaSigma, deltaMu, sigma, chi2Min, *fptr; + INT32 chi2[9]; + GaussianCurve sParams, sParamsWork, *psp; + int muEpsilon,sigmaEpsilon; + int k, dirMin; + Fit *pFit; + pFit = (Fit *)vpfit; + + pFit->nIters = 0; + pFit->converge = 0; // assume no convergence + muEpsilon = pFit->muEpsilon; + sigmaEpsilon = pFit->sigmaEpsilon; + + pFit->ndf = pfd->n - 2; // degrees of freedom + // take a guess at the S-curve parameters + + if(initialGuess(pfd,&sParams)) + { + psp = (GaussianCurve *)pFit->curve; + psp->a0 = sParams.a0; + psp->mu = sParams.mu; + psp->sigma = sParams.sigma; + pFit->converge = 1; + pFit->chi2 = 0; + return 0; + } + + // initialize loop parameters + psp = &sParamsWork; + psp->a0 = sParams.a0; + deltaSigma = (sParams.sigma*DSIGMUL)/1000 ; // scaled estimated value + deltaMu = (sParams.mu*DMUMUL)/1000 ; // scaled estimated value + + // the loop begins + + while(!pFit->converge && (pFit->nIters++ < pFit->maxIters)) + { + dirMin = 0; + fptr = chi2; + for(k=0;k<9;++k) *fptr++ = 0; + while((dirMin >= 0) && (pFit->nIters++ < pFit->maxIters)) + { + // * calculate neighboring points * + + psp->sigma=sParams.sigma - deltaSigma; + psp->mu = sParams.mu - deltaMu; + if(chi2[0] == 0) chi2[0] = logLikelihood(pfd,psp); + psp->mu = sParams.mu; + if(chi2[7] == 0) chi2[7] = logLikelihood(pfd,psp); + psp->mu = sParams.mu + deltaMu; + if(chi2[6] == 0) chi2[6] = logLikelihood(pfd,psp); + psp->sigma=sParams.sigma; + psp->mu = sParams.mu - deltaMu; + if(chi2[1] == 0) chi2[1] = logLikelihood(pfd,psp); + psp->mu = sParams.mu; + if(chi2[8] == 0) chi2[8] = logLikelihood(pfd,psp); + psp->mu = sParams.mu + deltaMu; + if(chi2[5] == 0) chi2[5] = logLikelihood(pfd,psp); + psp->sigma=sParams.sigma+deltaSigma; + psp->mu = sParams.mu - deltaMu; + if(chi2[2] == 0) chi2[2] = logLikelihood(pfd,psp); + psp->mu = sParams.mu; + if(chi2[3] == 0)chi2[3] = logLikelihood(pfd,psp); + psp->mu = sParams.mu + deltaMu; + if(chi2[4] == 0) chi2[4] = logLikelihood(pfd,psp); + + dirMin = -1; + chi2Min = chi2[8]; // first guess at minimum + for(k=0, fptr=chi2; k<8; ++k, ++fptr) + { + if(*fptr < chi2Min) + { + chi2Min = *fptr; + dirMin = k; + } + } +// printf("chi2: %d %d %d %d %d %d %d %d %d\n", +// chi2[0],chi2[1],chi2[2],chi2[3],chi2[4],chi2[5],chi2[6],chi2[7],chi2[8]); + switch(dirMin) + { + case -1: + if(!pFit->converge) + { + deltaSigma = deltaSigma >> 3; + deltaMu = deltaMu >> 3; + } + break; + case 0: + sigma = sParams.sigma - deltaSigma; + sParams.sigma=sigma; + sParams.mu = sParams.mu - deltaMu; + chi2[8] = chi2[0]; + chi2[3] = chi2[1]; + chi2[4] = chi2[8]; + chi2[5] = chi2[7]; + chi2[0] = chi2[1] = chi2[2] = + chi2[6] = chi2[7] = 0; + break; + case 1: + sParams.mu = sParams.mu - deltaMu; + chi2[8] = chi2[1]; + chi2[3] = chi2[2]; + chi2[4] = chi2[3]; + chi2[5] = chi2[8]; + chi2[6] = chi2[7]; + chi2[7] = chi2[0]; + chi2[0] = chi2[1] = chi2[2] = 0; + break; + case 2: + sigma = sParams.sigma + deltaSigma; + sParams.sigma=sigma; + sParams.mu = sParams.mu - deltaMu; + chi2[8] = chi2[2]; + chi2[5] = chi2[3]; + chi2[6] = chi2[8]; + chi2[7] = chi2[1]; + chi2[0] = chi2[1] = chi2[2] = + chi2[3] = chi2[4] = 0; + break; + case 3: + sigma = sParams.sigma + deltaSigma; + sParams.sigma=sigma; + chi2[8] = chi2[3]; + chi2[5] = chi2[4]; + chi2[6] = chi2[5]; + chi2[7] = chi2[8]; + chi2[0] = chi2[1]; + chi2[1] = chi2[2]; + chi2[2] = chi2[3] = chi2[4] = 0; + break; + case 4: + sigma = sParams.sigma + deltaSigma; + sParams.sigma=sigma; + sParams.mu = sParams.mu + deltaMu; + chi2[8] = chi2[4]; + chi2[7] = chi2[5]; + chi2[0] = chi2[8]; + chi2[1] = chi2[3]; + chi2[2] = chi2[3] = chi2[4] = + chi2[5] = chi2[6] = 0; + break; + case 5: + sParams.mu = sParams.mu + deltaMu; + chi2[8] = chi2[5]; + chi2[7] = chi2[6]; + chi2[0] = chi2[7]; + chi2[1] = chi2[8]; + chi2[2] = chi2[3]; + chi2[3] = chi2[4]; + chi2[4] = chi2[5] = chi2[6] = 0; + break; + case 6: + sigma = sParams.sigma - deltaSigma; + sParams.sigma=sigma; + sParams.mu = sParams.mu + deltaMu; + chi2[8] = chi2[6]; + chi2[1] = chi2[7]; + chi2[2] = chi2[8]; + chi2[3] = chi2[5]; + chi2[4] = chi2[5] = chi2[6] = + chi2[7] = chi2[0] = 0; + break; + case 7: + sigma = sParams.sigma - deltaSigma; + sParams.sigma=sigma; + chi2[8] = chi2[7]; + chi2[1] = chi2[0]; + chi2[2] = chi2[1]; + chi2[3] = chi2[8]; + chi2[4] = chi2[5]; + chi2[5] = chi2[6]; + chi2[6] = chi2[7] = chi2[0] = 0; + break; + } //end switch + } // end while dirMin >= 0 + if((deltaSigma < sigmaEpsilon) && (deltaMu < muEpsilon)) + { + pFit->converge = 1; + break; + } + } // end while !pFit->converge + psp = (GaussianCurve *)pFit->curve; + *psp = sParams; + pFit->chi2 = chiSquared(pfd,psp); + + // tot_itt+=pFit->nIters; + return pFit->converge ? 0 : 1; // 0 = success + +} + +template<typename TP, typename TE> +typename FitScurveLikelihoodFastInt<TP, TE>::UINT32 FitScurveLikelihoodFastInt<TP, TE>::chiSquared(FitData *pfd,GaussianCurve *s) { + UINT32 acc,y3; + INT32 y0,y1,y2; + UINT32 a0, chi2; + UINT32 *x; + UINT8 *y; + INT32 x0; + int j, k, n; + + x = pfd->x; + y = pfd->y; + n = pfd->n; + acc = 0; + a0 = s->a0; + // use binomial weighting + for(k=0;k<n;++k) { + x0 = *x++; + y0 =(INT32) *y++; + y1 = errf_ext(x0,s); + j=y1>>10; + y2 = y0*1000 - (a0 * j); + y2/=100; + y3=(UINT32) (y2*y2); + y3*=FitDataFastInt::binomial_weight[j]; + y3>>=7; + acc+=y3; + + } + chi2=acc/a0; + return chi2; +} + + + +//Modified from /DAQ/IBLDAQ-0-0-0/RodDaq/NewDsp/SLAVE/fittingRoutines.c + +// \brief Guess S curve + +template<typename TP, typename TE> +int FitScurveLikelihoodFastInt<TP, TE>::sGuess(FitData *pfd, void *vpfit) { + + int j, k, n, lo1, lo2, lo3, hi1, hi2, hi3, status; + UINT32 *x, a0, minSigma, sigma, pt1, pt2, pt3, x1, x2, x3, hits, y_lo, y_hi; + UINT8 *y, *pdlo, *pdhi; + + +// clock_t time1,time2; +// #ifdef ppc405 +// time1= RceSvc::ticks(); +// #endif + + n = pfd->n; + + status = 1; //1: failure + + if(n<2){ + return 1; //not enough points + } + + UINT32 invroot6 = 4082; + + // std::cout<<"doing sGuess with n = "<<n<<std::endl; + + GaussianCurve *sParams; + + Fit *pFit; + pFit = (Fit *)vpfit; + + pFit->nIters = 0; + pFit->converge = 0; // assume no convergence + + sParams = (GaussianCurve *)pFit->curve; + + sParams->a0 = pfd->y[n-1]; // assumes last data point sets plateau + + +// for(int i=0; i<n; i++){ +// std::cout<<" "<<pfd->x[i]<<" ;"; +// } +// std::cout<<" | "; +// for(int i=0; i<n; i++){ +// std::cout<<" "<<(unsigned int)pfd->y[i]<<" ;"; +// } +// std::cout<<std::endl; + + a0 = sParams->a0; + + + minSigma = (pfd->x[1] - pfd->x[0]) * invroot6 / 100; +// std::cout<<"minSigma = "<<minSigma<<std::endl; + + if(n == 2) { + // no interesting data point + sParams->mu = (5 * (pfd->x[1] + pfd->x[0]) ) / 10; + sigma = minSigma; // we do not have accurate information + status = 0; + } else if(n == 3) { + // one interesting data point + // aSquared = a0 * a0; + hits = pfd->y[1]; + + // this next part is voodoo. being at such small number of interesting points, + //the maximum likelihood lies along a curve. Intuitively, we have a feel for where + ///the mean and sigma go. sigma varies continuously between sigma0 and 2 * sigma0, + //sigma0 = bin / root(6) + sigma = minSigma; + + INT32 factor = 400000*hits/a0; + factor *= (a0 - hits)/a0; + // std::cout<<"a0 = "<<a0<<" ; hits = "<<hits<<" ; factor = "<<factor<<std::endl; + + // sigma = sigma * ( 1.0f + 4.0f * hits * (a0 - hits) / aSquared ); + + factor = (100000 + factor)/1000; + // std::cout<<"now, factor = "<<factor<<" ; sigma = "<<sigma<<std::endl; + + sigma = (sigma/10) * factor; // we now have sigma(*100)(*100) + sigma = sigma/10; //we now have sigma*1000 + + + //crude estimate for mu, based on linear extrapolation + pt1 = 5 * a0; + hits = hits * 10; + + if(hits > pt1){ + lo1 = 0; + hi1 = 1; + } + else{ + lo1 = 1; + hi1 = 2; + } + + y_lo = pfd->y[lo1]; + y_hi = pfd->y[hi1]; + + x1 = pfd->x[lo1]; + x2 = pfd->x[hi1]; + + + INT32 invslope = (1000*(x2-x1))/ (y_hi-y_lo); // 10000/slope + + // std::cout<<"1/m = "<<invslope<<" pt1 = "<<pt1<<" ; y_l0 = "<<y_lo<<std::endl; + + sParams->mu = (pt1 - 10*y_lo) * invslope / 10000 + x1; + + // std::cout<<"mu = "<<sParams->mu<<std::endl; + + status = 0; + } + else { + x = pfd->x; y = pfd->y; + pt1 = 16 * a0; + pt2 = 50 * a0; + pt3 = 84 * a0; + // find the range over which the data crosses the 16%, 50% and 84% points + hi1 = hi2 = hi3 = 0; // invalid values + lo1 = lo2 = lo3 = 0; // invalid values + pdlo = &y[0]; // y + pdhi = &y[n-1]; // y + n - 1 + // important note: for the sake of speed we want to perform as few comparisons as + //possible. Therefore, the integer comparison occurs first in each of the + //following operations. Depending on the logical value thereof, the next + //comparison will be made only if necessary. To further expedite the code, + //arrays are not used because there are only three members + j = n - 1; + for(k=0;k<n;++pdlo, --pdhi) { + y_lo = *pdlo; + y_hi = *pdhi; + + y_lo = y_lo * 100; + y_hi = y_hi * 100; + + if(!lo1 && (y_lo >= pt1)) lo1 = k; + if(!lo2 && (y_lo >= pt2)) lo2 = k; + if(!lo3 && (y_lo >= pt3)) lo3 = k; + if(!hi1 && (y_hi <= pt1)) hi1 = j; + if(!hi2 && (y_hi <= pt2)) hi2 = j; + if(!hi3 && (y_hi <= pt3)) hi3 = j; + --j; + ++k; + } + + +// std::cout<<"xlo = "<<x[lo1]<<" ; "<<x[lo2]<<" ; "<<x[lo3]<<std::endl; +// std::cout<<"xhi = "<<x[hi1]<<" ; "<<x[hi2]<<" ; "<<x[hi3]<<std::endl; + + + x1 = (x[lo1] + x[hi1]) / 2; + x2 = (x[lo2] + x[hi2]) / 2; + x3 = (x[lo3] + x[hi3]) / 2; + +// std::cout<<"x(1,2,3) = "<<x1<<" ; "<<x2<<" ; "<<x3<<std::endl; + + + // mu = threshold + + sParams->mu = x2; + sigma = ( (x3 - x1) * 7071 ) / 100; + + if(sigma < minSigma) { + sigma = minSigma; + } + + status = 0; + } + + + sParams->sigma= sigma; // this should actually be 1000 * sigma. + + // std::cout<<"mu = "<<sParams->mu<<" ; sigma = "<<sigma<<std::endl; + +// #ifdef ppc405 +// time2= RceSvc::ticks(); +// printf("sGuess fit time %f\n",(float)(time2-time1)/350.); +// #endif + + + return status; //0 = success + + +} + + +template<typename TP, typename TE> +int FitScurveLikelihoodFastInt<TP, TE>::roughFitRange(FitData *pfdi, FitData *pfdo, int& maxVal) { + //For use in crosstalk scan. Determines the start and end of the fit range, without requirement + //that the data y-values reach a plateau close to the number of triggers. + //Sets maxVal to the highest y-value in the data, and the start and end of the fit range are + //the points where y<0.2*maxVal and y>0.8*maxVal, respectively. + + + int nBins, status; + UINT32 *x; + UINT8 *y; + + status = 1; //1: failure + + int hitsStart, hitsEnd; + + nBins = pfdi->n; + y = pfdi->y; + x = pfdi->x; + + for(hitsStart = 0; hitsStart < nBins; ++hitsStart){ + if(y[hitsStart] != 0) break; + } + + if(hitsStart == (nBins-1)) //require more than one bin containing hits + return status; + if(hitsStart == 0) //require first bin to be empty + return status; + + if(y[nBins - 1] ==0){ //require hits in final bin + return status; + } + + + maxVal=0; + //set maxVal equal to highest y value + for(int iBin = nBins-1; iBin >= 0; --iBin){ + if(y[iBin] > maxVal){ + maxVal = y[iBin]; + hitsEnd = iBin; + } + } + + if(hitsEnd<hitsStart){ + return status; + } + + int firstBin=0, lastBin=0; + + //std::cout<<"hitsStart = "<<hitsStart<<" ; hitsEnd = "<<hitsEnd<<std::endl; + + for(int iBin = (hitsStart-1); iBin <=hitsEnd; ++iBin){ + if(y[iBin] >= 0.8*maxVal){ + lastBin = iBin; + break; + } + } + + for(int iBin = (hitsStart-1); iBin <=hitsEnd; ++iBin){ + if(y[iBin] >= 0.2*maxVal){ + firstBin = iBin-1; + break; + } + } + + // std::cout<<"firstBin = "<<firstBin<<" ; LastBin = "<<lastBin<<std::endl; + + if(firstBin>=lastBin){ + return status; + } + + //Successfully determined first and last bin + nBins = 1 + lastBin - firstBin; + + pfdo->n = nBins; + pfdo->y = &y[firstBin]; + pfdo->x = &x[firstBin]; + + return nBins; + +} diff --git a/rce/rcecalib/dataproc/fit/FitScurveLikelihoodFastInt.hh b/rce/rcecalib/dataproc/fit/FitScurveLikelihoodFastInt.hh new file mode 100644 index 00000000..1e92a06b --- /dev/null +++ b/rce/rcecalib/dataproc/fit/FitScurveLikelihoodFastInt.hh @@ -0,0 +1,77 @@ +#ifndef FITSCURVELIKELIHOODFASTINT_HH +#define FITSCURVELIKELIHOODFASTINT_HH +#include "rcecalib/dataproc/fit/AbsFit.hh" +#include "rcecalib/util/RceHisto2d.cc" +#include <vector> + +template<typename TP, typename TE> +class FitScurveLikelihoodFastInt:public AbsFit { + +typedef unsigned int UINT32; +typedef int INT32; +typedef unsigned long long UINT64; +typedef long long INT64; +typedef unsigned char UINT8; + +typedef struct FitData_ +{ + UINT32 n; + UINT32 *x; + UINT8 *y; +} FitData; + +typedef struct FitResult_ +{ + INT32 ndf; + INT32 mu0; + INT32 sigma; //inverted sigma + INT32 chi2; +} FitResult; + +typedef struct GaussianCurve_ +{ + UINT32 mu, a0; + UINT32 sigma; +} GaussianCurve; + +typedef struct { + INT32 muEpsilon; + INT32 sigmaEpsilon; /* user provides convergence criterion */ + INT32 nIters; + INT32 ndf; /* number of degrees of freedom */ + INT32 chi2; /* final result for chi2 */ + INT32 converge; + INT32 maxIters; + void *curve; +} Fit; +#define sc_lut_width (FAST_LUT_WIDTH << 16) +#define logx_length (2*FAST_LUT_LENGTH) +#define sc_lut_length ((FAST_LUT_LENGTH - 1) << 16) + +public: +FitScurveLikelihoodFastInt(ConfigIF *cif,std::vector<std::vector<RceHisto2d<TP, TE>*> > &histo,std::vector<int> &vcal, int nTrigger, const char* name=""); + ~FitScurveLikelihoodFastInt(); + int doFit(int); +protected: + inline INT32 *log_ext(INT32 x, INT32 mu,INT32 sigma); + UINT32 errf_ext(INT32 x, GaussianCurve *psp); + inline UINT32 logLikelihood(FitData *pfd, GaussianCurve *s); + int initFit(Fit *pFit); + int extractGoodData(FitData *pfdi,FitData *pfdo, UINT32 nTriggers); + int initialGuess(FitData *pfd, GaussianCurve *pSParams); + int fitPixel(FitData *pfd,void *vpfit); + UINT32 chiSquared(FitData *pfd,GaussianCurve *s); + int sGuess(FitData *pfd, void *vpfit); + int roughFitRange(FitData *pfdi, FitData *pfdo, int& maxVal); + Fit m_fit; + UINT32 *m_x; + UINT8 *m_y; + std::vector<std::vector<RceHisto2d<TP, TE>*> > &m_histo; + std::vector<std::vector<RceHisto2d<float, float>*> > m_fithisto; + const char* m_name; + +}; + + + +#endif diff --git a/rce/rcecalib/dataproc/fit/FitScurveLikelihoodFloat.cc b/rce/rcecalib/dataproc/fit/FitScurveLikelihoodFloat.cc new file mode 100644 index 00000000..ff99f23e --- /dev/null +++ b/rce/rcecalib/dataproc/fit/FitScurveLikelihoodFloat.cc @@ -0,0 +1,461 @@ +#include "rcecalib/dataproc/fit/FitScurveLikelihoodFloat.hh" +#include "rcecalib/dataproc/fit/FitData.hh" +#include "rcecalib/config/ConfigIF.hh" +#include <stdio.h> +#include <iostream> + +template<typename TP, typename TE> +FitScurveLikelihoodFloat<TP, TE>::FitScurveLikelihoodFloat(ConfigIF *cif,std::vector<std::vector<RceHisto2d<TP, TE>*> > &histo,std::vector<int> &vcal,int nTrigger):AbsFit(cif,vcal,nTrigger),m_histo(histo) { + initFit(&m_fit); +} + +template<typename TP, typename TE> +FitScurveLikelihoodFloat<TP, TE>::~FitScurveLikelihoodFloat() +{ + for(unsigned int module=0;module<m_config->getNmodules();module++) { + for(size_t i=0;i<m_fithisto[module].size();i++){ + delete m_fithisto[module][i]; + } + } +} + +template<typename TP, typename TE> +int FitScurveLikelihoodFloat<TP, TE>::doFit() { + FitData pfdi,pfdo; + GaussianCurve gc; + int nBins=m_vcal.size(); + if(!nBins) return -1; + m_x=new float[nBins]; + m_y=new float[nBins]; + + for(unsigned int module=0;module<m_config->getNmodules();module++) { + int nRows= m_config->getModuleInfo(module).getNRows(); + int nCols=m_config->getModuleInfo(module).getNColumns(); + //int nHistos=m_histo[module].size(); + std::cout << "nTrigger " << m_nTrigger << std::endl; + for(int chip=0;chip<m_config->getModuleInfo(module).getNFrontends();chip++) { + /* apply dac to electron calibration */ + for(int bin=0;bin<nBins;bin++) { + m_x[bin]=m_config->dacToElectrons(module,chip,m_vcal[bin]); + } + for(int col=0;col<nCols;col++) { + for(int row=0;row<nRows;row++) { + // extract S-Curve + for(int bin=0;bin<nBins;bin++) { + m_y[bin]=(*m_histo[module][bin])(row, chip*nCols+col); + } + pfdi.n=nBins; + pfdi.x=&m_x[0]; + pfdi.y=&m_y[0]; + int goodBins=extractGoodData(&pfdi,&pfdo,m_nTrigger); + if(goodBins<5) continue; + m_fit.curve=&gc; + m_fit.maxIters=100; + gc.a0=m_nTrigger; + int result=fitPixel(&pfdo,&m_fit); + if(!result) { + m_fithisto[module][0]->set(chip*nCols+col,row,gc.mu); + m_fithisto[module][1]->set(chip*nCols+col,row,gc.sigma); + m_fithisto[module][2]->set(chip*nCols+col,row,m_fit.chi2); + m_fithisto[module][3]->set(chip*nCols+col,row,(float) m_fit.nIters); + printf("%d %d %d %f %f %f %d\n",chip,col,row,gc.mu,gc.sigma,m_fit.chi2,m_fit.nIters); + } + } //rows + } //columns + } //chips + } // modules + delete [] m_x; + delete [] m_y; + return 0; +} +template<typename TP, typename TE> +float* FitScurveLikelihoodFloat<TP, TE>::log_ext(float x, GaussianCurve *psp) { + float u, t; + int n; + u = (x - psp->mu) / psp->sigma; + t = u * inverse_lut_interval; + n = LUT_WIDTH + (int)t; + if(n < 0) n = 0; + if(n >= LUT_LENGTH) n = LUT_LENGTH-1; // truncate at last value + n = 2 * n; + return (float*)&FitDataFloat::data_logx[n]; +} +template<typename TP, typename TE> +float FitScurveLikelihoodFloat<TP, TE>::errf_ext(float x, GaussianCurve *psp) { + float u, t; + int n; + + u = (x - psp->mu) / psp->sigma; + t = u * inverse_lut_interval; + n = LUT_WIDTH + (int)t; + if(n < 0) n = 0; + if(n >= LUT_LENGTH) n = LUT_LENGTH-1; // truncate at last value + return FitDataFloat::data_errf[n]; +} +template<typename TP, typename TE> +float FitScurveLikelihoodFloat<TP, TE>::logLikelihood(FitData *pfd, GaussianCurve *s) { + float acc, r, y2, y3, N; + float *x, *y, *p; + int k, n; + x = pfd->x; y = pfd->y; n = pfd->n; + acc = 0.0f; + N = s->a0; + for(k=0;k<n;++k) { + r = *y++; /* data point */ + p = log_ext(*x++,s); /* pointer to log(probability) */ + y2 = r * (*p++); /* log(prob) */ + y3 = (N - r) * (*p); /* log(1-prob) */ + acc -= (y2 + y3); + } + return acc; +} + +template<typename TP, typename TE> +int FitScurveLikelihoodFloat<TP, TE>::initFit(Fit *pFit) { + pFit->deltaSigma = 0.1f; + pFit->deltaMu = 0.1f; + pFit->maxIters = 100; + pFit->muEpsilon = 0.0001f; /* 0.01% */ + pFit->sigmaEpsilon = 0.0001f; /* 0.01% */ + /* create histograms */ + for (unsigned int i=0;i<m_config->getNmodules();i++){ + std::vector<RceHisto2d<float, float>*> vh; + m_fithisto.push_back(vh); + char name[128]; + //char title[128]; + int rows=m_config->getModuleInfo(i).getNRows(); + int cols=m_config->getModuleInfo(i).getNColumns()*m_config->getModuleInfo(i).getNFrontends(); + int id=m_config->getModuleInfo(i).getId(); + sprintf(name,"Mod_%d_Mean",id); + m_fithisto[i].push_back(new RceHisto2d<float, float>(name,"SCURVE_MEAN",cols,0,cols,rows, 0, rows)); + sprintf(name,"Mod_%d_Sigma",id); + m_fithisto[i].push_back(new RceHisto2d<float, float>(name,"SCURVE_SIGMA",cols,0,cols,rows, 0, rows)); + sprintf(name,"Mod_%d_ChiSquare",id); + m_fithisto[i].push_back(new RceHisto2d<float, float>(name,"SCURVE_CHI2",cols,0,cols,rows, 0, rows)); + sprintf(name,"Mod_%d_Iter",id); + m_fithisto[i].push_back(new RceHisto2d<float, float>(name,"SCURVE_ITER",cols,0,cols,rows, 0, rows)); + } + // allocate fit data buffer + + + return 0; +} +template<typename TP, typename TE> +int FitScurveLikelihoodFloat<TP, TE>::extractGoodData(FitData *pfdi,FitData *pfdo, float scanA0) { + int hitsStart, hitsEnd, nBins; + float a0, *y; + + nBins = pfdi->n; + y = pfdi->y; + + //new method to find hitsStart + for(hitsStart = nBins-1;hitsStart >= 0; --hitsStart) + if(y[hitsStart] == 0) break; + + if(hitsStart ==0) + return 0; + if(hitsStart == nBins) + return 0; + a0 = 0.999f * y[nBins - 1]; // just under last bin + if(a0 < 0.9 * scanA0) + return 0; + //failure mode, never reaches A0 + + for(hitsEnd = hitsStart; hitsEnd < nBins; ++hitsEnd) + if(y[hitsEnd] > a0) break; + nBins = 1 + hitsEnd - hitsStart; + if(hitsStart < 0) + hitsStart =0; + + if(hitsStart == hitsEnd) + return 0; + + if(nBins < 2) { + return 0; + //failure mode :: not enough data points + } + if(nBins < 0) nBins = 0; + pfdo->n = nBins; + + pfdo->y = &y[hitsStart]; + pfdo->x = &pfdi->x[hitsStart]; + return nBins; +} + +template<typename TP, typename TE> +int FitScurveLikelihoodFloat<TP, TE>::initialGuess(FitData *pfd, GaussianCurve *pSParams){ +#define invRoot6f 0.40824829046f +#define invRoot2f 0.7071067811f + float pt1, pt2, pt3, *pdlo, *pdhi, y_lo, y_hi, x1, x2, x3, sigma; + float *x, *y, a0, minSigma; + int j, k, n, lo1, lo2, lo3, hi1, hi2, hi3, status; + + pSParams->a0 = pfd->y[pfd->n-1]; // assumes last data point sets plateau + a0 = pSParams->a0; + a0 -= 0.00001f; // skim a token amount to ensure comparisons succeed + + n = pfd->n; // number of samples + + minSigma = (pfd->x[1] - pfd->x[0]) * invRoot6f; + + x = pfd->x; y = pfd->y; + pt1 = 0.16f * a0; + pt2 = 0.50f * a0; + pt3 = 0.84f * a0; + // find the range over which the data crosses the 16%, 50% and 84% points + hi1 = hi2 = hi3 = 0; // invalid values + lo1 = lo2 = lo3 = 0; // invalid values + pdlo = &y[0]; // y + pdhi = &y[n-1]; // y + n - 1 + // important note: for the sake of speed we want to perform as few comparisons as + //possible. Therefore, the integer comparison occurs first in each of the + //following operations. Depending on the logical value thereof, the next + //comparison will be made only if necessary. To further expedite the code, + //arrays are not used because there are only three members + j = n - 1; + for(k=0;k<n;++pdlo, --pdhi) { + y_lo = *pdlo; + y_hi = *pdhi; + if(!lo1 && (y_lo >= pt1)) lo1 = k; + if(!lo2 && (y_lo >= pt2)) lo2 = k; + if(!lo3 && (y_lo >= pt3)) lo3 = k; + if(!hi1 && (y_hi <= pt1)) hi1 = j; + if(!hi2 && (y_hi <= pt2)) hi2 = j; + if(!hi3 && (y_hi <= pt3)) hi3 = j; + --j; + ++k; + } + x1 = (x[lo1] + x[hi1]) * 0.5f; + x2 = (x[lo2] + x[hi2]) * 0.5f; + x3 = (x[lo3] + x[hi3]) * 0.5f; + + pSParams->mu = x2; + + sigma = (x3 - x1) * invRoot2f; + + if(sigma < minSigma) { + sigma = minSigma; + } + pSParams->sigma=sigma; + status = 0; + + return status; +} + +template<typename TP, typename TE> +int FitScurveLikelihoodFloat<TP, TE>::fitPixel(FitData *pfd,void *vpfit) +{ + float deltaSigma, deltaMu, sigma, chi2Min, *fptr; + float chi2[9]; + GaussianCurve sParams, sParamsWork, *psp; + int k, dirMin; + Fit *pFit; + pFit = (Fit *)vpfit; + + pFit->nIters = 0; + pFit->converge = 0; // assume no convergence + + pFit->ndf = pfd->n - 2; // degrees of freedom + + // take a guess at the S-curve parameters + + if(initialGuess(pfd,&sParams)) { + psp = (GaussianCurve *)pFit->curve; + psp->a0 = sParams.a0; + psp->mu = sParams.mu; + psp->sigma = sParams.sigma; + pFit->converge = 1; + pFit->muConverge = 0; + pFit->sigmaConverge = 0; + pFit->chi2 = 0.0f; + return 0; + } + + // initialize loop parameters + psp = &sParamsWork; + psp->a0 = sParams.a0; + deltaSigma = pFit->deltaSigma * sParams.sigma; // scaled + deltaMu = pFit->deltaMu * sParams.mu; // scaled + //* the loop begins * + // printf("delta %f %f\n",deltaSigma,deltaMu); + while(!pFit->converge && (pFit->nIters++ < pFit->maxIters)) { + + dirMin = 0; + fptr = chi2; + for(k=0;k<9;++k) *fptr++ = 0.0f; + + while((dirMin >= 0) && (pFit->nIters++ < pFit->maxIters)) { + //* calculate neighboring points * + //* calculate neighboring points * + psp->sigma=sParams.sigma - deltaSigma; + psp->mu = sParams.mu - deltaMu; + if(chi2[0] == 0.0f) + chi2[0] = logLikelihood(pfd,psp); + psp->mu = sParams.mu; + if(chi2[7] == 0.0f) + chi2[7] = logLikelihood(pfd,psp); + psp->mu = sParams.mu + deltaMu; + if(chi2[6] == 0.0f) + chi2[6] = logLikelihood(pfd,psp); + + psp->sigma=sParams.sigma; + psp->mu = sParams.mu - deltaMu; + if(chi2[1] == 0.0f) + chi2[1] = logLikelihood(pfd,psp); + psp->mu = sParams.mu; + if(chi2[8] == 0.0f) + chi2[8] = logLikelihood(pfd,psp); + psp->mu = sParams.mu + deltaMu; + if(chi2[5] == 0.0f) + chi2[5] = logLikelihood(pfd,psp); + + psp->sigma=sParams.sigma+deltaSigma; + psp->mu = sParams.mu - deltaMu; + if(chi2[2] == 0.0f) + chi2[2] = logLikelihood(pfd,psp); + psp->mu = sParams.mu; + if(chi2[3] == 0.0f) + chi2[3] = logLikelihood(pfd,psp); + psp->mu = sParams.mu + deltaMu; + if(chi2[4] == 0.0f) + chi2[4] = logLikelihood(pfd,psp); + + dirMin = -1; + chi2Min = chi2[8]; // first guess at minimum + for(k=0, fptr=chi2;k<8;++k, ++fptr) { + if(*fptr < chi2Min) { + chi2Min = *fptr; + dirMin = k; + } + } + switch(dirMin) { + case -1: + deltaSigma = deltaSigma * 0.1f; + deltaMu = deltaMu * 0.1f; + break; + case 0: + sigma = sParams.sigma - deltaSigma; + sParams.sigma=sigma; + sParams.mu = sParams.mu - deltaMu; + chi2[8] = chi2[0]; + chi2[3] = chi2[1]; + chi2[4] = chi2[8]; + chi2[5] = chi2[7]; + chi2[0] = chi2[1] = chi2[2] = + chi2[6] = chi2[7] = 0.0f; + break; + case 1: + sParams.mu = sParams.mu - deltaMu; + chi2[8] = chi2[1]; + chi2[3] = chi2[2]; + chi2[4] = chi2[3]; + chi2[5] = chi2[8]; + chi2[6] = chi2[7]; + chi2[7] = chi2[0]; + chi2[0] = chi2[1] = chi2[2] = 0.0f; + break; + case 2: + sigma = sParams.sigma + deltaSigma; + sParams.sigma=sigma; + sParams.mu = sParams.mu - deltaMu; + chi2[8] = chi2[2]; + chi2[5] = chi2[3]; + chi2[6] = chi2[8]; + chi2[7] = chi2[1]; + chi2[0] = chi2[1] = chi2[2] = + chi2[3] = chi2[4] = 0.0f; + break; + case 3: + sigma = sParams.sigma + deltaSigma; + sParams.sigma=sigma; + chi2[8] = chi2[3]; + chi2[5] = chi2[4]; + chi2[6] = chi2[5]; + chi2[7] = chi2[8]; + chi2[0] = chi2[1]; + chi2[1] = chi2[2]; + chi2[2] = chi2[3] = chi2[4] = 0.0f; + break; + case 4: + sigma = sParams.sigma + deltaSigma; + sParams.sigma=sigma; + sParams.mu = sParams.mu + deltaMu; + chi2[8] = chi2[4]; + chi2[7] = chi2[5]; + chi2[0] = chi2[8]; + chi2[1] = chi2[3]; + chi2[2] = chi2[3] = chi2[4] = + chi2[5] = chi2[6] = 0.0f; + break; + case 5: + sParams.mu = sParams.mu + deltaMu; + chi2[8] = chi2[5]; + chi2[7] = chi2[6]; + chi2[0] = chi2[7]; + chi2[1] = chi2[8]; + chi2[2] = chi2[3]; + chi2[3] = chi2[4]; + chi2[4] = chi2[5] = chi2[6] = 0.0f; + break; + case 6: + sigma = sParams.sigma - deltaSigma; + sParams.sigma=sigma; + sParams.mu = sParams.mu + deltaMu; + chi2[8] = chi2[6]; + chi2[1] = chi2[7]; + chi2[2] = chi2[8]; + chi2[3] = chi2[5]; + chi2[4] = chi2[5] = chi2[6] = + chi2[7] = chi2[0] = 0.0f; + break; + case 7: + sigma = sParams.sigma - deltaSigma; + sParams.sigma=sigma; + chi2[8] = chi2[7]; + chi2[1] = chi2[0]; + chi2[2] = chi2[1]; + chi2[3] = chi2[8]; + chi2[4] = chi2[5]; + chi2[5] = chi2[6]; + chi2[6] = chi2[7] = chi2[0] = 0.0f; + break; + } + } + + if(deltaSigma < (pFit->sigmaEpsilon * sParams.sigma) && + deltaMu < (pFit->muEpsilon * sParams.mu)) { + pFit->converge = 1; + break; + } + } + psp = (GaussianCurve *)pFit->curve; + *psp = sParams; + pFit->chi2=chiSquared(pfd,psp)/(float) pFit->ndf; + //static int d=0; + + // printf("%f %f %f \n",psp->mu,psp->sigma,pFit->chi2); + + return pFit->converge ? 0 : 1; // 0 = success +} +template<typename TP, typename TE> +float FitScurveLikelihoodFloat<TP, TE>::chiSquared(FitData *pfd,GaussianCurve *s) { + float acc, y0,y1,y2,y3, a0, chi2; + float *x, *y; + float x0; + int j, k, n; + x = pfd->x; y = pfd->y; n = pfd->n; + acc = 0.0f; + a0 = s->a0; + /* use binomial weighting */ + for(k=0;k<n;++k) { + x0 = *x++; + y0 = *y++; + y1 = errf_ext(x0,s); + j = (int)(y1 * inverse_weight_lut_interval); + y2 = y0 - a0 * y1; + y3 = y2 * y2; + acc += (y3 * FitDataFloat::binomial_weight[j]); + } + chi2 = acc/ a0; + return chi2; +} diff --git a/rce/rcecalib/dataproc/fit/FitScurveLikelihoodFloat.hh b/rce/rcecalib/dataproc/fit/FitScurveLikelihoodFloat.hh new file mode 100644 index 00000000..5c63d3cb --- /dev/null +++ b/rce/rcecalib/dataproc/fit/FitScurveLikelihoodFloat.hh @@ -0,0 +1,57 @@ +#ifndef FITSCURVELIKELIHOODFLOAT_HH +#define FITSCURVELIKELIHOODFLOAT_HH +#include "rcecalib/dataproc/fit/AbsFit.hh" +#include "rcecalib/util/RceHisto2d.cc" +#include "rcecalib/config/ConfigIF.hh" + +template<typename TP, typename TE> +class FitScurveLikelihoodFloat:public AbsFit { + + + typedef struct + { + float mu, sigma, a0; + } GaussianCurve; + + typedef struct { + float deltaMu, deltaSigma; /* user provides initial deltaMu and deltaSigma */ + float muEpsilon, sigmaEpsilon; /* user provides convergence criterion */ + int nIters; + int ndf; /* number of degrees of freedom */ + float chi2; /* final result for chi2 */ + int converge; + float muConverge,sigmaConverge; + int maxIters; + void *curve; + } Fit; + + typedef struct + { + unsigned int n; + float *x; + float *y; + } FitData; + + +public: + FitScurveLikelihoodFloat(ConfigIF *cif,std::vector<std::vector<RceHisto2d<TP, TE>*> > &histo,std::vector<int> &vcal, int nTrigger); + int doFit(); + ~FitScurveLikelihoodFloat(); +protected: + inline float *log_ext(float x, GaussianCurve *psp); + float errf_ext(float x, GaussianCurve *psp); + float logLikelihood(FitData *pfd, GaussianCurve *s); + int initFit(Fit *pFit); + int extractGoodData(FitData *pfdi,FitData *pfdo, float scanA0); + int initialGuess(FitData *pfd, GaussianCurve *pSParams); + int fitPixel(FitData *pfd,void *vpfit); + float chiSquared(FitData *pfd,GaussianCurve *s); + Fit m_fit; + /* buffer for fit data */ + float *m_x; + float *m_y; + std::vector<std::vector<RceHisto2d<TP, TE>*> > &m_histo; + std::vector<std::vector<RceHisto2d<float, float>*> > m_fithisto; +}; + +#endif diff --git a/rce/rcecalib/dataproc/fit/FitScurveLikelihoodInt.cc b/rce/rcecalib/dataproc/fit/FitScurveLikelihoodInt.cc new file mode 100644 index 00000000..640bfd14 --- /dev/null +++ b/rce/rcecalib/dataproc/fit/FitScurveLikelihoodInt.cc @@ -0,0 +1,543 @@ +#include "rcecalib/dataproc/fit/FitScurveLikelihoodInt.hh" +#include "rcecalib/dataproc/fit/FitData.hh" +#include "rcecalib/config/ConfigIF.hh" +#include <iostream> +#include <stdio.h> + +template<typename TP, typename TE> +FitScurveLikelihoodInt<TP, TE>::FitScurveLikelihoodInt(ConfigIF *cif,std::vector<std::vector<RceHisto2d<TP, TE>*> > &histo,std::vector<int> &vcal,int nTrigger,const char* name):AbsFit(cif,vcal,nTrigger),m_histo(histo),m_name(name) { + initFit(&m_fit); +} + +template<typename TP, typename TE> +FitScurveLikelihoodInt<TP, TE>::~FitScurveLikelihoodInt(){ + for(unsigned int module=0;module<m_fithisto.size();module++) { + for(size_t i=0;i<m_fithisto[module].size();i++){ + delete m_fithisto[module][i]; + } + } +} + + +template<typename TP, typename TE> +int FitScurveLikelihoodInt<TP, TE>::doFit(int fitopt) { + FitData pfdi,pfdo; + GaussianCurve gc; + int nBins=m_vcal.size(); + if(!nBins) return -1; + m_x=new UINT32[nBins]; + m_y=new UINT8[nBins]; + + for(unsigned int module=0;module<m_config->getNmodules();module++) { + int nRows= m_config->getModuleInfo(module).getNRows(); + int nCols=m_config->getModuleInfo(module).getNColumns(); + //int nHistos=m_histo[module].size(); + std::cout << "nTrigger " << m_nTrigger << std::endl; + for(int chip=0;chip<m_config->getModuleInfo(module).getNFrontends();chip++) { + if((fitopt&NOCONV)==0) { + /* apply dac to electron calibration */ + for(int bin=0;bin<nBins;bin++) { + /* for now we use float here */ + m_x[bin]=(UINT32)m_config->dacToElectrons(module,chip,m_vcal[bin])*10; + } + } else { + for(int bin=0;bin<nBins;bin++) { + /* for now we use float here */ + m_x[bin]=m_vcal[bin]*10; + } + } + for(int col=0;col<nCols;col++) { + for(int row=0;row<nRows;row++) { + // extract S-Curve + for(int bin=0;bin<nBins;bin++) { + m_y[bin]=(UINT8)(*m_histo[module][bin])(row, chip*nCols+col); + } + pfdi.n=nBins; + pfdi.x=&m_x[0]; + pfdi.y=&m_y[0]; + int goodBins=extractGoodData(&pfdi,&pfdo,m_nTrigger); + if(goodBins<5) continue; + m_fit.curve=&gc; + m_fit.maxIters=100; + gc.a0=m_nTrigger; + int result=fitPixel(&pfdo,&m_fit); + if(!result) { + m_fithisto[module][0]->set(chip*nCols+col,row,(double)gc.mu/10000.); + m_fithisto[module][1]->set(chip*nCols+col,row,(double)gc.sigma/10000.); + m_fithisto[module][2]->set(chip*nCols+col,row,(double)m_fit.chi2/100000.); + m_fithisto[module][3]->set(chip*nCols+col,row,(double) m_fit.nIters); + // printf("%d %d %d %f %f %f %d\n",chip,col,row,gc.mu/10000.,gc.sigma/10000.,m_fit.chi2/100000.,m_fit.nIters); + } + } //rows + } //columns + } //chips + } // modules + delete [] m_x; + delete [] m_y; + return 0; +} + +template<typename TP, typename TE> +typename FitScurveLikelihoodInt<TP, TE>::INT32 *FitScurveLikelihoodInt<TP, TE>::log_ext(INT32 x, GaussianCurve *psp) { + INT32 t; + INT32 u; + int n; + INT64 i64a,i64b; + u=(x*100 - psp->mu/100); + i64a=u; + i64a*=10000000LL; + i64b=(INT64) psp->sigma; + i64a/=i64b; + t = (INT32) i64a; + n = (UINT32) LUT_WIDTH + (UINT32)t; + if(n < 0) n = 0; + if(n >= LUT_LENGTH) n = LUT_LENGTH-1; // truncate at last value + n = 2 * n; + return (INT32*) &FitDataInt::data_logx[n]; +} + +template<typename TP, typename TE> +typename FitScurveLikelihoodInt<TP, TE>::UINT32 FitScurveLikelihoodInt<TP, TE>::errf_ext(INT32 x, GaussianCurve *psp) { + INT32 t; + INT32 u; + INT64 i64a,i64b; + int n; + u = (x*100 - psp->mu/100); + i64a=(INT64) u; + i64a*=10000000LL; + i64b=(INT64) psp->sigma; + i64a/=i64b; + t = (INT32) i64a; + n = LUT_WIDTH + (UINT32)t; + if(n < 0) n = 0; + if(n >= LUT_LENGTH) n = LUT_LENGTH-1; // truncate at last value + return FitDataInt::data_errf[n]; +} + +template<typename TP, typename TE> +typename FitScurveLikelihoodInt<TP, TE>::UINT32 FitScurveLikelihoodInt<TP, TE>::logLikelihood(FitData *pfd, GaussianCurve *s) { + INT32 r, N; + INT64 acc,y2,y3; + UINT32 *x; + UINT8 *y; + UINT32 ret; + INT32 *p; + INT64 i64; + int k, n; + x = pfd->x; y = pfd->y; n = pfd->n; + acc = 0; + N = s->a0; + for(k=0;k<n;++k) { + r = *y++; /* data point */ + p = log_ext(*x++,s); /* pointer to log(probability) */ + y2=(INT64) r; + i64=(INT64)*p++; + y2*=i64; + y3=(N - r); + i64=*p; + y3*=i64; + acc -= (y2 + y3); + } + acc/=10000ULL; + ret=(UINT32) (acc); + return (ret); +} + +template<typename TP, typename TE> +int FitScurveLikelihoodInt<TP, TE>::initFit(Fit *pFit) { + pFit->deltaSigma = 1000; + pFit->deltaMu = 1000; + pFit->maxIters = 100; + pFit->muEpsilon = 1; /* 0.01% */ + pFit->sigmaEpsilon = 1; /* 0.01% */ + for (unsigned int i=0;i<m_config->getNmodules();i++){ + std::vector<RceHisto2d<float, float>*> vh; + m_fithisto.push_back(vh); + char name[128]; + char title[128]; + char suffix[128]=""; + if(std::string(m_name)!=""){ + sprintf(suffix,"%s_",m_name); + } + + int rows=m_config->getModuleInfo(i).getNRows(); + int cols=m_config->getModuleInfo(i).getNColumns()*m_config->getModuleInfo(i).getNFrontends(); + int id=m_config->getModuleInfo(i).getId(); + std::string modName=m_config->getModuleInfo(i).getName(); + sprintf(name,"Mod_%d_%sMean", id, suffix); + sprintf(title,"MOD %d %s at %s SCURVE MEAN", id, suffix, modName.c_str()); + m_fithisto[i].push_back(new RceHisto2d<float, float>(name,title,cols,0,cols,rows, 0, rows)); + sprintf(title,"MOD %d %s at %s SCURVE SIGMA", id, suffix, modName.c_str()); + sprintf(name,"Mod_%d_%sSigma", id, suffix); + m_fithisto[i].push_back(new RceHisto2d<float, float>(name,title,cols,0,cols,rows, 0, rows)); + sprintf(title,"MOD %d %s at %s SCURVE CHI2", id, suffix, modName.c_str()); + sprintf(name,"Mod_%d_%sChiSquare", id, suffix); + m_fithisto[i].push_back(new RceHisto2d<float, float>(name,title,cols,0,cols,rows, 0, rows)); + sprintf(title,"MOD %d %s at %s SCURVE ITER", id, suffix, modName.c_str()); + sprintf(name,"Mod_%d_%sIter", id, suffix); + m_fithisto[i].push_back(new RceHisto2d<float, float>(name,title,cols,0,cols,rows, 0, rows)); + } + return 0; +} + +template<typename TP, typename TE> +int FitScurveLikelihoodInt<TP, TE>::extractGoodData(FitData *pfdi,FitData *pfdo, UINT32 nTriggers) { + int hitsStart, hitsEnd, nBins; + UINT32 a0; + UINT8 *y; + + nBins = pfdi->n; + y = pfdi->y; + + //new method to find hitsStart + + for(hitsStart = nBins-1;hitsStart >= 0; --hitsStart) + if(y[hitsStart] == 0) break; + + if(hitsStart ==0) + return 0; + if(hitsStart == nBins) + return 0; + + a0 = y[nBins - 1]; // last bin has at least 90% hits + if(a0*999 < nTriggers*900) + return 0; + //failure mode, never reaches A0 + + //dan's new method + for(hitsEnd = hitsStart; hitsEnd < nBins; ++hitsEnd) + if(y[hitsEnd] >= a0) break; + + // add 2 for old method or 1 for new method + // 1 because of where we start comparing and + // 1 because we want to include one instance of the maximum + nBins = 1 + hitsEnd - hitsStart; + + if(hitsStart < 0) hitsStart =0; + + if(hitsStart == hitsEnd) return 0; + + if(nBins < 2) { + return 0; + //failure mode :: not enough data points + } + if(nBins < 0) nBins = 0; + pfdo->n = nBins; + pfdo->y = &y[hitsStart]; + pfdo->x = &pfdi->x[hitsStart]; + return nBins; +} + + +template<typename TP, typename TE> +int FitScurveLikelihoodInt<TP, TE>::initialGuess(FitData *pfd, GaussianCurve *pSParams) { +#define invRoot6 4082482904LL +#define invRoot2 7071067811ULL + UINT32 pt1, pt2, pt3; + UINT8 *pdlo, *pdhi; + UINT32 y_lo, y_hi, sigma; + UINT32 *x; + UINT8 *y; + UINT32 a0; + UINT32 minSigma; + UINT32 j, k, n, lo1, lo2, lo3, hi1, hi2, hi3, status; + UINT32 x1,x2,x3; + UINT64 u64; + INT64 i64; + INT32 xdiff; + + n = pfd->n; + if(n<5) return 1; + pSParams->a0 = pfd->y[pfd->n-1]; // assumes last data point sets plateau + a0 = pSParams->a0*100000-1; // skim a token amount to ensure comparisons succeed + xdiff=pfd->x[1] - pfd->x[0]; + i64=(INT64) xdiff; + i64*=invRoot6; + i64/=100000000000LL; + minSigma = (UINT32) i64; + // minSigma = (UINT32) (((INT64) (pfd->x[1] - pfd->x[0])) * invRoot6) / 1000000LL; + + x = pfd->x; y = pfd->y; + pt1 = 16* a0; + pt2 = 50* a0; + pt3 = 84* a0; + // find the range over which the data crosses the 16%, 50% and 84% points + hi1 = hi2 = hi3 = 0; // invalid values + lo1 = lo2 = lo3 = 0; // invalid values + pdlo = &y[0]; // y + pdhi = &y[n-1]; // y + n - 1 + // important note: for the sake of speed we want to perform as few comparisons as + //possible. Therefore, the integer comparison occurs first in each of the + //following operations. Depending on the logical value thereof, the next + //comparison will be made only if necessary. To further expedite the code, + //arrays are not used because there are only three members + j = n - 1; + for(k=0;k<n;++pdlo, --pdhi) { + y_lo = (*pdlo)*10000000; + y_hi = (*pdhi)*10000000; + if(!lo1 && (y_lo >= pt1)) lo1 = k; + if(!lo2 && (y_lo >= pt2)) lo2 = k; + if(!lo3 && (y_lo >= pt3)) lo3 = k; + if(!hi1 && (y_hi <= pt1)) hi1 = j; + if(!hi2 && (y_hi <= pt2)) hi2 = j; + if(!hi3 && (y_hi <= pt3)) hi3 = j; + --j; + ++k; + } + x1 = (x[lo1] + x[hi1]) *5; + x2 = (x[lo2] + x[hi2]) *5; + x3 = (x[lo3] + x[hi3]) *5; + + // mu = threshold + + pSParams->mu = (UINT32) x2; + xdiff=(x3 - x1); + u64=(UINT64) xdiff; + u64*=invRoot2; + u64/=100000000LL; + sigma=(UINT32) u64; + if(sigma < minSigma) { + sigma = minSigma; + } + pSParams->sigma=sigma; + status = 0; + return status; +} +template<typename TP, typename TE> +int FitScurveLikelihoodInt<TP, TE>::fitPixel(FitData *pfd,void *vpfit) { + INT32 deltaSigma, deltaMu, sigma, chi2Min, *fptr; + INT32 chi2[9]; + UINT64 u64; + GaussianCurve sParams, sParamsWork, *psp; + int k, dirMin; + Fit *pFit; + pFit = (Fit *)vpfit; + + pFit->nIters = 0; + pFit->converge = 0; // assume no convergence + + pFit->ndf = pfd->n - 2; // degrees of freedom + + // take a guess at the S-curve parameters + + if(initialGuess(pfd,&sParams)) { + psp = (GaussianCurve *)pFit->curve; + psp->a0 = sParams.a0; + psp->mu = sParams.mu; + psp->sigma = sParams.sigma; + pFit->converge = 1; + pFit->muConverge = 0; + pFit->sigmaConverge = 0; + pFit->chi2 = 0; + return 0; + } + + // initialize loop parameters + psp = &sParamsWork; + psp->a0 = sParams.a0; + deltaSigma = sParams.sigma*100; // scaled + deltaMu = sParams.mu*100; // scaled + sParams.sigma*= pFit->deltaSigma; + sParams.mu*= pFit->deltaMu; + + + //* the loop begins * + // printf("delta %d %d\n",deltaSigma,deltaMu); + while(!pFit->converge && (pFit->nIters++ < pFit->maxIters)) { + dirMin = 0; + fptr = chi2; + for(k=0;k<9;++k) *fptr++ = 0; + + while((dirMin >= 0) && (pFit->nIters++ < pFit->maxIters)) { + + //* calculate neighboring points * + //* calculate neighboring points * + // printf("!! %d %d\n",sParams.sigma,deltaSigma); + psp->sigma=sParams.sigma - deltaSigma; + psp->mu = sParams.mu - deltaMu; + if(chi2[0] == 0) + chi2[0] = logLikelihood(pfd,psp); + psp->mu = sParams.mu; + if(chi2[7] == 0) + chi2[7] = logLikelihood(pfd,psp); + psp->mu = sParams.mu + deltaMu; + if(chi2[6] == 0) + chi2[6] = logLikelihood(pfd,psp); + + psp->sigma=sParams.sigma; + psp->mu = sParams.mu - deltaMu; + if(chi2[1] == 0) + chi2[1] = logLikelihood(pfd,psp); + psp->mu = sParams.mu; + if(chi2[8] == 0) + chi2[8] = logLikelihood(pfd,psp); + psp->mu = sParams.mu + deltaMu; + if(chi2[5] == 0) + chi2[5] = logLikelihood(pfd,psp); + + psp->sigma=sParams.sigma+deltaSigma; + psp->mu = sParams.mu - deltaMu; + if(chi2[2] == 0) + chi2[2] = logLikelihood(pfd,psp); + psp->mu = sParams.mu; + if(chi2[3] == 0) + chi2[3] = logLikelihood(pfd,psp); + psp->mu = sParams.mu + deltaMu; + if(chi2[4] == 0) + chi2[4] = logLikelihood(pfd,psp); + + dirMin = -1; + chi2Min = chi2[8]; // first guess at minimum + for(k=0, fptr=chi2;k<8;++k, ++fptr) { + if(*fptr < chi2Min) { + chi2Min = *fptr; + dirMin = k; + } + } + // printf("\n"); + switch(dirMin) { + case -1: + deltaSigma = deltaSigma /10; + deltaMu = deltaMu /10; + break; + case 0: + sigma = sParams.sigma - deltaSigma; + sParams.sigma=sigma; + sParams.mu = sParams.mu - deltaMu; + chi2[8] = chi2[0]; + chi2[3] = chi2[1]; + chi2[4] = chi2[8]; + chi2[5] = chi2[7]; + chi2[0] = chi2[1] = chi2[2] = + chi2[6] = chi2[7] = 0; + break; + case 1: + sParams.mu = sParams.mu - deltaMu; + chi2[8] = chi2[1]; + chi2[3] = chi2[2]; + chi2[4] = chi2[3]; + chi2[5] = chi2[8]; + chi2[6] = chi2[7]; + chi2[7] = chi2[0]; + chi2[0] = chi2[1] = chi2[2] = 0; + break; + case 2: + sigma = sParams.sigma + deltaSigma; + sParams.sigma=sigma; + sParams.mu = sParams.mu - deltaMu; + chi2[8] = chi2[2]; + chi2[5] = chi2[3]; + chi2[6] = chi2[8]; + chi2[7] = chi2[1]; + chi2[0] = chi2[1] = chi2[2] = + chi2[3] = chi2[4] = 0; + break; + case 3: + sigma = sParams.sigma + deltaSigma; + sParams.sigma=sigma; + chi2[8] = chi2[3]; + chi2[5] = chi2[4]; + chi2[6] = chi2[5]; + chi2[7] = chi2[8]; + chi2[0] = chi2[1]; + chi2[1] = chi2[2]; + chi2[2] = chi2[3] = chi2[4] = 0; + break; + case 4: + sigma = sParams.sigma + deltaSigma; + sParams.sigma=sigma; + sParams.mu = sParams.mu + deltaMu; + chi2[8] = chi2[4]; + chi2[7] = chi2[5]; + chi2[0] = chi2[8]; + chi2[1] = chi2[3]; + chi2[2] = chi2[3] = chi2[4] = + chi2[5] = chi2[6] = 0; + break; + case 5: + sParams.mu = sParams.mu + deltaMu; + chi2[8] = chi2[5]; + chi2[7] = chi2[6]; + chi2[0] = chi2[7]; + chi2[1] = chi2[8]; + chi2[2] = chi2[3]; + chi2[3] = chi2[4]; + chi2[4] = chi2[5] = chi2[6] = 0; + break; + case 6: + sigma = sParams.sigma - deltaSigma; + sParams.sigma=sigma; + sParams.mu = sParams.mu + deltaMu; + chi2[8] = chi2[6]; + chi2[1] = chi2[7]; + chi2[2] = chi2[8]; + chi2[3] = chi2[5]; + chi2[4] = chi2[5] = chi2[6] = + chi2[7] = chi2[0] = 0; + break; + case 7: + sigma = sParams.sigma - deltaSigma; + sParams.sigma=sigma; + chi2[8] = chi2[7]; + chi2[1] = chi2[0]; + chi2[2] = chi2[1]; + chi2[3] = chi2[8]; + chi2[4] = chi2[5]; + chi2[5] = chi2[6]; + chi2[6] = chi2[7] = chi2[0] = 0; + break; + } + } + + + if((unsigned int)deltaSigma/10 < ((pFit->sigmaEpsilon * sParams.sigma)/100000) && + (unsigned int)deltaMu/10 < (pFit->muEpsilon * sParams.mu)/100000) { + pFit->converge = 1; + break; + } + } + psp = (GaussianCurve *)pFit->curve; + *psp = sParams; + pFit->chi2 = chiSquared(pfd,psp) / pFit->ndf; + u64=(UINT64) sParams.sigma; + u64*=70710678ULL; + u64/=10000000000ULL; + psp->sigma=(UINT32) (UINT64) u64; + + return pFit->converge ? 0 : 1; // 0 = success + +} + +template<typename TP, typename TE> +typename FitScurveLikelihoodInt<TP, TE>::UINT32 FitScurveLikelihoodInt<TP, TE>::chiSquared(FitData *pfd,GaussianCurve *s) { + UINT64 acc; + INT32 y0,y1,y2; + INT64 y3; + INT64 ui64; + UINT32 a0, chi2; + UINT32 *x; + UINT8 *y; + INT32 x0; + int j, k, n; + x = pfd->x; y = pfd->y; n = pfd->n; + acc = 0; + a0 = s->a0; + /* use binomial weighting */ + for(k=0;k<n;++k) { + x0 = *x++; + y0 = *y++; + y1 = errf_ext(x0,s); + j = (int)(y1/1000); + y2 = y0*1000000 - (a0 * y1); + y2/=1000; + y3=(INT64) y2; + y3*=y3; + ui64=(UINT64)FitDataInt::binomial_weight[j]; + ui64*=y3; + acc+=ui64; + } + acc/=10000000ULL; + chi2=(UINT32) acc; + chi2/=a0; + return chi2; +} diff --git a/rce/rcecalib/dataproc/fit/FitScurveLikelihoodInt.hh b/rce/rcecalib/dataproc/fit/FitScurveLikelihoodInt.hh new file mode 100644 index 00000000..15f75469 --- /dev/null +++ b/rce/rcecalib/dataproc/fit/FitScurveLikelihoodInt.hh @@ -0,0 +1,66 @@ +#ifndef FITSCURVELIKELIHOODINT_HH +#define FITSCURVELIKELIHOODINT_HH +#include "rcecalib/dataproc/fit/AbsFit.hh" +#include "rcecalib/util/RceHisto2d.cc" +#include <vector> + +template<typename TP, typename TE> +class FitScurveLikelihoodInt:public AbsFit { + +typedef unsigned int UINT32; +typedef int INT32; +typedef unsigned long long UINT64; +typedef long long INT64; +typedef unsigned char UINT8; + +typedef struct FitData_ +{ + UINT32 n; + UINT32 *x; + UINT8 *y; +} FitData; + + +typedef struct GaussianCurve_ +{ + UINT32 mu, sigma, a0; +} GaussianCurve; + +typedef struct { + INT32 deltaMu, deltaSigma; /* user provides initial deltaMu and deltaSigma */ + INT32 muEpsilon, sigmaEpsilon; /* user provides convergence criterion */ + INT32 nIters; + INT32 ndf; /* number of degrees of freedom */ + INT32 chi2; /* final result for chi2 */ + INT32 converge; + INT32 muConverge,sigmaConverge; + INT32 maxIters; + void *curve; +} Fit; + + +public: + FitScurveLikelihoodInt(ConfigIF *cif,std::vector<std::vector<RceHisto2d<TP, TE>*> > &histo,std::vector<int> &vcal, int nTrigger, const char* name=""); + ~FitScurveLikelihoodInt(); + int doFit(int); +protected: + inline INT32 *log_ext(INT32 x, GaussianCurve *psp); + UINT32 errf_ext(INT32 x, GaussianCurve *psp); + UINT32 logLikelihood(FitData *pfd, GaussianCurve *s); + int initFit(Fit *pFit); + int extractGoodData(FitData *pfdi,FitData *pfdo, UINT32 nTriggers); + int initialGuess(FitData *pfd, GaussianCurve *pSParams); + int fitPixel(FitData *pfd,void *vpfit); + UINT32 chiSquared(FitData *pfd,GaussianCurve *s); + Fit m_fit; + UINT32 *m_x; + UINT8 *m_y; + std::vector<std::vector<RceHisto2d<TP, TE>*> > &m_histo; + std::vector<std::vector<RceHisto2d<float, float>*> > m_fithisto; + const char* m_name; + +}; + + + +#endif diff --git a/rce/rcecalib/dataproc/fit/binomial_weight.dat b/rce/rcecalib/dataproc/fit/binomial_weight.dat new file mode 100644 index 00000000..7c5736f5 --- /dev/null +++ b/rce/rcecalib/dataproc/fit/binomial_weight.dat @@ -0,0 +1,1001 @@ +1001.000954f, +1001.000954f, +501.001980f, +334.336339f, +251.004004f, +201.005011f, +167.672701f, +143.864188f, +126.008059f, +112.120186f, +101.010094f, +91.920206f, +84.345478f, +77.936247f, +72.442768f, +67.681892f, +63.516257f, +59.840820f, +56.573882f, +53.650943f, +51.020405f, +48.640494f, +46.477037f, +44.501799f, +42.691256f, +41.025640f, +39.488232f, +38.064785f, +36.743091f, +35.512624f, +34.364260f, +33.290055f, +32.283056f, +31.337157f, +30.446960f, +29.607698f, +28.815120f, +28.065448f, +27.355289f, +26.681608f, +26.041665f, +25.432996f, +24.853363f, +24.300745f, +23.773296f, +23.269342f, +22.787347f, +22.325913f, +21.883753f, +21.459687f, +21.052631f, +20.661583f, +20.285621f, +19.923890f, +19.575600f, +19.240018f, +18.916464f, +18.604304f, +18.302950f, +18.011851f, +17.730496f, +17.458404f, +17.195130f, +16.940251f, +16.693375f, +16.454133f, +16.222179f, +15.997184f, +15.778843f, +15.566866f, +15.360983f, +15.160933f, +14.966474f, +14.777378f, +14.593427f, +14.414414f, +14.240145f, +14.070435f, +13.905111f, +13.744004f, +13.586956f, +13.433818f, +13.284446f, +13.138705f, +12.996464f, +12.857602f, +12.721998f, +12.589542f, +12.460127f, +12.333650f, +12.210012f, +12.089120f, +11.970886f, +11.855224f, +11.742050f, +11.631287f, +11.522861f, +11.416698f, +11.312729f, +11.210887f, +11.111111f, +11.013337f, +10.917507f, +10.823564f, +10.731456f, +10.641128f, +10.552530f, +10.465615f, +10.380335f, +10.296646f, +10.214504f, +10.133868f, +10.054697f, +9.976953f, +9.900597f, +9.825596f, +9.751911f, +9.679511f, +9.608363f, +9.538435f, +9.469697f, +9.402119f, +9.335673f, +9.270332f, +9.206068f, +9.142857f, +9.080673f, +9.019491f, +8.959289f, +8.900043f, +8.841732f, +8.784335f, +8.727831f, +8.672199f, +8.617421f, +8.563476f, +8.510348f, +8.458018f, +8.406469f, +8.355684f, +8.305648f, +8.256343f, +8.207754f, +8.159868f, +8.112668f, +8.066142f, +8.020275f, +7.975054f, +7.930466f, +7.886497f, +7.843137f, +7.800373f, +7.758192f, +7.716585f, +7.675539f, +7.635045f, +7.595090f, +7.555666f, +7.516762f, +7.478368f, +7.440476f, +7.403075f, +7.366157f, +7.329712f, +7.293733f, +7.258211f, +7.223137f, +7.188504f, +7.154304f, +7.120529f, +7.087172f, +7.054226f, +7.021683f, +6.989536f, +6.957780f, +6.926407f, +6.895410f, +6.864784f, +6.834522f, +6.804619f, +6.775068f, +6.745863f, +6.716999f, +6.688471f, +6.660272f, +6.632399f, +6.604845f, +6.577606f, +6.550676f, +6.524051f, +6.497725f, +6.471696f, +6.445957f, +6.420504f, +6.395334f, +6.370441f, +6.345822f, +6.321472f, +6.297388f, +6.273565f, +6.250000f, +6.226689f, +6.203628f, +6.180813f, +6.158242f, +6.135910f, +6.113814f, +6.091952f, +6.070318f, +6.048911f, +6.027727f, +6.006763f, +5.986016f, +5.965483f, +5.945161f, +5.925048f, +5.905140f, +5.885434f, +5.865928f, +5.846620f, +5.827506f, +5.808584f, +5.789851f, +5.771306f, +5.752945f, +5.734767f, +5.716768f, +5.698947f, +5.681301f, +5.663829f, +5.646527f, +5.629394f, +5.612428f, +5.595626f, +5.578987f, +5.562508f, +5.546188f, +5.530025f, +5.514017f, +5.498161f, +5.482456f, +5.466900f, +5.451492f, +5.436230f, +5.421112f, +5.406136f, +5.391300f, +5.376604f, +5.362045f, +5.347622f, +5.333333f, +5.319177f, +5.305152f, +5.291257f, +5.277490f, +5.263850f, +5.250336f, +5.236946f, +5.223678f, +5.210531f, +5.197505f, +5.184598f, +5.171807f, +5.159133f, +5.146574f, +5.134129f, +5.121796f, +5.109575f, +5.097463f, +5.085461f, +5.073567f, +5.061779f, +5.050097f, +5.038519f, +5.027045f, +5.015674f, +5.004404f, +4.993234f, +4.982164f, +4.971192f, +4.960317f, +4.949539f, +4.938857f, +4.928269f, +4.917775f, +4.907373f, +4.897064f, +4.886845f, +4.876716f, +4.866677f, +4.856726f, +4.846863f, +4.837087f, +4.827396f, +4.817791f, +4.808270f, +4.798833f, +4.789478f, +4.780206f, +4.771015f, +4.761905f, +4.752874f, +4.743923f, +4.735050f, +4.726255f, +4.717537f, +4.708896f, +4.700330f, +4.691840f, +4.683424f, +4.675082f, +4.666813f, +4.658617f, +4.650492f, +4.642439f, +4.634457f, +4.626545f, +4.618703f, +4.610930f, +4.603225f, +4.595588f, +4.588019f, +4.580516f, +4.573080f, +4.565710f, +4.558404f, +4.551164f, +4.543988f, +4.536876f, +4.529826f, +4.522840f, +4.515916f, +4.509054f, +4.502253f, +4.495513f, +4.488834f, +4.482214f, +4.475655f, +4.469154f, +4.462712f, +4.456328f, +4.450002f, +4.443733f, +4.437522f, +4.431367f, +4.425268f, +4.419225f, +4.413238f, +4.407305f, +4.401428f, +4.395604f, +4.389835f, +4.384119f, +4.378456f, +4.372846f, +4.367289f, +4.361784f, +4.356330f, +4.350928f, +4.345578f, +4.340278f, +4.335028f, +4.329829f, +4.324680f, +4.319580f, +4.314529f, +4.309527f, +4.304574f, +4.299670f, +4.294813f, +4.290004f, +4.285243f, +4.280529f, +4.275861f, +4.271241f, +4.266667f, +4.262138f, +4.257656f, +4.253220f, +4.248828f, +4.244482f, +4.240181f, +4.235924f, +4.231712f, +4.227543f, +4.223419f, +4.219338f, +4.215301f, +4.211306f, +4.207355f, +4.203447f, +4.199581f, +4.195757f, +4.191976f, +4.188236f, +4.184538f, +4.180882f, +4.177266f, +4.173692f, +4.170159f, +4.166667f, +4.163215f, +4.159803f, +4.156431f, +4.153100f, +4.149808f, +4.146556f, +4.143343f, +4.140170f, +4.137035f, +4.133940f, +4.130883f, +4.127865f, +4.124885f, +4.121943f, +4.119040f, +4.116175f, +4.113347f, +4.110558f, +4.107805f, +4.105090f, +4.102413f, +4.099772f, +4.097168f, +4.094602f, +4.092072f, +4.089578f, +4.087121f, +4.084700f, +4.082316f, +4.079967f, +4.077655f, +4.075378f, +4.073137f, +4.070932f, +4.068762f, +4.066628f, +4.064528f, +4.062464f, +4.060436f, +4.058442f, +4.056482f, +4.054558f, +4.052668f, +4.050813f, +4.048993f, +4.047207f, +4.045455f, +4.043737f, +4.042053f, +4.040404f, +4.038788f, +4.037207f, +4.035659f, +4.034145f, +4.032665f, +4.031218f, +4.029804f, +4.028425f, +4.027078f, +4.025765f, +4.024485f, +4.023238f, +4.022025f, +4.020844f, +4.019696f, +4.018582f, +4.017500f, +4.016451f, +4.015435f, +4.014452f, +4.013501f, +4.012583f, +4.011698f, +4.010845f, +4.010025f, +4.009237f, +4.008482f, +4.007759f, +4.007068f, +4.006410f, +4.005784f, +4.005191f, +4.004629f, +4.004100f, +4.003603f, +4.003138f, +4.002706f, +4.002305f, +4.001937f, +4.001601f, +4.001296f, +4.001024f, +4.000784f, +4.000576f, +4.000400f, +4.000256f, +4.000144f, +4.000064f, +4.000016f, +4.000000f, +4.000016f, +4.000064f, +4.000144f, +4.000256f, +4.000400f, +4.000576f, +4.000784f, +4.001024f, +4.001296f, +4.001601f, +4.001937f, +4.002305f, +4.002706f, +4.003138f, +4.003603f, +4.004100f, +4.004629f, +4.005191f, +4.005784f, +4.006410f, +4.007068f, +4.007759f, +4.008482f, +4.009237f, +4.010025f, +4.010845f, +4.011698f, +4.012583f, +4.013501f, +4.014452f, +4.015435f, +4.016451f, +4.017500f, +4.018582f, +4.019697f, +4.020844f, +4.022025f, +4.023238f, +4.024485f, +4.025765f, +4.027078f, +4.028425f, +4.029804f, +4.031218f, +4.032665f, +4.034145f, +4.035659f, +4.037207f, +4.038789f, +4.040404f, +4.042054f, +4.043737f, +4.045455f, +4.047207f, +4.048993f, +4.050814f, +4.052669f, +4.054558f, +4.056482f, +4.058442f, +4.060436f, +4.062465f, +4.064529f, +4.066628f, +4.068762f, +4.070932f, +4.073137f, +4.075378f, +4.077655f, +4.079967f, +4.082316f, +4.084700f, +4.087121f, +4.089578f, +4.092072f, +4.094602f, +4.097169f, +4.099772f, +4.102413f, +4.105090f, +4.107805f, +4.110558f, +4.113347f, +4.116175f, +4.119040f, +4.121944f, +4.124885f, +4.127865f, +4.130883f, +4.133940f, +4.137035f, +4.140170f, +4.143343f, +4.146556f, +4.149808f, +4.153100f, +4.156431f, +4.159803f, +4.163215f, +4.166667f, +4.170159f, +4.173693f, +4.177267f, +4.180882f, +4.184538f, +4.188236f, +4.191976f, +4.195757f, +4.199581f, +4.203447f, +4.207355f, +4.211307f, +4.215301f, +4.219338f, +4.223419f, +4.227544f, +4.231712f, +4.235924f, +4.240181f, +4.244482f, +4.248829f, +4.253220f, +4.257656f, +4.262139f, +4.266667f, +4.271241f, +4.275862f, +4.280529f, +4.285243f, +4.290005f, +4.294813f, +4.299670f, +4.304575f, +4.309528f, +4.314529f, +4.319580f, +4.324680f, +4.329829f, +4.335029f, +4.340278f, +4.345578f, +4.350929f, +4.356330f, +4.361784f, +4.367289f, +4.372847f, +4.378456f, +4.384119f, +4.389835f, +4.395605f, +4.401428f, +4.407306f, +4.413238f, +4.419226f, +4.425268f, +4.431367f, +4.437522f, +4.443734f, +4.450002f, +4.456328f, +4.462712f, +4.469154f, +4.475655f, +4.482215f, +4.488834f, +4.495514f, +4.502254f, +4.509054f, +4.515917f, +4.522840f, +4.529827f, +4.536876f, +4.543988f, +4.551164f, +4.558405f, +4.565710f, +4.573080f, +4.580517f, +4.588019f, +4.595588f, +4.603225f, +4.610930f, +4.618703f, +4.626545f, +4.634458f, +4.642440f, +4.650493f, +4.658617f, +4.666813f, +4.675082f, +4.683424f, +4.691840f, +4.700331f, +4.708896f, +4.717538f, +4.726256f, +4.735050f, +4.743923f, +4.752875f, +4.761905f, +4.771015f, +4.780206f, +4.789479f, +4.798833f, +4.808271f, +4.817791f, +4.827397f, +4.837087f, +4.846864f, +4.856727f, +4.866678f, +4.876717f, +4.886846f, +4.897064f, +4.907374f, +4.917775f, +4.928269f, +4.938858f, +4.949540f, +4.960318f, +4.971192f, +4.982165f, +4.993235f, +5.004404f, +5.015674f, +5.027046f, +5.038520f, +5.050097f, +5.061779f, +5.073567f, +5.085461f, +5.097464f, +5.109575f, +5.121797f, +5.134129f, +5.146575f, +5.159134f, +5.171808f, +5.184598f, +5.197505f, +5.210532f, +5.223678f, +5.236946f, +5.250336f, +5.263851f, +5.277491f, +5.291258f, +5.305153f, +5.319177f, +5.333334f, +5.347623f, +5.362046f, +5.376605f, +5.391301f, +5.406137f, +5.421113f, +5.436231f, +5.451493f, +5.466902f, +5.482457f, +5.498161f, +5.514017f, +5.530025f, +5.546190f, +5.562509f, +5.578988f, +5.595627f, +5.612428f, +5.629395f, +5.646528f, +5.663830f, +5.681302f, +5.698948f, +5.716769f, +5.734768f, +5.752946f, +5.771306f, +5.789853f, +5.808585f, +5.827506f, +5.846620f, +5.865930f, +5.885435f, +5.905141f, +5.925049f, +5.945162f, +5.965485f, +5.986018f, +6.006764f, +6.027728f, +6.048912f, +6.070320f, +6.091953f, +6.113815f, +6.135911f, +6.158244f, +6.180815f, +6.203629f, +6.226689f, +6.250000f, +6.273566f, +6.297389f, +6.321473f, +6.345822f, +6.370443f, +6.395335f, +6.420506f, +6.445958f, +6.471696f, +6.497727f, +6.524052f, +6.550677f, +6.577607f, +6.604846f, +6.632401f, +6.660274f, +6.688472f, +6.717000f, +6.745865f, +6.775069f, +6.804620f, +6.834523f, +6.864785f, +6.895412f, +6.926408f, +6.957781f, +6.989537f, +7.021685f, +7.054228f, +7.087174f, +7.120530f, +7.154305f, +7.188506f, +7.223139f, +7.258212f, +7.293734f, +7.329713f, +7.366159f, +7.403077f, +7.440477f, +7.478370f, +7.516765f, +7.555669f, +7.595092f, +7.635046f, +7.675540f, +7.716588f, +7.758195f, +7.800374f, +7.843138f, +7.886498f, +7.930468f, +7.975056f, +8.020277f, +8.066143f, +8.112672f, +8.159871f, +8.207757f, +8.256344f, +8.305649f, +8.355688f, +8.406472f, +8.458020f, +8.510350f, +8.563480f, +8.617424f, +8.672202f, +8.727833f, +8.784337f, +8.841737f, +8.900047f, +8.959291f, +9.019493f, +9.080673f, +9.142861f, +9.206072f, +9.270334f, +9.335675f, +9.402124f, +9.469701f, +9.538438f, +9.608365f, +9.679513f, +9.751916f, +9.825599f, +9.900601f, +9.976955f, +10.054703f, +10.133873f, +10.214508f, +10.296649f, +10.380337f, +10.465621f, +10.552535f, +10.641132f, +10.731459f, +10.823566f, +10.917513f, +11.013342f, +11.111115f, +11.210890f, +11.312736f, +11.416704f, +11.522866f, +11.631292f, +11.742053f, +11.855231f, +11.970893f, +12.089126f, +12.210015f, +12.333659f, +12.460135f, +12.589549f, +12.722003f, +12.857605f, +12.996475f, +13.138713f, +13.284453f, +13.433823f, +13.586959f, +13.744014f, +13.905120f, +14.070443f, +14.240150f, +14.414427f, +14.593438f, +14.777387f, +14.966481f, +15.160937f, +15.360997f, +15.566879f, +15.778853f, +15.997191f, +16.222182f, +16.454149f, +16.693388f, +16.940261f, +17.195136f, +17.458424f, +17.730512f, +18.011864f, +18.302960f, +18.604311f, +18.916486f, +19.240037f, +19.575614f, +19.923900f, +20.285649f, +20.661607f, +21.052651f, +21.459702f, +21.883763f, +22.325945f, +22.787375f, +23.269364f, +23.773313f, +24.300755f, +24.853401f, +25.433027f, +26.041690f, +26.681625f, +27.355340f, +28.065492f, +28.815158f, +29.607725f, +30.446979f, +31.337218f, +32.283111f, +33.290099f, +34.364293f, +35.512714f, +36.743172f, +38.064854f, +39.488287f, +41.025679f, +42.691379f, +44.501911f, +46.477133f, +48.640570f, +51.020456f, +53.651129f, +56.574049f, +59.840962f, +63.516366f, +67.682224f, +72.443082f, +77.936533f, +84.345724f, +91.920398f, +101.010792f, +112.120887f, +126.008742f, +143.864815f, +167.673193f, +201.007600f, +251.007235f, +334.340634f, +501.008441f, +1001.073485f, +1001.073486f diff --git a/rce/rcecalib/dataproc/fit/binomial_weight_fastint.dat b/rce/rcecalib/dataproc/fit/binomial_weight_fastint.dat new file mode 100644 index 00000000..c2aee1d6 --- /dev/null +++ b/rce/rcecalib/dataproc/fit/binomial_weight_fastint.dat @@ -0,0 +1,1001 @@ +1001000954, +1001000954, +501001980, +334336339, +251004004, +201005011, +167672701, +143864188, +126008059, +112120186, +101010094, +91920206, +84345478, +77936247, +72442768, +67681892, +63516257, +59840820, +56573882, +53650943, +51020405, +48640494, +46477037, +44501799, +42691256, +41025640, +39488232, +38064785, +36743091, +35512624, +34364260, +33290055, +32283056, +31337157, +30446960, +29607698, +28815120, +28065448, +27355289, +26681608, +26041665, +25432996, +24853363, +24300745, +23773296, +23269342, +22787347, +22325913, +21883753, +21459687, +21052631, +20661583, +20285621, +19923890, +19575600, +19240018, +18916464, +18604304, +18302950, +18011851, +17730496, +17458404, +17195130, +16940251, +16693375, +16454132, +16222179, +15997184, +15778843, +15566866, +15360983, +15160933, +14966474, +14777378, +14593427, +14414414, +14240145, +14070435, +13905111, +13744004, +13586956, +13433818, +13284446, +13138705, +12996464, +12857602, +12721998, +12589542, +12460127, +12333650, +12210012, +12089120, +11970886, +11855224, +11742050, +11631287, +11522861, +11416698, +11312729, +11210887, +11111111, +11013337, +10917507, +10823564, +10731456, +10641128, +10552530, +10465615, +10380335, +10296646, +10214504, +10133868, +10054697, +9976953, +9900597, +9825596, +9751911, +9679511, +9608363, +9538435, +9469697, +9402119, +9335673, +9270332, +9206068, +9142857, +9080673, +9019491, +8959289, +8900043, +8841732, +8784335, +8727831, +8672199, +8617421, +8563476, +8510348, +8458018, +8406469, +8355684, +8305648, +8256342, +8207754, +8159867, +8112667, +8066141, +8020275, +7975054, +7930466, +7886497, +7843137, +7800373, +7758192, +7716585, +7675539, +7635045, +7595090, +7555666, +7516762, +7478368, +7440476, +7403075, +7366157, +7329712, +7293733, +7258211, +7223137, +7188504, +7154304, +7120529, +7087172, +7054226, +7021683, +6989536, +6957780, +6926407, +6895410, +6864784, +6834522, +6804619, +6775068, +6745863, +6716999, +6688471, +6660272, +6632399, +6604845, +6577606, +6550676, +6524051, +6497725, +6471696, +6445957, +6420504, +6395334, +6370441, +6345822, +6321472, +6297388, +6273565, +6250000, +6226689, +6203628, +6180813, +6158242, +6135910, +6113814, +6091952, +6070318, +6048911, +6027727, +6006763, +5986016, +5965483, +5945161, +5925048, +5905140, +5885434, +5865928, +5846620, +5827506, +5808584, +5789851, +5771306, +5752945, +5734767, +5716768, +5698947, +5681301, +5663829, +5646527, +5629394, +5612428, +5595626, +5578987, +5562508, +5546188, +5530025, +5514017, +5498161, +5482456, +5466900, +5451492, +5436230, +5421112, +5406136, +5391300, +5376604, +5362045, +5347622, +5333333, +5319177, +5305152, +5291257, +5277490, +5263850, +5250336, +5236946, +5223678, +5210531, +5197505, +5184598, +5171807, +5159133, +5146574, +5134129, +5121796, +5109575, +5097463, +5085461, +5073567, +5061779, +5050097, +5038519, +5027045, +5015674, +5004404, +4993234, +4982164, +4971192, +4960317, +4949539, +4938857, +4928269, +4917775, +4907373, +4897064, +4886845, +4876716, +4866677, +4856726, +4846863, +4837087, +4827396, +4817791, +4808270, +4798833, +4789478, +4780206, +4771015, +4761905, +4752874, +4743923, +4735050, +4726255, +4717537, +4708896, +4700330, +4691840, +4683424, +4675082, +4666813, +4658617, +4650492, +4642439, +4634457, +4626545, +4618703, +4610930, +4603225, +4595588, +4588019, +4580516, +4573080, +4565710, +4558404, +4551164, +4543988, +4536876, +4529826, +4522840, +4515916, +4509054, +4502253, +4495513, +4488834, +4482214, +4475655, +4469154, +4462712, +4456328, +4450002, +4443733, +4437522, +4431367, +4425268, +4419225, +4413238, +4407305, +4401428, +4395604, +4389835, +4384119, +4378456, +4372846, +4367289, +4361784, +4356330, +4350928, +4345578, +4340278, +4335028, +4329829, +4324680, +4319580, +4314529, +4309527, +4304574, +4299670, +4294813, +4290004, +4285243, +4280529, +4275861, +4271241, +4266667, +4262138, +4257656, +4253220, +4248828, +4244482, +4240181, +4235924, +4231712, +4227543, +4223419, +4219338, +4215301, +4211306, +4207355, +4203447, +4199581, +4195757, +4191976, +4188236, +4184538, +4180882, +4177266, +4173692, +4170159, +4166667, +4163215, +4159803, +4156431, +4153100, +4149808, +4146556, +4143343, +4140170, +4137035, +4133940, +4130883, +4127865, +4124885, +4121943, +4119040, +4116175, +4113347, +4110558, +4107805, +4105089, +4102413, +4099771, +4097168, +4094602, +4092072, +4089578, +4087121, +4084700, +4082315, +4079967, +4077655, +4075377, +4073137, +4070932, +4068762, +4066627, +4064528, +4062464, +4060436, +4058442, +4056482, +4054558, +4052667, +4050813, +4048993, +4047207, +4045454, +4043737, +4042053, +4040403, +4038788, +4037207, +4035659, +4034144, +4032664, +4031218, +4029804, +4028425, +4027078, +4025765, +4024485, +4023238, +4022025, +4020844, +4019695, +4018582, +4017500, +4016451, +4015435, +4014452, +4013500, +4012583, +4011698, +4010845, +4010024, +4009236, +4008482, +4007759, +4007068, +4006410, +4005784, +4005191, +4004629, +4004100, +4003603, +4003138, +4002706, +4002305, +4001937, +4001601, +4001296, +4001024, +4000784, +4000575, +4000400, +4000256, +4000143, +4000064, +4000015, +4000000, +4000015, +4000064, +4000143, +4000256, +4000400, +4000575, +4000784, +4001024, +4001296, +4001601, +4001937, +4002305, +4002706, +4003138, +4003603, +4004100, +4004629, +4005191, +4005784, +4006410, +4007068, +4007759, +4008482, +4009236, +4010024, +4010845, +4011698, +4012583, +4013500, +4014452, +4015435, +4016451, +4017500, +4018582, +4019697, +4020844, +4022025, +4023238, +4024485, +4025765, +4027078, +4028425, +4029804, +4031218, +4032664, +4034144, +4035659, +4037207, +4038789, +4040403, +4042054, +4043737, +4045454, +4047207, +4048993, +4050814, +4052669, +4054558, +4056482, +4058442, +4060436, +4062465, +4064529, +4066627, +4068762, +4070932, +4073137, +4075377, +4077655, +4079967, +4082315, +4084700, +4087121, +4089578, +4092072, +4094602, +4097169, +4099771, +4102413, +4105089, +4107805, +4110558, +4113347, +4116175, +4119040, +4121944, +4124885, +4127865, +4130883, +4133940, +4137035, +4140170, +4143343, +4146556, +4149808, +4153100, +4156431, +4159803, +4163215, +4166667, +4170159, +4173693, +4177266, +4180882, +4184538, +4188236, +4191976, +4195757, +4199581, +4203447, +4207355, +4211307, +4215301, +4219338, +4223419, +4227544, +4231712, +4235924, +4240181, +4244482, +4248829, +4253220, +4257656, +4262139, +4266667, +4271241, +4275862, +4280529, +4285243, +4290005, +4294813, +4299670, +4304575, +4309528, +4314529, +4319580, +4324680, +4329829, +4335029, +4340278, +4345578, +4350929, +4356330, +4361784, +4367289, +4372847, +4378456, +4384119, +4389835, +4395605, +4401428, +4407306, +4413238, +4419226, +4425268, +4431367, +4437522, +4443734, +4450002, +4456328, +4462712, +4469154, +4475655, +4482215, +4488834, +4495514, +4502254, +4509054, +4515917, +4522840, +4529827, +4536876, +4543988, +4551164, +4558405, +4565710, +4573080, +4580517, +4588019, +4595588, +4603225, +4610930, +4618703, +4626545, +4634458, +4642440, +4650493, +4658617, +4666813, +4675082, +4683424, +4691840, +4700331, +4708896, +4717538, +4726256, +4735050, +4743923, +4752875, +4761905, +4771015, +4780206, +4789479, +4798833, +4808271, +4817791, +4827397, +4837087, +4846864, +4856727, +4866678, +4876717, +4886846, +4897064, +4907374, +4917775, +4928269, +4938858, +4949540, +4960318, +4971192, +4982165, +4993235, +5004404, +5015674, +5027046, +5038520, +5050097, +5061779, +5073567, +5085461, +5097464, +5109575, +5121797, +5134129, +5146575, +5159134, +5171808, +5184598, +5197505, +5210532, +5223678, +5236946, +5250336, +5263851, +5277491, +5291258, +5305153, +5319177, +5333334, +5347623, +5362046, +5376605, +5391301, +5406137, +5421113, +5436231, +5451493, +5466902, +5482457, +5498161, +5514017, +5530025, +5546190, +5562509, +5578988, +5595627, +5612428, +5629395, +5646528, +5663830, +5681302, +5698948, +5716769, +5734768, +5752946, +5771306, +5789853, +5808585, +5827506, +5846620, +5865930, +5885435, +5905141, +5925049, +5945162, +5965485, +5986018, +6006764, +6027728, +6048912, +6070320, +6091953, +6113815, +6135911, +6158244, +6180815, +6203629, +6226689, +6250000, +6273566, +6297389, +6321473, +6345822, +6370443, +6395335, +6420506, +6445958, +6471696, +6497727, +6524052, +6550677, +6577607, +6604846, +6632401, +6660274, +6688472, +6717000, +6745865, +6775069, +6804620, +6834523, +6864785, +6895412, +6926408, +6957781, +6989537, +7021685, +7054228, +7087174, +7120530, +7154305, +7188506, +7223139, +7258212, +7293734, +7329713, +7366159, +7403077, +7440477, +7478370, +7516765, +7555669, +7595092, +7635046, +7675540, +7716588, +7758195, +7800374, +7843138, +7886498, +7930468, +7975056, +8020277, +8066143, +8112672, +8159871, +8207757, +8256344, +8305649, +8355688, +8406472, +8458020, +8510350, +8563480, +8617424, +8672202, +8727833, +8784337, +8841737, +8900047, +8959291, +9019493, +9080673, +9142861, +9206072, +9270334, +9335675, +9402124, +9469701, +9538438, +9608365, +9679513, +9751916, +9825599, +9900601, +9976955, +10054703, +10133873, +10214508, +10296649, +10380337, +10465621, +10552535, +10641132, +10731459, +10823566, +10917513, +11013342, +11111115, +11210890, +11312736, +11416704, +11522866, +11631292, +11742053, +11855231, +11970893, +12089126, +12210015, +12333659, +12460135, +12589549, +12722003, +12857605, +12996475, +13138713, +13284453, +13433823, +13586959, +13744014, +13905120, +14070443, +14240150, +14414427, +14593438, +14777387, +14966481, +15160937, +15360997, +15566879, +15778853, +15997191, +16222182, +16454149, +16693387, +16940261, +17195136, +17458424, +17730512, +18011864, +18302960, +18604311, +18916486, +19240037, +19575614, +19923900, +20285649, +20661607, +21052651, +21459702, +21883763, +22325945, +22787375, +23269364, +23773313, +24300755, +24853401, +25433027, +26041690, +26681625, +27355340, +28065492, +28815158, +29607725, +30446979, +31337218, +32283110, +33290098, +34364293, +35512714, +36743172, +38064854, +39488287, +41025679, +42691379, +44501911, +46477133, +48640570, +51020456, +53651129, +56574049, +59840962, +63516366, +67682224, +72443082, +77936533, +84345724, +91920398, +101010792, +112120887, +126008742, +143864815, +167673193, +201007600, +251007235, +334340634, +501008441, +1001073485, +1001073486 diff --git a/rce/rcecalib/dataproc/fit/binomial_weight_int.dat b/rce/rcecalib/dataproc/fit/binomial_weight_int.dat new file mode 100644 index 00000000..80a30437 --- /dev/null +++ b/rce/rcecalib/dataproc/fit/binomial_weight_int.dat @@ -0,0 +1,1001 @@ +128128, +128128, +64128, +42795, +32129, +25729, +21462, +18415, +16129, +14351, +12929, +11766, +10796, +9976, +9273, +8663, +8130, +7660, +7241, +6867, +6531, +6226, +5949, +5696, +5464, +5251, +5054, +4872, +4703, +4546, +4399, +4261, +4132, +4011, +3897, +3790, +3688, +3592, +3501, +3415, +3333, +3255, +3181, +3110, +3043, +2978, +2917, +2858, +2801, +2747, +2695, +2645, +2597, +2550, +2506, +2463, +2421, +2381, +2343, +2306, +2270, +2235, +2201, +2168, +2137, +2106, +2076, +2048, +2020, +1993, +1966, +1941, +1916, +1892, +1868, +1845, +1823, +1801, +1780, +1759, +1739, +1720, +1700, +1682, +1664, +1646, +1628, +1611, +1595, +1579, +1563, +1547, +1532, +1517, +1503, +1489, +1475, +1461, +1448, +1435, +1422, +1410, +1397, +1385, +1374, +1362, +1351, +1340, +1329, +1318, +1307, +1297, +1287, +1277, +1267, +1258, +1248, +1239, +1230, +1221, +1212, +1203, +1195, +1187, +1178, +1170, +1162, +1154, +1147, +1139, +1132, +1124, +1117, +1110, +1103, +1096, +1089, +1083, +1076, +1070, +1063, +1057, +1051, +1044, +1038, +1032, +1027, +1021, +1015, +1009, +1004, +998, +993, +988, +982, +977, +972, +967, +962, +957, +952, +948, +943, +938, +934, +929, +925, +920, +916, +911, +907, +903, +899, +895, +891, +887, +883, +879, +875, +871, +867, +863, +860, +856, +853, +849, +845, +842, +838, +835, +832, +828, +825, +822, +819, +815, +812, +809, +806, +803, +800, +797, +794, +791, +788, +785, +783, +780, +777, +774, +772, +769, +766, +764, +761, +758, +756, +753, +751, +748, +746, +743, +741, +739, +736, +734, +732, +729, +727, +725, +723, +721, +718, +716, +714, +712, +710, +708, +706, +704, +702, +700, +698, +696, +694, +692, +690, +688, +686, +684, +683, +681, +679, +677, +676, +674, +672, +670, +669, +667, +665, +664, +662, +660, +659, +657, +656, +654, +652, +651, +649, +648, +646, +645, +643, +642, +641, +639, +638, +636, +635, +634, +632, +631, +629, +628, +627, +626, +624, +623, +622, +620, +619, +618, +617, +615, +614, +613, +612, +611, +610, +608, +607, +606, +605, +604, +603, +602, +601, +599, +598, +597, +596, +595, +594, +593, +592, +591, +590, +589, +588, +587, +586, +585, +584, +583, +583, +582, +581, +580, +579, +578, +577, +576, +575, +575, +574, +573, +572, +571, +570, +570, +569, +568, +567, +566, +566, +565, +564, +563, +563, +562, +561, +560, +560, +559, +558, +558, +557, +556, +556, +555, +554, +554, +553, +552, +552, +551, +550, +550, +549, +549, +548, +547, +547, +546, +546, +545, +544, +544, +543, +543, +542, +542, +541, +541, +540, +540, +539, +539, +538, +538, +537, +537, +536, +536, +535, +535, +534, +534, +533, +533, +532, +532, +532, +531, +531, +530, +530, +530, +529, +529, +528, +528, +528, +527, +527, +527, +526, +526, +525, +525, +525, +524, +524, +524, +523, +523, +523, +523, +522, +522, +522, +521, +521, +521, +521, +520, +520, +520, +519, +519, +519, +519, +519, +518, +518, +518, +518, +517, +517, +517, +517, +517, +516, +516, +516, +516, +516, +515, +515, +515, +515, +515, +515, +515, +514, +514, +514, +514, +514, +514, +514, +513, +513, +513, +513, +513, +513, +513, +513, +513, +513, +513, +513, +512, +512, +512, +512, +512, +512, +512, +512, +512, +512, +512, +512, +512, +512, +512, +512, +512, +512, +512, +512, +512, +512, +512, +512, +512, +512, +512, +512, +512, +512, +512, +513, +513, +513, +513, +513, +513, +513, +513, +513, +513, +513, +513, +514, +514, +514, +514, +514, +514, +514, +515, +515, +515, +515, +515, +515, +515, +516, +516, +516, +516, +516, +517, +517, +517, +517, +517, +518, +518, +518, +518, +519, +519, +519, +519, +519, +520, +520, +520, +521, +521, +521, +521, +522, +522, +522, +523, +523, +523, +523, +524, +524, +524, +525, +525, +525, +526, +526, +527, +527, +527, +528, +528, +528, +529, +529, +530, +530, +530, +531, +531, +532, +532, +532, +533, +533, +534, +534, +535, +535, +536, +536, +537, +537, +538, +538, +539, +539, +540, +540, +541, +541, +542, +542, +543, +543, +544, +544, +545, +546, +546, +547, +547, +548, +549, +549, +550, +550, +551, +552, +552, +553, +554, +554, +555, +556, +556, +557, +558, +558, +559, +560, +560, +561, +562, +563, +563, +564, +565, +566, +566, +567, +568, +569, +570, +570, +571, +572, +573, +574, +575, +575, +576, +577, +578, +579, +580, +581, +582, +583, +583, +584, +585, +586, +587, +588, +589, +590, +591, +592, +593, +594, +595, +596, +597, +598, +599, +601, +602, +603, +604, +605, +606, +607, +608, +610, +611, +612, +613, +614, +615, +617, +618, +619, +620, +622, +623, +624, +626, +627, +628, +629, +631, +632, +634, +635, +636, +638, +639, +641, +642, +643, +645, +646, +648, +649, +651, +652, +654, +656, +657, +659, +660, +662, +664, +665, +667, +669, +670, +672, +674, +676, +677, +679, +681, +683, +684, +686, +688, +690, +692, +694, +696, +698, +700, +702, +704, +706, +708, +710, +712, +714, +716, +718, +721, +723, +725, +727, +729, +732, +734, +736, +739, +741, +743, +746, +748, +751, +753, +756, +758, +761, +764, +766, +769, +772, +774, +777, +780, +783, +785, +788, +791, +794, +797, +800, +803, +806, +809, +812, +815, +819, +822, +825, +828, +832, +835, +838, +842, +845, +849, +853, +856, +860, +863, +867, +871, +875, +879, +883, +887, +891, +895, +899, +903, +907, +911, +916, +920, +925, +929, +934, +938, +943, +948, +952, +957, +962, +967, +972, +977, +982, +988, +993, +998, +1004, +1009, +1015, +1021, +1027, +1032, +1038, +1044, +1051, +1057, +1063, +1070, +1076, +1083, +1089, +1096, +1103, +1110, +1117, +1124, +1132, +1139, +1147, +1154, +1162, +1170, +1178, +1187, +1195, +1203, +1212, +1221, +1230, +1239, +1248, +1258, +1267, +1277, +1287, +1297, +1307, +1318, +1329, +1340, +1351, +1362, +1374, +1385, +1397, +1410, +1422, +1435, +1448, +1461, +1475, +1489, +1503, +1517, +1532, +1547, +1563, +1579, +1595, +1611, +1628, +1646, +1664, +1682, +1700, +1720, +1739, +1759, +1780, +1801, +1823, +1845, +1868, +1892, +1916, +1941, +1966, +1993, +2020, +2048, +2076, +2106, +2137, +2168, +2201, +2235, +2270, +2306, +2343, +2381, +2421, +2463, +2506, +2550, +2597, +2645, +2695, +2747, +2801, +2858, +2917, +2978, +3043, +3110, +3181, +3255, +3333, +3415, +3501, +3592, +3688, +3790, +3897, +4011, +4132, +4261, +4399, +4546, +4703, +4872, +5055, +5251, +5464, +5696, +5949, +6226, +6531, +6867, +7241, +7660, +8130, +8663, +9273, +9976, +10796, +11766, +12929, +14351, +16129, +18415, +21462, +25729, +32129, +42796, +64129, +128137, +128137, diff --git a/rce/rcecalib/dataproc/fit/errf_ext.dat b/rce/rcecalib/dataproc/fit/errf_ext.dat new file mode 100644 index 00000000..46c6ba21 --- /dev/null +++ b/rce/rcecalib/dataproc/fit/errf_ext.dat @@ -0,0 +1,7001 @@ +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000000f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000001f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000002f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000003f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000004f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000005f, +0.000006f, +0.000006f, +0.000006f, +0.000006f, +0.000006f, +0.000006f, +0.000006f, +0.000006f, +0.000006f, +0.000006f, +0.000006f, +0.000006f, +0.000006f, +0.000006f, +0.000006f, +0.000006f, +0.000006f, +0.000006f, +0.000006f, +0.000006f, +0.000006f, +0.000006f, +0.000006f, +0.000006f, +0.000006f, +0.000006f, +0.000007f, +0.000007f, +0.000007f, +0.000007f, +0.000007f, +0.000007f, +0.000007f, +0.000007f, +0.000007f, +0.000007f, +0.000007f, +0.000007f, +0.000007f, +0.000007f, +0.000007f, +0.000007f, +0.000007f, +0.000007f, +0.000007f, +0.000007f, +0.000007f, +0.000007f, +0.000008f, +0.000008f, +0.000008f, +0.000008f, +0.000008f, +0.000008f, +0.000008f, +0.000008f, +0.000008f, +0.000008f, +0.000008f, +0.000008f, +0.000008f, +0.000008f, +0.000008f, +0.000008f, +0.000008f, +0.000008f, +0.000008f, +0.000009f, +0.000009f, +0.000009f, +0.000009f, +0.000009f, +0.000009f, +0.000009f, +0.000009f, +0.000009f, +0.000009f, +0.000009f, +0.000009f, +0.000009f, +0.000009f, +0.000009f, +0.000009f, +0.000009f, +0.000009f, +0.000010f, +0.000010f, +0.000010f, +0.000010f, +0.000010f, +0.000010f, +0.000010f, +0.000010f, +0.000010f, +0.000010f, +0.000010f, +0.000010f, +0.000010f, +0.000010f, +0.000010f, +0.000010f, +0.000011f, +0.000011f, +0.000011f, +0.000011f, +0.000011f, +0.000011f, +0.000011f, +0.000011f, +0.000011f, +0.000011f, +0.000011f, +0.000011f, +0.000011f, +0.000011f, +0.000012f, +0.000012f, +0.000012f, +0.000012f, +0.000012f, +0.000012f, +0.000012f, +0.000012f, +0.000012f, +0.000012f, +0.000012f, +0.000012f, +0.000012f, +0.000013f, +0.000013f, +0.000013f, +0.000013f, +0.000013f, +0.000013f, +0.000013f, +0.000013f, +0.000013f, +0.000013f, +0.000013f, +0.000013f, +0.000014f, +0.000014f, +0.000014f, +0.000014f, +0.000014f, +0.000014f, +0.000014f, +0.000014f, +0.000014f, +0.000014f, +0.000014f, +0.000014f, +0.000015f, +0.000015f, +0.000015f, +0.000015f, +0.000015f, +0.000015f, +0.000015f, +0.000015f, +0.000015f, +0.000015f, +0.000015f, +0.000016f, +0.000016f, +0.000016f, +0.000016f, +0.000016f, +0.000016f, +0.000016f, +0.000016f, +0.000016f, +0.000016f, +0.000017f, +0.000017f, +0.000017f, +0.000017f, +0.000017f, +0.000017f, +0.000017f, +0.000017f, +0.000017f, +0.000018f, +0.000018f, +0.000018f, +0.000018f, +0.000018f, +0.000018f, +0.000018f, +0.000018f, +0.000018f, +0.000019f, +0.000019f, +0.000019f, +0.000019f, +0.000019f, +0.000019f, +0.000019f, +0.000019f, +0.000019f, +0.000020f, +0.000020f, +0.000020f, +0.000020f, +0.000020f, +0.000020f, +0.000020f, +0.000020f, +0.000021f, +0.000021f, +0.000021f, +0.000021f, +0.000021f, +0.000021f, +0.000021f, +0.000021f, +0.000022f, +0.000022f, +0.000022f, +0.000022f, +0.000022f, +0.000022f, +0.000022f, +0.000023f, +0.000023f, +0.000023f, +0.000023f, +0.000023f, +0.000023f, +0.000023f, +0.000023f, +0.000024f, +0.000024f, +0.000024f, +0.000024f, +0.000024f, +0.000024f, +0.000025f, +0.000025f, +0.000025f, +0.000025f, +0.000025f, +0.000025f, +0.000025f, +0.000026f, +0.000026f, +0.000026f, +0.000026f, +0.000026f, +0.000026f, +0.000027f, +0.000027f, +0.000027f, +0.000027f, +0.000027f, +0.000027f, +0.000028f, +0.000028f, +0.000028f, +0.000028f, +0.000028f, +0.000028f, +0.000028f, +0.000029f, +0.000029f, +0.000029f, +0.000029f, +0.000029f, +0.000030f, +0.000030f, +0.000030f, +0.000030f, +0.000030f, +0.000030f, +0.000031f, +0.000031f, +0.000031f, +0.000031f, +0.000031f, +0.000032f, +0.000032f, +0.000032f, +0.000032f, +0.000032f, +0.000033f, +0.000033f, +0.000033f, +0.000033f, +0.000033f, +0.000033f, +0.000034f, +0.000034f, +0.000034f, +0.000034f, +0.000035f, +0.000035f, +0.000035f, +0.000035f, +0.000035f, +0.000036f, +0.000036f, +0.000036f, +0.000036f, +0.000036f, +0.000037f, +0.000037f, +0.000037f, +0.000037f, +0.000038f, +0.000038f, +0.000038f, +0.000038f, +0.000038f, +0.000039f, +0.000039f, +0.000039f, +0.000039f, +0.000040f, +0.000040f, +0.000040f, +0.000040f, +0.000041f, +0.000041f, +0.000041f, +0.000041f, +0.000041f, +0.000042f, +0.000042f, +0.000042f, +0.000042f, +0.000043f, +0.000043f, +0.000043f, +0.000043f, +0.000044f, +0.000044f, +0.000044f, +0.000044f, +0.000045f, +0.000045f, +0.000045f, +0.000046f, +0.000046f, +0.000046f, +0.000046f, +0.000047f, +0.000047f, +0.000047f, +0.000047f, +0.000048f, +0.000048f, +0.000048f, +0.000049f, +0.000049f, +0.000049f, +0.000049f, +0.000050f, +0.000050f, +0.000050f, +0.000051f, +0.000051f, +0.000051f, +0.000051f, +0.000052f, +0.000052f, +0.000052f, +0.000053f, +0.000053f, +0.000053f, +0.000054f, +0.000054f, +0.000054f, +0.000055f, +0.000055f, +0.000055f, +0.000056f, +0.000056f, +0.000056f, +0.000057f, +0.000057f, +0.000057f, +0.000057f, +0.000058f, +0.000058f, +0.000059f, +0.000059f, +0.000059f, +0.000060f, +0.000060f, +0.000060f, +0.000061f, +0.000061f, +0.000061f, +0.000062f, +0.000062f, +0.000062f, +0.000063f, +0.000063f, +0.000063f, +0.000064f, +0.000064f, +0.000065f, +0.000065f, +0.000065f, +0.000066f, +0.000066f, +0.000066f, +0.000067f, +0.000067f, +0.000068f, +0.000068f, +0.000068f, +0.000069f, +0.000069f, +0.000070f, +0.000070f, +0.000070f, +0.000071f, +0.000071f, +0.000072f, +0.000072f, +0.000072f, +0.000073f, +0.000073f, +0.000074f, +0.000074f, +0.000074f, +0.000075f, +0.000075f, +0.000076f, +0.000076f, +0.000077f, +0.000077f, +0.000077f, +0.000078f, +0.000078f, +0.000079f, +0.000079f, +0.000080f, +0.000080f, +0.000081f, +0.000081f, +0.000082f, +0.000082f, +0.000082f, +0.000083f, +0.000083f, +0.000084f, +0.000084f, +0.000085f, +0.000085f, +0.000086f, +0.000086f, +0.000087f, +0.000087f, +0.000088f, +0.000088f, +0.000089f, +0.000089f, +0.000090f, +0.000090f, +0.000091f, +0.000091f, +0.000092f, +0.000092f, +0.000093f, +0.000093f, +0.000094f, +0.000094f, +0.000095f, +0.000095f, +0.000096f, +0.000097f, +0.000097f, +0.000098f, +0.000098f, +0.000099f, +0.000099f, +0.000100f, +0.000100f, +0.000101f, +0.000102f, +0.000102f, +0.000103f, +0.000103f, +0.000104f, +0.000104f, +0.000105f, +0.000106f, +0.000106f, +0.000107f, +0.000107f, +0.000108f, +0.000109f, +0.000109f, +0.000110f, +0.000110f, +0.000111f, +0.000112f, +0.000112f, +0.000113f, +0.000114f, +0.000114f, +0.000115f, +0.000115f, +0.000116f, +0.000117f, +0.000117f, +0.000118f, +0.000119f, +0.000119f, +0.000120f, +0.000121f, +0.000121f, +0.000122f, +0.000123f, +0.000123f, +0.000124f, +0.000125f, +0.000125f, +0.000126f, +0.000127f, +0.000128f, +0.000128f, +0.000129f, +0.000130f, +0.000130f, +0.000131f, +0.000132f, +0.000133f, +0.000133f, +0.000134f, +0.000135f, +0.000135f, +0.000136f, +0.000137f, +0.000138f, +0.000138f, +0.000139f, +0.000140f, +0.000141f, +0.000142f, +0.000142f, +0.000143f, +0.000144f, +0.000145f, +0.000145f, +0.000146f, +0.000147f, +0.000148f, +0.000149f, +0.000150f, +0.000150f, +0.000151f, +0.000152f, +0.000153f, +0.000154f, +0.000154f, +0.000155f, +0.000156f, +0.000157f, +0.000158f, +0.000159f, +0.000160f, +0.000160f, +0.000161f, +0.000162f, +0.000163f, +0.000164f, +0.000165f, +0.000166f, +0.000167f, +0.000168f, +0.000169f, +0.000169f, +0.000170f, +0.000171f, +0.000172f, +0.000173f, +0.000174f, +0.000175f, +0.000176f, +0.000177f, +0.000178f, +0.000179f, +0.000180f, +0.000181f, +0.000182f, +0.000183f, +0.000184f, +0.000185f, +0.000186f, +0.000187f, +0.000188f, +0.000189f, +0.000190f, +0.000191f, +0.000192f, +0.000193f, +0.000194f, +0.000195f, +0.000196f, +0.000197f, +0.000198f, +0.000199f, +0.000200f, +0.000201f, +0.000202f, +0.000203f, +0.000205f, +0.000206f, +0.000207f, +0.000208f, +0.000209f, +0.000210f, +0.000211f, +0.000212f, +0.000214f, +0.000215f, +0.000216f, +0.000217f, +0.000218f, +0.000219f, +0.000220f, +0.000222f, +0.000223f, +0.000224f, +0.000225f, +0.000226f, +0.000228f, +0.000229f, +0.000230f, +0.000231f, +0.000232f, +0.000234f, +0.000235f, +0.000236f, +0.000237f, +0.000239f, +0.000240f, +0.000241f, +0.000243f, +0.000244f, +0.000245f, +0.000246f, +0.000248f, +0.000249f, +0.000250f, +0.000252f, +0.000253f, +0.000254f, +0.000256f, +0.000257f, +0.000258f, +0.000260f, +0.000261f, +0.000262f, +0.000264f, +0.000265f, +0.000267f, +0.000268f, +0.000270f, +0.000271f, +0.000272f, +0.000274f, +0.000275f, +0.000277f, +0.000278f, +0.000280f, +0.000281f, +0.000283f, +0.000284f, +0.000286f, +0.000287f, +0.000289f, +0.000290f, +0.000292f, +0.000293f, +0.000295f, +0.000296f, +0.000298f, +0.000299f, +0.000301f, +0.000302f, +0.000304f, +0.000306f, +0.000307f, +0.000309f, +0.000310f, +0.000312f, +0.000314f, +0.000315f, +0.000317f, +0.000319f, +0.000320f, +0.000322f, +0.000324f, +0.000325f, +0.000327f, +0.000329f, +0.000330f, +0.000332f, +0.000334f, +0.000335f, +0.000337f, +0.000339f, +0.000341f, +0.000342f, +0.000344f, +0.000346f, +0.000348f, +0.000350f, +0.000351f, +0.000353f, +0.000355f, +0.000357f, +0.000359f, +0.000361f, +0.000362f, +0.000364f, +0.000366f, +0.000368f, +0.000370f, +0.000372f, +0.000374f, +0.000376f, +0.000378f, +0.000380f, +0.000382f, +0.000384f, +0.000385f, +0.000387f, +0.000389f, +0.000391f, +0.000393f, +0.000396f, +0.000398f, +0.000400f, +0.000402f, +0.000404f, +0.000406f, +0.000408f, +0.000410f, +0.000412f, +0.000414f, +0.000416f, +0.000418f, +0.000420f, +0.000423f, +0.000425f, +0.000427f, +0.000429f, +0.000431f, +0.000434f, +0.000436f, +0.000438f, +0.000440f, +0.000442f, +0.000445f, +0.000447f, +0.000449f, +0.000451f, +0.000454f, +0.000456f, +0.000458f, +0.000461f, +0.000463f, +0.000465f, +0.000468f, +0.000470f, +0.000472f, +0.000475f, +0.000477f, +0.000480f, +0.000482f, +0.000485f, +0.000487f, +0.000489f, +0.000492f, +0.000494f, +0.000497f, +0.000499f, +0.000502f, +0.000504f, +0.000507f, +0.000510f, +0.000512f, +0.000515f, +0.000517f, +0.000520f, +0.000522f, +0.000525f, +0.000528f, +0.000530f, +0.000533f, +0.000536f, +0.000538f, +0.000541f, +0.000544f, +0.000547f, +0.000549f, +0.000552f, +0.000555f, +0.000558f, +0.000560f, +0.000563f, +0.000566f, +0.000569f, +0.000572f, +0.000574f, +0.000577f, +0.000580f, +0.000583f, +0.000586f, +0.000589f, +0.000592f, +0.000595f, +0.000598f, +0.000601f, +0.000604f, +0.000607f, +0.000610f, +0.000613f, +0.000616f, +0.000619f, +0.000622f, +0.000625f, +0.000628f, +0.000631f, +0.000634f, +0.000637f, +0.000641f, +0.000644f, +0.000647f, +0.000650f, +0.000653f, +0.000657f, +0.000660f, +0.000663f, +0.000666f, +0.000670f, +0.000673f, +0.000676f, +0.000680f, +0.000683f, +0.000686f, +0.000690f, +0.000693f, +0.000696f, +0.000700f, +0.000703f, +0.000707f, +0.000710f, +0.000714f, +0.000717f, +0.000721f, +0.000724f, +0.000728f, +0.000731f, +0.000735f, +0.000739f, +0.000742f, +0.000746f, +0.000749f, +0.000753f, +0.000757f, +0.000760f, +0.000764f, +0.000768f, +0.000772f, +0.000775f, +0.000779f, +0.000783f, +0.000787f, +0.000791f, +0.000794f, +0.000798f, +0.000802f, +0.000806f, +0.000810f, +0.000814f, +0.000818f, +0.000822f, +0.000826f, +0.000830f, +0.000834f, +0.000838f, +0.000842f, +0.000846f, +0.000850f, +0.000854f, +0.000858f, +0.000863f, +0.000867f, +0.000871f, +0.000875f, +0.000879f, +0.000884f, +0.000888f, +0.000892f, +0.000896f, +0.000901f, +0.000905f, +0.000909f, +0.000914f, +0.000918f, +0.000923f, +0.000927f, +0.000931f, +0.000936f, +0.000940f, +0.000945f, +0.000949f, +0.000954f, +0.000959f, +0.000963f, +0.000968f, +0.000972f, +0.000977f, +0.000982f, +0.000986f, +0.000991f, +0.000996f, +0.001001f, +0.001005f, +0.001010f, +0.001015f, +0.001020f, +0.001025f, +0.001030f, +0.001034f, +0.001039f, +0.001044f, +0.001049f, +0.001054f, +0.001059f, +0.001064f, +0.001069f, +0.001074f, +0.001080f, +0.001085f, +0.001090f, +0.001095f, +0.001100f, +0.001105f, +0.001111f, +0.001116f, +0.001121f, +0.001126f, +0.001132f, +0.001137f, +0.001142f, +0.001148f, +0.001153f, +0.001159f, +0.001164f, +0.001170f, +0.001175f, +0.001181f, +0.001186f, +0.001192f, +0.001197f, +0.001203f, +0.001209f, +0.001214f, +0.001220f, +0.001226f, +0.001232f, +0.001237f, +0.001243f, +0.001249f, +0.001255f, +0.001261f, +0.001267f, +0.001273f, +0.001278f, +0.001284f, +0.001290f, +0.001296f, +0.001303f, +0.001309f, +0.001315f, +0.001321f, +0.001327f, +0.001333f, +0.001339f, +0.001346f, +0.001352f, +0.001358f, +0.001364f, +0.001371f, +0.001377f, +0.001384f, +0.001390f, +0.001397f, +0.001403f, +0.001409f, +0.001416f, +0.001423f, +0.001429f, +0.001436f, +0.001442f, +0.001449f, +0.001456f, +0.001463f, +0.001469f, +0.001476f, +0.001483f, +0.001490f, +0.001497f, +0.001503f, +0.001510f, +0.001517f, +0.001524f, +0.001531f, +0.001538f, +0.001546f, +0.001553f, +0.001560f, +0.001567f, +0.001574f, +0.001581f, +0.001589f, +0.001596f, +0.001603f, +0.001611f, +0.001618f, +0.001625f, +0.001633f, +0.001640f, +0.001648f, +0.001655f, +0.001663f, +0.001670f, +0.001678f, +0.001686f, +0.001693f, +0.001701f, +0.001709f, +0.001717f, +0.001725f, +0.001732f, +0.001740f, +0.001748f, +0.001756f, +0.001764f, +0.001772f, +0.001780f, +0.001788f, +0.001796f, +0.001805f, +0.001813f, +0.001821f, +0.001829f, +0.001837f, +0.001846f, +0.001854f, +0.001863f, +0.001871f, +0.001879f, +0.001888f, +0.001896f, +0.001905f, +0.001914f, +0.001922f, +0.001931f, +0.001940f, +0.001948f, +0.001957f, +0.001966f, +0.001975f, +0.001984f, +0.001993f, +0.002001f, +0.002010f, +0.002020f, +0.002029f, +0.002038f, +0.002047f, +0.002056f, +0.002065f, +0.002074f, +0.002084f, +0.002093f, +0.002102f, +0.002112f, +0.002121f, +0.002131f, +0.002140f, +0.002150f, +0.002159f, +0.002169f, +0.002179f, +0.002188f, +0.002198f, +0.002208f, +0.002218f, +0.002228f, +0.002238f, +0.002248f, +0.002257f, +0.002268f, +0.002278f, +0.002288f, +0.002298f, +0.002308f, +0.002318f, +0.002329f, +0.002339f, +0.002349f, +0.002360f, +0.002370f, +0.002381f, +0.002391f, +0.002402f, +0.002412f, +0.002423f, +0.002434f, +0.002444f, +0.002455f, +0.002466f, +0.002477f, +0.002488f, +0.002499f, +0.002510f, +0.002521f, +0.002532f, +0.002543f, +0.002554f, +0.002565f, +0.002576f, +0.002588f, +0.002599f, +0.002611f, +0.002622f, +0.002633f, +0.002645f, +0.002657f, +0.002668f, +0.002680f, +0.002692f, +0.002703f, +0.002715f, +0.002727f, +0.002739f, +0.002751f, +0.002763f, +0.002775f, +0.002787f, +0.002799f, +0.002811f, +0.002823f, +0.002836f, +0.002848f, +0.002860f, +0.002873f, +0.002885f, +0.002898f, +0.002910f, +0.002923f, +0.002936f, +0.002948f, +0.002961f, +0.002974f, +0.002987f, +0.003000f, +0.003013f, +0.003026f, +0.003039f, +0.003052f, +0.003065f, +0.003078f, +0.003091f, +0.003105f, +0.003118f, +0.003132f, +0.003145f, +0.003159f, +0.003172f, +0.003186f, +0.003199f, +0.003213f, +0.003227f, +0.003241f, +0.003255f, +0.003269f, +0.003283f, +0.003297f, +0.003311f, +0.003325f, +0.003339f, +0.003354f, +0.003368f, +0.003382f, +0.003397f, +0.003411f, +0.003426f, +0.003440f, +0.003455f, +0.003470f, +0.003485f, +0.003499f, +0.003514f, +0.003529f, +0.003544f, +0.003559f, +0.003574f, +0.003590f, +0.003605f, +0.003620f, +0.003635f, +0.003651f, +0.003666f, +0.003682f, +0.003697f, +0.003713f, +0.003729f, +0.003745f, +0.003760f, +0.003776f, +0.003792f, +0.003808f, +0.003824f, +0.003840f, +0.003857f, +0.003873f, +0.003889f, +0.003905f, +0.003922f, +0.003938f, +0.003955f, +0.003972f, +0.003988f, +0.004005f, +0.004022f, +0.004039f, +0.004056f, +0.004073f, +0.004090f, +0.004107f, +0.004124f, +0.004141f, +0.004158f, +0.004176f, +0.004193f, +0.004211f, +0.004228f, +0.004246f, +0.004264f, +0.004282f, +0.004299f, +0.004317f, +0.004335f, +0.004353f, +0.004371f, +0.004390f, +0.004408f, +0.004426f, +0.004444f, +0.004463f, +0.004481f, +0.004500f, +0.004519f, +0.004537f, +0.004556f, +0.004575f, +0.004594f, +0.004613f, +0.004632f, +0.004651f, +0.004670f, +0.004690f, +0.004709f, +0.004728f, +0.004748f, +0.004767f, +0.004787f, +0.004807f, +0.004827f, +0.004846f, +0.004866f, +0.004886f, +0.004906f, +0.004927f, +0.004947f, +0.004967f, +0.004987f, +0.005008f, +0.005028f, +0.005049f, +0.005070f, +0.005090f, +0.005111f, +0.005132f, +0.005153f, +0.005174f, +0.005195f, +0.005216f, +0.005238f, +0.005259f, +0.005280f, +0.005302f, +0.005324f, +0.005345f, +0.005367f, +0.005389f, +0.005411f, +0.005433f, +0.005455f, +0.005477f, +0.005499f, +0.005521f, +0.005544f, +0.005566f, +0.005589f, +0.005611f, +0.005634f, +0.005657f, +0.005680f, +0.005703f, +0.005726f, +0.005749f, +0.005772f, +0.005795f, +0.005819f, +0.005842f, +0.005866f, +0.005889f, +0.005913f, +0.005937f, +0.005961f, +0.005984f, +0.006009f, +0.006033f, +0.006057f, +0.006081f, +0.006106f, +0.006130f, +0.006155f, +0.006179f, +0.006204f, +0.006229f, +0.006254f, +0.006279f, +0.006304f, +0.006329f, +0.006354f, +0.006379f, +0.006405f, +0.006430f, +0.006456f, +0.006482f, +0.006507f, +0.006533f, +0.006559f, +0.006585f, +0.006612f, +0.006638f, +0.006664f, +0.006691f, +0.006717f, +0.006744f, +0.006770f, +0.006797f, +0.006824f, +0.006851f, +0.006878f, +0.006905f, +0.006933f, +0.006960f, +0.006988f, +0.007015f, +0.007043f, +0.007071f, +0.007098f, +0.007126f, +0.007154f, +0.007183f, +0.007211f, +0.007239f, +0.007268f, +0.007296f, +0.007325f, +0.007353f, +0.007382f, +0.007411f, +0.007440f, +0.007469f, +0.007499f, +0.007528f, +0.007557f, +0.007587f, +0.007617f, +0.007646f, +0.007676f, +0.007706f, +0.007736f, +0.007766f, +0.007796f, +0.007827f, +0.007857f, +0.007888f, +0.007919f, +0.007949f, +0.007980f, +0.008011f, +0.008042f, +0.008073f, +0.008105f, +0.008136f, +0.008168f, +0.008199f, +0.008231f, +0.008263f, +0.008295f, +0.008327f, +0.008359f, +0.008391f, +0.008424f, +0.008456f, +0.008489f, +0.008521f, +0.008554f, +0.008587f, +0.008620f, +0.008653f, +0.008687f, +0.008720f, +0.008754f, +0.008787f, +0.008821f, +0.008855f, +0.008889f, +0.008923f, +0.008957f, +0.008991f, +0.009026f, +0.009060f, +0.009095f, +0.009130f, +0.009164f, +0.009199f, +0.009234f, +0.009270f, +0.009305f, +0.009340f, +0.009376f, +0.009412f, +0.009448f, +0.009483f, +0.009520f, +0.009556f, +0.009592f, +0.009628f, +0.009665f, +0.009702f, +0.009738f, +0.009775f, +0.009812f, +0.009849f, +0.009887f, +0.009924f, +0.009961f, +0.009999f, +0.010037f, +0.010075f, +0.010113f, +0.010151f, +0.010189f, +0.010227f, +0.010266f, +0.010305f, +0.010343f, +0.010382f, +0.010421f, +0.010460f, +0.010500f, +0.010539f, +0.010579f, +0.010618f, +0.010658f, +0.010698f, +0.010738f, +0.010778f, +0.010818f, +0.010859f, +0.010899f, +0.010940f, +0.010981f, +0.011022f, +0.011063f, +0.011104f, +0.011146f, +0.011187f, +0.011229f, +0.011270f, +0.011312f, +0.011354f, +0.011397f, +0.011439f, +0.011481f, +0.011524f, +0.011567f, +0.011609f, +0.011652f, +0.011696f, +0.011739f, +0.011782f, +0.011826f, +0.011869f, +0.011913f, +0.011957f, +0.012001f, +0.012046f, +0.012090f, +0.012135f, +0.012179f, +0.012224f, +0.012269f, +0.012314f, +0.012359f, +0.012405f, +0.012450f, +0.012496f, +0.012542f, +0.012588f, +0.012634f, +0.012680f, +0.012726f, +0.012773f, +0.012820f, +0.012867f, +0.012914f, +0.012961f, +0.013008f, +0.013055f, +0.013103f, +0.013151f, +0.013199f, +0.013247f, +0.013295f, +0.013343f, +0.013392f, +0.013440f, +0.013489f, +0.013538f, +0.013587f, +0.013637f, +0.013686f, +0.013736f, +0.013785f, +0.013835f, +0.013885f, +0.013935f, +0.013986f, +0.014036f, +0.014087f, +0.014138f, +0.014189f, +0.014240f, +0.014291f, +0.014343f, +0.014394f, +0.014446f, +0.014498f, +0.014550f, +0.014602f, +0.014655f, +0.014707f, +0.014760f, +0.014813f, +0.014866f, +0.014919f, +0.014972f, +0.015026f, +0.015080f, +0.015134f, +0.015188f, +0.015242f, +0.015296f, +0.015351f, +0.015406f, +0.015460f, +0.015515f, +0.015571f, +0.015626f, +0.015682f, +0.015737f, +0.015793f, +0.015849f, +0.015906f, +0.015962f, +0.016019f, +0.016075f, +0.016132f, +0.016189f, +0.016247f, +0.016304f, +0.016362f, +0.016419f, +0.016477f, +0.016536f, +0.016594f, +0.016652f, +0.016711f, +0.016770f, +0.016829f, +0.016888f, +0.016947f, +0.017007f, +0.017067f, +0.017127f, +0.017187f, +0.017247f, +0.017307f, +0.017368f, +0.017429f, +0.017490f, +0.017551f, +0.017612f, +0.017674f, +0.017736f, +0.017798f, +0.017860f, +0.017922f, +0.017984f, +0.018047f, +0.018110f, +0.018173f, +0.018236f, +0.018300f, +0.018363f, +0.018427f, +0.018491f, +0.018555f, +0.018619f, +0.018684f, +0.018749f, +0.018814f, +0.018879f, +0.018944f, +0.019009f, +0.019075f, +0.019141f, +0.019207f, +0.019273f, +0.019340f, +0.019406f, +0.019473f, +0.019540f, +0.019608f, +0.019675f, +0.019743f, +0.019810f, +0.019878f, +0.019947f, +0.020015f, +0.020084f, +0.020152f, +0.020222f, +0.020291f, +0.020360f, +0.020430f, +0.020500f, +0.020570f, +0.020640f, +0.020710f, +0.020781f, +0.020852f, +0.020923f, +0.020994f, +0.021065f, +0.021137f, +0.021209f, +0.021281f, +0.021353f, +0.021426f, +0.021498f, +0.021571f, +0.021644f, +0.021718f, +0.021791f, +0.021865f, +0.021939f, +0.022013f, +0.022088f, +0.022162f, +0.022237f, +0.022312f, +0.022387f, +0.022463f, +0.022538f, +0.022614f, +0.022690f, +0.022766f, +0.022843f, +0.022920f, +0.022997f, +0.023074f, +0.023151f, +0.023229f, +0.023307f, +0.023385f, +0.023463f, +0.023541f, +0.023620f, +0.023699f, +0.023778f, +0.023857f, +0.023937f, +0.024017f, +0.024097f, +0.024177f, +0.024258f, +0.024338f, +0.024419f, +0.024500f, +0.024582f, +0.024663f, +0.024745f, +0.024827f, +0.024910f, +0.024992f, +0.025075f, +0.025158f, +0.025241f, +0.025324f, +0.025408f, +0.025492f, +0.025576f, +0.025660f, +0.025745f, +0.025830f, +0.025915f, +0.026000f, +0.026086f, +0.026172f, +0.026258f, +0.026344f, +0.026430f, +0.026517f, +0.026604f, +0.026691f, +0.026779f, +0.026866f, +0.026954f, +0.027042f, +0.027131f, +0.027219f, +0.027308f, +0.027397f, +0.027487f, +0.027576f, +0.027666f, +0.027756f, +0.027846f, +0.027937f, +0.028028f, +0.028119f, +0.028210f, +0.028302f, +0.028394f, +0.028486f, +0.028578f, +0.028670f, +0.028763f, +0.028856f, +0.028950f, +0.029043f, +0.029137f, +0.029231f, +0.029325f, +0.029420f, +0.029515f, +0.029610f, +0.029705f, +0.029801f, +0.029896f, +0.029992f, +0.030089f, +0.030185f, +0.030282f, +0.030379f, +0.030477f, +0.030574f, +0.030672f, +0.030770f, +0.030869f, +0.030967f, +0.031066f, +0.031166f, +0.031265f, +0.031365f, +0.031465f, +0.031565f, +0.031665f, +0.031766f, +0.031867f, +0.031968f, +0.032070f, +0.032172f, +0.032274f, +0.032376f, +0.032479f, +0.032582f, +0.032685f, +0.032788f, +0.032892f, +0.032996f, +0.033100f, +0.033205f, +0.033310f, +0.033415f, +0.033520f, +0.033626f, +0.033731f, +0.033838f, +0.033944f, +0.034051f, +0.034158f, +0.034265f, +0.034372f, +0.034480f, +0.034588f, +0.034697f, +0.034805f, +0.034914f, +0.035023f, +0.035133f, +0.035243f, +0.035353f, +0.035463f, +0.035574f, +0.035684f, +0.035796f, +0.035907f, +0.036019f, +0.036131f, +0.036243f, +0.036356f, +0.036469f, +0.036582f, +0.036695f, +0.036809f, +0.036923f, +0.037037f, +0.037152f, +0.037267f, +0.037382f, +0.037497f, +0.037613f, +0.037729f, +0.037846f, +0.037962f, +0.038079f, +0.038196f, +0.038314f, +0.038432f, +0.038550f, +0.038668f, +0.038787f, +0.038906f, +0.039025f, +0.039145f, +0.039265f, +0.039385f, +0.039506f, +0.039626f, +0.039747f, +0.039869f, +0.039990f, +0.040112f, +0.040235f, +0.040357f, +0.040480f, +0.040603f, +0.040727f, +0.040851f, +0.040975f, +0.041099f, +0.041224f, +0.041349f, +0.041474f, +0.041600f, +0.041726f, +0.041852f, +0.041979f, +0.042106f, +0.042233f, +0.042361f, +0.042488f, +0.042617f, +0.042745f, +0.042874f, +0.043003f, +0.043132f, +0.043262f, +0.043392f, +0.043522f, +0.043653f, +0.043784f, +0.043915f, +0.044047f, +0.044179f, +0.044311f, +0.044443f, +0.044576f, +0.044710f, +0.044843f, +0.044977f, +0.045111f, +0.045245f, +0.045380f, +0.045515f, +0.045651f, +0.045787f, +0.045923f, +0.046059f, +0.046196f, +0.046333f, +0.046470f, +0.046608f, +0.046746f, +0.046884f, +0.047023f, +0.047162f, +0.047302f, +0.047441f, +0.047581f, +0.047722f, +0.047862f, +0.048003f, +0.048145f, +0.048286f, +0.048428f, +0.048571f, +0.048713f, +0.048856f, +0.049000f, +0.049143f, +0.049288f, +0.049432f, +0.049577f, +0.049722f, +0.049867f, +0.050013f, +0.050159f, +0.050305f, +0.050452f, +0.050599f, +0.050746f, +0.050894f, +0.051042f, +0.051191f, +0.051339f, +0.051489f, +0.051638f, +0.051788f, +0.051938f, +0.052089f, +0.052239f, +0.052391f, +0.052542f, +0.052694f, +0.052846f, +0.052999f, +0.053152f, +0.053305f, +0.053459f, +0.053613f, +0.053767f, +0.053922f, +0.054077f, +0.054232f, +0.054388f, +0.054544f, +0.054701f, +0.054857f, +0.055015f, +0.055172f, +0.055330f, +0.055488f, +0.055647f, +0.055806f, +0.055965f, +0.056125f, +0.056285f, +0.056445f, +0.056606f, +0.056767f, +0.056929f, +0.057090f, +0.057253f, +0.057415f, +0.057578f, +0.057741f, +0.057905f, +0.058069f, +0.058233f, +0.058398f, +0.058563f, +0.058729f, +0.058895f, +0.059061f, +0.059227f, +0.059394f, +0.059562f, +0.059729f, +0.059897f, +0.060066f, +0.060235f, +0.060404f, +0.060573f, +0.060743f, +0.060914f, +0.061084f, +0.061255f, +0.061427f, +0.061598f, +0.061771f, +0.061943f, +0.062116f, +0.062289f, +0.062463f, +0.062637f, +0.062811f, +0.062986f, +0.063161f, +0.063337f, +0.063513f, +0.063689f, +0.063866f, +0.064043f, +0.064220f, +0.064398f, +0.064576f, +0.064755f, +0.064934f, +0.065113f, +0.065293f, +0.065473f, +0.065654f, +0.065835f, +0.066016f, +0.066198f, +0.066380f, +0.066562f, +0.066745f, +0.066928f, +0.067112f, +0.067296f, +0.067480f, +0.067665f, +0.067850f, +0.068036f, +0.068222f, +0.068408f, +0.068595f, +0.068782f, +0.068969f, +0.069157f, +0.069346f, +0.069534f, +0.069724f, +0.069913f, +0.070103f, +0.070293f, +0.070484f, +0.070675f, +0.070867f, +0.071058f, +0.071251f, +0.071443f, +0.071636f, +0.071830f, +0.072024f, +0.072218f, +0.072413f, +0.072608f, +0.072803f, +0.072999f, +0.073196f, +0.073392f, +0.073589f, +0.073787f, +0.073985f, +0.074183f, +0.074382f, +0.074581f, +0.074781f, +0.074980f, +0.075181f, +0.075382f, +0.075583f, +0.075784f, +0.075986f, +0.076189f, +0.076392f, +0.076595f, +0.076798f, +0.077002f, +0.077207f, +0.077412f, +0.077617f, +0.077823f, +0.078029f, +0.078235f, +0.078442f, +0.078650f, +0.078857f, +0.079066f, +0.079274f, +0.079483f, +0.079693f, +0.079902f, +0.080113f, +0.080323f, +0.080534f, +0.080746f, +0.080958f, +0.081170f, +0.081383f, +0.081596f, +0.081810f, +0.082024f, +0.082238f, +0.082453f, +0.082669f, +0.082884f, +0.083100f, +0.083317f, +0.083534f, +0.083751f, +0.083969f, +0.084188f, +0.084406f, +0.084625f, +0.084845f, +0.085065f, +0.085285f, +0.085506f, +0.085727f, +0.085949f, +0.086171f, +0.086394f, +0.086617f, +0.086840f, +0.087064f, +0.087288f, +0.087513f, +0.087738f, +0.087964f, +0.088190f, +0.088416f, +0.088643f, +0.088870f, +0.089098f, +0.089326f, +0.089555f, +0.089784f, +0.090013f, +0.090243f, +0.090473f, +0.090704f, +0.090935f, +0.091167f, +0.091399f, +0.091632f, +0.091864f, +0.092098f, +0.092332f, +0.092566f, +0.092801f, +0.093036f, +0.093271f, +0.093507f, +0.093744f, +0.093981f, +0.094218f, +0.094456f, +0.094694f, +0.094933f, +0.095172f, +0.095412f, +0.095652f, +0.095892f, +0.096133f, +0.096374f, +0.096616f, +0.096858f, +0.097101f, +0.097344f, +0.097588f, +0.097832f, +0.098076f, +0.098321f, +0.098567f, +0.098812f, +0.099059f, +0.099305f, +0.099552f, +0.099800f, +0.100048f, +0.100297f, +0.100546f, +0.100795f, +0.101045f, +0.101295f, +0.101546f, +0.101797f, +0.102049f, +0.102301f, +0.102553f, +0.102806f, +0.103060f, +0.103314f, +0.103568f, +0.103823f, +0.104078f, +0.104334f, +0.104590f, +0.104847f, +0.105104f, +0.105362f, +0.105620f, +0.105878f, +0.106137f, +0.106396f, +0.106656f, +0.106917f, +0.107177f, +0.107439f, +0.107700f, +0.107962f, +0.108225f, +0.108488f, +0.108752f, +0.109016f, +0.109280f, +0.109545f, +0.109810f, +0.110076f, +0.110342f, +0.110609f, +0.110876f, +0.111144f, +0.111412f, +0.111681f, +0.111950f, +0.112219f, +0.112489f, +0.112760f, +0.113031f, +0.113302f, +0.113574f, +0.113846f, +0.114119f, +0.114392f, +0.114666f, +0.114940f, +0.115215f, +0.115490f, +0.115765f, +0.116041f, +0.116318f, +0.116595f, +0.116872f, +0.117150f, +0.117429f, +0.117707f, +0.117987f, +0.118267f, +0.118547f, +0.118828f, +0.119109f, +0.119390f, +0.119672f, +0.119955f, +0.120238f, +0.120522f, +0.120806f, +0.121090f, +0.121375f, +0.121660f, +0.121946f, +0.122233f, +0.122520f, +0.122807f, +0.123095f, +0.123383f, +0.123672f, +0.123961f, +0.124250f, +0.124541f, +0.124831f, +0.125122f, +0.125414f, +0.125706f, +0.125998f, +0.126291f, +0.126585f, +0.126879f, +0.127173f, +0.127468f, +0.127763f, +0.128059f, +0.128355f, +0.128652f, +0.128950f, +0.129247f, +0.129545f, +0.129844f, +0.130143f, +0.130443f, +0.130743f, +0.131044f, +0.131345f, +0.131646f, +0.131948f, +0.132251f, +0.132554f, +0.132857f, +0.133161f, +0.133466f, +0.133770f, +0.134076f, +0.134382f, +0.134688f, +0.134995f, +0.135302f, +0.135610f, +0.135918f, +0.136227f, +0.136536f, +0.136846f, +0.137156f, +0.137466f, +0.137778f, +0.138089f, +0.138401f, +0.138714f, +0.139027f, +0.139340f, +0.139654f, +0.139969f, +0.140284f, +0.140599f, +0.140915f, +0.141232f, +0.141549f, +0.141866f, +0.142184f, +0.142502f, +0.142821f, +0.143140f, +0.143460f, +0.143780f, +0.144101f, +0.144422f, +0.144744f, +0.145066f, +0.145389f, +0.145712f, +0.146036f, +0.146360f, +0.146684f, +0.147009f, +0.147335f, +0.147661f, +0.147987f, +0.148315f, +0.148642f, +0.148970f, +0.149298f, +0.149627f, +0.149957f, +0.150287f, +0.150617f, +0.150948f, +0.151279f, +0.151611f, +0.151944f, +0.152276f, +0.152610f, +0.152943f, +0.153278f, +0.153612f, +0.153948f, +0.154283f, +0.154620f, +0.154956f, +0.155293f, +0.155631f, +0.155969f, +0.156308f, +0.156647f, +0.156987f, +0.157327f, +0.157667f, +0.158008f, +0.158350f, +0.158692f, +0.159034f, +0.159377f, +0.159721f, +0.160065f, +0.160409f, +0.160754f, +0.161099f, +0.161445f, +0.161792f, +0.162138f, +0.162486f, +0.162834f, +0.163182f, +0.163531f, +0.163880f, +0.164230f, +0.164580f, +0.164931f, +0.165282f, +0.165634f, +0.165986f, +0.166338f, +0.166692f, +0.167045f, +0.167399f, +0.167754f, +0.168109f, +0.168464f, +0.168820f, +0.169177f, +0.169534f, +0.169891f, +0.170249f, +0.170608f, +0.170967f, +0.171326f, +0.171686f, +0.172047f, +0.172407f, +0.172769f, +0.173131f, +0.173493f, +0.173856f, +0.174219f, +0.174583f, +0.174947f, +0.175312f, +0.175677f, +0.176043f, +0.176409f, +0.176775f, +0.177142f, +0.177510f, +0.177878f, +0.178247f, +0.178616f, +0.178985f, +0.179355f, +0.179726f, +0.180097f, +0.180468f, +0.180840f, +0.181213f, +0.181586f, +0.181959f, +0.182333f, +0.182707f, +0.183082f, +0.183457f, +0.183833f, +0.184209f, +0.184586f, +0.184963f, +0.185341f, +0.185719f, +0.186098f, +0.186477f, +0.186856f, +0.187236f, +0.187617f, +0.187998f, +0.188380f, +0.188762f, +0.189144f, +0.189527f, +0.189910f, +0.190294f, +0.190679f, +0.191063f, +0.191449f, +0.191835f, +0.192221f, +0.192608f, +0.192995f, +0.193383f, +0.193771f, +0.194159f, +0.194549f, +0.194938f, +0.195328f, +0.195719f, +0.196110f, +0.196501f, +0.196893f, +0.197286f, +0.197679f, +0.198072f, +0.198466f, +0.198860f, +0.199255f, +0.199650f, +0.200046f, +0.200442f, +0.200839f, +0.201236f, +0.201634f, +0.202032f, +0.202430f, +0.202829f, +0.203229f, +0.203629f, +0.204029f, +0.204430f, +0.204832f, +0.205233f, +0.205636f, +0.206039f, +0.206442f, +0.206846f, +0.207250f, +0.207654f, +0.208059f, +0.208465f, +0.208871f, +0.209278f, +0.209685f, +0.210092f, +0.210500f, +0.210908f, +0.211317f, +0.211727f, +0.212136f, +0.212547f, +0.212957f, +0.213368f, +0.213780f, +0.214192f, +0.214605f, +0.215018f, +0.215431f, +0.215845f, +0.216259f, +0.216674f, +0.217090f, +0.217505f, +0.217922f, +0.218338f, +0.218755f, +0.219173f, +0.219591f, +0.220010f, +0.220429f, +0.220848f, +0.221268f, +0.221688f, +0.222109f, +0.222530f, +0.222952f, +0.223374f, +0.223797f, +0.224220f, +0.224643f, +0.225067f, +0.225492f, +0.225917f, +0.226342f, +0.226768f, +0.227194f, +0.227621f, +0.228048f, +0.228476f, +0.228904f, +0.229332f, +0.229761f, +0.230191f, +0.230620f, +0.231051f, +0.231481f, +0.231913f, +0.232344f, +0.232776f, +0.233209f, +0.233642f, +0.234075f, +0.234509f, +0.234943f, +0.235378f, +0.235813f, +0.236249f, +0.236685f, +0.237122f, +0.237559f, +0.237996f, +0.238434f, +0.238872f, +0.239311f, +0.239750f, +0.240190f, +0.240630f, +0.241070f, +0.241511f, +0.241953f, +0.242394f, +0.242837f, +0.243279f, +0.243722f, +0.244166f, +0.244610f, +0.245054f, +0.245499f, +0.245944f, +0.246390f, +0.246836f, +0.247283f, +0.247730f, +0.248177f, +0.248625f, +0.249073f, +0.249522f, +0.249971f, +0.250421f, +0.250871f, +0.251321f, +0.251772f, +0.252224f, +0.252675f, +0.253127f, +0.253580f, +0.254033f, +0.254486f, +0.254940f, +0.255395f, +0.255849f, +0.256304f, +0.256760f, +0.257216f, +0.257672f, +0.258129f, +0.258586f, +0.259044f, +0.259502f, +0.259961f, +0.260419f, +0.260879f, +0.261338f, +0.261799f, +0.262259f, +0.262720f, +0.263182f, +0.263643f, +0.264106f, +0.264568f, +0.265031f, +0.265495f, +0.265958f, +0.266423f, +0.266887f, +0.267353f, +0.267818f, +0.268284f, +0.268750f, +0.269217f, +0.269684f, +0.270152f, +0.270620f, +0.271088f, +0.271557f, +0.272026f, +0.272495f, +0.272965f, +0.273436f, +0.273906f, +0.274378f, +0.274849f, +0.275321f, +0.275793f, +0.276266f, +0.276739f, +0.277213f, +0.277687f, +0.278161f, +0.278636f, +0.279111f, +0.279587f, +0.280062f, +0.280539f, +0.281015f, +0.281493f, +0.281970f, +0.282448f, +0.282926f, +0.283405f, +0.283884f, +0.284363f, +0.284843f, +0.285323f, +0.285804f, +0.286285f, +0.286766f, +0.287248f, +0.287730f, +0.288212f, +0.288695f, +0.289179f, +0.289662f, +0.290146f, +0.290631f, +0.291115f, +0.291601f, +0.292086f, +0.292572f, +0.293058f, +0.293545f, +0.294032f, +0.294519f, +0.295007f, +0.295495f, +0.295984f, +0.296473f, +0.296962f, +0.297452f, +0.297942f, +0.298432f, +0.298923f, +0.299414f, +0.299905f, +0.300397f, +0.300889f, +0.301382f, +0.301875f, +0.302368f, +0.302862f, +0.303356f, +0.303850f, +0.304345f, +0.304840f, +0.305335f, +0.305831f, +0.306327f, +0.306824f, +0.307320f, +0.307818f, +0.308315f, +0.308813f, +0.309311f, +0.309810f, +0.310309f, +0.310808f, +0.311308f, +0.311808f, +0.312308f, +0.312809f, +0.313310f, +0.313811f, +0.314313f, +0.314815f, +0.315318f, +0.315821f, +0.316324f, +0.316827f, +0.317331f, +0.317835f, +0.318339f, +0.318844f, +0.319349f, +0.319855f, +0.320361f, +0.320867f, +0.321373f, +0.321880f, +0.322387f, +0.322895f, +0.323403f, +0.323911f, +0.324419f, +0.324928f, +0.325437f, +0.325946f, +0.326456f, +0.326966f, +0.327477f, +0.327987f, +0.328498f, +0.329010f, +0.329522f, +0.330034f, +0.330546f, +0.331059f, +0.331572f, +0.332085f, +0.332598f, +0.333112f, +0.333627f, +0.334141f, +0.334656f, +0.335171f, +0.335687f, +0.336202f, +0.336718f, +0.337235f, +0.337752f, +0.338269f, +0.338786f, +0.339304f, +0.339821f, +0.340340f, +0.340858f, +0.341377f, +0.341896f, +0.342416f, +0.342935f, +0.343455f, +0.343976f, +0.344496f, +0.345017f, +0.345538f, +0.346060f, +0.346582f, +0.347104f, +0.347626f, +0.348149f, +0.348672f, +0.349195f, +0.349719f, +0.350242f, +0.350767f, +0.351291f, +0.351816f, +0.352341f, +0.352866f, +0.353391f, +0.353917f, +0.354443f, +0.354969f, +0.355496f, +0.356023f, +0.356550f, +0.357078f, +0.357605f, +0.358133f, +0.358662f, +0.359190f, +0.359719f, +0.360248f, +0.360777f, +0.361307f, +0.361837f, +0.362367f, +0.362897f, +0.363428f, +0.363959f, +0.364490f, +0.365022f, +0.365553f, +0.366085f, +0.366617f, +0.367150f, +0.367683f, +0.368216f, +0.368749f, +0.369282f, +0.369816f, +0.370350f, +0.370884f, +0.371419f, +0.371954f, +0.372489f, +0.373024f, +0.373559f, +0.374095f, +0.374631f, +0.375167f, +0.375704f, +0.376241f, +0.376777f, +0.377315f, +0.377852f, +0.378390f, +0.378928f, +0.379466f, +0.380004f, +0.380543f, +0.381081f, +0.381621f, +0.382160f, +0.382699f, +0.383239f, +0.383779f, +0.384319f, +0.384860f, +0.385400f, +0.385941f, +0.386482f, +0.387023f, +0.387565f, +0.388107f, +0.388649f, +0.389191f, +0.389733f, +0.390276f, +0.390819f, +0.391362f, +0.391905f, +0.392448f, +0.392992f, +0.393536f, +0.394080f, +0.394624f, +0.395169f, +0.395714f, +0.396258f, +0.396804f, +0.397349f, +0.397894f, +0.398440f, +0.398986f, +0.399532f, +0.400078f, +0.400625f, +0.401172f, +0.401718f, +0.402266f, +0.402813f, +0.403360f, +0.403908f, +0.404456f, +0.405004f, +0.405552f, +0.406100f, +0.406649f, +0.407198f, +0.407747f, +0.408296f, +0.408845f, +0.409395f, +0.409944f, +0.410494f, +0.411044f, +0.411594f, +0.412145f, +0.412695f, +0.413246f, +0.413797f, +0.414348f, +0.414899f, +0.415450f, +0.416002f, +0.416554f, +0.417106f, +0.417658f, +0.418210f, +0.418762f, +0.419315f, +0.419867f, +0.420420f, +0.420973f, +0.421526f, +0.422080f, +0.422633f, +0.423187f, +0.423741f, +0.424295f, +0.424849f, +0.425403f, +0.425957f, +0.426512f, +0.427066f, +0.427621f, +0.428176f, +0.428731f, +0.429287f, +0.429842f, +0.430397f, +0.430953f, +0.431509f, +0.432065f, +0.432621f, +0.433177f, +0.433733f, +0.434290f, +0.434846f, +0.435403f, +0.435960f, +0.436517f, +0.437074f, +0.437631f, +0.438189f, +0.438746f, +0.439304f, +0.439861f, +0.440419f, +0.440977f, +0.441535f, +0.442093f, +0.442652f, +0.443210f, +0.443769f, +0.444327f, +0.444886f, +0.445445f, +0.446004f, +0.446563f, +0.447122f, +0.447681f, +0.448241f, +0.448800f, +0.449360f, +0.449919f, +0.450479f, +0.451039f, +0.451599f, +0.452159f, +0.452719f, +0.453280f, +0.453840f, +0.454400f, +0.454961f, +0.455522f, +0.456082f, +0.456643f, +0.457204f, +0.457765f, +0.458326f, +0.458887f, +0.459448f, +0.460010f, +0.460571f, +0.461133f, +0.461694f, +0.462256f, +0.462817f, +0.463379f, +0.463941f, +0.464503f, +0.465065f, +0.465627f, +0.466189f, +0.466751f, +0.467314f, +0.467876f, +0.468438f, +0.469001f, +0.469563f, +0.470126f, +0.470689f, +0.471251f, +0.471814f, +0.472377f, +0.472940f, +0.473503f, +0.474066f, +0.474629f, +0.475192f, +0.475755f, +0.476318f, +0.476881f, +0.477444f, +0.478008f, +0.478571f, +0.479135f, +0.479698f, +0.480261f, +0.480825f, +0.481388f, +0.481952f, +0.482516f, +0.483079f, +0.483643f, +0.484207f, +0.484771f, +0.485334f, +0.485898f, +0.486462f, +0.487026f, +0.487590f, +0.488154f, +0.488718f, +0.489282f, +0.489846f, +0.490410f, +0.490974f, +0.491538f, +0.492102f, +0.492666f, +0.493230f, +0.493794f, +0.494358f, +0.494922f, +0.495487f, +0.496051f, +0.496615f, +0.497179f, +0.497743f, +0.498307f, +0.498872f, +0.499436f, +0.500000f, +0.500000f, +0.500000f, +0.500564f, +0.501128f, +0.501693f, +0.502257f, +0.502821f, +0.503385f, +0.503949f, +0.504513f, +0.505078f, +0.505642f, +0.506206f, +0.506770f, +0.507334f, +0.507898f, +0.508462f, +0.509026f, +0.509590f, +0.510154f, +0.510718f, +0.511282f, +0.511846f, +0.512410f, +0.512974f, +0.513538f, +0.514102f, +0.514666f, +0.515229f, +0.515793f, +0.516357f, +0.516921f, +0.517484f, +0.518048f, +0.518612f, +0.519175f, +0.519739f, +0.520302f, +0.520865f, +0.521429f, +0.521992f, +0.522556f, +0.523119f, +0.523682f, +0.524245f, +0.524808f, +0.525371f, +0.525934f, +0.526497f, +0.527060f, +0.527623f, +0.528186f, +0.528749f, +0.529311f, +0.529874f, +0.530437f, +0.530999f, +0.531562f, +0.532124f, +0.532686f, +0.533249f, +0.533811f, +0.534373f, +0.534935f, +0.535497f, +0.536059f, +0.536621f, +0.537183f, +0.537744f, +0.538306f, +0.538867f, +0.539429f, +0.539990f, +0.540552f, +0.541113f, +0.541674f, +0.542235f, +0.542796f, +0.543357f, +0.543918f, +0.544478f, +0.545039f, +0.545600f, +0.546160f, +0.546720f, +0.547281f, +0.547841f, +0.548401f, +0.548961f, +0.549521f, +0.550081f, +0.550640f, +0.551200f, +0.551759f, +0.552319f, +0.552878f, +0.553437f, +0.553996f, +0.554555f, +0.555114f, +0.555673f, +0.556231f, +0.556790f, +0.557348f, +0.557907f, +0.558465f, +0.559023f, +0.559581f, +0.560139f, +0.560696f, +0.561254f, +0.561811f, +0.562369f, +0.562926f, +0.563483f, +0.564040f, +0.564597f, +0.565154f, +0.565710f, +0.566267f, +0.566823f, +0.567379f, +0.567935f, +0.568491f, +0.569047f, +0.569603f, +0.570158f, +0.570713f, +0.571269f, +0.571824f, +0.572379f, +0.572934f, +0.573488f, +0.574043f, +0.574597f, +0.575151f, +0.575705f, +0.576259f, +0.576813f, +0.577367f, +0.577920f, +0.578474f, +0.579027f, +0.579580f, +0.580133f, +0.580685f, +0.581238f, +0.581790f, +0.582342f, +0.582894f, +0.583446f, +0.583998f, +0.584550f, +0.585101f, +0.585652f, +0.586203f, +0.586754f, +0.587305f, +0.587855f, +0.588406f, +0.588956f, +0.589506f, +0.590056f, +0.590605f, +0.591155f, +0.591704f, +0.592253f, +0.592802f, +0.593351f, +0.593900f, +0.594448f, +0.594996f, +0.595544f, +0.596092f, +0.596640f, +0.597187f, +0.597734f, +0.598282f, +0.598828f, +0.599375f, +0.599922f, +0.600468f, +0.601014f, +0.601560f, +0.602106f, +0.602651f, +0.603196f, +0.603742f, +0.604286f, +0.604831f, +0.605376f, +0.605920f, +0.606464f, +0.607008f, +0.607552f, +0.608095f, +0.608638f, +0.609181f, +0.609724f, +0.610267f, +0.610809f, +0.611351f, +0.611893f, +0.612435f, +0.612977f, +0.613518f, +0.614059f, +0.614600f, +0.615140f, +0.615681f, +0.616221f, +0.616761f, +0.617301f, +0.617840f, +0.618379f, +0.618919f, +0.619457f, +0.619996f, +0.620534f, +0.621072f, +0.621610f, +0.622148f, +0.622685f, +0.623223f, +0.623759f, +0.624296f, +0.624833f, +0.625369f, +0.625905f, +0.626441f, +0.626976f, +0.627511f, +0.628046f, +0.628581f, +0.629116f, +0.629650f, +0.630184f, +0.630718f, +0.631251f, +0.631784f, +0.632317f, +0.632850f, +0.633383f, +0.633915f, +0.634447f, +0.634978f, +0.635510f, +0.636041f, +0.636572f, +0.637103f, +0.637633f, +0.638163f, +0.638693f, +0.639223f, +0.639752f, +0.640281f, +0.640810f, +0.641338f, +0.641867f, +0.642395f, +0.642922f, +0.643450f, +0.643977f, +0.644504f, +0.645031f, +0.645557f, +0.646083f, +0.646609f, +0.647134f, +0.647659f, +0.648184f, +0.648709f, +0.649233f, +0.649758f, +0.650281f, +0.650805f, +0.651328f, +0.651851f, +0.652374f, +0.652896f, +0.653418f, +0.653940f, +0.654462f, +0.654983f, +0.655504f, +0.656024f, +0.656545f, +0.657065f, +0.657584f, +0.658104f, +0.658623f, +0.659142f, +0.659660f, +0.660179f, +0.660696f, +0.661214f, +0.661731f, +0.662248f, +0.662765f, +0.663282f, +0.663798f, +0.664313f, +0.664829f, +0.665344f, +0.665859f, +0.666373f, +0.666888f, +0.667402f, +0.667915f, +0.668428f, +0.668941f, +0.669454f, +0.669966f, +0.670478f, +0.670990f, +0.671502f, +0.672013f, +0.672523f, +0.673034f, +0.673544f, +0.674054f, +0.674563f, +0.675072f, +0.675581f, +0.676089f, +0.676597f, +0.677105f, +0.677613f, +0.678120f, +0.678627f, +0.679133f, +0.679639f, +0.680145f, +0.680651f, +0.681156f, +0.681661f, +0.682165f, +0.682669f, +0.683173f, +0.683676f, +0.684179f, +0.684682f, +0.685185f, +0.685687f, +0.686189f, +0.686690f, +0.687191f, +0.687692f, +0.688192f, +0.688692f, +0.689192f, +0.689691f, +0.690190f, +0.690689f, +0.691187f, +0.691685f, +0.692182f, +0.692680f, +0.693176f, +0.693673f, +0.694169f, +0.694665f, +0.695160f, +0.695655f, +0.696150f, +0.696644f, +0.697138f, +0.697632f, +0.698125f, +0.698618f, +0.699111f, +0.699603f, +0.700095f, +0.700586f, +0.701077f, +0.701568f, +0.702058f, +0.702548f, +0.703038f, +0.703527f, +0.704016f, +0.704505f, +0.704993f, +0.705481f, +0.705968f, +0.706455f, +0.706942f, +0.707428f, +0.707914f, +0.708399f, +0.708885f, +0.709369f, +0.709854f, +0.710338f, +0.710821f, +0.711305f, +0.711788f, +0.712270f, +0.712752f, +0.713234f, +0.713715f, +0.714196f, +0.714677f, +0.715157f, +0.715637f, +0.716116f, +0.716595f, +0.717074f, +0.717552f, +0.718030f, +0.718507f, +0.718985f, +0.719461f, +0.719938f, +0.720413f, +0.720889f, +0.721364f, +0.721839f, +0.722313f, +0.722787f, +0.723261f, +0.723734f, +0.724207f, +0.724679f, +0.725151f, +0.725622f, +0.726094f, +0.726564f, +0.727035f, +0.727505f, +0.727974f, +0.728443f, +0.728912f, +0.729380f, +0.729848f, +0.730316f, +0.730783f, +0.731250f, +0.731716f, +0.732182f, +0.732647f, +0.733113f, +0.733577f, +0.734042f, +0.734505f, +0.734969f, +0.735432f, +0.735894f, +0.736357f, +0.736818f, +0.737280f, +0.737741f, +0.738201f, +0.738662f, +0.739121f, +0.739581f, +0.740039f, +0.740498f, +0.740956f, +0.741414f, +0.741871f, +0.742328f, +0.742784f, +0.743240f, +0.743696f, +0.744151f, +0.744605f, +0.745060f, +0.745514f, +0.745967f, +0.746420f, +0.746873f, +0.747325f, +0.747776f, +0.748228f, +0.748679f, +0.749129f, +0.749579f, +0.750029f, +0.750478f, +0.750927f, +0.751375f, +0.751823f, +0.752270f, +0.752717f, +0.753164f, +0.753610f, +0.754056f, +0.754501f, +0.754946f, +0.755390f, +0.755834f, +0.756278f, +0.756721f, +0.757163f, +0.757606f, +0.758047f, +0.758489f, +0.758930f, +0.759370f, +0.759810f, +0.760250f, +0.760689f, +0.761128f, +0.761566f, +0.762004f, +0.762441f, +0.762878f, +0.763315f, +0.763751f, +0.764187f, +0.764622f, +0.765057f, +0.765491f, +0.765925f, +0.766358f, +0.766791f, +0.767224f, +0.767656f, +0.768087f, +0.768519f, +0.768949f, +0.769380f, +0.769809f, +0.770239f, +0.770668f, +0.771096f, +0.771524f, +0.771952f, +0.772379f, +0.772806f, +0.773232f, +0.773658f, +0.774083f, +0.774508f, +0.774933f, +0.775357f, +0.775780f, +0.776203f, +0.776626f, +0.777048f, +0.777470f, +0.777891f, +0.778312f, +0.778732f, +0.779152f, +0.779571f, +0.779990f, +0.780409f, +0.780827f, +0.781245f, +0.781662f, +0.782078f, +0.782495f, +0.782910f, +0.783326f, +0.783741f, +0.784155f, +0.784569f, +0.784982f, +0.785395f, +0.785808f, +0.786220f, +0.786632f, +0.787043f, +0.787453f, +0.787864f, +0.788273f, +0.788683f, +0.789092f, +0.789500f, +0.789908f, +0.790315f, +0.790722f, +0.791129f, +0.791535f, +0.791941f, +0.792346f, +0.792750f, +0.793154f, +0.793558f, +0.793961f, +0.794364f, +0.794767f, +0.795168f, +0.795570f, +0.795971f, +0.796371f, +0.796771f, +0.797171f, +0.797570f, +0.797968f, +0.798366f, +0.798764f, +0.799161f, +0.799558f, +0.799954f, +0.800350f, +0.800745f, +0.801140f, +0.801534f, +0.801928f, +0.802321f, +0.802714f, +0.803107f, +0.803499f, +0.803890f, +0.804281f, +0.804672f, +0.805062f, +0.805451f, +0.805841f, +0.806229f, +0.806617f, +0.807005f, +0.807392f, +0.807779f, +0.808165f, +0.808551f, +0.808937f, +0.809321f, +0.809706f, +0.810090f, +0.810473f, +0.810856f, +0.811238f, +0.811620f, +0.812002f, +0.812383f, +0.812764f, +0.813144f, +0.813523f, +0.813902f, +0.814281f, +0.814659f, +0.815037f, +0.815414f, +0.815791f, +0.816167f, +0.816543f, +0.816918f, +0.817293f, +0.817667f, +0.818041f, +0.818414f, +0.818787f, +0.819160f, +0.819532f, +0.819903f, +0.820274f, +0.820645f, +0.821015f, +0.821384f, +0.821753f, +0.822122f, +0.822490f, +0.822858f, +0.823225f, +0.823591f, +0.823957f, +0.824323f, +0.824688f, +0.825053f, +0.825417f, +0.825781f, +0.826144f, +0.826507f, +0.826869f, +0.827231f, +0.827593f, +0.827953f, +0.828314f, +0.828674f, +0.829033f, +0.829392f, +0.829751f, +0.830109f, +0.830466f, +0.830823f, +0.831180f, +0.831536f, +0.831891f, +0.832246f, +0.832601f, +0.832955f, +0.833308f, +0.833662f, +0.834014f, +0.834366f, +0.834718f, +0.835069f, +0.835420f, +0.835770f, +0.836120f, +0.836469f, +0.836818f, +0.837166f, +0.837514f, +0.837862f, +0.838208f, +0.838555f, +0.838901f, +0.839246f, +0.839591f, +0.839935f, +0.840279f, +0.840623f, +0.840966f, +0.841308f, +0.841650f, +0.841992f, +0.842333f, +0.842673f, +0.843013f, +0.843353f, +0.843692f, +0.844031f, +0.844369f, +0.844707f, +0.845044f, +0.845380f, +0.845717f, +0.846052f, +0.846388f, +0.846722f, +0.847057f, +0.847390f, +0.847724f, +0.848056f, +0.848389f, +0.848721f, +0.849052f, +0.849383f, +0.849713f, +0.850043f, +0.850373f, +0.850702f, +0.851030f, +0.851358f, +0.851685f, +0.852013f, +0.852339f, +0.852665f, +0.852991f, +0.853316f, +0.853640f, +0.853964f, +0.854288f, +0.854611f, +0.854934f, +0.855256f, +0.855578f, +0.855899f, +0.856220f, +0.856540f, +0.856860f, +0.857179f, +0.857498f, +0.857816f, +0.858134f, +0.858451f, +0.858768f, +0.859085f, +0.859401f, +0.859716f, +0.860031f, +0.860346f, +0.860660f, +0.860973f, +0.861286f, +0.861599f, +0.861911f, +0.862222f, +0.862534f, +0.862844f, +0.863154f, +0.863464f, +0.863773f, +0.864082f, +0.864390f, +0.864698f, +0.865005f, +0.865312f, +0.865618f, +0.865924f, +0.866230f, +0.866534f, +0.866839f, +0.867143f, +0.867446f, +0.867749f, +0.868052f, +0.868354f, +0.868655f, +0.868956f, +0.869257f, +0.869557f, +0.869857f, +0.870156f, +0.870455f, +0.870753f, +0.871050f, +0.871348f, +0.871645f, +0.871941f, +0.872237f, +0.872532f, +0.872827f, +0.873121f, +0.873415f, +0.873709f, +0.874002f, +0.874294f, +0.874586f, +0.874878f, +0.875169f, +0.875459f, +0.875750f, +0.876039f, +0.876328f, +0.876617f, +0.876905f, +0.877193f, +0.877480f, +0.877767f, +0.878054f, +0.878340f, +0.878625f, +0.878910f, +0.879194f, +0.879478f, +0.879762f, +0.880045f, +0.880328f, +0.880610f, +0.880891f, +0.881172f, +0.881453f, +0.881733f, +0.882013f, +0.882293f, +0.882571f, +0.882850f, +0.883128f, +0.883405f, +0.883682f, +0.883959f, +0.884235f, +0.884510f, +0.884785f, +0.885060f, +0.885334f, +0.885608f, +0.885881f, +0.886154f, +0.886426f, +0.886698f, +0.886969f, +0.887240f, +0.887511f, +0.887781f, +0.888050f, +0.888319f, +0.888588f, +0.888856f, +0.889124f, +0.889391f, +0.889658f, +0.889924f, +0.890190f, +0.890455f, +0.890720f, +0.890984f, +0.891248f, +0.891512f, +0.891775f, +0.892038f, +0.892300f, +0.892561f, +0.892823f, +0.893083f, +0.893344f, +0.893604f, +0.893863f, +0.894122f, +0.894380f, +0.894638f, +0.894896f, +0.895153f, +0.895410f, +0.895666f, +0.895922f, +0.896177f, +0.896432f, +0.896686f, +0.896940f, +0.897194f, +0.897447f, +0.897699f, +0.897951f, +0.898203f, +0.898454f, +0.898705f, +0.898955f, +0.899205f, +0.899454f, +0.899703f, +0.899952f, +0.900200f, +0.900448f, +0.900695f, +0.900941f, +0.901188f, +0.901433f, +0.901679f, +0.901924f, +0.902168f, +0.902412f, +0.902656f, +0.902899f, +0.903142f, +0.903384f, +0.903626f, +0.903867f, +0.904108f, +0.904348f, +0.904588f, +0.904828f, +0.905067f, +0.905306f, +0.905544f, +0.905782f, +0.906019f, +0.906256f, +0.906493f, +0.906729f, +0.906964f, +0.907199f, +0.907434f, +0.907668f, +0.907902f, +0.908136f, +0.908368f, +0.908601f, +0.908833f, +0.909065f, +0.909296f, +0.909527f, +0.909757f, +0.909987f, +0.910216f, +0.910445f, +0.910674f, +0.910902f, +0.911130f, +0.911357f, +0.911584f, +0.911810f, +0.912036f, +0.912262f, +0.912487f, +0.912712f, +0.912936f, +0.913160f, +0.913383f, +0.913606f, +0.913829f, +0.914051f, +0.914273f, +0.914494f, +0.914715f, +0.914935f, +0.915155f, +0.915375f, +0.915594f, +0.915812f, +0.916031f, +0.916249f, +0.916466f, +0.916683f, +0.916900f, +0.917116f, +0.917331f, +0.917547f, +0.917762f, +0.917976f, +0.918190f, +0.918404f, +0.918617f, +0.918830f, +0.919042f, +0.919254f, +0.919466f, +0.919677f, +0.919887f, +0.920098f, +0.920307f, +0.920517f, +0.920726f, +0.920934f, +0.921143f, +0.921350f, +0.921558f, +0.921765f, +0.921971f, +0.922177f, +0.922383f, +0.922588f, +0.922793f, +0.922998f, +0.923202f, +0.923405f, +0.923608f, +0.923811f, +0.924014f, +0.924216f, +0.924417f, +0.924618f, +0.924819f, +0.925020f, +0.925219f, +0.925419f, +0.925618f, +0.925817f, +0.926015f, +0.926213f, +0.926411f, +0.926608f, +0.926804f, +0.927001f, +0.927197f, +0.927392f, +0.927587f, +0.927782f, +0.927976f, +0.928170f, +0.928364f, +0.928557f, +0.928749f, +0.928942f, +0.929133f, +0.929325f, +0.929516f, +0.929707f, +0.929897f, +0.930087f, +0.930276f, +0.930466f, +0.930654f, +0.930843f, +0.931031f, +0.931218f, +0.931405f, +0.931592f, +0.931778f, +0.931964f, +0.932150f, +0.932335f, +0.932520f, +0.932704f, +0.932888f, +0.933072f, +0.933255f, +0.933438f, +0.933620f, +0.933802f, +0.933984f, +0.934165f, +0.934346f, +0.934527f, +0.934707f, +0.934887f, +0.935066f, +0.935245f, +0.935424f, +0.935602f, +0.935780f, +0.935957f, +0.936134f, +0.936311f, +0.936487f, +0.936663f, +0.936839f, +0.937014f, +0.937189f, +0.937363f, +0.937537f, +0.937711f, +0.937884f, +0.938057f, +0.938229f, +0.938402f, +0.938573f, +0.938745f, +0.938916f, +0.939086f, +0.939257f, +0.939427f, +0.939596f, +0.939765f, +0.939934f, +0.940103f, +0.940271f, +0.940438f, +0.940606f, +0.940773f, +0.940939f, +0.941105f, +0.941271f, +0.941437f, +0.941602f, +0.941767f, +0.941931f, +0.942095f, +0.942259f, +0.942422f, +0.942585f, +0.942747f, +0.942910f, +0.943071f, +0.943233f, +0.943394f, +0.943555f, +0.943715f, +0.943875f, +0.944035f, +0.944194f, +0.944353f, +0.944512f, +0.944670f, +0.944828f, +0.944985f, +0.945143f, +0.945299f, +0.945456f, +0.945612f, +0.945768f, +0.945923f, +0.946078f, +0.946233f, +0.946387f, +0.946541f, +0.946695f, +0.946848f, +0.947001f, +0.947154f, +0.947306f, +0.947458f, +0.947609f, +0.947761f, +0.947911f, +0.948062f, +0.948212f, +0.948362f, +0.948511f, +0.948661f, +0.948809f, +0.948958f, +0.949106f, +0.949254f, +0.949401f, +0.949548f, +0.949695f, +0.949841f, +0.949987f, +0.950133f, +0.950278f, +0.950423f, +0.950568f, +0.950712f, +0.950857f, +0.951000f, +0.951144f, +0.951287f, +0.951429f, +0.951572f, +0.951714f, +0.951855f, +0.951997f, +0.952138f, +0.952278f, +0.952419f, +0.952559f, +0.952698f, +0.952838f, +0.952977f, +0.953116f, +0.953254f, +0.953392f, +0.953530f, +0.953667f, +0.953804f, +0.953941f, +0.954077f, +0.954213f, +0.954349f, +0.954485f, +0.954620f, +0.954755f, +0.954889f, +0.955023f, +0.955157f, +0.955290f, +0.955424f, +0.955557f, +0.955689f, +0.955821f, +0.955953f, +0.956085f, +0.956216f, +0.956347f, +0.956478f, +0.956608f, +0.956738f, +0.956868f, +0.956997f, +0.957126f, +0.957255f, +0.957383f, +0.957512f, +0.957639f, +0.957767f, +0.957894f, +0.958021f, +0.958148f, +0.958274f, +0.958400f, +0.958526f, +0.958651f, +0.958776f, +0.958901f, +0.959025f, +0.959149f, +0.959273f, +0.959397f, +0.959520f, +0.959643f, +0.959765f, +0.959888f, +0.960010f, +0.960131f, +0.960253f, +0.960374f, +0.960494f, +0.960615f, +0.960735f, +0.960855f, +0.960975f, +0.961094f, +0.961213f, +0.961332f, +0.961450f, +0.961568f, +0.961686f, +0.961804f, +0.961921f, +0.962038f, +0.962154f, +0.962271f, +0.962387f, +0.962503f, +0.962618f, +0.962733f, +0.962848f, +0.962963f, +0.963077f, +0.963191f, +0.963305f, +0.963418f, +0.963531f, +0.963644f, +0.963757f, +0.963869f, +0.963981f, +0.964093f, +0.964204f, +0.964316f, +0.964426f, +0.964537f, +0.964647f, +0.964757f, +0.964867f, +0.964977f, +0.965086f, +0.965195f, +0.965303f, +0.965412f, +0.965520f, +0.965628f, +0.965735f, +0.965842f, +0.965949f, +0.966056f, +0.966162f, +0.966269f, +0.966374f, +0.966480f, +0.966585f, +0.966690f, +0.966795f, +0.966900f, +0.967004f, +0.967108f, +0.967212f, +0.967315f, +0.967418f, +0.967521f, +0.967624f, +0.967726f, +0.967828f, +0.967930f, +0.968032f, +0.968133f, +0.968234f, +0.968335f, +0.968435f, +0.968535f, +0.968635f, +0.968735f, +0.968834f, +0.968934f, +0.969033f, +0.969131f, +0.969230f, +0.969328f, +0.969426f, +0.969523f, +0.969621f, +0.969718f, +0.969815f, +0.969911f, +0.970008f, +0.970104f, +0.970199f, +0.970295f, +0.970390f, +0.970485f, +0.970580f, +0.970675f, +0.970769f, +0.970863f, +0.970957f, +0.971050f, +0.971144f, +0.971237f, +0.971330f, +0.971422f, +0.971514f, +0.971606f, +0.971698f, +0.971790f, +0.971881f, +0.971972f, +0.972063f, +0.972154f, +0.972244f, +0.972334f, +0.972424f, +0.972513f, +0.972603f, +0.972692f, +0.972781f, +0.972869f, +0.972958f, +0.973046f, +0.973134f, +0.973221f, +0.973309f, +0.973396f, +0.973483f, +0.973570f, +0.973656f, +0.973742f, +0.973828f, +0.973914f, +0.974000f, +0.974085f, +0.974170f, +0.974255f, +0.974340f, +0.974424f, +0.974508f, +0.974592f, +0.974676f, +0.974759f, +0.974842f, +0.974925f, +0.975008f, +0.975090f, +0.975173f, +0.975255f, +0.975337f, +0.975418f, +0.975500f, +0.975581f, +0.975662f, +0.975742f, +0.975823f, +0.975903f, +0.975983f, +0.976063f, +0.976143f, +0.976222f, +0.976301f, +0.976380f, +0.976459f, +0.976537f, +0.976615f, +0.976693f, +0.976771f, +0.976849f, +0.976926f, +0.977003f, +0.977080f, +0.977157f, +0.977234f, +0.977310f, +0.977386f, +0.977462f, +0.977537f, +0.977613f, +0.977688f, +0.977763f, +0.977838f, +0.977912f, +0.977987f, +0.978061f, +0.978135f, +0.978209f, +0.978282f, +0.978356f, +0.978429f, +0.978502f, +0.978574f, +0.978647f, +0.978719f, +0.978791f, +0.978863f, +0.978935f, +0.979006f, +0.979077f, +0.979148f, +0.979219f, +0.979290f, +0.979360f, +0.979430f, +0.979500f, +0.979570f, +0.979640f, +0.979709f, +0.979778f, +0.979848f, +0.979916f, +0.979985f, +0.980053f, +0.980122f, +0.980190f, +0.980257f, +0.980325f, +0.980392f, +0.980460f, +0.980527f, +0.980594f, +0.980660f, +0.980727f, +0.980793f, +0.980859f, +0.980925f, +0.980991f, +0.981056f, +0.981121f, +0.981186f, +0.981251f, +0.981316f, +0.981381f, +0.981445f, +0.981509f, +0.981573f, +0.981637f, +0.981700f, +0.981764f, +0.981827f, +0.981890f, +0.981953f, +0.982016f, +0.982078f, +0.982140f, +0.982202f, +0.982264f, +0.982326f, +0.982388f, +0.982449f, +0.982510f, +0.982571f, +0.982632f, +0.982693f, +0.982753f, +0.982813f, +0.982873f, +0.982933f, +0.982993f, +0.983053f, +0.983112f, +0.983171f, +0.983230f, +0.983289f, +0.983348f, +0.983406f, +0.983464f, +0.983523f, +0.983581f, +0.983638f, +0.983696f, +0.983753f, +0.983811f, +0.983868f, +0.983925f, +0.983981f, +0.984038f, +0.984094f, +0.984151f, +0.984207f, +0.984263f, +0.984318f, +0.984374f, +0.984429f, +0.984485f, +0.984540f, +0.984594f, +0.984649f, +0.984704f, +0.984758f, +0.984812f, +0.984866f, +0.984920f, +0.984974f, +0.985028f, +0.985081f, +0.985134f, +0.985187f, +0.985240f, +0.985293f, +0.985345f, +0.985398f, +0.985450f, +0.985502f, +0.985554f, +0.985606f, +0.985657f, +0.985709f, +0.985760f, +0.985811f, +0.985862f, +0.985913f, +0.985964f, +0.986014f, +0.986065f, +0.986115f, +0.986165f, +0.986215f, +0.986264f, +0.986314f, +0.986363f, +0.986413f, +0.986462f, +0.986511f, +0.986560f, +0.986608f, +0.986657f, +0.986705f, +0.986753f, +0.986801f, +0.986849f, +0.986897f, +0.986945f, +0.986992f, +0.987039f, +0.987086f, +0.987133f, +0.987180f, +0.987227f, +0.987274f, +0.987320f, +0.987366f, +0.987412f, +0.987458f, +0.987504f, +0.987550f, +0.987595f, +0.987641f, +0.987686f, +0.987731f, +0.987776f, +0.987821f, +0.987865f, +0.987910f, +0.987954f, +0.987999f, +0.988043f, +0.988087f, +0.988131f, +0.988174f, +0.988218f, +0.988261f, +0.988304f, +0.988348f, +0.988391f, +0.988433f, +0.988476f, +0.988519f, +0.988561f, +0.988603f, +0.988646f, +0.988688f, +0.988730f, +0.988771f, +0.988813f, +0.988854f, +0.988896f, +0.988937f, +0.988978f, +0.989019f, +0.989060f, +0.989101f, +0.989141f, +0.989182f, +0.989222f, +0.989262f, +0.989302f, +0.989342f, +0.989382f, +0.989421f, +0.989461f, +0.989500f, +0.989540f, +0.989579f, +0.989618f, +0.989657f, +0.989695f, +0.989734f, +0.989773f, +0.989811f, +0.989849f, +0.989887f, +0.989925f, +0.989963f, +0.990001f, +0.990039f, +0.990076f, +0.990113f, +0.990151f, +0.990188f, +0.990225f, +0.990262f, +0.990298f, +0.990335f, +0.990372f, +0.990408f, +0.990444f, +0.990480f, +0.990517f, +0.990552f, +0.990588f, +0.990624f, +0.990660f, +0.990695f, +0.990730f, +0.990766f, +0.990801f, +0.990836f, +0.990870f, +0.990905f, +0.990940f, +0.990974f, +0.991009f, +0.991043f, +0.991077f, +0.991111f, +0.991145f, +0.991179f, +0.991213f, +0.991246f, +0.991280f, +0.991313f, +0.991347f, +0.991380f, +0.991413f, +0.991446f, +0.991479f, +0.991511f, +0.991544f, +0.991576f, +0.991609f, +0.991641f, +0.991673f, +0.991705f, +0.991737f, +0.991769f, +0.991801f, +0.991832f, +0.991864f, +0.991895f, +0.991927f, +0.991958f, +0.991989f, +0.992020f, +0.992051f, +0.992081f, +0.992112f, +0.992143f, +0.992173f, +0.992204f, +0.992234f, +0.992264f, +0.992294f, +0.992324f, +0.992354f, +0.992383f, +0.992413f, +0.992443f, +0.992472f, +0.992501f, +0.992531f, +0.992560f, +0.992589f, +0.992618f, +0.992647f, +0.992675f, +0.992704f, +0.992732f, +0.992761f, +0.992789f, +0.992817f, +0.992846f, +0.992874f, +0.992902f, +0.992929f, +0.992957f, +0.992985f, +0.993012f, +0.993040f, +0.993067f, +0.993095f, +0.993122f, +0.993149f, +0.993176f, +0.993203f, +0.993230f, +0.993256f, +0.993283f, +0.993309f, +0.993336f, +0.993362f, +0.993388f, +0.993415f, +0.993441f, +0.993467f, +0.993493f, +0.993518f, +0.993544f, +0.993570f, +0.993595f, +0.993621f, +0.993646f, +0.993671f, +0.993696f, +0.993721f, +0.993746f, +0.993771f, +0.993796f, +0.993821f, +0.993845f, +0.993870f, +0.993894f, +0.993919f, +0.993943f, +0.993967f, +0.993991f, +0.994016f, +0.994039f, +0.994063f, +0.994087f, +0.994111f, +0.994134f, +0.994158f, +0.994181f, +0.994205f, +0.994228f, +0.994251f, +0.994274f, +0.994297f, +0.994320f, +0.994343f, +0.994366f, +0.994389f, +0.994411f, +0.994434f, +0.994456f, +0.994479f, +0.994501f, +0.994523f, +0.994545f, +0.994567f, +0.994589f, +0.994611f, +0.994633f, +0.994655f, +0.994676f, +0.994698f, +0.994720f, +0.994741f, +0.994762f, +0.994784f, +0.994805f, +0.994826f, +0.994847f, +0.994868f, +0.994889f, +0.994910f, +0.994930f, +0.994951f, +0.994972f, +0.994992f, +0.995013f, +0.995033f, +0.995053f, +0.995073f, +0.995094f, +0.995114f, +0.995134f, +0.995154f, +0.995173f, +0.995193f, +0.995213f, +0.995233f, +0.995252f, +0.995272f, +0.995291f, +0.995310f, +0.995330f, +0.995349f, +0.995368f, +0.995387f, +0.995406f, +0.995425f, +0.995444f, +0.995463f, +0.995481f, +0.995500f, +0.995519f, +0.995537f, +0.995556f, +0.995574f, +0.995592f, +0.995610f, +0.995629f, +0.995647f, +0.995665f, +0.995683f, +0.995701f, +0.995718f, +0.995736f, +0.995754f, +0.995772f, +0.995789f, +0.995807f, +0.995824f, +0.995842f, +0.995859f, +0.995876f, +0.995893f, +0.995910f, +0.995927f, +0.995944f, +0.995961f, +0.995978f, +0.995995f, +0.996012f, +0.996028f, +0.996045f, +0.996062f, +0.996078f, +0.996095f, +0.996111f, +0.996127f, +0.996143f, +0.996160f, +0.996176f, +0.996192f, +0.996208f, +0.996224f, +0.996240f, +0.996255f, +0.996271f, +0.996287f, +0.996303f, +0.996318f, +0.996334f, +0.996349f, +0.996365f, +0.996380f, +0.996395f, +0.996410f, +0.996426f, +0.996441f, +0.996456f, +0.996471f, +0.996486f, +0.996501f, +0.996515f, +0.996530f, +0.996545f, +0.996560f, +0.996574f, +0.996589f, +0.996603f, +0.996618f, +0.996632f, +0.996646f, +0.996661f, +0.996675f, +0.996689f, +0.996703f, +0.996717f, +0.996731f, +0.996745f, +0.996759f, +0.996773f, +0.996787f, +0.996801f, +0.996814f, +0.996828f, +0.996841f, +0.996855f, +0.996868f, +0.996882f, +0.996895f, +0.996909f, +0.996922f, +0.996935f, +0.996948f, +0.996961f, +0.996974f, +0.996987f, +0.997000f, +0.997013f, +0.997026f, +0.997039f, +0.997052f, +0.997064f, +0.997077f, +0.997090f, +0.997102f, +0.997115f, +0.997127f, +0.997140f, +0.997152f, +0.997164f, +0.997177f, +0.997189f, +0.997201f, +0.997213f, +0.997225f, +0.997237f, +0.997249f, +0.997261f, +0.997273f, +0.997285f, +0.997297f, +0.997308f, +0.997320f, +0.997332f, +0.997343f, +0.997355f, +0.997367f, +0.997378f, +0.997389f, +0.997401f, +0.997412f, +0.997424f, +0.997435f, +0.997446f, +0.997457f, +0.997468f, +0.997479f, +0.997490f, +0.997501f, +0.997512f, +0.997523f, +0.997534f, +0.997545f, +0.997556f, +0.997566f, +0.997577f, +0.997588f, +0.997598f, +0.997609f, +0.997619f, +0.997630f, +0.997640f, +0.997651f, +0.997661f, +0.997671f, +0.997682f, +0.997692f, +0.997702f, +0.997712f, +0.997722f, +0.997732f, +0.997743f, +0.997752f, +0.997762f, +0.997772f, +0.997782f, +0.997792f, +0.997802f, +0.997812f, +0.997821f, +0.997831f, +0.997841f, +0.997850f, +0.997860f, +0.997869f, +0.997879f, +0.997888f, +0.997898f, +0.997907f, +0.997916f, +0.997926f, +0.997935f, +0.997944f, +0.997953f, +0.997962f, +0.997971f, +0.997980f, +0.997990f, +0.997999f, +0.998007f, +0.998016f, +0.998025f, +0.998034f, +0.998043f, +0.998052f, +0.998060f, +0.998069f, +0.998078f, +0.998086f, +0.998095f, +0.998104f, +0.998112f, +0.998121f, +0.998129f, +0.998137f, +0.998146f, +0.998154f, +0.998163f, +0.998171f, +0.998179f, +0.998187f, +0.998195f, +0.998204f, +0.998212f, +0.998220f, +0.998228f, +0.998236f, +0.998244f, +0.998252f, +0.998260f, +0.998268f, +0.998275f, +0.998283f, +0.998291f, +0.998299f, +0.998307f, +0.998314f, +0.998322f, +0.998330f, +0.998337f, +0.998345f, +0.998352f, +0.998360f, +0.998367f, +0.998375f, +0.998382f, +0.998389f, +0.998397f, +0.998404f, +0.998411f, +0.998419f, +0.998426f, +0.998433f, +0.998440f, +0.998447f, +0.998454f, +0.998462f, +0.998469f, +0.998476f, +0.998483f, +0.998490f, +0.998497f, +0.998503f, +0.998510f, +0.998517f, +0.998524f, +0.998531f, +0.998537f, +0.998544f, +0.998551f, +0.998558f, +0.998564f, +0.998571f, +0.998577f, +0.998584f, +0.998591f, +0.998597f, +0.998603f, +0.998610f, +0.998616f, +0.998623f, +0.998629f, +0.998636f, +0.998642f, +0.998648f, +0.998654f, +0.998661f, +0.998667f, +0.998673f, +0.998679f, +0.998685f, +0.998691f, +0.998697f, +0.998704f, +0.998710f, +0.998716f, +0.998722f, +0.998727f, +0.998733f, +0.998739f, +0.998745f, +0.998751f, +0.998757f, +0.998763f, +0.998768f, +0.998774f, +0.998780f, +0.998786f, +0.998791f, +0.998797f, +0.998803f, +0.998808f, +0.998814f, +0.998819f, +0.998825f, +0.998830f, +0.998836f, +0.998841f, +0.998847f, +0.998852f, +0.998858f, +0.998863f, +0.998868f, +0.998874f, +0.998879f, +0.998884f, +0.998889f, +0.998895f, +0.998900f, +0.998905f, +0.998910f, +0.998915f, +0.998920f, +0.998926f, +0.998931f, +0.998936f, +0.998941f, +0.998946f, +0.998951f, +0.998956f, +0.998961f, +0.998966f, +0.998970f, +0.998975f, +0.998980f, +0.998985f, +0.998990f, +0.998995f, +0.998999f, +0.999004f, +0.999009f, +0.999014f, +0.999018f, +0.999023f, +0.999028f, +0.999032f, +0.999037f, +0.999041f, +0.999046f, +0.999051f, +0.999055f, +0.999060f, +0.999064f, +0.999069f, +0.999073f, +0.999077f, +0.999082f, +0.999086f, +0.999091f, +0.999095f, +0.999099f, +0.999104f, +0.999108f, +0.999112f, +0.999116f, +0.999121f, +0.999125f, +0.999129f, +0.999133f, +0.999137f, +0.999142f, +0.999146f, +0.999150f, +0.999154f, +0.999158f, +0.999162f, +0.999166f, +0.999170f, +0.999174f, +0.999178f, +0.999182f, +0.999186f, +0.999190f, +0.999194f, +0.999198f, +0.999202f, +0.999206f, +0.999209f, +0.999213f, +0.999217f, +0.999221f, +0.999225f, +0.999228f, +0.999232f, +0.999236f, +0.999240f, +0.999243f, +0.999247f, +0.999251f, +0.999254f, +0.999258f, +0.999261f, +0.999265f, +0.999269f, +0.999272f, +0.999276f, +0.999279f, +0.999283f, +0.999286f, +0.999290f, +0.999293f, +0.999297f, +0.999300f, +0.999304f, +0.999307f, +0.999310f, +0.999314f, +0.999317f, +0.999320f, +0.999324f, +0.999327f, +0.999330f, +0.999334f, +0.999337f, +0.999340f, +0.999343f, +0.999347f, +0.999350f, +0.999353f, +0.999356f, +0.999359f, +0.999363f, +0.999366f, +0.999369f, +0.999372f, +0.999375f, +0.999378f, +0.999381f, +0.999384f, +0.999387f, +0.999390f, +0.999393f, +0.999396f, +0.999399f, +0.999402f, +0.999405f, +0.999408f, +0.999411f, +0.999414f, +0.999417f, +0.999420f, +0.999423f, +0.999426f, +0.999428f, +0.999431f, +0.999434f, +0.999437f, +0.999440f, +0.999442f, +0.999445f, +0.999448f, +0.999451f, +0.999453f, +0.999456f, +0.999459f, +0.999462f, +0.999464f, +0.999467f, +0.999470f, +0.999472f, +0.999475f, +0.999478f, +0.999480f, +0.999483f, +0.999485f, +0.999488f, +0.999490f, +0.999493f, +0.999496f, +0.999498f, +0.999501f, +0.999503f, +0.999506f, +0.999508f, +0.999511f, +0.999513f, +0.999515f, +0.999518f, +0.999520f, +0.999523f, +0.999525f, +0.999528f, +0.999530f, +0.999532f, +0.999535f, +0.999537f, +0.999539f, +0.999542f, +0.999544f, +0.999546f, +0.999549f, +0.999551f, +0.999553f, +0.999555f, +0.999558f, +0.999560f, +0.999562f, +0.999564f, +0.999566f, +0.999569f, +0.999571f, +0.999573f, +0.999575f, +0.999577f, +0.999580f, +0.999582f, +0.999584f, +0.999586f, +0.999588f, +0.999590f, +0.999592f, +0.999594f, +0.999596f, +0.999598f, +0.999600f, +0.999602f, +0.999604f, +0.999607f, +0.999609f, +0.999611f, +0.999613f, +0.999615f, +0.999616f, +0.999618f, +0.999620f, +0.999622f, +0.999624f, +0.999626f, +0.999628f, +0.999630f, +0.999632f, +0.999634f, +0.999636f, +0.999638f, +0.999639f, +0.999641f, +0.999643f, +0.999645f, +0.999647f, +0.999649f, +0.999650f, +0.999652f, +0.999654f, +0.999656f, +0.999658f, +0.999659f, +0.999661f, +0.999663f, +0.999665f, +0.999666f, +0.999668f, +0.999670f, +0.999671f, +0.999673f, +0.999675f, +0.999676f, +0.999678f, +0.999680f, +0.999681f, +0.999683f, +0.999685f, +0.999686f, +0.999688f, +0.999690f, +0.999691f, +0.999693f, +0.999694f, +0.999696f, +0.999698f, +0.999699f, +0.999701f, +0.999702f, +0.999704f, +0.999705f, +0.999707f, +0.999708f, +0.999710f, +0.999711f, +0.999713f, +0.999714f, +0.999716f, +0.999717f, +0.999719f, +0.999720f, +0.999722f, +0.999723f, +0.999725f, +0.999726f, +0.999728f, +0.999729f, +0.999730f, +0.999732f, +0.999733f, +0.999735f, +0.999736f, +0.999738f, +0.999739f, +0.999740f, +0.999742f, +0.999743f, +0.999744f, +0.999746f, +0.999747f, +0.999748f, +0.999750f, +0.999751f, +0.999752f, +0.999754f, +0.999755f, +0.999756f, +0.999757f, +0.999759f, +0.999760f, +0.999761f, +0.999763f, +0.999764f, +0.999765f, +0.999766f, +0.999768f, +0.999769f, +0.999770f, +0.999771f, +0.999772f, +0.999774f, +0.999775f, +0.999776f, +0.999777f, +0.999778f, +0.999780f, +0.999781f, +0.999782f, +0.999783f, +0.999784f, +0.999785f, +0.999786f, +0.999788f, +0.999789f, +0.999790f, +0.999791f, +0.999792f, +0.999793f, +0.999794f, +0.999795f, +0.999797f, +0.999798f, +0.999799f, +0.999800f, +0.999801f, +0.999802f, +0.999803f, +0.999804f, +0.999805f, +0.999806f, +0.999807f, +0.999808f, +0.999809f, +0.999810f, +0.999811f, +0.999812f, +0.999813f, +0.999814f, +0.999815f, +0.999816f, +0.999817f, +0.999818f, +0.999819f, +0.999820f, +0.999821f, +0.999822f, +0.999823f, +0.999824f, +0.999825f, +0.999826f, +0.999827f, +0.999828f, +0.999829f, +0.999830f, +0.999831f, +0.999831f, +0.999832f, +0.999833f, +0.999834f, +0.999835f, +0.999836f, +0.999837f, +0.999838f, +0.999839f, +0.999840f, +0.999840f, +0.999841f, +0.999842f, +0.999843f, +0.999844f, +0.999845f, +0.999846f, +0.999846f, +0.999847f, +0.999848f, +0.999849f, +0.999850f, +0.999850f, +0.999851f, +0.999852f, +0.999853f, +0.999854f, +0.999855f, +0.999855f, +0.999856f, +0.999857f, +0.999858f, +0.999858f, +0.999859f, +0.999860f, +0.999861f, +0.999862f, +0.999862f, +0.999863f, +0.999864f, +0.999865f, +0.999865f, +0.999866f, +0.999867f, +0.999867f, +0.999868f, +0.999869f, +0.999870f, +0.999870f, +0.999871f, +0.999872f, +0.999872f, +0.999873f, +0.999874f, +0.999875f, +0.999875f, +0.999876f, +0.999877f, +0.999877f, +0.999878f, +0.999879f, +0.999879f, +0.999880f, +0.999881f, +0.999881f, +0.999882f, +0.999883f, +0.999883f, +0.999884f, +0.999885f, +0.999885f, +0.999886f, +0.999886f, +0.999887f, +0.999888f, +0.999888f, +0.999889f, +0.999890f, +0.999890f, +0.999891f, +0.999891f, +0.999892f, +0.999893f, +0.999893f, +0.999894f, +0.999894f, +0.999895f, +0.999896f, +0.999896f, +0.999897f, +0.999897f, +0.999898f, +0.999898f, +0.999899f, +0.999900f, +0.999900f, +0.999901f, +0.999901f, +0.999902f, +0.999902f, +0.999903f, +0.999903f, +0.999904f, +0.999905f, +0.999905f, +0.999906f, +0.999906f, +0.999907f, +0.999907f, +0.999908f, +0.999908f, +0.999909f, +0.999909f, +0.999910f, +0.999910f, +0.999911f, +0.999911f, +0.999912f, +0.999912f, +0.999913f, +0.999913f, +0.999914f, +0.999914f, +0.999915f, +0.999915f, +0.999916f, +0.999916f, +0.999917f, +0.999917f, +0.999918f, +0.999918f, +0.999918f, +0.999919f, +0.999919f, +0.999920f, +0.999920f, +0.999921f, +0.999921f, +0.999922f, +0.999922f, +0.999923f, +0.999923f, +0.999923f, +0.999924f, +0.999924f, +0.999925f, +0.999925f, +0.999926f, +0.999926f, +0.999926f, +0.999927f, +0.999927f, +0.999928f, +0.999928f, +0.999928f, +0.999929f, +0.999929f, +0.999930f, +0.999930f, +0.999930f, +0.999931f, +0.999931f, +0.999932f, +0.999932f, +0.999932f, +0.999933f, +0.999933f, +0.999934f, +0.999934f, +0.999934f, +0.999935f, +0.999935f, +0.999935f, +0.999936f, +0.999936f, +0.999937f, +0.999937f, +0.999937f, +0.999938f, +0.999938f, +0.999938f, +0.999939f, +0.999939f, +0.999939f, +0.999940f, +0.999940f, +0.999940f, +0.999941f, +0.999941f, +0.999941f, +0.999942f, +0.999942f, +0.999943f, +0.999943f, +0.999943f, +0.999943f, +0.999944f, +0.999944f, +0.999944f, +0.999945f, +0.999945f, +0.999945f, +0.999946f, +0.999946f, +0.999946f, +0.999947f, +0.999947f, +0.999947f, +0.999948f, +0.999948f, +0.999948f, +0.999949f, +0.999949f, +0.999949f, +0.999949f, +0.999950f, +0.999950f, +0.999950f, +0.999951f, +0.999951f, +0.999951f, +0.999951f, +0.999952f, +0.999952f, +0.999952f, +0.999953f, +0.999953f, +0.999953f, +0.999953f, +0.999954f, +0.999954f, +0.999954f, +0.999954f, +0.999955f, +0.999955f, +0.999955f, +0.999956f, +0.999956f, +0.999956f, +0.999956f, +0.999957f, +0.999957f, +0.999957f, +0.999957f, +0.999958f, +0.999958f, +0.999958f, +0.999958f, +0.999959f, +0.999959f, +0.999959f, +0.999959f, +0.999959f, +0.999960f, +0.999960f, +0.999960f, +0.999960f, +0.999961f, +0.999961f, +0.999961f, +0.999961f, +0.999962f, +0.999962f, +0.999962f, +0.999962f, +0.999962f, +0.999963f, +0.999963f, +0.999963f, +0.999963f, +0.999964f, +0.999964f, +0.999964f, +0.999964f, +0.999964f, +0.999965f, +0.999965f, +0.999965f, +0.999965f, +0.999965f, +0.999966f, +0.999966f, +0.999966f, +0.999966f, +0.999967f, +0.999967f, +0.999967f, +0.999967f, +0.999967f, +0.999967f, +0.999968f, +0.999968f, +0.999968f, +0.999968f, +0.999968f, +0.999969f, +0.999969f, +0.999969f, +0.999969f, +0.999969f, +0.999970f, +0.999970f, +0.999970f, +0.999970f, +0.999970f, +0.999970f, +0.999971f, +0.999971f, +0.999971f, +0.999971f, +0.999971f, +0.999972f, +0.999972f, +0.999972f, +0.999972f, +0.999972f, +0.999972f, +0.999972f, +0.999973f, +0.999973f, +0.999973f, +0.999973f, +0.999973f, +0.999973f, +0.999974f, +0.999974f, +0.999974f, +0.999974f, +0.999974f, +0.999974f, +0.999975f, +0.999975f, +0.999975f, +0.999975f, +0.999975f, +0.999975f, +0.999975f, +0.999976f, +0.999976f, +0.999976f, +0.999976f, +0.999976f, +0.999976f, +0.999977f, +0.999977f, +0.999977f, +0.999977f, +0.999977f, +0.999977f, +0.999977f, +0.999977f, +0.999978f, +0.999978f, +0.999978f, +0.999978f, +0.999978f, +0.999978f, +0.999978f, +0.999979f, +0.999979f, +0.999979f, +0.999979f, +0.999979f, +0.999979f, +0.999979f, +0.999979f, +0.999980f, +0.999980f, +0.999980f, +0.999980f, +0.999980f, +0.999980f, +0.999980f, +0.999980f, +0.999981f, +0.999981f, +0.999981f, +0.999981f, +0.999981f, +0.999981f, +0.999981f, +0.999981f, +0.999981f, +0.999982f, +0.999982f, +0.999982f, +0.999982f, +0.999982f, +0.999982f, +0.999982f, +0.999982f, +0.999982f, +0.999983f, +0.999983f, +0.999983f, +0.999983f, +0.999983f, +0.999983f, +0.999983f, +0.999983f, +0.999983f, +0.999984f, +0.999984f, +0.999984f, +0.999984f, +0.999984f, +0.999984f, +0.999984f, +0.999984f, +0.999984f, +0.999984f, +0.999985f, +0.999985f, +0.999985f, +0.999985f, +0.999985f, +0.999985f, +0.999985f, +0.999985f, +0.999985f, +0.999985f, +0.999985f, +0.999986f, +0.999986f, +0.999986f, +0.999986f, +0.999986f, +0.999986f, +0.999986f, +0.999986f, +0.999986f, +0.999986f, +0.999986f, +0.999986f, +0.999987f, +0.999987f, +0.999987f, +0.999987f, +0.999987f, +0.999987f, +0.999987f, +0.999987f, +0.999987f, +0.999987f, +0.999987f, +0.999987f, +0.999988f, +0.999988f, +0.999988f, +0.999988f, +0.999988f, +0.999988f, +0.999988f, +0.999988f, +0.999988f, +0.999988f, +0.999988f, +0.999988f, +0.999988f, +0.999989f, +0.999989f, +0.999989f, +0.999989f, +0.999989f, +0.999989f, +0.999989f, +0.999989f, +0.999989f, +0.999989f, +0.999989f, +0.999989f, +0.999989f, +0.999989f, +0.999990f, +0.999990f, +0.999990f, +0.999990f, +0.999990f, +0.999990f, +0.999990f, +0.999990f, +0.999990f, +0.999990f, +0.999990f, +0.999990f, +0.999990f, +0.999990f, +0.999990f, +0.999990f, +0.999991f, +0.999991f, +0.999991f, +0.999991f, +0.999991f, +0.999991f, +0.999991f, +0.999991f, +0.999991f, +0.999991f, +0.999991f, +0.999991f, +0.999991f, +0.999991f, +0.999991f, +0.999991f, +0.999991f, +0.999991f, +0.999992f, +0.999992f, +0.999992f, +0.999992f, +0.999992f, +0.999992f, +0.999992f, +0.999992f, +0.999992f, +0.999992f, +0.999992f, +0.999992f, +0.999992f, +0.999992f, +0.999992f, +0.999992f, +0.999992f, +0.999992f, +0.999992f, +0.999993f, +0.999993f, +0.999993f, +0.999993f, +0.999993f, +0.999993f, +0.999993f, +0.999993f, +0.999993f, +0.999993f, +0.999993f, +0.999993f, +0.999993f, +0.999993f, +0.999993f, +0.999993f, +0.999993f, +0.999993f, +0.999993f, +0.999993f, +0.999993f, +0.999993f, +0.999994f, +0.999994f, +0.999994f, +0.999994f, +0.999994f, +0.999994f, +0.999994f, +0.999994f, +0.999994f, +0.999994f, +0.999994f, +0.999994f, +0.999994f, +0.999994f, +0.999994f, +0.999994f, +0.999994f, +0.999994f, +0.999994f, +0.999994f, +0.999994f, +0.999994f, +0.999994f, +0.999994f, +0.999994f, +0.999994f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999995f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999996f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999997f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999998f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +0.999999f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f, +1.000000f diff --git a/rce/rcecalib/dataproc/fit/errf_ext_fastint.dat b/rce/rcecalib/dataproc/fit/errf_ext_fastint.dat new file mode 100644 index 00000000..8d27297c --- /dev/null +++ b/rce/rcecalib/dataproc/fit/errf_ext_fastint.dat @@ -0,0 +1,8191 @@ +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +9, +9, +9, +9, +9, +9, +9, +9, +9, +9, +9, +9, +9, +9, +9, +9, +9, +9, +10, +10, +10, +10, +10, +10, +10, +10, +10, +10, +10, +10, +10, +10, +10, +11, +11, +11, +11, +11, +11, +11, +11, +11, +11, +11, +11, +11, +11, +11, +12, +12, +12, +12, +12, +12, +12, +12, +12, +12, +12, +12, +12, +13, +13, +13, +13, +13, +13, +13, +13, +13, +13, +13, +13, +14, +14, +14, +14, +14, +14, +14, +14, +14, +14, +14, +14, +15, +15, +15, +15, +15, +15, +15, +15, +15, +15, +15, +16, +16, +16, +16, +16, +16, +16, +16, +16, +16, +17, +17, +17, +17, +17, +17, +17, +17, +17, +18, +18, +18, +18, +18, +18, +18, +18, +18, +19, +19, +19, +19, +19, +19, +19, +19, +19, +20, +20, +20, +20, +20, +20, +20, +20, +21, +21, +21, +21, +21, +21, +21, +21, +22, +22, +22, +22, +22, +22, +22, +23, +23, +23, +23, +23, +23, +23, +23, +24, +24, +24, +24, +24, +24, +25, +25, +25, +25, +25, +25, +25, +26, +26, +26, +26, +26, +26, +27, +27, +27, +27, +27, +27, +27, +28, +28, +28, +28, +28, +29, +29, +29, +29, +29, +29, +30, +30, +30, +30, +30, +30, +31, +31, +31, +31, +31, +32, +32, +32, +32, +32, +33, +33, +33, +33, +33, +34, +34, +34, +34, +34, +35, +35, +35, +35, +35, +36, +36, +36, +36, +36, +37, +37, +37, +37, +38, +38, +38, +38, +38, +39, +39, +39, +39, +40, +40, +40, +40, +41, +41, +41, +41, +41, +43, +43, +43, +43, +44, +44, +44, +44, +45, +45, +45, +45, +46, +46, +46, +47, +47, +47, +47, +48, +48, +48, +48, +49, +49, +49, +50, +50, +50, +50, +51, +51, +51, +52, +52, +52, +52, +53, +53, +53, +54, +54, +54, +55, +55, +55, +56, +56, +56, +57, +57, +57, +58, +58, +58, +58, +59, +59, +60, +60, +60, +61, +61, +61, +62, +62, +62, +63, +63, +63, +64, +64, +64, +65, +65, +66, +66, +66, +67, +67, +67, +68, +68, +69, +69, +69, +70, +70, +71, +71, +71, +72, +72, +73, +73, +73, +74, +74, +75, +75, +75, +76, +76, +77, +77, +78, +78, +78, +79, +79, +80, +80, +81, +81, +82, +82, +83, +83, +83, +84, +84, +86, +86, +87, +87, +88, +88, +89, +89, +90, +90, +91, +91, +92, +92, +93, +93, +94, +94, +95, +95, +96, +96, +97, +97, +98, +99, +99, +100, +100, +101, +101, +102, +102, +103, +104, +104, +105, +105, +106, +106, +107, +108, +108, +109, +109, +110, +111, +111, +112, +112, +113, +114, +114, +115, +116, +116, +117, +117, +118, +119, +119, +120, +121, +121, +122, +123, +123, +124, +125, +125, +126, +128, +128, +129, +130, +131, +131, +132, +133, +133, +134, +135, +136, +136, +137, +138, +138, +139, +140, +141, +141, +142, +143, +144, +145, +145, +146, +147, +148, +148, +149, +150, +151, +152, +153, +153, +154, +155, +156, +157, +157, +158, +159, +160, +161, +162, +163, +163, +164, +165, +166, +167, +168, +169, +171, +172, +173, +173, +174, +175, +176, +177, +178, +179, +180, +181, +182, +183, +184, +185, +186, +187, +188, +189, +190, +191, +192, +193, +194, +195, +196, +197, +198, +199, +200, +201, +202, +203, +204, +205, +206, +207, +209, +210, +211, +212, +214, +215, +216, +217, +219, +220, +221, +222, +223, +224, +225, +227, +228, +229, +230, +231, +233, +234, +235, +236, +237, +239, +240, +241, +242, +244, +245, +246, +248, +249, +250, +251, +253, +254, +256, +258, +259, +260, +262, +263, +264, +266, +267, +269, +270, +271, +273, +274, +276, +277, +278, +280, +281, +283, +284, +286, +287, +289, +290, +292, +293, +295, +296, +299, +300, +302, +303, +305, +306, +308, +309, +311, +313, +314, +316, +317, +319, +321, +322, +324, +326, +327, +329, +331, +332, +334, +336, +337, +339, +342, +343, +345, +347, +349, +350, +352, +354, +356, +358, +359, +361, +363, +365, +367, +369, +370, +372, +374, +376, +378, +380, +382, +385, +387, +389, +391, +393, +395, +396, +398, +400, +402, +404, +407, +409, +411, +413, +415, +417, +419, +421, +423, +425, +428, +430, +433, +435, +437, +439, +441, +443, +446, +448, +450, +452, +455, +457, +459, +461, +464, +466, +468, +472, +474, +476, +479, +481, +483, +486, +488, +491, +493, +496, +498, +500, +503, +505, +508, +510, +514, +516, +519, +522, +524, +527, +529, +532, +534, +537, +540, +542, +545, +548, +550, +553, +557, +560, +562, +565, +568, +571, +573, +576, +579, +582, +585, +587, +590, +593, +596, +600, +603, +606, +609, +612, +615, +618, +621, +624, +627, +630, +633, +636, +639, +643, +646, +649, +652, +656, +659, +662, +665, +668, +672, +675, +678, +681, +686, +689, +692, +696, +699, +702, +706, +709, +712, +716, +719, +723, +727, +731, +734, +738, +741, +745, +748, +752, +756, +759, +763, +766, +771, +775, +778, +782, +786, +790, +793, +797, +801, +805, +809, +813, +817, +821, +825, +829, +833, +837, +841, +845, +849, +854, +858, +862, +866, +870, +874, +878, +883, +887, +891, +896, +900, +905, +909, +913, +917, +922, +926, +930, +935, +940, +945, +949, +953, +958, +962, +967, +971, +976, +982, +986, +991, +995, +1000, +1005, +1009, +1014, +1019, +1025, +1029, +1034, +1039, +1044, +1049, +1054, +1058, +1063, +1069, +1074, +1079, +1084, +1089, +1094, +1099, +1105, +1111, +1116, +1121, +1126, +1131, +1137, +1142, +1147, +1153, +1159, +1164, +1169, +1175, +1180, +1186, +1191, +1198, +1203, +1209, +1214, +1220, +1225, +1231, +1238, +1243, +1249, +1255, +1261, +1266, +1272, +1278, +1285, +1291, +1297, +1303, +1308, +1314, +1320, +1327, +1334, +1340, +1346, +1352, +1358, +1364, +1371, +1378, +1384, +1390, +1397, +1403, +1410, +1417, +1423, +1429, +1436, +1442, +1449, +1457, +1463, +1470, +1476, +1483, +1490, +1498, +1504, +1511, +1518, +1525, +1532, +1540, +1546, +1553, +1560, +1567, +1574, +1583, +1590, +1597, +1604, +1611, +1618, +1627, +1634, +1641, +1649, +1656, +1664, +1672, +1679, +1687, +1694, +1702, +1710, +1718, +1726, +1733, +1741, +1750, +1758, +1766, +1773, +1781, +1789, +1798, +1806, +1814, +1822, +1830, +1839, +1848, +1856, +1864, +1872, +1881, +1890, +1898, +1907, +1915, +1924, +1933, +1941, +1950, +1959, +1968, +1977, +1986, +1994, +2003, +2013, +2022, +2031, +2040, +2050, +2058, +2068, +2077, +2086, +2096, +2105, +2114, +2123, +2134, +2143, +2152, +2162, +2171, +2182, +2191, +2201, +2210, +2221, +2231, +2240, +2250, +2260, +2271, +2281, +2291, +2301, +2312, +2322, +2332, +2342, +2353, +2363, +2373, +2384, +2395, +2405, +2416, +2426, +2438, +2448, +2459, +2469, +2481, +2492, +2502, +2513, +2525, +2536, +2547, +2558, +2570, +2581, +2592, +2604, +2615, +2626, +2637, +2650, +2661, +2673, +2684, +2696, +2708, +2720, +2732, +2744, +2756, +2767, +2780, +2792, +2804, +2817, +2829, +2841, +2853, +2866, +2878, +2890, +2904, +2916, +2928, +2941, +2954, +2967, +2979, +2993, +3006, +3018, +3032, +3045, +3058, +3072, +3085, +3098, +3111, +3125, +3138, +3151, +3165, +3179, +3192, +3207, +3220, +3234, +3248, +3262, +3275, +3290, +3304, +3318, +3333, +3347, +3361, +3376, +3390, +3404, +3419, +3434, +3448, +3463, +3478, +3492, +3508, +3522, +3537, +3553, +3568, +3582, +3598, +3613, +3629, +3644, +3659, +3676, +3691, +3706, +3722, +3738, +3753, +3770, +3785, +3802, +3818, +3834, +3850, +3866, +3883, +3899, +3915, +3932, +3949, +3965, +3982, +3998, +4016, +4032, +4049, +4067, +4083, +4101, +4118, +4135, +4153, +4170, +4188, +4205, +4222, +4240, +4257, +4276, +4293, +4312, +4329, +4347, +4366, +4384, +4402, +4420, +4439, +4457, +4475, +4495, +4513, +4532, +4550, +4570, +4588, +4607, +4627, +4645, +4665, +4684, +4704, +4723, +4743, +4762, +4782, +4802, +4822, +4841, +4861, +4881, +4901, +4922, +4942, +4962, +4982, +5003, +5023, +5045, +5065, +5086, +5106, +5128, +5148, +5170, +5191, +5212, +5233, +5255, +5276, +5298, +5319, +5341, +5363, +5385, +5407, +5429, +5451, +5473, +5495, +5518, +5540, +5563, +5585, +5608, +5630, +5653, +5677, +5699, +5723, +5745, +5769, +5792, +5816, +5839, +5863, +5886, +5910, +5934, +5958, +5982, +6006, +6030, +6054, +6079, +6104, +6127, +6153, +6177, +6202, +6226, +6252, +6277, +6302, +6327, +6352, +6378, +6404, +6429, +6455, +6480, +6506, +6532, +6558, +6584, +6610, +6637, +6663, +6689, +6716, +6743, +6770, +6797, +6823, +6851, +6878, +6905, +6932, +6960, +6987, +7015, +7043, +7070, +7099, +7127, +7155, +7183, +7212, +7240, +7268, +7297, +7325, +7355, +7384, +7412, +7442, +7471, +7500, +7529, +7559, +7588, +7618, +7648, +7678, +7708, +7738, +7769, +7799, +7829, +7860, +7890, +7921, +7952, +7983, +8014, +8045, +8077, +8109, +8139, +8171, +8203, +8235, +8266, +8299, +8331, +8364, +8395, +8428, +8461, +8494, +8526, +8559, +8592, +8626, +8658, +8692, +8726, +8759, +8793, +8826, +8860, +8895, +8929, +8964, +8997, +9032, +9067, +9102, +9137, +9171, +9206, +9242, +9277, +9313, +9349, +9383, +9419, +9455, +9492, +9528, +9564, +9601, +9637, +9674, +9710, +9748, +9785, +9822, +9859, +9896, +9934, +9971, +10009, +10047, +10085, +10124, +10162, +10200, +10238, +10277, +10316, +10355, +10394, +10433, +10472, +10512, +10552, +10591, +10631, +10671, +10711, +10751, +10791, +10832, +10872, +10913, +10954, +10995, +11036, +11077, +11119, +11160, +11202, +11244, +11286, +11328, +11370, +11413, +11455, +11498, +11540, +11583, +11626, +11670, +11713, +11756, +11800, +11844, +11887, +11931, +11976, +12020, +12064, +12109, +12153, +12198, +12243, +12289, +12335, +12380, +12426, +12471, +12517, +12563, +12609, +12655, +12702, +12748, +12795, +12843, +12890, +12937, +12984, +13031, +13079, +13127, +13175, +13223, +13272, +13320, +13368, +13417, +13466, +13515, +13564, +13614, +13663, +13713, +13762, +13812, +13862, +13913, +13964, +14014, +14065, +14115, +14167, +14218, +14269, +14321, +14372, +14425, +14477, +14529, +14581, +14633, +14687, +14739, +14792, +14845, +14899, +14952, +15006, +15059, +15114, +15168, +15222, +15277, +15331, +15386, +15441, +15497, +15552, +15607, +15663, +15719, +15775, +15831, +15887, +15944, +16001, +16058, +16114, +16172, +16229, +16287, +16345, +16403, +16460, +16519, +16577, +16636, +16695, +16754, +16813, +16872, +16932, +16992, +17051, +17112, +17172, +17232, +17293, +17353, +17415, +17476, +17538, +17599, +17660, +17722, +17784, +17847, +17909, +17972, +18034, +18098, +18161, +18225, +18288, +18352, +18415, +18480, +18544, +18609, +18673, +18739, +18803, +18869, +18934, +19000, +19065, +19132, +19198, +19265, +19332, +19398, +19465, +19532, +19600, +19667, +19735, +19804, +19871, +19940, +20008, +20078, +20147, +20216, +20285, +20355, +20425, +20495, +20566, +20635, +20707, +20777, +20848, +20920, +20992, +21063, +21135, +21207, +21279, +21352, +21425, +21497, +21570, +21644, +21718, +21791, +21865, +21940, +22013, +22088, +22163, +22239, +22313, +22389, +22465, +22541, +22618, +22693, +22770, +22847, +22924, +23002, +23078, +23156, +23234, +23312, +23391, +23470, +23548, +23627, +23706, +23786, +23866, +23946, +24026, +24105, +24186, +24267, +24348, +24429, +24511, +24593, +24675, +24757, +24840, +24922, +25005, +25087, +25171, +25254, +25338, +25422, +25507, +25591, +25676, +25761, +25846, +25931, +26017, +26103, +26189, +26275, +26362, +26449, +26536, +26624, +26712, +26800, +26888, +26976, +27064, +27153, +27242, +27331, +27421, +27510, +27600, +27691, +27782, +27872, +27963, +28054, +28146, +28237, +28329, +28422, +28514, +28607, +28700, +28793, +28887, +28981, +29075, +29169, +29263, +29358, +29453, +29548, +29644, +29740, +29836, +29932, +30028, +30126, +30223, +30320, +30417, +30516, +30613, +30711, +30811, +30909, +31008, +31108, +31208, +31307, +31408, +31508, +31609, +31710, +31811, +31913, +32015, +32117, +32220, +32322, +32424, +32528, +32631, +32735, +32839, +32944, +33048, +33153, +33258, +33363, +33469, +33574, +33681, +33787, +33894, +34001, +34109, +34216, +34324, +34433, +34540, +34650, +34758, +34868, +34977, +35087, +35196, +35307, +35418, +35529, +35640, +35751, +35863, +35976, +36088, +36201, +36314, +36427, +36541, +36655, +36768, +36883, +36998, +37112, +37228, +37344, +37459, +37575, +37692, +37809, +37925, +38043, +38161, +38279, +38397, +38515, +38634, +38754, +38873, +38992, +39112, +39233, +39354, +39475, +39596, +39717, +39839, +39961, +40084, +40207, +40330, +40454, +40577, +40700, +40825, +40949, +41074, +41200, +41325, +41451, +41577, +41704, +41831, +41958, +42085, +42213, +42341, +42469, +42598, +42727, +42856, +42986, +43116, +43246, +43377, +43507, +43639, +43770, +43902, +44035, +44167, +44300, +44433, +44566, +44700, +44834, +44968, +45104, +45239, +45374, +45509, +45645, +45782, +45919, +46056, +46193, +46330, +46469, +46607, +46746, +46885, +47025, +47164, +47304, +47444, +47585, +47726, +47867, +48009, +48151, +48293, +48437, +48579, +48722, +48867, +49010, +49155, +49300, +49444, +49590, +49736, +49882, +50028, +50175, +50322, +50470, +50618, +50766, +50915, +51063, +51213, +51362, +51512, +51662, +51813, +51963, +52115, +52267, +52419, +52571, +52724, +52877, +53030, +53184, +53339, +53492, +53648, +53803, +53958, +54114, +54270, +54427, +54584, +54742, +54899, +55057, +55216, +55374, +55533, +55693, +55853, +56013, +56173, +56335, +56496, +56657, +56819, +56982, +57145, +57308, +57472, +57635, +57799, +57964, +58129, +58295, +58460, +58627, +58792, +58959, +59126, +59294, +59462, +59630, +59799, +59968, +60138, +60308, +60478, +60648, +60819, +60991, +61162, +61334, +61507, +61680, +61853, +62026, +62200, +62375, +62550, +62725, +62901, +63076, +63253, +63429, +63606, +63783, +63962, +64140, +64318, +64497, +64676, +64857, +65037, +65217, +65398, +65580, +65761, +65943, +66125, +66309, +66492, +66675, +66860, +67044, +67229, +67415, +67600, +67786, +67973, +68159, +68346, +68534, +68722, +68911, +69099, +69288, +69478, +69668, +69859, +70049, +70241, +70432, +70624, +70816, +71010, +71202, +71397, +71590, +71785, +71980, +72175, +72371, +72567, +72763, +72961, +73157, +73355, +73553, +73752, +73951, +74150, +74350, +74550, +74750, +74952, +75153, +75355, +75557, +75760, +75963, +76167, +76370, +76575, +76779, +76985, +77191, +77396, +77602, +77809, +78017, +78225, +78433, +78641, +78850, +79059, +79269, +79479, +79690, +79901, +80112, +80324, +80537, +80749, +80963, +81176, +81390, +81605, +81819, +82035, +82250, +82466, +82683, +82900, +83118, +83336, +83554, +83773, +83992, +84211, +84431, +84653, +84873, +85094, +85316, +85538, +85761, +85984, +86208, +86431, +86655, +86881, +87106, +87331, +87558, +87784, +88011, +88239, +88467, +88695, +88924, +89153, +89382, +89613, +89843, +90075, +90306, +90537, +90770, +91002, +91236, +91469, +91704, +91938, +92173, +92408, +92644, +92880, +93117, +93355, +93592, +93831, +94068, +94308, +94547, +94787, +95028, +95268, +95509, +95751, +95993, +96236, +96479, +96722, +96966, +97211, +97456, +97701, +97947, +98193, +98440, +98686, +98934, +99182, +99431, +99680, +99930, +100179, +100429, +100680, +100932, +101183, +101436, +101688, +101941, +102195, +102449, +102704, +102959, +103214, +103470, +103726, +103983, +104240, +104498, +104756, +105014, +105273, +105533, +105793, +106053, +106314, +106575, +106838, +107100, +107363, +107626, +107890, +108154, +108419, +108684, +108949, +109215, +109483, +109749, +110017, +110284, +110553, +110822, +111091, +111362, +111632, +111902, +112174, +112445, +112717, +112990, +113263, +113537, +113811, +114085, +114361, +114636, +114912, +115188, +115466, +115743, +116021, +116299, +116578, +116857, +117137, +117417, +117698, +117980, +118261, +118543, +118825, +119109, +119393, +119676, +119961, +120247, +120531, +120818, +121105, +121392, +121679, +121967, +122255, +122544, +122833, +123123, +123414, +123705, +123996, +124288, +124579, +124872, +125166, +125460, +125754, +126049, +126344, +126640, +126936, +127232, +127529, +127826, +128124, +128423, +128722, +129021, +129321, +129623, +129924, +130225, +130527, +130829, +131132, +131435, +131739, +132044, +132348, +132654, +132960, +133266, +133573, +133880, +134189, +134497, +134805, +135114, +135425, +135735, +136045, +136356, +136669, +136980, +137293, +137607, +137920, +138234, +138549, +138864, +139180, +139496, +139812, +140130, +140447, +140765, +141084, +141403, +141722, +142043, +142363, +142684, +143005, +143328, +143650, +143973, +144296, +144621, +144946, +145270, +145596, +145922, +146248, +146575, +146903, +147230, +147559, +147888, +148217, +148547, +148878, +149209, +149540, +149872, +150204, +150537, +150871, +151204, +151538, +151874, +152209, +152545, +152881, +153218, +153555, +153893, +154231, +154570, +154909, +155249, +155590, +155930, +156272, +156613, +156956, +157298, +157642, +157985, +158330, +158674, +159020, +159366, +159712, +160059, +160406, +160754, +161102, +161451, +161800, +162150, +162500, +162850, +163202, +163554, +163906, +164258, +164612, +164965, +165319, +165675, +166029, +166385, +166742, +167098, +167455, +167813, +168171, +168529, +168889, +169248, +169609, +169969, +170330, +170692, +171054, +171416, +171780, +172143, +172507, +172871, +173237, +173602, +173968, +174334, +174702, +175070, +175437, +175806, +176176, +176544, +176915, +177286, +177656, +178028, +178400, +178772, +179145, +179519, +179893, +180268, +180642, +181017, +181393, +181770, +182147, +182524, +182902, +183280, +183659, +184039, +184419, +184799, +185180, +185562, +185944, +186326, +186708, +187091, +187475, +187859, +188244, +188630, +189016, +189402, +189789, +190176, +190564, +190952, +191340, +191729, +192119, +192509, +192901, +193292, +193683, +194075, +194467, +194861, +195255, +195648, +196043, +196439, +196834, +197230, +197626, +198024, +198421, +198818, +199218, +199616, +200015, +200416, +200816, +201217, +201618, +202020, +202423, +202825, +203229, +203632, +204037, +204441, +204847, +205252, +205659, +206065, +206473, +206880, +207288, +207696, +208106, +208516, +208925, +209336, +209747, +210158, +210571, +210983, +211396, +211810, +212223, +212637, +213052, +213468, +213883, +214300, +214717, +215134, +215552, +215969, +216388, +216808, +217227, +217648, +218067, +218488, +218910, +219332, +219755, +220178, +220601, +221025, +221449, +221874, +222300, +222725, +223152, +223578, +224005, +224433, +224861, +225290, +225719, +226148, +226578, +227008, +227439, +227870, +228302, +228734, +229168, +229601, +230034, +230468, +230903, +231339, +231774, +232210, +232646, +233083, +233521, +233959, +234397, +234835, +235275, +235715, +236154, +236596, +237036, +237478, +237920, +238362, +238806, +239249, +239692, +240137, +240581, +241027, +241472, +241918, +242365, +242812, +243260, +243707, +244156, +244604, +245054, +245503, +245954, +246405, +246855, +247307, +247759, +248211, +248665, +249117, +249571, +250025, +250480, +250935, +251390, +251846, +252303, +252760, +253217, +253675, +254133, +254591, +255050, +255510, +255970, +256431, +256891, +257352, +257814, +258277, +258739, +259202, +259665, +260129, +260593, +261058, +261524, +261989, +262455, +262922, +263389, +263856, +264324, +264792, +265261, +265730, +266200, +266669, +267140, +267610, +268082, +268553, +269025, +269498, +269970, +270444, +270917, +271391, +271866, +272341, +272817, +273292, +273769, +274245, +274722, +275200, +275678, +276156, +276635, +277114, +277594, +278074, +278554, +279034, +279516, +279998, +280479, +280963, +281445, +281928, +282412, +282896, +283380, +283866, +284351, +284836, +285323, +285809, +286297, +286783, +287271, +287759, +288248, +288737, +289226, +289716, +290206, +290697, +291187, +291679, +292170, +292663, +293155, +293648, +294141, +294635, +295129, +295623, +296119, +296613, +297109, +297606, +298101, +298599, +299096, +299593, +300091, +300590, +301088, +301587, +302087, +302586, +303087, +303588, +304089, +304590, +305092, +305594, +306097, +306599, +307102, +307606, +308110, +308615, +309119, +309624, +310130, +310636, +311142, +311649, +312156, +312663, +313170, +313678, +314187, +314695, +315205, +315714, +316224, +316734, +317245, +317756, +318267, +318779, +319291, +319803, +320316, +320829, +321342, +321856, +322370, +322885, +323400, +323915, +324430, +324946, +325463, +325979, +326496, +327013, +327531, +328049, +328567, +329085, +329605, +330124, +330644, +331164, +331684, +332205, +332726, +333247, +333768, +334290, +334813, +335336, +335858, +336381, +336906, +337430, +337954, +338479, +339004, +339529, +340055, +340580, +341106, +341634, +342160, +342687, +343215, +343743, +344270, +344799, +345328, +345858, +346387, +346916, +347447, +347976, +348508, +349038, +349570, +350101, +350633, +351165, +351697, +352231, +352763, +353297, +353830, +354365, +354899, +355434, +355969, +356504, +357040, +357575, +358112, +358647, +359185, +359721, +360259, +360797, +361334, +361872, +362411, +362949, +363488, +364027, +364567, +365107, +365647, +366187, +366728, +367269, +367810, +368352, +368893, +369435, +369978, +370521, +371063, +371606, +372150, +372694, +373237, +373782, +374326, +374871, +375415, +375961, +376507, +377053, +377598, +378144, +378691, +379238, +379785, +380333, +380880, +381428, +381976, +382524, +383073, +383622, +384171, +384720, +385270, +385819, +386370, +386920, +387471, +388022, +388573, +389124, +389676, +390226, +390779, +391331, +391883, +392436, +392989, +393542, +394096, +394649, +395203, +395757, +396311, +396866, +397421, +397976, +398531, +399086, +399642, +400198, +400754, +401310, +401866, +402423, +402980, +403537, +404094, +404653, +405211, +405768, +406327, +406885, +407443, +408002, +408561, +409120, +409679, +410239, +410800, +411359, +411920, +412480, +413040, +413601, +414162, +414724, +415285, +415846, +416408, +416970, +417532, +418095, +418657, +419220, +419782, +420345, +420909, +421472, +422036, +422599, +423163, +423728, +424292, +424856, +425420, +425986, +426551, +427116, +427681, +428247, +428812, +429378, +429943, +430510, +431076, +431642, +432209, +432776, +433343, +433910, +434478, +435045, +435612, +436179, +436748, +437315, +437883, +438452, +439020, +439589, +440158, +440726, +441295, +441865, +442434, +443003, +443573, +444142, +444712, +445282, +445852, +446423, +446993, +447563, +448134, +448705, +449275, +449847, +450417, +450989, +451560, +452131, +452703, +453275, +453847, +454419, +454990, +455563, +456135, +456708, +457280, +457852, +458425, +458998, +459571, +460144, +460717, +461290, +461863, +462437, +463010, +463584, +464158, +464732, +465305, +465880, +466454, +467027, +467602, +468176, +468751, +469325, +469900, +470474, +471050, +471624, +472200, +472774, +473350, +473924, +474500, +475075, +475651, +476226, +476802, +477377, +477953, +478529, +479105, +479680, +480257, +480832, +481409, +481985, +482561, +483137, +483714, +484290, +484867, +485443, +486020, +486596, +487173, +487749, +488326, +488902, +489480, +490056, +490634, +491210, +491787, +492364, +492941, +493518, +494096, +494672, +495250, +495827, +496405, +496982, +497559, +498137, +498714, +499292, +499869, +500447, +501024, +501602, +502179, +502757, +503334, +503912, +504489, +505067, +505645, +506222, +506800, +507378, +507956, +508533, +509111, +509688, +510266, +510844, +511422, +512000, +512577, +513155, +513733, +514311, +514888, +515466, +516043, +516621, +517199, +517777, +518354, +518932, +519510, +520087, +520665, +521242, +521820, +522397, +522975, +523552, +524130, +524707, +525285, +525862, +526440, +527018, +527594, +528172, +528749, +529327, +529903, +530481, +531058, +531635, +532212, +532789, +533365, +533943, +534519, +535097, +535673, +536250, +536826, +537403, +537979, +538556, +539132, +539709, +540285, +540862, +541438, +542014, +542591, +543167, +543742, +544319, +544894, +545470, +546046, +546622, +547197, +547773, +548348, +548924, +549499, +550075, +550649, +551225, +551799, +552375, +552949, +553525, +554099, +554674, +555248, +555823, +556397, +556972, +557545, +558119, +558694, +559267, +559841, +560415, +560989, +561562, +562136, +562709, +563282, +563855, +564428, +565001, +565574, +566147, +566719, +567291, +567864, +568436, +569009, +569580, +570152, +570724, +571296, +571868, +572439, +573010, +573582, +574152, +574724, +575294, +575865, +576436, +577006, +577576, +578147, +578717, +579287, +579857, +580426, +580996, +581565, +582134, +582704, +583273, +583841, +584410, +584979, +585547, +586116, +586684, +587251, +587820, +588387, +588954, +589521, +590089, +590656, +591223, +591790, +592357, +592923, +593489, +594056, +594621, +595187, +595752, +596318, +596883, +597448, +598013, +598579, +599143, +599707, +600271, +600836, +601400, +601963, +602527, +603090, +603654, +604217, +604779, +605342, +605904, +606467, +607029, +607591, +608153, +608714, +609275, +609837, +610398, +610959, +611519, +612079, +612640, +613199, +613760, +614320, +614879, +615438, +615997, +616556, +617114, +617672, +618231, +618788, +619346, +619905, +620462, +621019, +621576, +622133, +622689, +623245, +623801, +624357, +624913, +625468, +626023, +626578, +627133, +627688, +628242, +628796, +629350, +629903, +630457, +631010, +631563, +632116, +632668, +633220, +633773, +634323, +634875, +635426, +635977, +636528, +637079, +637629, +638180, +638729, +639279, +639828, +640377, +640926, +641475, +642023, +642571, +643119, +643666, +644214, +644761, +645308, +645855, +646401, +646946, +647492, +648038, +648584, +649128, +649673, +650217, +650762, +651305, +651849, +652393, +652936, +653478, +654021, +654564, +655106, +655647, +656189, +656730, +657271, +657812, +658352, +658892, +659432, +659972, +660511, +661050, +661588, +662127, +662665, +663202, +663740, +664278, +664814, +665352, +665887, +666424, +666959, +667495, +668031, +668565, +669100, +669634, +670169, +670702, +671236, +671768, +672302, +672834, +673366, +673898, +674429, +674961, +675491, +676023, +676552, +677083, +677612, +678141, +678671, +679200, +679729, +680256, +680784, +681312, +681839, +682365, +682893, +683419, +683944, +684470, +684995, +685520, +686045, +686569, +687093, +687618, +688141, +688663, +689186, +689709, +690231, +690752, +691273, +691794, +692315, +692835, +693355, +693875, +694394, +694914, +695432, +695950, +696468, +696986, +697503, +698020, +698536, +699053, +699569, +700084, +700599, +701114, +701629, +702143, +702657, +703170, +703683, +704196, +704708, +705220, +705732, +706243, +706754, +707265, +707775, +708285, +708794, +709304, +709812, +710321, +710829, +711336, +711843, +712350, +712857, +713363, +713869, +714375, +714880, +715384, +715889, +716393, +716897, +717400, +717902, +718405, +718907, +719409, +719910, +720411, +720912, +721413, +721912, +722412, +722911, +723409, +723908, +724406, +724903, +725400, +725898, +726393, +726890, +727386, +727880, +728376, +728870, +729364, +729858, +730351, +730844, +731336, +731829, +732320, +732812, +733302, +733793, +734283, +734773, +735262, +735751, +736240, +736728, +737216, +737702, +738190, +738676, +739163, +739648, +740133, +740619, +741103, +741587, +742071, +742554, +743036, +743520, +744001, +744483, +744965, +745445, +745925, +746405, +746885, +747364, +747843, +748321, +748799, +749277, +749754, +750230, +750707, +751182, +751658, +752133, +752608, +753082, +753555, +754029, +754501, +754974, +755446, +755917, +756389, +756859, +757330, +757799, +758269, +758738, +759207, +759675, +760143, +760610, +761077, +761544, +762010, +762475, +762941, +763406, +763870, +764334, +764797, +765260, +765722, +766185, +766647, +767108, +767568, +768029, +768489, +768949, +769408, +769866, +770324, +770782, +771239, +771696, +772153, +772609, +773064, +773519, +773973, +774428, +774882, +775334, +775788, +776240, +776692, +777144, +777594, +778045, +778495, +778945, +779395, +779843, +780292, +780739, +781187, +781634, +782080, +782527, +782972, +783418, +783862, +784307, +784750, +785193, +785637, +786079, +786521, +786963, +787403, +787845, +788284, +788724, +789164, +789602, +790040, +790478, +790916, +791353, +791789, +792225, +792661, +793096, +793531, +793965, +794398, +794831, +795265, +795697, +796129, +796560, +796991, +797421, +797851, +798280, +798709, +799138, +799566, +799994, +800421, +800847, +801274, +801699, +802125, +802550, +802974, +803398, +803821, +804244, +804667, +805089, +805511, +805932, +806351, +806772, +807191, +807611, +808030, +808447, +808865, +809282, +809699, +810116, +810531, +810947, +811362, +811776, +812189, +812603, +813016, +813428, +813841, +814252, +814663, +815074, +815483, +815893, +816303, +816711, +817119, +817526, +817934, +818340, +818747, +819152, +819558, +819962, +820367, +820770, +821174, +821576, +821979, +822381, +822782, +823183, +823583, +823984, +824383, +824781, +825181, +825578, +825975, +826373, +826769, +827165, +827560, +827956, +828351, +828744, +829138, +829532, +829924, +830316, +830707, +831098, +831490, +831880, +832270, +832659, +833047, +833435, +833823, +834210, +834597, +834983, +835369, +835755, +836140, +836524, +836908, +837291, +837674, +838055, +838437, +838819, +839200, +839580, +839960, +840340, +840719, +841097, +841475, +841852, +842229, +842606, +842982, +843357, +843731, +844106, +844480, +844854, +845226, +845599, +845971, +846343, +846713, +847084, +847455, +847823, +848193, +848562, +848929, +849297, +849665, +850031, +850397, +850762, +851128, +851492, +851856, +852219, +852583, +852945, +853307, +853669, +854030, +854390, +854751, +855110, +855470, +855828, +856186, +856544, +856901, +857257, +857614, +857970, +858325, +858680, +859034, +859387, +859741, +860093, +860445, +860797, +861149, +861499, +861849, +862199, +862549, +862897, +863245, +863593, +863940, +864287, +864633, +864979, +865325, +865669, +866014, +866357, +866701, +867043, +867386, +867727, +868069, +868409, +868750, +869090, +869429, +869768, +870106, +870444, +870781, +871118, +871454, +871790, +872125, +872461, +872795, +873128, +873462, +873795, +874127, +874459, +874790, +875121, +875452, +875782, +876111, +876440, +876769, +877096, +877424, +877751, +878077, +878403, +878729, +879053, +879378, +879703, +880026, +880349, +880671, +880994, +881315, +881636, +881956, +882277, +882596, +882915, +883234, +883552, +883869, +884187, +884503, +884819, +885135, +885450, +885765, +886079, +886392, +886706, +887019, +887330, +887643, +887954, +888264, +888574, +888885, +889194, +889502, +889810, +890119, +890426, +890733, +891039, +891345, +891651, +891955, +892260, +892564, +892867, +893170, +893472, +893774, +894075, +894376, +894678, +894978, +895277, +895576, +895875, +896173, +896470, +896768, +897063, +897359, +897655, +897950, +898245, +898539, +898833, +899127, +899420, +899711, +900003, +900294, +900585, +900876, +901166, +901455, +901744, +902032, +902320, +902607, +902894, +903181, +903468, +903752, +904038, +904323, +904606, +904890, +905174, +905456, +905738, +906019, +906301, +906582, +906862, +907142, +907421, +907700, +907978, +908256, +908533, +908811, +909087, +909363, +909638, +909914, +910188, +910462, +910736, +911009, +911282, +911554, +911825, +912097, +912367, +912637, +912908, +913177, +913446, +913715, +913982, +914250, +914516, +914784, +915050, +915315, +915580, +915845, +916109, +916373, +916636, +916899, +917161, +917424, +917685, +917946, +918206, +918466, +918726, +918985, +919243, +919501, +919759, +920016, +920273, +920529, +920785, +921040, +921295, +921550, +921804, +922058, +922311, +922563, +922816, +923067, +923319, +923570, +923820, +924069, +924319, +924568, +924817, +925065, +925313, +925559, +925806, +926052, +926298, +926543, +926788, +927033, +927277, +927520, +927763, +928006, +928248, +928490, +928731, +928971, +929212, +929452, +929691, +929931, +930168, +930407, +930645, +930882, +931119, +931355, +931591, +931826, +932061, +932295, +932530, +932763, +932997, +933229, +933462, +933693, +933924, +934156, +934386, +934617, +934846, +935075, +935304, +935532, +935760, +935988, +936215, +936441, +936668, +936893, +937118, +937343, +937568, +937791, +938015, +938238, +938461, +938683, +938905, +939126, +939346, +939568, +939788, +940007, +940226, +940445, +940663, +940881, +941098, +941316, +941533, +941749, +941964, +942180, +942394, +942609, +942823, +943036, +943250, +943462, +943675, +943887, +944098, +944309, +944520, +944730, +944940, +945149, +945358, +945566, +945774, +945982, +946190, +946397, +946603, +946808, +947014, +947220, +947424, +947629, +947832, +948036, +948239, +948442, +948644, +948846, +949047, +949249, +949449, +949649, +949849, +950048, +950247, +950446, +950644, +950842, +951039, +951236, +951432, +951628, +951824, +952019, +952214, +952409, +952602, +952797, +952989, +953183, +953375, +953567, +953758, +953950, +954140, +954331, +954521, +954711, +954900, +955088, +955277, +955465, +955653, +955840, +956026, +956213, +956399, +956584, +956770, +956955, +957139, +957324, +957507, +957690, +957874, +958056, +958238, +958419, +958601, +958782, +958962, +959142, +959323, +959502, +959681, +959859, +960037, +960216, +960393, +960570, +960746, +960923, +961098, +961274, +961450, +961624, +961799, +961973, +962146, +962319, +962492, +962665, +962837, +963008, +963180, +963351, +963521, +963691, +963861, +964031, +964200, +964369, +964537, +964705, +964873, +965040, +965207, +965372, +965539, +965704, +965870, +966035, +966200, +966364, +966528, +966691, +966854, +967017, +967180, +967342, +967503, +967664, +967826, +967986, +968146, +968306, +968466, +968625, +968783, +968942, +969100, +969257, +969415, +969572, +969729, +969885, +970041, +970197, +970351, +970507, +970660, +970815, +970969, +971122, +971275, +971428, +971580, +971732, +971884, +972036, +972186, +972337, +972487, +972637, +972786, +972936, +973084, +973233, +973381, +973529, +973677, +973823, +973971, +974117, +974263, +974409, +974555, +974699, +974844, +974989, +975132, +975277, +975420, +975562, +975706, +975848, +975990, +976132, +976273, +976414, +976554, +976695, +976835, +976974, +977114, +977253, +977392, +977530, +977669, +977806, +977943, +978080, +978217, +978354, +978490, +978625, +978760, +978895, +979031, +979165, +979299, +979433, +979566, +979699, +979832, +979964, +980097, +980229, +980360, +980492, +980622, +980753, +980883, +981013, +981143, +981272, +981401, +981530, +981658, +981786, +981914, +982041, +982168, +982295, +982422, +982548, +982674, +982799, +982925, +983050, +983174, +983299, +983422, +983545, +983669, +983792, +983915, +984038, +984160, +984282, +984403, +984524, +984645, +984766, +984887, +985007, +985126, +985245, +985365, +985484, +985602, +985720, +985838, +985956, +986074, +986190, +986307, +986424, +986540, +986655, +986771, +986887, +987001, +987116, +987231, +987344, +987458, +987572, +987685, +987798, +987911, +988023, +988136, +988248, +988359, +988470, +988581, +988692, +988803, +988912, +989022, +989131, +989241, +989349, +989459, +989566, +989675, +989783, +989890, +989998, +990105, +990212, +990318, +990425, +990530, +990636, +990741, +990846, +990951, +991055, +991160, +991264, +991368, +991471, +991575, +991677, +991779, +991882, +991984, +992085, +992188, +992289, +992390, +992491, +992591, +992692, +992791, +992891, +992991, +993090, +993188, +993288, +993386, +993483, +993582, +993679, +993776, +993873, +993971, +994067, +994163, +994259, +994355, +994451, +994546, +994641, +994736, +994830, +994924, +995018, +995112, +995206, +995299, +995392, +995485, +995577, +995670, +995762, +995853, +995945, +996036, +996127, +996217, +996309, +996399, +996489, +996578, +996668, +996757, +996846, +996935, +997023, +997111, +997199, +997287, +997375, +997463, +997550, +997637, +997724, +997810, +997896, +997982, +998068, +998153, +998238, +998323, +998408, +998492, +998577, +998661, +998745, +998828, +998911, +998994, +999077, +999159, +999242, +999324, +999406, +999488, +999570, +999651, +999732, +999813, +999894, +999973, +1000053, +1000133, +1000213, +1000293, +1000372, +1000451, +1000529, +1000608, +1000687, +1000765, +1000843, +1000921, +1000997, +1001075, +1001152, +1001229, +1001306, +1001381, +1001458, +1001534, +1001610, +1001686, +1001760, +1001836, +1001911, +1001986, +1002059, +1002134, +1002208, +1002281, +1002355, +1002429, +1002502, +1002574, +1002647, +1002720, +1002792, +1002864, +1002936, +1003007, +1003079, +1003151, +1003222, +1003292, +1003364, +1003433, +1003504, +1003574, +1003644, +1003714, +1003783, +1003852, +1003921, +1003991, +1004059, +1004128, +1004195, +1004264, +1004332, +1004399, +1004467, +1004534, +1004601, +1004667, +1004734, +1004801, +1004867, +1004934, +1004999, +1005065, +1005130, +1005196, +1005260, +1005326, +1005390, +1005455, +1005519, +1005584, +1005647, +1005711, +1005774, +1005838, +1005901, +1005965, +1006027, +1006090, +1006152, +1006215, +1006277, +1006339, +1006400, +1006461, +1006523, +1006584, +1006646, +1006706, +1006767, +1006827, +1006887, +1006948, +1007007, +1007067, +1007127, +1007186, +1007245, +1007304, +1007363, +1007422, +1007480, +1007539, +1007596, +1007654, +1007712, +1007770, +1007827, +1007885, +1007941, +1007998, +1008055, +1008112, +1008168, +1008224, +1008280, +1008336, +1008392, +1008447, +1008502, +1008558, +1008613, +1008668, +1008722, +1008777, +1008831, +1008885, +1008940, +1008993, +1009047, +1009100, +1009154, +1009207, +1009260, +1009312, +1009366, +1009418, +1009470, +1009522, +1009574, +1009627, +1009678, +1009730, +1009781, +1009832, +1009884, +1009934, +1009985, +1010035, +1010086, +1010137, +1010187, +1010237, +1010286, +1010336, +1010385, +1010435, +1010484, +1010533, +1010582, +1010631, +1010679, +1010727, +1010776, +1010824, +1010872, +1010920, +1010968, +1011015, +1011062, +1011109, +1011156, +1011204, +1011251, +1011297, +1011344, +1011390, +1011436, +1011482, +1011528, +1011573, +1011619, +1011664, +1011710, +1011756, +1011801, +1011846, +1011890, +1011935, +1011979, +1012023, +1012068, +1012112, +1012155, +1012199, +1012243, +1012286, +1012329, +1012373, +1012416, +1012459, +1012501, +1012544, +1012586, +1012629, +1012671, +1012713, +1012755, +1012797, +1012839, +1012880, +1012922, +1012963, +1013004, +1013045, +1013086, +1013127, +1013167, +1013208, +1013247, +1013288, +1013328, +1013368, +1013408, +1013447, +1013487, +1013527, +1013566, +1013605, +1013644, +1013683, +1013722, +1013761, +1013799, +1013837, +1013875, +1013914, +1013952, +1013990, +1014028, +1014065, +1014103, +1014140, +1014177, +1014214, +1014251, +1014289, +1014325, +1014362, +1014398, +1014435, +1014471, +1014507, +1014544, +1014580, +1014616, +1014650, +1014686, +1014722, +1014757, +1014793, +1014828, +1014862, +1014897, +1014932, +1014967, +1015002, +1015035, +1015070, +1015104, +1015139, +1015173, +1015206, +1015240, +1015273, +1015307, +1015341, +1015373, +1015407, +1015440, +1015473, +1015505, +1015538, +1015571, +1015604, +1015635, +1015668, +1015700, +1015733, +1015765, +1015796, +1015828, +1015860, +1015890, +1015922, +1015954, +1015985, +1016016, +1016047, +1016078, +1016109, +1016139, +1016170, +1016200, +1016230, +1016261, +1016291, +1016321, +1016351, +1016381, +1016411, +1016440, +1016470, +1016499, +1016528, +1016557, +1016587, +1016615, +1016644, +1016674, +1016703, +1016731, +1016759, +1016787, +1016816, +1016844, +1016872, +1016900, +1016929, +1016956, +1016984, +1017012, +1017039, +1017067, +1017094, +1017121, +1017148, +1017176, +1017202, +1017229, +1017256, +1017283, +1017310, +1017336, +1017362, +1017389, +1017415, +1017441, +1017467, +1017493, +1017519, +1017544, +1017570, +1017595, +1017621, +1017647, +1017672, +1017697, +1017722, +1017747, +1017773, +1017797, +1017822, +1017846, +1017872, +1017895, +1017920, +1017945, +1017969, +1017993, +1018017, +1018041, +1018065, +1018089, +1018113, +1018136, +1018160, +1018183, +1018207, +1018230, +1018254, +1018276, +1018300, +1018322, +1018346, +1018369, +1018391, +1018414, +1018436, +1018459, +1018481, +1018504, +1018526, +1018548, +1018570, +1018592, +1018614, +1018636, +1018658, +1018680, +1018701, +1018723, +1018744, +1018766, +1018787, +1018808, +1018829, +1018851, +1018871, +1018893, +1018913, +1018934, +1018954, +1018976, +1018996, +1019017, +1019037, +1019057, +1019077, +1019098, +1019118, +1019138, +1019158, +1019177, +1019197, +1019217, +1019237, +1019256, +1019276, +1019295, +1019315, +1019334, +1019354, +1019372, +1019392, +1019411, +1019429, +1019449, +1019467, +1019486, +1019504, +1019524, +1019542, +1019560, +1019579, +1019597, +1019615, +1019633, +1019652, +1019670, +1019687, +1019706, +1019723, +1019742, +1019759, +1019777, +1019794, +1019811, +1019829, +1019846, +1019864, +1019881, +1019898, +1019916, +1019932, +1019950, +1019967, +1019983, +1020001, +1020017, +1020034, +1020050, +1020067, +1020084, +1020100, +1020117, +1020133, +1020149, +1020165, +1020181, +1020197, +1020214, +1020229, +1020246, +1020261, +1020277, +1020293, +1020308, +1020323, +1020340, +1020355, +1020370, +1020386, +1020401, +1020417, +1020431, +1020446, +1020462, +1020477, +1020491, +1020507, +1020521, +1020536, +1020551, +1020565, +1020580, +1020595, +1020609, +1020623, +1020638, +1020652, +1020666, +1020681, +1020695, +1020709, +1020724, +1020737, +1020751, +1020765, +1020779, +1020792, +1020807, +1020820, +1020834, +1020848, +1020861, +1020874, +1020888, +1020901, +1020914, +1020927, +1020941, +1020954, +1020967, +1020981, +1020993, +1021006, +1021020, +1021032, +1021045, +1021058, +1021071, +1021083, +1021095, +1021109, +1021121, +1021133, +1021146, +1021158, +1021170, +1021182, +1021195, +1021207, +1021219, +1021232, +1021243, +1021255, +1021267, +1021279, +1021291, +1021303, +1021315, +1021326, +1021338, +1021349, +1021362, +1021373, +1021384, +1021395, +1021407, +1021418, +1021429, +1021441, +1021452, +1021463, +1021474, +1021486, +1021497, +1021507, +1021518, +1021530, +1021540, +1021551, +1021561, +1021573, +1021583, +1021594, +1021604, +1021615, +1021626, +1021636, +1021646, +1021657, +1021667, +1021677, +1021687, +1021698, +1021708, +1021718, +1021728, +1021739, +1021749, +1021759, +1021768, +1021778, +1021789, +1021798, +1021808, +1021817, +1021828, +1021837, +1021847, +1021856, +1021865, +1021876, +1021885, +1021894, +1021903, +1021913, +1021922, +1021931, +1021941, +1021949, +1021959, +1021968, +1021977, +1021986, +1021996, +1022005, +1022013, +1022022, +1022031, +1022040, +1022049, +1022058, +1022066, +1022075, +1022084, +1022092, +1022101, +1022109, +1022118, +1022127, +1022135, +1022143, +1022151, +1022160, +1022169, +1022177, +1022185, +1022193, +1022201, +1022210, +1022218, +1022226, +1022233, +1022241, +1022250, +1022258, +1022266, +1022273, +1022281, +1022289, +1022297, +1022305, +1022312, +1022320, +1022327, +1022335, +1022343, +1022350, +1022358, +1022365, +1022372, +1022381, +1022388, +1022395, +1022402, +1022409, +1022416, +1022425, +1022432, +1022439, +1022446, +1022453, +1022459, +1022467, +1022474, +1022481, +1022488, +1022495, +1022501, +1022509, +1022516, +1022523, +1022529, +1022536, +1022542, +1022549, +1022557, +1022563, +1022570, +1022576, +1022582, +1022589, +1022596, +1022602, +1022609, +1022615, +1022621, +1022628, +1022635, +1022641, +1022647, +1022653, +1022659, +1022665, +1022672, +1022679, +1022685, +1022691, +1022696, +1022702, +1022708, +1022714, +1022721, +1022727, +1022733, +1022738, +1022744, +1022750, +1022756, +1022761, +1022768, +1022774, +1022779, +1022785, +1022790, +1022796, +1022801, +1022808, +1022813, +1022819, +1022824, +1022830, +1022835, +1022840, +1022846, +1022852, +1022857, +1022862, +1022868, +1022873, +1022878, +1022883, +1022888, +1022894, +1022900, +1022905, +1022910, +1022915, +1022920, +1022925, +1022930, +1022936, +1022941, +1022945, +1022950, +1022955, +1022960, +1022965, +1022970, +1022974, +1022980, +1022985, +1022990, +1022994, +1022999, +1023004, +1023008, +1023013, +1023018, +1023023, +1023028, +1023032, +1023037, +1023041, +1023046, +1023050, +1023054, +1023059, +1023064, +1023069, +1023073, +1023077, +1023082, +1023086, +1023090, +1023094, +1023099, +1023104, +1023108, +1023112, +1023116, +1023121, +1023125, +1023129, +1023133, +1023137, +1023141, +1023145, +1023150, +1023154, +1023158, +1023162, +1023166, +1023170, +1023174, +1023178, +1023182, +1023186, +1023190, +1023194, +1023198, +1023202, +1023206, +1023209, +1023213, +1023217, +1023221, +1023224, +1023228, +1023233, +1023236, +1023240, +1023243, +1023247, +1023251, +1023254, +1023258, +1023261, +1023265, +1023268, +1023272, +1023276, +1023280, +1023283, +1023287, +1023290, +1023293, +1023297, +1023300, +1023303, +1023307, +1023310, +1023313, +1023317, +1023321, +1023324, +1023327, +1023331, +1023334, +1023337, +1023340, +1023343, +1023347, +1023350, +1023353, +1023356, +1023359, +1023363, +1023366, +1023369, +1023372, +1023375, +1023378, +1023381, +1023384, +1023387, +1023390, +1023393, +1023396, +1023399, +1023403, +1023406, +1023409, +1023412, +1023414, +1023417, +1023420, +1023423, +1023426, +1023428, +1023431, +1023434, +1023437, +1023439, +1023442, +1023446, +1023449, +1023451, +1023454, +1023457, +1023459, +1023462, +1023465, +1023467, +1023470, +1023472, +1023475, +1023477, +1023480, +1023483, +1023485, +1023489, +1023491, +1023494, +1023496, +1023499, +1023501, +1023503, +1023506, +1023508, +1023511, +1023513, +1023516, +1023518, +1023520, +1023523, +1023525, +1023527, +1023531, +1023533, +1023535, +1023538, +1023540, +1023542, +1023544, +1023547, +1023549, +1023551, +1023553, +1023556, +1023558, +1023560, +1023562, +1023564, +1023566, +1023569, +1023571, +1023574, +1023576, +1023578, +1023580, +1023582, +1023584, +1023586, +1023588, +1023590, +1023592, +1023595, +1023597, +1023599, +1023601, +1023603, +1023604, +1023606, +1023608, +1023610, +1023612, +1023614, +1023617, +1023619, +1023621, +1023623, +1023625, +1023627, +1023629, +1023630, +1023632, +1023634, +1023636, +1023638, +1023640, +1023641, +1023643, +1023645, +1023647, +1023649, +1023650, +1023652, +1023654, +1023656, +1023657, +1023660, +1023662, +1023663, +1023665, +1023667, +1023668, +1023670, +1023672, +1023673, +1023675, +1023677, +1023678, +1023680, +1023682, +1023683, +1023685, +1023686, +1023688, +1023690, +1023691, +1023693, +1023694, +1023696, +1023697, +1023699, +1023700, +1023703, +1023704, +1023706, +1023707, +1023709, +1023710, +1023712, +1023713, +1023715, +1023716, +1023718, +1023719, +1023721, +1023722, +1023723, +1023725, +1023726, +1023728, +1023729, +1023730, +1023732, +1023733, +1023735, +1023736, +1023737, +1023739, +1023740, +1023741, +1023744, +1023744, +1023746, +1023748, +1023749, +1023750, +1023751, +1023753, +1023754, +1023755, +1023757, +1023758, +1023759, +1023760, +1023762, +1023763, +1023764, +1023765, +1023766, +1023768, +1023769, +1023770, +1023771, +1023772, +1023774, +1023775, +1023776, +1023777, +1023778, +1023779, +1023780, +1023782, +1023783, +1023784, +1023786, +1023786, +1023788, +1023789, +1023790, +1023792, +1023793, +1023794, +1023795, +1023796, +1023797, +1023798, +1023799, +1023800, +1023801, +1023802, +1023803, +1023804, +1023805, +1023806, +1023807, +1023808, +1023809, +1023810, +1023811, +1023812, +1023813, +1023814, +1023815, +1023816, +1023817, +1023818, +1023819, +1023820, +1023821, +1023822, +1023823, +1023824, +1023825, +1023826, +1023826, +1023827, +1023828, +1023830, +1023831, +1023832, +1023833, +1023834, +1023835, +1023836, +1023836, +1023837, +1023838, +1023839, +1023840, +1023841, +1023842, +1023842, +1023843, +1023844, +1023845, +1023846, +1023846, +1023847, +1023848, +1023849, +1023850, +1023851, +1023851, +1023852, +1023853, +1023854, +1023854, +1023855, +1023856, +1023857, +1023858, +1023858, +1023859, +1023860, +1023861, +1023861, +1023862, +1023863, +1023863, +1023864, +1023865, +1023866, +1023866, +1023867, +1023868, +1023868, +1023869, +1023870, +1023872, +1023872, +1023873, +1023874, +1023874, +1023875, +1023876, +1023876, +1023877, +1023878, +1023878, +1023879, +1023880, +1023880, +1023881, +1023882, +1023882, +1023883, +1023883, +1023884, +1023885, +1023885, +1023886, +1023887, +1023887, +1023888, +1023888, +1023889, +1023890, +1023890, +1023891, +1023891, +1023892, +1023893, +1023893, +1023894, +1023894, +1023895, +1023895, +1023896, +1023897, +1023897, +1023898, +1023898, +1023899, +1023899, +1023900, +1023900, +1023901, +1023902, +1023902, +1023903, +1023903, +1023904, +1023904, +1023905, +1023905, +1023906, +1023906, +1023907, +1023907, +1023908, +1023908, +1023909, +1023909, +1023910, +1023910, +1023911, +1023911, +1023912, +1023912, +1023914, +1023914, +1023914, +1023914, +1023916, +1023916, +1023916, +1023917, +1023917, +1023918, +1023918, +1023919, +1023919, +1023920, +1023920, +1023921, +1023921, +1023921, +1023922, +1023922, +1023923, +1023923, +1023924, +1023924, +1023924, +1023925, +1023925, +1023926, +1023926, +1023926, +1023927, +1023927, +1023928, +1023928, +1023928, +1023929, +1023929, +1023930, +1023930, +1023930, +1023931, +1023931, +1023932, +1023932, +1023932, +1023933, +1023933, +1023933, +1023934, +1023934, +1023935, +1023935, +1023935, +1023936, +1023936, +1023936, +1023937, +1023937, +1023937, +1023938, +1023938, +1023938, +1023939, +1023939, +1023939, +1023940, +1023940, +1023941, +1023941, +1023941, +1023941, +1023942, +1023942, +1023942, +1023943, +1023943, +1023943, +1023944, +1023944, +1023944, +1023945, +1023945, +1023945, +1023946, +1023946, +1023946, +1023947, +1023947, +1023947, +1023947, +1023948, +1023948, +1023948, +1023949, +1023949, +1023949, +1023949, +1023950, +1023950, +1023950, +1023951, +1023951, +1023951, +1023951, +1023952, +1023952, +1023952, +1023952, +1023953, +1023953, +1023953, +1023954, +1023954, +1023954, +1023954, +1023955, +1023955, +1023955, +1023955, +1023956, +1023956, +1023956, +1023956, +1023958, +1023958, +1023958, +1023958, +1023958, +1023959, +1023959, +1023959, +1023959, +1023960, +1023960, +1023960, +1023960, +1023961, +1023961, +1023961, +1023961, +1023961, +1023962, +1023962, +1023962, +1023962, +1023963, +1023963, +1023963, +1023963, +1023963, +1023964, +1023964, +1023964, +1023964, +1023964, +1023965, +1023965, +1023965, +1023965, +1023965, +1023966, +1023966, +1023966, +1023966, +1023966, +1023967, +1023967, +1023967, +1023967, +1023967, +1023968, +1023968, +1023968, +1023968, +1023968, +1023969, +1023969, +1023969, +1023969, +1023969, +1023969, +1023970, +1023970, +1023970, +1023970, +1023970, +1023970, +1023971, +1023971, +1023971, +1023971, +1023971, +1023972, +1023972, +1023972, +1023972, +1023972, +1023972, +1023972, +1023973, +1023973, +1023973, +1023973, +1023973, +1023973, +1023974, +1023974, +1023974, +1023974, +1023974, +1023974, +1023974, +1023975, +1023975, +1023975, +1023975, +1023975, +1023975, +1023976, +1023976, +1023976, +1023976, +1023976, +1023976, +1023976, +1023976, +1023977, +1023977, +1023977, +1023977, +1023977, +1023977, +1023977, +1023978, +1023978, +1023978, +1023978, +1023978, +1023978, +1023978, +1023978, +1023979, +1023979, +1023979, +1023979, +1023979, +1023979, +1023979, +1023979, +1023980, +1023980, +1023980, +1023980, +1023980, +1023980, +1023980, +1023980, +1023980, +1023981, +1023981, +1023981, +1023981, +1023981, +1023981, +1023981, +1023981, +1023981, +1023982, +1023982, +1023982, +1023982, +1023982, +1023982, +1023982, +1023982, +1023982, +1023983, +1023983, +1023983, +1023983, +1023983, +1023983, +1023983, +1023983, +1023983, +1023983, +1023984, +1023984, +1023984, +1023984, +1023984, +1023984, +1023984, +1023984, +1023984, +1023984, +1023984, +1023985, +1023985, +1023985, +1023985, +1023985, +1023985, +1023985, +1023985, +1023985, +1023985, +1023985, +1023985, +1023986, +1023986, +1023986, +1023986, +1023986, +1023986, +1023986, +1023986, +1023986, +1023986, +1023986, +1023986, +1023987, +1023987, +1023987, +1023987, +1023987, +1023987, +1023987, +1023987, +1023987, +1023987, +1023987, +1023987, +1023987, +1023988, +1023988, +1023988, +1023988, +1023988, +1023988, +1023988, +1023988, +1023988, +1023988, +1023988, +1023988, +1023988, +1023988, +1023988, +1023989, +1023989, +1023989, +1023989, +1023989, +1023989, +1023989, +1023989, +1023989, +1023989, +1023989, +1023989, +1023989, +1023989, +1023989, +1023990, +1023990, +1023990, +1023990, +1023990, +1023990, +1023990, +1023990, +1023990, +1023990, +1023990, +1023990, +1023990, +1023990, +1023990, +1023990, +1023990, +1023990, +1023991, +1023991, +1023991, +1023991, +1023991, +1023991, +1023991, +1023991, +1023991, +1023991, +1023991, +1023991, +1023991, +1023991, +1023991, +1023991, +1023991, +1023991, +1023991, +1023992, +1023992, +1023992, +1023992, +1023992, +1023992, +1023992, +1023992, +1023992, +1023992, +1023992, +1023992, +1023992, +1023992, +1023992, +1023992, +1023992, +1023992, +1023992, +1023992, +1023992, +1023992, +1023992, +1023993, +1023993, +1023993, +1023993, +1023993, +1023993, +1023993, +1023993, +1023993, +1023993, +1023993, +1023993, +1023993, +1023993, +1023993, +1023993, +1023993, +1023993, +1023993, +1023993, +1023993, +1023993, +1023993, +1023993, +1023993, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023994, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023995, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023996, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023997, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1023998, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, +1024000, diff --git a/rce/rcecalib/dataproc/fit/errf_ext_int.dat b/rce/rcecalib/dataproc/fit/errf_ext_int.dat new file mode 100644 index 00000000..adc1f0bf --- /dev/null +++ b/rce/rcecalib/dataproc/fit/errf_ext_int.dat @@ -0,0 +1,7001 @@ +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +9, +9, +9, +9, +9, +9, +9, +9, +9, +9, +9, +9, +9, +9, +9, +9, +9, +9, +10, +10, +10, +10, +10, +10, +10, +10, +10, +10, +10, +10, +10, +10, +10, +10, +11, +11, +11, +11, +11, +11, +11, +11, +11, +11, +11, +11, +11, +11, +12, +12, +12, +12, +12, +12, +12, +12, +12, +12, +12, +12, +12, +13, +13, +13, +13, +13, +13, +13, +13, +13, +13, +13, +13, +14, +14, +14, +14, +14, +14, +14, +14, +14, +14, +14, +14, +15, +15, +15, +15, +15, +15, +15, +15, +15, +15, +15, +16, +16, +16, +16, +16, +16, +16, +16, +16, +16, +17, +17, +17, +17, +17, +17, +17, +17, +17, +18, +18, +18, +18, +18, +18, +18, +18, +18, +19, +19, +19, +19, +19, +19, +19, +19, +19, +20, +20, +20, +20, +20, +20, +20, +20, +21, +21, +21, +21, +21, +21, +21, +21, +22, +22, +22, +22, +22, +22, +22, +23, +23, +23, +23, +23, +23, +23, +23, +24, +24, +24, +24, +24, +24, +25, +25, +25, +25, +25, +25, +25, +26, +26, +26, +26, +26, +26, +27, +27, +27, +27, +27, +27, +28, +28, +28, +28, +28, +28, +28, +29, +29, +29, +29, +29, +30, +30, +30, +30, +30, +30, +31, +31, +31, +31, +31, +32, +32, +32, +32, +32, +33, +33, +33, +33, +33, +33, +34, +34, +34, +34, +35, +35, +35, +35, +35, +36, +36, +36, +36, +36, +37, +37, +37, +37, +38, +38, +38, +38, +38, +39, +39, +39, +39, +40, +40, +40, +40, +41, +41, +41, +41, +41, +42, +42, +42, +42, +43, +43, +43, +43, +44, +44, +44, +44, +45, +45, +45, +46, +46, +46, +46, +47, +47, +47, +47, +48, +48, +48, +49, +49, +49, +49, +50, +50, +50, +51, +51, +51, +51, +52, +52, +52, +53, +53, +53, +54, +54, +54, +55, +55, +55, +56, +56, +56, +57, +57, +57, +57, +58, +58, +59, +59, +59, +60, +60, +60, +61, +61, +61, +62, +62, +62, +63, +63, +63, +64, +64, +65, +65, +65, +66, +66, +66, +67, +67, +68, +68, +68, +69, +69, +70, +70, +70, +71, +71, +72, +72, +72, +73, +73, +74, +74, +74, +75, +75, +76, +76, +77, +77, +77, +78, +78, +79, +79, +80, +80, +81, +81, +82, +82, +82, +83, +83, +84, +84, +85, +85, +86, +86, +87, +87, +88, +88, +89, +89, +90, +90, +91, +91, +92, +92, +93, +93, +94, +94, +95, +95, +96, +97, +97, +98, +98, +99, +99, +100, +100, +101, +102, +102, +103, +103, +104, +104, +105, +106, +106, +107, +107, +108, +109, +109, +110, +110, +111, +112, +112, +113, +114, +114, +115, +115, +116, +117, +117, +118, +119, +119, +120, +121, +121, +122, +123, +123, +124, +125, +125, +126, +127, +128, +128, +129, +130, +130, +131, +132, +133, +133, +134, +135, +135, +136, +137, +138, +138, +139, +140, +141, +142, +142, +143, +144, +145, +145, +146, +147, +148, +149, +150, +150, +151, +152, +153, +154, +154, +155, +156, +157, +158, +159, +160, +160, +161, +162, +163, +164, +165, +166, +167, +168, +169, +169, +170, +171, +172, +173, +174, +175, +176, +177, +178, +179, +180, +181, +182, +183, +184, +185, +186, +187, +188, +189, +190, +191, +192, +193, +194, +195, +196, +197, +198, +199, +200, +201, +202, +203, +205, +206, +207, +208, +209, +210, +211, +212, +214, +215, +216, +217, +218, +219, +220, +222, +223, +224, +225, +226, +228, +229, +230, +231, +232, +234, +235, +236, +237, +239, +240, +241, +243, +244, +245, +246, +248, +248, +250, +252, +253, +254, +256, +257, +258, +260, +261, +262, +264, +265, +267, +268, +270, +271, +272, +274, +275, +277, +278, +280, +281, +283, +284, +286, +287, +289, +290, +292, +293, +295, +296, +298, +299, +301, +302, +304, +306, +307, +309, +310, +312, +314, +315, +317, +319, +320, +322, +324, +325, +327, +329, +330, +332, +334, +335, +337, +339, +341, +342, +344, +346, +348, +350, +351, +353, +355, +357, +359, +361, +362, +364, +366, +368, +370, +372, +374, +376, +378, +380, +382, +384, +385, +387, +389, +391, +393, +396, +398, +400, +402, +404, +406, +408, +410, +412, +414, +416, +418, +420, +423, +425, +427, +429, +431, +434, +436, +438, +440, +442, +445, +447, +449, +451, +454, +456, +458, +461, +463, +465, +468, +470, +472, +475, +477, +480, +482, +485, +487, +488, +492, +494, +497, +499, +501, +504, +506, +510, +512, +515, +517, +520, +522, +525, +528, +530, +533, +536, +538, +541, +544, +547, +549, +552, +555, +558, +560, +563, +566, +569, +572, +574, +577, +580, +583, +586, +589, +592, +595, +598, +601, +604, +607, +610, +613, +616, +619, +622, +625, +628, +631, +634, +637, +641, +644, +647, +650, +653, +657, +660, +663, +666, +670, +673, +676, +680, +683, +686, +690, +693, +696, +700, +703, +707, +710, +714, +717, +721, +724, +728, +731, +735, +739, +742, +746, +749, +753, +757, +760, +764, +768, +772, +775, +779, +783, +787, +791, +794, +798, +802, +806, +810, +814, +818, +822, +826, +830, +834, +838, +842, +846, +850, +854, +858, +863, +867, +871, +875, +879, +884, +888, +892, +896, +901, +905, +909, +914, +918, +923, +927, +931, +936, +940, +945, +949, +954, +959, +963, +968, +972, +977, +982, +985, +990, +995, +1000, +1005, +1010, +1015, +1020, +1025, +1030, +1034, +1039, +1044, +1049, +1054, +1059, +1064, +1069, +1074, +1080, +1085, +1090, +1095, +1100, +1105, +1111, +1116, +1121, +1126, +1132, +1137, +1142, +1148, +1153, +1159, +1164, +1170, +1175, +1181, +1186, +1192, +1197, +1203, +1209, +1214, +1220, +1226, +1232, +1237, +1243, +1249, +1255, +1261, +1267, +1273, +1278, +1284, +1290, +1296, +1303, +1309, +1315, +1321, +1327, +1333, +1339, +1346, +1352, +1358, +1364, +1371, +1377, +1384, +1390, +1397, +1403, +1409, +1416, +1423, +1429, +1436, +1442, +1449, +1456, +1463, +1469, +1476, +1483, +1490, +1497, +1503, +1510, +1517, +1524, +1531, +1538, +1546, +1553, +1560, +1567, +1574, +1581, +1589, +1596, +1603, +1611, +1618, +1625, +1633, +1640, +1648, +1655, +1663, +1670, +1678, +1686, +1693, +1701, +1709, +1717, +1725, +1732, +1740, +1748, +1756, +1764, +1772, +1780, +1788, +1796, +1805, +1813, +1821, +1829, +1837, +1846, +1854, +1863, +1871, +1879, +1888, +1896, +1905, +1914, +1922, +1931, +1940, +1948, +1957, +1965, +1975, +1984, +1993, +2001, +2010, +2020, +2029, +2037, +2047, +2056, +2065, +2074, +2084, +2093, +2102, +2112, +2121, +2131, +2140, +2150, +2159, +2169, +2179, +2188, +2198, +2208, +2218, +2228, +2238, +2248, +2257, +2268, +2278, +2288, +2298, +2308, +2318, +2329, +2339, +2349, +2360, +2370, +2381, +2391, +2402, +2412, +2423, +2434, +2444, +2455, +2466, +2477, +2488, +2499, +2510, +2521, +2532, +2543, +2554, +2565, +2576, +2588, +2599, +2611, +2622, +2633, +2645, +2657, +2668, +2680, +2692, +2703, +2715, +2727, +2739, +2751, +2763, +2775, +2787, +2799, +2811, +2823, +2836, +2848, +2860, +2873, +2885, +2898, +2910, +2923, +2936, +2948, +2961, +2974, +2987, +3000, +3013, +3026, +3039, +3052, +3065, +3078, +3091, +3105, +3118, +3132, +3145, +3159, +3172, +3186, +3199, +3213, +3227, +3241, +3255, +3269, +3283, +3297, +3311, +3325, +3339, +3354, +3368, +3382, +3397, +3411, +3426, +3440, +3455, +3470, +3485, +3499, +3514, +3529, +3544, +3559, +3574, +3590, +3605, +3620, +3635, +3651, +3666, +3682, +3697, +3713, +3729, +3745, +3760, +3776, +3792, +3808, +3824, +3840, +3857, +3873, +3889, +3905, +3922, +3937, +3955, +3972, +3988, +4005, +4022, +4039, +4055, +4073, +4090, +4107, +4124, +4141, +4158, +4176, +4193, +4211, +4228, +4246, +4264, +4282, +4299, +4317, +4335, +4353, +4371, +4390, +4408, +4426, +4444, +4463, +4481, +4500, +4519, +4537, +4556, +4575, +4594, +4613, +4632, +4651, +4670, +4690, +4709, +4728, +4748, +4767, +4787, +4807, +4827, +4846, +4866, +4886, +4906, +4927, +4947, +4967, +4987, +5008, +5028, +5049, +5070, +5090, +5111, +5132, +5153, +5174, +5195, +5216, +5238, +5259, +5280, +5302, +5324, +5345, +5367, +5389, +5411, +5433, +5455, +5477, +5499, +5521, +5544, +5566, +5589, +5611, +5634, +5657, +5680, +5703, +5726, +5749, +5772, +5795, +5819, +5842, +5866, +5889, +5913, +5937, +5961, +5984, +6009, +6033, +6057, +6081, +6106, +6130, +6155, +6179, +6204, +6229, +6254, +6279, +6304, +6329, +6354, +6379, +6405, +6430, +6456, +6482, +6507, +6533, +6559, +6585, +6612, +6638, +6664, +6691, +6717, +6744, +6770, +6797, +6824, +6851, +6878, +6905, +6933, +6960, +6988, +7015, +7043, +7071, +7098, +7126, +7154, +7183, +7211, +7239, +7268, +7296, +7325, +7353, +7382, +7411, +7440, +7469, +7499, +7528, +7557, +7587, +7617, +7646, +7676, +7706, +7736, +7766, +7796, +7827, +7856, +7887, +7919, +7948, +7979, +8011, +8042, +8073, +8104, +8135, +8168, +8199, +8231, +8263, +8295, +8327, +8359, +8391, +8424, +8456, +8489, +8521, +8554, +8587, +8620, +8653, +8687, +8720, +8754, +8787, +8821, +8855, +8889, +8923, +8957, +8991, +9026, +9060, +9095, +9130, +9164, +9199, +9234, +9270, +9305, +9340, +9376, +9412, +9448, +9483, +9520, +9556, +9592, +9628, +9665, +9702, +9738, +9775, +9812, +9849, +9887, +9924, +9961, +9999, +10037, +10075, +10113, +10151, +10189, +10227, +10266, +10305, +10343, +10382, +10421, +10460, +10500, +10539, +10579, +10618, +10658, +10698, +10738, +10778, +10818, +10859, +10899, +10940, +10981, +11022, +11063, +11104, +11146, +11187, +11229, +11270, +11312, +11354, +11397, +11439, +11481, +11524, +11567, +11609, +11652, +11696, +11739, +11782, +11826, +11869, +11913, +11957, +12001, +12046, +12090, +12135, +12179, +12224, +12269, +12314, +12359, +12405, +12450, +12496, +12542, +12588, +12634, +12680, +12726, +12773, +12820, +12867, +12914, +12961, +13008, +13055, +13103, +13151, +13199, +13247, +13295, +13343, +13392, +13440, +13489, +13538, +13587, +13637, +13686, +13736, +13785, +13835, +13885, +13935, +13986, +14036, +14087, +14138, +14189, +14240, +14291, +14343, +14394, +14446, +14498, +14550, +14602, +14655, +14707, +14760, +14813, +14866, +14919, +14972, +15026, +15080, +15134, +15188, +15242, +15296, +15351, +15406, +15460, +15515, +15571, +15626, +15682, +15737, +15793, +15848, +15906, +15962, +16018, +16074, +16132, +16188, +16247, +16303, +16362, +16419, +16477, +16536, +16594, +16652, +16711, +16770, +16829, +16888, +16947, +17007, +17067, +17127, +17187, +17247, +17307, +17368, +17429, +17490, +17551, +17612, +17674, +17736, +17798, +17860, +17922, +17984, +18047, +18110, +18173, +18236, +18300, +18363, +18427, +18491, +18555, +18619, +18684, +18749, +18814, +18879, +18944, +19009, +19075, +19141, +19207, +19273, +19340, +19406, +19473, +19540, +19608, +19675, +19743, +19810, +19878, +19947, +20015, +20084, +20152, +20222, +20291, +20360, +20430, +20500, +20570, +20640, +20710, +20781, +20852, +20923, +20994, +21065, +21137, +21209, +21281, +21353, +21426, +21498, +21571, +21644, +21718, +21791, +21865, +21939, +22013, +22088, +22162, +22237, +22312, +22387, +22463, +22538, +22614, +22690, +22766, +22843, +22920, +22997, +23074, +23151, +23229, +23307, +23385, +23463, +23541, +23620, +23699, +23778, +23857, +23937, +24017, +24097, +24177, +24258, +24338, +24419, +24500, +24582, +24663, +24745, +24827, +24910, +24992, +25075, +25158, +25241, +25324, +25408, +25492, +25576, +25660, +25745, +25830, +25915, +26000, +26086, +26172, +26258, +26344, +26430, +26517, +26604, +26691, +26779, +26866, +26954, +27042, +27131, +27219, +27308, +27397, +27487, +27576, +27666, +27756, +27846, +27937, +28028, +28119, +28210, +28302, +28394, +28486, +28578, +28670, +28763, +28856, +28950, +29043, +29137, +29231, +29325, +29420, +29515, +29610, +29705, +29801, +29896, +29992, +30089, +30185, +30282, +30379, +30477, +30574, +30672, +30770, +30869, +30967, +31066, +31166, +31265, +31364, +31465, +31565, +31665, +31766, +31867, +31968, +32070, +32172, +32273, +32376, +32479, +32582, +32685, +32788, +32892, +32996, +33100, +33205, +33310, +33415, +33520, +33626, +33731, +33838, +33944, +34051, +34158, +34265, +34372, +34480, +34588, +34697, +34805, +34914, +35023, +35133, +35243, +35353, +35463, +35574, +35684, +35796, +35907, +36019, +36131, +36243, +36356, +36469, +36582, +36695, +36809, +36923, +37037, +37152, +37267, +37382, +37497, +37613, +37729, +37846, +37962, +38079, +38196, +38314, +38432, +38550, +38668, +38787, +38906, +39025, +39145, +39265, +39385, +39506, +39626, +39747, +39869, +39990, +40112, +40235, +40357, +40480, +40603, +40727, +40851, +40975, +41099, +41224, +41349, +41474, +41600, +41726, +41852, +41979, +42106, +42233, +42361, +42488, +42617, +42745, +42874, +43003, +43132, +43262, +43392, +43522, +43653, +43784, +43915, +44047, +44179, +44311, +44443, +44576, +44710, +44843, +44977, +45111, +45245, +45380, +45515, +45651, +45787, +45923, +46059, +46196, +46333, +46470, +46608, +46746, +46884, +47023, +47162, +47302, +47441, +47581, +47722, +47862, +48003, +48145, +48286, +48428, +48571, +48713, +48856, +49000, +49143, +49288, +49432, +49577, +49722, +49867, +50013, +50159, +50305, +50452, +50599, +50746, +50894, +51042, +51191, +51339, +51489, +51638, +51788, +51938, +52089, +52239, +52391, +52542, +52694, +52846, +52999, +53152, +53305, +53459, +53613, +53767, +53922, +54077, +54232, +54388, +54544, +54701, +54857, +55015, +55172, +55330, +55488, +55647, +55806, +55965, +56125, +56285, +56445, +56606, +56767, +56929, +57090, +57253, +57415, +57578, +57741, +57905, +58069, +58233, +58398, +58563, +58729, +58895, +59061, +59227, +59394, +59562, +59729, +59897, +60066, +60235, +60404, +60573, +60743, +60914, +61084, +61255, +61427, +61598, +61771, +61943, +62116, +62289, +62463, +62637, +62811, +62986, +63160, +63337, +63513, +63688, +63866, +64043, +64220, +64398, +64575, +64754, +64934, +65113, +65293, +65473, +65654, +65835, +66016, +66198, +66380, +66562, +66745, +66928, +67112, +67296, +67480, +67665, +67850, +68036, +68222, +68408, +68595, +68782, +68969, +69157, +69346, +69534, +69724, +69913, +70103, +70293, +70484, +70675, +70867, +71058, +71251, +71443, +71636, +71830, +72024, +72218, +72413, +72608, +72803, +72999, +73196, +73392, +73589, +73787, +73985, +74183, +74382, +74581, +74781, +74980, +75181, +75382, +75583, +75784, +75986, +76189, +76392, +76595, +76798, +77002, +77207, +77412, +77617, +77823, +78029, +78235, +78442, +78650, +78857, +79066, +79274, +79483, +79693, +79902, +80113, +80323, +80534, +80746, +80958, +81170, +81383, +81596, +81810, +82024, +82238, +82453, +82669, +82884, +83100, +83317, +83534, +83751, +83969, +84188, +84406, +84625, +84845, +85065, +85285, +85506, +85727, +85949, +86171, +86394, +86617, +86840, +87064, +87288, +87513, +87738, +87964, +88190, +88416, +88643, +88870, +89098, +89326, +89555, +89784, +90013, +90243, +90473, +90704, +90935, +91167, +91399, +91632, +91864, +92098, +92332, +92566, +92801, +93036, +93271, +93507, +93744, +93981, +94218, +94456, +94694, +94933, +95172, +95412, +95652, +95892, +96133, +96374, +96616, +96858, +97101, +97344, +97588, +97832, +98076, +98321, +98567, +98812, +99059, +99305, +99552, +99800, +100048, +100297, +100546, +100795, +101045, +101295, +101546, +101797, +102049, +102301, +102553, +102806, +103060, +103314, +103568, +103823, +104078, +104334, +104590, +104847, +105104, +105362, +105620, +105878, +106137, +106396, +106656, +106917, +107177, +107439, +107700, +107962, +108225, +108488, +108752, +109016, +109280, +109545, +109810, +110076, +110342, +110609, +110876, +111144, +111412, +111681, +111950, +112219, +112489, +112760, +113031, +113302, +113574, +113846, +114119, +114392, +114666, +114940, +115215, +115490, +115765, +116041, +116318, +116595, +116872, +117150, +117429, +117707, +117987, +118267, +118547, +118828, +119109, +119390, +119672, +119955, +120238, +120522, +120806, +121090, +121375, +121660, +121946, +122233, +122520, +122807, +123095, +123383, +123672, +123961, +124250, +124541, +124831, +125122, +125414, +125706, +125998, +126290, +126585, +126878, +127173, +127468, +127762, +128059, +128355, +128651, +128950, +129247, +129545, +129843, +130143, +130443, +130743, +131044, +131345, +131646, +131948, +132251, +132554, +132857, +133161, +133466, +133770, +134076, +134382, +134688, +134995, +135302, +135610, +135918, +136227, +136536, +136846, +137156, +137466, +137778, +138089, +138401, +138714, +139027, +139340, +139654, +139969, +140284, +140599, +140915, +141232, +141549, +141866, +142184, +142502, +142821, +143140, +143460, +143780, +144101, +144422, +144744, +145066, +145389, +145712, +146036, +146360, +146684, +147009, +147335, +147661, +147987, +148315, +148642, +148970, +149298, +149627, +149957, +150287, +150617, +150948, +151279, +151611, +151944, +152276, +152610, +152943, +153278, +153612, +153948, +154283, +154620, +154956, +155293, +155631, +155969, +156308, +156647, +156987, +157327, +157667, +158008, +158350, +158692, +159034, +159377, +159721, +160065, +160409, +160754, +161099, +161445, +161792, +162138, +162486, +162834, +163182, +163531, +163880, +164230, +164580, +164931, +165282, +165634, +165986, +166338, +166692, +167045, +167399, +167754, +168109, +168464, +168820, +169177, +169534, +169891, +170249, +170608, +170967, +171326, +171686, +172047, +172407, +172769, +173131, +173493, +173856, +174219, +174583, +174947, +175312, +175677, +176043, +176409, +176775, +177142, +177510, +177878, +178247, +178616, +178985, +179355, +179726, +180097, +180468, +180840, +181213, +181586, +181959, +182333, +182707, +183082, +183457, +183833, +184209, +184586, +184963, +185341, +185719, +186098, +186477, +186856, +187236, +187617, +187998, +188380, +188762, +189144, +189527, +189910, +190294, +190679, +191063, +191449, +191835, +192221, +192608, +192995, +193383, +193771, +194159, +194549, +194938, +195328, +195719, +196110, +196501, +196893, +197286, +197679, +198072, +198466, +198860, +199255, +199650, +200046, +200442, +200839, +201236, +201634, +202032, +202430, +202829, +203229, +203629, +204029, +204430, +204832, +205233, +205636, +206039, +206442, +206846, +207250, +207654, +208059, +208465, +208871, +209278, +209685, +210092, +210500, +210908, +211317, +211727, +212136, +212547, +212957, +213368, +213780, +214192, +214605, +215018, +215431, +215845, +216259, +216674, +217090, +217505, +217922, +218338, +218755, +219173, +219591, +220010, +220429, +220848, +221268, +221688, +222109, +222530, +222952, +223374, +223797, +224220, +224643, +225067, +225492, +225917, +226342, +226768, +227194, +227621, +228048, +228476, +228904, +229332, +229761, +230191, +230620, +231051, +231481, +231913, +232344, +232776, +233209, +233642, +234075, +234509, +234943, +235378, +235813, +236249, +236685, +237122, +237559, +237996, +238434, +238872, +239311, +239750, +240190, +240630, +241070, +241511, +241953, +242394, +242837, +243279, +243722, +244166, +244610, +245054, +245499, +245944, +246390, +246836, +247283, +247730, +248177, +248625, +249073, +249522, +249971, +250421, +250871, +251321, +251772, +252224, +252674, +253127, +253580, +254033, +254486, +254940, +255394, +255849, +256303, +256760, +257216, +257672, +258129, +258585, +259044, +259502, +259961, +260419, +260879, +261338, +261799, +262259, +262720, +263182, +263643, +264106, +264568, +265031, +265495, +265958, +266423, +266887, +267353, +267818, +268284, +268750, +269217, +269684, +270152, +270620, +271088, +271557, +272026, +272495, +272965, +273436, +273906, +274378, +274849, +275321, +275793, +276266, +276739, +277213, +277687, +278161, +278636, +279111, +279587, +280062, +280539, +281015, +281493, +281970, +282448, +282926, +283405, +283884, +284363, +284843, +285323, +285804, +286285, +286766, +287248, +287730, +288212, +288695, +289179, +289662, +290146, +290631, +291115, +291601, +292086, +292572, +293058, +293545, +294032, +294519, +295007, +295495, +295984, +296473, +296962, +297452, +297942, +298432, +298923, +299414, +299905, +300397, +300889, +301382, +301875, +302368, +302862, +303356, +303850, +304345, +304840, +305335, +305831, +306327, +306824, +307320, +307818, +308315, +308813, +309311, +309810, +310309, +310808, +311308, +311808, +312308, +312809, +313310, +313811, +314313, +314815, +315318, +315821, +316324, +316827, +317331, +317835, +318339, +318844, +319349, +319855, +320361, +320867, +321373, +321880, +322387, +322895, +323403, +323911, +324419, +324928, +325437, +325946, +326456, +326966, +327477, +327987, +328498, +329010, +329522, +330034, +330546, +331059, +331572, +332085, +332598, +333112, +333627, +334141, +334656, +335171, +335687, +336202, +336718, +337235, +337752, +338269, +338786, +339304, +339821, +340340, +340858, +341377, +341896, +342416, +342935, +343455, +343976, +344496, +345017, +345538, +346060, +346582, +347104, +347626, +348149, +348672, +349195, +349719, +350242, +350767, +351291, +351816, +352341, +352866, +353391, +353917, +354443, +354969, +355496, +356023, +356550, +357078, +357605, +358133, +358662, +359190, +359719, +360248, +360777, +361307, +361837, +362367, +362897, +363428, +363959, +364490, +365022, +365553, +366085, +366617, +367150, +367683, +368216, +368749, +369282, +369816, +370350, +370884, +371419, +371954, +372489, +373024, +373559, +374095, +374631, +375167, +375704, +376241, +376777, +377315, +377852, +378390, +378928, +379466, +380004, +380543, +381081, +381621, +382160, +382699, +383239, +383779, +384319, +384860, +385400, +385941, +386482, +387023, +387565, +388107, +388649, +389191, +389733, +390276, +390819, +391362, +391905, +392448, +392992, +393536, +394080, +394624, +395169, +395714, +396258, +396804, +397349, +397894, +398440, +398986, +399532, +400078, +400625, +401172, +401718, +402266, +402813, +403360, +403908, +404456, +405004, +405552, +406100, +406649, +407198, +407747, +408296, +408845, +409395, +409944, +410494, +411044, +411594, +412145, +412695, +413246, +413797, +414348, +414899, +415450, +416002, +416554, +417106, +417658, +418210, +418762, +419315, +419867, +420420, +420973, +421526, +422080, +422633, +423187, +423741, +424295, +424849, +425403, +425957, +426512, +427066, +427621, +428176, +428731, +429287, +429842, +430397, +430953, +431509, +432065, +432621, +433177, +433733, +434290, +434846, +435403, +435960, +436517, +437074, +437631, +438189, +438746, +439304, +439861, +440419, +440977, +441535, +442093, +442652, +443210, +443769, +444327, +444886, +445445, +446004, +446563, +447122, +447681, +448241, +448800, +449360, +449919, +450479, +451039, +451599, +452159, +452719, +453280, +453840, +454400, +454961, +455522, +456082, +456643, +457204, +457765, +458326, +458887, +459448, +460010, +460571, +461133, +461694, +462256, +462817, +463379, +463941, +464503, +465065, +465627, +466189, +466751, +467314, +467876, +468438, +469001, +469563, +470126, +470689, +471251, +471814, +472377, +472940, +473503, +474066, +474629, +475192, +475755, +476318, +476881, +477444, +478008, +478571, +479135, +479698, +480261, +480825, +481388, +481952, +482516, +483079, +483643, +484207, +484771, +485334, +485898, +486462, +487026, +487590, +488154, +488718, +489282, +489846, +490410, +490974, +491538, +492102, +492666, +493230, +493794, +494358, +494922, +495487, +496051, +496615, +497179, +497743, +498307, +498872, +499436, +500000, +500000, +500000, +500564, +501128, +501692, +502256, +502820, +503385, +503949, +504513, +505078, +505642, +506206, +506770, +507333, +507897, +508461, +509026, +509590, +510154, +510718, +511282, +511846, +512410, +512974, +513538, +514101, +514665, +515229, +515792, +516356, +516920, +517484, +518047, +518611, +519175, +519738, +520302, +520865, +521429, +521992, +522556, +523119, +523682, +524244, +524808, +525371, +525934, +526497, +527060, +527623, +528186, +528749, +529311, +529874, +530437, +530999, +531562, +532124, +532686, +533249, +533811, +534373, +534935, +535497, +536059, +536621, +537183, +537744, +538306, +538867, +539429, +539990, +540552, +541113, +541674, +542235, +542796, +543357, +543918, +544478, +545039, +545600, +546160, +546720, +547281, +547841, +548401, +548961, +549521, +550081, +550640, +551200, +551759, +552319, +552878, +553437, +553996, +554555, +555114, +555673, +556231, +556790, +557348, +557907, +558465, +559023, +559581, +560139, +560696, +561254, +561811, +562369, +562926, +563483, +564040, +564597, +565154, +565710, +566267, +566823, +567379, +567935, +568491, +569047, +569603, +570158, +570713, +571269, +571824, +572379, +572934, +573488, +574043, +574597, +575151, +575705, +576259, +576813, +577367, +577920, +578474, +579027, +579580, +580133, +580685, +581238, +581790, +582342, +582894, +583446, +583998, +584550, +585101, +585652, +586203, +586754, +587305, +587855, +588406, +588956, +589506, +590056, +590605, +591155, +591704, +592253, +592802, +593351, +593900, +594448, +594996, +595544, +596092, +596640, +597187, +597734, +598282, +598828, +599375, +599922, +600468, +601014, +601560, +602106, +602651, +603196, +603742, +604286, +604831, +605376, +605920, +606464, +607008, +607552, +608095, +608638, +609181, +609724, +610267, +610809, +611351, +611893, +612435, +612977, +613518, +614059, +614600, +615140, +615681, +616221, +616761, +617301, +617840, +618379, +618919, +619457, +619996, +620534, +621072, +621610, +622148, +622685, +623223, +623759, +624296, +624833, +625369, +625905, +626441, +626976, +627511, +628046, +628581, +629116, +629650, +630184, +630718, +631251, +631784, +632317, +632850, +633383, +633915, +634447, +634978, +635510, +636041, +636572, +637103, +637633, +638163, +638693, +639223, +639752, +640281, +640810, +641338, +641867, +642395, +642922, +643450, +643977, +644504, +645031, +645557, +646083, +646609, +647134, +647659, +648184, +648709, +649233, +649758, +650281, +650805, +651328, +651851, +652374, +652896, +653418, +653940, +654462, +654983, +655504, +656024, +656545, +657065, +657584, +658104, +658623, +659142, +659660, +660179, +660696, +661214, +661731, +662248, +662765, +663282, +663798, +664313, +664829, +665344, +665859, +666373, +666888, +667402, +667915, +668428, +668941, +669454, +669966, +670478, +670990, +671502, +672013, +672523, +673034, +673544, +674054, +674563, +675072, +675581, +676089, +676597, +677105, +677613, +678120, +678627, +679133, +679639, +680145, +680651, +681156, +681661, +682165, +682669, +683173, +683676, +684179, +684682, +685185, +685687, +686189, +686690, +687191, +687692, +688192, +688692, +689192, +689691, +690190, +690689, +691187, +691685, +692182, +692680, +693176, +693673, +694169, +694665, +695160, +695655, +696150, +696644, +697138, +697632, +698125, +698618, +699111, +699603, +700095, +700586, +701077, +701568, +702058, +702548, +703038, +703527, +704016, +704505, +704993, +705481, +705968, +706455, +706942, +707428, +707914, +708399, +708885, +709369, +709854, +710338, +710821, +711305, +711788, +712270, +712752, +713234, +713715, +714196, +714677, +715157, +715637, +716116, +716595, +717074, +717552, +718030, +718507, +718985, +719461, +719938, +720413, +720889, +721364, +721839, +722313, +722787, +723261, +723734, +724207, +724679, +725151, +725622, +726094, +726564, +727035, +727505, +727974, +728443, +728912, +729380, +729848, +730316, +730783, +731250, +731716, +732182, +732647, +733113, +733577, +734042, +734505, +734969, +735432, +735894, +736357, +736818, +737280, +737741, +738201, +738662, +739121, +739581, +740039, +740498, +740956, +741414, +741871, +742328, +742784, +743240, +743696, +744151, +744605, +745060, +745514, +745967, +746420, +746873, +747325, +747776, +748228, +748679, +749129, +749579, +750029, +750478, +750927, +751375, +751823, +752270, +752717, +753164, +753610, +754056, +754501, +754946, +755390, +755834, +756278, +756721, +757163, +757606, +758047, +758489, +758930, +759370, +759810, +760250, +760689, +761128, +761566, +762004, +762441, +762878, +763315, +763751, +764187, +764622, +765057, +765491, +765925, +766358, +766791, +767224, +767656, +768087, +768519, +768949, +769380, +769809, +770239, +770668, +771096, +771524, +771952, +772379, +772806, +773232, +773658, +774083, +774508, +774933, +775357, +775780, +776203, +776626, +777048, +777470, +777891, +778312, +778732, +779152, +779571, +779990, +780409, +780827, +781245, +781662, +782078, +782495, +782910, +783326, +783741, +784155, +784569, +784982, +785395, +785808, +786220, +786632, +787043, +787453, +787864, +788273, +788683, +789092, +789500, +789908, +790315, +790722, +791129, +791535, +791941, +792346, +792750, +793154, +793558, +793961, +794364, +794767, +795168, +795570, +795971, +796371, +796771, +797171, +797570, +797968, +798366, +798764, +799161, +799558, +799954, +800350, +800745, +801140, +801534, +801928, +802321, +802714, +803107, +803499, +803890, +804281, +804672, +805062, +805451, +805841, +806229, +806617, +807005, +807392, +807779, +808165, +808551, +808937, +809321, +809706, +810090, +810473, +810856, +811238, +811620, +812002, +812383, +812764, +813144, +813523, +813902, +814281, +814659, +815037, +815414, +815791, +816167, +816543, +816918, +817293, +817667, +818041, +818414, +818787, +819160, +819532, +819903, +820274, +820645, +821015, +821384, +821753, +822122, +822490, +822858, +823225, +823591, +823957, +824323, +824688, +825053, +825417, +825781, +826144, +826507, +826869, +827231, +827593, +827953, +828314, +828674, +829033, +829392, +829751, +830109, +830466, +830823, +831180, +831536, +831891, +832246, +832601, +832955, +833308, +833662, +834014, +834366, +834718, +835069, +835420, +835770, +836120, +836469, +836818, +837166, +837514, +837862, +838208, +838555, +838901, +839246, +839591, +839935, +840279, +840623, +840966, +841308, +841650, +841992, +842333, +842673, +843013, +843353, +843692, +844031, +844369, +844707, +845044, +845380, +845717, +846052, +846388, +846722, +847057, +847390, +847724, +848056, +848389, +848721, +849052, +849383, +849713, +850043, +850373, +850702, +851030, +851358, +851685, +852013, +852339, +852665, +852991, +853316, +853640, +853964, +854288, +854611, +854934, +855256, +855578, +855899, +856220, +856540, +856860, +857179, +857498, +857816, +858134, +858451, +858768, +859085, +859401, +859716, +860031, +860346, +860660, +860973, +861286, +861599, +861911, +862222, +862534, +862844, +863154, +863464, +863773, +864082, +864390, +864698, +865005, +865312, +865618, +865924, +866230, +866534, +866839, +867143, +867446, +867749, +868052, +868354, +868655, +868956, +869257, +869557, +869857, +870156, +870455, +870753, +871050, +871348, +871645, +871941, +872237, +872532, +872827, +873121, +873415, +873709, +874002, +874294, +874586, +874878, +875169, +875459, +875750, +876039, +876328, +876617, +876905, +877193, +877480, +877767, +878054, +878340, +878625, +878910, +879194, +879478, +879762, +880045, +880328, +880610, +880891, +881172, +881453, +881733, +882013, +882293, +882571, +882850, +883128, +883405, +883682, +883959, +884235, +884510, +884785, +885060, +885334, +885608, +885881, +886154, +886426, +886698, +886969, +887240, +887511, +887781, +888050, +888319, +888588, +888856, +889124, +889391, +889658, +889924, +890190, +890455, +890720, +890984, +891248, +891512, +891775, +892038, +892300, +892561, +892823, +893083, +893344, +893604, +893863, +894122, +894380, +894638, +894896, +895153, +895410, +895666, +895922, +896177, +896432, +896686, +896940, +897194, +897447, +897699, +897951, +898203, +898454, +898705, +898955, +899205, +899454, +899703, +899952, +900200, +900448, +900695, +900941, +901188, +901433, +901679, +901924, +902168, +902412, +902656, +902899, +903142, +903384, +903626, +903867, +904108, +904348, +904588, +904828, +905067, +905306, +905544, +905782, +906019, +906256, +906493, +906729, +906964, +907199, +907434, +907668, +907902, +908136, +908368, +908601, +908833, +909065, +909296, +909527, +909757, +909987, +910216, +910445, +910674, +910902, +911130, +911357, +911584, +911810, +912036, +912262, +912487, +912712, +912936, +913160, +913383, +913606, +913829, +914051, +914273, +914494, +914715, +914935, +915155, +915375, +915594, +915812, +916031, +916249, +916466, +916683, +916900, +917116, +917331, +917547, +917762, +917976, +918190, +918404, +918617, +918830, +919042, +919254, +919466, +919677, +919887, +920098, +920307, +920517, +920726, +920934, +921143, +921350, +921558, +921765, +921971, +922177, +922383, +922588, +922793, +922998, +923202, +923405, +923608, +923811, +924014, +924216, +924417, +924618, +924819, +925020, +925219, +925419, +925618, +925817, +926015, +926213, +926411, +926608, +926804, +927001, +927197, +927392, +927587, +927782, +927976, +928170, +928364, +928557, +928749, +928942, +929133, +929325, +929516, +929707, +929897, +930087, +930276, +930466, +930654, +930843, +931031, +931218, +931405, +931592, +931778, +931964, +932150, +932335, +932520, +932704, +932888, +933072, +933255, +933438, +933620, +933802, +933984, +934165, +934346, +934527, +934707, +934887, +935066, +935245, +935424, +935602, +935780, +935957, +936134, +936311, +936487, +936663, +936839, +937014, +937189, +937363, +937537, +937711, +937884, +938057, +938229, +938402, +938573, +938745, +938916, +939086, +939257, +939427, +939596, +939765, +939934, +940103, +940271, +940438, +940606, +940773, +940939, +941105, +941271, +941437, +941602, +941767, +941931, +942095, +942259, +942422, +942585, +942747, +942910, +943071, +943233, +943394, +943555, +943715, +943875, +944035, +944194, +944353, +944512, +944670, +944828, +944985, +945143, +945299, +945456, +945612, +945768, +945923, +946078, +946233, +946387, +946541, +946695, +946848, +947001, +947154, +947306, +947458, +947609, +947761, +947911, +948062, +948212, +948362, +948511, +948661, +948809, +948958, +949106, +949254, +949401, +949548, +949695, +949841, +949987, +950133, +950278, +950423, +950568, +950712, +950857, +951000, +951144, +951287, +951429, +951572, +951714, +951855, +951997, +952138, +952278, +952419, +952559, +952698, +952838, +952977, +953116, +953254, +953392, +953530, +953667, +953804, +953941, +954077, +954213, +954349, +954485, +954620, +954755, +954889, +955023, +955157, +955290, +955424, +955557, +955689, +955821, +955953, +956085, +956216, +956347, +956478, +956608, +956738, +956868, +956997, +957126, +957255, +957383, +957512, +957639, +957767, +957894, +958021, +958148, +958274, +958400, +958526, +958651, +958776, +958901, +959025, +959149, +959273, +959397, +959520, +959643, +959765, +959888, +960010, +960131, +960253, +960374, +960494, +960615, +960735, +960855, +960975, +961094, +961213, +961332, +961450, +961568, +961686, +961804, +961921, +962038, +962154, +962271, +962387, +962503, +962618, +962733, +962848, +962963, +963077, +963191, +963305, +963418, +963531, +963644, +963757, +963869, +963981, +964093, +964204, +964316, +964426, +964537, +964647, +964757, +964867, +964977, +965086, +965195, +965303, +965412, +965520, +965628, +965735, +965842, +965949, +966056, +966162, +966269, +966374, +966480, +966585, +966690, +966795, +966900, +967004, +967108, +967212, +967315, +967418, +967521, +967624, +967726, +967828, +967930, +968032, +968133, +968234, +968335, +968435, +968535, +968635, +968735, +968834, +968934, +969033, +969131, +969230, +969328, +969426, +969523, +969621, +969718, +969815, +969911, +970008, +970104, +970199, +970295, +970390, +970485, +970580, +970675, +970769, +970863, +970957, +971050, +971144, +971237, +971330, +971422, +971514, +971606, +971698, +971790, +971881, +971972, +972063, +972154, +972244, +972334, +972424, +972513, +972603, +972692, +972781, +972869, +972958, +973046, +973134, +973221, +973309, +973396, +973483, +973570, +973656, +973742, +973828, +973914, +974000, +974085, +974170, +974255, +974340, +974424, +974508, +974592, +974676, +974759, +974842, +974925, +975008, +975090, +975173, +975255, +975337, +975418, +975500, +975581, +975662, +975742, +975823, +975903, +975983, +976063, +976143, +976222, +976301, +976380, +976459, +976537, +976615, +976693, +976771, +976849, +976926, +977003, +977080, +977157, +977234, +977310, +977386, +977462, +977537, +977613, +977688, +977763, +977838, +977912, +977987, +978061, +978135, +978209, +978282, +978356, +978429, +978502, +978574, +978647, +978719, +978791, +978863, +978935, +979006, +979077, +979148, +979219, +979290, +979360, +979430, +979500, +979570, +979640, +979709, +979778, +979848, +979916, +979985, +980053, +980122, +980190, +980257, +980325, +980392, +980460, +980527, +980594, +980660, +980727, +980793, +980859, +980925, +980991, +981056, +981121, +981186, +981251, +981316, +981381, +981445, +981509, +981573, +981637, +981700, +981764, +981827, +981890, +981953, +982016, +982078, +982140, +982202, +982264, +982326, +982388, +982449, +982510, +982571, +982632, +982693, +982753, +982813, +982873, +982933, +982993, +983053, +983112, +983171, +983230, +983289, +983348, +983406, +983464, +983523, +983581, +983638, +983696, +983753, +983811, +983868, +983925, +983981, +984038, +984094, +984151, +984207, +984263, +984318, +984374, +984429, +984485, +984540, +984594, +984649, +984704, +984758, +984812, +984866, +984920, +984974, +985028, +985081, +985134, +985187, +985240, +985293, +985345, +985398, +985450, +985502, +985554, +985606, +985657, +985709, +985760, +985811, +985862, +985913, +985964, +986014, +986065, +986115, +986165, +986215, +986264, +986314, +986363, +986413, +986462, +986511, +986560, +986608, +986657, +986705, +986753, +986801, +986849, +986897, +986945, +986992, +987039, +987086, +987133, +987180, +987227, +987274, +987320, +987366, +987412, +987458, +987504, +987550, +987595, +987641, +987686, +987731, +987776, +987821, +987865, +987910, +987954, +987999, +988043, +988087, +988131, +988174, +988218, +988261, +988304, +988348, +988391, +988433, +988476, +988519, +988561, +988603, +988646, +988688, +988730, +988771, +988813, +988854, +988896, +988937, +988978, +989019, +989060, +989101, +989141, +989182, +989222, +989262, +989302, +989342, +989382, +989421, +989461, +989500, +989540, +989579, +989618, +989657, +989695, +989734, +989773, +989811, +989849, +989887, +989925, +989963, +990001, +990039, +990076, +990113, +990151, +990188, +990225, +990262, +990298, +990335, +990372, +990408, +990444, +990480, +990517, +990552, +990588, +990624, +990660, +990695, +990730, +990766, +990801, +990836, +990870, +990905, +990940, +990974, +991009, +991043, +991077, +991111, +991145, +991179, +991213, +991246, +991280, +991313, +991347, +991380, +991413, +991446, +991479, +991511, +991544, +991576, +991609, +991641, +991673, +991705, +991737, +991769, +991801, +991832, +991864, +991895, +991927, +991958, +991989, +992020, +992051, +992081, +992112, +992143, +992173, +992204, +992234, +992264, +992294, +992324, +992354, +992383, +992413, +992443, +992472, +992501, +992531, +992560, +992589, +992618, +992647, +992675, +992704, +992732, +992761, +992789, +992817, +992846, +992874, +992902, +992929, +992957, +992985, +993012, +993040, +993067, +993095, +993122, +993149, +993176, +993203, +993230, +993256, +993283, +993309, +993336, +993362, +993388, +993415, +993441, +993467, +993493, +993518, +993544, +993570, +993595, +993621, +993646, +993671, +993696, +993721, +993746, +993771, +993796, +993821, +993845, +993870, +993894, +993919, +993943, +993967, +993991, +994016, +994039, +994063, +994087, +994111, +994134, +994158, +994181, +994205, +994228, +994251, +994274, +994297, +994320, +994343, +994366, +994389, +994411, +994434, +994456, +994479, +994501, +994523, +994545, +994567, +994589, +994611, +994633, +994655, +994676, +994698, +994720, +994741, +994762, +994784, +994805, +994826, +994847, +994868, +994889, +994910, +994930, +994951, +994972, +994992, +995013, +995033, +995053, +995073, +995094, +995114, +995134, +995154, +995173, +995193, +995213, +995233, +995252, +995272, +995291, +995310, +995330, +995349, +995368, +995387, +995406, +995425, +995444, +995463, +995481, +995500, +995519, +995537, +995556, +995574, +995592, +995610, +995629, +995647, +995665, +995683, +995701, +995718, +995736, +995754, +995772, +995789, +995807, +995824, +995842, +995859, +995876, +995893, +995910, +995927, +995944, +995961, +995978, +995995, +996012, +996028, +996045, +996062, +996078, +996095, +996111, +996127, +996143, +996160, +996176, +996192, +996208, +996224, +996240, +996255, +996271, +996287, +996303, +996318, +996334, +996349, +996365, +996380, +996395, +996410, +996426, +996441, +996456, +996471, +996486, +996501, +996515, +996530, +996545, +996560, +996574, +996589, +996603, +996618, +996632, +996646, +996661, +996675, +996689, +996703, +996717, +996731, +996745, +996759, +996773, +996787, +996801, +996814, +996828, +996841, +996855, +996868, +996882, +996895, +996909, +996922, +996935, +996948, +996961, +996974, +996987, +997000, +997013, +997026, +997039, +997052, +997064, +997077, +997090, +997102, +997115, +997127, +997140, +997152, +997164, +997177, +997189, +997201, +997213, +997225, +997237, +997249, +997261, +997273, +997285, +997297, +997308, +997320, +997332, +997343, +997355, +997367, +997378, +997389, +997401, +997412, +997424, +997435, +997446, +997457, +997468, +997479, +997490, +997501, +997512, +997523, +997534, +997545, +997556, +997566, +997577, +997588, +997598, +997609, +997619, +997630, +997640, +997651, +997661, +997671, +997682, +997692, +997702, +997712, +997722, +997732, +997743, +997752, +997762, +997772, +997782, +997792, +997802, +997812, +997821, +997831, +997841, +997850, +997860, +997869, +997879, +997888, +997898, +997907, +997916, +997926, +997935, +997944, +997953, +997962, +997971, +997980, +997990, +997999, +998007, +998016, +998025, +998034, +998043, +998052, +998060, +998069, +998078, +998086, +998095, +998104, +998112, +998121, +998129, +998137, +998146, +998154, +998163, +998171, +998179, +998187, +998195, +998204, +998212, +998220, +998228, +998236, +998244, +998252, +998260, +998268, +998275, +998283, +998291, +998299, +998307, +998314, +998322, +998330, +998337, +998345, +998352, +998360, +998367, +998375, +998382, +998389, +998397, +998404, +998411, +998419, +998426, +998433, +998440, +998447, +998454, +998462, +998469, +998476, +998483, +998490, +998497, +998503, +998510, +998517, +998524, +998531, +998537, +998544, +998551, +998558, +998564, +998571, +998577, +998584, +998591, +998597, +998603, +998610, +998616, +998623, +998629, +998636, +998642, +998648, +998654, +998661, +998667, +998673, +998679, +998685, +998691, +998697, +998704, +998710, +998716, +998722, +998727, +998733, +998739, +998745, +998751, +998757, +998763, +998768, +998774, +998780, +998786, +998791, +998797, +998803, +998808, +998814, +998819, +998825, +998830, +998836, +998841, +998847, +998852, +998858, +998863, +998868, +998874, +998879, +998884, +998889, +998895, +998900, +998905, +998910, +998915, +998920, +998926, +998931, +998936, +998941, +998946, +998951, +998956, +998961, +998966, +998970, +998975, +998980, +998985, +998990, +998995, +998999, +999004, +999009, +999014, +999018, +999023, +999028, +999032, +999037, +999041, +999046, +999051, +999055, +999060, +999064, +999069, +999073, +999077, +999082, +999086, +999091, +999095, +999099, +999104, +999108, +999112, +999116, +999121, +999125, +999129, +999133, +999137, +999142, +999146, +999150, +999154, +999158, +999162, +999166, +999170, +999174, +999178, +999182, +999186, +999190, +999194, +999198, +999202, +999206, +999209, +999213, +999217, +999221, +999225, +999228, +999232, +999236, +999240, +999243, +999247, +999251, +999254, +999258, +999261, +999265, +999269, +999272, +999276, +999279, +999283, +999286, +999290, +999293, +999297, +999300, +999304, +999307, +999310, +999314, +999317, +999320, +999324, +999327, +999330, +999334, +999337, +999340, +999343, +999347, +999350, +999353, +999356, +999359, +999363, +999366, +999369, +999372, +999375, +999378, +999381, +999384, +999387, +999390, +999393, +999396, +999399, +999402, +999405, +999408, +999411, +999414, +999417, +999420, +999423, +999426, +999428, +999431, +999434, +999437, +999440, +999442, +999445, +999448, +999451, +999453, +999456, +999459, +999462, +999464, +999467, +999470, +999472, +999475, +999478, +999480, +999483, +999485, +999488, +999490, +999493, +999496, +999498, +999501, +999503, +999506, +999508, +999511, +999513, +999515, +999518, +999520, +999523, +999525, +999528, +999530, +999532, +999535, +999537, +999539, +999542, +999544, +999546, +999549, +999551, +999553, +999555, +999558, +999560, +999562, +999564, +999566, +999569, +999571, +999573, +999575, +999577, +999580, +999582, +999584, +999586, +999588, +999590, +999592, +999594, +999596, +999598, +999600, +999602, +999604, +999607, +999609, +999611, +999613, +999615, +999616, +999618, +999620, +999622, +999624, +999626, +999628, +999630, +999632, +999634, +999636, +999638, +999639, +999641, +999643, +999645, +999647, +999649, +999650, +999652, +999654, +999656, +999658, +999659, +999661, +999663, +999665, +999666, +999668, +999670, +999671, +999673, +999675, +999676, +999678, +999680, +999681, +999683, +999685, +999686, +999688, +999690, +999691, +999693, +999694, +999696, +999698, +999699, +999701, +999702, +999704, +999705, +999707, +999708, +999710, +999711, +999713, +999714, +999716, +999717, +999719, +999720, +999722, +999723, +999725, +999726, +999728, +999729, +999730, +999732, +999733, +999735, +999736, +999738, +999739, +999740, +999742, +999743, +999744, +999746, +999747, +999748, +999750, +999751, +999752, +999754, +999755, +999756, +999757, +999759, +999760, +999761, +999763, +999764, +999765, +999766, +999768, +999769, +999770, +999771, +999772, +999774, +999775, +999776, +999777, +999778, +999780, +999781, +999782, +999783, +999784, +999785, +999786, +999788, +999789, +999790, +999791, +999792, +999793, +999794, +999795, +999797, +999798, +999799, +999800, +999801, +999802, +999803, +999804, +999805, +999806, +999807, +999808, +999809, +999810, +999811, +999812, +999813, +999814, +999815, +999816, +999817, +999818, +999819, +999820, +999821, +999822, +999823, +999824, +999825, +999826, +999827, +999828, +999829, +999830, +999831, +999831, +999832, +999833, +999834, +999835, +999836, +999837, +999838, +999839, +999840, +999840, +999841, +999842, +999843, +999844, +999845, +999846, +999846, +999847, +999848, +999849, +999850, +999850, +999851, +999852, +999853, +999854, +999855, +999855, +999856, +999857, +999858, +999858, +999859, +999860, +999861, +999862, +999862, +999863, +999864, +999865, +999865, +999866, +999867, +999867, +999868, +999869, +999870, +999870, +999871, +999872, +999872, +999873, +999874, +999875, +999875, +999876, +999877, +999877, +999878, +999879, +999879, +999880, +999881, +999881, +999882, +999883, +999883, +999884, +999885, +999885, +999886, +999886, +999887, +999888, +999888, +999889, +999890, +999890, +999891, +999891, +999892, +999893, +999893, +999894, +999894, +999895, +999896, +999896, +999897, +999897, +999898, +999898, +999899, +999900, +999900, +999901, +999901, +999902, +999902, +999903, +999903, +999904, +999905, +999905, +999906, +999906, +999907, +999907, +999908, +999908, +999909, +999909, +999910, +999910, +999911, +999911, +999912, +999912, +999913, +999913, +999914, +999914, +999915, +999915, +999916, +999916, +999917, +999917, +999918, +999918, +999918, +999919, +999919, +999920, +999920, +999921, +999921, +999922, +999922, +999923, +999923, +999923, +999924, +999924, +999925, +999925, +999926, +999926, +999926, +999927, +999927, +999928, +999928, +999928, +999929, +999929, +999930, +999930, +999930, +999931, +999931, +999932, +999932, +999932, +999933, +999933, +999934, +999934, +999934, +999935, +999935, +999935, +999936, +999936, +999937, +999937, +999937, +999938, +999938, +999938, +999939, +999939, +999939, +999940, +999940, +999940, +999941, +999941, +999941, +999942, +999942, +999943, +999943, +999943, +999943, +999944, +999944, +999944, +999945, +999945, +999945, +999946, +999946, +999946, +999947, +999947, +999947, +999948, +999948, +999948, +999949, +999949, +999949, +999949, +999950, +999950, +999950, +999951, +999951, +999951, +999951, +999952, +999952, +999952, +999953, +999953, +999953, +999953, +999954, +999954, +999954, +999954, +999955, +999955, +999955, +999956, +999956, +999956, +999956, +999957, +999957, +999957, +999957, +999958, +999958, +999958, +999958, +999959, +999959, +999959, +999959, +999959, +999960, +999960, +999960, +999960, +999961, +999961, +999961, +999961, +999962, +999962, +999962, +999962, +999962, +999963, +999963, +999963, +999963, +999964, +999964, +999964, +999964, +999964, +999965, +999965, +999965, +999965, +999965, +999966, +999966, +999966, +999966, +999967, +999967, +999967, +999967, +999967, +999967, +999968, +999968, +999968, +999968, +999968, +999969, +999969, +999969, +999969, +999969, +999970, +999970, +999970, +999970, +999970, +999970, +999971, +999971, +999971, +999971, +999971, +999972, +999972, +999972, +999972, +999972, +999972, +999972, +999973, +999973, +999973, +999973, +999973, +999973, +999974, +999974, +999974, +999974, +999974, +999974, +999975, +999975, +999975, +999975, +999975, +999975, +999975, +999976, +999976, +999976, +999976, +999976, +999976, +999977, +999977, +999977, +999977, +999977, +999977, +999977, +999977, +999978, +999978, +999978, +999978, +999978, +999978, +999978, +999979, +999979, +999979, +999979, +999979, +999979, +999979, +999979, +999980, +999980, +999980, +999980, +999980, +999980, +999980, +999980, +999981, +999981, +999981, +999981, +999981, +999981, +999981, +999981, +999981, +999982, +999982, +999982, +999982, +999982, +999982, +999982, +999982, +999982, +999983, +999983, +999983, +999983, +999983, +999983, +999983, +999983, +999983, +999984, +999984, +999984, +999984, +999984, +999984, +999984, +999984, +999984, +999984, +999985, +999985, +999985, +999985, +999985, +999985, +999985, +999985, +999985, +999985, +999985, +999986, +999986, +999986, +999986, +999986, +999986, +999986, +999986, +999986, +999986, +999986, +999986, +999987, +999987, +999987, +999987, +999987, +999987, +999987, +999987, +999987, +999987, +999987, +999987, +999988, +999988, +999988, +999988, +999988, +999988, +999988, +999988, +999988, +999988, +999988, +999988, +999988, +999989, +999989, +999989, +999989, +999989, +999989, +999989, +999989, +999989, +999989, +999989, +999989, +999989, +999989, +999990, +999990, +999990, +999990, +999990, +999990, +999990, +999990, +999990, +999990, +999990, +999990, +999990, +999990, +999990, +999990, +999991, +999991, +999991, +999991, +999991, +999991, +999991, +999991, +999991, +999991, +999991, +999991, +999991, +999991, +999991, +999991, +999991, +999991, +999992, +999992, +999992, +999992, +999992, +999992, +999992, +999992, +999992, +999992, +999992, +999992, +999992, +999992, +999992, +999992, +999992, +999992, +999992, +999993, +999993, +999993, +999993, +999993, +999993, +999993, +999993, +999993, +999993, +999993, +999993, +999993, +999993, +999993, +999993, +999993, +999993, +999993, +999993, +999993, +999993, +999994, +999994, +999994, +999994, +999994, +999994, +999994, +999994, +999994, +999994, +999994, +999994, +999994, +999994, +999994, +999994, +999994, +999994, +999994, +999994, +999994, +999994, +999994, +999994, +999994, +999994, +999995, +999995, +999995, +999995, +999995, +999995, +999995, +999995, +999995, +999995, +999995, +999995, +999995, +999995, +999995, +999995, +999995, +999995, +999995, +999995, +999995, +999995, +999995, +999995, +999995, +999995, +999995, +999995, +999995, +999995, +999995, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999996, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999997, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999998, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +999999, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000, +1000000 diff --git a/rce/rcecalib/dataproc/fit/logx.dat b/rce/rcecalib/dataproc/fit/logx.dat new file mode 100644 index 00000000..7541fb46 --- /dev/null +++ b/rce/rcecalib/dataproc/fit/logx.dat @@ -0,0 +1,7001 @@ +-20.366591f, +-6.551079f, +-5.857933f, +-5.452468f, +-5.164786f, +-4.941642f, +-4.759321f, +-4.605170f, +-4.471639f, +-4.353856f, +-4.248495f, +-4.153185f, +-4.066174f, +-3.986131f, +-3.912023f, +-3.843030f, +-3.778492f, +-3.717867f, +-3.660709f, +-3.606641f, +-3.555348f, +-3.506558f, +-3.460038f, +-3.415586f, +-3.373026f, +-3.332204f, +-3.292984f, +-3.255243f, +-3.218876f, +-3.183784f, +-3.149883f, +-3.117093f, +-3.085344f, +-3.054573f, +-3.024720f, +-2.995732f, +-2.967561f, +-2.940162f, +-2.913494f, +-2.887519f, +-2.862201f, +-2.837508f, +-2.813411f, +-2.789880f, +-2.766891f, +-2.744418f, +-2.722439f, +-2.700933f, +-2.679879f, +-2.659260f, +-2.639057f, +-2.619255f, +-2.599837f, +-2.580788f, +-2.562096f, +-2.543747f, +-2.525729f, +-2.508029f, +-2.490637f, +-2.473543f, +-2.456736f, +-2.440206f, +-2.423946f, +-2.407946f, +-2.392197f, +-2.376693f, +-2.361426f, +-2.346388f, +-2.331573f, +-2.316974f, +-2.302585f, +-2.288400f, +-2.274414f, +-2.260621f, +-2.247015f, +-2.233592f, +-2.220347f, +-2.207275f, +-2.194371f, +-2.181632f, +-2.169054f, +-2.156631f, +-2.144361f, +-2.132240f, +-2.120264f, +-2.108429f, +-2.096733f, +-2.085172f, +-2.073744f, +-2.062444f, +-2.051271f, +-2.040221f, +-2.029292f, +-2.018481f, +-2.007786f, +-1.997203f, +-1.986732f, +-1.976369f, +-1.966113f, +-1.955960f, +-1.945910f, +-1.935960f, +-1.926108f, +-1.916351f, +-1.906689f, +-1.897120f, +-1.887641f, +-1.878251f, +-1.868949f, +-1.859732f, +-1.850600f, +-1.841550f, +-1.832581f, +-1.823693f, +-1.814882f, +-1.806148f, +-1.797490f, +-1.788906f, +-1.780396f, +-1.771957f, +-1.763589f, +-1.755290f, +-1.747059f, +-1.738896f, +-1.730799f, +-1.722767f, +-1.714798f, +-1.706893f, +-1.699050f, +-1.691268f, +-1.683546f, +-1.675883f, +-1.668278f, +-1.660731f, +-1.653241f, +-1.645806f, +-1.638425f, +-1.631099f, +-1.623827f, +-1.616606f, +-1.609438f, +-1.602320f, +-1.595253f, +-1.588236f, +-1.581267f, +-1.574347f, +-1.567474f, +-1.560648f, +-1.553868f, +-1.547134f, +-1.540445f, +-1.533800f, +-1.527200f, +-1.520642f, +-1.514128f, +-1.507655f, +-1.501224f, +-1.494835f, +-1.488485f, +-1.482176f, +-1.475907f, +-1.469676f, +-1.463484f, +-1.457330f, +-1.451214f, +-1.445135f, +-1.439093f, +-1.433087f, +-1.427116f, +-1.421182f, +-1.415282f, +-1.409417f, +-1.403586f, +-1.397789f, +-1.392025f, +-1.386294f, +-1.380596f, +-1.374931f, +-1.369297f, +-1.363695f, +-1.358123f, +-1.352583f, +-1.347074f, +-1.341594f, +-1.336145f, +-1.330725f, +-1.325334f, +-1.319972f, +-1.314638f, +-1.309333f, +-1.304056f, +-1.298807f, +-1.293585f, +-1.288390f, +-1.283222f, +-1.278081f, +-1.272966f, +-1.267877f, +-1.262813f, +-1.257776f, +-1.252763f, +-1.247775f, +-1.242813f, +-1.237874f, +-1.232960f, +-1.228070f, +-1.223204f, +-1.218362f, +-1.213542f, +-1.208746f, +-1.203973f, +-1.199222f, +-1.194494f, +-1.189788f, +-1.185104f, +-1.180442f, +-1.175802f, +-1.171183f, +-1.166585f, +-1.162009f, +-1.157453f, +-1.152918f, +-1.148403f, +-1.143909f, +-1.139434f, +-1.134980f, +-1.130545f, +-1.126130f, +-1.121735f, +-1.117358f, +-1.113001f, +-1.108663f, +-1.104343f, +-1.100042f, +-1.095759f, +-1.091495f, +-1.087249f, +-1.083020f, +-1.078810f, +-1.074617f, +-1.070441f, +-1.066283f, +-1.062143f, +-1.058019f, +-1.053912f, +-1.049822f, +-1.045749f, +-1.041692f, +-1.037652f, +-1.033627f, +-1.029619f, +-1.025627f, +-1.021651f, +-1.017691f, +-1.013746f, +-1.009817f, +-1.005903f, +-1.002004f, +-0.998121f, +-0.994252f, +-0.990399f, +-0.986560f, +-0.982736f, +-0.978926f, +-0.975131f, +-0.971351f, +-0.967584f, +-0.963832f, +-0.960093f, +-0.956369f, +-0.952658f, +-0.948962f, +-0.945278f, +-0.941609f, +-0.937952f, +-0.934309f, +-0.930679f, +-0.927063f, +-0.923459f, +-0.919869f, +-0.916291f, +-0.912726f, +-0.909173f, +-0.905633f, +-0.902106f, +-0.898591f, +-0.895089f, +-0.891598f, +-0.888120f, +-0.884654f, +-0.881199f, +-0.877757f, +-0.874327f, +-0.870908f, +-0.867501f, +-0.864105f, +-0.860721f, +-0.857348f, +-0.853987f, +-0.850637f, +-0.847298f, +-0.843970f, +-0.840653f, +-0.837348f, +-0.834053f, +-0.830769f, +-0.827495f, +-0.824233f, +-0.820981f, +-0.817739f, +-0.814508f, +-0.811287f, +-0.808077f, +-0.804877f, +-0.801687f, +-0.798508f, +-0.795338f, +-0.792179f, +-0.789029f, +-0.785889f, +-0.782759f, +-0.779639f, +-0.776529f, +-0.773428f, +-0.770337f, +-0.767255f, +-0.764183f, +-0.761120f, +-0.758067f, +-0.755023f, +-0.751988f, +-0.748962f, +-0.745945f, +-0.742938f, +-0.739939f, +-0.736950f, +-0.733969f, +-0.730997f, +-0.728034f, +-0.725080f, +-0.722135f, +-0.719198f, +-0.716270f, +-0.713350f, +-0.710439f, +-0.707536f, +-0.704642f, +-0.701756f, +-0.698878f, +-0.696008f, +-0.693147f, +-0.690294f, +-0.687449f, +-0.684612f, +-0.681783f, +-0.678963f, +-0.676150f, +-0.673345f, +-0.670547f, +-0.667758f, +-0.664976f, +-0.662202f, +-0.659436f, +-0.656677f, +-0.653926f, +-0.651183f, +-0.648447f, +-0.645718f, +-0.642997f, +-0.640284f, +-0.637577f, +-0.634878f, +-0.632186f, +-0.629502f, +-0.626825f, +-0.624154f, +-0.621491f, +-0.618835f, +-0.616186f, +-0.613544f, +-0.610909f, +-0.608281f, +-0.605660f, +-0.603045f, +-0.600438f, +-0.597837f, +-0.595243f, +-0.592656f, +-0.590075f, +-0.587501f, +-0.584934f, +-0.582373f, +-0.579818f, +-0.577271f, +-0.574729f, +-0.572195f, +-0.569666f, +-0.567144f, +-0.564628f, +-0.562119f, +-0.559616f, +-0.557119f, +-0.554628f, +-0.552144f, +-0.549665f, +-0.547193f, +-0.544727f, +-0.542267f, +-0.539813f, +-0.537365f, +-0.534923f, +-0.532487f, +-0.530057f, +-0.527633f, +-0.525214f, +-0.522802f, +-0.520395f, +-0.517994f, +-0.515599f, +-0.513209f, +-0.510826f, +-0.508447f, +-0.506075f, +-0.503708f, +-0.501347f, +-0.498991f, +-0.496641f, +-0.494296f, +-0.491957f, +-0.489623f, +-0.487295f, +-0.484972f, +-0.482655f, +-0.480343f, +-0.478036f, +-0.475734f, +-0.473438f, +-0.471147f, +-0.468861f, +-0.466581f, +-0.464306f, +-0.462035f, +-0.459770f, +-0.457511f, +-0.455256f, +-0.453006f, +-0.450761f, +-0.448522f, +-0.446287f, +-0.444057f, +-0.441833f, +-0.439613f, +-0.437398f, +-0.435188f, +-0.432983f, +-0.430783f, +-0.428588f, +-0.426397f, +-0.424211f, +-0.422030f, +-0.419854f, +-0.417682f, +-0.415515f, +-0.413353f, +-0.411196f, +-0.409043f, +-0.406895f, +-0.404751f, +-0.402612f, +-0.400478f, +-0.398348f, +-0.396222f, +-0.394101f, +-0.391985f, +-0.389873f, +-0.387766f, +-0.385662f, +-0.383564f, +-0.381470f, +-0.379380f, +-0.377294f, +-0.375213f, +-0.373136f, +-0.371064f, +-0.368995f, +-0.366931f, +-0.364872f, +-0.362816f, +-0.360765f, +-0.358718f, +-0.356675f, +-0.354636f, +-0.352602f, +-0.350571f, +-0.348545f, +-0.346523f, +-0.344504f, +-0.342490f, +-0.340480f, +-0.338474f, +-0.336472f, +-0.334474f, +-0.332480f, +-0.330490f, +-0.328504f, +-0.326522f, +-0.324544f, +-0.322569f, +-0.320599f, +-0.318632f, +-0.316670f, +-0.314711f, +-0.312756f, +-0.310804f, +-0.308857f, +-0.306913f, +-0.304974f, +-0.303037f, +-0.301105f, +-0.299176f, +-0.297252f, +-0.295330f, +-0.293413f, +-0.291499f, +-0.289589f, +-0.287682f, +-0.285779f, +-0.283880f, +-0.281984f, +-0.280092f, +-0.278203f, +-0.276318f, +-0.274437f, +-0.272559f, +-0.270684f, +-0.268814f, +-0.266946f, +-0.265082f, +-0.263222f, +-0.261365f, +-0.259511f, +-0.257661f, +-0.255814f, +-0.253971f, +-0.252131f, +-0.250295f, +-0.248461f, +-0.246632f, +-0.244805f, +-0.242982f, +-0.241162f, +-0.239346f, +-0.237532f, +-0.235722f, +-0.233916f, +-0.232112f, +-0.230312f, +-0.228515f, +-0.226721f, +-0.224931f, +-0.223144f, +-0.221359f, +-0.219578f, +-0.217801f, +-0.216026f, +-0.214255f, +-0.212486f, +-0.210721f, +-0.208959f, +-0.207200f, +-0.205444f, +-0.203691f, +-0.201941f, +-0.200195f, +-0.198451f, +-0.196710f, +-0.194973f, +-0.193238f, +-0.191506f, +-0.189778f, +-0.188052f, +-0.186330f, +-0.184610f, +-0.182893f, +-0.181179f, +-0.179468f, +-0.177761f, +-0.176056f, +-0.174353f, +-0.172654f, +-0.170958f, +-0.169264f, +-0.167574f, +-0.165886f, +-0.164201f, +-0.162519f, +-0.160840f, +-0.159163f, +-0.157490f, +-0.155819f, +-0.154151f, +-0.152485f, +-0.150823f, +-0.149163f, +-0.147506f, +-0.145852f, +-0.144200f, +-0.142552f, +-0.140905f, +-0.139262f, +-0.137621f, +-0.135983f, +-0.134348f, +-0.132715f, +-0.131085f, +-0.129458f, +-0.127833f, +-0.126211f, +-0.124592f, +-0.122975f, +-0.121361f, +-0.119749f, +-0.118140f, +-0.116534f, +-0.114930f, +-0.113329f, +-0.111730f, +-0.110134f, +-0.108540f, +-0.106949f, +-0.105361f, +-0.103774f, +-0.102191f, +-0.100610f, +-0.099031f, +-0.097455f, +-0.095882f, +-0.094311f, +-0.092742f, +-0.091176f, +-0.089612f, +-0.088051f, +-0.086492f, +-0.084936f, +-0.083382f, +-0.081830f, +-0.080281f, +-0.078734f, +-0.077190f, +-0.075648f, +-0.074108f, +-0.072571f, +-0.071036f, +-0.069503f, +-0.067973f, +-0.066445f, +-0.064920f, +-0.063396f, +-0.061875f, +-0.060357f, +-0.058840f, +-0.057326f, +-0.055815f, +-0.054305f, +-0.052798f, +-0.051293f, +-0.049791f, +-0.048290f, +-0.046792f, +-0.045296f, +-0.043803f, +-0.042311f, +-0.040822f, +-0.039335f, +-0.037850f, +-0.036368f, +-0.034887f, +-0.033409f, +-0.031933f, +-0.030459f, +-0.028988f, +-0.027518f, +-0.026051f, +-0.024585f, +-0.023122f, +-0.021661f, +-0.020203f, +-0.018746f, +-0.017291f, +-0.015839f, +-0.014389f, +-0.012941f, +-0.011494f, +-0.010050f, +-0.008608f, +-0.007168f, +-0.005731f, +-0.004295f, +-0.002861f, +-0.001430f, +0.000000f, +0.001428f, +0.002853f, +0.004277f, +0.005698f, +0.007117f, +0.008535f, +0.009950f, +0.011364f, +0.012775f, +0.014185f, +0.015592f, +0.016998f, +0.018401f, +0.019803f, +0.021202f, +0.022600f, +0.023996f, +0.025389f, +0.026781f, +0.028171f, +0.029559f, +0.030945f, +0.032329f, +0.033711f, +0.035091f, +0.036470f, +0.037846f, +0.039221f, +0.040593f, +0.041964f, +0.043333f, +0.044700f, +0.046065f, +0.047429f, +0.048790f, +0.050150f, +0.051508f, +0.052863f, +0.054218f, +0.055570f, +0.056920f, +0.058269f, +0.059616f, +0.060961f, +0.062304f, +0.063645f, +0.064985f, +0.066323f, +0.067659f, +0.068993f, +0.070325f, +0.071656f, +0.072985f, +0.074312f, +0.075637f, +0.076961f, +0.078283f, +0.079603f, +0.080921f, +0.082238f, +0.083553f, +0.084866f, +0.086178f, +0.087487f, +0.088796f, +0.090102f, +0.091406f, +0.092709f, +0.094011f, +0.095310f, +0.096608f, +0.097904f, +0.099199f, +0.100492f, +0.101783f, +0.103072f, +0.104360f, +0.105646f, +0.106931f, +0.108214f, +0.109495f, +0.110774f, +0.112052f, +0.113329f, +0.114603f, +0.115876f, +0.117148f, +0.118418f, +0.119686f, +0.120953f, +0.122218f, +0.123481f, +0.124743f, +0.126003f, +0.127262f, +0.128519f, +0.129774f, +0.131028f, +0.132281f, +0.133531f, +0.134781f, +0.136028f, +0.137274f, +0.138519f, +0.139762f, +0.141003f, +0.142243f, +0.143482f, +0.144719f, +0.145954f, +0.147188f, +0.148420f, +0.149651f, +0.150880f, +0.152108f, +0.153334f, +0.154559f, +0.155782f, +0.157004f, +0.158224f, +0.159443f, +0.160660f, +0.161876f, +0.163090f, +0.164303f, +0.165514f, +0.166724f, +0.167933f, +0.169140f, +0.170345f, +0.171549f, +0.172752f, +0.173953f, +0.175153f, +0.176351f, +0.177548f, +0.178744f, +0.179938f, +0.181130f, +0.182322f, +0.183511f, +0.184700f, +0.185887f, +0.187072f, +0.188256f, +0.189439f, +0.190620f, +0.191800f, +0.192979f, +0.194156f, +0.195332f, +0.196506f, +0.197679f, +0.198851f, +0.200021f, +0.201190f, +0.202358f, +0.203524f, +0.204689f, +0.205852f, +0.207014f, +0.208175f, +0.209334f, +0.210492f, +0.211649f, +0.212805f, +0.213959f, +0.215111f, +0.216263f, +0.217413f, +0.218562f, +0.219709f, +0.220855f, +0.222000f, +0.223144f, +0.224286f, +0.225427f, +0.226566f, +0.227705f, +0.228842f, +0.229977f, +0.231112f, +0.232245f, +0.233377f, +0.234507f, +0.235637f, +0.236765f, +0.237891f, +0.239017f, +0.240141f, +0.241264f, +0.242386f, +0.243506f, +0.244625f, +0.245743f, +0.246860f, +0.247976f, +0.249090f, +0.250203f, +0.251314f, +0.252425f, +0.253534f, +0.254642f, +0.255749f, +0.256855f, +0.257959f, +0.259062f, +0.260164f, +0.261265f, +0.262364f, +0.263463f, +0.264560f, +0.265656f, +0.266750f, +0.267844f, +0.268936f, +0.270027f, +0.271117f, +0.272206f, +0.273293f, +0.274380f, +0.275465f, +0.276549f, +0.277632f, +0.278713f, +0.279794f, +0.280873f, +0.281951f, +0.283028f, +0.284104f, +0.285179f, +0.286252f, +0.287325f, +0.288396f, +0.289466f, +0.290535f, +0.291603f, +0.292670f, +0.293735f, +0.294800f, +0.295863f, +0.296925f, +0.297986f, +0.299046f, +0.300105f, +0.301162f, +0.302219f, +0.303274f, +0.304328f, +0.305382f, +0.306434f, +0.307485f, +0.308535f, +0.309583f, +0.310631f, +0.311678f, +0.312723f, +0.313767f, +0.314811f, +0.315853f, +0.316894f, +0.317934f, +0.318973f, +0.320011f, +0.321048f, +0.322084f, +0.323118f, +0.324152f, +0.325184f, +0.326216f, +0.327246f, +0.328275f, +0.329304f, +0.330331f, +0.331357f, +0.332382f, +0.333406f, +0.334429f, +0.335451f, +0.336472f, +0.337492f, +0.338511f, +0.339529f, +0.340546f, +0.341561f, +0.342576f, +0.343590f, +0.344602f, +0.345614f, +0.346625f, +0.347634f, +0.348643f, +0.349650f, +0.350657f, +0.351662f, +0.352667f, +0.353670f, +0.354673f, +0.355674f, +0.356675f, +0.357674f, +0.358673f, +0.359670f, +0.360667f, +0.361662f, +0.362657f, +0.363651f, +0.364643f, +0.365635f, +0.366625f, +0.367615f, +0.368604f, +0.369591f, +0.370578f, +0.371564f, +0.372548f, +0.373532f, +0.374515f, +0.375497f, +0.376478f, +0.377457f, +0.378436f, +0.379414f, +0.380391f, +0.381368f, +0.382343f, +0.383317f, +0.384290f, +0.385262f, +0.386234f, +0.387204f, +0.388174f, +0.389142f, +0.390110f, +0.391076f, +0.392042f, +0.393007f, +0.393971f, +0.394934f, +0.395896f, +0.396857f, +0.397817f, +0.398776f, +0.399734f, +0.400692f, +0.401648f, +0.402604f, +0.403559f, +0.404512f, +0.405465f, +0.406417f, +0.407368f, +0.408318f, +0.409267f, +0.410216f, +0.411163f, +0.412110f, +0.413055f, +0.414000f, +0.414944f, +0.415887f, +0.416829f, +0.417770f, +0.418710f, +0.419650f, +0.420588f, +0.421526f, +0.422463f, +0.423399f, +0.424334f, +0.425268f, +0.426201f, +0.427133f, +0.428065f, +0.428996f, +0.429925f, +0.430854f, +0.431782f, +0.432710f, +0.433636f, +0.434561f, +0.435486f, +0.436410f, +0.437333f, +0.438255f, +0.439176f, +0.440097f, +0.441016f, +0.441935f, +0.442853f, +0.443770f, +0.444686f, +0.445601f, +0.446516f, +0.447429f, +0.448342f, +0.449254f, +0.450165f, +0.451076f, +0.451985f, +0.452894f, +0.453802f, +0.454709f, +0.455615f, +0.456520f, +0.457425f, +0.458329f, +0.459232f, +0.460134f, +0.461035f, +0.461935f, +0.462835f, +0.463734f, +0.464632f, +0.465529f, +0.466426f, +0.467321f, +0.468216f, +0.469110f, +0.470004f, +0.470896f, +0.471788f, +0.472679f, +0.473569f, +0.474458f, +0.475346f, +0.476234f, +0.477121f, +0.478007f, +0.478893f, +0.479777f, +0.480661f, +0.481544f, +0.482426f, +0.483308f, +0.484188f, +0.485068f, +0.485947f, +0.486826f, +0.487703f, +0.488580f, +0.489456f, +0.490331f, +0.491206f, +0.492080f, +0.492953f, +0.493825f, +0.494696f, +0.495567f, +0.496437f, +0.497306f, +0.498175f, +0.499042f, +0.499909f, +0.500775f, +0.501641f, +0.502505f, +0.503369f, +0.504233f, +0.505095f, +0.505957f, +0.506818f, +0.507678f, +0.508537f, +0.509396f, +0.510254f, +0.511111f, +0.511968f, +0.512824f, +0.513679f, +0.514533f, +0.515387f, +0.516240f, +0.517092f, +0.517943f, +0.518794f, +0.519644f, +0.520493f, +0.521342f, +0.522189f, +0.523036f, +0.523883f, +0.524729f, +0.525573f, +0.526418f, +0.527261f, +0.528104f, +0.528946f, +0.529788f, +0.530628f, +0.531468f, +0.532308f, +0.533146f, +0.533984f, +0.534821f, +0.535658f, +0.536493f, +0.537328f, +0.538163f, +0.538997f, +0.539829f, +0.540662f, +0.541493f, +0.542324f, +0.543155f, +0.543984f, +0.544813f, +0.545641f, +0.546469f, +0.547295f, +0.548121f, +0.548947f, +0.549772f, +0.550596f, +0.551419f, +0.552242f, +0.553064f, +0.553885f, +0.554706f, +0.555526f, +0.556345f, +0.557164f, +0.557982f, +0.558799f, +0.559616f, +0.560432f, +0.561247f, +0.562062f, +0.562876f, +0.563689f, +0.564502f, +0.565314f, +0.566125f, +0.566936f, +0.567746f, +0.568555f, +0.569364f, +0.570172f, +0.570980f, +0.571786f, +0.572592f, +0.573398f, +0.574203f, +0.575007f, +0.575810f, +0.576613f, +0.577416f, +0.578217f, +0.579018f, +0.579818f, +0.580618f, +0.581417f, +0.582216f, +0.583013f, +0.583811f, +0.584607f, +0.585403f, +0.586198f, +0.586993f, +0.587787f, +0.588580f, +0.589373f, +0.590165f, +0.590956f, +0.591747f, +0.592537f, +0.593327f, +0.594116f, +0.594904f, +0.595692f, +0.596479f, +0.597265f, +0.598051f, +0.598837f, +0.599621f, +0.600405f, +0.601189f, +0.601971f, +0.602753f, +0.603535f, +0.604316f, +0.605096f, +0.605876f, +0.606655f, +0.607434f, +0.608212f, +0.608989f, +0.609766f, +0.610542f, +0.611317f, +0.612092f, +0.612866f, +0.613640f, +0.614413f, +0.615186f, +0.615958f, +0.616729f, +0.617500f, +0.618270f, +0.619039f, +0.619808f, +0.620576f, +0.621344f, +0.622111f, +0.622878f, +0.623644f, +0.624409f, +0.625174f, +0.625938f, +0.626702f, +0.627465f, +0.628228f, +0.628990f, +0.629751f, +0.630512f, +0.631272f, +0.632031f, +0.632790f, +0.633549f, +0.634307f, +0.635064f, +0.635821f, +0.636577f, +0.637332f, +0.638087f, +0.638842f, +0.639596f, +0.640349f, +0.641102f, +0.641854f, +0.642605f, +0.643357f, +0.644107f, +0.644857f, +0.645606f, +0.646355f, +0.647103f, +0.647851f, +0.648598f, +0.649345f, +0.650091f, +0.650836f, +0.651581f, +0.652325f, +0.653069f, +0.653812f, +0.654555f, +0.655297f, +0.656039f, +0.656780f, +0.657520f, +0.658260f, +0.658999f, +0.659738f, +0.660476f, +0.661214f, +0.661951f, +0.662688f, +0.663424f, +0.664160f, +0.664895f, +0.665629f, +0.666363f, +0.667097f, +0.667829f, +0.668562f, +0.669294f, +0.670025f, +0.670755f, +0.671486f, +0.672215f, +0.672944f, +0.673673f, +0.674401f, +0.675129f, +0.675856f, +0.676582f, +0.677308f, +0.678034f, +0.678758f, +0.679483f, +0.680207f, +0.680930f, +0.681653f, +0.682375f, +0.683097f, +0.683818f, +0.684539f, +0.685259f, +0.685979f, +0.686698f, +0.687417f, +0.688135f, +0.688852f, +0.689569f, +0.690286f, +0.691002f, +0.691718f, +0.692433f, +0.693147f, +0.693861f, +0.694575f, +0.695288f, +0.696000f, +0.696712f, +0.697424f, +0.698135f, +0.698845f, +0.699555f, +0.700265f, +0.700974f, +0.701682f, +0.702390f, +0.703098f, +0.703804f, +0.704511f, +0.705217f, +0.705922f, +0.706627f, +0.707332f, +0.708036f, +0.708739f, +0.709442f, +0.710145f, +0.710847f, +0.711548f, +0.712249f, +0.712950f, +0.713650f, +0.714349f, +0.715048f, +0.715747f, +0.716445f, +0.717143f, +0.717840f, +0.718536f, +0.719233f, +0.719928f, +0.720623f, +0.721318f, +0.722012f, +0.722706f, +0.723399f, +0.724092f, +0.724784f, +0.725476f, +0.726167f, +0.726858f, +0.727549f, +0.728239f, +0.728928f, +0.729617f, +0.730305f, +0.730993f, +0.731681f, +0.732368f, +0.733054f, +0.733741f, +0.734426f, +0.735111f, +0.735796f, +0.736480f, +0.737164f, +0.737847f, +0.738530f, +0.739213f, +0.739894f, +0.740576f, +0.741257f, +0.741937f, +0.742617f, +0.743297f, +0.743976f, +0.744655f, +0.745333f, +0.746011f, +0.746688f, +0.747365f, +0.748041f, +0.748717f, +0.749392f, +0.750067f, +0.750742f, +0.751416f, +0.752090f, +0.752763f, +0.753436f, +0.754108f, +0.754780f, +0.755451f, +0.756122f, +0.756792f, +0.757462f, +0.758132f, +0.758801f, +0.759470f, +0.760138f, +0.760806f, +0.761473f, +0.762140f, +0.762806f, +0.763472f, +0.764138f, +0.764803f, +0.765468f, +0.766132f, +0.766796f, +0.767459f, +0.768122f, +0.768785f, +0.769447f, +0.770108f, +0.770769f, +0.771430f, +0.772090f, +0.772750f, +0.773410f, +0.774069f, +0.774727f, +0.775385f, +0.776043f, +0.776700f, +0.777357f, +0.778013f, +0.778669f, +0.779325f, +0.779980f, +0.780635f, +0.781289f, +0.781943f, +0.782596f, +0.783249f, +0.783902f, +0.784554f, +0.785205f, +0.785857f, +0.786507f, +0.787158f, +0.787808f, +0.788457f, +0.789107f, +0.789755f, +0.790404f, +0.791051f, +0.791699f, +0.792346f, +0.792993f, +0.793639f, +0.794285f, +0.794930f, +0.795575f, +0.796219f, +0.796863f, +0.797507f, +0.798150f, +0.798793f, +0.799436f, +0.800078f, +0.800720f, +0.801361f, +0.802002f, +0.802642f, +0.803282f, +0.803922f, +0.804561f, +0.805200f, +0.805838f, +0.806476f, +0.807113f, +0.807751f, +0.808387f, +0.809024f, +0.809660f, +0.810295f, +0.810930f, +0.811565f, +0.812199f, +0.812833f, +0.813467f, +0.814100f, +0.814733f, +0.815365f, +0.815997f, +0.816628f, +0.817259f, +0.817890f, +0.818520f, +0.819150f, +0.819780f, +0.820409f, +0.821038f, +0.821666f, +0.822294f, +0.822922f, +0.823549f, +0.824175f, +0.824802f, +0.825428f, +0.826053f, +0.826679f, +0.827303f, +0.827928f, +0.828552f, +0.829175f, +0.829799f, +0.830422f, +0.831044f, +0.831666f, +0.832288f, +0.832909f, +0.833530f, +0.834151f, +0.834771f, +0.835391f, +0.836010f, +0.836629f, +0.837248f, +0.837866f, +0.838484f, +0.839101f, +0.839718f, +0.840335f, +0.840951f, +0.841567f, +0.842183f, +0.842798f, +0.843413f, +0.844027f, +0.844641f, +0.845255f, +0.845868f, +0.846481f, +0.847094f, +0.847706f, +0.848318f, +0.848929f, +0.849540f, +0.850151f, +0.850761f, +0.851371f, +0.851981f, +0.852590f, +0.853199f, +0.853807f, +0.854415f, +0.855023f, +0.855630f, +0.856237f, +0.856844f, +0.857450f, +0.858056f, +0.858662f, +0.859267f, +0.859872f, +0.860476f, +0.861080f, +0.861684f, +0.862287f, +0.862890f, +0.863493f, +0.864095f, +0.864697f, +0.865298f, +0.865899f, +0.866500f, +0.867100f, +0.867701f, +0.868300f, +0.868900f, +0.869499f, +0.870097f, +0.870695f, +0.871293f, +0.871891f, +0.872488f, +0.873085f, +0.873681f, +0.874278f, +0.874873f, +0.875469f, +0.876064f, +0.876659f, +0.877253f, +0.877847f, +0.878441f, +0.879034f, +0.879627f, +0.880219f, +0.880812f, +0.881403f, +0.881995f, +0.882586f, +0.883177f, +0.883768f, +0.884358f, +0.884947f, +0.885537f, +0.886126f, +0.886715f, +0.887303f, +0.887891f, +0.888479f, +0.889066f, +0.889653f, +0.890240f, +0.890826f, +0.891412f, +0.891998f, +0.892583f, +0.893168f, +0.893753f, +0.894337f, +0.894921f, +0.895505f, +0.896088f, +0.896671f, +0.897254f, +0.897836f, +0.898418f, +0.898999f, +0.899580f, +0.900161f, +0.900742f, +0.901322f, +0.901902f, +0.902482f, +0.903061f, +0.903640f, +0.904218f, +0.904796f, +0.905374f, +0.905952f, +0.906529f, +0.907106f, +0.907682f, +0.908259f, +0.908834f, +0.909410f, +0.909985f, +0.910560f, +0.911135f, +0.911709f, +0.912283f, +0.912856f, +0.913430f, +0.914002f, +0.914575f, +0.915147f, +0.915719f, +0.916291f, +0.916862f, +0.917433f, +0.918004f, +0.918574f, +0.919144f, +0.919713f, +0.920283f, +0.920852f, +0.921420f, +0.921989f, +0.922557f, +0.923124f, +0.923692f, +0.924259f, +0.924826f, +0.925392f, +0.925958f, +0.926524f, +0.927089f, +0.927654f, +0.928219f, +0.928784f, +0.929348f, +0.929912f, +0.930475f, +0.931039f, +0.931601f, +0.932164f, +0.932726f, +0.933288f, +0.933850f, +0.934411f, +0.934972f, +0.935533f, +0.936093f, +0.936653f, +0.937213f, +0.937773f, +0.938332f, +0.938891f, +0.939449f, +0.940007f, +0.940565f, +0.941123f, +0.941680f, +0.942237f, +0.942794f, +0.943350f, +0.943906f, +0.944462f, +0.945017f, +0.945572f, +0.946127f, +0.946681f, +0.947236f, +0.947789f, +0.948343f, +0.948896f, +0.949449f, +0.950002f, +0.950554f, +0.951106f, +0.951658f, +0.952209f, +0.952760f, +0.953311f, +0.953862f, +0.954412f, +0.954962f, +0.955511f, +0.956061f, +0.956610f, +0.957158f, +0.957707f, +0.958255f, +0.958803f, +0.959350f, +0.959897f, +0.960444f, +0.960991f, +0.961537f, +0.962083f, +0.962629f, +0.963174f, +0.963719f, +0.964264f, +0.964809f, +0.965353f, +0.965897f, +0.966441f, +0.966984f, +0.967527f, +0.968070f, +0.968612f, +0.969154f, +0.969696f, +0.970238f, +0.970779f, +0.971320f, +0.971861f, +0.972401f, +0.972941f, +0.973481f, +0.974020f, +0.974560f, +0.975099f, +0.975637f, +0.976176f, +0.976714f, +0.977251f, +0.977789f, +0.978326f, +0.978863f, +0.979400f, +0.979936f, +0.980472f, +0.981008f, +0.981543f, +0.982078f, +0.982613f, +0.983148f, +0.983682f, +0.984216f, +0.984750f, +0.985284f, +0.985817f, +0.986350f, +0.986882f, +0.987415f, +0.987947f, +0.988478f, +0.989010f, +0.989541f, +0.990072f, +0.990603f, +0.991133f, +0.991663f, +0.992193f, +0.992723f, +0.993252f, +0.993781f, +0.994309f, +0.994838f, +0.995366f, +0.995894f, +0.996421f, +0.996949f, +0.997476f, +0.998002f, +0.998529f, +0.999055f, +0.999581f, +1.000107f, +1.000632f, +1.001157f, +1.001682f, +1.002206f, +1.002731f, +1.003254f, +1.003778f, +1.004302f, +1.004825f, +1.005348f, +1.005870f, +1.006393f, +1.006915f, +1.007436f, +1.007958f, +1.008479f, +1.009000f, +1.009521f, +1.010041f, +1.010561f, +1.011081f, +1.011601f, +1.012120f, +1.012639f, +1.013158f, +1.013677f, +1.014195f, +1.014713f, +1.015231f, +1.015748f, +1.016265f, +1.016782f, +1.017299f, +1.017815f, +1.018331f, +1.018847f, +1.019363f, +1.019878f, +1.020393f, +1.020908f, +1.021423f, +1.021937f, +1.022451f, +1.022965f, +1.023478f, +1.023991f, +1.024504f, +1.025017f, +1.025529f, +1.026042f, +1.026553f, +1.027065f, +1.027577f, +1.028088f, +1.028598f, +1.029109f, +1.029619f, +1.030129f, +1.030639f, +1.031149f, +1.031658f, +1.032167f, +1.032676f, +1.033184f, +1.033693f, +1.034201f, +1.034708f, +1.035216f, +1.035723f, +1.036230f, +1.036737f, +1.037243f, +1.037750f, +1.038255f, +1.038761f, +1.039267f, +1.039772f, +1.040277f, +1.040781f, +1.041286f, +1.041790f, +1.042294f, +1.042798f, +1.043301f, +1.043804f, +1.044307f, +1.044810f, +1.045312f, +1.045814f, +1.046316f, +1.046818f, +1.047319f, +1.047820f, +1.048321f, +1.048822f, +1.049322f, +1.049822f, +1.050322f, +1.050822f, +1.051321f, +1.051820f, +1.052319f, +1.052818f, +1.053316f, +1.053814f, +1.054312f, +1.054810f, +1.055307f, +1.055804f, +1.056301f, +1.056798f, +1.057294f, +1.057790f, +1.058286f, +1.058782f, +1.059277f, +1.059772f, +1.060267f, +1.060762f, +1.061257f, +1.061751f, +1.062245f, +1.062738f, +1.063232f, +1.063725f, +1.064218f, +1.064711f, +1.065203f, +1.065695f, +1.066187f, +1.066679f, +1.067171f, +1.067662f, +1.068153f, +1.068644f, +1.069134f, +1.069625f, +1.070115f, +1.070605f, +1.071094f, +1.071584f, +1.072073f, +1.072562f, +1.073050f, +1.073539f, +1.074027f, +1.074515f, +1.075002f, +1.075490f, +1.075977f, +1.076464f, +1.076951f, +1.077437f, +1.077924f, +1.078410f, +1.078895f, +1.079381f, +1.079866f, +1.080351f, +1.080836f, +1.081321f, +1.081805f, +1.082289f, +1.082773f, +1.083257f, +1.083740f, +1.084224f, +1.084707f, +1.085189f, +1.085672f, +1.086154f, +1.086636f, +1.087118f, +1.087599f, +1.088081f, +1.088562f, +1.089043f, +1.089523f, +1.090004f, +1.090484f, +1.090964f, +1.091444f, +1.091923f, +1.092403f, +1.092882f, +1.093360f, +1.093839f, +1.094317f, +1.094795f, +1.095273f, +1.095751f, +1.096228f, +1.096706f, +1.097183f, +1.097659f, +1.098136f, +1.098612f, +1.099088f, +1.099564f, +1.100040f, +1.100515f, +1.100990f, +1.101465f, +1.101940f, +1.102415f, +1.102889f, +1.103363f, +1.103837f, +1.104310f, +1.104784f, +1.105257f, +1.105730f, +1.106202f, +1.106675f, +1.107147f, +1.107619f, +1.108091f, +1.108563f, +1.109034f, +1.109505f, +1.109976f, +1.110447f, +1.110917f, +1.111387f, +1.111858f, +1.112327f, +1.112797f, +1.113266f, +1.113735f, +1.114204f, +1.114673f, +1.115142f, +1.115610f, +1.116078f, +1.116546f, +1.117013f, +1.117481f, +1.117948f, +1.118415f, +1.118882f, +1.119348f, +1.119814f, +1.120281f, +1.120746f, +1.121212f, +1.121678f, +1.122143f, +1.122608f, +1.123073f, +1.123537f, +1.124002f, +1.124466f, +1.124930f, +1.125393f, +1.125857f, +1.126320f, +1.126783f, +1.127246f, +1.127709f, +1.128171f, +1.128633f, +1.129095f, +1.129557f, +1.130019f, +1.130480f, +1.130941f, +1.131402f, +1.131863f, +1.132323f, +1.132784f, +1.133244f, +1.133704f, +1.134163f, +1.134623f, +1.135082f, +1.135541f, +1.136000f, +1.136458f, +1.136917f, +1.137375f, +1.137833f, +1.138291f, +1.138748f, +1.139206f, +1.139663f, +1.140120f, +1.140576f, +1.141033f, +1.141489f, +1.141945f, +1.142401f, +1.142857f, +1.143312f, +1.143768f, +1.144223f, +1.144678f, +1.145132f, +1.145587f, +1.146041f, +1.146495f, +1.146949f, +1.147402f, +1.147856f, +1.148309f, +1.148762f, +1.149215f, +1.149667f, +1.150120f, +1.150572f, +1.151024f, +1.151476f, +1.151927f, +1.152379f, +1.152830f, +1.153281f, +1.153732f, +1.154182f, +1.154632f, +1.155083f, +1.155533f, +1.155982f, +1.156432f, +1.156881f, +1.157330f, +1.157779f, +1.158228f, +1.158677f, +1.159125f, +1.159573f, +1.160021f, +1.160469f, +1.160916f, +1.161363f, +1.161811f, +1.162258f, +1.162704f, +1.163151f, +1.163597f, +1.164043f, +1.164489f, +1.164935f, +1.165380f, +1.165826f, +1.166271f, +1.166716f, +1.167161f, +1.167605f, +1.168050f, +1.168494f, +1.168938f, +1.169381f, +1.169825f, +1.170268f, +1.170711f, +1.171154f, +1.171597f, +1.172040f, +1.172482f, +1.172924f, +1.173366f, +1.173808f, +1.174250f, +1.174691f, +1.175132f, +1.175573f, +1.176014f, +1.176455f, +1.176895f, +1.177335f, +1.177775f, +1.178215f, +1.178655f, +1.179094f, +1.179534f, +1.179973f, +1.180412f, +1.180850f, +1.181289f, +1.181727f, +1.182165f, +1.182603f, +1.183041f, +1.183479f, +1.183916f, +1.184353f, +1.184790f, +1.185227f, +1.185663f, +1.186100f, +1.186536f, +1.186972f, +1.187408f, +1.187843f, +1.188279f, +1.188714f, +1.189149f, +1.189584f, +1.190019f, +1.190453f, +1.190888f, +1.191322f, +1.191756f, +1.192189f, +1.192623f, +1.193056f, +1.193489f, +1.193922f, +1.194355f, +1.194788f, +1.195220f, +1.195653f, +1.196085f, +1.196517f, +1.196948f, +1.197380f, +1.197811f, +1.198242f, +1.198673f, +1.199104f, +1.199534f, +1.199965f, +1.200395f, +1.200825f, +1.201255f, +1.201684f, +1.202114f, +1.202543f, +1.202972f, +1.203401f, +1.203830f, +1.204258f, +1.204687f, +1.205115f, +1.205543f, +1.205971f, +1.206398f, +1.206826f, +1.207253f, +1.207680f, +1.208107f, +1.208534f, +1.208960f, +1.209387f, +1.209813f, +1.210239f, +1.210665f, +1.211090f, +1.211516f, +1.211941f, +1.212366f, +1.212791f, +1.213216f, +1.213640f, +1.214065f, +1.214489f, +1.214913f, +1.215337f, +1.215760f, +1.216184f, +1.216607f, +1.217030f, +1.217453f, +1.217876f, +1.218298f, +1.218721f, +1.219143f, +1.219565f, +1.219987f, +1.220408f, +1.220830f, +1.221251f, +1.221672f, +1.222093f, +1.222514f, +1.222935f, +1.223355f, +1.223775f, +1.224196f, +1.224615f, +1.225035f, +1.225455f, +1.225874f, +1.226293f, +1.226712f, +1.227131f, +1.227550f, +1.227968f, +1.228387f, +1.228805f, +1.229223f, +1.229641f, +1.230058f, +1.230476f, +1.230893f, +1.231310f, +1.231727f, +1.232144f, +1.232560f, +1.232977f, +1.233393f, +1.233809f, +1.234225f, +1.234641f, +1.235056f, +1.235471f, +1.235887f, +1.236302f, +1.236717f, +1.237131f, +1.237546f, +1.237960f, +1.238374f, +1.238788f, +1.239202f, +1.239616f, +1.240029f, +1.240442f, +1.240856f, +1.241269f, +1.241681f, +1.242094f, +1.242506f, +1.242919f, +1.243331f, +1.243743f, +1.244155f, +1.244566f, +1.244978f, +1.245389f, +1.245800f, +1.246211f, +1.246622f, +1.247032f, +1.247443f, +1.247853f, +1.248263f, +1.248673f, +1.249083f, +1.249492f, +1.249902f, +1.250311f, +1.250720f, +1.251129f, +1.251538f, +1.251946f, +1.252355f, +1.252763f, +1.253171f, +1.253579f, +1.253987f, +1.254394f, +1.254802f, +1.255209f, +1.255616f, +1.256023f, +1.256430f, +1.256836f, +1.257243f, +1.257649f, +1.258055f, +1.258461f, +1.258867f, +1.259272f, +1.259678f, +1.260083f, +1.260488f, +1.260893f, +1.261298f, +1.261702f, +1.262107f, +1.262511f, +1.262915f, +1.263319f, +1.263723f, +1.264127f, +1.264530f, +1.264934f, +1.265337f, +1.265740f, +1.266142f, +1.266545f, +1.266948f, +1.267350f, +1.267752f, +1.268154f, +1.268556f, +1.268958f, +1.269359f, +1.269761f, +1.270162f, +1.270563f, +1.270964f, +1.271364f, +1.271765f, +1.272165f, +1.272566f, +1.272966f, +1.273366f, +1.273765f, +1.274165f, +1.274564f, +1.274964f, +1.275363f, +1.275762f, +1.276161f, +1.276559f, +1.276958f, +1.277356f, +1.277754f, +1.278152f, +1.278550f, +1.278948f, +1.279345f, +1.279743f, +1.280140f, +1.280537f, +1.280934f, +1.281331f, +1.281727f, +1.282124f, +1.282520f, +1.282916f, +1.283312f, +1.283708f, +1.284103f, +1.284499f, +1.284894f, +1.285289f, +1.285684f, +1.286079f, +1.286474f, +1.286869f, +1.287263f, +1.287657f, +1.288051f, +1.288445f, +1.288839f, +1.289233f, +1.289626f, +1.290019f, +1.290413f, +1.290806f, +1.291198f, +1.291591f, +1.291984f, +1.292376f, +1.292768f, +1.293160f, +1.293552f, +1.293944f, +1.294336f, +1.294727f, +1.295118f, +1.295510f, +1.295901f, +1.296292f, +1.296682f, +1.297073f, +1.297463f, +1.297853f, +1.298243f, +1.298633f, +1.299023f, +1.299413f, +1.299802f, +1.300192f, +1.300581f, +1.300970f, +1.301359f, +1.301747f, +1.302136f, +1.302524f, +1.302913f, +1.303301f, +1.303689f, +1.304077f, +1.304464f, +1.304852f, +1.305239f, +1.305626f, +1.306014f, +1.306400f, +1.306787f, +1.307174f, +1.307560f, +1.307947f, +1.308333f, +1.308719f, +1.309105f, +1.309490f, +1.309876f, +1.310261f, +1.310647f, +1.311032f, +1.311417f, +1.311802f, +1.312186f, +1.312571f, +1.312955f, +1.313340f, +1.313724f, +1.314108f, +1.314491f, +1.314875f, +1.315259f, +1.315642f, +1.316025f, +1.316408f, +1.316791f, +1.317174f, +1.317557f, +1.317939f, +1.318321f, +1.318704f, +1.319086f, +1.319468f, +1.319849f, +1.320231f, +1.320612f, +1.320994f, +1.321375f, +1.321756f, +1.322137f, +1.322517f, +1.322898f, +1.323278f, +1.323659f, +1.324039f, +1.324419f, +1.324799f, +1.325179f, +1.325558f, +1.325938f, +1.326317f, +1.326696f, +1.327075f, +1.327454f, +1.327833f, +1.328211f, +1.328590f, +1.328968f, +1.329346f, +1.329724f, +1.330102f, +1.330480f, +1.330857f, +1.331235f, +1.331612f, +1.331989f, +1.332366f, +1.332743f, +1.333120f, +1.333496f, +1.333873f, +1.334249f, +1.334625f, +1.335001f, +1.335377f, +1.335753f, +1.336128f, +1.336504f, +1.336879f, +1.337254f, +1.337629f, +1.338004f, +1.338379f, +1.338753f, +1.339128f, +1.339502f, +1.339876f, +1.340250f, +1.340624f, +1.340998f, +1.341372f, +1.341745f, +1.342119f, +1.342492f, +1.342865f, +1.343238f, +1.343611f, +1.343983f, +1.344356f, +1.344728f, +1.345100f, +1.345472f, +1.345844f, +1.346216f, +1.346588f, +1.346959f, +1.347331f, +1.347702f, +1.348073f, +1.348444f, +1.348815f, +1.349186f, +1.349556f, +1.349927f, +1.350297f, +1.350667f, +1.351037f, +1.351407f, +1.351777f, +1.352146f, +1.352516f, +1.352885f, +1.353255f, +1.353624f, +1.353993f, +1.354361f, +1.354730f, +1.355099f, +1.355467f, +1.355835f, +1.356203f, +1.356571f, +1.356939f, +1.357307f, +1.357674f, +1.358042f, +1.358409f, +1.358776f, +1.359143f, +1.359510f, +1.359877f, +1.360244f, +1.360610f, +1.360977f, +1.361343f, +1.361709f, +1.362075f, +1.362441f, +1.362806f, +1.363172f, +1.363537f, +1.363903f, +1.364268f, +1.364633f, +1.364998f, +1.365363f, +1.365727f, +1.366092f, +1.366456f, +1.366820f, +1.367184f, +1.367548f, +1.367912f, +1.368276f, +1.368639f, +1.369003f, +1.369366f, +1.369729f, +1.370092f, +1.370455f, +1.370818f, +1.371181f, +1.371543f, +1.371906f, +1.372268f, +1.372630f, +1.372992f, +1.373354f, +1.373716f, +1.374077f, +1.374439f, +1.374800f, +1.375161f, +1.375522f, +1.375883f, +1.376244f, +1.376605f, +1.376965f, +1.377326f, +1.377686f, +1.378046f, +1.378406f, +1.378766f, +1.379126f, +1.379486f, +1.379845f, +1.380204f, +1.380564f, +1.380923f, +1.381282f, +1.381641f, +1.381999f, +1.382358f, +1.382717f, +1.383075f, +1.383433f, +1.383791f, +1.384149f, +1.384507f, +1.384865f, +1.385222f, +1.385580f, +1.385937f, +1.386294f, +1.386651f, +1.387008f, +1.387365f, +1.387722f, +1.388078f, +1.388435f, +1.388791f, +1.389147f, +1.389503f, +1.389859f, +1.390215f, +1.390571f, +1.390926f, +1.391282f, +1.391637f, +1.391992f, +1.392347f, +1.392702f, +1.393057f, +1.393412f, +1.393766f, +1.394121f, +1.394475f, +1.394829f, +1.395183f, +1.395537f, +1.395891f, +1.396245f, +1.396598f, +1.396952f, +1.397305f, +1.397658f, +1.398011f, +1.398364f, +1.398717f, +1.399070f, +1.399422f, +1.399775f, +1.400127f, +1.400479f, +1.400831f, +1.401183f, +1.401535f, +1.401886f, +1.402238f, +1.402589f, +1.402941f, +1.403292f, +1.403643f, +1.403994f, +1.404345f, +1.404695f, +1.405046f, +1.405396f, +1.405747f, +1.406097f, +1.406447f, +1.406797f, +1.407147f, +1.407497f, +1.407846f, +1.408196f, +1.408545f, +1.408894f, +1.409243f, +1.409592f, +1.409941f, +1.410290f, +1.410638f, +1.410987f, +1.411335f, +1.411684f, +1.412032f, +1.412380f, +1.412728f, +1.413075f, +1.413423f, +1.413771f, +1.414118f, +1.414465f, +1.414812f, +1.415159f, +1.415506f, +1.415853f, +1.416200f, +1.416546f, +1.416893f, +1.417239f, +1.417585f, +1.417931f, +1.418277f, +1.418623f, +1.418969f, +1.419315f, +1.419660f, +1.420005f, +1.420351f, +1.420696f, +1.421041f, +1.421386f, +1.421730f, +1.422075f, +1.422420f, +1.422764f, +1.423108f, +1.423453f, +1.423797f, +1.424141f, +1.424484f, +1.424828f, +1.425172f, +1.425515f, +1.425858f, +1.426202f, +1.426545f, +1.426888f, +1.427231f, +1.427573f, +1.427916f, +1.428259f, +1.428601f, +1.428943f, +1.429285f, +1.429627f, +1.429969f, +1.430311f, +1.430653f, +1.430995f, +1.431336f, +1.431677f, +1.432019f, +1.432360f, +1.432701f, +1.433042f, +1.433382f, +1.433723f, +1.434064f, +1.434404f, +1.434744f, +1.435085f, +1.435425f, +1.435765f, +1.436104f, +1.436444f, +1.436784f, +1.437123f, +1.437463f, +1.437802f, +1.438141f, +1.438480f, +1.438819f, +1.439158f, +1.439497f, +1.439835f, +1.440174f, +1.440512f, +1.440850f, +1.441188f, +1.441526f, +1.441864f, +1.442202f, +1.442540f, +1.442877f, +1.443215f, +1.443552f, +1.443889f, +1.444226f, +1.444563f, +1.444900f, +1.445237f, +1.445574f, +1.445910f, +1.446246f, +1.446583f, +1.446919f, +1.447255f, +1.447591f, +1.447927f, +1.448263f, +1.448598f, +1.448934f, +1.449269f, +1.449604f, +1.449940f, +1.450275f, +1.450610f, +1.450944f, +1.451279f, +1.451614f, +1.451948f, +1.452283f, +1.452617f, +1.452951f, +1.453285f, +1.453619f, +1.453953f, +1.454287f, +1.454620f, +1.454954f, +1.455287f, +1.455621f, +1.455954f, +1.456287f, +1.456620f, +1.456953f, +1.457285f, +1.457618f, +1.457950f, +1.458283f, +1.458615f, +1.458947f, +1.459279f, +1.459611f, +1.459943f, +1.460275f, +1.460606f, +1.460938f, +1.461269f, +1.461601f, +1.461932f, +1.462263f, +1.462594f, +1.462925f, +1.463255f, +1.463586f, +1.463917f, +1.464247f, +1.464577f, +1.464907f, +1.465238f, +1.465568f, +1.465897f, +1.466227f, +1.466557f, +1.466886f, +1.467216f, +1.467545f, +1.467874f, +1.468203f, +1.468532f, +1.468861f, +1.469190f, +1.469519f, +1.469847f, +1.470176f, +1.470504f, +1.470832f, +1.471161f, +1.471489f, +1.471817f, +1.472144f, +1.472472f, +1.472800f, +1.473127f, +1.473455f, +1.473782f, +1.474109f, +1.474436f, +1.474763f, +1.475090f, +1.475417f, +1.475743f, +1.476070f, +1.476396f, +1.476723f, +1.477049f, +1.477375f, +1.477701f, +1.478027f, +1.478353f, +1.478678f, +1.479004f, +1.479329f, +1.479655f, +1.479980f, +1.480305f, +1.480630f, +1.480955f, +1.481280f, +1.481605f, +1.481929f, +1.482254f, +1.482578f, +1.482902f, +1.483227f, +1.483551f, +1.483875f, +1.484199f, +1.484522f, +1.484846f, +1.485170f, +1.485493f, +1.485816f, +1.486140f, +1.486463f, +1.486786f, +1.487109f, +1.487432f, +1.487754f, +1.488077f, +1.488400f, +1.488722f, +1.489044f, +1.489367f, +1.489689f, +1.490011f, +1.490333f, +1.490654f, +1.490976f, +1.491298f, +1.491619f, +1.491941f, +1.492262f, +1.492583f, +1.492904f, +1.493225f, +1.493546f, +1.493867f, +1.494187f, +1.494508f, +1.494828f, +1.495149f, +1.495469f, +1.495789f, +1.496109f, +1.496429f, +1.496749f, +1.497069f, +1.497388f, +1.497708f, +1.498027f, +1.498347f, +1.498666f, +1.498985f, +1.499304f, +1.499623f, +1.499942f, +1.500261f, +1.500579f, +1.500898f, +1.501216f, +1.501534f, +1.501853f, +1.502171f, +1.502489f, +1.502807f, +1.503125f, +1.503442f, +1.503760f, +1.504077f, +1.504395f, +1.504712f, +1.505029f, +1.505346f, +1.505663f, +1.505980f, +1.506297f, +1.506614f, +1.506930f, +1.507247f, +1.507563f, +1.507880f, +1.508196f, +1.508512f, +1.508828f, +1.509144f, +1.509460f, +1.509775f, +1.510091f, +1.510407f, +1.510722f, +1.511037f, +1.511352f, +1.511668f, +1.511983f, +1.512297f, +1.512612f, +1.512927f, +1.513242f, +1.513556f, +1.513871f, +1.514185f, +1.514499f, +1.514813f, +1.515127f, +1.515441f, +1.515755f, +1.516069f, +1.516382f, +1.516696f, +1.517009f, +1.517323f, +1.517636f, +1.517949f, +1.518262f, +1.518575f, +1.518888f, +1.519201f, +1.519513f, +1.519826f, +1.520138f, +1.520451f, +1.520763f, +1.521075f, +1.521387f, +1.521699f, +1.522011f, +1.522323f, +1.522634f, +1.522946f, +1.523257f, +1.523569f, +1.523880f, +1.524191f, +1.524502f, +1.524813f, +1.525124f, +1.525435f, +1.525746f, +1.526056f, +1.526367f, +1.526677f, +1.526988f, +1.527298f, +1.527608f, +1.527918f, +1.528228f, +1.528538f, +1.528847f, +1.529157f, +1.529467f, +1.529776f, +1.530085f, +1.530395f, +1.530704f, +1.531013f, +1.531322f, +1.531631f, +1.531940f, +1.532248f, +1.532557f, +1.532865f, +1.533174f, +1.533482f, +1.533790f, +1.534098f, +1.534406f, +1.534714f, +1.535022f, +1.535330f, +1.535638f, +1.535945f, +1.536253f, +1.536560f, +1.536867f, +1.537174f, +1.537481f, +1.537788f, +1.538095f, +1.538402f, +1.538709f, +1.539015f, +1.539322f, +1.539628f, +1.539935f, +1.540241f, +1.540547f, +1.540853f, +1.541159f, +1.541465f, +1.541771f, +1.542076f, +1.542382f, +1.542687f, +1.542993f, +1.543298f, +1.543603f, +1.543908f, +1.544213f, +1.544518f, +1.544823f, +1.545128f, +1.545433f, +1.545737f, +1.546042f, +1.546346f, +1.546650f, +1.546954f, +1.547259f, +1.547563f, +1.547866f, +1.548170f, +1.548474f, +1.548778f, +1.549081f, +1.549385f, +1.549688f, +1.549991f, +1.550294f, +1.550597f, +1.550900f, +1.551203f, +1.551506f, +1.551809f, +1.552111f, +1.552414f, +1.552716f, +1.553019f, +1.553321f, +1.553623f, +1.553925f, +1.554227f, +1.554529f, +1.554831f, +1.555133f, +1.555434f, +1.555736f, +1.556037f, +1.556338f, +1.556640f, +1.556941f, +1.557242f, +1.557543f, +1.557844f, +1.558145f, +1.558445f, +1.558746f, +1.559046f, +1.559347f, +1.559647f, +1.559948f, +1.560248f, +1.560548f, +1.560848f, +1.561148f, +1.561447f, +1.561747f, +1.562047f, +1.562346f, +1.562646f, +1.562945f, +1.563244f, +1.563544f, +1.563843f, +1.564142f, +1.564441f, +1.564739f, +1.565038f, +1.565337f, +1.565635f, +1.565934f, +1.566232f, +1.566530f, +1.566829f, +1.567127f, +1.567425f, +1.567723f, +1.568021f, +1.568318f, +1.568616f, +1.568913f, +1.569211f, +1.569508f, +1.569806f, +1.570103f, +1.570400f, +1.570697f, +1.570994f, +1.571291f, +1.571588f, +1.571884f, +1.572181f, +1.572478f, +1.572774f, +1.573070f, +1.573367f, +1.573663f, +1.573959f, +1.574255f, +1.574551f, +1.574846f, +1.575142f, +1.575438f, +1.575733f, +1.576029f, +1.576324f, +1.576620f, +1.576915f, +1.577210f, +1.577505f, +1.577800f, +1.578095f, +1.578389f, +1.578684f, +1.578979f, +1.579273f, +1.579568f, +1.579862f, +1.580156f, +1.580450f, +1.580744f, +1.581038f, +1.581332f, +1.581626f, +1.581920f, +1.582214f, +1.582507f, +1.582801f, +1.583094f, +1.583387f, +1.583680f, +1.583974f, +1.584267f, +1.584560f, +1.584852f, +1.585145f, +1.585438f, +1.585731f, +1.586023f, +1.586315f, +1.586608f, +1.586900f, +1.587192f, +1.587484f, +1.587776f, +1.588068f, +1.588360f, +1.588652f, +1.588944f, +1.589235f, +1.589527f, +1.589818f, +1.590109f, +1.590401f, +1.590692f, +1.590983f, +1.591274f, +1.591565f, +1.591856f, +1.592146f, +1.592437f, +1.592728f, +1.593018f, +1.593309f, +1.593599f, +1.593889f, +1.594179f, +1.594469f, +1.594759f, +1.595049f, +1.595339f, +1.595629f, +1.595918f, +1.596208f, +1.596497f, +1.596787f, +1.597076f, +1.597365f, +1.597654f, +1.597944f, +1.598233f, +1.598521f, +1.598810f, +1.599099f, +1.599388f, +1.599676f, +1.599965f, +1.600253f, +1.600541f, +1.600830f, +1.601118f, +1.601406f, +1.601694f, +1.601982f, +1.602269f, +1.602557f, +1.602845f, +1.603132f, +1.603420f, +1.603707f, +1.603995f, +1.604282f, +1.604569f, +1.604856f, +1.605143f, +1.605430f, +1.605717f, +1.606003f, +1.606290f, +1.606577f, +1.606863f, +1.607150f, +1.607436f, +1.607722f, +1.608008f, +1.608294f, +1.608580f, +1.608866f, +1.609152f, +1.609438f, +1.609724f, +1.610009f, +1.610295f, +1.610580f, +1.610865f, +1.611151f, +1.611436f, +1.611721f, +1.612006f, +1.612291f, +1.612576f, +1.612861f, +1.613145f, +1.613430f, +1.613714f, +1.613999f, +1.614283f, +1.614568f, +1.614852f, +1.615136f, +1.615420f, +1.615704f, +1.615988f, +1.616272f, +1.616555f, +1.616839f, +1.617123f, +1.617406f, +1.617689f, +1.617973f, +1.618256f, +1.618539f, +1.618822f, +1.619105f, +1.619388f, +1.619671f, +1.619954f, +1.620237f, +1.620519f, +1.620802f, +1.621084f, +1.621366f, +1.621649f, +1.621931f, +1.622213f, +1.622495f, +1.622777f, +1.623059f, +1.623341f, +1.623623f, +1.623904f, +1.624186f, +1.624467f, +1.624749f, +1.625030f, +1.625311f, +1.625592f, +1.625874f, +1.626155f, +1.626435f, +1.626716f, +1.626997f, +1.627278f, +1.627558f, +1.627839f, +1.628119f, +1.628400f, +1.628680f, +1.628960f, +1.629241f, +1.629521f, +1.629801f, +1.630081f, +1.630360f, +1.630640f, +1.630920f, +1.631199f, +1.631479f, +1.631758f, +1.632038f, +1.632317f, +1.632596f, +1.632875f, +1.633154f, +1.633433f, +1.633712f, +1.633991f, +1.634270f, +1.634549f, +1.634827f, +1.635106f, +1.635384f, +1.635662f, +1.635941f, +1.636219f, +1.636497f, +1.636775f, +1.637053f, +1.637331f, +1.637609f, +1.637887f, +1.638164f, +1.638442f, +1.638719f, +1.638997f, +1.639274f, +1.639551f, +1.639829f, +1.640106f, +1.640383f, +1.640660f, +1.640937f, +1.641213f, +1.641490f, +1.641767f, +1.642043f, +1.642320f, +1.642596f, +1.642873f, +1.643149f, +1.643425f, +1.643701f, +1.643977f, +1.644253f, +1.644529f, +1.644805f, +1.645081f, +1.645356f, +1.645632f, +1.645908f, +1.646183f, +1.646458f, +1.646734f, +1.647009f, +1.647284f, +1.647559f, +1.647834f, +1.648109f, +1.648384f, +1.648659f, +1.648933f, +1.649208f, +1.649482f, +1.649757f, +1.650031f, +1.650306f, +1.650580f, +1.650854f, +1.651128f, +1.651402f, +1.651676f, +1.651950f, +1.652224f, +1.652497f, +1.652771f, +1.653045f, +1.653318f, +1.653591f, +1.653865f, +1.654138f, +1.654411f, +1.654684f, +1.654957f, +1.655230f, +1.655503f, +1.655776f, +1.656049f, +1.656321f, +1.656594f, +1.656867f, +1.657139f, +1.657411f, +1.657684f, +1.657956f, +1.658228f, +1.658500f, +1.658772f, +1.659044f, +1.659316f, +1.659588f, +1.659859f, +1.660131f, +1.660403f, +1.660674f, +1.660945f, +1.661217f, +1.661488f, +1.661759f, +1.662030f, +1.662301f, +1.662572f, +1.662843f, +1.663114f, +1.663385f, +1.663655f, +1.663926f, +1.664197f, +1.664467f, +1.664737f, +1.665008f, +1.665278f, +1.665548f, +1.665818f, +1.666088f, +1.666358f, +1.666628f, +1.666898f, +1.667168f, +1.667437f, +1.667707f, +1.667976f, +1.668246f, +1.668515f, +1.668784f, +1.669054f, +1.669323f, +1.669592f, +1.669861f, +1.670130f, +1.670399f, +1.670667f, +1.670936f, +1.671205f, +1.671473f, +1.671742f, +1.672010f, +1.672279f, +1.672547f, +1.672815f, +1.673083f, +1.673351f, +1.673619f, +1.673887f, +1.674155f, +1.674423f, +1.674690f, +1.674958f, +1.675226f, +1.675493f, +1.675761f, +1.676028f, +1.676295f, +1.676562f, +1.676830f, +1.677097f, +1.677364f, +1.677630f, +1.677897f, +1.678164f, +1.678431f, +1.678697f, +1.678964f, +1.679230f, +1.679497f, +1.679763f, +1.680030f, +1.680296f, +1.680562f, +1.680828f, +1.681094f, +1.681360f, +1.681626f, +1.681891f, +1.682157f, +1.682423f, +1.682688f, +1.682954f, +1.683219f, +1.683485f, +1.683750f, +1.684015f, +1.684280f, +1.684545f, +1.684810f, +1.685075f, +1.685340f, +1.685605f, +1.685870f, +1.686134f, +1.686399f, +1.686663f, +1.686928f, +1.687192f, +1.687457f, +1.687721f, +1.687985f, +1.688249f, +1.688513f, +1.688777f, +1.689041f, +1.689305f, +1.689569f, +1.689832f, +1.690096f, +1.690359f, +1.690623f, +1.690886f, +1.691150f, +1.691413f, +1.691676f, +1.691939f, +1.692202f, +1.692465f, +1.692728f, +1.692991f, +1.693254f, +1.693516f, +1.693779f, +1.694042f, +1.694304f, +1.694567f, +1.694829f, +1.695091f, +1.695353f, +1.695616f, +1.695878f, +1.696140f, +1.696402f, +1.696664f, +1.696925f, +1.697187f, +1.697449f, +1.697710f, +1.697972f, +1.698233f, +1.698495f, +1.698756f, +1.699017f, +1.699279f, +1.699540f, +1.699801f, +1.700062f, +1.700323f, +1.700584f, +1.700844f, +1.701105f, +1.701366f, +1.701626f, +1.701887f, +1.702147f, +1.702408f, +1.702668f, +1.702928f, +1.703188f, +1.703449f, +1.703709f, +1.703969f, +1.704228f, +1.704488f, +1.704748f, +1.705008f, +1.705267f, +1.705527f, +1.705787f, +1.706046f, +1.706305f, +1.706565f, +1.706824f, +1.707083f, +1.707342f, +1.707601f, +1.707860f, +1.708119f, +1.708378f, +1.708637f, +1.708895f, +1.709154f, +1.709413f, +1.709671f, +1.709929f, +1.710188f, +1.710446f, +1.710704f, +1.710963f, +1.711221f, +1.711479f, +1.711737f, +1.711995f, +1.712252f, +1.712510f, +1.712768f, +1.713025f, +1.713283f, +1.713540f, +1.713798f, +1.714055f, +1.714313f, +1.714570f, +1.714827f, +1.715084f, +1.715341f, +1.715598f, +1.715855f, +1.716112f, +1.716369f, +1.716625f, +1.716882f, +1.717139f, +1.717395f, +1.717651f, +1.717908f, +1.718164f, +1.718420f, +1.718677f, +1.718933f, +1.719189f, +1.719445f, +1.719701f, +1.719957f, +1.720212f, +1.720468f, +1.720724f, +1.720979f, +1.721235f, +1.721490f, +1.721746f, +1.722001f, +1.722256f, +1.722511f, +1.722767f, +1.723022f, +1.723277f, +1.723532f, +1.723786f, +1.724041f, +1.724296f, +1.724551f, +1.724805f, +1.725060f, +1.725314f, +1.725569f, +1.725823f, +1.726077f, +1.726332f, +1.726586f, +1.726840f, +1.727094f, +1.727348f, +1.727602f, +1.727856f, +1.728109f, +1.728363f, +1.728617f, +1.728870f, +1.729124f, +1.729377f, +1.729631f, +1.729884f, +1.730137f, +1.730391f, +1.730644f, +1.730897f, +1.731150f, +1.731403f, +1.731656f, +1.731908f, +1.732161f, +1.732414f, +1.732666f, +1.732919f, +1.733171f, +1.733424f, +1.733676f, +1.733929f, +1.734181f, +1.734433f, +1.734685f, +1.734937f, +1.735189f, +1.735441f, +1.735693f, +1.735945f, +1.736196f, +1.736448f, +1.736700f, +1.736951f, +1.737203f, +1.737454f, +1.737705f, +1.737957f, +1.738208f, +1.738459f, +1.738710f, +1.738961f, +1.739212f, +1.739463f, +1.739714f, +1.739965f, +1.740216f, +1.740466f, +1.740717f, +1.740967f, +1.741218f, +1.741468f, +1.741719f, +1.741969f, +1.742219f, +1.742469f, +1.742719f, +1.742969f, +1.743219f, +1.743469f, +1.743719f, +1.743969f, +1.744219f, +1.744468f, +1.744718f, +1.744967f, +1.745217f, +1.745466f, +1.745716f, +1.745965f, +1.746214f, +1.746463f, +1.746712f, +1.746961f, +1.747210f, +1.747459f, +1.747708f, +1.747957f, +1.748206f, +1.748454f, +1.748703f, +1.748951f, +1.749200f, +1.749448f, +1.749697f, +1.749945f, +1.750193f, +1.750441f, +1.750689f, +1.750937f, +1.751185f, +1.751433f, +1.751681f, +1.751929f, +1.752177f, +1.752424f, +1.752672f, +1.752920f, +1.753167f, +1.753415f, +1.753662f, +1.753909f, +1.754156f, +1.754404f, +1.754651f, +1.754898f, +1.755145f, +1.755392f, +1.755639f, +1.755886f, +1.756132f, +1.756379f, +1.756626f, +1.756872f, +1.757119f, +1.757365f, +1.757612f, +1.757858f, +1.758104f, +1.758350f, +1.758597f, +1.758843f, +1.759089f, +1.759335f, +1.759581f, +1.759826f, +1.760072f, +1.760318f, +1.760564f, +1.760809f, +1.761055f, +1.761300f, +1.761546f, +1.761791f, +1.762036f, +1.762282f, +1.762527f, +1.762772f, +1.763017f, +1.763262f, +1.763507f, +1.763752f, +1.763997f, +1.764241f, +1.764486f, +1.764731f, +1.764975f, +1.765220f, +1.765464f, +1.765709f, +1.765953f, +1.766197f, +1.766442f, +1.766686f, +1.766930f, +1.767174f, +1.767418f, +1.767662f, +1.767906f, +1.768150f, +1.768393f, +1.768637f, +1.768881f, +1.769124f, +1.769368f, +1.769611f, +1.769855f, +1.770098f, +1.770341f, +1.770584f, +1.770828f, +1.771071f, +1.771314f, +1.771557f, +1.771800f, +1.772043f, +1.772285f, +1.772528f, +1.772771f, +1.773013f, +1.773256f, +1.773499f, +1.773741f, +1.773983f, +1.774226f, +1.774468f, +1.774710f, +1.774952f, +1.775194f, +1.775436f, +1.775678f, +1.775920f, +1.776162f, +1.776404f, +1.776646f, +1.776888f, +1.777129f, +1.777371f, +1.777612f, +1.777854f, +1.778095f, +1.778336f, +1.778578f, +1.778819f, +1.779060f, +1.779301f, +1.779542f, +1.779783f, +1.780024f, +1.780265f, +1.780506f, +1.780747f, +1.780987f, +1.781228f, +1.781469f, +1.781709f, +1.781950f, +1.782190f, +1.782430f, +1.782671f, +1.782911f, +1.783151f, +1.783391f, +1.783631f, +1.783871f, +1.784111f, +1.784351f, +1.784591f, +1.784831f, +1.785070f, +1.785310f, +1.785550f, +1.785789f, +1.786029f, +1.786268f, +1.786508f, +1.786747f, +1.786986f, +1.787225f, +1.787465f, +1.787704f, +1.787943f, +1.788182f, +1.788421f, +1.788659f, +1.788898f, +1.789137f, +1.789376f, +1.789614f, +1.789853f, +1.790091f, +1.790330f, +1.790568f, +1.790807f, +1.791045f, +1.791283f, +1.791521f, +1.791759f, +1.791998f, +1.792236f, +1.792474f, +1.792711f, +1.792949f, +1.793187f, +1.793425f, +1.793662f, +1.793900f, +1.794138f, +1.794375f, +1.794613f, +1.794850f, +1.795087f, +1.795325f, +1.795562f, +1.795799f, +1.796036f, +1.796273f, +1.796510f, +1.796747f, +1.796984f, +1.797221f, +1.797457f, +1.797694f, +1.797931f, +1.798167f, +1.798404f, +1.798641f, +1.798877f, +1.799113f, +1.799350f, +1.799586f, +1.799822f, +1.800058f, +1.800294f, +1.800530f, +1.800766f, +1.801002f, +1.801238f, +1.801474f, +1.801710f, +1.801946f, +1.802181f, +1.802417f, +1.802652f, +1.802888f, +1.803123f, +1.803359f, +1.803594f, +1.803829f, +1.804064f, +1.804300f, +1.804535f, +1.804770f, +1.805005f, +1.805240f, +1.805475f, +1.805709f, +1.805944f, +1.806179f, +1.806413f, +1.806648f, +1.806883f, +1.807117f, +1.807352f, +1.807586f, +1.807820f, +1.808055f, +1.808289f, +1.808523f, +1.808757f, +1.808991f, +1.809225f, +1.809459f, +1.809693f, +1.809927f, +1.810161f, +1.810394f, +1.810628f, +1.810862f, +1.811095f, +1.811329f, +1.811562f, +1.811795f, +1.812029f, +1.812262f, +1.812495f, +1.812729f, +1.812962f, +1.813195f, +1.813428f, +1.813661f, +1.813894f, +1.814126f, +1.814359f, +1.814592f, +1.814825f, +1.815057f, +1.815290f, +1.815522f, +1.815755f, +1.815987f, +1.816220f, +1.816452f, +1.816684f, +1.816917f, +1.817149f, +1.817381f, +1.817613f, +1.817845f, +1.818077f, +1.818309f, +1.818540f, +1.818772f, +1.819004f, +1.819236f, +1.819467f, +1.819699f, +1.819930f, +1.820162f, +1.820393f, +1.820625f, +1.820856f, +1.821087f, +1.821318f, +1.821549f, +1.821780f, +1.822012f, +1.822242f, +1.822473f, +1.822704f, +1.822935f, +1.823166f, +1.823397f, +1.823627f, +1.823858f, +1.824088f, +1.824319f, +1.824549f, +1.824780f, +1.825010f, +1.825240f, +1.825471f, +1.825701f, +1.825931f, +1.826161f, +1.826391f, +1.826621f, +1.826851f, +1.827081f, +1.827310f, +1.827540f, +1.827770f, +1.828000f, +1.828229f, +1.828459f, +1.828688f, +1.828918f, +1.829147f, +1.829376f, +1.829606f, +1.829835f, +1.830064f, +1.830293f, +1.830522f, +1.830751f, +1.830980f, +1.831209f, +1.831438f, +1.831667f, +1.831896f, +1.832124f, +1.832353f, +1.832581f, +1.832810f, +1.833039f, +1.833267f, +1.833495f, +1.833724f, +1.833952f, +1.834180f, +1.834408f, +1.834636f, +1.834865f, +1.835093f, +1.835321f, +1.835548f, +1.835776f, +1.836004f, +1.836232f, +1.836460f, +1.836687f, +1.836915f, +1.837142f, +1.837370f, +1.837597f, +1.837825f, +1.838052f, +1.838279f, +1.838507f, +1.838734f, +1.838961f, +1.839188f, +1.839415f, +1.839642f, +1.839869f, +1.840096f, +1.840323f, +1.840550f, +1.840776f, +1.841003f, +1.841230f, +1.841456f, +1.841683f, +1.841909f, +1.842136f, +1.842362f, +1.842588f, +1.842815f, +1.843041f, +1.843267f, +1.843493f, +1.843719f, +1.843945f, +1.844171f, +1.844397f, +1.844623f, +1.844849f, +1.845075f, +1.845300f, +1.845526f, +1.845751f, +1.845977f, +1.846203f, +1.846428f, +1.846653f, +1.846879f, +1.847104f, +1.847329f, +1.847555f, +1.847780f, +1.848005f, +1.848230f, +1.848455f, +1.848680f, +1.848905f, +1.849130f, +1.849354f, +1.849579f, +1.849804f, +1.850028f, +1.850253f, +1.850478f, +1.850702f, +1.850926f, +1.851151f, +1.851375f, +1.851599f, +1.851824f, +1.852048f, +1.852272f, +1.852496f, +1.852720f, +1.852944f, +1.853168f, +1.853392f, +1.853616f, +1.853840f, +1.854063f, +1.854287f, +1.854511f, +1.854734f, +1.854958f, +1.855181f, +1.855405f, +1.855628f, +1.855851f, +1.856075f, +1.856298f, +1.856521f, +1.856744f, +1.856967f, +1.857190f, +1.857413f, +1.857636f, +1.857859f, +1.858082f, +1.858305f, +1.858528f, +1.858750f, +1.858973f, +1.859196f, +1.859418f, +1.859641f, +1.859863f, +1.860085f, +1.860308f, +1.860530f, +1.860752f, +1.860975f, +1.861197f, +1.861419f, +1.861641f, +1.861863f, +1.862085f, +1.862307f, +1.862529f, +1.862750f, +1.862972f, +1.863194f, +1.863415f, +1.863637f, +1.863859f, +1.864080f, +1.864302f, +1.864523f, +1.864744f, +1.864966f, +1.865187f, +1.865408f, +1.865629f, +1.865850f, +1.866072f, +1.866293f, +1.866513f, +1.866734f, +1.866955f, +1.867176f, +1.867397f, +1.867618f, +1.867838f, +1.868059f, +1.868279f, +1.868500f, +1.868721f, +1.868941f, +1.869161f, +1.869382f, +1.869602f, +1.869822f, +1.870042f, +1.870263f, +1.870483f, +1.870703f, +1.870923f, +1.871143f, +1.871363f, +1.871582f, +1.871802f, +1.872022f, +1.872242f, +1.872461f, +1.872681f, +1.872900f, +1.873120f, +1.873339f, +1.873559f, +1.873778f, +1.873998f, +1.874217f, +1.874436f, +1.874655f, +1.874874f, +1.875093f, +1.875312f, +1.875531f, +1.875750f, +1.875969f, +1.876188f, +1.876407f, +1.876626f, +1.876844f, +1.877063f, +1.877282f, +1.877500f, +1.877719f, +1.877937f, +1.878156f, +1.878374f, +1.878592f, +1.878811f, +1.879029f, +1.879247f, +1.879465f, +1.879683f, +1.879901f, +1.880119f, +1.880337f, +1.880555f, +1.880773f, +1.880991f, +1.881208f, +1.881426f, +1.881644f, +1.881861f, +1.882079f, +1.882296f, +1.882514f, +1.882731f, +1.882949f, +1.883166f, +1.883383f, +1.883600f, +1.883818f, +1.884035f, +1.884252f, +1.884469f, +1.884686f, +1.884903f, +1.885120f, +1.885337f, +1.885553f, +1.885770f, +1.885987f, +1.886203f, +1.886420f, +1.886637f, +1.886853f, +1.887070f, +1.887286f, +1.887502f, +1.887719f, +1.887935f, +1.888151f, +1.888368f, +1.888584f, +1.888800f, +1.889016f, +1.889232f, +1.889448f, +1.889664f, +1.889880f, +1.890095f, +1.890311f, +1.890527f, +1.890743f, +1.890958f, +1.891174f, +1.891389f, +1.891605f, +1.891820f, +1.892036f, +1.892251f, +1.892466f, +1.892682f, +1.892897f, +1.893112f, +1.893327f, +1.893542f, +1.893757f, +1.893972f, +1.894187f, +1.894402f, +1.894617f, +1.894832f, +1.895046f, +1.895261f, +1.895476f, +1.895690f, +1.895905f, +1.896119f, +1.896334f, +1.896548f, +1.896763f, +1.896977f, +1.897191f, +1.897406f, +1.897620f, +1.897834f, +1.898048f, +1.898262f, +1.898476f, +1.898690f, +1.898904f, +1.899118f, +1.899332f, +1.899546f, +1.899759f, +1.899973f, +1.900187f, +1.900400f, +1.900614f, +1.900827f, +1.901041f, +1.901254f, +1.901468f, +1.901681f, +1.901894f, +1.902108f, +1.902321f, +1.902534f, +1.902747f, +1.902960f, +1.903173f, +1.903386f, +1.903599f, +1.903812f, +1.904025f, +1.904237f, +1.904450f, +1.904663f, +1.904876f, +1.905088f, +1.905301f, +1.905513f, +1.905726f, +1.905938f, +1.906151f, +1.906363f, +1.906575f, +1.906787f, +1.907000f, +1.907212f, +1.907424f, +1.907636f, +1.907848f, +1.908060f, +1.908272f, +1.908484f, +1.908696f, +1.908907f, +1.909119f, +1.909331f, +1.909543f, +1.909754f, +1.909966f, +1.910177f, +1.910389f, +1.910600f, +1.910812f, +1.911023f, +1.911234f, +1.911445f, +1.911657f, +1.911868f, +1.912079f, +1.912290f, +1.912501f, +1.912712f, +1.912923f, +1.913134f, +1.913345f, +1.913556f, +1.913766f, +1.913977f, +1.914188f, +1.914398f, +1.914609f, +1.914820f, +1.915030f, +1.915241f, +1.915451f, +1.915661f, +1.915872f, +1.916082f, +1.916292f, +1.916502f, +1.916713f, +1.916923f, +1.917133f, +1.917343f, +1.917553f, +1.917763f, +1.917972f, +1.918182f, +1.918392f, +1.918602f, +1.918812f, +1.919021f, +1.919231f, +1.919440f, +1.919650f, +1.919859f, +1.920069f, +1.920278f, +1.920488f, +1.920697f, +1.920906f, +1.921115f, +1.921325f, +1.921534f, +1.921743f, +1.921952f, +1.922161f, +1.922370f, +1.922579f, +1.922788f, +1.922997f, +1.923205f, +1.923414f, +1.923623f, +1.923831f, +1.924040f, +1.924249f, +1.924457f, +1.924666f, +1.924874f, +1.925083f, +1.925291f, +1.925499f, +1.925707f, +1.925916f, +1.926124f, +1.926332f, +1.926540f, +1.926748f, +1.926956f, +1.927164f, +1.927372f, +1.927580f, +1.927788f, +1.927996f, +1.928203f, +1.928411f, +1.928619f, +1.928826f, +1.929034f, +1.929241f, +1.929449f, +1.929656f, +1.929864f, +1.930071f, +1.930278f, +1.930486f, +1.930693f, +1.930900f, +1.931107f, +1.931314f, +1.931521f, +1.931728f, +1.931935f, +1.932142f, +1.932349f, +1.932556f, +1.932763f, +1.932970f, +1.933176f, +1.933383f, +1.933590f, +1.933796f, +1.934003f, +1.934209f, +1.934416f, +1.934622f, +1.934829f, +1.935035f, +1.935241f, +1.935447f, +1.935654f, +1.935860f, +1.936066f, +1.936272f, +1.936478f, +1.936684f, +1.936890f, +1.937096f, +1.937302f, +1.937508f, +1.937713f, +1.937919f, +1.938125f, +1.938330f, +1.938536f, +1.938742f, +1.938947f, +1.939153f, +1.939358f, +1.939564f, +1.939769f, +1.939974f, +1.940179f, +1.940385f, +1.940590f, +1.940795f, +1.941000f, +1.941205f, +1.941410f, +1.941615f, +1.941820f, +1.942025f, +1.942230f, +1.942435f, +1.942640f, +1.942844f, +1.943049f, +1.943254f, +1.943458f, +1.943663f, +1.943867f, +1.944072f, +1.944276f, +1.944481f, +1.944685f, +1.944889f, +1.945093f, +1.945298f, +1.945502f, +1.945706f, +1.945910f, +1.946114f, +1.946318f, +1.946522f, +1.946726f, +1.946930f, +1.947134f, +1.947338f, +1.947541f, +1.947745f, +1.947949f, +1.948153f, +1.948356f, +1.948560f, +1.948763f, +1.948967f, +1.949170f, +1.949374f, +1.949577f, +1.949780f, +1.949983f, +1.950187f, +1.950390f, +1.950593f, +1.950796f, +1.950999f, +1.951202f, +1.951405f, +1.951608f, +1.951811f, +1.952014f, +1.952217f, +1.952420f, +1.952622f, +1.952825f, +1.953028f, +1.953230f, +1.953433f, +1.953635f, +1.953838f, +1.954040f, +1.954243f, +1.954445f, +1.954647f, +1.954850f, +1.955052f, +1.955254f, +1.955456f, +1.955658f, +1.955860f, +1.956063f, +1.956265f, +1.956466f, +1.956668f, +1.956870f, +1.957072f, +1.957274f, +1.957476f, +1.957677f, +1.957879f, +1.958081f, +1.958282f, +1.958484f, +1.958685f, +1.958887f, +1.959088f, +1.959290f, +1.959491f, +1.959692f, +1.959894f, +1.960095f, +1.960296f, +1.960497f, +1.960698f, +1.960899f, +1.961100f, +1.961301f, +1.961502f, +1.961703f, +1.961904f, +1.962105f, +1.962306f, +1.962506f, +1.962707f, +1.962908f, +1.963108f, +1.963309f, +1.963509f, +1.963710f, +1.963910f, +1.964111f, +1.964311f, +1.964512f, +1.964712f, +1.964912f, +1.965112f, +1.965313f, +1.965513f, +1.965713f, +1.965913f, +1.966113f, +1.966313f, +1.966513f, +1.966713f, +1.966913f, +1.967112f, +1.967312f, +1.967512f, +1.967712f, +1.967911f, +1.968111f, +1.968310f, +1.968510f, +1.968709f, +1.968909f, +1.969108f, +1.969308f, +1.969507f, +1.969706f, +1.969906f, +1.970105f, +1.970304f, +1.970503f, +1.970702f, +1.970901f, +1.971100f, +1.971299f, +1.971498f, +1.971697f, +1.971896f, +1.972095f, +1.972294f, +1.972492f, +1.972691f, +1.972890f, +1.973088f, +1.973287f, +1.973486f, +1.973684f, +1.973883f, +1.974081f, +1.974279f, +1.974478f, +1.974676f, +1.974874f, +1.975073f, +1.975271f, +1.975469f, +1.975667f, +1.975865f, +1.976063f, +1.976261f, +1.976459f, +1.976657f, +1.976855f, +1.977053f, +1.977251f, +1.977448f, +1.977646f, +1.977844f, +1.978041f, +1.978239f, +1.978437f, +1.978634f, +1.978832f, +1.979029f, +1.979226f, +1.979424f, +1.979621f, +1.979819f, +1.980016f, +1.980213f, +1.980410f, +1.980607f, +1.980804f, +1.981001f, +1.981198f, +1.981395f, +1.981592f, +1.981789f, +1.981986f, +1.982183f, +1.982380f, +1.982577f, +1.982773f, +1.982970f, +1.983167f, +1.983363f, +1.983560f, +1.983756f, +1.983953f, +1.984149f, +1.984346f, +1.984542f, +1.984738f, +1.984935f, +1.985131f, +1.985327f, +1.985523f, +1.985719f, +1.985915f, +1.986112f, +1.986308f, +1.986504f, +1.986699f, +1.986895f, +1.987091f, +1.987287f, +1.987483f, +1.987679f, +1.987874f, +1.988070f, +1.988266f, +1.988461f, +1.988657f, +1.988852f, +1.989048f, +1.989243f, +1.989439f, +1.989634f, +1.989829f, +1.990025f, +1.990220f, +1.990415f, +1.990610f, +1.990805f, +1.991001f, +1.991196f, +1.991391f, +1.991586f, +1.991781f, +1.991976f, +1.992170f, +1.992365f, +1.992560f, +1.992755f, +1.992950f, +1.993144f, +1.993339f, +1.993533f, +1.993728f, +1.993923f, +1.994117f, +1.994312f, +1.994506f, +1.994700f, +1.994895f, +1.995089f, +1.995283f, +1.995477f, +1.995672f, +1.995866f, +1.996060f, +1.996254f, +1.996448f, +1.996642f, +1.996836f, +1.997030f, +1.997224f, +1.997418f, +1.997612f, +1.997805f, +1.997999f, +1.998193f, +1.998386f, +1.998580f, +1.998774f, +1.998967f, +1.999161f, +1.999354f, +1.999548f, +1.999741f, +1.999934f, +2.000128f, +2.000321f, +2.000514f, +2.000708f, +2.000901f, +2.001094f, +2.001287f, +2.001480f, +2.001673f, +2.001866f, +2.002059f, +2.002252f, +2.002445f, +2.002638f, +2.002830f, +2.003023f, +2.003216f, +2.003409f, +2.003601f, +2.003794f, +2.003987f, +2.004179f, +2.004372f, +2.004564f, +2.004756f, +2.004949f, +2.005141f, +2.005334f, +2.005526f, +2.005718f, +2.005910f, +2.006103f, +2.006295f, +2.006487f, +2.006679f, +2.006871f, +2.007063f, +2.007255f, +2.007447f, +2.007639f, +2.007830f, +2.008022f, +2.008214f, +2.008406f, +2.008597f, +2.008789f, +2.008981f, +2.009172f, +2.009364f, +2.009555f, +2.009747f, +2.009938f, +2.010130f, +2.010321f, +2.010512f, +2.010704f, +2.010895f, +2.011086f, +2.011277f, +2.011469f, +2.011660f, +2.011851f, +2.012042f, +2.012233f, +2.012424f, +2.012615f, +2.012806f, +2.012996f, +2.013187f, +2.013378f, +2.013569f, +2.013760f, +2.013950f, +2.014141f, +2.014331f, +2.014522f, +2.014713f, +2.014903f, +2.015093f, +2.015284f, +2.015474f, +2.015665f, +2.015855f, +2.016045f, +2.016235f, +2.016426f, +2.016616f, +2.016806f, +2.016996f, +2.017186f, +2.017376f, +2.017566f, +2.017756f, +2.017946f, +2.018136f, +2.018326f, +2.018516f, +2.018705f, +2.018895f, +2.019085f, +2.019274f, +2.019464f, +2.019654f, +2.019843f, +2.020033f, +2.020222f, +2.020412f, +2.020601f, +2.020790f, +2.020980f, +2.021169f, +2.021358f, +2.021548f, +2.021737f, +2.021926f, +2.022115f, +2.022304f, +2.022493f, +2.022682f, +2.022871f, +2.023060f, +2.023249f, +2.023438f, +2.023627f, +2.023816f, +2.024004f, +2.024193f, +2.024382f, +2.024570f, +2.024759f, +2.024948f, +2.025136f, +2.025325f, +2.025513f, +2.025702f, +2.025890f, +2.026078f, +2.026267f, +2.026455f, +2.026643f, +2.026832f, +2.027020f, +2.027208f, +2.027396f, +2.027584f, +2.027772f, +2.027960f, +2.028148f, +2.028336f, +2.028524f, +2.028712f, +2.028900f, +2.029088f, +2.029275f, +2.029463f, +2.029651f, +2.029839f, +2.030026f, +2.030214f, +2.030401f, +2.030589f, +2.030776f, +2.030964f, +2.031151f, +2.031339f, +2.031526f, +2.031713f, +2.031901f, +2.032088f, +2.032275f, +2.032462f, +2.032649f, +2.032836f, +2.033024f, +2.033211f, +2.033398f, +2.033585f, +2.033772f, +2.033958f, +2.034145f, +2.034332f, +2.034519f, +2.034706f, +2.034892f, +2.035079f, +2.035266f, +2.035452f, +2.035639f, +2.035825f, +2.036012f, +2.036198f, +2.036385f, +2.036571f, +2.036758f, +2.036944f, +2.037130f, +2.037317f, +2.037503f, +2.037689f, +2.037875f, +2.038061f, +2.038247f, +2.038434f, +2.038620f, +2.038806f, +2.038992f, +2.039177f, +2.039363f, +2.039549f, +2.039735f, +2.039921f, +2.040107f, +2.040292f, +2.040478f, +2.040664f, +2.040849f, +2.041035f, +2.041220f, +2.041406f, +2.041591f, +2.041777f, +2.041962f, +2.042148f, +2.042333f, +2.042518f, +2.042703f, +2.042889f, +2.043074f, +2.043259f, +2.043444f, +2.043629f, +2.043814f, +2.043999f, +2.044184f, +2.044369f, +2.044554f, +2.044739f, +2.044924f, +2.045109f, +2.045294f, +2.045478f, +2.045663f, +2.045848f, +2.046032f, +2.046217f, +2.046402f, +2.046586f, +2.046771f, +2.046955f, +2.047140f, +2.047324f, +2.047508f, +2.047693f, +2.047877f, +2.048061f, +2.048246f, +2.048430f, +2.048614f, +2.048798f, +2.048982f, +2.049166f, +2.049350f, +2.049534f, +2.049718f, +2.049902f, +2.050086f, +2.050270f, +2.050454f, +2.050638f, +2.050822f, +2.051005f, +2.051189f, +2.051373f, +2.051556f, +2.051740f, +2.051924f, +2.052107f, +2.052291f, +2.052474f, +2.052657f, +2.052841f, +2.053024f, +2.053208f, +2.053391f, +2.053574f, +2.053757f, +2.053941f, +2.054124f, +2.054307f, +2.054490f, +2.054673f, +2.054856f, +2.055039f, +2.055222f, +2.055405f, +2.055588f, +2.055771f, +2.055954f, +2.056136f, +2.056319f, +2.056502f, +2.056685f, +2.056867f, +2.057050f, +2.057232f, +2.057415f, +2.057598f, +2.057780f, +2.057963f, +2.058145f, +2.058327f, +2.058510f, +2.058692f, +2.058874f, +2.059057f, +2.059239f, +2.059421f, +2.059603f, +2.059785f, +2.059967f, +2.060149f, +2.060332f, +2.060514f, +2.060695f, +2.060877f, +2.061059f, +2.061241f, +2.061423f, +2.061605f, +2.061787f, +2.061968f, +2.062150f, +2.062332f, +2.062513f, +2.062695f, +2.062877f, +2.063058f, +2.063240f, +2.063421f, +2.063602f, +2.063784f, +2.063965f, +2.064147f, +2.064328f, +2.064509f, +2.064690f, +2.064872f, +2.065053f, +2.065234f, +2.065415f, +2.065596f, +2.065777f, +2.065958f, +2.066139f, +2.066320f, +2.066501f, +2.066682f, +2.066863f, +2.067044f, +2.067224f, +2.067405f, +2.067586f, +2.067767f, +2.067947f, +2.068128f, +2.068308f, +2.068489f, +2.068669f, +2.068850f, +2.069030f, +2.069211f, +2.069391f, +2.069572f, +2.069752f, +2.069932f, +2.070112f, +2.070293f, +2.070473f, +2.070653f, +2.070833f, +2.071013f, +2.071193f, +2.071373f, +2.071553f, +2.071733f, +2.071913f, +2.072093f, +2.072273f, +2.072453f, +2.072633f, +2.072812f, +2.072992f, +2.073172f, +2.073352f, +2.073531f, +2.073711f, +2.073890f, +2.074070f, +2.074250f, +2.074429f, +2.074608f, +2.074788f, +2.074967f, +2.075147f, +2.075326f, +2.075505f, +2.075684f, +2.075864f, +2.076043f, +2.076222f, +2.076401f, +2.076580f, +2.076759f, +2.076938f, +2.077117f, +2.077296f, +2.077475f, +2.077654f, +2.077833f, +2.078012f, +2.078191f, +2.078370f, +2.078548f, +2.078727f, +2.078906f, +2.079084f, +2.079263f, +2.079442f, +2.079620f, +2.079799f, +2.079977f, +2.080156f, +2.080334f, +2.080512f, +2.080691f, +2.080869f, +2.081047f, +2.081226f, +2.081404f, +2.081582f, +2.081760f, +2.081938f, +2.082117f, +2.082295f, +2.082473f, +2.082651f, +2.082829f, +2.083007f, +2.083185f, +2.083362f, +2.083540f, +2.083718f, +2.083896f, +2.084074f, +2.084251f, +2.084429f, +2.084607f, +2.084784f, +2.084962f, +2.085140f, +2.085317f, +2.085495f, +2.085672f, +2.085850f, +2.086027f, +2.086204f, +2.086382f, +2.086559f, +2.086736f, +2.086914f, +2.087091f, +2.087268f, +2.087445f, +2.087622f, +2.087799f, +2.087976f, +2.088153f, +2.088330f, +2.088507f, +2.088684f, +2.088861f, +2.089038f, +2.089215f, +2.089392f, +2.089569f, +2.089745f, +2.089922f, +2.090099f, +2.090275f, +2.090452f, +2.090629f, +2.090805f, +2.090982f, +2.091158f, +2.091335f, +2.091511f, +2.091688f, +2.091864f, +2.092040f, +2.092217f, +2.092393f, +2.092569f, +2.092746f, +2.092922f, +2.093098f, +2.093274f, +2.093450f, +2.093626f, +2.093802f, +2.093978f, +2.094154f, +2.094330f, +2.094506f, +2.094682f, +2.094858f, +2.095034f, +2.095209f, +2.095385f, +2.095561f, +2.095737f, +2.095912f, +2.096088f, +2.096264f, +2.096439f, +2.096615f, +2.096790f, +2.096966f, +2.097141f, +2.097317f, +2.097492f, +2.097667f, +2.097843f, +2.098018f, +2.098193f, +2.098368f, +2.098544f, +2.098719f, +2.098894f, +2.099069f, +2.099244f, +2.099419f, +2.099594f, +2.099769f, +2.099944f, +2.100119f, +2.100294f, +2.100469f, +2.100644f, +2.100819f, +2.100993f, +2.101168f, +2.101343f, +2.101517f, +2.101692f, +2.101867f, +2.102041f, +2.102216f, +2.102390f, +2.102565f, +2.102739f, +2.102914f, +2.103088f, +2.103263f, +2.103437f, +2.103611f, +2.103786f, +2.103960f, +2.104134f, +2.104308f, +2.104483f, +2.104657f, +2.104831f, +2.105005f, +2.105179f, +2.105353f, +2.105527f, +2.105701f, +2.105875f, +2.106049f, +2.106223f, +2.106396f, +2.106570f, +2.106744f, +2.106918f, +2.107091f, +2.107265f, +2.107439f, +2.107612f, +2.107786f, +2.107960f, +2.108133f, +2.108307f, +2.108480f, +2.108654f, +2.108827f, +2.109000f, +2.109174f, +2.109347f, +2.109520f, +2.109694f, +2.109867f, +2.110040f, +2.110213f, +2.110386f, +2.110559f, +2.110733f, +2.110906f, +2.111079f, +2.111252f, +2.111425f, +2.111598f, +2.111770f, +2.111943f, +2.112116f, +2.112289f, +2.112462f, +2.112635f, +2.112807f, +2.112980f, +2.113153f, +2.113325f, +2.113498f, +2.113670f, +2.113843f, +2.114015f, +2.114188f, +2.114360f, +2.114533f, +2.114705f, +2.114878f, +2.115050f, +2.115222f, +2.115395f, +2.115567f, +2.115739f, +2.115911f, +2.116083f, +2.116256f, +2.116428f, +2.116600f, +2.116772f, +2.116944f, +2.117116f, +2.117288f, +2.117460f, +2.117632f, +2.117803f, +2.117975f, +2.118147f, +2.118319f, +2.118491f, +2.118662f, +2.118834f, +2.119006f, +2.119177f, +2.119349f, +2.119520f, +2.119692f, +2.119863f, +2.120035f, +2.120206f, +2.120378f, +2.120549f, +2.120721f, +2.120892f, +2.121063f, +2.121234f, +2.121406f, +2.121577f, +2.121748f, +2.121919f, +2.122090f, +2.122262f, +2.122433f, +2.122604f, +2.122775f, +2.122946f, +2.123117f, +2.123288f, +2.123458f, +2.123629f, +2.123800f, +2.123971f, +2.124142f, +2.124312f, +2.124483f, +2.124654f, +2.124825f, +2.124995f, +2.125166f, +2.125336f, +2.125507f, +2.125677f, +2.125848f, +2.126018f, +2.126189f, +2.126359f, +2.126530f, +2.126700f, +2.126870f, +2.127041f, +2.127211f, +2.127381f, +2.127551f, +2.127721f, +2.127892f, +2.128062f, +2.128232f, +2.128402f, +2.128572f, +2.128742f, +2.128912f, +2.129082f, +2.129252f, +2.129421f, +2.129591f, +2.129761f, +2.129931f, +2.130101f, +2.130270f, +2.130440f, +2.130610f, +2.130779f, +2.130949f, +2.131119f, +2.131288f, +2.131458f, +2.131627f, +2.131797f, +2.131966f, +2.132136f, +2.132305f, +2.132474f, +2.132644f, +2.132813f, +2.132982f, +2.133152f, +2.133321f, +2.133490f, +2.133659f, +2.133828f, +2.133997f, +2.134166f, +2.134335f, +2.134505f, +2.134673f, +2.134842f, +2.135011f, +2.135180f, +2.135349f, +2.135518f, +2.135687f, +2.135856f, +2.136024f, +2.136193f, +2.136362f, +2.136531f, +2.136699f, +2.136868f, +2.137036f, +2.137205f, +2.137373f, +2.137542f, +2.137710f, +2.137879f, +2.138047f, +2.138216f, +2.138384f, +2.138552f, +2.138721f, +2.138889f, +2.139057f, +2.139225f, +2.139394f, +2.139562f, +2.139730f, +2.139898f, +2.140066f, +2.140234f, +2.140402f, +2.140570f, +2.140738f, +2.140906f, +2.141074f, +2.141242f, +2.141410f, +2.141578f, +2.141745f, +2.141913f, +2.142081f, +2.142249f, +2.142416f, +2.142584f, +2.142752f, +2.142919f, +2.143087f, +2.143254f, +2.143422f, +2.143589f, +2.143757f, +2.143924f, +2.144092f, +2.144259f, +2.144426f, +2.144594f, +2.144761f, +2.144928f, +2.145096f, +2.145263f, +2.145430f, +2.145597f, +2.145764f, +2.145931f, +2.146098f, +2.146265f, +2.146432f, +2.146599f, +2.146766f, +2.146933f, +2.147100f, +2.147267f, +2.147434f, +2.147601f, +2.147768f, +2.147934f, +2.148101f, +2.148268f, +2.148434f, +2.148601f, +2.148768f, +2.148934f, +2.149101f, +2.149267f, +2.149434f, +2.149600f, +2.149767f, +2.149933f, +2.150100f, +2.150266f, +2.150432f, +2.150599f, +2.150765f, +2.150931f, +2.151098f, +2.151264f, +2.151430f, +2.151596f, +2.151762f, +2.151928f, +2.152094f, +2.152260f, +2.152426f, +2.152592f, +2.152758f, +2.152924f, +2.153090f, +2.153256f, +2.153422f, +2.153588f, +2.153754f, +2.153919f, +2.154085f, +2.154251f, +2.154416f, +2.154582f, +2.154748f, +2.154913f, +2.155079f, +2.155245f, +2.155410f, +2.155576f, +2.155741f, +2.155906f, +2.156072f, +2.156237f, +2.156403f, +2.156568f, +2.156733f, +2.156898f, +2.157064f, +2.157229f, +2.157394f, +2.157559f, +2.157724f, +2.157890f, +2.158055f, +2.158220f, +2.158385f, +2.158550f, +2.158715f, +2.158880f, +2.159045f, +2.159209f, +2.159374f, +2.159539f, +2.159704f, +2.159869f, +2.160034f, +2.160198f, +2.160363f, +2.160528f, +2.160692f, +2.160857f, +2.161022f, +2.161186f, +2.161351f, +2.161515f, +2.161680f, +2.161844f, +2.162009f, +2.162173f, +2.162337f, +2.162502f, +2.162666f, +2.162830f, +2.162995f, +2.163159f, +2.163323f, +2.163487f, +2.163651f, +2.163816f, +2.163980f, +2.164144f, +2.164308f, +2.164472f, +2.164636f, +2.164800f, +2.164964f, +2.165128f, +2.165292f, +2.165455f, +2.165619f, +2.165783f, +2.165947f, +2.166111f, +2.166274f, +2.166438f, +2.166602f, +2.166765f, +2.166929f, +2.167093f, +2.167256f, +2.167420f, +2.167583f, +2.167747f, +2.167910f, +2.168074f, +2.168237f, +2.168400f, +2.168564f, +2.168727f, +2.168890f, +2.169054f, +2.169217f, +2.169380f, +2.169543f, +2.169707f, +2.169870f, +2.170033f, +2.170196f, +2.170359f, +2.170522f, +2.170685f, +2.170848f, +2.171011f, +2.171174f, +2.171337f, +2.171500f, +2.171663f, +2.171825f, +2.171988f, +2.172151f, +2.172314f, +2.172476f, +2.172639f, +2.172802f, +2.172964f, +2.173127f, +2.173290f, +2.173452f, +2.173615f, +2.173777f, +2.173940f, +2.174102f, +2.174265f, +2.174427f, +2.174589f, +2.174752f, +2.174914f, +2.175076f, +2.175239f, +2.175401f, +2.175563f, +2.175725f, +2.175887f, +2.176050f, +2.176212f, +2.176374f, +2.176536f, +2.176698f, +2.176860f, +2.177022f, +2.177184f, +2.177346f, +2.177508f, +2.177670f, +2.177831f, +2.177993f, +2.178155f, +2.178317f, +2.178479f, +2.178640f, +2.178802f, +2.178964f, +2.179125f, +2.179287f, +2.179448f, +2.179610f, +2.179772f, +2.179933f, +2.180095f, +2.180256f, +2.180417f, +2.180579f, +2.180740f, +2.180902f, +2.181063f, +2.181224f, +2.181386f, +2.181547f, +2.181708f, +2.181869f, +2.182030f, +2.182192f, +2.182353f, +2.182514f, +2.182675f, +2.182836f, +2.182997f, +2.183158f, +2.183319f, +2.183480f, +2.183641f, +2.183802f, +2.183962f, +2.184123f, +2.184284f, +2.184445f, +2.184606f, +2.184766f, +2.184927f, +2.185088f, +2.185248f, +2.185409f, +2.185570f, +2.185730f, +2.185891f, +2.186051f, +2.186212f, +2.186372f, +2.186533f, +2.186693f, +2.186854f, +2.187014f, +2.187174f, +2.187335f, +2.187495f, +2.187655f, +2.187815f, +2.187976f, +2.188136f, +2.188296f, +2.188456f, +2.188616f, +2.188776f, +2.188936f, +2.189096f, +2.189256f, +2.189416f, +2.189576f, +2.189736f, +2.189896f, +2.190056f, +2.190216f, +2.190376f, +2.190536f, +2.190695f, +2.190855f, +2.191015f, +2.191175f, +2.191334f, +2.191494f, +2.191654f, +2.191813f, +2.191973f, +2.192132f, +2.192292f, +2.192451f, +2.192611f, +2.192770f, +2.192930f, +2.193089f, +2.193248f, +2.193408f, +2.193567f, +2.193726f, +2.193886f, +2.194045f, +2.194204f, +2.194363f, +2.194523f, +2.194682f, +2.194841f, +2.195000f, +2.195159f, +2.195318f, +2.195477f, +2.195636f, +2.195795f, +2.195954f, +2.196113f, +2.196272f, +2.196431f, +2.196589f, +2.196748f, +2.196907f, +2.197066f, +2.197225f, +2.197383f, +2.197542f, +2.197701f, +2.197859f, +2.198018f, +2.198177f, +2.198335f, +2.198494f, +2.198652f, +2.198811f, +2.198969f, +2.199128f, +2.199286f, +2.199444f, +2.199603f, +2.199761f, +2.199919f, +2.200078f, +2.200236f, +2.200394f, +2.200552f, +2.200711f, +2.200869f, +2.201027f, +2.201185f, +2.201343f, +2.201501f, +2.201659f, +2.201817f, +2.201975f, +2.202133f, +2.202291f, +2.202449f, +2.202607f, +2.202765f, +2.202923f, +2.203080f, +2.203238f, +2.203396f, +2.203554f, +2.203711f, +2.203869f, +2.204027f, +2.204184f, +2.204342f, +2.204500f, +2.204657f, +2.204815f, +2.204972f, +2.205130f, +2.205287f, +2.205445f, +2.205602f, +2.205759f, +2.205917f, +2.206074f, +2.206232f, +2.206389f, +2.206546f, +2.206703f, +2.206861f, +2.207018f, +2.207175f, +2.207332f, +2.207489f, +2.207646f, +2.207803f, +2.207960f, +2.208117f, +2.208274f, +2.208431f, +2.208588f, +2.208745f, +2.208902f, +2.209059f, +2.209216f, +2.209373f, +2.209530f, +2.209686f, +2.209843f, +2.210000f, +2.210156f, +2.210313f, +2.210470f, +2.210626f, +2.210783f, +2.210940f, +2.211096f, +2.211253f, +2.211409f, +2.211566f, +2.211722f, +2.211879f, +2.212035f, +2.212191f, +2.212348f, +2.212504f, +2.212660f, +2.212817f, +2.212973f, +2.213129f, +2.213285f, +2.213442f, +2.213598f, +2.213754f, +2.213910f, +2.214066f, +2.214222f, +2.214378f, +2.214534f, +2.214690f, +2.214846f, +2.215002f, +2.215158f, +2.215314f, +2.215470f, +2.215626f, +2.215781f, +2.215937f, +2.216093f, +2.216249f, +2.216405f, +2.216560f, +2.216716f, +2.216872f, +2.217027f, +2.217183f, +2.217338f, +2.217494f, +2.217649f, +2.217805f, +2.217960f, +2.218116f, +2.218271f, +2.218427f, +2.218582f, +2.218738f, +2.218893f, +2.219048f, +2.219203f, +2.219359f, +2.219514f, +2.219669f, +2.219824f, +2.219980f, +2.220135f, +2.220290f, +2.220445f, +2.220600f, +2.220755f, +2.220910f, +2.221065f, +2.221220f, +2.221375f, +2.221530f, +2.221685f, +2.221840f, +2.221995f, +2.222149f, +2.222304f, +2.222459f, +2.222614f, +2.222769f, +2.222923f, +2.223078f, +2.223233f, +2.223387f, +2.223542f, +2.223696f, +2.223851f, +2.224006f, +2.224160f, +2.224315f, +2.224469f, +2.224624f, +2.224778f, +2.224932f, +2.225087f, +2.225241f, +2.225395f, +2.225550f, +2.225704f, +2.225858f, +2.226013f, +2.226167f, +2.226321f, +2.226475f, +2.226629f, +2.226783f, +2.226937f, +2.227092f, +2.227246f, +2.227400f, +2.227554f, +2.227708f, +2.227862f, +2.228015f, +2.228169f, +2.228323f, +2.228477f, +2.228631f, +2.228785f, +2.228939f, +2.229092f, +2.229246f, +2.229400f, +2.229553f, +2.229707f, +2.229861f, +2.230014f, +2.230168f, +2.230322f, +2.230475f, +2.230629f, +2.230782f, +2.230936f, +2.231089f, +2.231243f, +2.231396f, +2.231549f, +2.231703f, +2.231856f, +2.232009f, +2.232163f, +2.232316f, +2.232469f, +2.232622f, +2.232776f, +2.232929f, +2.233082f, +2.233235f, +2.233388f, +2.233541f, +2.233694f, +2.233847f, +2.234000f, +2.234153f, +2.234306f, +2.234459f, +2.234612f, +2.234765f, +2.234918f, +2.235071f, +2.235224f, +2.235376f, +2.235529f, +2.235682f, +2.235835f, +2.235987f, +2.236140f, +2.236293f, +2.236445f, +2.236598f, +2.236750f, +2.236903f, +2.237056f, +2.237208f, +2.237361f, +2.237513f, +2.237666f, +2.237818f, +2.237970f, +2.238123f, +2.238275f, +2.238427f, +2.238580f, +2.238732f, +2.238884f, +2.239037f, +2.239189f, +2.239341f, +2.239493f, +2.239645f, +2.239797f, +2.239950f, +2.240102f, +2.240254f, +2.240406f, +2.240558f, +2.240710f, +2.240862f, +2.241014f, +2.241166f, +2.241317f, +2.241469f, +2.241621f, +2.241773f, +2.241925f, +2.242077f, +2.242228f, +2.242380f, +2.242532f, +2.242683f, +2.242835f, +2.242987f, +2.243138f, +2.243290f, +2.243442f, +2.243593f, +2.243745f, +2.243896f, +2.244048f, +2.244199f, +2.244350f, +2.244502f, +2.244653f, +2.244805f, +2.244956f, +2.245107f, +2.245259f, +2.245410f, +2.245561f, +2.245712f, +2.245864f, +2.246015f, +2.246166f, +2.246317f, +2.246468f, +2.246619f, +2.246770f, +2.246921f, +2.247072f, +2.247223f, +2.247374f, +2.247525f, +2.247676f, +2.247827f, +2.247978f, +2.248129f, +2.248280f, +2.248431f, +2.248581f, +2.248732f, +2.248883f, +2.249034f, +2.249184f, +2.249335f, +2.249486f, +2.249636f, +2.249787f, +2.249937f, +2.250088f, +2.250239f, +2.250389f, +2.250540f, +2.250690f, +2.250841f, +2.250991f, +2.251141f, +2.251292f, +2.251442f, +2.251593f, +2.251743f, +2.251893f, +2.252043f, +2.252194f, +2.252344f, +2.252494f, +2.252644f, +2.252794f, +2.252945f, +2.253095f, +2.253245f, +2.253395f, +2.253545f, +2.253695f, +2.253845f, +2.253995f, +2.254145f, +2.254295f, +2.254445f, +2.254595f, +2.254744f, +2.254894f, +2.255044f, +2.255194f, +2.255344f, +2.255493f, +2.255643f, +2.255793f, +2.255943f, +2.256092f, +2.256242f, +2.256392f, +2.256541f, +2.256691f, +2.256840f, +2.256990f, +2.257139f, +2.257289f, +2.257438f, +2.257588f, +2.257737f, +2.257887f, +2.258036f, +2.258185f, +2.258335f, +2.258484f, +2.258633f, +2.258782f, +2.258932f, +2.259081f, +2.259230f, +2.259379f, +2.259528f, +2.259678f, +2.259827f, +2.259976f, +2.260125f, +2.260274f, +2.260423f, +2.260572f, +2.260721f, +2.260870f, +2.261019f, +2.261168f, +2.261317f, +2.261465f, +2.261614f, +2.261763f, +2.261912f, +2.262061f, +2.262209f, +2.262358f, +2.262507f, +2.262656f, +2.262804f, +2.262953f, +2.263101f, +2.263250f, +2.263399f, +2.263547f, +2.263696f, +2.263844f, +2.263993f, +2.264141f, +2.264290f, +2.264438f, +2.264586f, +2.264735f, +2.264883f, +2.265032f, +2.265180f, +2.265328f, +2.265476f, +2.265625f, +2.265773f, +2.265921f, +2.266069f, +2.266217f, +2.266366f, +2.266514f, +2.266662f, +2.266810f, +2.266958f, +2.267106f, +2.267254f, +2.267402f, +2.267550f, +2.267698f, +2.267846f, +2.267994f, +2.268142f, +2.268289f, +2.268437f, +2.268585f, +2.268733f, +2.268881f, +2.269028f, +2.269176f, +2.269324f, +2.269471f, +2.269619f, +2.269767f, +2.269914f, +2.270062f, +2.270209f, +2.270357f, +2.270505f, +2.270652f, +2.270800f, +2.270947f, +2.271094f, +2.271242f, +2.271389f, +2.271537f, +2.271684f, +2.271831f, +2.271979f, +2.272126f, +2.272273f, +2.272420f, +2.272568f, +2.272715f, +2.272862f, +2.273009f, +2.273156f, +2.273303f, +2.273450f, +2.273598f, +2.273745f, +2.273892f, +2.274039f, +2.274186f, +2.274333f, +2.274480f, +2.274626f, +2.274773f, +2.274920f, +2.275067f, +2.275214f, +2.275361f, +2.275507f, +2.275654f, +2.275801f, +2.275948f, +2.276094f, +2.276241f, +2.276388f, +2.276534f, +2.276681f, +2.276828f, +2.276974f, +2.277121f, +2.277267f, +2.277414f, +2.277560f, +2.277707f, +2.277853f, +2.278000f, +2.278146f, +2.278292f, +2.278439f, +2.278585f, +2.278731f, +2.278878f, +2.279024f, +2.279170f, +2.279316f, +2.279463f, +2.279609f, +2.279755f, +2.279901f, +2.280047f, +2.280193f, +2.280339f, +2.280486f, +2.280632f, +2.280778f, +2.280924f, +2.281070f, +2.281216f, +2.281361f, +2.281507f, +2.281653f, +2.281799f, +2.281945f, +2.282091f, +2.282237f, +2.282382f, +2.282528f, +2.282674f, +2.282820f, +2.282965f, +2.283111f, +2.283257f, +2.283402f, +2.283548f, +2.283693f, +2.283839f, +2.283985f, +2.284130f, +2.284276f, +2.284421f, +2.284567f, +2.284712f, +2.284857f, +2.285003f, +2.285148f, +2.285294f, +2.285439f, +2.285584f, +2.285730f, +2.285875f, +2.286020f, +2.286165f, +2.286311f, +2.286456f, +2.286601f, +2.286746f, +2.286891f, +2.287036f, +2.287181f, +2.287326f, +2.287471f, +2.287616f, +2.287761f, +2.287906f, +2.288051f, +2.288196f, +2.288341f, +2.288486f, +2.288631f, +2.288776f, +2.288921f, +2.289066f, +2.289210f, +2.289355f, +2.289500f, +2.289645f, +2.289789f, +2.289934f, +2.290079f, +2.290223f, +2.290368f, +2.290513f, +2.290657f, +2.290802f, +2.290946f, +2.291091f, +2.291235f, +2.291380f, +2.291524f, +2.291669f, +2.291813f, +2.291957f, +2.292102f, +2.292246f, +2.292390f, +2.292535f, +2.292679f, +2.292823f, +2.292968f, +2.293112f, +2.293256f, +2.293400f, +2.293544f, +2.293688f, +2.293833f, +2.293977f, +2.294121f, +2.294265f, +2.294409f, +2.294553f, +2.294697f, +2.294841f, +2.294985f, +2.295129f, +2.295273f, +2.295417f, +2.295560f, +2.295704f, +2.295848f, +2.295992f, +2.296136f, +2.296280f, +2.296423f, +2.296567f, +2.296711f, +2.296854f, +2.296998f, +2.297142f, +2.297285f, +2.297429f, +2.297573f, +2.297716f, +2.297860f, +2.298003f, +2.298147f, +2.298290f, +2.298434f, +2.298577f, +2.298720f, +2.298864f, +2.299007f, +2.299151f, +2.299294f, +2.299437f, +2.299581f, +2.299724f, +2.299867f, +2.300010f, +2.300154f, +2.300297f, +2.300440f, +2.300583f, +2.300726f, +2.300869f, +2.301012f, +2.301156f, +2.301299f, +2.301442f, +2.301585f, +2.301728f, +2.301871f, +2.302014f, +2.302156f, +2.302299f, +2.302442f, +2.302585f diff --git a/rce/rcecalib/dataproc/fit/logx_ext.dat b/rce/rcecalib/dataproc/fit/logx_ext.dat new file mode 100644 index 00000000..683d27b3 --- /dev/null +++ b/rce/rcecalib/dataproc/fit/logx_ext.dat @@ -0,0 +1,14002 @@ +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-13.122363f, +-0.000002f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.716898f, +-0.000003f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.429216f, +-0.000004f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.206073f, +-0.000005f, +-12.023751f, +-0.000006f, +-12.023751f, +-0.000006f, +-12.023751f, +-0.000006f, +-12.023751f, +-0.000006f, +-12.023751f, +-0.000006f, +-12.023751f, +-0.000006f, +-12.023751f, +-0.000006f, +-12.023751f, +-0.000006f, +-12.023751f, +-0.000006f, +-12.023751f, +-0.000006f, +-12.023751f, +-0.000006f, +-12.023751f, +-0.000006f, +-12.023751f, +-0.000006f, +-12.023751f, +-0.000006f, +-12.023751f, +-0.000006f, +-12.023751f, +-0.000006f, +-12.023751f, +-0.000006f, +-12.023751f, +-0.000006f, +-12.023751f, +-0.000006f, +-12.023751f, +-0.000006f, +-12.023751f, +-0.000006f, +-12.023751f, +-0.000006f, +-12.023751f, +-0.000006f, +-12.023751f, +-0.000006f, +-12.023751f, +-0.000006f, +-12.023751f, +-0.000006f, +-11.869600f, +-0.000007f, +-11.869600f, +-0.000007f, +-11.869600f, +-0.000007f, +-11.869600f, +-0.000007f, +-11.869600f, +-0.000007f, +-11.869600f, +-0.000007f, +-11.869600f, +-0.000007f, +-11.869600f, +-0.000007f, +-11.869600f, +-0.000007f, +-11.869600f, +-0.000007f, +-11.869600f, +-0.000007f, +-11.869600f, +-0.000007f, +-11.869600f, +-0.000007f, +-11.869600f, +-0.000007f, +-11.869600f, +-0.000007f, +-11.869600f, +-0.000007f, +-11.869600f, +-0.000007f, +-11.869600f, +-0.000007f, +-11.869600f, +-0.000007f, +-11.869600f, +-0.000007f, +-11.869600f, +-0.000007f, +-11.869600f, +-0.000007f, +-11.736069f, +-0.000008f, +-11.736069f, +-0.000008f, +-11.736069f, +-0.000008f, +-11.736069f, +-0.000008f, +-11.736069f, +-0.000008f, +-11.736069f, +-0.000008f, +-11.736069f, +-0.000008f, +-11.736069f, +-0.000008f, +-11.736069f, +-0.000008f, +-11.736069f, +-0.000008f, +-11.736069f, +-0.000008f, +-11.736069f, +-0.000008f, +-11.736069f, +-0.000008f, +-11.736069f, +-0.000008f, +-11.736069f, +-0.000008f, +-11.736069f, +-0.000008f, +-11.736069f, +-0.000008f, +-11.736069f, +-0.000008f, +-11.736069f, +-0.000008f, +-11.618286f, +-0.000009f, +-11.618286f, +-0.000009f, +-11.618286f, +-0.000009f, +-11.618286f, +-0.000009f, +-11.618286f, +-0.000009f, +-11.618286f, +-0.000009f, +-11.618286f, +-0.000009f, +-11.618286f, +-0.000009f, +-11.618286f, +-0.000009f, +-11.618286f, +-0.000009f, +-11.618286f, +-0.000009f, +-11.618286f, +-0.000009f, +-11.618286f, +-0.000009f, +-11.618286f, +-0.000009f, +-11.618286f, +-0.000009f, +-11.618286f, +-0.000009f, +-11.618286f, +-0.000009f, +-11.618286f, +-0.000009f, +-11.512925f, +-0.000010f, +-11.512925f, +-0.000010f, +-11.512925f, +-0.000010f, +-11.512925f, +-0.000010f, +-11.512925f, +-0.000010f, +-11.512925f, +-0.000010f, +-11.512925f, +-0.000010f, +-11.512925f, +-0.000010f, +-11.512925f, +-0.000010f, +-11.512925f, +-0.000010f, +-11.512925f, +-0.000010f, +-11.512925f, +-0.000010f, +-11.512925f, +-0.000010f, +-11.512925f, +-0.000010f, +-11.512925f, +-0.000010f, +-11.512925f, +-0.000010f, +-11.417615f, +-0.000011f, +-11.417615f, +-0.000011f, +-11.417615f, +-0.000011f, +-11.417615f, +-0.000011f, +-11.417615f, +-0.000011f, +-11.417615f, +-0.000011f, +-11.417615f, +-0.000011f, +-11.417615f, +-0.000011f, +-11.417615f, +-0.000011f, +-11.417615f, +-0.000011f, +-11.417615f, +-0.000011f, +-11.417615f, +-0.000011f, +-11.417615f, +-0.000011f, +-11.417615f, +-0.000011f, +-11.330604f, +-0.000012f, +-11.330604f, +-0.000012f, +-11.330604f, +-0.000012f, +-11.330604f, +-0.000012f, +-11.330604f, +-0.000012f, +-11.330604f, +-0.000012f, +-11.330604f, +-0.000012f, +-11.330604f, +-0.000012f, +-11.330604f, +-0.000012f, +-11.330604f, +-0.000012f, +-11.330604f, +-0.000012f, +-11.330604f, +-0.000012f, +-11.330604f, +-0.000012f, +-11.250561f, +-0.000013f, +-11.250561f, +-0.000013f, +-11.250561f, +-0.000013f, +-11.250561f, +-0.000013f, +-11.250561f, +-0.000013f, +-11.250561f, +-0.000013f, +-11.250561f, +-0.000013f, +-11.250561f, +-0.000013f, +-11.250561f, +-0.000013f, +-11.250561f, +-0.000013f, +-11.250561f, +-0.000013f, +-11.250561f, +-0.000013f, +-11.176453f, +-0.000014f, +-11.176453f, +-0.000014f, +-11.176453f, +-0.000014f, +-11.176453f, +-0.000014f, +-11.176453f, +-0.000014f, +-11.176453f, +-0.000014f, +-11.176453f, +-0.000014f, +-11.176453f, +-0.000014f, +-11.176453f, +-0.000014f, +-11.176453f, +-0.000014f, +-11.176453f, +-0.000014f, +-11.176453f, +-0.000014f, +-11.107460f, +-0.000015f, +-11.107460f, +-0.000015f, +-11.107460f, +-0.000015f, +-11.107460f, +-0.000015f, +-11.107460f, +-0.000015f, +-11.107460f, +-0.000015f, +-11.107460f, +-0.000015f, +-11.107460f, +-0.000015f, +-11.107460f, +-0.000015f, +-11.107460f, +-0.000015f, +-11.107460f, +-0.000015f, +-11.042922f, +-0.000016f, +-11.042922f, +-0.000016f, +-11.042922f, +-0.000016f, +-11.042922f, +-0.000016f, +-11.042922f, +-0.000016f, +-11.042922f, +-0.000016f, +-11.042922f, +-0.000016f, +-11.042922f, +-0.000016f, +-11.042922f, +-0.000016f, +-11.042922f, +-0.000016f, +-10.982297f, +-0.000017f, +-10.982297f, +-0.000017f, +-10.982297f, +-0.000017f, +-10.982297f, +-0.000017f, +-10.982297f, +-0.000017f, +-10.982297f, +-0.000017f, +-10.982297f, +-0.000017f, +-10.982297f, +-0.000017f, +-10.982297f, +-0.000017f, +-10.925139f, +-0.000018f, +-10.925139f, +-0.000018f, +-10.925139f, +-0.000018f, +-10.925139f, +-0.000018f, +-10.925139f, +-0.000018f, +-10.925139f, +-0.000018f, +-10.925139f, +-0.000018f, +-10.925139f, +-0.000018f, +-10.925139f, +-0.000018f, +-10.871072f, +-0.000019f, +-10.871072f, +-0.000019f, +-10.871072f, +-0.000019f, +-10.871072f, +-0.000019f, +-10.871072f, +-0.000019f, +-10.871072f, +-0.000019f, +-10.871072f, +-0.000019f, +-10.871072f, +-0.000019f, +-10.871072f, +-0.000019f, +-10.819778f, +-0.000020f, +-10.819778f, +-0.000020f, +-10.819778f, +-0.000020f, +-10.819778f, +-0.000020f, +-10.819778f, +-0.000020f, +-10.819778f, +-0.000020f, +-10.819778f, +-0.000020f, +-10.819778f, +-0.000020f, +-10.770988f, +-0.000021f, +-10.770988f, +-0.000021f, +-10.770988f, +-0.000021f, +-10.770988f, +-0.000021f, +-10.770988f, +-0.000021f, +-10.770988f, +-0.000021f, +-10.770988f, +-0.000021f, +-10.770988f, +-0.000021f, +-10.724468f, +-0.000022f, +-10.724468f, +-0.000022f, +-10.724468f, +-0.000022f, +-10.724468f, +-0.000022f, +-10.724468f, +-0.000022f, +-10.724468f, +-0.000022f, +-10.724468f, +-0.000022f, +-10.680016f, +-0.000023f, +-10.680016f, +-0.000023f, +-10.680016f, +-0.000023f, +-10.680016f, +-0.000023f, +-10.680016f, +-0.000023f, +-10.680016f, +-0.000023f, +-10.680016f, +-0.000023f, +-10.680016f, +-0.000023f, +-10.637457f, +-0.000024f, +-10.637457f, +-0.000024f, +-10.637457f, +-0.000024f, +-10.637457f, +-0.000024f, +-10.637457f, +-0.000024f, +-10.637457f, +-0.000024f, +-10.596635f, +-0.000025f, +-10.596635f, +-0.000025f, +-10.596635f, +-0.000025f, +-10.596635f, +-0.000025f, +-10.596635f, +-0.000025f, +-10.596635f, +-0.000025f, +-10.596635f, +-0.000025f, +-10.557414f, +-0.000026f, +-10.557414f, +-0.000026f, +-10.557414f, +-0.000026f, +-10.557414f, +-0.000026f, +-10.557414f, +-0.000026f, +-10.557414f, +-0.000026f, +-10.519674f, +-0.000027f, +-10.519674f, +-0.000027f, +-10.519674f, +-0.000027f, +-10.519674f, +-0.000027f, +-10.519674f, +-0.000027f, +-10.519674f, +-0.000027f, +-10.483306f, +-0.000028f, +-10.483306f, +-0.000028f, +-10.483306f, +-0.000028f, +-10.483306f, +-0.000028f, +-10.483306f, +-0.000028f, +-10.483306f, +-0.000028f, +-10.483306f, +-0.000028f, +-10.448215f, +-0.000029f, +-10.448215f, +-0.000029f, +-10.448215f, +-0.000029f, +-10.448215f, +-0.000029f, +-10.448215f, +-0.000029f, +-10.414313f, +-0.000030f, +-10.414313f, +-0.000030f, +-10.414313f, +-0.000030f, +-10.414313f, +-0.000030f, +-10.414313f, +-0.000030f, +-10.414313f, +-0.000030f, +-10.381523f, +-0.000031f, +-10.381523f, +-0.000031f, +-10.381523f, +-0.000031f, +-10.381523f, +-0.000031f, +-10.381523f, +-0.000031f, +-10.349775f, +-0.000032f, +-10.349775f, +-0.000032f, +-10.349775f, +-0.000032f, +-10.349775f, +-0.000032f, +-10.349775f, +-0.000032f, +-10.319003f, +-0.000033f, +-10.319003f, +-0.000033f, +-10.319003f, +-0.000033f, +-10.319003f, +-0.000033f, +-10.319003f, +-0.000033f, +-10.319003f, +-0.000033f, +-10.289150f, +-0.000034f, +-10.289150f, +-0.000034f, +-10.289150f, +-0.000034f, +-10.289150f, +-0.000034f, +-10.260162f, +-0.000035f, +-10.260162f, +-0.000035f, +-10.260162f, +-0.000035f, +-10.260162f, +-0.000035f, +-10.260162f, +-0.000035f, +-10.231992f, +-0.000036f, +-10.231992f, +-0.000036f, +-10.231992f, +-0.000036f, +-10.231992f, +-0.000036f, +-10.231992f, +-0.000036f, +-10.204593f, +-0.000037f, +-10.204593f, +-0.000037f, +-10.204593f, +-0.000037f, +-10.204593f, +-0.000037f, +-10.177924f, +-0.000038f, +-10.177924f, +-0.000038f, +-10.177924f, +-0.000038f, +-10.177924f, +-0.000038f, +-10.177924f, +-0.000038f, +-10.151949f, +-0.000039f, +-10.151949f, +-0.000039f, +-10.151949f, +-0.000039f, +-10.151949f, +-0.000039f, +-10.126631f, +-0.000040f, +-10.126631f, +-0.000040f, +-10.126631f, +-0.000040f, +-10.126631f, +-0.000040f, +-10.101939f, +-0.000041f, +-10.101939f, +-0.000041f, +-10.101939f, +-0.000041f, +-10.101939f, +-0.000041f, +-10.101939f, +-0.000041f, +-10.077841f, +-0.000042f, +-10.077841f, +-0.000042f, +-10.077841f, +-0.000042f, +-10.077841f, +-0.000042f, +-10.054310f, +-0.000043f, +-10.054310f, +-0.000043f, +-10.054310f, +-0.000043f, +-10.054310f, +-0.000043f, +-10.031321f, +-0.000044f, +-10.031321f, +-0.000044f, +-10.031321f, +-0.000044f, +-10.031321f, +-0.000044f, +-10.008848f, +-0.000045f, +-10.008848f, +-0.000045f, +-10.008848f, +-0.000045f, +-9.986869f, +-0.000046f, +-9.986869f, +-0.000046f, +-9.986869f, +-0.000046f, +-9.986869f, +-0.000046f, +-9.965363f, +-0.000047f, +-9.965363f, +-0.000047f, +-9.965363f, +-0.000047f, +-9.965363f, +-0.000047f, +-9.944310f, +-0.000048f, +-9.944310f, +-0.000048f, +-9.944310f, +-0.000048f, +-9.923690f, +-0.000049f, +-9.923690f, +-0.000049f, +-9.923690f, +-0.000049f, +-9.923690f, +-0.000049f, +-9.903488f, +-0.000050f, +-9.903488f, +-0.000050f, +-9.903488f, +-0.000050f, +-9.883685f, +-0.000051f, +-9.883685f, +-0.000051f, +-9.883685f, +-0.000051f, +-9.883685f, +-0.000051f, +-9.864267f, +-0.000052f, +-9.864267f, +-0.000052f, +-9.864267f, +-0.000052f, +-9.845219f, +-0.000053f, +-9.845219f, +-0.000053f, +-9.845219f, +-0.000053f, +-9.826527f, +-0.000054f, +-9.826527f, +-0.000054f, +-9.826527f, +-0.000054f, +-9.808177f, +-0.000055f, +-9.808177f, +-0.000055f, +-9.808177f, +-0.000055f, +-9.790159f, +-0.000056f, +-9.790159f, +-0.000056f, +-9.790159f, +-0.000056f, +-9.772459f, +-0.000057f, +-9.772459f, +-0.000057f, +-9.772459f, +-0.000057f, +-9.772459f, +-0.000057f, +-9.755068f, +-0.000058f, +-9.755068f, +-0.000058f, +-9.737973f, +-0.000059f, +-9.737973f, +-0.000059f, +-9.737973f, +-0.000059f, +-9.721166f, +-0.000060f, +-9.721166f, +-0.000060f, +-9.721166f, +-0.000060f, +-9.704637f, +-0.000061f, +-9.704637f, +-0.000061f, +-9.704637f, +-0.000061f, +-9.688376f, +-0.000062f, +-9.688376f, +-0.000062f, +-9.688376f, +-0.000062f, +-9.672376f, +-0.000063f, +-9.672376f, +-0.000063f, +-9.672376f, +-0.000063f, +-9.656627f, +-0.000064f, +-9.656627f, +-0.000064f, +-9.641123f, +-0.000065f, +-9.641123f, +-0.000065f, +-9.641123f, +-0.000065f, +-9.625856f, +-0.000066f, +-9.625856f, +-0.000066f, +-9.625856f, +-0.000066f, +-9.610818f, +-0.000067f, +-9.610818f, +-0.000067f, +-9.596003f, +-0.000068f, +-9.596003f, +-0.000068f, +-9.596003f, +-0.000068f, +-9.581404f, +-0.000069f, +-9.581404f, +-0.000069f, +-9.567015f, +-0.000070f, +-9.567015f, +-0.000070f, +-9.567015f, +-0.000070f, +-9.552831f, +-0.000071f, +-9.552831f, +-0.000071f, +-9.538844f, +-0.000072f, +-9.538844f, +-0.000072f, +-9.538844f, +-0.000072f, +-9.525051f, +-0.000073f, +-9.525051f, +-0.000073f, +-9.511445f, +-0.000074f, +-9.511445f, +-0.000074f, +-9.511445f, +-0.000074f, +-9.498022f, +-0.000075f, +-9.498022f, +-0.000075f, +-9.484777f, +-0.000076f, +-9.484777f, +-0.000076f, +-9.471705f, +-0.000077f, +-9.471705f, +-0.000077f, +-9.471705f, +-0.000077f, +-9.458802f, +-0.000078f, +-9.458802f, +-0.000078f, +-9.446063f, +-0.000079f, +-9.446063f, +-0.000079f, +-9.433484f, +-0.000080f, +-9.433484f, +-0.000080f, +-9.421061f, +-0.000081f, +-9.421061f, +-0.000081f, +-9.408791f, +-0.000082f, +-9.408791f, +-0.000082f, +-9.408791f, +-0.000082f, +-9.396670f, +-0.000083f, +-9.396670f, +-0.000083f, +-9.384694f, +-0.000084f, +-9.384694f, +-0.000084f, +-9.372859f, +-0.000085f, +-9.372859f, +-0.000085f, +-9.361163f, +-0.000086f, +-9.361163f, +-0.000086f, +-9.349602f, +-0.000087f, +-9.349602f, +-0.000087f, +-9.338174f, +-0.000088f, +-9.338174f, +-0.000088f, +-9.326874f, +-0.000089f, +-9.326874f, +-0.000089f, +-9.315701f, +-0.000090f, +-9.315701f, +-0.000090f, +-9.304651f, +-0.000091f, +-9.304651f, +-0.000091f, +-9.293722f, +-0.000092f, +-9.293722f, +-0.000092f, +-9.282911f, +-0.000093f, +-9.282911f, +-0.000093f, +-9.272216f, +-0.000094f, +-9.272216f, +-0.000094f, +-9.261634f, +-0.000095f, +-9.261634f, +-0.000095f, +-9.251162f, +-0.000096f, +-9.240800f, +-0.000097f, +-9.240800f, +-0.000097f, +-9.230543f, +-0.000098f, +-9.230543f, +-0.000098f, +-9.220391f, +-0.000099f, +-9.220391f, +-0.000099f, +-9.210340f, +-0.000100f, +-9.210340f, +-0.000100f, +-9.200390f, +-0.000101f, +-9.190538f, +-0.000102f, +-9.190538f, +-0.000102f, +-9.180782f, +-0.000103f, +-9.180782f, +-0.000103f, +-9.171120f, +-0.000104f, +-9.171120f, +-0.000104f, +-9.161550f, +-0.000105f, +-9.152071f, +-0.000106f, +-9.152071f, +-0.000106f, +-9.142682f, +-0.000107f, +-9.142682f, +-0.000107f, +-9.133379f, +-0.000108f, +-9.124163f, +-0.000109f, +-9.124163f, +-0.000109f, +-9.115030f, +-0.000110f, +-9.115030f, +-0.000110f, +-9.105980f, +-0.000111f, +-9.097012f, +-0.000112f, +-9.097012f, +-0.000112f, +-9.088123f, +-0.000113f, +-9.079312f, +-0.000114f, +-9.079312f, +-0.000114f, +-9.070578f, +-0.000115f, +-9.070578f, +-0.000115f, +-9.061920f, +-0.000116f, +-9.053337f, +-0.000117f, +-9.053337f, +-0.000117f, +-9.044826f, +-0.000118f, +-9.036387f, +-0.000119f, +-9.036387f, +-0.000119f, +-9.028019f, +-0.000120f, +-9.019720f, +-0.000121f, +-9.019720f, +-0.000121f, +-9.011490f, +-0.000122f, +-9.003326f, +-0.000123f, +-9.003326f, +-0.000123f, +-8.995229f, +-0.000124f, +-8.987197f, +-0.000125f, +-8.987197f, +-0.000125f, +-8.979229f, +-0.000126f, +-8.971323f, +-0.000127f, +-8.963480f, +-0.000128f, +-8.963480f, +-0.000128f, +-8.955698f, +-0.000129f, +-8.947976f, +-0.000130f, +-8.947976f, +-0.000130f, +-8.940313f, +-0.000131f, +-8.932709f, +-0.000132f, +-8.925161f, +-0.000133f, +-8.925161f, +-0.000133f, +-8.917671f, +-0.000134f, +-8.910236f, +-0.000135f, +-8.910236f, +-0.000135f, +-8.902856f, +-0.000136f, +-8.895530f, +-0.000137f, +-8.888257f, +-0.000138f, +-8.888257f, +-0.000138f, +-8.881037f, +-0.000139f, +-8.873868f, +-0.000140f, +-8.866751f, +-0.000141f, +-8.859683f, +-0.000142f, +-8.859683f, +-0.000142f, +-8.852666f, +-0.000143f, +-8.845697f, +-0.000144f, +-8.838777f, +-0.000145f, +-8.838777f, +-0.000145f, +-8.831904f, +-0.000146f, +-8.825078f, +-0.000147f, +-8.818298f, +-0.000148f, +-8.811564f, +-0.000149f, +-8.804875f, +-0.000150f, +-8.804875f, +-0.000150f, +-8.798231f, +-0.000151f, +-8.791630f, +-0.000152f, +-8.785073f, +-0.000153f, +-8.778558f, +-0.000154f, +-8.778558f, +-0.000154f, +-8.772085f, +-0.000155f, +-8.765655f, +-0.000156f, +-8.759265f, +-0.000157f, +-8.752916f, +-0.000158f, +-8.746606f, +-0.000159f, +-8.740337f, +-0.000160f, +-8.740337f, +-0.000160f, +-8.734106f, +-0.000161f, +-8.727914f, +-0.000162f, +-8.721760f, +-0.000163f, +-8.715644f, +-0.000164f, +-8.709565f, +-0.000165f, +-8.703523f, +-0.000166f, +-8.697517f, +-0.000167f, +-8.691547f, +-0.000168f, +-8.685612f, +-0.000169f, +-8.685612f, +-0.000169f, +-8.679712f, +-0.000170f, +-8.673847f, +-0.000171f, +-8.668016f, +-0.000172f, +-8.662219f, +-0.000173f, +-8.656455f, +-0.000174f, +-8.650725f, +-0.000175f, +-8.645027f, +-0.000176f, +-8.639361f, +-0.000177f, +-8.633727f, +-0.000178f, +-8.628125f, +-0.000179f, +-8.622554f, +-0.000180f, +-8.617014f, +-0.000181f, +-8.611504f, +-0.000182f, +-8.606024f, +-0.000183f, +-8.600575f, +-0.000184f, +-8.595155f, +-0.000185f, +-8.589764f, +-0.000186f, +-8.584402f, +-0.000187f, +-8.579069f, +-0.000188f, +-8.573764f, +-0.000189f, +-8.568486f, +-0.000190f, +-8.563237f, +-0.000191f, +-8.558015f, +-0.000192f, +-8.552820f, +-0.000193f, +-8.547652f, +-0.000194f, +-8.542511f, +-0.000195f, +-8.537396f, +-0.000196f, +-8.532307f, +-0.000197f, +-8.527244f, +-0.000198f, +-8.522206f, +-0.000199f, +-8.517193f, +-0.000200f, +-8.512206f, +-0.000201f, +-8.507243f, +-0.000202f, +-8.502305f, +-0.000203f, +-8.492501f, +-0.000205f, +-8.487634f, +-0.000206f, +-8.482792f, +-0.000207f, +-8.477972f, +-0.000208f, +-8.473176f, +-0.000209f, +-8.468403f, +-0.000210f, +-8.463652f, +-0.000211f, +-8.458924f, +-0.000212f, +-8.449535f, +-0.000214f, +-8.444873f, +-0.000215f, +-8.440232f, +-0.000216f, +-8.435613f, +-0.000217f, +-8.431015f, +-0.000218f, +-8.426439f, +-0.000219f, +-8.421883f, +-0.000220f, +-8.412833f, +-0.000222f, +-8.408339f, +-0.000223f, +-8.403864f, +-0.000224f, +-8.399410f, +-0.000225f, +-8.394976f, +-0.000226f, +-8.386165f, +-0.000228f, +-8.381789f, +-0.000229f, +-8.377431f, +-0.000230f, +-8.373093f, +-0.000231f, +-8.368773f, +-0.000232f, +-8.360189f, +-0.000234f, +-8.355925f, +-0.000235f, +-8.351679f, +-0.000236f, +-8.347450f, +-0.000237f, +-8.339047f, +-0.000239f, +-8.334872f, +-0.000240f, +-8.330714f, +-0.000241f, +-8.322449f, +-0.000243f, +-8.318342f, +-0.000244f, +-8.314252f, +-0.000245f, +-8.310179f, +-0.000246f, +-8.302082f, +-0.000248f, +-8.298058f, +-0.000249f, +-8.294050f, +-0.000250f, +-8.286081f, +-0.000252f, +-8.282121f, +-0.000253f, +-8.278176f, +-0.000254f, +-8.270333f, +-0.000256f, +-8.266434f, +-0.000257f, +-8.262551f, +-0.000258f, +-8.254829f, +-0.000260f, +-8.250990f, +-0.000261f, +-8.247166f, +-0.000262f, +-8.239561f, +-0.000264f, +-8.235781f, +-0.000265f, +-8.228262f, +-0.000267f, +-8.224524f, +-0.000268f, +-8.217089f, +-0.000270f, +-8.213392f, +-0.000271f, +-8.209708f, +-0.000272f, +-8.202382f, +-0.000274f, +-8.198739f, +-0.000275f, +-8.191493f, +-0.000277f, +-8.187889f, +-0.000278f, +-8.180721f, +-0.000280f, +-8.177156f, +-0.000281f, +-8.170064f, +-0.000283f, +-8.166536f, +-0.000284f, +-8.159519f, +-0.000286f, +-8.156028f, +-0.000287f, +-8.149084f, +-0.000289f, +-8.145630f, +-0.000290f, +-8.138757f, +-0.000292f, +-8.135338f, +-0.000293f, +-8.128535f, +-0.000295f, +-8.125151f, +-0.000296f, +-8.118417f, +-0.000298f, +-8.115067f, +-0.000299f, +-8.108400f, +-0.000301f, +-8.105084f, +-0.000302f, +-8.098483f, +-0.000304f, +-8.091925f, +-0.000306f, +-8.088663f, +-0.000307f, +-8.082169f, +-0.000309f, +-8.078938f, +-0.000310f, +-8.072507f, +-0.000312f, +-8.066118f, +-0.000314f, +-8.062938f, +-0.000315f, +-8.056609f, +-0.000317f, +-8.050319f, +-0.000319f, +-8.047190f, +-0.000320f, +-8.040959f, +-0.000322f, +-8.034767f, +-0.000324f, +-8.031685f, +-0.000325f, +-8.025550f, +-0.000327f, +-8.019453f, +-0.000329f, +-8.016418f, +-0.000330f, +-8.010376f, +-0.000332f, +-8.004370f, +-0.000334f, +-8.001380f, +-0.000335f, +-7.995428f, +-0.000337f, +-7.989510f, +-0.000339f, +-7.983628f, +-0.000341f, +-7.980700f, +-0.000342f, +-7.974869f, +-0.000344f, +-7.969072f, +-0.000346f, +-7.963308f, +-0.000348f, +-7.957577f, +-0.000350f, +-7.954724f, +-0.000351f, +-7.949042f, +-0.000353f, +-7.943393f, +-0.000355f, +-7.937775f, +-0.000357f, +-7.932188f, +-0.000359f, +-7.926633f, +-0.000361f, +-7.923866f, +-0.000362f, +-7.918357f, +-0.000364f, +-7.912877f, +-0.000366f, +-7.907428f, +-0.000368f, +-7.902008f, +-0.000370f, +-7.896617f, +-0.000372f, +-7.891255f, +-0.000374f, +-7.885921f, +-0.000376f, +-7.880616f, +-0.000378f, +-7.875339f, +-0.000380f, +-7.870090f, +-0.000382f, +-7.864868f, +-0.000384f, +-7.862267f, +-0.000385f, +-7.857086f, +-0.000387f, +-7.851931f, +-0.000389f, +-7.846803f, +-0.000391f, +-7.841701f, +-0.000393f, +-7.834096f, +-0.000396f, +-7.829059f, +-0.000398f, +-7.824046f, +-0.000400f, +-7.819058f, +-0.000402f, +-7.814096f, +-0.000404f, +-7.809157f, +-0.000406f, +-7.804243f, +-0.000408f, +-7.799353f, +-0.000410f, +-7.794487f, +-0.000412f, +-7.789645f, +-0.000414f, +-7.784825f, +-0.000416f, +-7.780029f, +-0.000418f, +-7.775256f, +-0.000420f, +-7.768138f, +-0.000423f, +-7.763421f, +-0.000425f, +-7.758727f, +-0.000427f, +-7.754054f, +-0.000429f, +-7.749402f, +-0.000431f, +-7.742466f, +-0.000434f, +-7.737868f, +-0.000436f, +-7.733292f, +-0.000438f, +-7.728736f, +-0.000440f, +-7.724201f, +-0.000442f, +-7.717436f, +-0.000445f, +-7.712952f, +-0.000447f, +-7.708488f, +-0.000449f, +-7.704043f, +-0.000451f, +-7.697413f, +-0.000454f, +-7.693018f, +-0.000456f, +-7.688641f, +-0.000458f, +-7.682113f, +-0.000461f, +-7.677783f, +-0.000463f, +-7.673473f, +-0.000465f, +-7.667042f, +-0.000468f, +-7.662778f, +-0.000470f, +-7.658532f, +-0.000472f, +-7.652196f, +-0.000475f, +-7.647994f, +-0.000477f, +-7.641724f, +-0.000480f, +-7.637566f, +-0.000482f, +-7.631362f, +-0.000485f, +-7.627246f, +-0.000487f, +-7.623148f, +-0.000489f, +-7.617032f, +-0.000492f, +-7.612975f, +-0.000494f, +-7.606921f, +-0.000497f, +-7.602904f, +-0.000499f, +-7.596910f, +-0.000502f, +-7.592934f, +-0.000504f, +-7.587000f, +-0.000507f, +-7.581100f, +-0.000510f, +-7.577186f, +-0.000512f, +-7.571344f, +-0.000515f, +-7.567468f, +-0.000517f, +-7.561682f, +-0.000520f, +-7.557843f, +-0.000522f, +-7.552112f, +-0.000525f, +-7.546414f, +-0.000528f, +-7.542634f, +-0.000530f, +-7.536989f, +-0.000533f, +-7.531376f, +-0.000536f, +-7.527652f, +-0.000538f, +-7.522091f, +-0.000541f, +-7.516561f, +-0.000544f, +-7.511062f, +-0.000547f, +-7.507412f, +-0.000549f, +-7.501962f, +-0.000552f, +-7.496542f, +-0.000555f, +-7.491152f, +-0.000558f, +-7.487574f, +-0.000560f, +-7.482231f, +-0.000563f, +-7.476916f, +-0.000566f, +-7.471630f, +-0.000569f, +-7.466372f, +-0.000572f, +-7.462881f, +-0.000574f, +-7.457668f, +-0.000577f, +-7.452482f, +-0.000580f, +-7.447323f, +-0.000583f, +-7.442191f, +-0.000586f, +-7.437084f, +-0.000589f, +-7.432004f, +-0.000592f, +-7.426949f, +-0.000595f, +-7.421920f, +-0.000598f, +-7.416916f, +-0.000601f, +-7.411936f, +-0.000604f, +-7.406982f, +-0.000607f, +-7.402052f, +-0.000610f, +-7.397146f, +-0.000613f, +-7.392264f, +-0.000616f, +-7.387405f, +-0.000619f, +-7.382570f, +-0.000622f, +-7.377759f, +-0.000625f, +-7.372970f, +-0.000628f, +-7.368205f, +-0.000631f, +-7.363462f, +-0.000634f, +-7.358741f, +-0.000637f, +-7.352481f, +-0.000641f, +-7.347812f, +-0.000644f, +-7.343164f, +-0.000647f, +-7.338538f, +-0.000650f, +-7.333933f, +-0.000653f, +-7.327827f, +-0.000657f, +-7.323271f, +-0.000660f, +-7.318736f, +-0.000663f, +-7.314221f, +-0.000666f, +-7.308233f, +-0.000670f, +-7.303765f, +-0.000673f, +-7.299317f, +-0.000676f, +-7.293418f, +-0.000680f, +-7.289016f, +-0.000683f, +-7.284633f, +-0.000686f, +-7.278819f, +-0.000690f, +-7.274481f, +-0.000693f, +-7.270161f, +-0.000696f, +-7.264430f, +-0.000700f, +-7.260154f, +-0.000703f, +-7.254480f, +-0.000707f, +-7.250246f, +-0.000710f, +-7.244628f, +-0.000714f, +-7.240435f, +-0.000717f, +-7.234871f, +-0.000721f, +-7.230719f, +-0.000724f, +-7.225209f, +-0.000728f, +-7.221097f, +-0.000731f, +-7.215640f, +-0.000735f, +-7.210213f, +-0.000739f, +-7.206161f, +-0.000742f, +-7.200785f, +-0.000746f, +-7.196772f, +-0.000749f, +-7.191445f, +-0.000753f, +-7.186147f, +-0.000757f, +-7.182192f, +-0.000760f, +-7.176943f, +-0.000764f, +-7.171721f, +-0.000768f, +-7.166526f, +-0.000772f, +-7.162647f, +-0.000775f, +-7.157500f, +-0.000779f, +-7.152378f, +-0.000783f, +-7.147282f, +-0.000787f, +-7.142213f, +-0.000791f, +-7.138427f, +-0.000794f, +-7.133402f, +-0.000798f, +-7.128402f, +-0.000802f, +-7.123427f, +-0.000806f, +-7.118476f, +-0.000810f, +-7.113550f, +-0.000814f, +-7.108648f, +-0.000818f, +-7.103770f, +-0.000822f, +-7.098916f, +-0.000826f, +-7.094085f, +-0.000830f, +-7.089277f, +-0.000834f, +-7.084492f, +-0.000838f, +-7.079731f, +-0.000842f, +-7.074991f, +-0.000846f, +-7.070274f, +-0.000850f, +-7.065579f, +-0.000854f, +-7.060906f, +-0.000858f, +-7.055096f, +-0.000863f, +-7.050472f, +-0.000867f, +-7.045869f, +-0.000871f, +-7.041287f, +-0.000875f, +-7.036726f, +-0.000879f, +-7.031054f, +-0.000884f, +-7.026539f, +-0.000888f, +-7.022044f, +-0.000892f, +-7.017570f, +-0.000896f, +-7.012005f, +-0.000901f, +-7.007576f, +-0.000905f, +-7.003165f, +-0.000909f, +-6.997680f, +-0.000914f, +-6.993313f, +-0.000918f, +-6.987881f, +-0.000923f, +-6.983557f, +-0.000927f, +-6.979251f, +-0.000931f, +-6.973895f, +-0.000936f, +-6.969631f, +-0.000940f, +-6.964326f, +-0.000945f, +-6.960102f, +-0.000949f, +-6.954847f, +-0.000954f, +-6.949619f, +-0.000959f, +-6.945457f, +-0.000963f, +-6.940278f, +-0.000968f, +-6.936155f, +-0.000972f, +-6.931024f, +-0.000977f, +-6.925919f, +-0.000982f, +-6.921854f, +-0.000986f, +-6.916796f, +-0.000991f, +-6.911763f, +-0.000996f, +-6.906756f, +-0.001002f, +-6.902768f, +-0.001006f, +-6.897805f, +-0.001011f, +-6.892867f, +-0.001016f, +-6.887953f, +-0.001021f, +-6.883063f, +-0.001026f, +-6.878196f, +-0.001031f, +-6.874321f, +-0.001035f, +-6.869497f, +-0.001040f, +-6.864696f, +-0.001045f, +-6.859918f, +-0.001050f, +-6.855163f, +-0.001055f, +-6.850430f, +-0.001060f, +-6.845720f, +-0.001065f, +-6.841032f, +-0.001070f, +-6.836365f, +-0.001075f, +-6.830794f, +-0.001081f, +-6.826175f, +-0.001086f, +-6.821578f, +-0.001091f, +-6.817001f, +-0.001096f, +-6.812445f, +-0.001101f, +-6.807910f, +-0.001106f, +-6.802495f, +-0.001112f, +-6.798004f, +-0.001117f, +-6.793534f, +-0.001122f, +-6.789084f, +-0.001127f, +-6.783769f, +-0.001133f, +-6.779362f, +-0.001138f, +-6.774974f, +-0.001143f, +-6.769734f, +-0.001149f, +-6.765388f, +-0.001154f, +-6.760198f, +-0.001160f, +-6.755893f, +-0.001165f, +-6.750752f, +-0.001171f, +-6.746487f, +-0.001176f, +-6.741394f, +-0.001182f, +-6.737169f, +-0.001187f, +-6.732123f, +-0.001193f, +-6.727937f, +-0.001198f, +-6.722937f, +-0.001204f, +-6.717962f, +-0.001210f, +-6.713835f, +-0.001215f, +-6.708904f, +-0.001221f, +-6.703998f, +-0.001227f, +-6.699116f, +-0.001233f, +-6.695066f, +-0.001238f, +-6.690227f, +-0.001244f, +-6.685412f, +-0.001250f, +-6.680620f, +-0.001256f, +-6.675850f, +-0.001262f, +-6.671103f, +-0.001268f, +-6.666379f, +-0.001274f, +-6.662459f, +-0.001279f, +-6.657775f, +-0.001285f, +-6.653113f, +-0.001291f, +-6.648473f, +-0.001297f, +-6.643086f, +-0.001304f, +-6.638492f, +-0.001310f, +-6.633919f, +-0.001316f, +-6.629366f, +-0.001322f, +-6.624835f, +-0.001328f, +-6.620323f, +-0.001334f, +-6.615832f, +-0.001340f, +-6.610618f, +-0.001347f, +-6.606170f, +-0.001353f, +-6.601742f, +-0.001359f, +-6.597334f, +-0.001365f, +-6.592215f, +-0.001372f, +-6.587848f, +-0.001378f, +-6.582777f, +-0.001385f, +-6.578452f, +-0.001391f, +-6.573428f, +-0.001398f, +-6.569142f, +-0.001404f, +-6.564875f, +-0.001410f, +-6.559919f, +-0.001417f, +-6.554988f, +-0.001424f, +-6.550780f, +-0.001430f, +-6.545894f, +-0.001437f, +-6.541724f, +-0.001443f, +-6.536882f, +-0.001450f, +-6.532062f, +-0.001457f, +-6.527266f, +-0.001464f, +-6.523173f, +-0.001470f, +-6.518420f, +-0.001477f, +-6.513688f, +-0.001484f, +-6.508979f, +-0.001491f, +-6.504292f, +-0.001498f, +-6.500292f, +-0.001504f, +-6.495646f, +-0.001511f, +-6.491021f, +-0.001518f, +-6.486417f, +-0.001525f, +-6.481834f, +-0.001532f, +-6.477272f, +-0.001539f, +-6.472084f, +-0.001547f, +-6.467567f, +-0.001554f, +-6.463069f, +-0.001561f, +-6.458592f, +-0.001568f, +-6.454135f, +-0.001575f, +-6.449698f, +-0.001582f, +-6.444650f, +-0.001590f, +-6.440255f, +-0.001597f, +-6.435878f, +-0.001604f, +-6.430900f, +-0.001612f, +-6.426564f, +-0.001619f, +-6.422247f, +-0.001626f, +-6.417336f, +-0.001634f, +-6.413059f, +-0.001641f, +-6.408193f, +-0.001649f, +-6.403954f, +-0.001656f, +-6.399132f, +-0.001664f, +-6.394932f, +-0.001671f, +-6.390153f, +-0.001679f, +-6.385396f, +-0.001687f, +-6.381253f, +-0.001694f, +-6.376539f, +-0.001702f, +-6.371847f, +-0.001710f, +-6.367177f, +-0.001718f, +-6.362528f, +-0.001726f, +-6.358478f, +-0.001734f, +-6.353870f, +-0.001742f, +-6.349283f, +-0.001750f, +-6.344717f, +-0.001758f, +-6.340171f, +-0.001766f, +-6.335646f, +-0.001774f, +-6.331142f, +-0.001782f, +-6.326658f, +-0.001790f, +-6.322193f, +-0.001798f, +-6.317195f, +-0.001807f, +-6.312772f, +-0.001815f, +-6.308369f, +-0.001823f, +-6.303986f, +-0.001831f, +-6.299621f, +-0.001839f, +-6.294734f, +-0.001848f, +-6.290410f, +-0.001856f, +-6.285567f, +-0.001865f, +-6.281282f, +-0.001873f, +-6.277016f, +-0.001881f, +-6.272237f, +-0.001890f, +-6.268009f, +-0.001898f, +-6.263273f, +-0.001907f, +-6.258560f, +-0.001916f, +-6.254389f, +-0.001924f, +-6.249717f, +-0.001933f, +-6.245067f, +-0.001942f, +-6.240952f, +-0.001950f, +-6.236343f, +-0.001959f, +-6.231754f, +-0.001968f, +-6.227187f, +-0.001977f, +-6.222640f, +-0.001986f, +-6.218114f, +-0.001995f, +-6.214108f, +-0.002003f, +-6.209621f, +-0.002012f, +-6.204658f, +-0.002022f, +-6.200212f, +-0.002031f, +-6.195786f, +-0.002040f, +-6.191380f, +-0.002049f, +-6.186993f, +-0.002058f, +-6.182625f, +-0.002067f, +-6.178276f, +-0.002076f, +-6.173466f, +-0.002086f, +-6.169157f, +-0.002095f, +-6.164866f, +-0.002104f, +-6.160120f, +-0.002114f, +-6.155868f, +-0.002123f, +-6.151164f, +-0.002133f, +-6.146949f, +-0.002142f, +-6.142287f, +-0.002152f, +-6.138110f, +-0.002161f, +-6.133489f, +-0.002171f, +-6.128889f, +-0.002181f, +-6.124767f, +-0.002190f, +-6.120207f, +-0.002200f, +-6.115668f, +-0.002210f, +-6.111149f, +-0.002220f, +-6.106651f, +-0.002230f, +-6.102173f, +-0.002241f, +-6.097714f, +-0.002251f, +-6.093719f, +-0.002260f, +-6.088857f, +-0.002271f, +-6.084457f, +-0.002281f, +-6.080077f, +-0.002291f, +-6.075716f, +-0.002301f, +-6.071374f, +-0.002311f, +-6.067051f, +-0.002321f, +-6.062316f, +-0.002332f, +-6.058032f, +-0.002342f, +-6.053766f, +-0.002352f, +-6.049094f, +-0.002363f, +-6.044865f, +-0.002373f, +-6.040235f, +-0.002384f, +-6.036044f, +-0.002394f, +-6.031454f, +-0.002405f, +-6.027299f, +-0.002415f, +-6.022749f, +-0.002426f, +-6.018219f, +-0.002437f, +-6.014119f, +-0.002447f, +-6.009628f, +-0.002458f, +-6.005158f, +-0.002469f, +-6.000707f, +-0.002480f, +-5.996276f, +-0.002491f, +-5.991865f, +-0.002502f, +-5.987473f, +-0.002513f, +-5.983100f, +-0.002524f, +-5.978746f, +-0.002535f, +-5.974411f, +-0.002546f, +-5.970095f, +-0.002557f, +-5.965797f, +-0.002568f, +-5.961517f, +-0.002579f, +-5.956870f, +-0.002591f, +-5.952629f, +-0.002602f, +-5.948022f, +-0.002614f, +-5.943818f, +-0.002625f, +-5.939631f, +-0.002636f, +-5.935084f, +-0.002649f, +-5.930558f, +-0.002661f, +-5.926426f, +-0.002672f, +-5.921939f, +-0.002684f, +-5.917471f, +-0.002696f, +-5.913393f, +-0.002707f, +-5.908963f, +-0.002719f, +-5.904553f, +-0.002731f, +-5.900162f, +-0.002743f, +-5.895791f, +-0.002755f, +-5.891438f, +-0.002767f, +-5.887105f, +-0.002779f, +-5.882790f, +-0.002791f, +-5.878493f, +-0.002803f, +-5.874215f, +-0.002815f, +-5.869955f, +-0.002827f, +-5.865361f, +-0.002840f, +-5.861138f, +-0.002852f, +-5.856934f, +-0.002864f, +-5.852399f, +-0.002877f, +-5.848230f, +-0.002889f, +-5.843734f, +-0.002902f, +-5.839602f, +-0.002914f, +-5.835145f, +-0.002927f, +-5.830707f, +-0.002940f, +-5.826628f, +-0.002952f, +-5.822228f, +-0.002965f, +-5.817847f, +-0.002978f, +-5.813486f, +-0.002991f, +-5.809143f, +-0.003005f, +-5.804819f, +-0.003018f, +-5.800514f, +-0.003031f, +-5.796227f, +-0.003044f, +-5.791958f, +-0.003057f, +-5.787708f, +-0.003070f, +-5.783475f, +-0.003083f, +-5.779261f, +-0.003096f, +-5.774742f, +-0.003110f, +-5.770564f, +-0.003123f, +-5.766083f, +-0.003137f, +-5.761941f, +-0.003150f, +-5.757500f, +-0.003164f, +-5.753393f, +-0.003177f, +-5.748989f, +-0.003191f, +-5.744917f, +-0.003204f, +-5.740550f, +-0.003218f, +-5.736202f, +-0.003232f, +-5.731873f, +-0.003246f, +-5.727563f, +-0.003260f, +-5.723271f, +-0.003274f, +-5.718998f, +-0.003288f, +-5.714742f, +-0.003302f, +-5.710505f, +-0.003316f, +-5.706286f, +-0.003331f, +-5.702084f, +-0.003345f, +-5.697602f, +-0.003360f, +-5.693436f, +-0.003374f, +-5.689288f, +-0.003388f, +-5.684863f, +-0.003403f, +-5.680750f, +-0.003417f, +-5.676362f, +-0.003432f, +-5.672284f, +-0.003446f, +-5.667933f, +-0.003461f, +-5.663601f, +-0.003476f, +-5.659287f, +-0.003491f, +-5.655278f, +-0.003505f, +-5.651000f, +-0.003520f, +-5.646741f, +-0.003535f, +-5.642499f, +-0.003550f, +-5.638276f, +-0.003565f, +-5.634070f, +-0.003580f, +-5.629603f, +-0.003596f, +-5.625434f, +-0.003612f, +-5.621281f, +-0.003627f, +-5.617146f, +-0.003642f, +-5.612754f, +-0.003658f, +-5.608654f, +-0.003673f, +-5.604299f, +-0.003689f, +-5.600234f, +-0.003704f, +-5.595915f, +-0.003720f, +-5.591615f, +-0.003736f, +-5.587334f, +-0.003752f, +-5.583336f, +-0.003767f, +-5.579090f, +-0.003783f, +-5.574862f, +-0.003799f, +-5.570651f, +-0.003815f, +-5.566458f, +-0.003831f, +-5.562283f, +-0.003847f, +-5.557866f, +-0.003864f, +-5.553726f, +-0.003881f, +-5.549603f, +-0.003897f, +-5.545498f, +-0.003913f, +-5.541154f, +-0.003930f, +-5.537082f, +-0.003946f, +-5.532775f, +-0.003963f, +-5.528486f, +-0.003980f, +-5.524465f, +-0.003996f, +-5.520212f, +-0.004013f, +-5.515976f, +-0.004030f, +-5.511758f, +-0.004047f, +-5.507558f, +-0.004064f, +-5.503375f, +-0.004081f, +-5.499210f, +-0.004098f, +-5.495062f, +-0.004115f, +-5.490932f, +-0.004133f, +-5.486818f, +-0.004150f, +-5.482721f, +-0.004167f, +-5.478401f, +-0.004185f, +-5.474339f, +-0.004202f, +-5.470055f, +-0.004220f, +-5.466026f, +-0.004237f, +-5.461778f, +-0.004255f, +-5.457548f, +-0.004273f, +-5.453335f, +-0.004291f, +-5.449373f, +-0.004308f, +-5.445195f, +-0.004326f, +-5.441034f, +-0.004344f, +-5.436890f, +-0.004363f, +-5.432763f, +-0.004381f, +-5.428426f, +-0.004400f, +-5.424334f, +-0.004418f, +-5.420259f, +-0.004436f, +-5.416200f, +-0.004454f, +-5.411934f, +-0.004473f, +-5.407909f, +-0.004491f, +-5.403678f, +-0.004510f, +-5.399465f, +-0.004529f, +-5.395489f, +-0.004547f, +-5.391310f, +-0.004566f, +-5.387149f, +-0.004585f, +-5.383004f, +-0.004605f, +-5.378877f, +-0.004624f, +-5.374767f, +-0.004643f, +-5.370673f, +-0.004662f, +-5.366596f, +-0.004681f, +-5.362323f, +-0.004701f, +-5.358280f, +-0.004720f, +-5.354253f, +-0.004739f, +-5.350032f, +-0.004759f, +-5.346038f, +-0.004778f, +-5.341851f, +-0.004798f, +-5.337682f, +-0.004819f, +-5.333530f, +-0.004839f, +-5.329602f, +-0.004858f, +-5.325483f, +-0.004878f, +-5.321381f, +-0.004898f, +-5.317296f, +-0.004918f, +-5.313025f, +-0.004939f, +-5.308974f, +-0.004959f, +-5.304939f, +-0.004979f, +-5.300921f, +-0.004999f, +-5.296719f, +-0.005021f, +-5.292733f, +-0.005041f, +-5.288565f, +-0.005062f, +-5.284414f, +-0.005083f, +-5.280477f, +-0.005103f, +-5.276360f, +-0.005124f, +-5.272260f, +-0.005145f, +-5.268176f, +-0.005166f, +-5.264109f, +-0.005187f, +-5.260059f, +-0.005209f, +-5.256024f, +-0.005230f, +-5.251816f, +-0.005252f, +-5.247814f, +-0.005273f, +-5.243829f, +-0.005294f, +-5.239671f, +-0.005316f, +-5.235530f, +-0.005338f, +-5.231594f, +-0.005359f, +-5.227486f, +-0.005381f, +-5.223395f, +-0.005404f, +-5.219321f, +-0.005426f, +-5.215264f, +-0.005448f, +-5.211223f, +-0.005470f, +-5.207198f, +-0.005492f, +-5.203189f, +-0.005514f, +-5.199196f, +-0.005536f, +-5.195039f, +-0.005559f, +-5.191079f, +-0.005582f, +-5.186955f, +-0.005605f, +-5.183026f, +-0.005627f, +-5.178936f, +-0.005650f, +-5.174862f, +-0.005673f, +-5.170804f, +-0.005696f, +-5.166763f, +-0.005719f, +-5.162738f, +-0.005742f, +-5.158729f, +-0.005766f, +-5.154737f, +-0.005789f, +-5.150760f, +-0.005812f, +-5.146627f, +-0.005836f, +-5.142682f, +-0.005859f, +-5.138582f, +-0.005883f, +-5.134669f, +-0.005906f, +-5.130602f, +-0.005931f, +-5.126551f, +-0.005955f, +-5.122517f, +-0.005979f, +-5.118666f, +-0.006002f, +-5.114497f, +-0.006027f, +-5.110511f, +-0.006051f, +-5.106541f, +-0.006075f, +-5.102586f, +-0.006100f, +-5.098483f, +-0.006125f, +-5.094561f, +-0.006149f, +-5.090491f, +-0.006174f, +-5.086599f, +-0.006198f, +-5.082561f, +-0.006223f, +-5.078539f, +-0.006248f, +-5.074534f, +-0.006274f, +-5.070545f, +-0.006299f, +-5.066571f, +-0.006324f, +-5.062613f, +-0.006349f, +-5.058671f, +-0.006374f, +-5.054744f, +-0.006399f, +-5.050676f, +-0.006426f, +-5.046781f, +-0.006451f, +-5.042745f, +-0.006477f, +-5.038726f, +-0.006503f, +-5.034877f, +-0.006528f, +-5.030889f, +-0.006554f, +-5.026917f, +-0.006581f, +-5.022961f, +-0.006607f, +-5.018869f, +-0.006634f, +-5.014945f, +-0.006660f, +-5.011035f, +-0.006686f, +-5.006992f, +-0.006713f, +-5.003114f, +-0.006740f, +-4.999102f, +-0.006767f, +-4.995254f, +-0.006793f, +-4.991274f, +-0.006820f, +-4.987309f, +-0.006847f, +-4.983361f, +-0.006875f, +-4.979427f, +-0.006902f, +-4.975509f, +-0.006929f, +-4.971463f, +-0.006957f, +-4.967576f, +-0.006984f, +-4.963561f, +-0.007013f, +-4.959705f, +-0.007040f, +-4.955721f, +-0.007068f, +-4.951753f, +-0.007096f, +-4.947942f, +-0.007123f, +-4.944005f, +-0.007152f, +-4.940084f, +-0.007180f, +-4.936038f, +-0.007209f, +-4.932148f, +-0.007237f, +-4.928272f, +-0.007265f, +-4.924274f, +-0.007295f, +-4.920429f, +-0.007323f, +-4.916462f, +-0.007352f, +-4.912647f, +-0.007380f, +-4.908711f, +-0.007409f, +-4.904790f, +-0.007439f, +-4.900884f, +-0.007468f, +-4.896994f, +-0.007497f, +-4.892986f, +-0.007527f, +-4.889126f, +-0.007556f, +-4.885281f, +-0.007586f, +-4.881319f, +-0.007616f, +-4.877373f, +-0.007646f, +-4.873573f, +-0.007675f, +-4.869657f, +-0.007706f, +-4.865756f, +-0.007736f, +-4.861870f, +-0.007766f, +-4.858000f, +-0.007796f, +-4.854144f, +-0.007827f, +-4.850176f, +-0.007858f, +-4.846350f, +-0.007888f, +-4.842413f, +-0.007919f, +-4.838490f, +-0.007951f, +-4.834709f, +-0.007981f, +-4.830817f, +-0.008012f, +-4.826940f, +-0.008043f, +-4.823077f, +-0.008075f, +-4.819230f, +-0.008106f, +-4.815274f, +-0.008138f, +-4.811457f, +-0.008169f, +-4.807531f, +-0.008202f, +-4.803743f, +-0.008233f, +-4.799848f, +-0.008265f, +-4.795968f, +-0.008297f, +-4.792102f, +-0.008330f, +-4.788252f, +-0.008362f, +-4.784416f, +-0.008394f, +-4.780596f, +-0.008426f, +-4.776671f, +-0.008460f, +-4.772879f, +-0.008492f, +-4.768984f, +-0.008525f, +-4.765222f, +-0.008558f, +-4.761356f, +-0.008591f, +-4.757506f, +-0.008624f, +-4.753670f, +-0.008657f, +-4.749849f, +-0.008691f, +-4.745928f, +-0.008725f, +-4.742136f, +-0.008758f, +-4.738245f, +-0.008793f, +-4.734482f, +-0.008826f, +-4.730620f, +-0.008860f, +-4.726773f, +-0.008894f, +-4.722941f, +-0.008929f, +-4.719123f, +-0.008963f, +-4.715320f, +-0.008997f, +-4.711531f, +-0.009032f, +-4.707646f, +-0.009067f, +-4.703886f, +-0.009101f, +-4.700030f, +-0.009137f, +-4.696190f, +-0.009172f, +-4.692473f, +-0.009206f, +-4.688661f, +-0.009242f, +-4.684863f, +-0.009277f, +-4.680972f, +-0.009313f, +-4.677203f, +-0.009349f, +-4.673449f, +-0.009384f, +-4.669602f, +-0.009420f, +-4.665770f, +-0.009457f, +-4.661952f, +-0.009493f, +-4.658255f, +-0.009528f, +-4.654360f, +-0.009566f, +-4.650586f, +-0.009602f, +-4.646826f, +-0.009638f, +-4.643080f, +-0.009675f, +-4.639244f, +-0.009712f, +-4.635423f, +-0.009749f, +-4.631720f, +-0.009786f, +-4.627927f, +-0.009823f, +-4.624149f, +-0.009860f, +-4.620385f, +-0.009898f, +-4.616535f, +-0.009936f, +-4.612799f, +-0.009974f, +-4.609078f, +-0.010011f, +-4.605270f, +-0.010049f, +-4.601477f, +-0.010088f, +-4.597698f, +-0.010126f, +-4.593934f, +-0.010164f, +-4.590183f, +-0.010203f, +-4.586447f, +-0.010241f, +-4.582724f, +-0.010280f, +-4.578918f, +-0.010319f, +-4.575126f, +-0.010358f, +-4.571445f, +-0.010397f, +-4.567682f, +-0.010436f, +-4.563932f, +-0.010476f, +-4.560197f, +-0.010515f, +-4.556380f, +-0.010556f, +-4.552673f, +-0.010595f, +-4.548884f, +-0.010635f, +-4.545205f, +-0.010675f, +-4.541445f, +-0.010715f, +-4.537698f, +-0.010756f, +-4.533966f, +-0.010796f, +-4.530248f, +-0.010837f, +-4.526544f, +-0.010877f, +-4.522761f, +-0.010918f, +-4.519084f, +-0.010959f, +-4.515329f, +-0.011000f, +-4.511589f, +-0.011042f, +-4.507862f, +-0.011083f, +-4.504149f, +-0.011125f, +-4.500450f, +-0.011166f, +-4.496675f, +-0.011209f, +-4.493003f, +-0.011250f, +-4.489256f, +-0.011293f, +-4.485611f, +-0.011334f, +-4.481891f, +-0.011376f, +-4.478185f, +-0.011419f, +-4.474405f, +-0.011462f, +-4.470727f, +-0.011505f, +-4.467062f, +-0.011547f, +-4.463323f, +-0.011591f, +-4.459599f, +-0.011634f, +-4.455975f, +-0.011677f, +-4.452277f, +-0.011720f, +-4.448508f, +-0.011765f, +-4.444839f, +-0.011808f, +-4.441182f, +-0.011852f, +-4.437455f, +-0.011896f, +-4.433825f, +-0.011940f, +-4.430125f, +-0.011985f, +-4.426438f, +-0.012029f, +-4.422765f, +-0.012074f, +-4.419023f, +-0.012119f, +-4.415377f, +-0.012164f, +-4.411661f, +-0.012209f, +-4.408042f, +-0.012254f, +-4.404354f, +-0.012299f, +-4.400680f, +-0.012345f, +-4.397018f, +-0.012390f, +-4.393371f, +-0.012436f, +-4.389656f, +-0.012483f, +-4.386035f, +-0.012528f, +-4.382347f, +-0.012575f, +-4.378672f, +-0.012621f, +-4.375011f, +-0.012668f, +-4.371364f, +-0.012714f, +-4.367729f, +-0.012761f, +-4.364108f, +-0.012808f, +-4.360422f, +-0.012855f, +-4.356749f, +-0.012903f, +-4.353089f, +-0.012950f, +-4.349443f, +-0.012998f, +-4.345810f, +-0.013046f, +-4.342191f, +-0.013093f, +-4.338584f, +-0.013141f, +-4.334914f, +-0.013190f, +-4.331257f, +-0.013238f, +-4.327614f, +-0.013287f, +-4.323984f, +-0.013336f, +-4.320367f, +-0.013384f, +-4.316763f, +-0.013433f, +-4.313098f, +-0.013482f, +-4.309520f, +-0.013531f, +-4.305881f, +-0.013581f, +-4.302255f, +-0.013630f, +-4.298642f, +-0.013680f, +-4.294969f, +-0.013731f, +-4.291382f, +-0.013781f, +-4.287735f, +-0.013831f, +-4.284174f, +-0.013881f, +-4.280554f, +-0.013932f, +-4.276946f, +-0.013982f, +-4.273352f, +-0.014033f, +-4.269698f, +-0.014085f, +-4.266130f, +-0.014135f, +-4.262503f, +-0.014187f, +-4.258889f, +-0.014239f, +-4.255288f, +-0.014291f, +-4.251700f, +-0.014342f, +-4.248125f, +-0.014394f, +-4.244493f, +-0.014447f, +-4.240944f, +-0.014499f, +-4.237338f, +-0.014551f, +-4.233745f, +-0.014604f, +-4.230164f, +-0.014657f, +-4.226597f, +-0.014710f, +-4.222974f, +-0.014763f, +-4.219432f, +-0.014816f, +-4.215834f, +-0.014870f, +-4.212250f, +-0.014924f, +-4.208679f, +-0.014978f, +-4.205120f, +-0.015031f, +-4.201573f, +-0.015085f, +-4.197973f, +-0.015140f, +-4.194386f, +-0.015195f, +-4.190811f, +-0.015250f, +-4.187250f, +-0.015305f, +-4.183700f, +-0.015359f, +-4.180164f, +-0.015414f, +-4.176575f, +-0.015470f, +-4.172998f, +-0.015526f, +-4.169499f, +-0.015581f, +-4.165948f, +-0.015637f, +-4.162345f, +-0.015694f, +-4.158819f, +-0.015749f, +-4.155242f, +-0.015806f, +-4.151741f, +-0.015862f, +-4.148189f, +-0.015919f, +-4.144649f, +-0.015976f, +-4.141059f, +-0.016034f, +-4.137544f, +-0.016091f, +-4.133980f, +-0.016149f, +-4.130490f, +-0.016206f, +-4.126950f, +-0.016264f, +-4.123423f, +-0.016321f, +-4.119847f, +-0.016380f, +-4.116345f, +-0.016438f, +-4.112794f, +-0.016497f, +-4.109316f, +-0.016555f, +-4.105790f, +-0.016614f, +-4.102216f, +-0.016674f, +-4.098714f, +-0.016733f, +-4.095225f, +-0.016792f, +-4.091688f, +-0.016852f, +-4.088164f, +-0.016912f, +-4.084652f, +-0.016972f, +-4.081152f, +-0.017032f, +-4.077664f, +-0.017092f, +-4.074130f, +-0.017153f, +-4.070608f, +-0.017214f, +-4.067099f, +-0.017275f, +-4.063602f, +-0.017336f, +-4.060117f, +-0.017397f, +-4.056644f, +-0.017459f, +-4.053126f, +-0.017521f, +-4.049620f, +-0.017583f, +-4.046126f, +-0.017645f, +-4.042644f, +-0.017707f, +-4.039175f, +-0.017769f, +-4.035661f, +-0.017832f, +-4.032159f, +-0.017895f, +-4.028669f, +-0.017958f, +-4.025192f, +-0.018021f, +-4.021726f, +-0.018085f, +-4.018273f, +-0.018148f, +-4.014776f, +-0.018212f, +-4.011291f, +-0.018276f, +-4.007818f, +-0.018340f, +-4.004358f, +-0.018404f, +-4.000854f, +-0.018470f, +-3.997417f, +-0.018534f, +-3.993938f, +-0.018599f, +-3.990471f, +-0.018664f, +-3.987016f, +-0.018729f, +-3.983573f, +-0.018795f, +-3.980088f, +-0.018861f, +-3.976615f, +-0.018927f, +-3.973154f, +-0.018993f, +-3.969705f, +-0.019059f, +-3.966268f, +-0.019126f, +-3.962843f, +-0.019192f, +-3.959377f, +-0.019259f, +-3.955923f, +-0.019327f, +-3.952480f, +-0.019394f, +-3.949050f, +-0.019461f, +-3.945580f, +-0.019529f, +-3.942173f, +-0.019597f, +-3.938726f, +-0.019665f, +-3.935292f, +-0.019733f, +-3.931818f, +-0.019803f, +-3.928407f, +-0.019871f, +-3.924956f, +-0.019940f, +-3.921568f, +-0.020009f, +-3.918142f, +-0.020078f, +-3.914677f, +-0.020149f, +-3.911273f, +-0.020218f, +-3.907832f, +-0.020288f, +-3.904452f, +-0.020358f, +-3.900984f, +-0.020429f, +-3.897578f, +-0.020500f, +-3.894183f, +-0.020570f, +-3.890751f, +-0.020642f, +-3.887330f, +-0.020713f, +-3.883922f, +-0.020785f, +-3.880524f, +-0.020856f, +-3.877139f, +-0.020927f, +-3.873716f, +-0.021000f, +-3.870305f, +-0.021072f, +-3.866906f, +-0.021145f, +-3.863519f, +-0.021218f, +-3.860142f, +-0.021290f, +-3.856730f, +-0.021364f, +-3.853330f, +-0.021437f, +-3.849941f, +-0.021511f, +-3.846563f, +-0.021584f, +-3.843150f, +-0.021659f, +-3.839795f, +-0.021732f, +-3.836405f, +-0.021807f, +-3.833027f, +-0.021882f, +-3.829614f, +-0.021957f, +-3.826258f, +-0.022032f, +-3.822868f, +-0.022108f, +-3.819489f, +-0.022183f, +-3.816122f, +-0.022259f, +-3.812721f, +-0.022336f, +-3.809376f, +-0.022411f, +-3.805998f, +-0.022488f, +-3.802631f, +-0.022565f, +-3.799275f, +-0.022641f, +-3.795886f, +-0.022719f, +-3.792552f, +-0.022796f, +-3.789186f, +-0.022874f, +-3.785831f, +-0.022951f, +-3.782487f, +-0.023029f, +-3.779111f, +-0.023108f, +-3.775745f, +-0.023187f, +-3.772392f, +-0.023266f, +-3.769049f, +-0.023344f, +-3.765717f, +-0.023423f, +-3.762354f, +-0.023503f, +-3.759002f, +-0.023583f, +-3.755661f, +-0.023663f, +-3.752331f, +-0.023743f, +-3.749012f, +-0.023823f, +-3.745661f, +-0.023903f, +-3.742322f, +-0.023984f, +-3.738994f, +-0.024065f, +-3.735678f, +-0.024146f, +-3.732330f, +-0.024228f, +-3.728993f, +-0.024310f, +-3.725668f, +-0.024392f, +-3.722354f, +-0.024474f, +-3.719009f, +-0.024557f, +-3.715716f, +-0.024639f, +-3.712394f, +-0.024722f, +-3.709082f, +-0.024805f, +-3.705741f, +-0.024889f, +-3.702451f, +-0.024972f, +-3.699132f, +-0.025056f, +-3.695824f, +-0.025140f, +-3.692486f, +-0.025226f, +-3.689199f, +-0.025310f, +-3.685884f, +-0.025395f, +-3.682579f, +-0.025480f, +-3.679286f, +-0.025565f, +-3.676003f, +-0.025650f, +-3.672691f, +-0.025736f, +-3.669391f, +-0.025823f, +-3.666101f, +-0.025909f, +-3.662822f, +-0.025995f, +-3.659515f, +-0.026082f, +-3.656219f, +-0.026169f, +-3.652933f, +-0.026257f, +-3.649659f, +-0.026344f, +-3.646356f, +-0.026432f, +-3.643065f, +-0.026521f, +-3.639785f, +-0.026609f, +-3.636515f, +-0.026697f, +-3.633256f, +-0.026786f, +-3.629969f, +-0.026875f, +-3.626694f, +-0.026964f, +-3.623429f, +-0.027054f, +-3.620137f, +-0.027144f, +-3.616894f, +-0.027233f, +-3.613624f, +-0.027324f, +-3.610364f, +-0.027414f, +-3.607078f, +-0.027506f, +-3.603840f, +-0.027596f, +-3.600576f, +-0.027688f, +-3.597322f, +-0.027779f, +-3.594042f, +-0.027872f, +-3.590809f, +-0.027963f, +-3.587551f, +-0.028056f, +-3.584303f, +-0.028148f, +-3.581066f, +-0.028241f, +-3.577803f, +-0.028335f, +-3.574551f, +-0.028428f, +-3.571310f, +-0.028522f, +-3.568079f, +-0.028616f, +-3.564823f, +-0.028710f, +-3.561577f, +-0.028805f, +-3.558343f, +-0.028900f, +-3.555118f, +-0.028994f, +-3.551904f, +-0.029089f, +-3.548665f, +-0.029185f, +-3.545437f, +-0.029281f, +-3.542185f, +-0.029377f, +-3.538978f, +-0.029473f, +-3.535746f, +-0.029570f, +-3.532525f, +-0.029667f, +-3.529315f, +-0.029764f, +-3.526081f, +-0.029861f, +-3.522857f, +-0.029959f, +-3.519643f, +-0.030057f, +-3.516440f, +-0.030155f, +-3.513213f, +-0.030254f, +-3.510031f, +-0.030352f, +-3.506825f, +-0.030451f, +-3.503596f, +-0.030551f, +-3.500410f, +-0.030650f, +-3.497202f, +-0.030750f, +-3.494004f, +-0.030850f, +-3.490783f, +-0.030951f, +-3.487605f, +-0.031051f, +-3.484405f, +-0.031152f, +-3.481215f, +-0.031253f, +-3.478003f, +-0.031355f, +-3.474833f, +-0.031457f, +-3.471641f, +-0.031559f, +-3.468428f, +-0.031662f, +-3.465256f, +-0.031764f, +-3.462063f, +-0.031867f, +-3.458879f, +-0.031971f, +-3.455706f, +-0.032074f, +-3.452543f, +-0.032177f, +-3.449359f, +-0.032281f, +-3.446184f, +-0.032386f, +-3.443020f, +-0.032490f, +-3.439834f, +-0.032596f, +-3.436659f, +-0.032701f, +-3.433493f, +-0.032806f, +-3.430338f, +-0.032912f, +-3.427162f, +-0.033018f, +-3.423995f, +-0.033125f, +-3.420839f, +-0.033231f, +-3.417693f, +-0.033338f, +-3.414526f, +-0.033445f, +-3.411369f, +-0.033553f, +-3.408222f, +-0.033660f, +-3.405055f, +-0.033769f, +-3.401898f, +-0.033877f, +-3.398750f, +-0.033986f, +-3.395613f, +-0.034095f, +-3.392456f, +-0.034204f, +-3.389338f, +-0.034313f, +-3.386171f, +-0.034424f, +-3.383043f, +-0.034533f, +-3.379896f, +-0.034644f, +-3.376758f, +-0.034755f, +-3.373631f, +-0.034866f, +-3.370513f, +-0.034977f, +-3.367376f, +-0.035088f, +-3.364248f, +-0.035200f, +-3.361102f, +-0.035313f, +-3.357994f, +-0.035425f, +-3.354867f, +-0.035538f, +-3.351750f, +-0.035651f, +-3.348614f, +-0.035765f, +-3.345488f, +-0.035879f, +-3.342372f, +-0.035993f, +-3.339265f, +-0.036107f, +-3.336140f, +-0.036222f, +-3.333053f, +-0.036336f, +-3.329919f, +-0.036452f, +-3.326823f, +-0.036568f, +-3.323709f, +-0.036684f, +-3.320604f, +-0.036800f, +-3.317509f, +-0.036916f, +-3.314396f, +-0.037033f, +-3.311293f, +-0.037151f, +-3.308199f, +-0.037268f, +-3.305115f, +-0.037385f, +-3.302013f, +-0.037504f, +-3.298921f, +-0.037622f, +-3.295838f, +-0.037740f, +-3.292738f, +-0.037860f, +-3.289647f, +-0.037979f, +-3.286566f, +-0.038099f, +-3.283494f, +-0.038218f, +-3.280406f, +-0.038339f, +-3.277326f, +-0.038459f, +-3.274230f, +-0.038581f, +-3.271170f, +-0.038701f, +-3.268092f, +-0.038823f, +-3.265024f, +-0.038945f, +-3.261940f, +-0.039067f, +-3.258865f, +-0.039190f, +-3.255799f, +-0.039313f, +-3.252743f, +-0.039435f, +-3.249670f, +-0.039559f, +-3.246607f, +-0.039683f, +-3.243553f, +-0.039807f, +-3.240483f, +-0.039932f, +-3.237422f, +-0.040057f, +-3.234370f, +-0.040182f, +-3.231303f, +-0.040308f, +-3.228270f, +-0.040432f, +-3.225221f, +-0.040558f, +-3.222156f, +-0.040686f, +-3.219126f, +-0.040812f, +-3.216080f, +-0.040939f, +-3.213018f, +-0.041067f, +-3.209990f, +-0.041194f, +-3.206947f, +-0.041322f, +-3.203913f, +-0.041450f, +-3.200864f, +-0.041580f, +-3.197824f, +-0.041709f, +-3.194793f, +-0.041838f, +-3.191771f, +-0.041967f, +-3.188735f, +-0.042098f, +-3.185707f, +-0.042228f, +-3.182689f, +-0.042359f, +-3.179655f, +-0.042490f, +-3.176631f, +-0.042622f, +-3.173616f, +-0.042753f, +-3.170586f, +-0.042886f, +-3.167565f, +-0.043018f, +-3.164553f, +-0.043151f, +-3.161527f, +-0.043284f, +-3.158534f, +-0.043417f, +-3.155502f, +-0.043552f, +-3.152503f, +-0.043685f, +-3.149490f, +-0.043820f, +-3.146485f, +-0.043955f, +-3.143490f, +-0.044090f, +-3.140481f, +-0.044226f, +-3.137480f, +-0.044362f, +-3.134489f, +-0.044497f, +-3.131483f, +-0.044634f, +-3.128487f, +-0.044771f, +-3.125499f, +-0.044908f, +-3.122498f, +-0.045047f, +-3.119506f, +-0.045185f, +-3.116522f, +-0.045323f, +-3.113548f, +-0.045461f, +-3.110560f, +-0.045600f, +-3.107558f, +-0.045740f, +-3.104588f, +-0.045880f, +-3.101604f, +-0.046020f, +-3.098629f, +-0.046160f, +-3.095663f, +-0.046301f, +-3.092684f, +-0.046442f, +-3.089713f, +-0.046583f, +-3.086730f, +-0.046726f, +-3.083755f, +-0.046868f, +-3.080789f, +-0.047011f, +-3.077832f, +-0.047153f, +-3.074862f, +-0.047297f, +-3.071901f, +-0.047441f, +-3.068948f, +-0.047584f, +-3.065983f, +-0.047729f, +-3.063027f, +-0.047874f, +-3.060079f, +-0.048019f, +-3.057118f, +-0.048165f, +-3.054167f, +-0.048310f, +-3.051203f, +-0.048457f, +-3.048268f, +-0.048603f, +-3.045322f, +-0.048750f, +-3.042363f, +-0.048898f, +-3.039433f, +-0.049045f, +-3.036492f, +-0.049193f, +-3.033538f, +-0.049343f, +-3.030614f, +-0.049491f, +-3.027677f, +-0.049640f, +-3.024729f, +-0.049790f, +-3.021809f, +-0.049939f, +-3.018878f, +-0.050090f, +-3.015935f, +-0.050241f, +-3.013021f, +-0.050392f, +-3.010075f, +-0.050544f, +-3.007157f, +-0.050696f, +-3.004228f, +-0.050848f, +-3.001308f, +-0.051001f, +-2.998396f, +-0.051153f, +-2.995472f, +-0.051307f, +-2.992557f, +-0.051461f, +-2.989651f, +-0.051614f, +-2.986733f, +-0.051769f, +-2.983823f, +-0.051924f, +-2.980922f, +-0.052079f, +-2.978010f, +-0.052235f, +-2.975106f, +-0.052391f, +-2.972192f, +-0.052548f, +-2.969305f, +-0.052704f, +-2.966387f, +-0.052862f, +-2.963497f, +-0.053019f, +-2.960597f, +-0.053177f, +-2.957705f, +-0.053335f, +-2.954802f, +-0.053495f, +-2.951926f, +-0.053653f, +-2.949020f, +-0.053813f, +-2.946142f, +-0.053973f, +-2.943254f, +-0.054133f, +-2.940373f, +-0.054294f, +-2.937482f, +-0.054455f, +-2.934600f, +-0.054617f, +-2.931725f, +-0.054778f, +-2.928840f, +-0.054941f, +-2.925964f, +-0.055104f, +-2.923095f, +-0.055266f, +-2.920217f, +-0.055430f, +-2.917346f, +-0.055594f, +-2.914484f, +-0.055758f, +-2.911612f, +-0.055923f, +-2.908748f, +-0.056088f, +-2.905873f, +-0.056254f, +-2.903025f, +-0.056419f, +-2.900149f, +-0.056586f, +-2.897300f, +-0.056752f, +-2.894440f, +-0.056920f, +-2.891588f, +-0.057087f, +-2.888727f, +-0.057255f, +-2.885874f, +-0.057424f, +-2.883029f, +-0.057592f, +-2.880174f, +-0.057762f, +-2.877327f, +-0.057931f, +-2.874489f, +-0.058101f, +-2.871640f, +-0.058271f, +-2.868800f, +-0.058442f, +-2.865950f, +-0.058614f, +-2.863126f, +-0.058784f, +-2.860275f, +-0.058957f, +-2.857450f, +-0.059129f, +-2.854615f, +-0.059302f, +-2.851788f, +-0.059475f, +-2.848952f, +-0.059649f, +-2.846123f, +-0.059823f, +-2.843303f, +-0.059997f, +-2.840474f, +-0.060173f, +-2.837652f, +-0.060348f, +-2.834822f, +-0.060524f, +-2.831999f, +-0.060701f, +-2.829185f, +-0.060877f, +-2.826378f, +-0.061053f, +-2.823562f, +-0.061231f, +-2.820737f, +-0.061410f, +-2.817938f, +-0.061587f, +-2.815129f, +-0.061766f, +-2.812311f, +-0.061946f, +-2.809502f, +-0.062125f, +-2.806700f, +-0.062305f, +-2.803906f, +-0.062485f, +-2.801103f, +-0.062666f, +-2.798292f, +-0.062848f, +-2.795505f, +-0.063029f, +-2.792710f, +-0.063211f, +-2.789906f, +-0.063395f, +-2.787126f, +-0.063577f, +-2.784321f, +-0.063761f, +-2.781541f, +-0.063945f, +-2.778752f, +-0.064129f, +-2.775970f, +-0.064313f, +-2.773181f, +-0.064499f, +-2.770399f, +-0.064685f, +-2.767625f, +-0.064870f, +-2.764843f, +-0.065057f, +-2.762068f, +-0.065244f, +-2.759286f, +-0.065432f, +-2.756511f, +-0.065620f, +-2.753743f, +-0.065808f, +-2.750968f, +-0.065997f, +-2.748201f, +-0.066186f, +-2.745441f, +-0.066375f, +-2.742673f, +-0.066565f, +-2.739912f, +-0.066755f, +-2.737144f, +-0.066947f, +-2.734384f, +-0.067138f, +-2.731631f, +-0.067330f, +-2.728870f, +-0.067522f, +-2.726117f, +-0.067715f, +-2.723357f, +-0.067908f, +-2.720604f, +-0.068102f, +-2.717858f, +-0.068296f, +-2.715105f, +-0.068491f, +-2.712359f, +-0.068686f, +-2.709621f, +-0.068881f, +-2.706876f, +-0.069077f, +-2.704138f, +-0.069273f, +-2.701392f, +-0.069470f, +-2.698655f, +-0.069667f, +-2.695924f, +-0.069865f, +-2.693186f, +-0.070063f, +-2.690456f, +-0.070262f, +-2.687718f, +-0.070461f, +-2.684988f, +-0.070661f, +-2.682266f, +-0.070860f, +-2.679536f, +-0.071061f, +-2.676813f, +-0.071262f, +-2.674098f, +-0.071463f, +-2.671376f, +-0.071665f, +-2.668647f, +-0.071868f, +-2.665939f, +-0.072070f, +-2.663211f, +-0.072274f, +-2.660504f, +-0.072477f, +-2.657790f, +-0.072681f, +-2.655083f, +-0.072886f, +-2.652370f, +-0.073091f, +-2.649663f, +-0.073297f, +-2.646950f, +-0.073503f, +-2.644259f, +-0.073709f, +-2.641546f, +-0.073917f, +-2.638855f, +-0.074124f, +-2.636158f, +-0.074331f, +-2.633453f, +-0.074540f, +-2.630756f, +-0.074749f, +-2.628066f, +-0.074958f, +-2.625369f, +-0.075169f, +-2.622680f, +-0.075379f, +-2.619998f, +-0.075589f, +-2.617310f, +-0.075801f, +-2.614614f, +-0.076013f, +-2.611940f, +-0.076225f, +-2.609260f, +-0.076437f, +-2.606573f, +-0.076651f, +-2.603893f, +-0.076865f, +-2.601220f, +-0.077079f, +-2.598541f, +-0.077294f, +-2.595870f, +-0.077509f, +-2.593191f, +-0.077725f, +-2.590534f, +-0.077940f, +-2.587857f, +-0.078157f, +-2.585187f, +-0.078375f, +-2.582524f, +-0.078592f, +-2.579868f, +-0.078809f, +-2.577206f, +-0.079028f, +-2.574538f, +-0.079248f, +-2.571877f, +-0.079468f, +-2.569223f, +-0.079687f, +-2.566577f, +-0.079907f, +-2.563924f, +-0.080128f, +-2.561265f, +-0.080350f, +-2.558613f, +-0.080573f, +-2.555969f, +-0.080795f, +-2.553318f, +-0.081018f, +-2.550675f, +-0.081242f, +-2.548038f, +-0.081465f, +-2.545396f, +-0.081690f, +-2.542748f, +-0.081915f, +-2.540119f, +-0.082140f, +-2.537472f, +-0.082367f, +-2.534845f, +-0.082593f, +-2.532212f, +-0.082820f, +-2.529574f, +-0.083048f, +-2.526954f, +-0.083275f, +-2.524317f, +-0.083504f, +-2.521699f, +-0.083733f, +-2.519076f, +-0.083962f, +-2.516447f, +-0.084193f, +-2.513825f, +-0.084423f, +-2.511210f, +-0.084654f, +-2.508589f, +-0.084886f, +-2.505975f, +-0.085118f, +-2.503356f, +-0.085351f, +-2.500743f, +-0.085584f, +-2.498138f, +-0.085817f, +-2.495527f, +-0.086051f, +-2.492911f, +-0.086287f, +-2.490313f, +-0.086521f, +-2.487711f, +-0.086757f, +-2.485103f, +-0.086994f, +-2.482502f, +-0.087230f, +-2.479907f, +-0.087467f, +-2.477308f, +-0.087705f, +-2.474703f, +-0.087944f, +-2.472117f, +-0.088182f, +-2.469526f, +-0.088421f, +-2.466929f, +-0.088662f, +-2.464340f, +-0.088902f, +-2.461757f, +-0.089143f, +-2.459169f, +-0.089384f, +-2.456587f, +-0.089626f, +-2.454001f, +-0.089869f, +-2.451422f, +-0.090112f, +-2.448837f, +-0.090356f, +-2.446259f, +-0.090600f, +-2.443688f, +-0.090844f, +-2.441112f, +-0.091089f, +-2.438542f, +-0.091335f, +-2.435968f, +-0.091581f, +-2.433400f, +-0.091828f, +-2.430828f, +-0.092076f, +-2.428262f, +-0.092324f, +-2.425702f, +-0.092572f, +-2.423138f, +-0.092821f, +-2.420581f, +-0.093070f, +-2.418018f, +-0.093320f, +-2.415463f, +-0.093570f, +-2.412902f, +-0.093822f, +-2.410349f, +-0.094073f, +-2.407801f, +-0.094325f, +-2.405249f, +-0.094578f, +-2.402704f, +-0.094831f, +-2.400154f, +-0.095085f, +-2.397610f, +-0.095339f, +-2.395062f, +-0.095594f, +-2.392521f, +-0.095849f, +-2.389975f, +-0.096106f, +-2.387446f, +-0.096361f, +-2.384902f, +-0.096619f, +-2.382365f, +-0.096877f, +-2.379833f, +-0.097134f, +-2.377298f, +-0.097393f, +-2.374769f, +-0.097653f, +-2.372246f, +-0.097912f, +-2.369719f, +-0.098172f, +-2.367188f, +-0.098433f, +-2.364663f, +-0.098695f, +-2.362144f, +-0.098957f, +-2.359621f, +-0.099219f, +-2.357105f, +-0.099482f, +-2.354584f, +-0.099746f, +-2.352069f, +-0.100010f, +-2.349551f, +-0.100276f, +-2.347039f, +-0.100541f, +-2.344533f, +-0.100806f, +-2.342023f, +-0.101073f, +-2.339519f, +-0.101340f, +-2.337011f, +-0.101608f, +-2.334509f, +-0.101875f, +-2.332004f, +-0.102145f, +-2.329504f, +-0.102414f, +-2.327001f, +-0.102684f, +-2.324504f, +-0.102955f, +-2.322013f, +-0.103225f, +-2.319518f, +-0.103497f, +-2.317019f, +-0.103770f, +-2.314536f, +-0.104041f, +-2.312040f, +-0.104316f, +-2.309559f, +-0.104589f, +-2.307075f, +-0.104863f, +-2.304587f, +-0.105138f, +-2.302105f, +-0.105414f, +-2.299620f, +-0.105691f, +-2.297140f, +-0.105967f, +-2.294667f, +-0.106244f, +-2.292189f, +-0.106522f, +-2.289718f, +-0.106800f, +-2.287243f, +-0.107080f, +-2.284775f, +-0.107359f, +-2.282302f, +-0.107640f, +-2.279836f, +-0.107920f, +-2.277376f, +-0.108201f, +-2.274912f, +-0.108483f, +-2.272444f, +-0.108766f, +-2.269982f, +-0.109050f, +-2.267527f, +-0.109333f, +-2.265068f, +-0.109617f, +-2.262615f, +-0.109902f, +-2.260158f, +-0.110188f, +-2.257707f, +-0.110474f, +-2.255253f, +-0.110761f, +-2.252805f, +-0.111048f, +-2.250353f, +-0.111336f, +-2.247908f, +-0.111625f, +-2.245468f, +-0.111913f, +-2.243025f, +-0.112203f, +-2.240587f, +-0.112493f, +-2.238147f, +-0.112784f, +-2.235702f, +-0.113076f, +-2.233274f, +-0.113367f, +-2.230832f, +-0.113660f, +-2.228406f, +-0.113953f, +-2.225976f, +-0.114247f, +-2.223543f, +-0.114541f, +-2.221116f, +-0.114836f, +-2.218685f, +-0.115133f, +-2.216261f, +-0.115429f, +-2.213842f, +-0.115725f, +-2.211420f, +-0.116023f, +-2.209004f, +-0.116320f, +-2.206584f, +-0.116619f, +-2.204171f, +-0.116918f, +-2.201754f, +-0.117218f, +-2.199343f, +-0.117519f, +-2.196929f, +-0.117820f, +-2.194520f, +-0.118122f, +-2.192109f, +-0.118424f, +-2.189703f, +-0.118727f, +-2.187303f, +-0.119030f, +-2.184900f, +-0.119334f, +-2.182494f, +-0.119640f, +-2.180093f, +-0.119945f, +-2.177698f, +-0.120251f, +-2.175301f, +-0.120558f, +-2.172909f, +-0.120865f, +-2.170514f, +-0.121173f, +-2.168124f, +-0.121481f, +-2.165732f, +-0.121790f, +-2.163345f, +-0.122100f, +-2.160955f, +-0.122411f, +-2.158571f, +-0.122721f, +-2.156193f, +-0.123032f, +-2.153812f, +-0.123345f, +-2.151427f, +-0.123658f, +-2.149049f, +-0.123972f, +-2.146676f, +-0.124285f, +-2.144300f, +-0.124600f, +-2.141921f, +-0.124916f, +-2.139557f, +-0.125231f, +-2.137181f, +-0.125548f, +-2.134811f, +-0.125866f, +-2.132446f, +-0.126184f, +-2.130078f, +-0.126502f, +-2.127716f, +-0.126821f, +-2.125360f, +-0.127140f, +-2.123001f, +-0.127461f, +-2.120639f, +-0.127782f, +-2.118282f, +-0.128104f, +-2.115923f, +-0.128427f, +-2.113569f, +-0.128750f, +-2.111221f, +-0.129073f, +-2.108870f, +-0.129397f, +-2.106525f, +-0.129722f, +-2.104177f, +-0.130047f, +-2.101826f, +-0.130374f, +-2.099481f, +-0.130701f, +-2.097141f, +-0.131028f, +-2.094799f, +-0.131357f, +-2.092462f, +-0.131685f, +-2.090122f, +-0.132015f, +-2.087788f, +-0.132345f, +-2.085460f, +-0.132675f, +-2.083120f, +-0.133007f, +-2.080794f, +-0.133338f, +-2.078466f, +-0.133671f, +-2.076135f, +-0.134005f, +-2.073809f, +-0.134339f, +-2.071489f, +-0.134673f, +-2.069166f, +-0.135008f, +-2.066841f, +-0.135344f, +-2.064521f, +-0.135681f, +-2.062207f, +-0.136018f, +-2.059890f, +-0.136356f, +-2.057578f, +-0.136694f, +-2.055264f, +-0.137034f, +-2.052955f, +-0.137373f, +-2.050644f, +-0.137714f, +-2.048331f, +-0.138056f, +-2.046030f, +-0.138397f, +-2.043727f, +-0.138739f, +-2.041422f, +-0.139083f, +-2.039121f, +-0.139426f, +-2.036819f, +-0.139771f, +-2.034522f, +-0.140116f, +-2.032222f, +-0.140463f, +-2.029928f, +-0.140809f, +-2.027639f, +-0.141156f, +-2.025347f, +-0.141504f, +-2.023054f, +-0.141853f, +-2.020765f, +-0.142202f, +-2.018482f, +-0.142551f, +-2.016196f, +-0.142902f, +-2.013908f, +-0.143254f, +-2.011633f, +-0.143605f, +-2.009348f, +-0.143958f, +-2.007069f, +-0.144312f, +-2.004794f, +-0.144665f, +-2.002518f, +-0.145020f, +-2.000246f, +-0.145375f, +-1.997972f, +-0.145731f, +-1.995703f, +-0.146088f, +-1.993433f, +-0.146445f, +-1.991167f, +-0.146803f, +-1.988899f, +-0.147162f, +-1.986636f, +-0.147521f, +-1.984379f, +-0.147881f, +-1.982112f, +-0.148242f, +-1.979857f, +-0.148603f, +-1.977600f, +-0.148965f, +-1.975341f, +-0.149329f, +-1.973087f, +-0.149692f, +-1.970838f, +-0.150056f, +-1.968587f, +-0.150421f, +-1.966334f, +-0.150787f, +-1.964086f, +-0.151153f, +-1.961843f, +-0.151520f, +-1.959598f, +-0.151887f, +-1.957351f, +-0.152256f, +-1.955109f, +-0.152626f, +-1.952872f, +-0.152995f, +-1.950633f, +-0.153366f, +-1.948399f, +-0.153736f, +-1.946163f, +-0.154109f, +-1.943932f, +-0.154481f, +-1.941699f, +-0.154854f, +-1.939471f, +-0.155228f, +-1.937241f, +-0.155603f, +-1.935016f, +-0.155978f, +-1.932789f, +-0.156354f, +-1.930567f, +-0.156731f, +-1.928342f, +-0.157109f, +-1.926123f, +-0.157487f, +-1.923902f, +-0.157866f, +-1.921686f, +-0.158246f, +-1.919475f, +-0.158625f, +-1.917261f, +-0.159006f, +-1.915046f, +-0.159389f, +-1.912836f, +-0.159771f, +-1.910631f, +-0.160153f, +-1.908417f, +-0.160539f, +-1.906215f, +-0.160923f, +-1.904010f, +-0.161308f, +-1.901811f, +-0.161693f, +-1.899610f, +-0.162080f, +-1.897407f, +-0.162468f, +-1.895208f, +-0.162857f, +-1.893015f, +-0.163245f, +-1.890820f, +-0.163635f, +-1.888629f, +-0.164025f, +-1.886437f, +-0.164416f, +-1.884243f, +-0.164809f, +-1.882061f, +-0.165200f, +-1.879870f, +-0.165594f, +-1.877690f, +-0.165987f, +-1.875502f, +-0.166383f, +-1.873325f, +-0.166777f, +-1.871140f, +-0.167174f, +-1.868967f, +-0.167570f, +-1.866785f, +-0.167969f, +-1.864614f, +-0.168367f, +-1.862442f, +-0.168765f, +-1.860267f, +-0.169166f, +-1.858098f, +-0.169566f, +-1.855927f, +-0.169968f, +-1.853760f, +-0.170370f, +-1.851592f, +-0.170773f, +-1.849429f, +-0.171176f, +-1.847270f, +-0.171580f, +-1.845110f, +-0.171985f, +-1.842947f, +-0.172391f, +-1.840790f, +-0.172797f, +-1.838637f, +-0.173204f, +-1.836483f, +-0.173612f, +-1.834327f, +-0.174021f, +-1.832175f, +-0.174431f, +-1.830028f, +-0.174840f, +-1.827880f, +-0.175251f, +-1.825736f, +-0.175663f, +-1.823591f, +-0.176075f, +-1.821444f, +-0.176489f, +-1.819307f, +-0.176902f, +-1.817163f, +-0.177317f, +-1.815024f, +-0.177733f, +-1.812889f, +-0.178149f, +-1.810753f, +-0.178566f, +-1.808621f, +-0.178983f, +-1.806487f, +-0.179402f, +-1.804358f, +-0.179821f, +-1.802228f, +-0.180241f, +-1.800102f, +-0.180661f, +-1.797975f, +-0.181083f, +-1.795852f, +-0.181505f, +-1.793733f, +-0.181927f, +-1.791607f, +-0.182352f, +-1.789492f, +-0.182776f, +-1.787375f, +-0.183201f, +-1.785257f, +-0.183627f, +-1.783143f, +-0.184054f, +-1.781033f, +-0.184481f, +-1.778922f, +-0.184909f, +-1.776810f, +-0.185338f, +-1.774702f, +-0.185768f, +-1.772598f, +-0.186198f, +-1.770493f, +-0.186630f, +-1.768387f, +-0.187062f, +-1.766285f, +-0.187495f, +-1.764187f, +-0.187928f, +-1.762088f, +-0.188363f, +-1.759988f, +-0.188799f, +-1.757897f, +-0.189234f, +-1.755800f, +-0.189671f, +-1.753707f, +-0.190109f, +-1.751618f, +-0.190547f, +-1.749528f, +-0.190986f, +-1.747442f, +-0.191426f, +-1.745355f, +-0.191867f, +-1.743272f, +-0.192308f, +-1.741188f, +-0.192750f, +-1.739108f, +-0.193193f, +-1.737027f, +-0.193637f, +-1.734950f, +-0.194081f, +-1.732878f, +-0.194526f, +-1.730804f, +-0.194972f, +-1.728728f, +-0.195419f, +-1.726657f, +-0.195866f, +-1.724585f, +-0.196315f, +-1.722517f, +-0.196765f, +-1.720453f, +-0.197214f, +-1.718388f, +-0.197665f, +-1.716322f, +-0.198117f, +-1.714260f, +-0.198569f, +-1.712202f, +-0.199022f, +-1.710143f, +-0.199476f, +-1.708082f, +-0.199931f, +-1.706026f, +-0.200387f, +-1.703974f, +-0.200843f, +-1.701921f, +-0.201300f, +-1.699872f, +-0.201758f, +-1.697821f, +-0.202217f, +-1.695775f, +-0.202676f, +-1.693728f, +-0.203136f, +-1.691684f, +-0.203597f, +-1.689640f, +-0.204059f, +-1.687599f, +-0.204522f, +-1.685558f, +-0.204986f, +-1.683521f, +-0.205450f, +-1.681482f, +-0.205915f, +-1.679447f, +-0.206381f, +-1.677417f, +-0.206847f, +-1.675385f, +-0.207314f, +-1.673353f, +-0.207783f, +-1.671324f, +-0.208252f, +-1.669294f, +-0.208723f, +-1.667268f, +-0.209194f, +-1.665247f, +-0.209665f, +-1.663224f, +-0.210137f, +-1.661205f, +-0.210610f, +-1.659185f, +-0.211084f, +-1.657164f, +-0.211560f, +-1.655152f, +-0.212034f, +-1.653134f, +-0.212512f, +-1.651120f, +-0.212989f, +-1.649110f, +-0.213467f, +-1.647098f, +-0.213946f, +-1.645091f, +-0.214425f, +-1.643083f, +-0.214906f, +-1.641078f, +-0.215387f, +-1.639078f, +-0.215869f, +-1.637071f, +-0.216353f, +-1.635074f, +-0.216836f, +-1.633075f, +-0.217321f, +-1.631075f, +-0.217807f, +-1.629080f, +-0.218293f, +-1.627088f, +-0.218779f, +-1.625095f, +-0.219267f, +-1.623101f, +-0.219757f, +-1.621111f, +-0.220246f, +-1.619125f, +-0.220736f, +-1.617137f, +-0.221228f, +-1.615154f, +-0.221720f, +-1.613170f, +-0.222213f, +-1.611189f, +-0.222706f, +-1.609208f, +-0.223201f, +-1.607230f, +-0.223696f, +-1.605252f, +-0.224193f, +-1.603277f, +-0.224690f, +-1.601301f, +-0.225188f, +-1.599329f, +-0.225687f, +-1.597361f, +-0.226186f, +-1.595392f, +-0.226686f, +-1.593422f, +-0.227188f, +-1.591456f, +-0.227690f, +-1.589493f, +-0.228193f, +-1.587530f, +-0.228696f, +-1.585565f, +-0.229202f, +-1.583609f, +-0.229706f, +-1.581648f, +-0.230213f, +-1.579690f, +-0.230721f, +-1.577736f, +-0.231229f, +-1.575781f, +-0.231738f, +-1.573829f, +-0.232247f, +-1.571882f, +-0.232757f, +-1.569934f, +-0.233268f, +-1.567984f, +-0.233781f, +-1.566038f, +-0.234294f, +-1.564092f, +-0.234809f, +-1.562149f, +-0.235324f, +-1.560210f, +-0.235839f, +-1.558270f, +-0.236355f, +-1.556333f, +-0.236872f, +-1.554396f, +-0.237391f, +-1.552458f, +-0.237911f, +-1.550528f, +-0.238430f, +-1.548592f, +-0.238952f, +-1.546665f, +-0.239472f, +-1.544737f, +-0.239995f, +-1.542808f, +-0.240519f, +-1.540882f, +-0.241043f, +-1.538956f, +-0.241569f, +-1.537034f, +-0.242094f, +-1.535115f, +-0.242621f, +-1.533195f, +-0.243149f, +-1.531279f, +-0.243677f, +-1.529361f, +-0.244206f, +-1.527443f, +-0.244738f, +-1.525533f, +-0.245268f, +-1.523618f, +-0.245801f, +-1.521711f, +-0.246333f, +-1.519803f, +-0.246866f, +-1.517894f, +-0.247402f, +-1.515989f, +-0.247937f, +-1.514082f, +-0.248474f, +-1.512180f, +-0.249012f, +-1.510281f, +-0.249549f, +-1.508381f, +-0.250088f, +-1.506484f, +-0.250628f, +-1.504587f, +-0.251169f, +-1.502693f, +-0.251710f, +-1.500799f, +-0.252253f, +-1.498908f, +-0.252796f, +-1.497016f, +-0.253341f, +-1.495128f, +-0.253886f, +-1.493243f, +-0.254432f, +-1.491357f, +-0.254979f, +-1.489471f, +-0.255527f, +-1.487588f, +-0.256076f, +-1.485708f, +-0.256625f, +-1.483828f, +-0.257176f, +-1.481951f, +-0.257727f, +-1.480073f, +-0.258280f, +-1.478199f, +-0.258833f, +-1.476324f, +-0.259388f, +-1.474453f, +-0.259942f, +-1.472585f, +-0.260498f, +-1.470716f, +-0.261054f, +-1.468846f, +-0.261613f, +-1.466984f, +-0.262170f, +-1.465117f, +-0.262731f, +-1.463257f, +-0.263290f, +-1.461393f, +-0.263852f, +-1.459536f, +-0.264414f, +-1.457679f, +-0.264976f, +-1.455820f, +-0.265541f, +-1.453965f, +-0.266106f, +-1.452114f, +-0.266671f, +-1.450261f, +-0.267238f, +-1.448412f, +-0.267805f, +-1.446563f, +-0.268374f, +-1.444716f, +-0.268943f, +-1.442869f, +-0.269513f, +-1.441025f, +-0.270084f, +-1.439181f, +-0.270657f, +-1.437339f, +-0.271230f, +-1.435501f, +-0.271803f, +-1.433663f, +-0.272378f, +-1.431827f, +-0.272954f, +-1.429991f, +-0.273531f, +-1.428159f, +-0.274108f, +-1.426325f, +-0.274687f, +-1.424495f, +-0.275266f, +-1.422668f, +-0.275846f, +-1.420840f, +-0.276427f, +-1.419012f, +-0.277010f, +-1.417191f, +-0.277592f, +-1.415365f, +-0.278177f, +-1.413546f, +-0.278761f, +-1.411727f, +-0.279346f, +-1.409907f, +-0.279934f, +-1.408090f, +-0.280521f, +-1.406277f, +-0.281109f, +-1.404462f, +-0.281699f, +-1.402651f, +-0.282289f, +-1.400840f, +-0.282880f, +-1.399031f, +-0.283472f, +-1.397222f, +-0.284066f, +-1.395416f, +-0.284660f, +-1.393613f, +-0.285254f, +-1.391810f, +-0.285850f, +-1.390009f, +-0.286447f, +-1.388208f, +-0.287045f, +-1.386410f, +-0.287643f, +-1.384612f, +-0.288244f, +-1.382816f, +-0.288844f, +-1.381024f, +-0.289445f, +-1.379231f, +-0.290048f, +-1.377438f, +-0.290652f, +-1.375651f, +-0.291255f, +-1.373864f, +-0.291860f, +-1.372076f, +-0.292467f, +-1.370291f, +-0.293074f, +-1.368509f, +-0.293681f, +-1.366727f, +-0.294291f, +-1.364944f, +-0.294901f, +-1.363168f, +-0.295511f, +-1.361391f, +-0.296123f, +-1.359613f, +-0.296736f, +-1.357839f, +-0.297350f, +-1.356068f, +-0.297964f, +-1.354296f, +-0.298580f, +-1.352527f, +-0.299196f, +-1.350757f, +-0.299814f, +-1.348991f, +-0.300432f, +-1.347224f, +-0.301052f, +-1.345463f, +-0.301671f, +-1.343699f, +-0.302294f, +-1.341941f, +-0.302915f, +-1.340178f, +-0.303539f, +-1.338423f, +-0.304162f, +-1.336666f, +-0.304788f, +-1.334909f, +-0.305414f, +-1.333159f, +-0.306040f, +-1.331405f, +-0.306669f, +-1.329657f, +-0.307297f, +-1.327908f, +-0.307927f, +-1.326159f, +-0.308558f, +-1.324417f, +-0.309189f, +-1.322670f, +-0.309823f, +-1.320930f, +-0.310455f, +-1.319185f, +-0.311091f, +-1.317448f, +-0.311726f, +-1.315709f, +-0.312363f, +-1.313974f, +-0.313000f, +-1.312237f, +-0.313639f, +-1.310504f, +-0.314278f, +-1.308771f, +-0.314919f, +-1.307040f, +-0.315560f, +-1.305312f, +-0.316202f, +-1.303583f, +-0.316846f, +-1.301858f, +-0.317490f, +-1.300135f, +-0.318134f, +-1.298412f, +-0.318781f, +-1.296688f, +-0.319429f, +-1.294970f, +-0.320076f, +-1.293249f, +-0.320726f, +-1.291533f, +-0.321375f, +-1.289818f, +-0.322026f, +-1.288105f, +-0.322678f, +-1.286391f, +-0.323331f, +-1.284680f, +-0.323985f, +-1.282969f, +-0.324641f, +-1.281261f, +-0.325297f, +-1.279555f, +-0.325953f, +-1.277849f, +-0.326611f, +-1.276146f, +-0.327270f, +-1.274442f, +-0.327931f, +-1.272744f, +-0.328590f, +-1.271043f, +-0.329253f, +-1.269347f, +-0.329915f, +-1.267648f, +-0.330580f, +-1.265955f, +-0.331244f, +-1.264261f, +-0.331910f, +-1.262570f, +-0.332576f, +-1.260878f, +-0.333244f, +-1.259190f, +-0.333913f, +-1.257504f, +-0.334582f, +-1.255817f, +-0.335253f, +-1.254133f, +-0.335925f, +-1.252449f, +-0.336598f, +-1.250767f, +-0.337272f, +-1.249089f, +-0.337946f, +-1.247409f, +-0.338622f, +-1.245733f, +-0.339298f, +-1.244059f, +-0.339975f, +-1.242384f, +-0.340654f, +-1.240709f, +-0.341335f, +-1.239041f, +-0.342014f, +-1.237371f, +-0.342696f, +-1.235701f, +-0.343379f, +-1.234037f, +-0.344062f, +-1.232369f, +-0.344748f, +-1.230707f, +-0.345433f, +-1.229045f, +-0.346119f, +-1.227385f, +-0.346807f, +-1.225724f, +-0.347496f, +-1.224067f, +-0.348185f, +-1.222412f, +-0.348875f, +-1.220756f, +-0.349567f, +-1.219103f, +-0.350260f, +-1.217450f, +-0.350954f, +-1.215799f, +-0.351649f, +-1.214151f, +-0.352344f, +-1.212502f, +-0.353042f, +-1.210856f, +-0.353739f, +-1.209213f, +-0.354437f, +-1.207569f, +-0.355138f, +-1.205928f, +-0.355838f, +-1.204290f, +-0.356539f, +-1.202650f, +-0.357242f, +-1.201014f, +-0.357946f, +-1.199377f, +-0.358651f, +-1.197742f, +-0.359357f, +-1.196111f, +-0.360064f, +-1.194478f, +-0.360772f, +-1.192848f, +-0.361481f, +-1.191221f, +-0.362190f, +-1.189593f, +-0.362901f, +-1.187968f, +-0.363613f, +-1.186346f, +-0.364326f, +-1.184723f, +-0.365040f, +-1.183102f, +-0.365755f, +-1.181481f, +-0.366471f, +-1.179866f, +-0.367187f, +-1.178247f, +-0.367906f, +-1.176633f, +-0.368625f, +-1.175019f, +-0.369345f, +-1.173408f, +-0.370066f, +-1.171796f, +-0.370788f, +-1.170187f, +-0.371512f, +-1.168580f, +-0.372235f, +-1.166973f, +-0.372961f, +-1.165368f, +-0.373687f, +-1.163765f, +-0.374414f, +-1.162163f, +-0.375143f, +-1.160562f, +-0.375872f, +-1.158964f, +-0.376602f, +-1.157366f, +-0.377334f, +-1.155770f, +-0.378066f, +-1.154174f, +-0.378801f, +-1.152580f, +-0.379536f, +-1.150988f, +-0.380271f, +-1.149399f, +-0.381007f, +-1.147810f, +-0.381745f, +-1.146223f, +-0.382484f, +-1.144638f, +-0.383223f, +-1.143053f, +-0.383964f, +-1.141471f, +-0.384706f, +-1.139887f, +-0.385449f, +-1.138307f, +-0.386193f, +-1.136729f, +-0.386938f, +-1.135153f, +-0.387684f, +-1.133576f, +-0.388431f, +-1.132003f, +-0.389179f, +-1.130428f, +-0.389929f, +-1.128856f, +-0.390679f, +-1.127286f, +-0.391431f, +-1.125719f, +-0.392182f, +-1.124152f, +-0.392936f, +-1.122586f, +-0.393690f, +-1.121024f, +-0.394445f, +-1.119460f, +-0.395202f, +-1.117899f, +-0.395959f, +-1.116337f, +-0.396719f, +-1.114781f, +-0.397478f, +-1.113225f, +-0.398238f, +-1.111667f, +-0.399001f, +-1.110112f, +-0.399764f, +-1.108560f, +-0.400528f, +-1.107009f, +-0.401293f, +-1.105459f, +-0.402059f, +-1.103910f, +-0.402827f, +-1.102364f, +-0.403594f, +-1.100821f, +-0.404363f, +-1.099277f, +-0.405133f, +-1.097732f, +-0.405906f, +-1.096192f, +-0.406677f, +-1.094652f, +-0.407451f, +-1.093114f, +-0.408225f, +-1.091576f, +-0.409002f, +-1.090043f, +-0.409777f, +-1.088510f, +-0.410555f, +-1.086975f, +-0.411335f, +-1.085443f, +-0.412115f, +-1.083914f, +-0.412896f, +-1.082387f, +-0.413678f, +-1.080859f, +-0.414461f, +-1.079336f, +-0.415244f, +-1.077810f, +-0.416031f, +-1.076289f, +-0.416816f, +-1.074768f, +-0.417604f, +-1.073249f, +-0.418392f, +-1.071729f, +-0.419183f, +-1.070214f, +-0.419972f, +-1.068699f, +-0.420764f, +-1.067183f, +-0.421558f, +-1.065673f, +-0.422351f, +-1.064162f, +-0.423146f, +-1.062653f, +-0.423942f, +-1.061143f, +-0.424740f, +-1.059636f, +-0.425538f, +-1.058131f, +-0.426337f, +-1.056628f, +-0.427137f, +-1.055125f, +-0.427939f, +-1.053624f, +-0.428742f, +-1.052125f, +-0.429545f, +-1.050625f, +-0.430351f, +-1.049131f, +-0.431155f, +-1.047633f, +-0.431964f, +-1.046140f, +-0.432771f, +-1.044647f, +-0.433581f, +-1.043156f, +-0.434391f, +-1.041667f, +-0.435202f, +-1.040180f, +-0.436013f, +-1.038693f, +-0.436827f, +-1.037208f, +-0.437642f, +-1.035725f, +-0.438457f, +-1.034241f, +-0.439274f, +-1.032760f, +-0.440092f, +-1.031281f, +-0.440911f, +-1.029801f, +-0.441732f, +-1.028326f, +-0.442552f, +-1.026851f, +-0.443374f, +-1.025375f, +-0.444199f, +-1.023904f, +-0.445022f, +-1.022432f, +-0.445848f, +-1.020963f, +-0.446675f, +-1.019495f, +-0.447502f, +-1.018027f, +-0.448331f, +-1.016561f, +-0.449162f, +-1.015098f, +-0.449992f, +-1.013636f, +-0.450824f, +-1.012174f, +-0.451658f, +-1.010714f, +-0.452492f, +-1.009256f, +-0.453327f, +-1.007798f, +-0.454165f, +-1.006344f, +-0.455002f, +-1.004890f, +-0.455840f, +-1.003438f, +-0.456680f, +-1.001985f, +-0.457522f, +-1.000534f, +-0.458364f, +-0.999086f, +-0.459208f, +-0.997639f, +-0.460052f, +-0.996195f, +-0.460896f, +-0.994750f, +-0.461743f, +-0.993307f, +-0.462591f, +-0.991866f, +-0.463440f, +-0.990424f, +-0.464290f, +-0.988985f, +-0.465142f, +-0.987548f, +-0.465994f, +-0.986113f, +-0.466847f, +-0.984679f, +-0.467701f, +-0.983246f, +-0.468557f, +-0.981814f, +-0.469413f, +-0.980384f, +-0.470271f, +-0.978954f, +-0.471131f, +-0.977525f, +-0.471991f, +-0.976102f, +-0.472851f, +-0.974675f, +-0.473715f, +-0.973253f, +-0.474577f, +-0.971830f, +-0.475442f, +-0.970409f, +-0.476308f, +-0.968990f, +-0.477175f, +-0.967574f, +-0.478042f, +-0.966156f, +-0.478912f, +-0.964743f, +-0.479781f, +-0.963327f, +-0.480654f, +-0.961916f, +-0.481526f, +-0.960506f, +-0.482399f, +-0.959096f, +-0.483274f, +-0.957688f, +-0.484150f, +-0.956282f, +-0.485026f, +-0.954876f, +-0.485905f, +-0.953474f, +-0.486784f, +-0.952071f, +-0.487664f, +-0.950670f, +-0.488546f, +-0.949271f, +-0.489428f, +-0.947872f, +-0.490312f, +-0.946474f, +-0.491198f, +-0.945079f, +-0.492084f, +-0.943685f, +-0.492971f, +-0.942293f, +-0.493859f, +-0.940901f, +-0.494749f, +-0.939511f, +-0.495640f, +-0.938122f, +-0.496532f, +-0.936736f, +-0.497424f, +-0.935351f, +-0.498318f, +-0.933966f, +-0.499213f, +-0.932583f, +-0.500110f, +-0.931201f, +-0.501007f, +-0.929822f, +-0.501906f, +-0.928442f, +-0.502806f, +-0.927064f, +-0.503708f, +-0.925690f, +-0.504608f, +-0.924313f, +-0.505513f, +-0.922940f, +-0.506417f, +-0.921570f, +-0.507322f, +-0.920198f, +-0.508229f, +-0.918829f, +-0.509137f, +-0.917461f, +-0.510046f, +-0.916096f, +-0.510956f, +-0.914729f, +-0.511868f, +-0.913365f, +-0.512781f, +-0.912005f, +-0.513693f, +-0.910642f, +-0.514609f, +-0.909283f, +-0.515525f, +-0.907926f, +-0.516441f, +-0.906568f, +-0.517360f, +-0.905212f, +-0.518280f, +-0.903858f, +-0.519201f, +-0.902506f, +-0.520122f, +-0.901156f, +-0.521044f, +-0.899805f, +-0.521969f, +-0.898456f, +-0.522895f, +-0.897108f, +-0.523821f, +-0.895763f, +-0.524749f, +-0.894419f, +-0.525677f, +-0.893075f, +-0.526608f, +-0.891735f, +-0.527538f, +-0.890394f, +-0.528470f, +-0.889055f, +-0.529404f, +-0.887718f, +-0.530338f, +-0.886380f, +-0.531275f, +-0.885046f, +-0.532211f, +-0.883712f, +-0.533150f, +-0.882380f, +-0.534089f, +-0.881049f, +-0.535030f, +-0.879720f, +-0.535971f, +-0.878393f, +-0.536913f, +-0.877065f, +-0.537858f, +-0.875739f, +-0.538803f, +-0.874415f, +-0.539750f, +-0.873092f, +-0.540697f, +-0.871772f, +-0.541646f, +-0.870453f, +-0.542595f, +-0.869133f, +-0.543547f, +-0.867817f, +-0.544498f, +-0.866501f, +-0.545452f, +-0.865187f, +-0.546406f, +-0.863874f, +-0.547362f, +-0.862560f, +-0.548320f, +-0.861251f, +-0.549277f, +-0.859941f, +-0.550237f, +-0.858633f, +-0.551198f, +-0.857326f, +-0.552160f, +-0.856021f, +-0.553123f, +-0.854718f, +-0.554086f, +-0.853417f, +-0.555051f, +-0.852115f, +-0.556018f, +-0.850817f, +-0.556985f, +-0.849518f, +-0.557954f, +-0.848221f, +-0.558924f, +-0.846926f, +-0.559895f, +-0.845630f, +-0.560869f, +-0.844338f, +-0.561842f, +-0.843047f, +-0.562816f, +-0.841756f, +-0.563792f, +-0.840467f, +-0.564770f, +-0.839179f, +-0.565748f, +-0.837893f, +-0.566728f, +-0.836609f, +-0.567708f, +-0.835326f, +-0.568690f, +-0.834043f, +-0.569674f, +-0.832763f, +-0.570657f, +-0.831483f, +-0.571643f, +-0.830205f, +-0.572630f, +-0.828928f, +-0.573618f, +-0.827653f, +-0.574607f, +-0.826379f, +-0.575597f, +-0.825105f, +-0.576590f, +-0.823835f, +-0.577582f, +-0.822564f, +-0.578576f, +-0.821297f, +-0.579570f, +-0.820029f, +-0.580567f, +-0.818763f, +-0.581565f, +-0.817498f, +-0.582563f, +-0.816235f, +-0.583563f, +-0.814971f, +-0.584565f, +-0.813712f, +-0.585567f, +-0.812451f, +-0.586572f, +-0.811195f, +-0.587575f, +-0.809937f, +-0.588582f, +-0.808681f, +-0.589589f, +-0.807427f, +-0.590598f, +-0.806175f, +-0.591607f, +-0.804924f, +-0.592618f, +-0.803674f, +-0.593630f, +-0.802424f, +-0.594644f, +-0.801178f, +-0.595658f, +-0.799931f, +-0.596674f, +-0.798688f, +-0.597690f, +-0.797444f, +-0.598708f, +-0.796201f, +-0.599728f, +-0.794961f, +-0.600749f, +-0.793721f, +-0.601770f, +-0.792484f, +-0.602793f, +-0.791245f, +-0.603818f, +-0.790011f, +-0.604843f, +-0.788777f, +-0.605869f, +-0.787544f, +-0.606898f, +-0.786311f, +-0.607928f, +-0.785083f, +-0.608957f, +-0.783853f, +-0.609989f, +-0.782626f, +-0.611022f, +-0.781399f, +-0.612056f, +-0.780175f, +-0.613091f, +-0.778951f, +-0.614127f, +-0.777729f, +-0.615164f, +-0.776507f, +-0.616205f, +-0.775288f, +-0.617244f, +-0.774069f, +-0.618286f, +-0.772853f, +-0.619328f, +-0.771636f, +-0.620373f, +-0.770424f, +-0.621416f, +-0.769210f, +-0.622463f, +-0.767998f, +-0.623511f, +-0.766787f, +-0.624560f, +-0.765578f, +-0.625610f, +-0.764370f, +-0.626661f, +-0.763164f, +-0.627713f, +-0.761959f, +-0.628767f, +-0.760754f, +-0.629823f, +-0.759552f, +-0.630879f, +-0.758352f, +-0.631935f, +-0.757150f, +-0.632995f, +-0.755953f, +-0.634054f, +-0.754755f, +-0.635116f, +-0.753558f, +-0.636179f, +-0.752364f, +-0.637241f, +-0.751170f, +-0.638307f, +-0.749978f, +-0.639373f, +-0.748787f, +-0.640441f, +-0.747597f, +-0.641510f, +-0.746409f, +-0.642580f, +-0.745222f, +-0.643651f, +-0.744036f, +-0.644723f, +-0.742852f, +-0.645796f, +-0.741670f, +-0.646871f, +-0.740488f, +-0.647946f, +-0.739308f, +-0.649023f, +-0.738128f, +-0.650103f, +-0.736951f, +-0.651182f, +-0.735773f, +-0.652264f, +-0.734599f, +-0.653346f, +-0.733426f, +-0.654429f, +-0.732252f, +-0.655514f, +-0.731082f, +-0.656599f, +-0.729911f, +-0.657687f, +-0.728741f, +-0.658777f, +-0.727575f, +-0.659865f, +-0.726408f, +-0.660957f, +-0.725243f, +-0.662050f, +-0.724079f, +-0.663144f, +-0.722918f, +-0.664237f, +-0.721757f, +-0.665334f, +-0.720596f, +-0.666431f, +-0.719438f, +-0.667530f, +-0.718280f, +-0.668630f, +-0.717124f, +-0.669731f, +-0.715970f, +-0.670834f, +-0.714816f, +-0.671938f, +-0.713664f, +-0.673043f, +-0.712514f, +-0.674149f, +-0.711364f, +-0.675256f, +-0.710216f, +-0.676365f, +-0.709069f, +-0.677475f, +-0.707924f, +-0.678586f, +-0.706780f, +-0.679698f, +-0.705637f, +-0.680812f, +-0.704495f, +-0.681926f, +-0.703355f, +-0.683042f, +-0.702214f, +-0.684162f, +-0.701077f, +-0.685280f, +-0.699940f, +-0.686400f, +-0.698805f, +-0.687521f, +-0.697671f, +-0.688643f, +-0.696539f, +-0.689767f, +-0.695406f, +-0.690894f, +-0.694276f, +-0.692020f, +-0.693147f, +-0.693147f, +-0.693147f, +-0.693147f, +-0.693147f, +-0.693147f, +-0.692020f, +-0.694276f, +-0.690894f, +-0.695406f, +-0.689767f, +-0.696539f, +-0.688643f, +-0.697671f, +-0.687521f, +-0.698805f, +-0.686400f, +-0.699940f, +-0.685280f, +-0.701077f, +-0.684162f, +-0.702214f, +-0.683042f, +-0.703355f, +-0.681926f, +-0.704495f, +-0.680812f, +-0.705637f, +-0.679698f, +-0.706780f, +-0.678586f, +-0.707924f, +-0.677475f, +-0.709069f, +-0.676365f, +-0.710216f, +-0.675256f, +-0.711364f, +-0.674149f, +-0.712514f, +-0.673043f, +-0.713664f, +-0.671938f, +-0.714816f, +-0.670834f, +-0.715970f, +-0.669731f, +-0.717124f, +-0.668630f, +-0.718280f, +-0.667530f, +-0.719438f, +-0.666431f, +-0.720596f, +-0.665334f, +-0.721757f, +-0.664237f, +-0.722918f, +-0.663144f, +-0.724079f, +-0.662050f, +-0.725243f, +-0.660957f, +-0.726408f, +-0.659865f, +-0.727575f, +-0.658777f, +-0.728741f, +-0.657687f, +-0.729911f, +-0.656599f, +-0.731082f, +-0.655514f, +-0.732252f, +-0.654429f, +-0.733426f, +-0.653346f, +-0.734599f, +-0.652264f, +-0.735773f, +-0.651182f, +-0.736951f, +-0.650103f, +-0.738128f, +-0.649023f, +-0.739308f, +-0.647946f, +-0.740488f, +-0.646871f, +-0.741670f, +-0.645796f, +-0.742852f, +-0.644723f, +-0.744036f, +-0.643651f, +-0.745222f, +-0.642580f, +-0.746409f, +-0.641510f, +-0.747597f, +-0.640441f, +-0.748787f, +-0.639373f, +-0.749978f, +-0.638307f, +-0.751170f, +-0.637241f, +-0.752364f, +-0.636179f, +-0.753558f, +-0.635116f, +-0.754755f, +-0.634054f, +-0.755953f, +-0.632995f, +-0.757150f, +-0.631935f, +-0.758351f, +-0.630879f, +-0.759552f, +-0.629823f, +-0.760754f, +-0.628767f, +-0.761959f, +-0.627713f, +-0.763164f, +-0.626661f, +-0.764370f, +-0.625610f, +-0.765578f, +-0.624560f, +-0.766787f, +-0.623511f, +-0.767998f, +-0.622463f, +-0.769210f, +-0.621416f, +-0.770424f, +-0.620373f, +-0.771636f, +-0.619328f, +-0.772853f, +-0.618286f, +-0.774069f, +-0.617244f, +-0.775288f, +-0.616205f, +-0.776507f, +-0.615164f, +-0.777730f, +-0.614127f, +-0.778951f, +-0.613091f, +-0.780175f, +-0.612056f, +-0.781399f, +-0.611022f, +-0.782626f, +-0.609989f, +-0.783853f, +-0.608957f, +-0.785083f, +-0.607928f, +-0.786311f, +-0.606898f, +-0.787544f, +-0.605869f, +-0.788777f, +-0.604843f, +-0.790011f, +-0.603818f, +-0.791245f, +-0.602793f, +-0.792484f, +-0.601770f, +-0.793721f, +-0.600749f, +-0.794961f, +-0.599728f, +-0.796201f, +-0.598708f, +-0.797444f, +-0.597690f, +-0.798688f, +-0.596674f, +-0.799931f, +-0.595658f, +-0.801178f, +-0.594644f, +-0.802424f, +-0.593630f, +-0.803674f, +-0.592618f, +-0.804924f, +-0.591607f, +-0.806175f, +-0.590598f, +-0.807427f, +-0.589589f, +-0.808681f, +-0.588582f, +-0.809937f, +-0.587575f, +-0.811195f, +-0.586572f, +-0.812451f, +-0.585567f, +-0.813712f, +-0.584565f, +-0.814971f, +-0.583563f, +-0.816235f, +-0.582563f, +-0.817498f, +-0.581565f, +-0.818763f, +-0.580567f, +-0.820029f, +-0.579570f, +-0.821297f, +-0.578576f, +-0.822564f, +-0.577582f, +-0.823835f, +-0.576590f, +-0.825105f, +-0.575597f, +-0.826379f, +-0.574607f, +-0.827653f, +-0.573618f, +-0.828928f, +-0.572630f, +-0.830205f, +-0.571643f, +-0.831483f, +-0.570657f, +-0.832763f, +-0.569674f, +-0.834043f, +-0.568690f, +-0.835326f, +-0.567708f, +-0.836609f, +-0.566728f, +-0.837893f, +-0.565748f, +-0.839179f, +-0.564770f, +-0.840467f, +-0.563792f, +-0.841756f, +-0.562816f, +-0.843047f, +-0.561842f, +-0.844338f, +-0.560869f, +-0.845630f, +-0.559895f, +-0.846926f, +-0.558924f, +-0.848221f, +-0.557954f, +-0.849518f, +-0.556985f, +-0.850817f, +-0.556018f, +-0.852115f, +-0.555051f, +-0.853417f, +-0.554086f, +-0.854718f, +-0.553123f, +-0.856022f, +-0.552160f, +-0.857326f, +-0.551198f, +-0.858633f, +-0.550237f, +-0.859941f, +-0.549277f, +-0.861251f, +-0.548320f, +-0.862560f, +-0.547362f, +-0.863874f, +-0.546406f, +-0.865187f, +-0.545452f, +-0.866501f, +-0.544498f, +-0.867817f, +-0.543547f, +-0.869133f, +-0.542595f, +-0.870452f, +-0.541646f, +-0.871772f, +-0.540697f, +-0.873092f, +-0.539750f, +-0.874415f, +-0.538803f, +-0.875739f, +-0.537858f, +-0.877065f, +-0.536913f, +-0.878393f, +-0.535971f, +-0.879720f, +-0.535030f, +-0.881049f, +-0.534089f, +-0.882380f, +-0.533150f, +-0.883712f, +-0.532211f, +-0.885046f, +-0.531275f, +-0.886380f, +-0.530338f, +-0.887718f, +-0.529404f, +-0.889055f, +-0.528470f, +-0.890394f, +-0.527538f, +-0.891735f, +-0.526608f, +-0.893075f, +-0.525677f, +-0.894419f, +-0.524749f, +-0.895763f, +-0.523821f, +-0.897108f, +-0.522895f, +-0.898456f, +-0.521969f, +-0.899805f, +-0.521044f, +-0.901156f, +-0.520122f, +-0.902506f, +-0.519201f, +-0.903858f, +-0.518280f, +-0.905212f, +-0.517360f, +-0.906568f, +-0.516441f, +-0.907926f, +-0.515525f, +-0.909283f, +-0.514609f, +-0.910642f, +-0.513693f, +-0.912005f, +-0.512781f, +-0.913365f, +-0.511868f, +-0.914729f, +-0.510956f, +-0.916096f, +-0.510046f, +-0.917461f, +-0.509137f, +-0.918829f, +-0.508229f, +-0.920198f, +-0.507322f, +-0.921570f, +-0.506417f, +-0.922940f, +-0.505513f, +-0.924313f, +-0.504608f, +-0.925690f, +-0.503708f, +-0.927064f, +-0.502806f, +-0.928442f, +-0.501906f, +-0.929822f, +-0.501007f, +-0.931201f, +-0.500110f, +-0.932583f, +-0.499213f, +-0.933966f, +-0.498318f, +-0.935351f, +-0.497424f, +-0.936736f, +-0.496532f, +-0.938122f, +-0.495640f, +-0.939511f, +-0.494749f, +-0.940901f, +-0.493859f, +-0.942293f, +-0.492971f, +-0.943685f, +-0.492084f, +-0.945079f, +-0.491198f, +-0.946474f, +-0.490312f, +-0.947872f, +-0.489428f, +-0.949271f, +-0.488546f, +-0.950670f, +-0.487664f, +-0.952071f, +-0.486784f, +-0.953474f, +-0.485905f, +-0.954876f, +-0.485026f, +-0.956282f, +-0.484150f, +-0.957688f, +-0.483274f, +-0.959097f, +-0.482399f, +-0.960506f, +-0.481526f, +-0.961916f, +-0.480654f, +-0.963327f, +-0.479781f, +-0.964743f, +-0.478912f, +-0.966156f, +-0.478042f, +-0.967574f, +-0.477175f, +-0.968990f, +-0.476308f, +-0.970409f, +-0.475442f, +-0.971830f, +-0.474577f, +-0.973253f, +-0.473714f, +-0.974675f, +-0.472851f, +-0.976102f, +-0.471991f, +-0.977525f, +-0.471131f, +-0.978954f, +-0.470271f, +-0.980384f, +-0.469413f, +-0.981814f, +-0.468557f, +-0.983245f, +-0.467701f, +-0.984679f, +-0.466847f, +-0.986113f, +-0.465994f, +-0.987548f, +-0.465142f, +-0.988985f, +-0.464290f, +-0.990424f, +-0.463440f, +-0.991866f, +-0.462591f, +-0.993307f, +-0.461743f, +-0.994750f, +-0.460896f, +-0.996195f, +-0.460052f, +-0.997639f, +-0.459208f, +-0.999086f, +-0.458364f, +-1.000534f, +-0.457522f, +-1.001985f, +-0.456680f, +-1.003438f, +-0.455840f, +-1.004890f, +-0.455002f, +-1.006344f, +-0.454165f, +-1.007798f, +-0.453327f, +-1.009256f, +-0.452492f, +-1.010714f, +-0.451658f, +-1.012174f, +-0.450824f, +-1.013636f, +-0.449992f, +-1.015098f, +-0.449162f, +-1.016561f, +-0.448331f, +-1.018027f, +-0.447502f, +-1.019495f, +-0.446675f, +-1.020963f, +-0.445848f, +-1.022432f, +-0.445022f, +-1.023904f, +-0.444199f, +-1.025375f, +-0.443374f, +-1.026851f, +-0.442552f, +-1.028326f, +-0.441732f, +-1.029801f, +-0.440911f, +-1.031281f, +-0.440092f, +-1.032760f, +-0.439274f, +-1.034241f, +-0.438457f, +-1.035725f, +-0.437642f, +-1.037208f, +-0.436827f, +-1.038693f, +-0.436013f, +-1.040180f, +-0.435202f, +-1.041667f, +-0.434391f, +-1.043156f, +-0.433581f, +-1.044647f, +-0.432771f, +-1.046140f, +-0.431964f, +-1.047633f, +-0.431155f, +-1.049131f, +-0.430351f, +-1.050625f, +-0.429545f, +-1.052125f, +-0.428742f, +-1.053624f, +-0.427939f, +-1.055125f, +-0.427137f, +-1.056628f, +-0.426337f, +-1.058131f, +-0.425538f, +-1.059636f, +-0.424740f, +-1.061143f, +-0.423942f, +-1.062653f, +-0.423146f, +-1.064162f, +-0.422351f, +-1.065673f, +-0.421558f, +-1.067183f, +-0.420764f, +-1.068699f, +-0.419972f, +-1.070214f, +-0.419183f, +-1.071729f, +-0.418392f, +-1.073249f, +-0.417604f, +-1.074768f, +-0.416816f, +-1.076289f, +-0.416031f, +-1.077810f, +-0.415244f, +-1.079336f, +-0.414461f, +-1.080859f, +-0.413678f, +-1.082387f, +-0.412896f, +-1.083914f, +-0.412115f, +-1.085443f, +-0.411335f, +-1.086975f, +-0.410555f, +-1.088509f, +-0.409777f, +-1.090043f, +-0.409002f, +-1.091576f, +-0.408225f, +-1.093114f, +-0.407451f, +-1.094652f, +-0.406677f, +-1.096192f, +-0.405906f, +-1.097732f, +-0.405133f, +-1.099277f, +-0.404363f, +-1.100821f, +-0.403594f, +-1.102364f, +-0.402827f, +-1.103910f, +-0.402059f, +-1.105459f, +-0.401293f, +-1.107009f, +-0.400528f, +-1.108560f, +-0.399764f, +-1.110112f, +-0.399001f, +-1.111667f, +-0.398238f, +-1.113225f, +-0.397478f, +-1.114781f, +-0.396719f, +-1.116338f, +-0.395959f, +-1.117899f, +-0.395202f, +-1.119460f, +-0.394445f, +-1.121024f, +-0.393690f, +-1.122586f, +-0.392936f, +-1.124152f, +-0.392182f, +-1.125719f, +-0.391431f, +-1.127286f, +-0.390679f, +-1.128856f, +-0.389929f, +-1.130428f, +-0.389179f, +-1.132003f, +-0.388431f, +-1.133577f, +-0.387684f, +-1.135153f, +-0.386938f, +-1.136729f, +-0.386194f, +-1.138307f, +-0.385449f, +-1.139888f, +-0.384706f, +-1.141471f, +-0.383964f, +-1.143053f, +-0.383223f, +-1.144638f, +-0.382484f, +-1.146223f, +-0.381745f, +-1.147810f, +-0.381007f, +-1.149399f, +-0.380271f, +-1.150988f, +-0.379536f, +-1.152580f, +-0.378801f, +-1.154174f, +-0.378066f, +-1.155770f, +-0.377334f, +-1.157366f, +-0.376602f, +-1.158964f, +-0.375872f, +-1.160562f, +-0.375143f, +-1.162163f, +-0.374414f, +-1.163765f, +-0.373687f, +-1.165368f, +-0.372961f, +-1.166972f, +-0.372235f, +-1.168580f, +-0.371512f, +-1.170187f, +-0.370788f, +-1.171796f, +-0.370066f, +-1.173408f, +-0.369345f, +-1.175019f, +-0.368625f, +-1.176633f, +-0.367906f, +-1.178247f, +-0.367187f, +-1.179866f, +-0.366471f, +-1.181481f, +-0.365755f, +-1.183102f, +-0.365040f, +-1.184723f, +-0.364326f, +-1.186346f, +-0.363613f, +-1.187968f, +-0.362901f, +-1.189593f, +-0.362190f, +-1.191221f, +-0.361481f, +-1.192848f, +-0.360772f, +-1.194478f, +-0.360064f, +-1.196111f, +-0.359357f, +-1.197742f, +-0.358651f, +-1.199377f, +-0.357946f, +-1.201014f, +-0.357242f, +-1.202650f, +-0.356539f, +-1.204290f, +-0.355838f, +-1.205928f, +-0.355138f, +-1.207569f, +-0.354437f, +-1.209213f, +-0.353739f, +-1.210857f, +-0.353042f, +-1.212503f, +-0.352344f, +-1.214151f, +-0.351649f, +-1.215799f, +-0.350954f, +-1.217450f, +-0.350260f, +-1.219103f, +-0.349567f, +-1.220756f, +-0.348875f, +-1.222412f, +-0.348185f, +-1.224067f, +-0.347496f, +-1.225724f, +-0.346807f, +-1.227385f, +-0.346119f, +-1.229044f, +-0.345433f, +-1.230707f, +-0.344748f, +-1.232369f, +-0.344062f, +-1.234037f, +-0.343379f, +-1.235701f, +-0.342696f, +-1.237371f, +-0.342014f, +-1.239041f, +-0.341335f, +-1.240709f, +-0.340654f, +-1.242385f, +-0.339975f, +-1.244059f, +-0.339298f, +-1.245733f, +-0.338622f, +-1.247409f, +-0.337946f, +-1.249089f, +-0.337272f, +-1.250768f, +-0.336598f, +-1.252449f, +-0.335925f, +-1.254133f, +-0.335253f, +-1.255817f, +-0.334582f, +-1.257504f, +-0.333913f, +-1.259190f, +-0.333244f, +-1.260878f, +-0.332576f, +-1.262570f, +-0.331910f, +-1.264261f, +-0.331244f, +-1.265955f, +-0.330580f, +-1.267648f, +-0.329915f, +-1.269347f, +-0.329253f, +-1.271043f, +-0.328590f, +-1.272744f, +-0.327931f, +-1.274442f, +-0.327270f, +-1.276146f, +-0.326611f, +-1.277849f, +-0.325953f, +-1.279555f, +-0.325297f, +-1.281261f, +-0.324641f, +-1.282969f, +-0.323985f, +-1.284680f, +-0.323331f, +-1.286391f, +-0.322678f, +-1.288105f, +-0.322026f, +-1.289818f, +-0.321375f, +-1.291533f, +-0.320726f, +-1.293249f, +-0.320076f, +-1.294970f, +-0.319429f, +-1.296688f, +-0.318781f, +-1.298412f, +-0.318134f, +-1.300135f, +-0.317490f, +-1.301858f, +-0.316846f, +-1.303583f, +-0.316202f, +-1.305312f, +-0.315560f, +-1.307040f, +-0.314919f, +-1.308771f, +-0.314278f, +-1.310504f, +-0.313639f, +-1.312237f, +-0.313000f, +-1.313974f, +-0.312363f, +-1.315709f, +-0.311726f, +-1.317448f, +-0.311091f, +-1.319185f, +-0.310455f, +-1.320930f, +-0.309823f, +-1.322670f, +-0.309189f, +-1.324417f, +-0.308558f, +-1.326159f, +-0.307927f, +-1.327909f, +-0.307297f, +-1.329657f, +-0.306669f, +-1.331405f, +-0.306040f, +-1.333159f, +-0.305414f, +-1.334910f, +-0.304788f, +-1.336666f, +-0.304162f, +-1.338423f, +-0.303539f, +-1.340178f, +-0.302915f, +-1.341941f, +-0.302294f, +-1.343699f, +-0.301671f, +-1.345463f, +-0.301052f, +-1.347224f, +-0.300432f, +-1.348991f, +-0.299814f, +-1.350757f, +-0.299196f, +-1.352527f, +-0.298580f, +-1.354296f, +-0.297964f, +-1.356068f, +-0.297350f, +-1.357839f, +-0.296736f, +-1.359613f, +-0.296123f, +-1.361391f, +-0.295511f, +-1.363168f, +-0.294901f, +-1.364944f, +-0.294290f, +-1.366727f, +-0.293681f, +-1.368509f, +-0.293074f, +-1.370291f, +-0.292467f, +-1.372076f, +-0.291860f, +-1.373864f, +-0.291255f, +-1.375651f, +-0.290652f, +-1.377438f, +-0.290048f, +-1.379231f, +-0.289445f, +-1.381024f, +-0.288844f, +-1.382816f, +-0.288244f, +-1.384612f, +-0.287643f, +-1.386410f, +-0.287045f, +-1.388208f, +-0.286447f, +-1.390009f, +-0.285850f, +-1.391810f, +-0.285254f, +-1.393613f, +-0.284660f, +-1.395416f, +-0.284066f, +-1.397222f, +-0.283472f, +-1.399031f, +-0.282880f, +-1.400840f, +-0.282289f, +-1.402651f, +-0.281699f, +-1.404462f, +-0.281109f, +-1.406277f, +-0.280521f, +-1.408090f, +-0.279934f, +-1.409907f, +-0.279346f, +-1.411727f, +-0.278761f, +-1.413546f, +-0.278177f, +-1.415365f, +-0.277592f, +-1.417191f, +-0.277010f, +-1.419012f, +-0.276427f, +-1.420840f, +-0.275846f, +-1.422668f, +-0.275266f, +-1.424495f, +-0.274687f, +-1.426325f, +-0.274108f, +-1.428158f, +-0.273531f, +-1.429991f, +-0.272954f, +-1.431827f, +-0.272378f, +-1.433663f, +-0.271803f, +-1.435501f, +-0.271230f, +-1.437339f, +-0.270657f, +-1.439181f, +-0.270084f, +-1.441025f, +-0.269513f, +-1.442869f, +-0.268943f, +-1.444716f, +-0.268374f, +-1.446562f, +-0.267805f, +-1.448412f, +-0.267238f, +-1.450261f, +-0.266671f, +-1.452114f, +-0.266106f, +-1.453965f, +-0.265541f, +-1.455820f, +-0.264976f, +-1.457679f, +-0.264414f, +-1.459536f, +-0.263852f, +-1.461393f, +-0.263290f, +-1.463257f, +-0.262731f, +-1.465117f, +-0.262170f, +-1.466984f, +-0.261613f, +-1.468846f, +-0.261054f, +-1.470716f, +-0.260498f, +-1.472585f, +-0.259942f, +-1.474453f, +-0.259387f, +-1.476324f, +-0.258833f, +-1.478199f, +-0.258280f, +-1.480073f, +-0.257727f, +-1.481951f, +-0.257176f, +-1.483828f, +-0.256625f, +-1.485708f, +-0.256076f, +-1.487588f, +-0.255527f, +-1.489471f, +-0.254979f, +-1.491357f, +-0.254432f, +-1.493243f, +-0.253886f, +-1.495128f, +-0.253341f, +-1.497016f, +-0.252796f, +-1.498908f, +-0.252253f, +-1.500799f, +-0.251710f, +-1.502693f, +-0.251169f, +-1.504587f, +-0.250628f, +-1.506484f, +-0.250088f, +-1.508381f, +-0.249549f, +-1.510280f, +-0.249012f, +-1.512180f, +-0.248474f, +-1.514082f, +-0.247937f, +-1.515988f, +-0.247402f, +-1.517894f, +-0.246866f, +-1.519803f, +-0.246333f, +-1.521711f, +-0.245801f, +-1.523618f, +-0.245268f, +-1.525534f, +-0.244738f, +-1.527443f, +-0.244206f, +-1.529361f, +-0.243677f, +-1.531279f, +-0.243149f, +-1.533195f, +-0.242621f, +-1.535115f, +-0.242094f, +-1.537034f, +-0.241568f, +-1.538956f, +-0.241043f, +-1.540883f, +-0.240519f, +-1.542808f, +-0.239995f, +-1.544737f, +-0.239472f, +-1.546665f, +-0.238952f, +-1.548592f, +-0.238430f, +-1.550528f, +-0.237911f, +-1.552457f, +-0.237391f, +-1.554396f, +-0.236872f, +-1.556333f, +-0.236355f, +-1.558270f, +-0.235839f, +-1.560210f, +-0.235324f, +-1.562149f, +-0.234809f, +-1.564092f, +-0.234294f, +-1.566038f, +-0.233781f, +-1.567984f, +-0.233268f, +-1.569934f, +-0.232757f, +-1.571882f, +-0.232247f, +-1.573829f, +-0.231738f, +-1.575781f, +-0.231229f, +-1.577736f, +-0.230721f, +-1.579690f, +-0.230214f, +-1.581648f, +-0.229706f, +-1.583609f, +-0.229202f, +-1.585565f, +-0.228696f, +-1.587530f, +-0.228193f, +-1.589493f, +-0.227690f, +-1.591455f, +-0.227188f, +-1.593422f, +-0.226686f, +-1.595392f, +-0.226186f, +-1.597361f, +-0.225687f, +-1.599329f, +-0.225188f, +-1.601301f, +-0.224690f, +-1.603277f, +-0.224193f, +-1.605252f, +-0.223696f, +-1.607230f, +-0.223201f, +-1.609208f, +-0.222706f, +-1.611189f, +-0.222213f, +-1.613170f, +-0.221720f, +-1.615154f, +-0.221228f, +-1.617137f, +-0.220736f, +-1.619125f, +-0.220246f, +-1.621111f, +-0.219757f, +-1.623101f, +-0.219267f, +-1.625095f, +-0.218779f, +-1.627088f, +-0.218293f, +-1.629080f, +-0.217807f, +-1.631075f, +-0.217321f, +-1.633075f, +-0.216836f, +-1.635074f, +-0.216353f, +-1.637071f, +-0.215869f, +-1.639078f, +-0.215387f, +-1.641078f, +-0.214906f, +-1.643083f, +-0.214425f, +-1.645091f, +-0.213946f, +-1.647098f, +-0.213467f, +-1.649110f, +-0.212989f, +-1.651120f, +-0.212512f, +-1.653134f, +-0.212034f, +-1.655152f, +-0.211560f, +-1.657164f, +-0.211084f, +-1.659185f, +-0.210610f, +-1.661205f, +-0.210137f, +-1.663224f, +-0.209665f, +-1.665247f, +-0.209194f, +-1.667268f, +-0.208723f, +-1.669294f, +-0.208252f, +-1.671324f, +-0.207783f, +-1.673353f, +-0.207315f, +-1.675385f, +-0.206847f, +-1.677417f, +-0.206381f, +-1.679447f, +-0.205915f, +-1.681482f, +-0.205450f, +-1.683520f, +-0.204986f, +-1.685558f, +-0.204522f, +-1.687600f, +-0.204059f, +-1.689640f, +-0.203597f, +-1.691684f, +-0.203136f, +-1.693728f, +-0.202676f, +-1.695775f, +-0.202217f, +-1.697821f, +-0.201758f, +-1.699871f, +-0.201300f, +-1.701921f, +-0.200843f, +-1.703974f, +-0.200387f, +-1.706026f, +-0.199931f, +-1.708082f, +-0.199476f, +-1.710143f, +-0.199022f, +-1.712202f, +-0.198569f, +-1.714260f, +-0.198117f, +-1.716322f, +-0.197665f, +-1.718388f, +-0.197214f, +-1.720453f, +-0.196765f, +-1.722517f, +-0.196315f, +-1.724585f, +-0.195867f, +-1.726657f, +-0.195419f, +-1.728728f, +-0.194972f, +-1.730803f, +-0.194526f, +-1.732878f, +-0.194081f, +-1.734950f, +-0.193637f, +-1.737027f, +-0.193193f, +-1.739108f, +-0.192750f, +-1.741188f, +-0.192308f, +-1.743272f, +-0.191867f, +-1.745355f, +-0.191426f, +-1.747442f, +-0.190986f, +-1.749528f, +-0.190547f, +-1.751618f, +-0.190109f, +-1.753707f, +-0.189671f, +-1.755800f, +-0.189234f, +-1.757897f, +-0.188799f, +-1.759987f, +-0.188363f, +-1.762088f, +-0.187928f, +-1.764187f, +-0.187495f, +-1.766285f, +-0.187062f, +-1.768387f, +-0.186630f, +-1.770493f, +-0.186198f, +-1.772598f, +-0.185768f, +-1.774702f, +-0.185338f, +-1.776810f, +-0.184909f, +-1.778922f, +-0.184481f, +-1.781033f, +-0.184054f, +-1.783143f, +-0.183627f, +-1.785257f, +-0.183201f, +-1.787375f, +-0.182776f, +-1.789492f, +-0.182352f, +-1.791607f, +-0.181927f, +-1.793733f, +-0.181505f, +-1.795852f, +-0.181083f, +-1.797975f, +-0.180661f, +-1.800102f, +-0.180241f, +-1.802228f, +-0.179821f, +-1.804359f, +-0.179402f, +-1.806487f, +-0.178983f, +-1.808621f, +-0.178566f, +-1.810753f, +-0.178149f, +-1.812889f, +-0.177733f, +-1.815024f, +-0.177317f, +-1.817163f, +-0.176902f, +-1.819308f, +-0.176489f, +-1.821444f, +-0.176075f, +-1.823591f, +-0.175663f, +-1.825736f, +-0.175251f, +-1.827880f, +-0.174840f, +-1.830029f, +-0.174431f, +-1.832175f, +-0.174021f, +-1.834327f, +-0.173612f, +-1.836483f, +-0.173204f, +-1.838637f, +-0.172797f, +-1.840790f, +-0.172391f, +-1.842948f, +-0.171985f, +-1.845110f, +-0.171580f, +-1.847270f, +-0.171176f, +-1.849429f, +-0.170773f, +-1.851592f, +-0.170370f, +-1.853760f, +-0.169968f, +-1.855927f, +-0.169566f, +-1.858098f, +-0.169166f, +-1.860267f, +-0.168765f, +-1.862442f, +-0.168367f, +-1.864614f, +-0.167969f, +-1.866785f, +-0.167570f, +-1.868967f, +-0.167174f, +-1.871140f, +-0.166777f, +-1.873325f, +-0.166383f, +-1.875502f, +-0.165987f, +-1.877690f, +-0.165594f, +-1.879870f, +-0.165200f, +-1.882061f, +-0.164809f, +-1.884243f, +-0.164416f, +-1.886437f, +-0.164025f, +-1.888630f, +-0.163635f, +-1.890820f, +-0.163245f, +-1.893015f, +-0.162857f, +-1.895209f, +-0.162468f, +-1.897407f, +-0.162080f, +-1.899610f, +-0.161693f, +-1.901811f, +-0.161308f, +-1.904010f, +-0.160923f, +-1.906215f, +-0.160539f, +-1.908417f, +-0.160154f, +-1.910631f, +-0.159771f, +-1.912836f, +-0.159389f, +-1.915046f, +-0.159006f, +-1.917261f, +-0.158625f, +-1.919475f, +-0.158246f, +-1.921686f, +-0.157866f, +-1.923902f, +-0.157487f, +-1.926123f, +-0.157109f, +-1.928342f, +-0.156731f, +-1.930566f, +-0.156354f, +-1.932789f, +-0.155978f, +-1.935016f, +-0.155603f, +-1.937241f, +-0.155228f, +-1.939471f, +-0.154854f, +-1.941699f, +-0.154481f, +-1.943932f, +-0.154109f, +-1.946163f, +-0.153736f, +-1.948399f, +-0.153366f, +-1.950633f, +-0.152995f, +-1.952872f, +-0.152626f, +-1.955109f, +-0.152256f, +-1.957351f, +-0.151887f, +-1.959599f, +-0.151520f, +-1.961843f, +-0.151153f, +-1.964086f, +-0.150787f, +-1.966334f, +-0.150421f, +-1.968587f, +-0.150056f, +-1.970838f, +-0.149692f, +-1.973087f, +-0.149329f, +-1.975341f, +-0.148965f, +-1.977600f, +-0.148603f, +-1.979857f, +-0.148242f, +-1.982112f, +-0.147881f, +-1.984379f, +-0.147521f, +-1.986636f, +-0.147162f, +-1.988899f, +-0.146803f, +-1.991167f, +-0.146445f, +-1.993433f, +-0.146088f, +-1.995703f, +-0.145731f, +-1.997972f, +-0.145375f, +-2.000246f, +-0.145020f, +-2.002518f, +-0.144665f, +-2.004794f, +-0.144312f, +-2.007069f, +-0.143958f, +-2.009348f, +-0.143605f, +-2.011633f, +-0.143254f, +-2.013908f, +-0.142902f, +-2.016196f, +-0.142551f, +-2.018482f, +-0.142202f, +-2.020765f, +-0.141853f, +-2.023053f, +-0.141504f, +-2.025347f, +-0.141156f, +-2.027639f, +-0.140809f, +-2.029928f, +-0.140463f, +-2.032222f, +-0.140116f, +-2.034522f, +-0.139771f, +-2.036819f, +-0.139426f, +-2.039122f, +-0.139083f, +-2.041421f, +-0.138739f, +-2.043727f, +-0.138397f, +-2.046030f, +-0.138056f, +-2.048331f, +-0.137714f, +-2.050644f, +-0.137373f, +-2.052955f, +-0.137034f, +-2.055264f, +-0.136694f, +-2.057579f, +-0.136356f, +-2.059890f, +-0.136018f, +-2.062207f, +-0.135681f, +-2.064522f, +-0.135344f, +-2.066841f, +-0.135008f, +-2.069167f, +-0.134673f, +-2.071489f, +-0.134339f, +-2.073809f, +-0.134005f, +-2.076135f, +-0.133671f, +-2.078466f, +-0.133338f, +-2.080794f, +-0.133007f, +-2.083120f, +-0.132675f, +-2.085460f, +-0.132345f, +-2.087789f, +-0.132015f, +-2.090122f, +-0.131685f, +-2.092462f, +-0.131357f, +-2.094799f, +-0.131028f, +-2.097141f, +-0.130701f, +-2.099481f, +-0.130374f, +-2.101826f, +-0.130047f, +-2.104177f, +-0.129722f, +-2.106525f, +-0.129397f, +-2.108870f, +-0.129073f, +-2.111221f, +-0.128750f, +-2.113570f, +-0.128427f, +-2.115923f, +-0.128104f, +-2.118282f, +-0.127782f, +-2.120639f, +-0.127461f, +-2.123001f, +-0.127140f, +-2.125360f, +-0.126821f, +-2.127716f, +-0.126502f, +-2.130078f, +-0.126184f, +-2.132446f, +-0.125866f, +-2.134811f, +-0.125548f, +-2.137181f, +-0.125231f, +-2.139557f, +-0.124916f, +-2.141921f, +-0.124600f, +-2.144300f, +-0.124285f, +-2.146676f, +-0.123971f, +-2.149049f, +-0.123658f, +-2.151428f, +-0.123345f, +-2.153812f, +-0.123032f, +-2.156193f, +-0.122721f, +-2.158571f, +-0.122411f, +-2.160955f, +-0.122100f, +-2.163345f, +-0.121790f, +-2.165732f, +-0.121481f, +-2.168124f, +-0.121173f, +-2.170514f, +-0.120865f, +-2.172909f, +-0.120558f, +-2.175300f, +-0.120251f, +-2.177699f, +-0.119945f, +-2.180093f, +-0.119640f, +-2.182494f, +-0.119334f, +-2.184900f, +-0.119030f, +-2.187303f, +-0.118727f, +-2.189703f, +-0.118424f, +-2.192109f, +-0.118122f, +-2.194520f, +-0.117820f, +-2.196929f, +-0.117519f, +-2.199343f, +-0.117218f, +-2.201754f, +-0.116918f, +-2.204170f, +-0.116619f, +-2.206584f, +-0.116320f, +-2.209004f, +-0.116023f, +-2.211420f, +-0.115725f, +-2.213842f, +-0.115429f, +-2.216261f, +-0.115133f, +-2.218685f, +-0.114836f, +-2.221115f, +-0.114541f, +-2.223543f, +-0.114247f, +-2.225976f, +-0.113953f, +-2.228406f, +-0.113660f, +-2.230832f, +-0.113367f, +-2.233273f, +-0.113076f, +-2.235702f, +-0.112784f, +-2.238146f, +-0.112493f, +-2.240587f, +-0.112203f, +-2.243025f, +-0.111913f, +-2.245468f, +-0.111625f, +-2.247907f, +-0.111336f, +-2.250353f, +-0.111048f, +-2.252805f, +-0.110761f, +-2.255253f, +-0.110474f, +-2.257707f, +-0.110188f, +-2.260158f, +-0.109902f, +-2.262615f, +-0.109617f, +-2.265068f, +-0.109333f, +-2.267527f, +-0.109050f, +-2.269983f, +-0.108766f, +-2.272444f, +-0.108483f, +-2.274912f, +-0.108201f, +-2.277375f, +-0.107920f, +-2.279836f, +-0.107640f, +-2.282302f, +-0.107359f, +-2.284775f, +-0.107080f, +-2.287243f, +-0.106800f, +-2.289718f, +-0.106522f, +-2.292189f, +-0.106244f, +-2.294667f, +-0.105967f, +-2.297140f, +-0.105691f, +-2.299620f, +-0.105414f, +-2.302105f, +-0.105138f, +-2.304587f, +-0.104863f, +-2.307075f, +-0.104589f, +-2.309560f, +-0.104315f, +-2.312040f, +-0.104041f, +-2.314536f, +-0.103770f, +-2.317019f, +-0.103497f, +-2.319517f, +-0.103225f, +-2.322013f, +-0.102955f, +-2.324503f, +-0.102684f, +-2.327001f, +-0.102414f, +-2.329504f, +-0.102145f, +-2.332004f, +-0.101876f, +-2.334509f, +-0.101608f, +-2.337011f, +-0.101340f, +-2.339519f, +-0.101073f, +-2.342023f, +-0.100806f, +-2.344533f, +-0.100541f, +-2.347039f, +-0.100276f, +-2.349551f, +-0.100010f, +-2.352070f, +-0.099746f, +-2.354584f, +-0.099482f, +-2.357104f, +-0.099219f, +-2.359621f, +-0.098957f, +-2.362144f, +-0.098695f, +-2.364662f, +-0.098433f, +-2.367188f, +-0.098172f, +-2.369719f, +-0.097912f, +-2.372246f, +-0.097653f, +-2.374769f, +-0.097393f, +-2.377298f, +-0.097134f, +-2.379833f, +-0.096877f, +-2.382364f, +-0.096619f, +-2.384902f, +-0.096361f, +-2.387446f, +-0.096106f, +-2.389975f, +-0.095849f, +-2.392521f, +-0.095594f, +-2.395063f, +-0.095339f, +-2.397610f, +-0.095085f, +-2.400154f, +-0.094831f, +-2.402704f, +-0.094578f, +-2.405249f, +-0.094325f, +-2.407801f, +-0.094073f, +-2.410348f, +-0.093822f, +-2.412902f, +-0.093570f, +-2.415462f, +-0.093320f, +-2.418019f, +-0.093070f, +-2.420581f, +-0.092821f, +-2.423138f, +-0.092572f, +-2.425703f, +-0.092324f, +-2.428261f, +-0.092076f, +-2.430828f, +-0.091828f, +-2.433400f, +-0.091581f, +-2.435968f, +-0.091335f, +-2.438542f, +-0.091090f, +-2.441111f, +-0.090844f, +-2.443688f, +-0.090600f, +-2.446259f, +-0.090356f, +-2.448837f, +-0.090112f, +-2.451422f, +-0.089869f, +-2.454001f, +-0.089626f, +-2.456588f, +-0.089384f, +-2.459168f, +-0.089143f, +-2.461757f, +-0.088902f, +-2.464340f, +-0.088662f, +-2.466929f, +-0.088421f, +-2.469525f, +-0.088182f, +-2.472117f, +-0.087944f, +-2.474703f, +-0.087705f, +-2.477308f, +-0.087467f, +-2.479907f, +-0.087230f, +-2.482502f, +-0.086994f, +-2.485103f, +-0.086757f, +-2.487710f, +-0.086521f, +-2.490313f, +-0.086287f, +-2.492910f, +-0.086051f, +-2.495527f, +-0.085817f, +-2.498138f, +-0.085584f, +-2.500744f, +-0.085351f, +-2.503356f, +-0.085118f, +-2.505975f, +-0.084886f, +-2.508589f, +-0.084654f, +-2.511209f, +-0.084423f, +-2.513825f, +-0.084193f, +-2.516447f, +-0.083962f, +-2.519076f, +-0.083733f, +-2.521700f, +-0.083504f, +-2.524317f, +-0.083275f, +-2.526954f, +-0.083048f, +-2.529573f, +-0.082820f, +-2.532212f, +-0.082593f, +-2.534845f, +-0.082367f, +-2.537473f, +-0.082140f, +-2.540119f, +-0.081915f, +-2.542748f, +-0.081690f, +-2.545396f, +-0.081465f, +-2.548039f, +-0.081241f, +-2.550675f, +-0.081018f, +-2.553318f, +-0.080795f, +-2.555969f, +-0.080573f, +-2.558613f, +-0.080350f, +-2.561265f, +-0.080128f, +-2.563924f, +-0.079907f, +-2.566576f, +-0.079687f, +-2.569223f, +-0.079468f, +-2.571877f, +-0.079248f, +-2.574538f, +-0.079028f, +-2.577206f, +-0.078809f, +-2.579868f, +-0.078592f, +-2.582524f, +-0.078375f, +-2.585187f, +-0.078157f, +-2.587857f, +-0.077940f, +-2.590534f, +-0.077725f, +-2.593191f, +-0.077509f, +-2.595869f, +-0.077294f, +-2.598541f, +-0.077079f, +-2.601220f, +-0.076865f, +-2.603893f, +-0.076651f, +-2.606573f, +-0.076437f, +-2.609259f, +-0.076225f, +-2.611941f, +-0.076013f, +-2.614615f, +-0.075801f, +-2.617310f, +-0.075589f, +-2.619998f, +-0.075379f, +-2.622680f, +-0.075169f, +-2.625369f, +-0.074958f, +-2.628066f, +-0.074749f, +-2.630756f, +-0.074540f, +-2.633453f, +-0.074331f, +-2.636157f, +-0.074124f, +-2.638855f, +-0.073917f, +-2.641547f, +-0.073709f, +-2.644259f, +-0.073503f, +-2.646950f, +-0.073297f, +-2.649663f, +-0.073091f, +-2.652370f, +-0.072886f, +-2.655083f, +-0.072681f, +-2.657790f, +-0.072477f, +-2.660503f, +-0.072274f, +-2.663210f, +-0.072070f, +-2.665939f, +-0.071868f, +-2.668647f, +-0.071665f, +-2.671376f, +-0.071463f, +-2.674098f, +-0.071262f, +-2.676814f, +-0.071061f, +-2.679536f, +-0.070860f, +-2.682265f, +-0.070661f, +-2.684988f, +-0.070461f, +-2.687718f, +-0.070262f, +-2.690456f, +-0.070063f, +-2.693187f, +-0.069865f, +-2.695924f, +-0.069667f, +-2.698654f, +-0.069470f, +-2.701392f, +-0.069273f, +-2.704137f, +-0.069077f, +-2.706876f, +-0.068881f, +-2.709621f, +-0.068686f, +-2.712359f, +-0.068491f, +-2.715105f, +-0.068296f, +-2.717858f, +-0.068102f, +-2.720604f, +-0.067908f, +-2.723357f, +-0.067715f, +-2.726117f, +-0.067522f, +-2.728870f, +-0.067330f, +-2.731631f, +-0.067138f, +-2.734384f, +-0.066947f, +-2.737144f, +-0.066755f, +-2.739912f, +-0.066565f, +-2.742673f, +-0.066375f, +-2.745440f, +-0.066186f, +-2.748201f, +-0.065997f, +-2.750968f, +-0.065808f, +-2.753744f, +-0.065620f, +-2.756511f, +-0.065432f, +-2.759285f, +-0.065244f, +-2.762068f, +-0.065057f, +-2.764843f, +-0.064870f, +-2.767625f, +-0.064685f, +-2.770400f, +-0.064499f, +-2.773181f, +-0.064313f, +-2.775970f, +-0.064129f, +-2.778751f, +-0.063945f, +-2.781541f, +-0.063761f, +-2.784322f, +-0.063577f, +-2.787126f, +-0.063395f, +-2.789906f, +-0.063211f, +-2.792710f, +-0.063029f, +-2.795506f, +-0.062848f, +-2.798293f, +-0.062666f, +-2.801104f, +-0.062485f, +-2.803906f, +-0.062305f, +-2.806700f, +-0.062125f, +-2.809501f, +-0.061946f, +-2.812312f, +-0.061766f, +-2.815129f, +-0.061587f, +-2.817938f, +-0.061410f, +-2.820737f, +-0.061231f, +-2.823562f, +-0.061053f, +-2.826378f, +-0.060877f, +-2.829185f, +-0.060701f, +-2.831999f, +-0.060524f, +-2.834822f, +-0.060348f, +-2.837652f, +-0.060173f, +-2.840473f, +-0.059997f, +-2.843303f, +-0.059823f, +-2.846123f, +-0.059649f, +-2.848951f, +-0.059475f, +-2.851788f, +-0.059302f, +-2.854614f, +-0.059129f, +-2.857450f, +-0.058957f, +-2.860275f, +-0.058784f, +-2.863127f, +-0.058614f, +-2.865951f, +-0.058442f, +-2.868800f, +-0.058271f, +-2.871640f, +-0.058101f, +-2.874489f, +-0.057931f, +-2.877327f, +-0.057762f, +-2.880174f, +-0.057592f, +-2.883029f, +-0.057424f, +-2.885874f, +-0.057255f, +-2.888727f, +-0.057087f, +-2.891589f, +-0.056920f, +-2.894440f, +-0.056752f, +-2.897299f, +-0.056586f, +-2.900149f, +-0.056419f, +-2.903025f, +-0.056254f, +-2.905874f, +-0.056088f, +-2.908748f, +-0.055923f, +-2.911612f, +-0.055758f, +-2.914484f, +-0.055594f, +-2.917346f, +-0.055430f, +-2.920217f, +-0.055266f, +-2.923095f, +-0.055104f, +-2.925964f, +-0.054941f, +-2.928840f, +-0.054778f, +-2.931726f, +-0.054617f, +-2.934599f, +-0.054455f, +-2.937482f, +-0.054294f, +-2.940373f, +-0.054133f, +-2.943253f, +-0.053973f, +-2.946143f, +-0.053813f, +-2.949021f, +-0.053653f, +-2.951926f, +-0.053495f, +-2.954802f, +-0.053335f, +-2.957705f, +-0.053177f, +-2.960597f, +-0.053019f, +-2.963497f, +-0.052862f, +-2.966387f, +-0.052704f, +-2.969305f, +-0.052548f, +-2.972192f, +-0.052391f, +-2.975106f, +-0.052235f, +-2.978010f, +-0.052079f, +-2.980922f, +-0.051924f, +-2.983824f, +-0.051769f, +-2.986733f, +-0.051614f, +-2.989651f, +-0.051461f, +-2.992558f, +-0.051307f, +-2.995472f, +-0.051153f, +-2.998396f, +-0.051001f, +-3.001307f, +-0.050848f, +-3.004228f, +-0.050696f, +-3.007158f, +-0.050544f, +-3.010075f, +-0.050392f, +-3.013021f, +-0.050241f, +-3.015934f, +-0.050090f, +-3.018878f, +-0.049940f, +-3.021809f, +-0.049790f, +-3.024729f, +-0.049640f, +-3.027677f, +-0.049491f, +-3.030613f, +-0.049343f, +-3.033538f, +-0.049193f, +-3.036491f, +-0.049045f, +-3.039434f, +-0.048898f, +-3.042363f, +-0.048750f, +-3.045321f, +-0.048603f, +-3.048268f, +-0.048457f, +-3.051203f, +-0.048310f, +-3.054167f, +-0.048165f, +-3.057118f, +-0.048019f, +-3.060079f, +-0.047874f, +-3.063026f, +-0.047729f, +-3.065984f, +-0.047584f, +-3.068949f, +-0.047441f, +-3.071901f, +-0.047297f, +-3.074862f, +-0.047153f, +-3.077832f, +-0.047011f, +-3.080789f, +-0.046868f, +-3.083756f, +-0.046726f, +-3.086729f, +-0.046583f, +-3.089713f, +-0.046442f, +-3.092684f, +-0.046301f, +-3.095663f, +-0.046160f, +-3.098629f, +-0.046020f, +-3.101604f, +-0.045880f, +-3.104587f, +-0.045740f, +-3.107559f, +-0.045600f, +-3.110560f, +-0.045461f, +-3.113548f, +-0.045323f, +-3.116523f, +-0.045185f, +-3.119505f, +-0.045047f, +-3.122498f, +-0.044908f, +-3.125500f, +-0.044771f, +-3.128486f, +-0.044634f, +-3.131483f, +-0.044497f, +-3.134489f, +-0.044362f, +-3.137480f, +-0.044226f, +-3.140481f, +-0.044090f, +-3.143490f, +-0.043955f, +-3.146485f, +-0.043820f, +-3.149490f, +-0.043685f, +-3.152503f, +-0.043552f, +-3.155502f, +-0.043417f, +-3.158534f, +-0.043284f, +-3.161527f, +-0.043151f, +-3.164554f, +-0.043018f, +-3.167566f, +-0.042886f, +-3.170585f, +-0.042753f, +-3.173616f, +-0.042622f, +-3.176631f, +-0.042490f, +-3.179655f, +-0.042359f, +-3.182689f, +-0.042228f, +-3.185707f, +-0.042098f, +-3.188735f, +-0.041967f, +-3.191771f, +-0.041838f, +-3.194794f, +-0.041709f, +-3.197824f, +-0.041580f, +-3.200864f, +-0.041450f, +-3.203914f, +-0.041322f, +-3.206947f, +-0.041194f, +-3.209991f, +-0.041067f, +-3.213018f, +-0.040939f, +-3.216079f, +-0.040812f, +-3.219126f, +-0.040686f, +-3.222156f, +-0.040558f, +-3.225221f, +-0.040432f, +-3.228270f, +-0.040308f, +-3.231302f, +-0.040182f, +-3.234370f, +-0.040057f, +-3.237422f, +-0.039932f, +-3.240483f, +-0.039807f, +-3.243553f, +-0.039683f, +-3.246607f, +-0.039559f, +-3.249670f, +-0.039435f, +-3.252743f, +-0.039313f, +-3.255799f, +-0.039190f, +-3.258865f, +-0.039067f, +-3.261940f, +-0.038945f, +-3.265024f, +-0.038823f, +-3.268092f, +-0.038701f, +-3.271169f, +-0.038581f, +-3.274229f, +-0.038459f, +-3.277326f, +-0.038339f, +-3.280406f, +-0.038218f, +-3.283495f, +-0.038099f, +-3.286566f, +-0.037979f, +-3.289646f, +-0.037860f, +-3.292738f, +-0.037740f, +-3.295837f, +-0.037622f, +-3.298921f, +-0.037504f, +-3.302012f, +-0.037385f, +-3.305115f, +-0.037268f, +-3.308199f, +-0.037151f, +-3.311293f, +-0.037033f, +-3.314397f, +-0.036916f, +-3.317508f, +-0.036800f, +-3.320603f, +-0.036684f, +-3.323708f, +-0.036567f, +-3.326824f, +-0.036452f, +-3.329919f, +-0.036336f, +-3.333053f, +-0.036222f, +-3.336140f, +-0.036107f, +-3.339266f, +-0.035993f, +-3.342372f, +-0.035879f, +-3.345489f, +-0.035765f, +-3.348614f, +-0.035651f, +-3.351751f, +-0.035538f, +-3.354867f, +-0.035425f, +-3.357994f, +-0.035313f, +-3.361102f, +-0.035200f, +-3.364249f, +-0.035088f, +-3.367377f, +-0.034977f, +-3.370514f, +-0.034866f, +-3.373631f, +-0.034755f, +-3.376759f, +-0.034644f, +-3.379896f, +-0.034533f, +-3.383043f, +-0.034424f, +-3.386172f, +-0.034313f, +-3.389338f, +-0.034204f, +-3.392455f, +-0.034095f, +-3.395614f, +-0.033986f, +-3.398750f, +-0.033877f, +-3.401898f, +-0.033769f, +-3.405056f, +-0.033660f, +-3.408222f, +-0.033553f, +-3.411369f, +-0.033445f, +-3.414526f, +-0.033338f, +-3.417693f, +-0.033231f, +-3.420840f, +-0.033125f, +-3.423996f, +-0.033018f, +-3.427162f, +-0.032912f, +-3.430338f, +-0.032806f, +-3.433493f, +-0.032701f, +-3.436658f, +-0.032595f, +-3.439835f, +-0.032490f, +-3.443020f, +-0.032386f, +-3.446183f, +-0.032281f, +-3.449359f, +-0.032177f, +-3.452542f, +-0.032074f, +-3.455706f, +-0.031971f, +-3.458880f, +-0.031867f, +-3.462063f, +-0.031764f, +-3.465255f, +-0.031662f, +-3.468427f, +-0.031559f, +-3.471641f, +-0.031457f, +-3.474833f, +-0.031355f, +-3.478003f, +-0.031253f, +-3.481215f, +-0.031152f, +-3.484405f, +-0.031051f, +-3.487605f, +-0.030951f, +-3.490783f, +-0.030850f, +-3.494004f, +-0.030750f, +-3.497201f, +-0.030650f, +-3.500411f, +-0.030551f, +-3.503595f, +-0.030451f, +-3.506825f, +-0.030352f, +-3.510030f, +-0.030254f, +-3.513213f, +-0.030155f, +-3.516440f, +-0.030057f, +-3.519644f, +-0.029959f, +-3.522856f, +-0.029861f, +-3.526080f, +-0.029764f, +-3.529315f, +-0.029667f, +-3.532525f, +-0.029570f, +-3.535746f, +-0.029473f, +-3.538977f, +-0.029377f, +-3.542186f, +-0.029280f, +-3.545438f, +-0.029185f, +-3.548666f, +-0.029089f, +-3.551904f, +-0.028994f, +-3.555119f, +-0.028900f, +-3.558342f, +-0.028805f, +-3.561578f, +-0.028710f, +-3.564822f, +-0.028616f, +-3.568079f, +-0.028522f, +-3.571309f, +-0.028428f, +-3.574551f, +-0.028335f, +-3.577803f, +-0.028241f, +-3.581067f, +-0.028148f, +-3.584304f, +-0.028056f, +-3.587552f, +-0.027963f, +-3.590808f, +-0.027872f, +-3.594043f, +-0.027779f, +-3.597323f, +-0.027688f, +-3.600576f, +-0.027596f, +-3.603840f, +-0.027506f, +-3.607078f, +-0.027414f, +-3.610365f, +-0.027324f, +-3.613624f, +-0.027234f, +-3.616893f, +-0.027144f, +-3.620137f, +-0.027054f, +-3.623428f, +-0.026964f, +-3.626694f, +-0.026875f, +-3.629970f, +-0.026786f, +-3.633255f, +-0.026697f, +-3.636515f, +-0.026609f, +-3.639785f, +-0.026521f, +-3.643066f, +-0.026432f, +-3.646358f, +-0.026344f, +-3.649658f, +-0.026257f, +-3.652932f, +-0.026169f, +-3.656220f, +-0.026082f, +-3.659516f, +-0.025995f, +-3.662823f, +-0.025909f, +-3.666101f, +-0.025823f, +-3.669390f, +-0.025736f, +-3.672690f, +-0.025650f, +-3.676003f, +-0.025565f, +-3.679285f, +-0.025480f, +-3.682580f, +-0.025395f, +-3.685883f, +-0.025310f, +-3.689200f, +-0.025225f, +-3.692487f, +-0.025140f, +-3.695823f, +-0.025056f, +-3.699132f, +-0.024972f, +-3.702452f, +-0.024889f, +-3.705740f, +-0.024805f, +-3.709082f, +-0.024722f, +-3.712393f, +-0.024639f, +-3.715716f, +-0.024557f, +-3.719008f, +-0.024474f, +-3.722353f, +-0.024392f, +-3.725667f, +-0.024310f, +-3.728994f, +-0.024228f, +-3.732330f, +-0.024146f, +-3.735678f, +-0.024065f, +-3.738994f, +-0.023984f, +-3.742323f, +-0.023903f, +-3.745661f, +-0.023822f, +-3.749013f, +-0.023743f, +-3.752330f, +-0.023663f, +-3.755661f, +-0.023583f, +-3.759000f, +-0.023503f, +-3.762354f, +-0.023423f, +-3.765718f, +-0.023344f, +-3.769050f, +-0.023266f, +-3.772391f, +-0.023187f, +-3.775745f, +-0.023108f, +-3.779110f, +-0.023029f, +-3.782487f, +-0.022951f, +-3.785831f, +-0.022874f, +-3.789186f, +-0.022796f, +-3.792552f, +-0.022719f, +-3.795885f, +-0.022641f, +-3.799274f, +-0.022565f, +-3.802631f, +-0.022488f, +-3.805998f, +-0.022411f, +-3.809375f, +-0.022336f, +-3.812721f, +-0.022259f, +-3.816122f, +-0.022183f, +-3.819490f, +-0.022108f, +-3.822868f, +-0.022032f, +-3.826259f, +-0.021957f, +-3.829613f, +-0.021882f, +-3.833027f, +-0.021807f, +-3.836406f, +-0.021732f, +-3.839794f, +-0.021659f, +-3.843149f, +-0.021584f, +-3.846563f, +-0.021511f, +-3.849940f, +-0.021437f, +-3.853330f, +-0.021364f, +-3.856730f, +-0.021290f, +-3.860143f, +-0.021218f, +-3.863518f, +-0.021145f, +-3.866905f, +-0.021073f, +-3.870304f, +-0.021000f, +-3.873717f, +-0.020927f, +-3.877139f, +-0.020856f, +-3.880524f, +-0.020784f, +-3.883923f, +-0.020713f, +-3.887330f, +-0.020642f, +-3.890749f, +-0.020570f, +-3.894183f, +-0.020500f, +-3.897579f, +-0.020429f, +-3.900984f, +-0.020358f, +-3.904453f, +-0.020288f, +-3.907831f, +-0.020218f, +-3.911273f, +-0.020149f, +-3.914677f, +-0.020078f, +-3.918143f, +-0.020009f, +-3.921567f, +-0.019941f, +-3.924955f, +-0.019871f, +-3.928406f, +-0.019803f, +-3.931817f, +-0.019733f, +-3.935291f, +-0.019665f, +-3.938726f, +-0.019597f, +-3.942172f, +-0.019529f, +-3.945581f, +-0.019461f, +-3.949051f, +-0.019394f, +-3.952480f, +-0.019327f, +-3.955922f, +-0.019259f, +-3.959378f, +-0.019192f, +-3.962843f, +-0.019126f, +-3.966267f, +-0.019059f, +-3.969705f, +-0.018993f, +-3.973153f, +-0.018927f, +-3.976615f, +-0.018861f, +-3.980086f, +-0.018795f, +-3.983573f, +-0.018729f, +-3.987017f, +-0.018664f, +-3.990470f, +-0.018599f, +-3.993938f, +-0.018534f, +-3.997418f, +-0.018470f, +-4.000854f, +-0.018404f, +-4.004359f, +-0.018340f, +-4.007819f, +-0.018276f, +-4.011292f, +-0.018212f, +-4.014777f, +-0.018148f, +-4.018274f, +-0.018085f, +-4.021727f, +-0.018021f, +-4.025192f, +-0.017958f, +-4.028669f, +-0.017895f, +-4.032158f, +-0.017832f, +-4.035659f, +-0.017769f, +-4.039176f, +-0.017707f, +-4.042644f, +-0.017645f, +-4.046124f, +-0.017583f, +-4.049620f, +-0.017521f, +-4.053125f, +-0.017459f, +-4.056645f, +-0.017397f, +-4.060116f, +-0.017336f, +-4.063602f, +-0.017275f, +-4.067100f, +-0.017214f, +-4.070608f, +-0.017153f, +-4.074131f, +-0.017092f, +-4.077666f, +-0.017032f, +-4.081151f, +-0.016972f, +-4.084651f, +-0.016912f, +-4.088163f, +-0.016852f, +-4.091688f, +-0.016792f, +-4.095226f, +-0.016733f, +-4.098715f, +-0.016674f, +-4.102216f, +-0.016614f, +-4.105790f, +-0.016555f, +-4.109316f, +-0.016497f, +-4.112793f, +-0.016438f, +-4.116344f, +-0.016380f, +-4.119849f, +-0.016321f, +-4.123425f, +-0.016264f, +-4.126951f, +-0.016206f, +-4.130489f, +-0.016149f, +-4.133981f, +-0.016091f, +-4.137544f, +-0.016034f, +-4.141060f, +-0.015976f, +-4.144649f, +-0.015919f, +-4.148187f, +-0.015862f, +-4.151741f, +-0.015806f, +-4.155243f, +-0.015749f, +-4.158818f, +-0.015693f, +-4.162345f, +-0.015637f, +-4.165946f, +-0.015581f, +-4.169498f, +-0.015526f, +-4.172997f, +-0.015470f, +-4.176575f, +-0.015414f, +-4.180165f, +-0.015359f, +-4.183702f, +-0.015304f, +-4.187251f, +-0.015250f, +-4.190813f, +-0.015195f, +-4.194388f, +-0.015140f, +-4.197975f, +-0.015085f, +-4.201575f, +-0.015031f, +-4.205121f, +-0.014978f, +-4.208679f, +-0.014924f, +-4.212250f, +-0.014870f, +-4.215833f, +-0.014816f, +-4.219430f, +-0.014763f, +-4.222974f, +-0.014710f, +-4.226596f, +-0.014657f, +-4.230166f, +-0.014604f, +-4.233745f, +-0.014551f, +-4.237336f, +-0.014499f, +-4.240945f, +-0.014447f, +-4.244492f, +-0.014394f, +-4.248126f, +-0.014342f, +-4.251699f, +-0.014291f, +-4.255288f, +-0.014239f, +-4.258890f, +-0.014187f, +-4.262501f, +-0.014135f, +-4.266130f, +-0.014085f, +-4.269699f, +-0.014033f, +-4.273350f, +-0.013982f, +-4.276945f, +-0.013932f, +-4.280553f, +-0.013881f, +-4.284174f, +-0.013831f, +-4.287734f, +-0.013781f, +-4.291382f, +-0.013731f, +-4.294968f, +-0.013680f, +-4.298642f, +-0.013630f, +-4.302255f, +-0.013581f, +-4.305880f, +-0.013531f, +-4.309519f, +-0.013482f, +-4.313100f, +-0.013433f, +-4.316765f, +-0.013384f, +-4.320368f, +-0.013336f, +-4.323983f, +-0.013287f, +-4.327616f, +-0.013238f, +-4.331258f, +-0.013190f, +-4.334913f, +-0.013141f, +-4.338582f, +-0.013093f, +-4.342191f, +-0.013046f, +-4.345813f, +-0.012998f, +-4.349443f, +-0.012950f, +-4.353091f, +-0.012903f, +-4.356748f, +-0.012855f, +-4.360423f, +-0.012808f, +-4.364107f, +-0.012761f, +-4.367730f, +-0.012714f, +-4.371365f, +-0.012668f, +-4.375009f, +-0.012621f, +-4.378672f, +-0.012575f, +-4.382347f, +-0.012528f, +-4.386036f, +-0.012483f, +-4.389657f, +-0.012436f, +-4.393369f, +-0.012390f, +-4.397017f, +-0.012345f, +-4.400678f, +-0.012299f, +-4.404353f, +-0.012254f, +-4.408041f, +-0.012209f, +-4.411659f, +-0.012164f, +-4.415374f, +-0.012119f, +-4.419024f, +-0.012074f, +-4.422767f, +-0.012029f, +-4.426439f, +-0.011985f, +-4.430125f, +-0.011940f, +-4.433824f, +-0.011896f, +-4.437457f, +-0.011852f, +-4.441183f, +-0.011808f, +-4.444837f, +-0.011765f, +-4.448510f, +-0.011720f, +-4.452278f, +-0.011677f, +-4.455973f, +-0.011634f, +-4.459599f, +-0.011591f, +-4.463322f, +-0.011547f, +-4.467063f, +-0.011505f, +-4.470724f, +-0.011462f, +-4.474405f, +-0.011419f, +-4.478183f, +-0.011376f, +-4.481890f, +-0.011334f, +-4.485612f, +-0.011292f, +-4.489257f, +-0.011250f, +-4.493001f, +-0.011209f, +-4.496674f, +-0.011166f, +-4.500451f, +-0.011125f, +-4.504151f, +-0.011083f, +-4.507865f, +-0.011042f, +-4.511587f, +-0.011000f, +-4.515328f, +-0.010959f, +-4.519084f, +-0.010918f, +-4.522760f, +-0.010877f, +-4.526543f, +-0.010837f, +-4.530247f, +-0.010796f, +-4.533965f, +-0.010756f, +-4.537697f, +-0.010715f, +-4.541442f, +-0.010675f, +-4.545207f, +-0.010635f, +-4.548885f, +-0.010595f, +-4.552673f, +-0.010556f, +-4.556379f, +-0.010515f, +-4.560195f, +-0.010476f, +-4.563934f, +-0.010436f, +-4.567682f, +-0.010397f, +-4.571444f, +-0.010358f, +-4.575127f, +-0.010319f, +-4.578917f, +-0.010280f, +-4.582722f, +-0.010241f, +-4.586447f, +-0.010203f, +-4.590180f, +-0.010164f, +-4.593933f, +-0.010126f, +-4.597701f, +-0.010088f, +-4.601477f, +-0.010049f, +-4.605272f, +-0.010011f, +-4.609077f, +-0.009974f, +-4.612800f, +-0.009936f, +-4.616537f, +-0.009898f, +-4.620384f, +-0.009860f, +-4.624149f, +-0.009823f, +-4.627929f, +-0.009786f, +-4.631717f, +-0.009749f, +-4.635420f, +-0.009712f, +-4.639243f, +-0.009675f, +-4.643080f, +-0.009638f, +-4.646826f, +-0.009602f, +-4.650587f, +-0.009566f, +-4.654361f, +-0.009528f, +-4.658257f, +-0.009493f, +-4.661953f, +-0.009457f, +-4.665771f, +-0.009420f, +-4.669603f, +-0.009384f, +-4.673450f, +-0.009349f, +-4.677203f, +-0.009313f, +-4.680971f, +-0.009277f, +-4.684862f, +-0.009242f, +-4.688658f, +-0.009206f, +-4.692475f, +-0.009172f, +-4.696189f, +-0.009137f, +-4.700029f, +-0.009101f, +-4.703883f, +-0.009067f, +-4.707647f, +-0.009032f, +-4.711531f, +-0.008997f, +-4.715317f, +-0.008963f, +-4.719124f, +-0.008929f, +-4.722939f, +-0.008894f, +-4.726775f, +-0.008860f, +-4.730619f, +-0.008826f, +-4.734485f, +-0.008793f, +-4.738243f, +-0.008758f, +-4.742138f, +-0.008725f, +-4.745925f, +-0.008691f, +-4.749851f, +-0.008657f, +-4.753667f, +-0.008624f, +-4.757506f, +-0.008591f, +-4.761358f, +-0.008558f, +-4.765219f, +-0.008525f, +-4.768983f, +-0.008492f, +-4.772880f, +-0.008460f, +-4.776672f, +-0.008426f, +-4.780593f, +-0.008394f, +-4.784415f, +-0.008362f, +-4.788251f, +-0.008330f, +-4.792102f, +-0.008297f, +-4.795969f, +-0.008265f, +-4.799850f, +-0.008233f, +-4.803746f, +-0.008202f, +-4.807533f, +-0.008169f, +-4.811460f, +-0.008138f, +-4.815277f, +-0.008106f, +-4.819234f, +-0.008074f, +-4.823080f, +-0.008043f, +-4.826942f, +-0.008012f, +-4.830818f, +-0.007981f, +-4.834710f, +-0.007951f, +-4.838489f, +-0.007919f, +-4.842410f, +-0.007888f, +-4.846347f, +-0.007858f, +-4.850178f, +-0.007827f, +-4.854146f, +-0.007796f, +-4.857999f, +-0.007766f, +-4.861867f, +-0.007736f, +-4.865758f, +-0.007706f, +-4.869656f, +-0.007675f, +-4.873569f, +-0.007646f, +-4.877373f, +-0.007616f, +-4.881317f, +-0.007586f, +-4.885284f, +-0.007556f, +-4.889125f, +-0.007527f, +-4.892988f, +-0.007497f, +-4.896994f, +-0.007468f, +-4.900888f, +-0.007439f, +-4.904789f, +-0.007409f, +-4.908714f, +-0.007380f, +-4.912646f, +-0.007352f, +-4.916463f, +-0.007323f, +-4.920425f, +-0.007295f, +-4.924273f, +-0.007265f, +-4.928274f, +-0.007237f, +-4.932144f, +-0.007209f, +-4.936036f, +-0.007180f, +-4.940085f, +-0.007151f, +-4.944009f, +-0.007123f, +-4.947940f, +-0.007096f, +-4.951751f, +-0.007068f, +-4.955720f, +-0.007040f, +-4.959706f, +-0.007013f, +-4.963562f, +-0.006984f, +-4.967579f, +-0.006957f, +-4.971466f, +-0.006929f, +-4.975507f, +-0.006902f, +-4.979425f, +-0.006875f, +-4.983358f, +-0.006847f, +-4.987307f, +-0.006820f, +-4.991272f, +-0.006793f, +-4.995252f, +-0.006767f, +-4.999098f, +-0.006740f, +-5.003110f, +-0.006713f, +-5.006995f, +-0.006686f, +-5.011039f, +-0.006660f, +-5.014946f, +-0.006634f, +-5.018869f, +-0.006607f, +-5.022961f, +-0.006581f, +-5.026915f, +-0.006554f, +-5.030885f, +-0.006528f, +-5.034880f, +-0.006503f, +-5.038725f, +-0.006477f, +-5.042743f, +-0.006451f, +-5.046785f, +-0.006426f, +-5.050677f, +-0.006399f, +-5.054743f, +-0.006374f, +-5.058675f, +-0.006349f, +-5.062613f, +-0.006324f, +-5.066567f, +-0.006299f, +-5.070546f, +-0.006274f, +-5.074531f, +-0.006248f, +-5.078542f, +-0.006223f, +-5.082560f, +-0.006198f, +-5.086603f, +-0.006174f, +-5.090488f, +-0.006149f, +-5.094564f, +-0.006125f, +-5.098480f, +-0.006100f, +-5.102589f, +-0.006075f, +-5.106537f, +-0.006051f, +-5.110510f, +-0.006027f, +-5.114500f, +-0.006002f, +-5.118665f, +-0.005979f, +-5.122517f, +-0.005955f, +-5.126555f, +-0.005931f, +-5.130599f, +-0.005906f, +-5.134669f, +-0.005883f, +-5.138584f, +-0.005859f, +-5.142687f, +-0.005836f, +-5.146623f, +-0.005812f, +-5.150759f, +-0.005789f, +-5.154738f, +-0.005766f, +-5.158732f, +-0.005742f, +-5.162742f, +-0.005719f, +-5.166768f, +-0.005696f, +-5.170800f, +-0.005673f, +-5.174859f, +-0.005650f, +-5.178934f, +-0.005627f, +-5.183026f, +-0.005605f, +-5.186953f, +-0.005582f, +-5.191078f, +-0.005559f, +-5.195038f, +-0.005536f, +-5.199196f, +-0.005514f, +-5.203188f, +-0.005492f, +-5.207196f, +-0.005470f, +-5.211220f, +-0.005448f, +-5.215260f, +-0.005426f, +-5.219316f, +-0.005404f, +-5.223400f, +-0.005381f, +-5.227490f, +-0.005359f, +-5.231596f, +-0.005338f, +-5.235529f, +-0.005316f, +-5.239669f, +-0.005294f, +-5.243826f, +-0.005273f, +-5.247819f, +-0.005252f, +-5.251816f, +-0.005230f, +-5.256024f, +-0.005209f, +-5.260054f, +-0.005187f, +-5.264113f, +-0.005166f, +-5.268176f, +-0.005145f, +-5.272256f, +-0.005124f, +-5.276364f, +-0.005103f, +-5.280478f, +-0.005083f, +-5.284420f, +-0.005062f, +-5.288567f, +-0.005041f, +-5.292731f, +-0.005021f, +-5.296722f, +-0.004999f, +-5.300920f, +-0.004979f, +-5.304944f, +-0.004959f, +-5.308973f, +-0.004939f, +-5.313029f, +-0.004918f, +-5.317297f, +-0.004898f, +-5.321387f, +-0.004878f, +-5.325482f, +-0.004858f, +-5.329606f, +-0.004839f, +-5.333525f, +-0.004819f, +-5.337683f, +-0.004799f, +-5.341846f, +-0.004778f, +-5.346038f, +-0.004759f, +-5.350035f, +-0.004739f, +-5.354249f, +-0.004720f, +-5.358279f, +-0.004701f, +-5.362325f, +-0.004681f, +-5.366591f, +-0.004662f, +-5.370671f, +-0.004643f, +-5.374767f, +-0.004624f, +-5.378881f, +-0.004605f, +-5.382998f, +-0.004586f, +-5.387145f, +-0.004566f, +-5.391310f, +-0.004547f, +-5.395492f, +-0.004529f, +-5.399468f, +-0.004510f, +-5.403684f, +-0.004491f, +-5.407905f, +-0.004473f, +-5.411930f, +-0.004454f, +-5.416200f, +-0.004436f, +-5.420258f, +-0.004418f, +-5.424334f, +-0.004400f, +-5.428426f, +-0.004381f, +-5.432766f, +-0.004362f, +-5.436893f, +-0.004344f, +-5.441037f, +-0.004326f, +-5.445198f, +-0.004308f, +-5.449376f, +-0.004291f, +-5.453336f, +-0.004273f, +-5.457548f, +-0.004255f, +-5.461779f, +-0.004237f, +-5.466027f, +-0.004220f, +-5.470053f, +-0.004202f, +-5.474337f, +-0.004185f, +-5.478396f, +-0.004167f, +-5.482716f, +-0.004150f, +-5.486824f, +-0.004133f, +-5.490935f, +-0.004115f, +-5.495063f, +-0.004098f, +-5.499208f, +-0.004081f, +-5.503370f, +-0.004064f, +-5.507564f, +-0.004047f, +-5.511761f, +-0.004030f, +-5.515975f, +-0.004013f, +-5.520208f, +-0.003996f, +-5.524459f, +-0.003980f, +-5.528487f, +-0.003963f, +-5.532773f, +-0.003946f, +-5.537077f, +-0.003930f, +-5.541157f, +-0.003913f, +-5.545498f, +-0.003897f, +-5.549597f, +-0.003881f, +-5.553728f, +-0.003864f, +-5.557861f, +-0.003847f, +-5.562275f, +-0.003831f, +-5.566459f, +-0.003815f, +-5.570646f, +-0.003799f, +-5.574865f, +-0.003783f, +-5.579086f, +-0.003767f, +-5.583342f, +-0.003752f, +-5.587328f, +-0.003736f, +-5.591619f, +-0.003720f, +-5.595912f, +-0.003704f, +-5.600240f, +-0.003689f, +-5.604294f, +-0.003673f, +-5.608659f, +-0.003658f, +-5.612748f, +-0.003642f, +-5.617149f, +-0.003627f, +-5.621273f, +-0.003612f, +-5.625431f, +-0.003596f, +-5.629606f, +-0.003580f, +-5.634066f, +-0.003565f, +-5.638278f, +-0.003550f, +-5.642507f, +-0.003535f, +-5.646737f, +-0.003520f, +-5.651003f, +-0.003505f, +-5.655286f, +-0.003491f, +-5.659280f, +-0.003476f, +-5.663600f, +-0.003461f, +-5.667938f, +-0.003446f, +-5.672277f, +-0.003432f, +-5.676357f, +-0.003417f, +-5.680751f, +-0.003403f, +-5.684866f, +-0.003388f, +-5.689280f, +-0.003374f, +-5.693430f, +-0.003360f, +-5.697598f, +-0.003345f, +-5.702086f, +-0.003331f, +-5.706290f, +-0.003316f, +-5.710512f, +-0.003302f, +-5.714751f, +-0.003288f, +-5.718990f, +-0.003274f, +-5.723266f, +-0.003260f, +-5.727560f, +-0.003246f, +-5.731873f, +-0.003232f, +-5.736204f, +-0.003218f, +-5.740554f, +-0.003204f, +-5.744923f, +-0.003191f, +-5.748993f, +-0.003177f, +-5.753399f, +-0.003164f, +-5.757504f, +-0.003150f, +-5.761948f, +-0.003137f, +-5.766088f, +-0.003123f, +-5.770570f, +-0.003110f, +-5.774746f, +-0.003096f, +-5.779268f, +-0.003083f, +-5.783480f, +-0.003070f, +-5.787711f, +-0.003057f, +-5.791959f, +-0.003044f, +-5.796226f, +-0.003031f, +-5.800511f, +-0.003018f, +-5.804814f, +-0.003005f, +-5.809136f, +-0.002991f, +-5.813477f, +-0.002978f, +-5.817856f, +-0.002965f, +-5.822235f, +-0.002952f, +-5.826633f, +-0.002940f, +-5.830705f, +-0.002927f, +-5.835141f, +-0.002914f, +-5.839596f, +-0.002902f, +-5.843742f, +-0.002889f, +-5.848236f, +-0.002877f, +-5.852397f, +-0.002864f, +-5.856930f, +-0.002852f, +-5.861128f, +-0.002840f, +-5.865365f, +-0.002827f, +-5.869957f, +-0.002815f, +-5.874210f, +-0.002803f, +-5.878502f, +-0.002791f, +-5.882792f, +-0.002779f, +-5.887100f, +-0.002767f, +-5.891448f, +-0.002755f, +-5.895793f, +-0.002743f, +-5.900158f, +-0.002731f, +-5.904563f, +-0.002719f, +-5.908966f, +-0.002707f, +-5.913389f, +-0.002696f, +-5.917477f, +-0.002684f, +-5.921937f, +-0.002672f, +-5.926417f, +-0.002661f, +-5.930559f, +-0.002649f, +-5.935078f, +-0.002636f, +-5.939641f, +-0.002625f, +-5.943815f, +-0.002614f, +-5.948029f, +-0.002602f, +-5.952628f, +-0.002591f, +-5.956880f, +-0.002579f, +-5.961520f, +-0.002568f, +-5.965787f, +-0.002557f, +-5.970095f, +-0.002546f, +-5.974422f, +-0.002535f, +-5.978744f, +-0.002524f, +-5.983108f, +-0.002513f, +-5.987468f, +-0.002502f, +-5.991871f, +-0.002491f, +-5.996269f, +-0.002480f, +-6.000711f, +-0.002469f, +-6.005149f, +-0.002458f, +-6.009630f, +-0.002447f, +-6.014107f, +-0.002437f, +-6.018213f, +-0.002426f, +-6.022754f, +-0.002415f, +-6.027290f, +-0.002405f, +-6.031450f, +-0.002394f, +-6.036052f, +-0.002384f, +-6.040223f, +-0.002373f, +-6.044865f, +-0.002363f, +-6.049099f, +-0.002352f, +-6.053757f, +-0.002342f, +-6.058029f, +-0.002332f, +-6.062320f, +-0.002321f, +-6.067040f, +-0.002311f, +-6.071369f, +-0.002301f, +-6.075717f, +-0.002291f, +-6.080084f, +-0.002281f, +-6.084470f, +-0.002271f, +-6.088850f, +-0.002260f, +-6.093723f, +-0.002251f, +-6.097719f, +-0.002240f, +-6.102184f, +-0.002231f, +-6.106641f, +-0.002220f, +-6.111146f, +-0.002210f, +-6.115671f, +-0.002200f, +-6.120216f, +-0.002190f, +-6.124755f, +-0.002181f, +-6.128877f, +-0.002171f, +-6.133483f, +-0.002161f, +-6.138110f, +-0.002152f, +-6.142288f, +-0.002142f, +-6.146956f, +-0.002133f, +-6.151171f, +-0.002123f, +-6.155881f, +-0.002114f, +-6.160133f, +-0.002104f, +-6.164858f, +-0.002095f, +-6.169149f, +-0.002086f, +-6.173458f, +-0.002076f, +-6.178275f, +-0.002067f, +-6.182624f, +-0.002058f, +-6.186992f, +-0.002049f, +-6.191379f, +-0.002040f, +-6.195785f, +-0.002031f, +-6.200211f, +-0.002022f, +-6.204657f, +-0.002012f, +-6.209627f, +-0.002003f, +-6.214114f, +-0.001995f, +-6.218114f, +-0.001986f, +-6.222640f, +-0.001977f, +-6.227187f, +-0.001968f, +-6.231754f, +-0.001959f, +-6.236343f, +-0.001950f, +-6.240953f, +-0.001942f, +-6.245061f, +-0.001933f, +-6.249711f, +-0.001924f, +-6.254383f, +-0.001916f, +-6.258547f, +-0.001907f, +-6.263261f, +-0.001898f, +-6.267996f, +-0.001890f, +-6.272249f, +-0.001881f, +-6.277028f, +-0.001873f, +-6.281288f, +-0.001865f, +-6.285566f, +-0.001856f, +-6.290408f, +-0.001848f, +-6.294726f, +-0.001839f, +-6.299613f, +-0.001831f, +-6.303971f, +-0.001823f, +-6.308380f, +-0.001815f, +-6.312775f, +-0.001807f, +-6.317191f, +-0.001798f, +-6.322189f, +-0.001790f, +-6.326646f, +-0.001782f, +-6.331157f, +-0.001774f, +-6.335654f, +-0.001766f, +-6.340172f, +-0.001758f, +-6.344710f, +-0.001750f, +-6.349268f, +-0.001741f, +-6.353882f, +-0.001733f, +-6.358483f, +-0.001727f, +-6.362518f, +-0.001718f, +-6.367193f, +-0.001710f, +-6.371856f, +-0.001702f, +-6.376541f, +-0.001694f, +-6.381247f, +-0.001687f, +-6.385410f, +-0.001679f, +-6.390159f, +-0.001671f, +-6.394930f, +-0.001664f, +-6.399115f, +-0.001656f, +-6.403965f, +-0.001649f, +-6.408187f, +-0.001641f, +-6.413046f, +-0.001634f, +-6.417344f, +-0.001626f, +-6.422247f, +-0.001619f, +-6.426547f, +-0.001612f, +-6.430904f, +-0.001604f, +-6.435874f, +-0.001597f, +-6.440271f, +-0.001590f, +-6.444650f, +-0.001582f, +-6.449689f, +-0.001575f, +-6.454148f, +-0.001568f, +-6.458588f, +-0.001561f, +-6.463087f, +-0.001554f, +-6.467567f, +-0.001547f, +-6.472068f, +-0.001539f, +-6.477286f, +-0.001532f, +-6.481831f, +-0.001525f, +-6.486435f, +-0.001518f, +-6.491022f, +-0.001511f, +-6.495630f, +-0.001504f, +-6.500298f, +-0.001498f, +-6.504312f, +-0.001491f, +-6.508981f, +-0.001484f, +-6.513673f, +-0.001477f, +-6.518426f, +-0.001470f, +-6.523162f, +-0.001464f, +-6.527269f, +-0.001457f, +-6.532047f, +-0.001450f, +-6.536889f, +-0.001443f, +-6.541714f, +-0.001437f, +-6.545897f, +-0.001430f, +-6.550765f, +-0.001424f, +-6.554987f, +-0.001417f, +-6.559900f, +-0.001410f, +-6.564879f, +-0.001404f, +-6.569161f, +-0.001398f, +-6.573418f, +-0.001391f, +-6.578466f, +-0.001385f, +-6.582763f, +-0.001378f, +-6.587858f, +-0.001372f, +-6.592196f, +-0.001365f, +-6.597339f, +-0.001359f, +-6.601762f, +-0.001353f, +-6.606161f, +-0.001347f, +-6.610624f, +-0.001340f, +-6.615819f, +-0.001334f, +-6.620325f, +-0.001328f, +-6.624851f, +-0.001322f, +-6.629353f, +-0.001316f, +-6.633920f, +-0.001310f, +-6.638509f, +-0.001304f, +-6.643073f, +-0.001297f, +-6.648485f, +-0.001291f, +-6.653095f, +-0.001285f, +-6.657773f, +-0.001279f, +-6.662472f, +-0.001274f, +-6.666397f, +-0.001268f, +-6.671091f, +-0.001262f, +-6.675854f, +-0.001256f, +-6.680639f, +-0.001250f, +-6.685400f, +-0.001244f, +-6.690231f, +-0.001238f, +-6.695086f, +-0.001233f, +-6.699094f, +-0.001227f, +-6.703992f, +-0.001221f, +-6.708914f, +-0.001215f, +-6.713812f, +-0.001210f, +-6.717945f, +-0.001204f, +-6.722936f, +-0.001198f, +-6.727953f, +-0.001193f, +-6.732145f, +-0.001187f, +-6.737158f, +-0.001182f, +-6.741388f, +-0.001176f, +-6.746499f, +-0.001171f, +-6.750769f, +-0.001165f, +-6.755877f, +-0.001160f, +-6.760187f, +-0.001154f, +-6.765395f, +-0.001149f, +-6.769747f, +-0.001143f, +-6.774952f, +-0.001138f, +-6.779346f, +-0.001133f, +-6.783759f, +-0.001127f, +-6.789091f, +-0.001122f, +-6.793548f, +-0.001117f, +-6.798024f, +-0.001112f, +-6.802521f, +-0.001106f, +-6.807900f, +-0.001101f, +-6.812442f, +-0.001096f, +-6.817004f, +-0.001091f, +-6.821587f, +-0.001086f, +-6.826191f, +-0.001081f, +-6.830816f, +-0.001075f, +-6.836350f, +-0.001070f, +-6.841023f, +-0.001065f, +-6.845718f, +-0.001060f, +-6.850434f, +-0.001055f, +-6.855173f, +-0.001050f, +-6.859935f, +-0.001045f, +-6.864719f, +-0.001040f, +-6.869469f, +-0.001035f, +-6.874300f, +-0.001031f, +-6.878169f, +-0.001026f, +-6.883042f, +-0.001021f, +-6.887939f, +-0.001016f, +-6.892859f, +-0.001011f, +-6.897804f, +-0.001005f, +-6.902774f, +-0.001002f, +-6.906755f, +-0.000996f, +-6.911770f, +-0.000991f, +-6.916809f, +-0.000986f, +-6.921874f, +-0.000982f, +-6.925933f, +-0.000977f, +-6.931045f, +-0.000972f, +-6.936183f, +-0.000968f, +-6.940300f, +-0.000963f, +-6.945486f, +-0.000959f, +-6.949641f, +-0.000954f, +-6.954876f, +-0.000949f, +-6.960075f, +-0.000945f, +-6.964355f, +-0.000940f, +-6.969604f, +-0.000936f, +-6.973925f, +-0.000931f, +-6.979225f, +-0.000927f, +-6.983588f, +-0.000923f, +-6.987905f, +-0.000918f, +-6.993345f, +-0.000914f, +-6.997704f, +-0.000909f, +-7.003198f, +-0.000905f, +-7.007601f, +-0.000901f, +-7.012023f, +-0.000896f, +-7.017596f, +-0.000892f, +-7.022063f, +-0.000888f, +-7.026550f, +-0.000884f, +-7.031057f, +-0.000879f, +-7.036737f, +-0.000875f, +-7.041291f, +-0.000871f, +-7.045866f, +-0.000867f, +-7.050461f, +-0.000863f, +-7.055078f, +-0.000858f, +-7.060896f, +-0.000854f, +-7.065561f, +-0.000850f, +-7.070249f, +-0.000846f, +-7.074958f, +-0.000842f, +-7.079760f, +-0.000838f, +-7.084514f, +-0.000834f, +-7.089291f, +-0.000830f, +-7.094091f, +-0.000826f, +-7.098914f, +-0.000822f, +-7.103761f, +-0.000818f, +-7.108631f, +-0.000814f, +-7.113525f, +-0.000810f, +-7.118443f, +-0.000806f, +-7.123459f, +-0.000802f, +-7.128426f, +-0.000798f, +-7.133418f, +-0.000794f, +-7.138435f, +-0.000791f, +-7.142196f, +-0.000787f, +-7.147257f, +-0.000783f, +-7.152344f, +-0.000779f, +-7.157534f, +-0.000775f, +-7.162674f, +-0.000772f, +-7.166527f, +-0.000768f, +-7.171713f, +-0.000764f, +-7.176927f, +-0.000760f, +-7.182167f, +-0.000757f, +-7.186175f, +-0.000753f, +-7.191465f, +-0.000749f, +-7.196782f, +-0.000746f, +-7.200769f, +-0.000742f, +-7.206137f, +-0.000739f, +-7.210242f, +-0.000735f, +-7.215661f, +-0.000731f, +-7.221109f, +-0.000728f, +-7.225194f, +-0.000724f, +-7.230695f, +-0.000721f, +-7.234902f, +-0.000717f, +-7.240457f, +-0.000714f, +-7.244622f, +-0.000710f, +-7.250231f, +-0.000707f, +-7.254521f, +-0.000703f, +-7.260186f, +-0.000700f, +-7.264435f, +-0.000696f, +-7.270156f, +-0.000693f, +-7.274447f, +-0.000690f, +-7.278843f, +-0.000686f, +-7.284648f, +-0.000683f, +-7.289002f, +-0.000680f, +-7.293375f, +-0.000676f, +-7.299353f, +-0.000673f, +-7.303771f, +-0.000670f, +-7.308209f, +-0.000666f, +-7.314187f, +-0.000663f, +-7.318762f, +-0.000660f, +-7.323267f, +-0.000657f, +-7.327793f, +-0.000653f, +-7.333890f, +-0.000650f, +-7.338556f, +-0.000647f, +-7.343151f, +-0.000644f, +-7.347768f, +-0.000641f, +-7.352499f, +-0.000637f, +-7.358749f, +-0.000634f, +-7.363439f, +-0.000631f, +-7.368245f, +-0.000628f, +-7.372979f, +-0.000625f, +-7.377736f, +-0.000622f, +-7.382612f, +-0.000619f, +-7.387415f, +-0.000616f, +-7.392241f, +-0.000613f, +-7.397188f, +-0.000610f, +-7.402062f, +-0.000607f, +-7.406959f, +-0.000604f, +-7.411980f, +-0.000601f, +-7.416926f, +-0.000598f, +-7.421897f, +-0.000595f, +-7.426994f, +-0.000592f, +-7.432015f, +-0.000589f, +-7.437062f, +-0.000586f, +-7.442236f, +-0.000583f, +-7.447335f, +-0.000580f, +-7.452460f, +-0.000577f, +-7.457715f, +-0.000574f, +-7.462894f, +-0.000572f, +-7.466327f, +-0.000569f, +-7.471655f, +-0.000566f, +-7.476906f, +-0.000563f, +-7.482186f, +-0.000560f, +-7.487599f, +-0.000558f, +-7.491118f, +-0.000555f, +-7.496581f, +-0.000552f, +-7.501965f, +-0.000549f, +-7.507379f, +-0.000547f, +-7.511077f, +-0.000544f, +-7.516540f, +-0.000541f, +-7.522143f, +-0.000538f, +-7.527668f, +-0.000536f, +-7.531331f, +-0.000533f, +-7.537018f, +-0.000530f, +-7.542625f, +-0.000528f, +-7.546456f, +-0.000525f, +-7.552117f, +-0.000522f, +-7.557809f, +-0.000520f, +-7.561699f, +-0.000517f, +-7.567447f, +-0.000515f, +-7.571374f, +-0.000512f, +-7.577178f, +-0.000510f, +-7.581144f, +-0.000507f, +-7.587005f, +-0.000504f, +-7.592901f, +-0.000502f, +-7.596930f, +-0.000499f, +-7.602884f, +-0.000497f, +-7.606954f, +-0.000494f, +-7.612968f, +-0.000492f, +-7.617079f, +-0.000489f, +-7.623155f, +-0.000487f, +-7.627186f, +-0.000485f, +-7.631355f, +-0.000482f, +-7.637519f, +-0.000480f, +-7.641732f, +-0.000477f, +-7.647961f, +-0.000475f, +-7.652218f, +-0.000472f, +-7.658512f, +-0.000470f, +-7.662815f, +-0.000468f, +-7.667009f, +-0.000465f, +-7.673525f, +-0.000463f, +-7.677764f, +-0.000461f, +-7.682151f, +-0.000458f, +-7.688637f, +-0.000456f, +-7.693071f, +-0.000454f, +-7.697394f, +-0.000451f, +-7.703980f, +-0.000449f, +-7.708484f, +-0.000447f, +-7.713007f, +-0.000445f, +-7.717418f, +-0.000442f, +-7.724137f, +-0.000440f, +-7.728732f, +-0.000438f, +-7.733349f, +-0.000436f, +-7.737850f, +-0.000434f, +-7.742509f, +-0.000431f, +-7.749400f, +-0.000429f, +-7.754113f, +-0.000427f, +-7.758709f, +-0.000425f, +-7.763466f, +-0.000423f, +-7.768105f, +-0.000420f, +-7.775317f, +-0.000418f, +-7.780011f, +-0.000416f, +-7.784871f, +-0.000414f, +-7.789611f, +-0.000412f, +-7.794518f, +-0.000410f, +-7.799304f, +-0.000408f, +-7.804259f, +-0.000406f, +-7.809091f, +-0.000404f, +-7.814095f, +-0.000402f, +-7.819124f, +-0.000400f, +-7.824029f, +-0.000398f, +-7.829108f, +-0.000396f, +-7.834063f, +-0.000393f, +-7.841769f, +-0.000391f, +-7.846786f, +-0.000389f, +-7.851983f, +-0.000387f, +-7.857052f, +-0.000385f, +-7.862303f, +-0.000384f, +-7.864938f, +-0.000382f, +-7.870074f, +-0.000380f, +-7.875393f, +-0.000378f, +-7.880583f, +-0.000376f, +-7.885958f, +-0.000374f, +-7.891204f, +-0.000372f, +-7.896637f, +-0.000370f, +-7.901938f, +-0.000368f, +-7.907430f, +-0.000366f, +-7.912952f, +-0.000364f, +-7.918341f, +-0.000362f, +-7.923924f, +-0.000361f, +-7.926562f, +-0.000359f, +-7.932192f, +-0.000357f, +-7.937853f, +-0.000355f, +-7.943378f, +-0.000353f, +-7.949103f, +-0.000351f, +-7.954691f, +-0.000350f, +-7.957582f, +-0.000348f, +-7.963389f, +-0.000346f, +-7.969057f, +-0.000344f, +-7.974932f, +-0.000342f, +-7.980666f, +-0.000341f, +-7.983633f, +-0.000339f, +-7.989594f, +-0.000337f, +-7.995414f, +-0.000335f, +-8.001445f, +-0.000334f, +-8.004296f, +-0.000332f, +-8.010382f, +-0.000330f, +-8.016505f, +-0.000329f, +-8.019399f, +-0.000327f, +-8.025578f, +-0.000325f, +-8.031611f, +-0.000324f, +-8.034734f, +-0.000322f, +-8.041008f, +-0.000320f, +-8.047135f, +-0.000319f, +-8.050307f, +-0.000317f, +-8.056680f, +-0.000315f, +-8.062904f, +-0.000314f, +-8.066126f, +-0.000312f, +-8.072601f, +-0.000310f, +-8.078926f, +-0.000309f, +-8.082200f, +-0.000307f, +-8.088586f, +-0.000306f, +-8.091892f, +-0.000304f, +-8.098537f, +-0.000302f, +-8.105028f, +-0.000301f, +-8.108389f, +-0.000299f, +-8.115144f, +-0.000298f, +-8.118339f, +-0.000296f, +-8.125162f, +-0.000295f, +-8.128592f, +-0.000293f, +-8.135282f, +-0.000292f, +-8.138746f, +-0.000290f, +-8.145710f, +-0.000289f, +-8.149005f, +-0.000287f, +-8.156041f, +-0.000286f, +-8.159578f, +-0.000284f, +-8.166480f, +-0.000283f, +-8.170054f, +-0.000281f, +-8.177240f, +-0.000280f, +-8.180640f, +-0.000278f, +-8.187904f, +-0.000277f, +-8.191555f, +-0.000275f, +-8.198682f, +-0.000274f, +-8.202373f, +-0.000272f, +-8.209797f, +-0.000271f, +-8.213309f, +-0.000270f, +-8.217055f, +-0.000268f, +-8.224589f, +-0.000267f, +-8.228154f, +-0.000265f, +-8.235772f, +-0.000264f, +-8.239603f, +-0.000262f, +-8.247082f, +-0.000261f, +-8.250957f, +-0.000260f, +-8.254846f, +-0.000258f, +-8.262440f, +-0.000257f, +-8.266375f, +-0.000256f, +-8.270325f, +-0.000254f, +-8.278273f, +-0.000253f, +-8.282035f, +-0.000252f, +-8.286048f, +-0.000250f, +-8.294122f, +-0.000249f, +-8.297944f, +-0.000248f, +-8.302022f, +-0.000246f, +-8.310226f, +-0.000245f, +-8.314354f, +-0.000244f, +-8.318255f, +-0.000243f, +-8.322416f, +-0.000241f, +-8.330790f, +-0.000240f, +-8.334755f, +-0.000239f, +-8.338986f, +-0.000237f, +-8.347501f, +-0.000236f, +-8.351786f, +-0.000235f, +-8.355835f, +-0.000234f, +-8.360156f, +-0.000232f, +-8.368854f, +-0.000231f, +-8.372973f, +-0.000230f, +-8.377369f, +-0.000229f, +-8.381784f, +-0.000228f, +-8.386219f, +-0.000226f, +-8.394883f, +-0.000225f, +-8.399377f, +-0.000224f, +-8.403890f, +-0.000223f, +-8.408424f, +-0.000222f, +-8.412710f, +-0.000220f, +-8.421880f, +-0.000219f, +-8.426496f, +-0.000218f, +-8.431134f, +-0.000217f, +-8.435519f, +-0.000216f, +-8.440199f, +-0.000215f, +-8.444901f, +-0.000214f, +-8.449625f, +-0.000212f, +-8.458860f, +-0.000211f, +-8.463650f, +-0.000210f, +-8.468464f, +-0.000209f, +-8.473301f, +-0.000208f, +-8.477875f, +-0.000207f, +-8.482758f, +-0.000206f, +-8.487665f, +-0.000205f, +-8.492596f, +-0.000203f, +-8.502238f, +-0.000202f, +-8.507242f, +-0.000201f, +-8.512271f, +-0.000200f, +-8.517325f, +-0.000199f, +-8.522106f, +-0.000198f, +-8.527210f, +-0.000197f, +-8.532341f, +-0.000196f, +-8.537498f, +-0.000195f, +-8.542376f, +-0.000194f, +-8.547585f, +-0.000193f, +-8.552821f, +-0.000192f, +-8.558085f, +-0.000191f, +-8.563377f, +-0.000190f, +-8.568383f, +-0.000189f, +-8.573730f, +-0.000188f, +-8.579106f, +-0.000187f, +-8.584510f, +-0.000186f, +-8.589624f, +-0.000185f, +-8.595085f, +-0.000184f, +-8.600577f, +-0.000183f, +-8.606099f, +-0.000182f, +-8.611652f, +-0.000181f, +-8.616907f, +-0.000180f, +-8.622520f, +-0.000179f, +-8.628165f, +-0.000178f, +-8.633842f, +-0.000177f, +-8.639215f, +-0.000176f, +-8.644955f, +-0.000175f, +-8.650729f, +-0.000174f, +-8.656536f, +-0.000173f, +-8.662377f, +-0.000172f, +-8.667906f, +-0.000171f, +-8.673814f, +-0.000170f, +-8.679757f, +-0.000169f, +-8.685735f, +-0.000169f, +-8.685735f, +-0.000168f, +-8.691395f, +-0.000167f, +-8.697444f, +-0.000166f, +-8.703529f, +-0.000165f, +-8.709652f, +-0.000164f, +-8.715813f, +-0.000163f, +-8.721646f, +-0.000162f, +-8.727881f, +-0.000161f, +-8.734155f, +-0.000160f, +-8.740469f, +-0.000160f, +-8.740469f, +-0.000159f, +-8.746448f, +-0.000158f, +-8.752840f, +-0.000157f, +-8.759273f, +-0.000156f, +-8.765748f, +-0.000155f, +-8.772266f, +-0.000154f, +-8.778438f, +-0.000154f, +-8.778438f, +-0.000153f, +-8.785039f, +-0.000152f, +-8.791684f, +-0.000151f, +-8.798373f, +-0.000150f, +-8.804709f, +-0.000150f, +-8.804709f, +-0.000149f, +-8.811486f, +-0.000148f, +-8.818310f, +-0.000147f, +-8.825180f, +-0.000146f, +-8.832097f, +-0.000145f, +-8.838652f, +-0.000145f, +-8.838652f, +-0.000144f, +-8.845664f, +-0.000143f, +-8.852725f, +-0.000142f, +-8.859837f, +-0.000142f, +-8.859837f, +-0.000141f, +-8.866576f, +-0.000140f, +-8.873787f, +-0.000139f, +-8.881051f, +-0.000138f, +-8.888367f, +-0.000138f, +-8.888367f, +-0.000137f, +-8.895738f, +-0.000136f, +-8.902725f, +-0.000135f, +-8.910202f, +-0.000135f, +-8.910202f, +-0.000134f, +-8.917736f, +-0.000133f, +-8.925327f, +-0.000133f, +-8.925327f, +-0.000132f, +-8.932525f, +-0.000131f, +-8.940229f, +-0.000130f, +-8.947994f, +-0.000130f, +-8.947994f, +-0.000129f, +-8.955819f, +-0.000128f, +-8.963706f, +-0.000128f, +-8.963706f, +-0.000127f, +-8.971186f, +-0.000126f, +-8.979195f, +-0.000125f, +-8.987269f, +-0.000125f, +-8.987269f, +-0.000124f, +-8.995409f, +-0.000123f, +-9.003131f, +-0.000123f, +-9.003131f, +-0.000122f, +-9.011402f, +-0.000121f, +-9.019741f, +-0.000121f, +-9.019741f, +-0.000120f, +-9.028151f, +-0.000119f, +-9.036632f, +-0.000119f, +-9.036632f, +-0.000118f, +-9.044680f, +-0.000117f, +-9.053303f, +-0.000117f, +-9.053303f, +-0.000116f, +-9.062001f, +-0.000115f, +-9.070775f, +-0.000115f, +-9.070775f, +-0.000114f, +-9.079104f, +-0.000114f, +-9.079104f, +-0.000113f, +-9.088031f, +-0.000112f, +-9.097037f, +-0.000112f, +-9.097037f, +-0.000111f, +-9.106126f, +-0.000110f, +-9.115298f, +-0.000110f, +-9.115298f, +-0.000109f, +-9.124008f, +-0.000109f, +-9.124008f, +-0.000108f, +-9.133346f, +-0.000107f, +-9.142772f, +-0.000107f, +-9.142772f, +-0.000106f, +-9.152288f, +-0.000106f, +-9.152288f, +-0.000105f, +-9.161328f, +-0.000104f, +-9.171022f, +-0.000104f, +-9.171022f, +-0.000103f, +-9.180812f, +-0.000103f, +-9.180812f, +-0.000102f, +-9.190699f, +-0.000102f, +-9.190699f, +-0.000101f, +-9.200684f, +-0.000100f, +-9.210174f, +-0.000100f, +-9.210174f, +-0.000099f, +-9.220357f, +-0.000099f, +-9.220357f, +-0.000098f, +-9.230645f, +-0.000098f, +-9.230645f, +-0.000097f, +-9.241039f, +-0.000097f, +-9.241039f, +-0.000096f, +-9.250922f, +-0.000095f, +-9.261530f, +-0.000095f, +-9.261530f, +-0.000094f, +-9.272253f, +-0.000094f, +-9.272253f, +-0.000093f, +-9.283091f, +-0.000093f, +-9.283091f, +-0.000092f, +-9.293401f, +-0.000092f, +-9.293401f, +-0.000091f, +-9.304472f, +-0.000091f, +-9.304472f, +-0.000090f, +-9.315667f, +-0.000090f, +-9.315667f, +-0.000089f, +-9.326990f, +-0.000089f, +-9.326990f, +-0.000088f, +-9.338441f, +-0.000088f, +-9.338441f, +-0.000087f, +-9.349341f, +-0.000087f, +-9.349341f, +-0.000086f, +-9.361053f, +-0.000086f, +-9.361053f, +-0.000085f, +-9.372904f, +-0.000085f, +-9.372904f, +-0.000084f, +-9.384897f, +-0.000084f, +-9.384897f, +-0.000083f, +-9.396317f, +-0.000083f, +-9.396317f, +-0.000082f, +-9.408596f, +-0.000082f, +-9.408596f, +-0.000082f, +-9.408596f, +-0.000081f, +-9.421028f, +-0.000081f, +-9.421028f, +-0.000080f, +-9.433616f, +-0.000080f, +-9.433616f, +-0.000079f, +-9.446365f, +-0.000079f, +-9.446365f, +-0.000078f, +-9.458514f, +-0.000078f, +-9.458514f, +-0.000077f, +-9.471586f, +-0.000077f, +-9.471586f, +-0.000077f, +-9.471586f, +-0.000076f, +-9.484831f, +-0.000076f, +-9.484831f, +-0.000075f, +-9.498254f, +-0.000075f, +-9.498254f, +-0.000074f, +-9.511054f, +-0.000074f, +-9.511054f, +-0.000074f, +-9.511054f, +-0.000073f, +-9.524836f, +-0.000073f, +-9.524836f, +-0.000072f, +-9.538811f, +-0.000072f, +-9.538811f, +-0.000072f, +-9.538811f, +-0.000071f, +-9.552984f, +-0.000071f, +-9.552984f, +-0.000070f, +-9.567360f, +-0.000070f, +-9.567360f, +-0.000070f, +-9.567360f, +-0.000069f, +-9.581083f, +-0.000069f, +-9.581083f, +-0.000068f, +-9.595872f, +-0.000068f, +-9.595872f, +-0.000068f, +-9.595872f, +-0.000067f, +-9.610883f, +-0.000067f, +-9.610883f, +-0.000066f, +-9.626123f, +-0.000066f, +-9.626123f, +-0.000066f, +-9.626123f, +-0.000065f, +-9.640682f, +-0.000065f, +-9.640682f, +-0.000065f, +-9.640682f, +-0.000064f, +-9.656387f, +-0.000064f, +-9.656387f, +-0.000063f, +-9.672342f, +-0.000063f, +-9.672342f, +-0.000063f, +-9.672342f, +-0.000062f, +-9.688556f, +-0.000062f, +-9.688556f, +-0.000062f, +-9.688556f, +-0.000061f, +-9.705038f, +-0.000061f, +-9.705038f, +-0.000061f, +-9.705038f, +-0.000060f, +-9.720801f, +-0.000060f, +-9.720801f, +-0.000060f, +-9.720801f, +-0.000059f, +-9.737827f, +-0.000059f, +-9.737827f, +-0.000059f, +-9.737827f, +-0.000058f, +-9.755148f, +-0.000058f, +-9.755148f, +-0.000057f, +-9.772774f, +-0.000057f, +-9.772774f, +-0.000057f, +-9.772774f, +-0.000057f, +-9.772774f, +-0.000056f, +-9.789652f, +-0.000056f, +-9.789652f, +-0.000056f, +-9.789652f, +-0.000055f, +-9.807903f, +-0.000055f, +-9.807903f, +-0.000055f, +-9.807903f, +-0.000054f, +-9.826493f, +-0.000054f, +-9.826493f, +-0.000054f, +-9.826493f, +-0.000053f, +-9.845435f, +-0.000053f, +-9.845435f, +-0.000053f, +-9.845435f, +-0.000052f, +-9.864743f, +-0.000052f, +-9.864743f, +-0.000052f, +-9.864743f, +-0.000051f, +-9.883262f, +-0.000051f, +-9.883262f, +-0.000051f, +-9.883262f, +-0.000051f, +-9.883262f, +-0.000050f, +-9.903322f, +-0.000050f, +-9.903322f, +-0.000050f, +-9.903322f, +-0.000049f, +-9.923792f, +-0.000049f, +-9.923792f, +-0.000049f, +-9.923792f, +-0.000049f, +-9.923792f, +-0.000048f, +-9.944690f, +-0.000048f, +-9.944690f, +-0.000048f, +-9.944690f, +-0.000047f, +-9.964766f, +-0.000047f, +-9.964766f, +-0.000047f, +-9.964766f, +-0.000047f, +-9.964766f, +-0.000046f, +-9.986548f, +-0.000046f, +-9.986548f, +-0.000046f, +-9.986548f, +-0.000046f, +-9.986548f, +-0.000045f, +-10.008815f, +-0.000045f, +-10.008815f, +-0.000045f, +-10.008815f, +-0.000044f, +-10.031589f, +-0.000044f, +-10.031589f, +-0.000044f, +-10.031589f, +-0.000044f, +-10.031589f, +-0.000043f, +-10.054893f, +-0.000043f, +-10.054893f, +-0.000043f, +-10.054893f, +-0.000043f, +-10.054893f, +-0.000042f, +-10.077335f, +-0.000042f, +-10.077335f, +-0.000042f, +-10.077335f, +-0.000042f, +-10.077335f, +-0.000041f, +-10.101743f, +-0.000041f, +-10.101743f, +-0.000041f, +-10.101743f, +-0.000041f, +-10.101743f, +-0.000041f, +-10.101743f, +-0.000040f, +-10.126763f, +-0.000040f, +-10.126763f, +-0.000040f, +-10.126763f, +-0.000040f, +-10.126763f, +-0.000039f, +-10.152425f, +-0.000039f, +-10.152425f, +-0.000039f, +-10.152425f, +-0.000039f, +-10.152425f, +-0.000038f, +-10.177194f, +-0.000038f, +-10.177194f, +-0.000038f, +-10.177194f, +-0.000038f, +-10.177194f, +-0.000038f, +-10.177194f, +-0.000037f, +-10.204201f, +-0.000037f, +-10.204201f, +-0.000037f, +-10.204201f, +-0.000037f, +-10.204201f, +-0.000036f, +-10.231958f, +-0.000036f, +-10.231958f, +-0.000036f, +-10.231958f, +-0.000036f, +-10.231958f, +-0.000036f, +-10.231958f, +-0.000035f, +-10.260508f, +-0.000035f, +-10.260508f, +-0.000035f, +-10.260508f, +-0.000035f, +-10.260508f, +-0.000035f, +-10.260508f, +-0.000034f, +-10.289896f, +-0.000034f, +-10.289896f, +-0.000034f, +-10.289896f, +-0.000034f, +-10.289896f, +-0.000033f, +-10.318368f, +-0.000033f, +-10.318368f, +-0.000033f, +-10.318368f, +-0.000033f, +-10.318368f, +-0.000033f, +-10.318368f, +-0.000033f, +-10.318368f, +-0.000032f, +-10.349534f, +-0.000032f, +-10.349534f, +-0.000032f, +-10.349534f, +-0.000032f, +-10.349534f, +-0.000032f, +-10.349534f, +-0.000031f, +-10.381704f, +-0.000031f, +-10.381704f, +-0.000031f, +-10.381704f, +-0.000031f, +-10.381704f, +-0.000031f, +-10.381704f, +-0.000030f, +-10.414942f, +-0.000030f, +-10.414942f, +-0.000030f, +-10.414942f, +-0.000030f, +-10.414942f, +-0.000030f, +-10.414942f, +-0.000030f, +-10.414942f, +-0.000029f, +-10.447268f, +-0.000029f, +-10.447268f, +-0.000029f, +-10.447268f, +-0.000029f, +-10.447268f, +-0.000029f, +-10.447268f, +-0.000028f, +-10.482800f, +-0.000028f, +-10.482800f, +-0.000028f, +-10.482800f, +-0.000028f, +-10.482800f, +-0.000028f, +-10.482800f, +-0.000028f, +-10.482800f, +-0.000028f, +-10.482800f, +-0.000027f, +-10.519640f, +-0.000027f, +-10.519640f, +-0.000027f, +-10.519640f, +-0.000027f, +-10.519640f, +-0.000027f, +-10.519640f, +-0.000027f, +-10.519640f, +-0.000026f, +-10.557890f, +-0.000026f, +-10.557890f, +-0.000026f, +-10.557890f, +-0.000026f, +-10.557890f, +-0.000026f, +-10.557890f, +-0.000026f, +-10.557890f, +-0.000025f, +-10.597661f, +-0.000025f, +-10.597661f, +-0.000025f, +-10.597661f, +-0.000025f, +-10.597661f, +-0.000025f, +-10.597661f, +-0.000025f, +-10.597661f, +-0.000025f, +-10.597661f, +-0.000024f, +-10.636596f, +-0.000024f, +-10.636596f, +-0.000024f, +-10.636596f, +-0.000024f, +-10.636596f, +-0.000024f, +-10.636596f, +-0.000024f, +-10.636596f, +-0.000023f, +-10.679695f, +-0.000023f, +-10.679695f, +-0.000023f, +-10.679695f, +-0.000023f, +-10.679695f, +-0.000023f, +-10.679695f, +-0.000023f, +-10.679695f, +-0.000023f, +-10.679695f, +-0.000023f, +-10.679695f, +-0.000022f, +-10.724736f, +-0.000022f, +-10.724736f, +-0.000022f, +-10.724736f, +-0.000022f, +-10.724736f, +-0.000022f, +-10.724736f, +-0.000022f, +-10.724736f, +-0.000022f, +-10.724736f, +-0.000021f, +-10.771901f, +-0.000021f, +-10.771901f, +-0.000021f, +-10.771901f, +-0.000021f, +-10.771901f, +-0.000021f, +-10.771901f, +-0.000021f, +-10.771901f, +-0.000021f, +-10.771901f, +-0.000021f, +-10.771901f, +-0.000020f, +-10.818421f, +-0.000020f, +-10.818421f, +-0.000020f, +-10.818421f, +-0.000020f, +-10.818421f, +-0.000020f, +-10.818421f, +-0.000020f, +-10.818421f, +-0.000020f, +-10.818421f, +-0.000020f, +-10.818421f, +-0.000019f, +-10.870341f, +-0.000019f, +-10.870341f, +-0.000019f, +-10.870341f, +-0.000019f, +-10.870341f, +-0.000019f, +-10.870341f, +-0.000019f, +-10.870341f, +-0.000019f, +-10.870341f, +-0.000019f, +-10.870341f, +-0.000019f, +-10.870341f, +-0.000018f, +-10.925105f, +-0.000018f, +-10.925105f, +-0.000018f, +-10.925105f, +-0.000018f, +-10.925105f, +-0.000018f, +-10.925105f, +-0.000018f, +-10.925105f, +-0.000018f, +-10.925105f, +-0.000018f, +-10.925105f, +-0.000018f, +-10.925105f, +-0.000017f, +-10.983043f, +-0.000017f, +-10.983043f, +-0.000017f, +-10.983043f, +-0.000017f, +-10.983043f, +-0.000017f, +-10.983043f, +-0.000017f, +-10.983043f, +-0.000017f, +-10.983043f, +-0.000017f, +-10.983043f, +-0.000017f, +-10.983043f, +-0.000016f, +-11.044545f, +-0.000016f, +-11.044545f, +-0.000016f, +-11.044545f, +-0.000016f, +-11.044545f, +-0.000016f, +-11.044545f, +-0.000016f, +-11.044545f, +-0.000016f, +-11.044545f, +-0.000016f, +-11.044545f, +-0.000016f, +-11.044545f, +-0.000016f, +-11.044545f, +-0.000015f, +-11.106103f, +-0.000015f, +-11.106103f, +-0.000015f, +-11.106103f, +-0.000015f, +-11.106103f, +-0.000015f, +-11.106103f, +-0.000015f, +-11.106103f, +-0.000015f, +-11.106103f, +-0.000015f, +-11.106103f, +-0.000015f, +-11.106103f, +-0.000015f, +-11.106103f, +-0.000015f, +-11.106103f, +-0.000014f, +-11.175947f, +-0.000014f, +-11.175947f, +-0.000014f, +-11.175947f, +-0.000014f, +-11.175947f, +-0.000014f, +-11.175947f, +-0.000014f, +-11.175947f, +-0.000014f, +-11.175947f, +-0.000014f, +-11.175947f, +-0.000014f, +-11.175947f, +-0.000014f, +-11.175947f, +-0.000014f, +-11.175947f, +-0.000014f, +-11.175947f, +-0.000013f, +-11.251037f, +-0.000013f, +-11.251037f, +-0.000013f, +-11.251037f, +-0.000013f, +-11.251037f, +-0.000013f, +-11.251037f, +-0.000013f, +-11.251037f, +-0.000013f, +-11.251037f, +-0.000013f, +-11.251037f, +-0.000013f, +-11.251037f, +-0.000013f, +-11.251037f, +-0.000013f, +-11.251037f, +-0.000013f, +-11.251037f, +-0.000012f, +-11.332227f, +-0.000012f, +-11.332227f, +-0.000012f, +-11.332227f, +-0.000012f, +-11.332227f, +-0.000012f, +-11.332227f, +-0.000012f, +-11.332227f, +-0.000012f, +-11.332227f, +-0.000012f, +-11.332227f, +-0.000012f, +-11.332227f, +-0.000012f, +-11.332227f, +-0.000012f, +-11.332227f, +-0.000012f, +-11.332227f, +-0.000012f, +-11.332227f, +-0.000011f, +-11.415177f, +-0.000011f, +-11.415177f, +-0.000011f, +-11.415177f, +-0.000011f, +-11.415177f, +-0.000011f, +-11.415177f, +-0.000011f, +-11.415177f, +-0.000011f, +-11.415177f, +-0.000011f, +-11.415177f, +-0.000011f, +-11.415177f, +-0.000011f, +-11.415177f, +-0.000011f, +-11.415177f, +-0.000011f, +-11.415177f, +-0.000011f, +-11.415177f, +-0.000011f, +-11.415177f, +-0.000010f, +-11.511568f, +-0.000010f, +-11.511568f, +-0.000010f, +-11.511568f, +-0.000010f, +-11.511568f, +-0.000010f, +-11.511568f, +-0.000010f, +-11.511568f, +-0.000010f, +-11.511568f, +-0.000010f, +-11.511568f, +-0.000010f, +-11.511568f, +-0.000010f, +-11.511568f, +-0.000010f, +-11.511568f, +-0.000010f, +-11.511568f, +-0.000010f, +-11.511568f, +-0.000010f, +-11.511568f, +-0.000010f, +-11.511568f, +-0.000010f, +-11.511568f, +-0.000009f, +-11.618252f, +-0.000009f, +-11.618252f, +-0.000009f, +-11.618252f, +-0.000009f, +-11.618252f, +-0.000009f, +-11.618252f, +-0.000009f, +-11.618252f, +-0.000009f, +-11.618252f, +-0.000009f, +-11.618252f, +-0.000009f, +-11.618252f, +-0.000009f, +-11.618252f, +-0.000009f, +-11.618252f, +-0.000009f, +-11.618252f, +-0.000009f, +-11.618252f, +-0.000009f, +-11.618252f, +-0.000009f, +-11.618252f, +-0.000009f, +-11.618252f, +-0.000009f, +-11.618252f, +-0.000009f, +-11.618252f, +-0.000008f, +-11.737693f, +-0.000008f, +-11.737693f, +-0.000008f, +-11.737693f, +-0.000008f, +-11.737693f, +-0.000008f, +-11.737693f, +-0.000008f, +-11.737693f, +-0.000008f, +-11.737693f, +-0.000008f, +-11.737693f, +-0.000008f, +-11.737693f, +-0.000008f, +-11.737693f, +-0.000008f, +-11.737693f, +-0.000008f, +-11.737693f, +-0.000008f, +-11.737693f, +-0.000008f, +-11.737693f, +-0.000008f, +-11.737693f, +-0.000008f, +-11.737693f, +-0.000008f, +-11.737693f, +-0.000008f, +-11.737693f, +-0.000008f, +-11.737693f, +-0.000007f, +-11.873358f, +-0.000007f, +-11.873358f, +-0.000007f, +-11.873358f, +-0.000007f, +-11.873358f, +-0.000007f, +-11.873358f, +-0.000007f, +-11.873358f, +-0.000007f, +-11.873358f, +-0.000007f, +-11.873358f, +-0.000007f, +-11.873358f, +-0.000007f, +-11.873358f, +-0.000007f, +-11.873358f, +-0.000007f, +-11.873358f, +-0.000007f, +-11.873358f, +-0.000007f, +-11.873358f, +-0.000007f, +-11.873358f, +-0.000007f, +-11.873358f, +-0.000007f, +-11.873358f, +-0.000007f, +-11.873358f, +-0.000007f, +-11.873358f, +-0.000007f, +-11.873358f, +-0.000007f, +-11.873358f, +-0.000007f, +-11.873358f, +-0.000006f, +-12.020412f, +-0.000006f, +-12.020412f, +-0.000006f, +-12.020412f, +-0.000006f, +-12.020412f, +-0.000006f, +-12.020412f, +-0.000006f, +-12.020412f, +-0.000006f, +-12.020412f, +-0.000006f, +-12.020412f, +-0.000006f, +-12.020412f, +-0.000006f, +-12.020412f, +-0.000006f, +-12.020412f, +-0.000006f, +-12.020412f, +-0.000006f, +-12.020412f, +-0.000006f, +-12.020412f, +-0.000006f, +-12.020412f, +-0.000006f, +-12.020412f, +-0.000006f, +-12.020412f, +-0.000006f, +-12.020412f, +-0.000006f, +-12.020412f, +-0.000006f, +-12.020412f, +-0.000006f, +-12.020412f, +-0.000006f, +-12.020412f, +-0.000006f, +-12.020412f, +-0.000006f, +-12.020412f, +-0.000006f, +-12.020412f, +-0.000006f, +-12.020412f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000005f, +-12.204716f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000004f, +-12.430840f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000003f, +-12.723509f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000002f, +-13.109172f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.802319f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f, +-0.000001f, +-13.815511f diff --git a/rce/rcecalib/dataproc/fit/logx_ext_fastint.dat b/rce/rcecalib/dataproc/fit/logx_ext_fastint.dat new file mode 100644 index 00000000..370ec323 --- /dev/null +++ b/rce/rcecalib/dataproc/fit/logx_ext_fastint.dat @@ -0,0 +1,16382 @@ +-159447, +0, +-159378, +0, +-159309, +0, +-159240, +0, +-159171, +0, +-159102, +0, +-159033, +0, +-158964, +0, +-158895, +0, +-158826, +0, +-158758, +0, +-158689, +0, +-158620, +0, +-158551, +0, +-158482, +0, +-158414, +0, +-158345, +0, +-158276, +0, +-158208, +0, +-158139, +0, +-158070, +0, +-158002, +0, +-157933, +0, +-157864, +0, +-157796, +0, +-157727, +0, +-157659, +0, +-157590, +0, +-157522, +0, +-157453, +0, +-157385, +0, +-157316, +0, +-157248, +0, +-157179, +0, +-157111, +0, +-157042, +0, +-156974, +0, +-156905, +0, +-156837, +0, +-156769, +0, +-156700, +0, +-156632, +0, +-156564, +0, +-156495, +0, +-156427, +0, +-156359, +0, +-156291, +0, +-156222, +0, +-156154, +0, +-156086, +0, +-156018, +0, +-155950, +0, +-155882, +0, +-155813, +0, +-155745, +0, +-155677, +0, +-155609, +0, +-155541, +0, +-155473, +0, +-155405, +0, +-155337, +0, +-155269, +0, +-155201, +0, +-155133, +0, +-155065, +0, +-154997, +0, +-154929, +0, +-154861, +0, +-154793, +0, +-154725, +0, +-154658, +0, +-154590, +0, +-154522, +0, +-154454, +0, +-154386, +0, +-154319, +0, +-154251, +0, +-154183, +0, +-154115, +0, +-154048, +0, +-153980, +0, +-153912, +0, +-153844, +0, +-153777, +0, +-153709, +0, +-153642, +0, +-153574, +0, +-153506, +0, +-153439, +0, +-153371, +0, +-153304, +0, +-153236, +0, +-153169, +0, +-153101, +0, +-153034, +0, +-152966, +0, +-152899, +0, +-152831, +0, +-152764, +0, +-152696, +0, +-152629, +0, +-152562, +0, +-152494, +0, +-152427, +0, +-152360, +0, +-152292, +0, +-152225, +0, +-152158, +0, +-152091, +0, +-152023, +0, +-151956, +0, +-151889, +0, +-151822, +0, +-151755, +0, +-151687, +0, +-151620, +0, +-151553, +0, +-151486, +0, +-151419, +0, +-151352, +0, +-151285, +0, +-151218, +0, +-151151, +0, +-151084, +0, +-151017, +0, +-150950, +0, +-150883, +0, +-150816, +0, +-150749, +0, +-150682, +0, +-150615, +0, +-150548, +0, +-150481, +0, +-150414, +0, +-150348, +0, +-150281, +0, +-150214, +0, +-150147, +0, +-150080, +0, +-150014, +0, +-149947, +0, +-149880, +0, +-149813, +0, +-149747, +0, +-149680, +0, +-149613, +0, +-149547, +0, +-149480, +0, +-149413, +0, +-149347, +0, +-149280, +0, +-149214, +0, +-149147, +0, +-149081, +0, +-149014, +0, +-148948, +0, +-148881, +0, +-148815, +0, +-148748, +0, +-148682, +0, +-148615, +0, +-148549, +0, +-148482, +0, +-148416, +0, +-148350, +0, +-148283, +0, +-148217, +0, +-148151, +0, +-148084, +0, +-148018, +0, +-147952, +0, +-147886, +0, +-147819, +0, +-147753, +0, +-147687, +0, +-147621, +0, +-147555, +0, +-147488, +0, +-147422, +0, +-147356, +0, +-147290, +0, +-147224, +0, +-147158, +0, +-147092, +0, +-147026, +0, +-146960, +0, +-146894, +0, +-146828, +0, +-146762, +0, +-146696, +0, +-146630, +0, +-146564, +0, +-146498, +0, +-146432, +0, +-146366, +0, +-146300, +0, +-146234, +0, +-146169, +0, +-146103, +0, +-146037, +0, +-145971, +0, +-145905, +0, +-145840, +0, +-145774, +0, +-145708, +0, +-145642, +0, +-145577, +0, +-145511, +0, +-145445, +0, +-145380, +0, +-145314, +0, +-145248, +0, +-145183, +0, +-145117, +0, +-145052, +0, +-144986, +0, +-144921, +0, +-144855, +0, +-144790, +0, +-144724, +0, +-144659, +0, +-144593, +0, +-144528, +0, +-144462, +0, +-144397, +0, +-144332, +0, +-144266, +0, +-144201, +0, +-144135, +0, +-144070, +0, +-144005, +0, +-143940, +0, +-143874, +0, +-143809, +0, +-143744, +0, +-143678, +0, +-143613, +0, +-143548, +0, +-143483, +0, +-143418, +0, +-143353, +0, +-143287, +0, +-143222, +0, +-143157, +0, +-143092, +0, +-143027, +0, +-142962, +0, +-142897, +0, +-142832, +0, +-142767, +0, +-142702, +0, +-142637, +0, +-142572, +0, +-142507, +0, +-142442, +0, +-142377, +0, +-142312, +0, +-142247, +0, +-142183, +0, +-142118, +0, +-142053, +0, +-141988, +0, +-141923, +0, +-141858, +0, +-141794, +0, +-141729, +0, +-141664, +0, +-141599, +0, +-141535, +0, +-141470, +0, +-141405, +0, +-141341, +0, +-141276, +0, +-141211, +0, +-141147, +0, +-141082, +0, +-141018, +0, +-140953, +0, +-140889, +0, +-140824, +0, +-140759, +0, +-140695, +0, +-140630, +0, +-140566, +0, +-140502, +0, +-140437, +0, +-140373, +0, +-140308, +0, +-140244, +0, +-140180, +0, +-140115, +0, +-140051, +0, +-139986, +0, +-139922, +0, +-139858, +0, +-139794, +0, +-139729, +0, +-139665, +0, +-139601, +0, +-139537, +0, +-139472, +0, +-139408, +0, +-139344, +0, +-139280, +0, +-139216, +0, +-139152, +0, +-139088, +0, +-139024, +0, +-138959, +0, +-138895, +0, +-138831, +0, +-138767, +0, +-138703, +0, +-138639, +0, +-138575, +0, +-138511, +0, +-138447, +0, +-138384, +0, +-138320, +0, +-138256, +0, +-138192, +0, +-138128, +0, +-138064, +0, +-138000, +0, +-137936, +0, +-137873, +0, +-137809, +0, +-137745, +0, +-137681, +0, +-137618, +0, +-137554, +0, +-137490, +0, +-137426, +0, +-137363, +0, +-137299, +0, +-137236, +0, +-137172, +0, +-137108, +0, +-137045, +0, +-136981, +0, +-136918, +0, +-136854, +0, +-136790, +0, +-136727, +0, +-136663, +0, +-136600, +0, +-136536, +0, +-136473, +0, +-136410, +0, +-136346, +0, +-136283, +0, +-136219, +0, +-136156, +0, +-136093, +0, +-136029, +0, +-135966, +0, +-135903, +0, +-135839, +0, +-135776, +0, +-135713, +0, +-135650, +0, +-135586, +0, +-135523, +0, +-135460, +0, +-135397, +0, +-135334, +0, +-135270, +0, +-135207, +0, +-135144, +0, +-135081, +0, +-135018, +0, +-134955, +0, +-134892, +0, +-134829, +0, +-134766, +0, +-134703, +0, +-134640, +0, +-134577, +0, +-134514, +0, +-134451, +0, +-134388, +0, +-134325, +0, +-134262, +0, +-134199, +0, +-134137, +0, +-134074, +0, +-134011, +0, +-133948, +0, +-133885, +0, +-133822, +0, +-133760, +0, +-133697, +0, +-133634, +0, +-133571, +0, +-133509, +0, +-133446, +0, +-133383, +0, +-133321, +0, +-133258, +0, +-133195, +0, +-133133, +0, +-133070, +0, +-133008, +0, +-132945, +0, +-132883, +0, +-132820, +0, +-132758, +0, +-132695, +0, +-132633, +0, +-132570, +0, +-132508, +0, +-132445, +0, +-132383, +0, +-132320, +0, +-132258, +0, +-132196, +0, +-132133, +0, +-132071, +0, +-132009, +0, +-131946, +0, +-131884, +0, +-131822, +0, +-131759, +0, +-131697, +0, +-131635, +0, +-131573, +0, +-131511, +0, +-131448, +0, +-131386, +0, +-131324, +0, +-131262, +0, +-131200, +0, +-131138, +0, +-131076, +0, +-131014, +0, +-130952, +0, +-130889, +0, +-130827, +0, +-130765, +0, +-130703, +0, +-130642, +0, +-130580, +0, +-130518, +0, +-130456, +0, +-130394, +0, +-130332, +0, +-130270, +0, +-130208, +0, +-130146, +0, +-130084, +0, +-130023, +0, +-129961, +0, +-129899, +0, +-129837, +0, +-129776, +0, +-129714, +0, +-129652, +0, +-129590, +0, +-129529, +0, +-129467, +0, +-129405, +0, +-129344, +0, +-129282, +0, +-129220, +0, +-129159, +0, +-129097, +0, +-129036, +0, +-128974, +0, +-128913, +0, +-128851, +0, +-128790, +0, +-128728, +0, +-128667, +0, +-128605, +0, +-128544, +0, +-128482, +0, +-128421, +0, +-128360, +0, +-128298, +0, +-128237, +0, +-128176, +0, +-128114, +0, +-128053, +0, +-127992, +0, +-127930, +0, +-127869, +0, +-127808, +0, +-127747, +0, +-127685, +0, +-127624, +0, +-127563, +0, +-127502, +0, +-127441, +0, +-127380, +0, +-127318, +0, +-127257, +0, +-127196, +0, +-127135, +0, +-127074, +0, +-127013, +0, +-126952, +0, +-126891, +0, +-126830, +0, +-126769, +0, +-126708, +0, +-126647, +0, +-126586, +0, +-126525, +0, +-126465, +0, +-126404, +0, +-126343, +0, +-126282, +0, +-126221, +0, +-126160, +0, +-126099, +0, +-126039, +0, +-125978, +0, +-125917, +0, +-125856, +0, +-125796, +0, +-125735, +0, +-125674, +0, +-125614, +0, +-125553, +0, +-125492, +0, +-125432, +0, +-125371, +0, +-125311, +0, +-125250, +0, +-125189, +0, +-125129, +0, +-125068, +0, +-125008, +0, +-124947, +0, +-124887, +0, +-124826, +0, +-124766, +0, +-124705, +0, +-124645, +0, +-124585, +0, +-124524, +0, +-124464, +0, +-124404, +0, +-124343, +0, +-124283, +0, +-124223, +0, +-124162, +0, +-124102, +0, +-124042, +0, +-123981, +0, +-123921, +0, +-123861, +0, +-123801, +0, +-123741, +0, +-123680, +0, +-123620, +0, +-123560, +0, +-123500, +0, +-123440, +0, +-123380, +0, +-123320, +0, +-123260, +0, +-123200, +0, +-123140, +0, +-123080, +0, +-123020, +0, +-122960, +0, +-122900, +0, +-122840, +0, +-122780, +0, +-122720, +0, +-122660, +0, +-122600, +0, +-122540, +0, +-122480, +0, +-122421, +0, +-122361, +0, +-122301, +0, +-122241, +0, +-122181, +0, +-122122, +0, +-122062, +0, +-122002, +0, +-121943, +0, +-121883, +0, +-121823, +0, +-121764, +0, +-121704, +0, +-121644, +0, +-121585, +0, +-121525, +0, +-121465, +0, +-121406, +0, +-121346, +0, +-121287, +0, +-121227, +0, +-121168, +0, +-121108, +0, +-121049, +0, +-120989, +0, +-120930, +0, +-120871, +0, +-120811, +0, +-120752, +0, +-120692, +0, +-120633, +0, +-120574, +0, +-120514, +0, +-120455, +0, +-120396, +0, +-120336, +0, +-120277, +0, +-120218, +0, +-120159, +0, +-120100, +0, +-120040, +0, +-119981, +0, +-119922, +0, +-119863, +0, +-119804, +0, +-119745, +0, +-119685, +0, +-119626, +0, +-119567, +0, +-119508, +0, +-119449, +0, +-119390, +0, +-119331, +0, +-119272, +0, +-119213, +0, +-119154, +0, +-119095, +0, +-119036, +0, +-118977, +0, +-118919, +0, +-118860, +0, +-118801, +0, +-118742, +0, +-118683, +0, +-118624, +0, +-118566, +0, +-118507, +0, +-118448, +0, +-118389, +0, +-118330, +0, +-118272, +0, +-118213, +0, +-118154, +0, +-118096, +0, +-118037, +0, +-117978, +0, +-117920, +0, +-117861, +0, +-117803, +0, +-117744, +0, +-117685, +0, +-117627, +0, +-117568, +0, +-117510, +0, +-117451, +0, +-117393, +0, +-117334, +0, +-117276, +0, +-117217, +0, +-117159, +0, +-117101, +0, +-117042, +0, +-116984, +0, +-116925, +0, +-116867, +0, +-116809, +0, +-116750, +0, +-116692, +0, +-116634, +0, +-116576, +0, +-116517, +0, +-116459, +0, +-116401, +0, +-116343, +0, +-116285, +0, +-116226, +0, +-116168, +0, +-116110, +0, +-116052, +0, +-115994, +0, +-115936, +0, +-115878, +0, +-115820, +0, +-115762, +0, +-115704, +0, +-115646, +0, +-115588, +0, +-115530, +0, +-115472, +0, +-115414, +0, +-115356, +0, +-115298, +0, +-115240, +0, +-115182, +0, +-115124, +0, +-115066, +0, +-115008, +0, +-114951, +0, +-114893, +0, +-114835, +0, +-114777, +0, +-114719, +0, +-114662, +0, +-114604, +0, +-114546, +0, +-114489, +0, +-114431, +0, +-114373, +0, +-114316, +0, +-114258, +0, +-114200, +0, +-114143, +0, +-114085, +0, +-114028, +0, +-113970, +0, +-113912, +0, +-113855, +0, +-113797, +0, +-113740, +0, +-113682, +0, +-113625, +0, +-113568, +0, +-113510, +0, +-113453, +0, +-113395, +0, +-113338, +0, +-113281, +0, +-113223, +0, +-113166, +0, +-113109, +0, +-113051, +0, +-112994, +0, +-112937, +0, +-112880, +0, +-112822, +0, +-112765, +0, +-112708, +0, +-112651, +0, +-112593, +0, +-112536, +0, +-112479, +0, +-112422, +0, +-112365, +0, +-112308, +0, +-112251, +0, +-112194, +0, +-112137, +0, +-112080, +0, +-112023, +0, +-111966, +0, +-111909, +0, +-111852, +0, +-111795, +0, +-111738, +0, +-111681, +0, +-111624, +0, +-111567, +0, +-111510, +0, +-111453, +0, +-111396, +0, +-111340, +0, +-111283, +0, +-111226, +0, +-111169, +0, +-111112, +0, +-111056, +0, +-110999, +0, +-110942, +0, +-110886, +0, +-110829, +0, +-110772, +0, +-110716, +0, +-110659, +0, +-110602, +0, +-110546, +0, +-110489, +0, +-110433, +0, +-110376, +0, +-110319, +0, +-110263, +0, +-110206, +0, +-110150, +0, +-110093, +0, +-110037, +0, +-109981, +0, +-109924, +0, +-109868, +0, +-109811, +0, +-109755, +0, +-109699, +0, +-109642, +0, +-109586, +0, +-109529, +0, +-109473, +0, +-109417, +0, +-109361, +0, +-109304, +0, +-109248, +0, +-109192, +0, +-109136, +0, +-109079, +0, +-109023, +0, +-108967, +0, +-108911, +0, +-108855, +0, +-108799, +0, +-108743, +0, +-108687, +0, +-108630, +0, +-108574, +0, +-108518, +0, +-108462, +0, +-108406, +0, +-108350, +0, +-108294, +0, +-108238, +0, +-108182, +0, +-108127, +0, +-108071, +0, +-108015, +0, +-107959, +0, +-107903, +0, +-107847, +0, +-107791, +0, +-107736, +0, +-107680, +0, +-107624, +0, +-107568, +0, +-107512, +0, +-107457, +0, +-107401, +0, +-107345, +0, +-107290, +0, +-107234, +0, +-107178, +0, +-107123, +0, +-107067, +0, +-107011, +0, +-106956, +0, +-106900, +0, +-106845, +0, +-106789, +0, +-106734, +0, +-106678, +0, +-106622, +0, +-106567, +0, +-106512, +0, +-106456, +0, +-106401, +0, +-106345, +0, +-106290, +0, +-106234, +0, +-106179, +0, +-106124, +0, +-106068, +0, +-106013, +0, +-105958, +0, +-105902, +0, +-105847, +0, +-105792, +0, +-105737, +0, +-105681, +0, +-105626, +0, +-105571, +0, +-105516, +0, +-105461, +0, +-105405, +0, +-105350, +0, +-105295, +0, +-105240, +0, +-105185, +0, +-105130, +0, +-105075, +0, +-105020, +0, +-104965, +0, +-104910, +0, +-104855, +0, +-104800, +0, +-104745, +0, +-104690, +0, +-104635, +0, +-104580, +0, +-104525, +0, +-104470, +0, +-104415, +0, +-104361, +0, +-104306, +0, +-104251, +0, +-104196, +0, +-104141, +0, +-104086, +0, +-104032, +0, +-103977, +0, +-103922, +0, +-103868, +0, +-103813, +0, +-103758, +0, +-103703, +0, +-103649, +0, +-103594, +0, +-103540, +0, +-103485, +0, +-103430, +0, +-103376, +0, +-103321, +0, +-103267, +0, +-103212, +0, +-103158, +0, +-103103, +0, +-103049, +0, +-102994, +0, +-102940, +0, +-102885, +0, +-102831, +0, +-102777, +0, +-102722, +0, +-102668, +0, +-102613, +0, +-102559, +0, +-102505, +0, +-102450, +0, +-102396, +0, +-102342, +0, +-102288, +0, +-102233, +0, +-102179, +0, +-102125, +0, +-102071, +0, +-102017, +0, +-101962, +0, +-101908, +0, +-101854, +0, +-101800, +0, +-101746, +0, +-101692, +0, +-101638, +0, +-101584, +0, +-101530, +0, +-101476, +0, +-101422, +0, +-101368, +0, +-101314, +0, +-101260, +0, +-101206, +0, +-101152, +0, +-101098, +0, +-101044, +0, +-100990, +0, +-100936, +0, +-100883, +0, +-100829, +0, +-100775, +0, +-100721, +0, +-100667, +0, +-100614, +0, +-100560, +0, +-100506, +0, +-100452, +0, +-100399, +0, +-100345, +0, +-100291, +0, +-100238, +0, +-100184, +0, +-100130, +0, +-100077, +0, +-100023, +0, +-99970, +0, +-99916, +0, +-99862, +0, +-99809, +0, +-99755, +0, +-99702, +0, +-99648, +0, +-99595, +0, +-99541, +0, +-99488, +0, +-99435, +0, +-99381, +0, +-99328, +0, +-99274, +0, +-99221, +0, +-99168, +0, +-99114, +0, +-99061, +0, +-99008, +0, +-98954, +0, +-98901, +0, +-98848, +0, +-98795, +0, +-98742, +0, +-98688, +0, +-98635, +0, +-98582, +0, +-98529, +0, +-98476, +0, +-98423, +0, +-98369, +0, +-98316, +0, +-98263, +0, +-98210, +0, +-98157, +0, +-98104, +0, +-98051, +0, +-97998, +0, +-97945, +0, +-97892, +0, +-97839, +0, +-97786, +0, +-97733, +0, +-97680, +0, +-97628, +0, +-97575, +0, +-97522, +0, +-97469, +0, +-97416, +0, +-97363, +0, +-97311, +0, +-97258, +0, +-97205, +0, +-97152, +0, +-97100, +0, +-97047, +0, +-96994, +0, +-96941, +0, +-96889, +0, +-96836, +0, +-96783, +0, +-96731, +0, +-96678, +0, +-96626, +0, +-96573, +0, +-96521, +0, +-96468, +0, +-96415, +0, +-96363, +0, +-96310, +0, +-96258, +0, +-96205, +0, +-96153, +0, +-96101, +0, +-96048, +0, +-95996, +0, +-95943, +0, +-95891, +0, +-95839, +0, +-95786, +0, +-95734, +0, +-95682, +0, +-95629, +0, +-95577, +0, +-95525, +0, +-95473, +0, +-95420, +0, +-95368, +0, +-95316, +0, +-95264, +0, +-95212, +0, +-95160, +0, +-95107, +0, +-95055, +0, +-95003, +0, +-94951, +0, +-94899, +0, +-94847, +0, +-94795, +0, +-94743, +0, +-94691, +0, +-94639, +0, +-94587, +0, +-94535, +0, +-94483, +0, +-94431, +0, +-94379, +0, +-94327, +0, +-94275, +0, +-94223, +0, +-94172, +0, +-94120, +0, +-94068, +0, +-94016, +0, +-93964, +0, +-93913, +0, +-93861, +0, +-93809, +0, +-93757, +0, +-93706, +0, +-93654, +0, +-93602, +0, +-93551, +0, +-93499, +0, +-93447, +0, +-93396, +0, +-93344, +0, +-93293, +0, +-93241, +0, +-93189, +0, +-93138, +0, +-93086, +0, +-93035, +0, +-92983, +0, +-92932, +0, +-92880, +0, +-92829, +0, +-92778, +0, +-92726, +0, +-92675, +0, +-92623, +0, +-92572, +0, +-92521, +0, +-92469, +0, +-92418, +0, +-92367, +0, +-92315, +0, +-92264, +0, +-92213, +0, +-92162, +0, +-92110, +0, +-92059, +0, +-92008, +0, +-91957, +0, +-91906, +0, +-91855, +0, +-91803, +0, +-91752, +0, +-91701, +0, +-91650, +0, +-91599, +0, +-91548, +0, +-91497, +0, +-91446, +0, +-91395, +0, +-91344, +0, +-91293, +0, +-91242, +0, +-91191, +0, +-91140, +0, +-91089, +0, +-91038, +0, +-90987, +0, +-90937, +0, +-90886, +0, +-90835, +0, +-90784, +0, +-90733, +0, +-90682, +0, +-90632, +0, +-90581, +0, +-90530, +0, +-90479, +0, +-90429, +0, +-90378, +0, +-90327, +0, +-90277, +0, +-90226, +0, +-90175, +0, +-90125, +0, +-90074, +0, +-90024, +0, +-89973, +0, +-89923, +0, +-89872, +0, +-89822, +0, +-89771, +0, +-89721, +0, +-89670, +0, +-89620, +0, +-89569, +0, +-89519, +0, +-89468, +0, +-89418, +0, +-89368, +0, +-89317, +0, +-89267, +0, +-89216, +0, +-89166, +0, +-89116, +0, +-89066, +0, +-89015, +0, +-88965, +0, +-88915, +0, +-88865, +0, +-88814, +0, +-88764, +0, +-88714, +0, +-88664, +0, +-88614, +0, +-88564, +0, +-88513, +0, +-88463, +0, +-88413, +0, +-88363, +0, +-88313, +0, +-88263, +0, +-88213, +0, +-88163, +0, +-88113, +0, +-88063, +0, +-88013, +0, +-87963, +0, +-87913, +0, +-87863, +0, +-87814, +0, +-87764, +0, +-87714, +0, +-87664, +0, +-87614, +0, +-87564, +0, +-87515, +0, +-87465, +0, +-87415, +0, +-87365, +0, +-87315, +0, +-87266, +0, +-87216, +0, +-87166, +0, +-87117, +0, +-87067, +0, +-87017, +0, +-86968, +0, +-86918, +0, +-86869, +0, +-86819, +0, +-86769, +0, +-86720, +0, +-86670, +0, +-86621, +0, +-86571, +0, +-86522, +0, +-86472, +0, +-86423, +0, +-86373, +0, +-86324, +0, +-86275, +0, +-86225, +0, +-86176, +0, +-86126, +0, +-86077, +0, +-86028, +0, +-85978, +0, +-85929, +0, +-85880, +0, +-85831, +0, +-85781, +0, +-85732, +0, +-85683, +0, +-85634, +0, +-85585, +0, +-85535, +0, +-85486, +0, +-85437, +0, +-85388, +0, +-85339, +0, +-85290, +0, +-85241, +0, +-85192, +0, +-85143, +0, +-85093, +0, +-85044, +0, +-84995, +0, +-84946, +0, +-84898, +0, +-84849, +0, +-84800, +0, +-84751, +0, +-84702, +0, +-84653, +0, +-84604, +0, +-84555, +0, +-84506, +0, +-84457, +0, +-84409, +0, +-84360, +0, +-84311, +0, +-84262, +0, +-84214, +0, +-84165, +0, +-84116, +0, +-84067, +0, +-84019, +0, +-83970, +0, +-83921, +0, +-83873, +0, +-83824, +0, +-83775, +0, +-83727, +0, +-83678, +0, +-83630, +0, +-83581, +0, +-83533, +0, +-83484, +0, +-83436, +0, +-83387, +0, +-83339, +0, +-83290, +0, +-83242, +0, +-83193, +0, +-83145, +0, +-83097, +0, +-83048, +0, +-83000, +0, +-82951, +0, +-82903, +0, +-82855, +0, +-82807, +0, +-82758, +0, +-82710, +0, +-82662, +0, +-82613, +0, +-82565, +0, +-82517, +0, +-82469, +0, +-82421, +0, +-82373, +0, +-82324, +0, +-82276, +0, +-82228, +0, +-82180, +0, +-82132, +0, +-82084, +0, +-82036, +0, +-81988, +0, +-81940, +0, +-81892, +0, +-81844, +0, +-81796, +0, +-81748, +0, +-81700, +0, +-81652, +0, +-81604, +0, +-81556, +0, +-81508, +0, +-81460, +0, +-81413, +0, +-81365, +0, +-81317, +0, +-81269, +0, +-81221, +0, +-81174, +0, +-81126, +0, +-81078, +0, +-81030, +0, +-80983, +0, +-80935, +0, +-80887, +0, +-80840, +0, +-80792, +0, +-80744, +0, +-80697, +0, +-80649, +0, +-80602, +0, +-80554, +0, +-80506, +0, +-80459, +0, +-80411, +0, +-80364, +0, +-80316, +0, +-80269, +0, +-80221, +0, +-80174, +0, +-80127, +0, +-80079, +0, +-80032, +0, +-79984, +0, +-79937, +0, +-79890, +0, +-79842, +0, +-79795, +0, +-79748, +0, +-79700, +0, +-79653, +0, +-79606, +0, +-79559, +0, +-79511, +0, +-79464, +0, +-79417, +0, +-79370, +0, +-79323, +0, +-79276, +0, +-79228, +0, +-79181, +0, +-79134, +0, +-79087, +0, +-79040, +0, +-78993, +0, +-78946, +0, +-78899, +0, +-78852, +0, +-78805, +0, +-78758, +0, +-78711, +0, +-78664, +0, +-78617, +0, +-78570, +0, +-78523, +0, +-78476, +0, +-78430, +0, +-78383, +0, +-78336, +0, +-78289, +0, +-78242, +0, +-78195, +0, +-78149, +0, +-78102, +0, +-78055, +0, +-78008, +0, +-77962, +0, +-77915, +0, +-77868, +0, +-77822, +0, +-77775, +0, +-77728, +0, +-77682, +0, +-77635, +0, +-77589, +0, +-77542, +0, +-77496, +0, +-77449, +0, +-77402, +0, +-77356, +0, +-77309, +0, +-77263, +0, +-77217, +0, +-77170, +0, +-77124, +0, +-77077, +0, +-77031, +0, +-76984, +0, +-76938, +0, +-76892, +0, +-76845, +0, +-76799, +0, +-76753, +0, +-76706, +0, +-76660, +0, +-76614, +0, +-76568, +0, +-76521, +0, +-76475, +0, +-76429, +0, +-76383, +0, +-76337, +0, +-76291, +0, +-76244, +0, +-76198, +0, +-76152, +0, +-76106, +0, +-76060, +0, +-76014, +0, +-75968, +0, +-75922, +0, +-75876, +0, +-75830, +0, +-75784, +0, +-75738, +0, +-75692, +0, +-75646, +0, +-75600, +0, +-75554, +0, +-75508, +0, +-75462, +0, +-75417, +0, +-75371, +0, +-75325, +0, +-75279, +0, +-75233, +0, +-75188, +0, +-75142, +0, +-75096, +0, +-75050, +0, +-75005, +0, +-74959, +0, +-74913, +0, +-74868, +0, +-74822, +0, +-74776, +0, +-74731, +0, +-74685, +0, +-74639, +0, +-74594, +0, +-74548, +0, +-74503, +0, +-74457, +0, +-74412, +0, +-74366, +0, +-74321, +0, +-74275, +0, +-74230, +0, +-74184, +0, +-74139, +0, +-74094, +0, +-74048, +0, +-74003, +0, +-73957, +0, +-73912, +0, +-73867, +0, +-73821, +0, +-73776, +-1, +-73731, +-1, +-73686, +-1, +-73640, +-1, +-73595, +-1, +-73550, +-1, +-73505, +-1, +-73459, +-1, +-73414, +-1, +-73369, +-1, +-73324, +-1, +-73279, +-1, +-73234, +-1, +-73189, +-1, +-73144, +-1, +-73099, +-1, +-73053, +-1, +-73008, +-1, +-72963, +-1, +-72918, +-1, +-72873, +-1, +-72828, +-1, +-72783, +-1, +-72739, +-1, +-72694, +-1, +-72649, +-1, +-72604, +-1, +-72559, +-1, +-72514, +-1, +-72469, +-1, +-72424, +-1, +-72380, +-1, +-72335, +-1, +-72290, +-1, +-72245, +-1, +-72200, +-1, +-72156, +-1, +-72111, +-1, +-72066, +-1, +-72022, +-1, +-71977, +-1, +-71932, +-1, +-71888, +-1, +-71843, +-1, +-71798, +-1, +-71754, +-1, +-71709, +-1, +-71665, +-1, +-71620, +-1, +-71576, +-1, +-71531, +-1, +-71487, +-1, +-71442, +-1, +-71398, +-1, +-71353, +-1, +-71309, +-1, +-71264, +-1, +-71220, +-1, +-71175, +-1, +-71131, +-1, +-71087, +-1, +-71042, +-1, +-70998, +-1, +-70954, +-1, +-70909, +-1, +-70865, +-1, +-70821, +-1, +-70776, +-1, +-70732, +-1, +-70688, +-1, +-70644, +-1, +-70600, +-1, +-70555, +-1, +-70511, +-1, +-70467, +-1, +-70423, +-1, +-70379, +-1, +-70335, +-1, +-70291, +-1, +-70247, +-1, +-70203, +-1, +-70159, +-1, +-70114, +-1, +-70070, +-1, +-70026, +-1, +-69982, +-1, +-69939, +-1, +-69895, +-1, +-69851, +-1, +-69807, +-1, +-69763, +-1, +-69719, +-1, +-69675, +-1, +-69631, +-1, +-69587, +-1, +-69544, +-1, +-69500, +-1, +-69456, +-1, +-69412, +-1, +-69368, +-1, +-69325, +-1, +-69281, +-1, +-69237, +-1, +-69193, +-1, +-69150, +-1, +-69106, +-1, +-69062, +-1, +-69019, +-1, +-68975, +-1, +-68932, +-1, +-68888, +-1, +-68844, +-1, +-68801, +-1, +-68757, +-1, +-68714, +-1, +-68670, +-1, +-68627, +-1, +-68583, +-1, +-68540, +-1, +-68496, +-1, +-68453, +-1, +-68409, +-1, +-68366, +-1, +-68323, +-1, +-68279, +-1, +-68236, +-1, +-68193, +-1, +-68149, +-1, +-68106, +-2, +-68063, +-2, +-68019, +-2, +-67976, +-2, +-67933, +-2, +-67890, +-2, +-67846, +-2, +-67803, +-2, +-67760, +-2, +-67717, +-2, +-67674, +-2, +-67630, +-2, +-67587, +-2, +-67544, +-2, +-67501, +-2, +-67458, +-2, +-67415, +-2, +-67372, +-2, +-67329, +-2, +-67286, +-2, +-67243, +-2, +-67200, +-2, +-67157, +-2, +-67114, +-2, +-67071, +-2, +-67028, +-2, +-66985, +-2, +-66942, +-2, +-66899, +-2, +-66856, +-2, +-66814, +-2, +-66771, +-2, +-66728, +-2, +-66685, +-2, +-66642, +-2, +-66600, +-2, +-66557, +-2, +-66514, +-2, +-66471, +-2, +-66429, +-2, +-66386, +-2, +-66343, +-2, +-66301, +-2, +-66258, +-2, +-66215, +-2, +-66173, +-2, +-66130, +-2, +-66088, +-2, +-66045, +-2, +-66002, +-2, +-65960, +-2, +-65917, +-2, +-65875, +-2, +-65832, +-2, +-65790, +-2, +-65747, +-2, +-65705, +-2, +-65662, +-2, +-65620, +-2, +-65578, +-2, +-65535, +-2, +-65493, +-2, +-65450, +-2, +-65408, +-2, +-65366, +-2, +-65324, +-2, +-65281, +-2, +-65239, +-2, +-65197, +-2, +-65154, +-2, +-65112, +-2, +-65070, +-2, +-65028, +-2, +-64986, +-2, +-64943, +-2, +-64901, +-2, +-64859, +-2, +-64817, +-2, +-64775, +-3, +-64733, +-3, +-64691, +-3, +-64649, +-3, +-64607, +-3, +-64565, +-3, +-64522, +-3, +-64480, +-3, +-64438, +-3, +-64397, +-3, +-64355, +-3, +-64313, +-3, +-64271, +-3, +-64229, +-3, +-64187, +-3, +-64145, +-3, +-64103, +-3, +-64061, +-3, +-64019, +-3, +-63978, +-3, +-63936, +-3, +-63894, +-3, +-63852, +-3, +-63810, +-3, +-63769, +-3, +-63727, +-3, +-63685, +-3, +-63644, +-3, +-63602, +-3, +-63560, +-3, +-63519, +-3, +-63477, +-3, +-63435, +-3, +-63394, +-3, +-63352, +-3, +-63311, +-3, +-63269, +-3, +-63227, +-3, +-63186, +-3, +-63144, +-3, +-63103, +-3, +-63061, +-3, +-63020, +-3, +-62979, +-3, +-62937, +-3, +-62896, +-3, +-62854, +-3, +-62813, +-3, +-62772, +-3, +-62730, +-3, +-62689, +-3, +-62647, +-3, +-62606, +-3, +-62565, +-3, +-62524, +-3, +-62482, +-3, +-62441, +-4, +-62400, +-4, +-62359, +-4, +-62317, +-4, +-62276, +-4, +-62235, +-4, +-62194, +-4, +-62153, +-4, +-62112, +-4, +-62071, +-4, +-62029, +-4, +-61988, +-4, +-61947, +-4, +-61906, +-4, +-61865, +-4, +-61824, +-4, +-61783, +-4, +-61742, +-4, +-61701, +-4, +-61660, +-4, +-61619, +-4, +-61578, +-4, +-61537, +-4, +-61497, +-4, +-61456, +-4, +-61415, +-4, +-61374, +-4, +-61333, +-4, +-61292, +-4, +-61251, +-4, +-61211, +-4, +-61170, +-4, +-61129, +-4, +-61088, +-4, +-61048, +-4, +-61007, +-4, +-60966, +-4, +-60926, +-4, +-60885, +-4, +-60844, +-4, +-60804, +-4, +-60763, +-4, +-60722, +-4, +-60682, +-4, +-60641, +-4, +-60601, +-5, +-60560, +-5, +-60520, +-5, +-60479, +-5, +-60439, +-5, +-60398, +-5, +-60358, +-5, +-60317, +-5, +-60277, +-5, +-60236, +-5, +-60196, +-5, +-60156, +-5, +-60115, +-5, +-60075, +-5, +-60034, +-5, +-59994, +-5, +-59954, +-5, +-59913, +-5, +-59873, +-5, +-59833, +-5, +-59793, +-5, +-59752, +-5, +-59712, +-5, +-59672, +-5, +-59632, +-5, +-59592, +-5, +-59551, +-5, +-59511, +-5, +-59471, +-5, +-59431, +-5, +-59391, +-5, +-59351, +-5, +-59311, +-5, +-59271, +-5, +-59231, +-5, +-59191, +-5, +-59151, +-5, +-59111, +-6, +-59071, +-6, +-59031, +-6, +-58991, +-6, +-58951, +-6, +-58911, +-6, +-58871, +-6, +-58831, +-6, +-58791, +-6, +-58751, +-6, +-58712, +-6, +-58672, +-6, +-58632, +-6, +-58592, +-6, +-58552, +-6, +-58513, +-6, +-58473, +-6, +-58433, +-6, +-58393, +-6, +-58354, +-6, +-58314, +-6, +-58274, +-6, +-58235, +-6, +-58195, +-6, +-58155, +-6, +-58116, +-6, +-58076, +-6, +-58037, +-6, +-57997, +-6, +-57958, +-6, +-57918, +-6, +-57879, +-7, +-57839, +-7, +-57800, +-7, +-57760, +-7, +-57721, +-7, +-57681, +-7, +-57642, +-7, +-57602, +-7, +-57563, +-7, +-57524, +-7, +-57484, +-7, +-57445, +-7, +-57405, +-7, +-57366, +-7, +-57327, +-7, +-57288, +-7, +-57248, +-7, +-57209, +-7, +-57170, +-7, +-57131, +-7, +-57091, +-7, +-57052, +-7, +-57013, +-7, +-56974, +-7, +-56935, +-7, +-56896, +-7, +-56856, +-7, +-56817, +-7, +-56778, +-8, +-56739, +-8, +-56700, +-8, +-56661, +-8, +-56622, +-8, +-56583, +-8, +-56544, +-8, +-56505, +-8, +-56466, +-8, +-56427, +-8, +-56388, +-8, +-56349, +-8, +-56310, +-8, +-56271, +-8, +-56233, +-8, +-56194, +-8, +-56155, +-8, +-56116, +-8, +-56077, +-8, +-56038, +-8, +-56000, +-8, +-55961, +-8, +-55922, +-8, +-55883, +-8, +-55845, +-8, +-55806, +-9, +-55767, +-9, +-55729, +-9, +-55690, +-9, +-55651, +-9, +-55613, +-9, +-55574, +-9, +-55535, +-9, +-55497, +-9, +-55458, +-9, +-55420, +-9, +-55381, +-9, +-55343, +-9, +-55304, +-9, +-55266, +-9, +-55227, +-9, +-55189, +-9, +-55150, +-9, +-55112, +-9, +-55073, +-9, +-55035, +-9, +-54997, +-9, +-54958, +-10, +-54920, +-10, +-54881, +-10, +-54843, +-10, +-54805, +-10, +-54767, +-10, +-54728, +-10, +-54690, +-10, +-54652, +-10, +-54613, +-10, +-54575, +-10, +-54537, +-10, +-54499, +-10, +-54461, +-10, +-54423, +-10, +-54384, +-10, +-54346, +-10, +-54308, +-10, +-54270, +-10, +-54232, +-10, +-54194, +-10, +-54156, +-11, +-54118, +-11, +-54080, +-11, +-54042, +-11, +-54004, +-11, +-53966, +-11, +-53928, +-11, +-53890, +-11, +-53852, +-11, +-53814, +-11, +-53776, +-11, +-53738, +-11, +-53700, +-11, +-53663, +-11, +-53625, +-11, +-53587, +-11, +-53549, +-11, +-53511, +-11, +-53473, +-11, +-53436, +-12, +-53398, +-12, +-53360, +-12, +-53323, +-12, +-53285, +-12, +-53247, +-12, +-53209, +-12, +-53172, +-12, +-53134, +-12, +-53097, +-12, +-53059, +-12, +-53021, +-12, +-52984, +-12, +-52946, +-12, +-52909, +-12, +-52871, +-12, +-52834, +-12, +-52796, +-13, +-52759, +-13, +-52721, +-13, +-52684, +-13, +-52646, +-13, +-52609, +-13, +-52571, +-13, +-52534, +-13, +-52497, +-13, +-52459, +-13, +-52422, +-13, +-52384, +-13, +-52347, +-13, +-52310, +-13, +-52273, +-13, +-52235, +-13, +-52198, +-14, +-52161, +-14, +-52124, +-14, +-52086, +-14, +-52049, +-14, +-52012, +-14, +-51975, +-14, +-51938, +-14, +-51900, +-14, +-51863, +-14, +-51826, +-14, +-51789, +-14, +-51752, +-14, +-51715, +-14, +-51678, +-14, +-51641, +-14, +-51604, +-15, +-51567, +-15, +-51530, +-15, +-51493, +-15, +-51456, +-15, +-51419, +-15, +-51382, +-15, +-51345, +-15, +-51308, +-15, +-51271, +-15, +-51235, +-15, +-51198, +-15, +-51161, +-15, +-51124, +-15, +-51087, +-16, +-51050, +-16, +-51014, +-16, +-50977, +-16, +-50940, +-16, +-50903, +-16, +-50867, +-16, +-50830, +-16, +-50793, +-16, +-50757, +-16, +-50720, +-16, +-50683, +-16, +-50647, +-16, +-50610, +-17, +-50574, +-17, +-50537, +-17, +-50500, +-17, +-50464, +-17, +-50427, +-17, +-50391, +-17, +-50354, +-17, +-50318, +-17, +-50281, +-17, +-50245, +-17, +-50208, +-17, +-50172, +-17, +-50136, +-18, +-50099, +-18, +-50063, +-18, +-50026, +-18, +-49990, +-18, +-49954, +-18, +-49917, +-18, +-49881, +-18, +-49845, +-18, +-49809, +-18, +-49772, +-18, +-49736, +-18, +-49700, +-19, +-49664, +-19, +-49627, +-19, +-49591, +-19, +-49555, +-19, +-49519, +-19, +-49483, +-19, +-49447, +-19, +-49410, +-19, +-49374, +-19, +-49338, +-19, +-49302, +-19, +-49266, +-20, +-49230, +-20, +-49194, +-20, +-49158, +-20, +-49122, +-20, +-49086, +-20, +-49050, +-20, +-49014, +-20, +-48978, +-20, +-48942, +-20, +-48907, +-20, +-48871, +-21, +-48835, +-21, +-48799, +-21, +-48763, +-21, +-48727, +-21, +-48691, +-21, +-48656, +-21, +-48620, +-21, +-48584, +-21, +-48548, +-21, +-48513, +-21, +-48477, +-22, +-48441, +-22, +-48406, +-22, +-48370, +-22, +-48334, +-22, +-48299, +-22, +-48263, +-22, +-48227, +-22, +-48192, +-22, +-48156, +-22, +-48121, +-23, +-48085, +-23, +-48049, +-23, +-48014, +-23, +-47978, +-23, +-47943, +-23, +-47907, +-23, +-47872, +-23, +-47837, +-23, +-47801, +-23, +-47766, +-24, +-47730, +-24, +-47695, +-24, +-47660, +-24, +-47624, +-24, +-47589, +-24, +-47554, +-24, +-47518, +-24, +-47483, +-24, +-47448, +-25, +-47412, +-25, +-47377, +-25, +-47342, +-25, +-47307, +-25, +-47272, +-25, +-47236, +-25, +-47201, +-25, +-47166, +-25, +-47131, +-26, +-47096, +-26, +-47061, +-26, +-47026, +-26, +-46990, +-26, +-46955, +-26, +-46920, +-26, +-46885, +-26, +-46850, +-26, +-46815, +-27, +-46780, +-27, +-46745, +-27, +-46710, +-27, +-46675, +-27, +-46640, +-27, +-46606, +-27, +-46571, +-27, +-46536, +-27, +-46501, +-28, +-46466, +-28, +-46431, +-28, +-46396, +-28, +-46361, +-28, +-46327, +-28, +-46292, +-28, +-46257, +-28, +-46222, +-29, +-46188, +-29, +-46153, +-29, +-46118, +-29, +-46084, +-29, +-46049, +-29, +-46014, +-29, +-45980, +-29, +-45945, +-30, +-45910, +-30, +-45876, +-30, +-45841, +-30, +-45807, +-30, +-45772, +-30, +-45737, +-30, +-45703, +-30, +-45668, +-31, +-45634, +-31, +-45599, +-31, +-45565, +-31, +-45531, +-31, +-45496, +-31, +-45462, +-31, +-45427, +-32, +-45393, +-32, +-45358, +-32, +-45324, +-32, +-45290, +-32, +-45255, +-32, +-45221, +-32, +-45187, +-33, +-45153, +-33, +-45118, +-33, +-45084, +-33, +-45050, +-33, +-45016, +-33, +-44981, +-33, +-44947, +-33, +-44913, +-34, +-44879, +-34, +-44845, +-34, +-44811, +-34, +-44776, +-34, +-44742, +-34, +-44708, +-35, +-44674, +-35, +-44640, +-35, +-44606, +-35, +-44572, +-35, +-44538, +-35, +-44504, +-35, +-44470, +-36, +-44436, +-36, +-44402, +-36, +-44368, +-36, +-44334, +-36, +-44300, +-36, +-44266, +-36, +-44233, +-37, +-44199, +-37, +-44165, +-37, +-44131, +-37, +-44097, +-37, +-44063, +-37, +-44030, +-38, +-43996, +-38, +-43962, +-38, +-43928, +-38, +-43895, +-38, +-43861, +-38, +-43827, +-38, +-43793, +-39, +-43760, +-39, +-43726, +-39, +-43692, +-39, +-43659, +-39, +-43625, +-39, +-43592, +-40, +-43558, +-40, +-43524, +-40, +-43491, +-40, +-43457, +-40, +-43424, +-40, +-43390, +-41, +-43357, +-41, +-43323, +-41, +-43290, +-41, +-43256, +-41, +-43223, +-41, +-43190, +-42, +-43156, +-42, +-43123, +-42, +-43089, +-42, +-43056, +-42, +-43023, +-43, +-42989, +-43, +-42956, +-43, +-42923, +-43, +-42890, +-43, +-42856, +-43, +-42823, +-44, +-42790, +-44, +-42757, +-44, +-42723, +-44, +-42690, +-44, +-42657, +-44, +-42624, +-45, +-42591, +-45, +-42558, +-45, +-42524, +-45, +-42491, +-45, +-42458, +-46, +-42425, +-46, +-42392, +-46, +-42359, +-46, +-42326, +-46, +-42293, +-47, +-42260, +-47, +-42227, +-47, +-42194, +-47, +-42161, +-47, +-42128, +-47, +-42095, +-48, +-42062, +-48, +-42030, +-48, +-41997, +-48, +-41964, +-48, +-41931, +-49, +-41898, +-49, +-41865, +-49, +-41832, +-49, +-41800, +-49, +-41767, +-50, +-41734, +-50, +-41701, +-50, +-41669, +-50, +-41636, +-50, +-41603, +-51, +-41571, +-51, +-41538, +-51, +-41505, +-51, +-41473, +-52, +-41440, +-52, +-41407, +-52, +-41375, +-52, +-41342, +-52, +-41310, +-53, +-41277, +-53, +-41245, +-53, +-41212, +-53, +-41180, +-53, +-41147, +-54, +-41115, +-54, +-41082, +-54, +-41050, +-54, +-41017, +-54, +-40985, +-55, +-40952, +-55, +-40920, +-55, +-40888, +-55, +-40855, +-56, +-40823, +-56, +-40791, +-56, +-40758, +-56, +-40726, +-56, +-40694, +-57, +-40662, +-57, +-40629, +-57, +-40597, +-57, +-40565, +-58, +-40533, +-58, +-40500, +-58, +-40468, +-58, +-40436, +-59, +-40404, +-59, +-40372, +-59, +-40340, +-59, +-40308, +-59, +-40276, +-60, +-40243, +-60, +-40211, +-60, +-40179, +-60, +-40147, +-61, +-40115, +-61, +-40083, +-61, +-40051, +-61, +-40019, +-62, +-39987, +-62, +-39955, +-62, +-39924, +-62, +-39892, +-63, +-39860, +-63, +-39828, +-63, +-39796, +-63, +-39764, +-64, +-39732, +-64, +-39700, +-64, +-39669, +-64, +-39637, +-65, +-39605, +-65, +-39573, +-65, +-39542, +-65, +-39510, +-66, +-39478, +-66, +-39446, +-66, +-39415, +-66, +-39383, +-67, +-39351, +-67, +-39320, +-67, +-39288, +-67, +-39257, +-68, +-39225, +-68, +-39193, +-68, +-39162, +-69, +-39130, +-69, +-39099, +-69, +-39067, +-69, +-39036, +-70, +-39004, +-70, +-38973, +-70, +-38941, +-70, +-38910, +-71, +-38878, +-71, +-38847, +-71, +-38816, +-72, +-38784, +-72, +-38753, +-72, +-38721, +-72, +-38690, +-73, +-38659, +-73, +-38627, +-73, +-38596, +-73, +-38565, +-74, +-38534, +-74, +-38502, +-74, +-38471, +-75, +-38440, +-75, +-38409, +-75, +-38377, +-75, +-38346, +-76, +-38315, +-76, +-38284, +-76, +-38253, +-77, +-38222, +-77, +-38191, +-77, +-38160, +-78, +-38128, +-78, +-38097, +-78, +-38066, +-78, +-38035, +-79, +-38004, +-79, +-37973, +-79, +-37942, +-80, +-37911, +-80, +-37880, +-80, +-37849, +-81, +-37818, +-81, +-37788, +-81, +-37757, +-82, +-37726, +-82, +-37695, +-82, +-37664, +-82, +-37633, +-83, +-37602, +-83, +-37572, +-83, +-37541, +-84, +-37510, +-84, +-37479, +-84, +-37448, +-85, +-37418, +-85, +-37387, +-85, +-37356, +-86, +-37326, +-86, +-37295, +-86, +-37264, +-87, +-37234, +-87, +-37203, +-87, +-37172, +-88, +-37142, +-88, +-37111, +-88, +-37081, +-89, +-37050, +-89, +-37020, +-89, +-36989, +-90, +-36958, +-90, +-36928, +-90, +-36897, +-91, +-36867, +-91, +-36837, +-91, +-36806, +-92, +-36776, +-92, +-36745, +-92, +-36715, +-93, +-36684, +-93, +-36654, +-93, +-36624, +-94, +-36593, +-94, +-36563, +-94, +-36533, +-95, +-36503, +-95, +-36472, +-96, +-36442, +-96, +-36412, +-96, +-36381, +-97, +-36351, +-97, +-36321, +-97, +-36291, +-98, +-36261, +-98, +-36231, +-98, +-36200, +-99, +-36170, +-99, +-36140, +-100, +-36110, +-100, +-36080, +-100, +-36050, +-101, +-36020, +-101, +-35990, +-101, +-35960, +-102, +-35930, +-102, +-35900, +-103, +-35870, +-103, +-35840, +-103, +-35810, +-104, +-35780, +-104, +-35750, +-104, +-35720, +-105, +-35690, +-105, +-35660, +-106, +-35630, +-106, +-35601, +-106, +-35571, +-107, +-35541, +-107, +-35511, +-108, +-35481, +-108, +-35452, +-108, +-35422, +-109, +-35392, +-109, +-35362, +-110, +-35333, +-110, +-35303, +-110, +-35273, +-111, +-35243, +-111, +-35214, +-112, +-35184, +-112, +-35155, +-112, +-35125, +-113, +-35095, +-113, +-35066, +-114, +-35036, +-114, +-35007, +-114, +-34977, +-115, +-34948, +-115, +-34918, +-116, +-34889, +-116, +-34859, +-117, +-34830, +-117, +-34800, +-117, +-34771, +-118, +-34741, +-118, +-34712, +-119, +-34682, +-119, +-34653, +-120, +-34624, +-120, +-34594, +-120, +-34565, +-121, +-34536, +-121, +-34506, +-122, +-34477, +-122, +-34448, +-123, +-34419, +-123, +-34389, +-124, +-34360, +-124, +-34331, +-124, +-34302, +-125, +-34272, +-125, +-34243, +-126, +-34214, +-126, +-34185, +-127, +-34156, +-127, +-34127, +-128, +-34098, +-128, +-34069, +-129, +-34039, +-129, +-34010, +-129, +-33981, +-130, +-33952, +-130, +-33923, +-131, +-33894, +-131, +-33865, +-132, +-33836, +-132, +-33807, +-133, +-33778, +-133, +-33750, +-134, +-33721, +-134, +-33692, +-135, +-33663, +-135, +-33634, +-136, +-33605, +-136, +-33576, +-137, +-33547, +-137, +-33519, +-138, +-33490, +-138, +-33461, +-139, +-33432, +-139, +-33404, +-140, +-33375, +-140, +-33346, +-141, +-33317, +-141, +-33289, +-142, +-33260, +-142, +-33231, +-143, +-33203, +-143, +-33174, +-144, +-33145, +-144, +-33117, +-145, +-33088, +-145, +-33060, +-146, +-33031, +-146, +-33003, +-147, +-32974, +-147, +-32945, +-148, +-32917, +-148, +-32888, +-149, +-32860, +-149, +-32832, +-150, +-32803, +-150, +-32775, +-151, +-32746, +-151, +-32718, +-152, +-32689, +-152, +-32661, +-153, +-32633, +-153, +-32604, +-154, +-32576, +-155, +-32548, +-155, +-32519, +-156, +-32491, +-156, +-32463, +-157, +-32435, +-157, +-32406, +-158, +-32378, +-158, +-32350, +-159, +-32322, +-159, +-32294, +-160, +-32265, +-161, +-32237, +-161, +-32209, +-162, +-32181, +-162, +-32153, +-163, +-32125, +-163, +-32097, +-164, +-32069, +-165, +-32041, +-165, +-32013, +-166, +-31985, +-166, +-31957, +-167, +-31929, +-167, +-31901, +-168, +-31873, +-169, +-31845, +-169, +-31817, +-170, +-31789, +-170, +-31761, +-171, +-31733, +-172, +-31705, +-172, +-31677, +-173, +-31649, +-173, +-31622, +-174, +-31594, +-175, +-31566, +-175, +-31538, +-176, +-31510, +-176, +-31483, +-177, +-31455, +-178, +-31427, +-178, +-31399, +-179, +-31372, +-179, +-31344, +-180, +-31316, +-181, +-31289, +-181, +-31261, +-182, +-31233, +-182, +-31206, +-183, +-31178, +-184, +-31151, +-184, +-31123, +-185, +-31096, +-186, +-31068, +-186, +-31040, +-187, +-31013, +-188, +-30985, +-188, +-30958, +-189, +-30931, +-189, +-30903, +-190, +-30876, +-191, +-30848, +-191, +-30821, +-192, +-30793, +-193, +-30766, +-193, +-30739, +-194, +-30711, +-195, +-30684, +-195, +-30657, +-196, +-30629, +-197, +-30602, +-197, +-30575, +-198, +-30547, +-199, +-30520, +-199, +-30493, +-200, +-30466, +-201, +-30439, +-201, +-30411, +-202, +-30384, +-203, +-30357, +-203, +-30330, +-204, +-30303, +-205, +-30276, +-205, +-30249, +-206, +-30221, +-207, +-30194, +-208, +-30167, +-208, +-30140, +-209, +-30113, +-210, +-30086, +-210, +-30059, +-211, +-30032, +-212, +-30005, +-212, +-29978, +-213, +-29951, +-214, +-29924, +-215, +-29897, +-215, +-29871, +-216, +-29844, +-217, +-29817, +-217, +-29790, +-218, +-29763, +-219, +-29736, +-220, +-29709, +-220, +-29683, +-221, +-29656, +-222, +-29629, +-223, +-29602, +-223, +-29576, +-224, +-29549, +-225, +-29522, +-226, +-29495, +-226, +-29469, +-227, +-29442, +-228, +-29415, +-229, +-29389, +-229, +-29362, +-230, +-29335, +-231, +-29309, +-232, +-29282, +-232, +-29256, +-233, +-29229, +-234, +-29203, +-235, +-29176, +-235, +-29150, +-236, +-29123, +-237, +-29097, +-238, +-29070, +-239, +-29044, +-239, +-29017, +-240, +-28991, +-241, +-28964, +-242, +-28938, +-243, +-28912, +-243, +-28885, +-244, +-28859, +-245, +-28832, +-246, +-28806, +-247, +-28780, +-247, +-28754, +-248, +-28727, +-249, +-28701, +-250, +-28675, +-251, +-28649, +-251, +-28622, +-252, +-28596, +-253, +-28570, +-254, +-28544, +-255, +-28518, +-256, +-28491, +-256, +-28465, +-257, +-28439, +-258, +-28413, +-259, +-28387, +-260, +-28361, +-261, +-28335, +-261, +-28309, +-262, +-28283, +-263, +-28257, +-264, +-28231, +-265, +-28205, +-266, +-28179, +-267, +-28153, +-267, +-28127, +-268, +-28101, +-269, +-28075, +-270, +-28049, +-271, +-28023, +-272, +-27997, +-273, +-27971, +-273, +-27945, +-274, +-27920, +-275, +-27894, +-276, +-27868, +-277, +-27842, +-278, +-27816, +-279, +-27791, +-280, +-27765, +-281, +-27739, +-281, +-27713, +-282, +-27688, +-283, +-27662, +-284, +-27636, +-285, +-27611, +-286, +-27585, +-287, +-27559, +-288, +-27534, +-289, +-27508, +-290, +-27483, +-291, +-27457, +-292, +-27431, +-292, +-27406, +-293, +-27380, +-294, +-27355, +-295, +-27329, +-296, +-27304, +-297, +-27278, +-298, +-27253, +-299, +-27227, +-300, +-27202, +-301, +-27176, +-302, +-27151, +-303, +-27126, +-304, +-27100, +-305, +-27075, +-306, +-27050, +-307, +-27024, +-308, +-26999, +-309, +-26974, +-310, +-26948, +-311, +-26923, +-312, +-26898, +-313, +-26873, +-314, +-26847, +-315, +-26822, +-316, +-26797, +-317, +-26772, +-318, +-26746, +-319, +-26721, +-320, +-26696, +-321, +-26671, +-322, +-26646, +-323, +-26621, +-324, +-26596, +-325, +-26571, +-326, +-26546, +-327, +-26520, +-328, +-26495, +-329, +-26470, +-330, +-26445, +-331, +-26420, +-332, +-26395, +-333, +-26370, +-334, +-26346, +-335, +-26321, +-336, +-26296, +-337, +-26271, +-338, +-26246, +-339, +-26221, +-340, +-26196, +-341, +-26171, +-342, +-26146, +-343, +-26122, +-344, +-26097, +-345, +-26072, +-347, +-26047, +-348, +-26022, +-349, +-25998, +-350, +-25973, +-351, +-25948, +-352, +-25924, +-353, +-25899, +-354, +-25874, +-355, +-25849, +-356, +-25825, +-357, +-25800, +-358, +-25776, +-360, +-25751, +-361, +-25726, +-362, +-25702, +-363, +-25677, +-364, +-25653, +-365, +-25628, +-366, +-25604, +-367, +-25579, +-369, +-25555, +-370, +-25530, +-371, +-25506, +-372, +-25481, +-373, +-25457, +-374, +-25432, +-375, +-25408, +-376, +-25383, +-378, +-25359, +-379, +-25335, +-380, +-25310, +-381, +-25286, +-382, +-25262, +-383, +-25237, +-385, +-25213, +-386, +-25189, +-387, +-25165, +-388, +-25140, +-389, +-25116, +-390, +-25092, +-392, +-25068, +-393, +-25043, +-394, +-25019, +-395, +-24995, +-396, +-24971, +-398, +-24947, +-399, +-24923, +-400, +-24898, +-401, +-24874, +-402, +-24850, +-404, +-24826, +-405, +-24802, +-406, +-24778, +-407, +-24754, +-409, +-24730, +-410, +-24706, +-411, +-24682, +-412, +-24658, +-414, +-24634, +-415, +-24610, +-416, +-24586, +-417, +-24562, +-419, +-24538, +-420, +-24515, +-421, +-24491, +-422, +-24467, +-424, +-24443, +-425, +-24419, +-426, +-24395, +-427, +-24372, +-429, +-24348, +-430, +-24324, +-431, +-24300, +-433, +-24276, +-434, +-24253, +-435, +-24229, +-436, +-24205, +-438, +-24182, +-439, +-24158, +-440, +-24134, +-442, +-24111, +-443, +-24087, +-444, +-24063, +-446, +-24040, +-447, +-24016, +-448, +-23993, +-450, +-23969, +-451, +-23945, +-452, +-23922, +-454, +-23898, +-455, +-23875, +-456, +-23851, +-458, +-23828, +-459, +-23804, +-460, +-23781, +-462, +-23758, +-463, +-23734, +-464, +-23711, +-466, +-23687, +-467, +-23664, +-469, +-23641, +-470, +-23617, +-471, +-23594, +-473, +-23571, +-474, +-23547, +-475, +-23524, +-477, +-23501, +-478, +-23477, +-480, +-23454, +-481, +-23431, +-482, +-23408, +-484, +-23384, +-485, +-23361, +-487, +-23338, +-488, +-23315, +-490, +-23292, +-491, +-23269, +-492, +-23245, +-494, +-23222, +-495, +-23199, +-497, +-23176, +-498, +-23153, +-500, +-23130, +-501, +-23107, +-503, +-23084, +-504, +-23061, +-505, +-23038, +-507, +-23015, +-508, +-22992, +-510, +-22969, +-511, +-22946, +-513, +-22923, +-514, +-22900, +-516, +-22877, +-517, +-22854, +-519, +-22832, +-520, +-22809, +-522, +-22786, +-523, +-22763, +-525, +-22740, +-526, +-22717, +-528, +-22695, +-529, +-22672, +-531, +-22649, +-532, +-22626, +-534, +-22604, +-536, +-22581, +-537, +-22558, +-539, +-22535, +-540, +-22513, +-542, +-22490, +-543, +-22467, +-545, +-22445, +-546, +-22422, +-548, +-22400, +-549, +-22377, +-551, +-22354, +-553, +-22332, +-554, +-22309, +-556, +-22287, +-557, +-22264, +-559, +-22242, +-561, +-22219, +-562, +-22197, +-564, +-22174, +-565, +-22152, +-567, +-22129, +-569, +-22107, +-570, +-22084, +-572, +-22062, +-573, +-22040, +-575, +-22017, +-577, +-21995, +-578, +-21973, +-580, +-21950, +-582, +-21928, +-583, +-21906, +-585, +-21883, +-587, +-21861, +-588, +-21839, +-590, +-21817, +-592, +-21794, +-593, +-21772, +-595, +-21750, +-597, +-21728, +-598, +-21706, +-600, +-21683, +-602, +-21661, +-603, +-21639, +-605, +-21617, +-607, +-21595, +-608, +-21573, +-610, +-21551, +-612, +-21529, +-614, +-21507, +-615, +-21485, +-617, +-21462, +-619, +-21440, +-620, +-21418, +-622, +-21396, +-624, +-21375, +-626, +-21353, +-627, +-21331, +-629, +-21309, +-631, +-21287, +-633, +-21265, +-634, +-21243, +-636, +-21221, +-638, +-21199, +-640, +-21177, +-642, +-21156, +-643, +-21134, +-645, +-21112, +-647, +-21090, +-649, +-21068, +-650, +-21047, +-652, +-21025, +-654, +-21003, +-656, +-20981, +-658, +-20960, +-660, +-20938, +-661, +-20916, +-663, +-20895, +-665, +-20873, +-667, +-20851, +-669, +-20830, +-671, +-20808, +-672, +-20787, +-674, +-20765, +-676, +-20743, +-678, +-20722, +-680, +-20700, +-682, +-20679, +-684, +-20657, +-685, +-20636, +-687, +-20614, +-689, +-20593, +-691, +-20571, +-693, +-20550, +-695, +-20528, +-697, +-20507, +-699, +-20486, +-701, +-20464, +-703, +-20443, +-704, +-20421, +-706, +-20400, +-708, +-20379, +-710, +-20357, +-712, +-20336, +-714, +-20315, +-716, +-20294, +-718, +-20272, +-720, +-20251, +-722, +-20230, +-724, +-20209, +-726, +-20187, +-728, +-20166, +-730, +-20145, +-732, +-20124, +-734, +-20103, +-736, +-20082, +-738, +-20060, +-740, +-20039, +-742, +-20018, +-744, +-19997, +-746, +-19976, +-748, +-19955, +-750, +-19934, +-752, +-19913, +-754, +-19892, +-756, +-19871, +-758, +-19850, +-760, +-19829, +-762, +-19808, +-764, +-19787, +-766, +-19766, +-768, +-19745, +-770, +-19724, +-772, +-19703, +-774, +-19682, +-776, +-19662, +-778, +-19641, +-781, +-19620, +-783, +-19599, +-785, +-19578, +-787, +-19557, +-789, +-19537, +-791, +-19516, +-793, +-19495, +-795, +-19474, +-797, +-19454, +-799, +-19433, +-802, +-19412, +-804, +-19392, +-806, +-19371, +-808, +-19350, +-810, +-19330, +-812, +-19309, +-814, +-19288, +-817, +-19268, +-819, +-19247, +-821, +-19226, +-823, +-19206, +-825, +-19185, +-827, +-19165, +-830, +-19144, +-832, +-19124, +-834, +-19103, +-836, +-19083, +-838, +-19062, +-841, +-19042, +-843, +-19021, +-845, +-19001, +-847, +-18981, +-850, +-18960, +-852, +-18940, +-854, +-18919, +-856, +-18899, +-859, +-18879, +-861, +-18858, +-863, +-18838, +-865, +-18818, +-868, +-18797, +-870, +-18777, +-872, +-18757, +-874, +-18737, +-877, +-18716, +-879, +-18696, +-881, +-18676, +-884, +-18656, +-886, +-18636, +-888, +-18615, +-891, +-18595, +-893, +-18575, +-895, +-18555, +-897, +-18535, +-900, +-18515, +-902, +-18495, +-905, +-18475, +-907, +-18454, +-909, +-18434, +-912, +-18414, +-914, +-18394, +-916, +-18374, +-919, +-18354, +-921, +-18334, +-923, +-18314, +-926, +-18294, +-928, +-18275, +-931, +-18255, +-933, +-18235, +-935, +-18215, +-938, +-18195, +-940, +-18175, +-943, +-18155, +-945, +-18135, +-948, +-18115, +-950, +-18096, +-952, +-18076, +-955, +-18056, +-957, +-18036, +-960, +-18016, +-962, +-17997, +-965, +-17977, +-967, +-17957, +-970, +-17938, +-972, +-17918, +-975, +-17898, +-977, +-17879, +-980, +-17859, +-982, +-17839, +-985, +-17820, +-987, +-17800, +-990, +-17780, +-992, +-17761, +-995, +-17741, +-997, +-17722, +-1000, +-17702, +-1002, +-17683, +-1005, +-17663, +-1007, +-17643, +-1010, +-17624, +-1013, +-17605, +-1015, +-17585, +-1018, +-17566, +-1020, +-17546, +-1023, +-17527, +-1025, +-17507, +-1028, +-17488, +-1031, +-17469, +-1033, +-17449, +-1036, +-17430, +-1038, +-17410, +-1041, +-17391, +-1044, +-17372, +-1046, +-17352, +-1049, +-17333, +-1052, +-17314, +-1054, +-17295, +-1057, +-17275, +-1060, +-17256, +-1062, +-17237, +-1065, +-17218, +-1068, +-17198, +-1070, +-17179, +-1073, +-17160, +-1076, +-17141, +-1078, +-17122, +-1081, +-17103, +-1084, +-17084, +-1086, +-17064, +-1089, +-17045, +-1092, +-17026, +-1095, +-17007, +-1097, +-16988, +-1100, +-16969, +-1103, +-16950, +-1105, +-16931, +-1108, +-16912, +-1111, +-16893, +-1114, +-16874, +-1117, +-16855, +-1119, +-16836, +-1122, +-16817, +-1125, +-16798, +-1128, +-16779, +-1130, +-16761, +-1133, +-16742, +-1136, +-16723, +-1139, +-16704, +-1142, +-16685, +-1145, +-16666, +-1147, +-16647, +-1150, +-16629, +-1153, +-16610, +-1156, +-16591, +-1159, +-16572, +-1162, +-16554, +-1164, +-16535, +-1167, +-16516, +-1170, +-16497, +-1173, +-16479, +-1176, +-16460, +-1179, +-16441, +-1182, +-16423, +-1185, +-16404, +-1188, +-16386, +-1190, +-16367, +-1193, +-16348, +-1196, +-16330, +-1199, +-16311, +-1202, +-16293, +-1205, +-16274, +-1208, +-16256, +-1211, +-16237, +-1214, +-16218, +-1217, +-16200, +-1220, +-16182, +-1223, +-16163, +-1226, +-16145, +-1229, +-16126, +-1232, +-16108, +-1235, +-16089, +-1238, +-16071, +-1241, +-16053, +-1244, +-16034, +-1247, +-16016, +-1250, +-15997, +-1253, +-15979, +-1256, +-15961, +-1259, +-15942, +-1262, +-15924, +-1265, +-15906, +-1268, +-15888, +-1271, +-15869, +-1274, +-15851, +-1277, +-15833, +-1280, +-15815, +-1283, +-15796, +-1287, +-15778, +-1290, +-15760, +-1293, +-15742, +-1296, +-15724, +-1299, +-15706, +-1302, +-15688, +-1305, +-15669, +-1308, +-15651, +-1311, +-15633, +-1315, +-15615, +-1318, +-15597, +-1321, +-15579, +-1324, +-15561, +-1327, +-15543, +-1330, +-15525, +-1334, +-15507, +-1337, +-15489, +-1340, +-15471, +-1343, +-15453, +-1346, +-15435, +-1350, +-15417, +-1353, +-15399, +-1356, +-15382, +-1359, +-15364, +-1363, +-15346, +-1366, +-15328, +-1369, +-15310, +-1372, +-15292, +-1376, +-15274, +-1379, +-15257, +-1382, +-15239, +-1385, +-15221, +-1389, +-15203, +-1392, +-15186, +-1395, +-15168, +-1398, +-15150, +-1402, +-15132, +-1405, +-15115, +-1408, +-15097, +-1412, +-15079, +-1415, +-15062, +-1418, +-15044, +-1422, +-15026, +-1425, +-15009, +-1428, +-14991, +-1432, +-14973, +-1435, +-14956, +-1439, +-14938, +-1442, +-14921, +-1445, +-14903, +-1449, +-14886, +-1452, +-14868, +-1455, +-14851, +-1459, +-14833, +-1462, +-14816, +-1466, +-14798, +-1469, +-14781, +-1473, +-14763, +-1476, +-14746, +-1479, +-14729, +-1483, +-14711, +-1486, +-14694, +-1490, +-14676, +-1493, +-14659, +-1497, +-14642, +-1500, +-14624, +-1504, +-14607, +-1507, +-14590, +-1511, +-14572, +-1514, +-14555, +-1518, +-14538, +-1521, +-14521, +-1525, +-14503, +-1528, +-14486, +-1532, +-14469, +-1535, +-14452, +-1539, +-14435, +-1543, +-14417, +-1546, +-14400, +-1550, +-14383, +-1553, +-14366, +-1557, +-14349, +-1560, +-14332, +-1564, +-14315, +-1568, +-14297, +-1571, +-14280, +-1575, +-14263, +-1579, +-14246, +-1582, +-14229, +-1586, +-14212, +-1589, +-14195, +-1593, +-14178, +-1597, +-14161, +-1600, +-14144, +-1604, +-14127, +-1608, +-14110, +-1611, +-14093, +-1615, +-14077, +-1619, +-14060, +-1622, +-14043, +-1626, +-14026, +-1630, +-14009, +-1634, +-13992, +-1637, +-13975, +-1641, +-13958, +-1645, +-13942, +-1649, +-13925, +-1652, +-13908, +-1656, +-13891, +-1660, +-13875, +-1664, +-13858, +-1667, +-13841, +-1671, +-13824, +-1675, +-13808, +-1679, +-13791, +-1683, +-13774, +-1686, +-13758, +-1690, +-13741, +-1694, +-13724, +-1698, +-13708, +-1702, +-13691, +-1706, +-13674, +-1709, +-13658, +-1713, +-13641, +-1717, +-13625, +-1721, +-13608, +-1725, +-13592, +-1729, +-13575, +-1733, +-13558, +-1736, +-13542, +-1740, +-13525, +-1744, +-13509, +-1748, +-13493, +-1752, +-13476, +-1756, +-13460, +-1760, +-13443, +-1764, +-13427, +-1768, +-13410, +-1772, +-13394, +-1776, +-13378, +-1780, +-13361, +-1784, +-13345, +-1788, +-13329, +-1792, +-13312, +-1796, +-13296, +-1800, +-13280, +-1804, +-13263, +-1808, +-13247, +-1812, +-13231, +-1816, +-13215, +-1820, +-13198, +-1824, +-13182, +-1828, +-13166, +-1832, +-13150, +-1836, +-13134, +-1840, +-13117, +-1844, +-13101, +-1848, +-13085, +-1852, +-13069, +-1857, +-13053, +-1861, +-13037, +-1865, +-13021, +-1869, +-13005, +-1873, +-12988, +-1877, +-12972, +-1881, +-12956, +-1885, +-12940, +-1890, +-12924, +-1894, +-12908, +-1898, +-12892, +-1902, +-12876, +-1906, +-12860, +-1910, +-12844, +-1915, +-12828, +-1919, +-12813, +-1923, +-12797, +-1927, +-12781, +-1931, +-12765, +-1936, +-12749, +-1940, +-12733, +-1944, +-12717, +-1948, +-12701, +-1953, +-12686, +-1957, +-12670, +-1961, +-12654, +-1966, +-12638, +-1970, +-12622, +-1974, +-12607, +-1978, +-12591, +-1983, +-12575, +-1987, +-12559, +-1991, +-12544, +-1996, +-12528, +-2000, +-12512, +-2004, +-12497, +-2009, +-12481, +-2013, +-12465, +-2017, +-12450, +-2022, +-12434, +-2026, +-12418, +-2031, +-12403, +-2035, +-12387, +-2039, +-12372, +-2044, +-12356, +-2048, +-12341, +-2053, +-12325, +-2057, +-12310, +-2062, +-12294, +-2066, +-12279, +-2070, +-12263, +-2075, +-12248, +-2079, +-12232, +-2084, +-12217, +-2088, +-12201, +-2093, +-12186, +-2097, +-12170, +-2102, +-12155, +-2106, +-12140, +-2111, +-12124, +-2115, +-12109, +-2120, +-12094, +-2124, +-12078, +-2129, +-12063, +-2133, +-12048, +-2138, +-12032, +-2143, +-12017, +-2147, +-12002, +-2152, +-11986, +-2156, +-11971, +-2161, +-11956, +-2166, +-11941, +-2170, +-11926, +-2175, +-11910, +-2179, +-11895, +-2184, +-11880, +-2189, +-11865, +-2193, +-11850, +-2198, +-11835, +-2203, +-11819, +-2207, +-11804, +-2212, +-11789, +-2217, +-11774, +-2221, +-11759, +-2226, +-11744, +-2231, +-11729, +-2236, +-11714, +-2240, +-11699, +-2245, +-11684, +-2250, +-11669, +-2254, +-11654, +-2259, +-11639, +-2264, +-11624, +-2269, +-11609, +-2274, +-11594, +-2278, +-11579, +-2283, +-11564, +-2288, +-11549, +-2293, +-11535, +-2298, +-11520, +-2302, +-11505, +-2307, +-11490, +-2312, +-11475, +-2317, +-11460, +-2322, +-11446, +-2327, +-11431, +-2331, +-11416, +-2336, +-11401, +-2341, +-11386, +-2346, +-11372, +-2351, +-11357, +-2356, +-11342, +-2361, +-11328, +-2366, +-11313, +-2371, +-11298, +-2376, +-11283, +-2381, +-11269, +-2385, +-11254, +-2390, +-11240, +-2395, +-11225, +-2400, +-11210, +-2405, +-11196, +-2410, +-11181, +-2415, +-11167, +-2420, +-11152, +-2425, +-11137, +-2430, +-11123, +-2435, +-11108, +-2440, +-11094, +-2445, +-11079, +-2451, +-11065, +-2456, +-11050, +-2461, +-11036, +-2466, +-11022, +-2471, +-11007, +-2476, +-10993, +-2481, +-10978, +-2486, +-10964, +-2491, +-10949, +-2496, +-10935, +-2501, +-10921, +-2507, +-10906, +-2512, +-10892, +-2517, +-10878, +-2522, +-10863, +-2527, +-10849, +-2532, +-10835, +-2538, +-10821, +-2543, +-10806, +-2548, +-10792, +-2553, +-10778, +-2558, +-10764, +-2564, +-10749, +-2569, +-10735, +-2574, +-10721, +-2579, +-10707, +-2585, +-10693, +-2590, +-10678, +-2595, +-10664, +-2600, +-10650, +-2606, +-10636, +-2611, +-10622, +-2616, +-10608, +-2622, +-10594, +-2627, +-10580, +-2632, +-10566, +-2638, +-10552, +-2643, +-10538, +-2648, +-10524, +-2654, +-10510, +-2659, +-10496, +-2664, +-10482, +-2670, +-10468, +-2675, +-10454, +-2680, +-10440, +-2686, +-10426, +-2691, +-10412, +-2697, +-10398, +-2702, +-10384, +-2708, +-10370, +-2713, +-10356, +-2719, +-10342, +-2724, +-10329, +-2729, +-10315, +-2735, +-10301, +-2740, +-10287, +-2746, +-10273, +-2751, +-10260, +-2757, +-10246, +-2762, +-10232, +-2768, +-10218, +-2773, +-10205, +-2779, +-10191, +-2785, +-10177, +-2790, +-10163, +-2796, +-10150, +-2801, +-10136, +-2807, +-10122, +-2812, +-10109, +-2818, +-10095, +-2824, +-10081, +-2829, +-10068, +-2835, +-10054, +-2841, +-10041, +-2846, +-10027, +-2852, +-10013, +-2857, +-10000, +-2863, +-9986, +-2869, +-9973, +-2875, +-9959, +-2880, +-9946, +-2886, +-9932, +-2892, +-9919, +-2897, +-9905, +-2903, +-9892, +-2909, +-9878, +-2915, +-9865, +-2920, +-9852, +-2926, +-9838, +-2932, +-9825, +-2938, +-9811, +-2943, +-9798, +-2949, +-9785, +-2955, +-9771, +-2961, +-9758, +-2967, +-9745, +-2972, +-9731, +-2978, +-9718, +-2984, +-9705, +-2990, +-9691, +-2996, +-9678, +-3002, +-9665, +-3008, +-9652, +-3013, +-9638, +-3019, +-9625, +-3025, +-9612, +-3031, +-9599, +-3037, +-9586, +-3043, +-9572, +-3049, +-9559, +-3055, +-9546, +-3061, +-9533, +-3067, +-9520, +-3073, +-9507, +-3079, +-9494, +-3085, +-9481, +-3091, +-9468, +-3097, +-9454, +-3103, +-9441, +-3109, +-9428, +-3115, +-9415, +-3121, +-9402, +-3127, +-9389, +-3133, +-9376, +-3139, +-9363, +-3145, +-9350, +-3151, +-9337, +-3157, +-9325, +-3163, +-9312, +-3169, +-9299, +-3175, +-9286, +-3182, +-9273, +-3188, +-9260, +-3194, +-9247, +-3200, +-9234, +-3206, +-9221, +-3212, +-9209, +-3218, +-9196, +-3225, +-9183, +-3231, +-9170, +-3237, +-9157, +-3243, +-9145, +-3249, +-9132, +-3256, +-9119, +-3262, +-9106, +-3268, +-9094, +-3274, +-9081, +-3281, +-9068, +-3287, +-9055, +-3293, +-9043, +-3299, +-9030, +-3306, +-9017, +-3312, +-9005, +-3318, +-8992, +-3325, +-8980, +-3331, +-8967, +-3337, +-8954, +-3344, +-8942, +-3350, +-8929, +-3356, +-8917, +-3363, +-8904, +-3369, +-8891, +-3376, +-8879, +-3382, +-8866, +-3388, +-8854, +-3395, +-8841, +-3401, +-8829, +-3408, +-8816, +-3414, +-8804, +-3421, +-8792, +-3427, +-8779, +-3433, +-8767, +-3440, +-8754, +-3446, +-8742, +-3453, +-8729, +-3459, +-8717, +-3466, +-8705, +-3472, +-8692, +-3479, +-8680, +-3486, +-8668, +-3492, +-8655, +-3499, +-8643, +-3505, +-8631, +-3512, +-8619, +-3518, +-8606, +-3525, +-8594, +-3532, +-8582, +-3538, +-8569, +-3545, +-8557, +-3551, +-8545, +-3558, +-8533, +-3565, +-8521, +-3571, +-8508, +-3578, +-8496, +-3585, +-8484, +-3591, +-8472, +-3598, +-8460, +-3605, +-8448, +-3611, +-8436, +-3618, +-8424, +-3625, +-8411, +-3632, +-8399, +-3638, +-8387, +-3645, +-8375, +-3652, +-8363, +-3659, +-8351, +-3665, +-8339, +-3672, +-8327, +-3679, +-8315, +-3686, +-8303, +-3693, +-8291, +-3699, +-8279, +-3706, +-8267, +-3713, +-8255, +-3720, +-8243, +-3727, +-8232, +-3734, +-8220, +-3741, +-8208, +-3748, +-8196, +-3754, +-8184, +-3761, +-8172, +-3768, +-8160, +-3775, +-8148, +-3782, +-8137, +-3789, +-8125, +-3796, +-8113, +-3803, +-8101, +-3810, +-8090, +-3817, +-8078, +-3824, +-8066, +-3831, +-8054, +-3838, +-8043, +-3845, +-8031, +-3852, +-8019, +-3859, +-8007, +-3866, +-7996, +-3873, +-7984, +-3880, +-7972, +-3887, +-7961, +-3894, +-7949, +-3901, +-7937, +-3909, +-7926, +-3916, +-7914, +-3923, +-7903, +-3930, +-7891, +-3937, +-7880, +-3944, +-7868, +-3951, +-7856, +-3958, +-7845, +-3966, +-7833, +-3973, +-7822, +-3980, +-7810, +-3987, +-7799, +-3994, +-7787, +-4002, +-7776, +-4009, +-7764, +-4016, +-7753, +-4023, +-7742, +-4031, +-7730, +-4038, +-7719, +-4045, +-7707, +-4052, +-7696, +-4060, +-7685, +-4067, +-7673, +-4074, +-7662, +-4082, +-7651, +-4089, +-7639, +-4096, +-7628, +-4104, +-7617, +-4111, +-7605, +-4118, +-7594, +-4126, +-7583, +-4133, +-7571, +-4141, +-7560, +-4148, +-7549, +-4155, +-7538, +-4163, +-7527, +-4170, +-7515, +-4178, +-7504, +-4185, +-7493, +-4193, +-7482, +-4200, +-7471, +-4208, +-7459, +-4215, +-7448, +-4223, +-7437, +-4230, +-7426, +-4238, +-7415, +-4245, +-7404, +-4253, +-7393, +-4260, +-7382, +-4268, +-7371, +-4275, +-7360, +-4283, +-7349, +-4291, +-7338, +-4298, +-7327, +-4306, +-7316, +-4313, +-7305, +-4321, +-7294, +-4329, +-7283, +-4336, +-7272, +-4344, +-7261, +-4352, +-7250, +-4359, +-7239, +-4367, +-7228, +-4375, +-7217, +-4382, +-7206, +-4390, +-7195, +-4398, +-7184, +-4406, +-7174, +-4413, +-7163, +-4421, +-7152, +-4429, +-7141, +-4437, +-7130, +-4444, +-7119, +-4452, +-7109, +-4460, +-7098, +-4468, +-7087, +-4476, +-7076, +-4483, +-7066, +-4491, +-7055, +-4499, +-7044, +-4507, +-7033, +-4515, +-7023, +-4523, +-7012, +-4531, +-7001, +-4539, +-6991, +-4546, +-6980, +-4554, +-6969, +-4562, +-6959, +-4570, +-6948, +-4578, +-6938, +-4586, +-6927, +-4594, +-6916, +-4602, +-6906, +-4610, +-6895, +-4618, +-6885, +-4626, +-6874, +-4634, +-6864, +-4642, +-6853, +-4650, +-6842, +-4658, +-6832, +-4666, +-6821, +-4674, +-6811, +-4682, +-6801, +-4690, +-6790, +-4699, +-6780, +-4707, +-6769, +-4715, +-6759, +-4723, +-6748, +-4731, +-6738, +-4739, +-6728, +-4747, +-6717, +-4756, +-6707, +-4764, +-6696, +-4772, +-6686, +-4780, +-6676, +-4788, +-6665, +-4796, +-6655, +-4805, +-6645, +-4813, +-6635, +-4821, +-6624, +-4829, +-6614, +-4838, +-6604, +-4846, +-6593, +-4854, +-6583, +-4863, +-6573, +-4871, +-6563, +-4879, +-6553, +-4887, +-6542, +-4896, +-6532, +-4904, +-6522, +-4912, +-6512, +-4921, +-6502, +-4929, +-6492, +-4938, +-6481, +-4946, +-6471, +-4954, +-6461, +-4963, +-6451, +-4971, +-6441, +-4980, +-6431, +-4988, +-6421, +-4997, +-6411, +-5005, +-6401, +-5013, +-6391, +-5022, +-6381, +-5030, +-6371, +-5039, +-6361, +-5047, +-6351, +-5056, +-6341, +-5064, +-6331, +-5073, +-6321, +-5082, +-6311, +-5090, +-6301, +-5099, +-6291, +-5107, +-6281, +-5116, +-6271, +-5124, +-6261, +-5133, +-6251, +-5142, +-6241, +-5150, +-6232, +-5159, +-6222, +-5168, +-6212, +-5176, +-6202, +-5185, +-6192, +-5194, +-6182, +-5202, +-6173, +-5211, +-6163, +-5220, +-6153, +-5229, +-6143, +-5237, +-6134, +-5246, +-6124, +-5255, +-6114, +-5264, +-6104, +-5272, +-6095, +-5281, +-6085, +-5290, +-6075, +-5299, +-6066, +-5307, +-6056, +-5316, +-6046, +-5325, +-6037, +-5334, +-6027, +-5343, +-6017, +-5352, +-6008, +-5361, +-5998, +-5369, +-5989, +-5378, +-5979, +-5387, +-5969, +-5396, +-5960, +-5405, +-5950, +-5414, +-5941, +-5423, +-5931, +-5432, +-5922, +-5441, +-5912, +-5450, +-5903, +-5459, +-5893, +-5468, +-5884, +-5477, +-5874, +-5486, +-5865, +-5495, +-5855, +-5504, +-5846, +-5513, +-5836, +-5522, +-5827, +-5531, +-5818, +-5540, +-5808, +-5549, +-5799, +-5558, +-5789, +-5568, +-5780, +-5577, +-5771, +-5586, +-5761, +-5595, +-5752, +-5604, +-5743, +-5613, +-5733, +-5622, +-5724, +-5632, +-5715, +-5641, +-5706, +-5650, +-5696, +-5659, +-5687, +-5669, +-5678, +-5678, +-5669, +-5687, +-5659, +-5696, +-5650, +-5706, +-5641, +-5715, +-5632, +-5724, +-5622, +-5733, +-5613, +-5743, +-5604, +-5752, +-5595, +-5761, +-5586, +-5771, +-5577, +-5780, +-5568, +-5789, +-5558, +-5799, +-5549, +-5808, +-5540, +-5818, +-5531, +-5827, +-5522, +-5836, +-5513, +-5846, +-5504, +-5855, +-5495, +-5865, +-5486, +-5874, +-5477, +-5884, +-5468, +-5893, +-5459, +-5903, +-5450, +-5912, +-5441, +-5922, +-5432, +-5931, +-5423, +-5941, +-5414, +-5950, +-5405, +-5960, +-5396, +-5969, +-5387, +-5979, +-5378, +-5989, +-5369, +-5998, +-5361, +-6008, +-5352, +-6017, +-5343, +-6027, +-5334, +-6037, +-5325, +-6046, +-5316, +-6056, +-5307, +-6066, +-5299, +-6075, +-5290, +-6085, +-5281, +-6095, +-5272, +-6104, +-5264, +-6114, +-5255, +-6124, +-5246, +-6134, +-5237, +-6143, +-5229, +-6153, +-5220, +-6163, +-5211, +-6173, +-5202, +-6182, +-5194, +-6192, +-5185, +-6202, +-5176, +-6212, +-5168, +-6222, +-5159, +-6232, +-5150, +-6241, +-5142, +-6251, +-5133, +-6261, +-5124, +-6271, +-5116, +-6281, +-5107, +-6291, +-5099, +-6301, +-5090, +-6311, +-5082, +-6321, +-5073, +-6331, +-5064, +-6341, +-5056, +-6351, +-5047, +-6361, +-5039, +-6371, +-5030, +-6381, +-5022, +-6391, +-5013, +-6401, +-5005, +-6411, +-4997, +-6421, +-4988, +-6431, +-4980, +-6441, +-4971, +-6451, +-4963, +-6461, +-4954, +-6471, +-4946, +-6481, +-4938, +-6492, +-4929, +-6502, +-4921, +-6512, +-4912, +-6522, +-4904, +-6532, +-4896, +-6542, +-4887, +-6553, +-4879, +-6563, +-4871, +-6573, +-4863, +-6583, +-4854, +-6593, +-4846, +-6604, +-4838, +-6614, +-4829, +-6624, +-4821, +-6635, +-4813, +-6645, +-4805, +-6655, +-4796, +-6665, +-4788, +-6676, +-4780, +-6686, +-4772, +-6696, +-4764, +-6707, +-4756, +-6717, +-4747, +-6728, +-4739, +-6738, +-4731, +-6748, +-4723, +-6759, +-4715, +-6769, +-4707, +-6780, +-4699, +-6790, +-4690, +-6801, +-4682, +-6811, +-4674, +-6821, +-4666, +-6832, +-4658, +-6842, +-4650, +-6853, +-4642, +-6864, +-4634, +-6874, +-4626, +-6885, +-4618, +-6895, +-4610, +-6906, +-4602, +-6916, +-4594, +-6927, +-4586, +-6938, +-4578, +-6948, +-4570, +-6959, +-4562, +-6969, +-4554, +-6980, +-4546, +-6991, +-4539, +-7001, +-4531, +-7012, +-4523, +-7023, +-4515, +-7033, +-4507, +-7044, +-4499, +-7055, +-4491, +-7066, +-4483, +-7076, +-4476, +-7087, +-4468, +-7098, +-4460, +-7109, +-4452, +-7119, +-4444, +-7130, +-4437, +-7141, +-4429, +-7152, +-4421, +-7163, +-4413, +-7174, +-4406, +-7184, +-4398, +-7195, +-4390, +-7206, +-4382, +-7217, +-4375, +-7228, +-4367, +-7239, +-4359, +-7250, +-4352, +-7261, +-4344, +-7272, +-4336, +-7283, +-4329, +-7294, +-4321, +-7305, +-4313, +-7316, +-4306, +-7327, +-4298, +-7338, +-4291, +-7349, +-4283, +-7360, +-4275, +-7371, +-4268, +-7382, +-4260, +-7393, +-4253, +-7404, +-4245, +-7415, +-4238, +-7426, +-4230, +-7437, +-4223, +-7448, +-4215, +-7459, +-4208, +-7471, +-4200, +-7482, +-4193, +-7493, +-4185, +-7504, +-4178, +-7515, +-4170, +-7527, +-4163, +-7538, +-4155, +-7549, +-4148, +-7560, +-4141, +-7571, +-4133, +-7583, +-4126, +-7594, +-4118, +-7605, +-4111, +-7617, +-4104, +-7628, +-4096, +-7639, +-4089, +-7651, +-4082, +-7662, +-4074, +-7673, +-4067, +-7685, +-4060, +-7696, +-4052, +-7707, +-4045, +-7719, +-4038, +-7730, +-4031, +-7742, +-4023, +-7753, +-4016, +-7764, +-4009, +-7776, +-4002, +-7787, +-3994, +-7799, +-3987, +-7810, +-3980, +-7822, +-3973, +-7833, +-3966, +-7845, +-3958, +-7856, +-3951, +-7868, +-3944, +-7880, +-3937, +-7891, +-3930, +-7903, +-3923, +-7914, +-3916, +-7926, +-3909, +-7937, +-3901, +-7949, +-3894, +-7961, +-3887, +-7972, +-3880, +-7984, +-3873, +-7996, +-3866, +-8007, +-3859, +-8019, +-3852, +-8031, +-3845, +-8043, +-3838, +-8054, +-3831, +-8066, +-3824, +-8078, +-3817, +-8090, +-3810, +-8101, +-3803, +-8113, +-3796, +-8125, +-3789, +-8137, +-3782, +-8148, +-3775, +-8160, +-3768, +-8172, +-3761, +-8184, +-3754, +-8196, +-3748, +-8208, +-3741, +-8220, +-3734, +-8232, +-3727, +-8243, +-3720, +-8255, +-3713, +-8267, +-3706, +-8279, +-3699, +-8291, +-3693, +-8303, +-3686, +-8315, +-3679, +-8327, +-3672, +-8339, +-3665, +-8351, +-3659, +-8363, +-3652, +-8375, +-3645, +-8387, +-3638, +-8399, +-3632, +-8411, +-3625, +-8424, +-3618, +-8436, +-3611, +-8448, +-3605, +-8460, +-3598, +-8472, +-3591, +-8484, +-3585, +-8496, +-3578, +-8508, +-3571, +-8521, +-3565, +-8533, +-3558, +-8545, +-3551, +-8557, +-3545, +-8569, +-3538, +-8582, +-3532, +-8594, +-3525, +-8606, +-3518, +-8619, +-3512, +-8631, +-3505, +-8643, +-3499, +-8655, +-3492, +-8668, +-3486, +-8680, +-3479, +-8692, +-3472, +-8705, +-3466, +-8717, +-3459, +-8729, +-3453, +-8742, +-3446, +-8754, +-3440, +-8767, +-3433, +-8779, +-3427, +-8792, +-3421, +-8804, +-3414, +-8816, +-3408, +-8829, +-3401, +-8841, +-3395, +-8854, +-3388, +-8866, +-3382, +-8879, +-3376, +-8891, +-3369, +-8904, +-3363, +-8917, +-3356, +-8929, +-3350, +-8942, +-3344, +-8954, +-3337, +-8967, +-3331, +-8980, +-3325, +-8992, +-3318, +-9005, +-3312, +-9017, +-3306, +-9030, +-3299, +-9043, +-3293, +-9055, +-3287, +-9068, +-3281, +-9081, +-3274, +-9094, +-3268, +-9106, +-3262, +-9119, +-3256, +-9132, +-3249, +-9145, +-3243, +-9157, +-3237, +-9170, +-3231, +-9183, +-3225, +-9196, +-3218, +-9209, +-3212, +-9221, +-3206, +-9234, +-3200, +-9247, +-3194, +-9260, +-3188, +-9273, +-3182, +-9286, +-3175, +-9299, +-3169, +-9312, +-3163, +-9325, +-3157, +-9337, +-3151, +-9350, +-3145, +-9363, +-3139, +-9376, +-3133, +-9389, +-3127, +-9402, +-3121, +-9415, +-3115, +-9428, +-3109, +-9441, +-3103, +-9454, +-3097, +-9468, +-3091, +-9481, +-3085, +-9494, +-3079, +-9507, +-3073, +-9520, +-3067, +-9533, +-3061, +-9546, +-3055, +-9559, +-3049, +-9572, +-3043, +-9586, +-3037, +-9599, +-3031, +-9612, +-3025, +-9625, +-3019, +-9638, +-3013, +-9652, +-3008, +-9665, +-3002, +-9678, +-2996, +-9691, +-2990, +-9705, +-2984, +-9718, +-2978, +-9731, +-2972, +-9745, +-2967, +-9758, +-2961, +-9771, +-2955, +-9785, +-2949, +-9798, +-2943, +-9811, +-2938, +-9825, +-2932, +-9838, +-2926, +-9852, +-2920, +-9865, +-2915, +-9878, +-2909, +-9892, +-2903, +-9905, +-2897, +-9919, +-2892, +-9932, +-2886, +-9946, +-2880, +-9959, +-2875, +-9973, +-2869, +-9986, +-2863, +-10000, +-2857, +-10013, +-2852, +-10027, +-2846, +-10041, +-2841, +-10054, +-2835, +-10068, +-2829, +-10081, +-2824, +-10095, +-2818, +-10109, +-2812, +-10122, +-2807, +-10136, +-2801, +-10150, +-2796, +-10163, +-2790, +-10177, +-2785, +-10191, +-2779, +-10205, +-2773, +-10218, +-2768, +-10232, +-2762, +-10246, +-2757, +-10260, +-2751, +-10273, +-2746, +-10287, +-2740, +-10301, +-2735, +-10315, +-2729, +-10329, +-2724, +-10342, +-2719, +-10356, +-2713, +-10370, +-2708, +-10384, +-2702, +-10398, +-2697, +-10412, +-2691, +-10426, +-2686, +-10440, +-2680, +-10454, +-2675, +-10468, +-2670, +-10482, +-2664, +-10496, +-2659, +-10510, +-2654, +-10524, +-2648, +-10538, +-2643, +-10552, +-2638, +-10566, +-2632, +-10580, +-2627, +-10594, +-2622, +-10608, +-2616, +-10622, +-2611, +-10636, +-2606, +-10650, +-2600, +-10664, +-2595, +-10678, +-2590, +-10693, +-2585, +-10707, +-2579, +-10721, +-2574, +-10735, +-2569, +-10749, +-2564, +-10764, +-2558, +-10778, +-2553, +-10792, +-2548, +-10806, +-2543, +-10821, +-2538, +-10835, +-2532, +-10849, +-2527, +-10863, +-2522, +-10878, +-2517, +-10892, +-2512, +-10906, +-2507, +-10921, +-2501, +-10935, +-2496, +-10949, +-2491, +-10964, +-2486, +-10978, +-2481, +-10993, +-2476, +-11007, +-2471, +-11022, +-2466, +-11036, +-2461, +-11050, +-2456, +-11065, +-2451, +-11079, +-2445, +-11094, +-2440, +-11108, +-2435, +-11123, +-2430, +-11137, +-2425, +-11152, +-2420, +-11167, +-2415, +-11181, +-2410, +-11196, +-2405, +-11210, +-2400, +-11225, +-2395, +-11240, +-2390, +-11254, +-2385, +-11269, +-2381, +-11283, +-2376, +-11298, +-2371, +-11313, +-2366, +-11328, +-2361, +-11342, +-2356, +-11357, +-2351, +-11372, +-2346, +-11386, +-2341, +-11401, +-2336, +-11416, +-2331, +-11431, +-2327, +-11446, +-2322, +-11460, +-2317, +-11475, +-2312, +-11490, +-2307, +-11505, +-2302, +-11520, +-2298, +-11535, +-2293, +-11549, +-2288, +-11564, +-2283, +-11579, +-2278, +-11594, +-2274, +-11609, +-2269, +-11624, +-2264, +-11639, +-2259, +-11654, +-2254, +-11669, +-2250, +-11684, +-2245, +-11699, +-2240, +-11714, +-2236, +-11729, +-2231, +-11744, +-2226, +-11759, +-2221, +-11774, +-2217, +-11789, +-2212, +-11804, +-2207, +-11819, +-2203, +-11835, +-2198, +-11850, +-2193, +-11865, +-2189, +-11880, +-2184, +-11895, +-2179, +-11910, +-2175, +-11926, +-2170, +-11941, +-2166, +-11956, +-2161, +-11971, +-2156, +-11986, +-2152, +-12002, +-2147, +-12017, +-2143, +-12032, +-2138, +-12048, +-2133, +-12063, +-2129, +-12078, +-2124, +-12094, +-2120, +-12109, +-2115, +-12124, +-2111, +-12140, +-2106, +-12155, +-2102, +-12170, +-2097, +-12186, +-2093, +-12201, +-2088, +-12217, +-2084, +-12232, +-2079, +-12248, +-2075, +-12263, +-2070, +-12279, +-2066, +-12294, +-2062, +-12310, +-2057, +-12325, +-2053, +-12341, +-2048, +-12356, +-2044, +-12372, +-2039, +-12387, +-2035, +-12403, +-2031, +-12418, +-2026, +-12434, +-2022, +-12450, +-2017, +-12465, +-2013, +-12481, +-2009, +-12497, +-2004, +-12512, +-2000, +-12528, +-1996, +-12544, +-1991, +-12559, +-1987, +-12575, +-1983, +-12591, +-1978, +-12607, +-1974, +-12622, +-1970, +-12638, +-1966, +-12654, +-1961, +-12670, +-1957, +-12686, +-1953, +-12701, +-1948, +-12717, +-1944, +-12733, +-1940, +-12749, +-1936, +-12765, +-1931, +-12781, +-1927, +-12797, +-1923, +-12813, +-1919, +-12828, +-1915, +-12844, +-1910, +-12860, +-1906, +-12876, +-1902, +-12892, +-1898, +-12908, +-1894, +-12924, +-1890, +-12940, +-1885, +-12956, +-1881, +-12972, +-1877, +-12988, +-1873, +-13005, +-1869, +-13021, +-1865, +-13037, +-1861, +-13053, +-1857, +-13069, +-1852, +-13085, +-1848, +-13101, +-1844, +-13117, +-1840, +-13134, +-1836, +-13150, +-1832, +-13166, +-1828, +-13182, +-1824, +-13198, +-1820, +-13215, +-1816, +-13231, +-1812, +-13247, +-1808, +-13263, +-1804, +-13280, +-1800, +-13296, +-1796, +-13312, +-1792, +-13329, +-1788, +-13345, +-1784, +-13361, +-1780, +-13378, +-1776, +-13394, +-1772, +-13410, +-1768, +-13427, +-1764, +-13443, +-1760, +-13460, +-1756, +-13476, +-1752, +-13493, +-1748, +-13509, +-1744, +-13525, +-1740, +-13542, +-1736, +-13558, +-1733, +-13575, +-1729, +-13592, +-1725, +-13608, +-1721, +-13625, +-1717, +-13641, +-1713, +-13658, +-1709, +-13674, +-1706, +-13691, +-1702, +-13708, +-1698, +-13724, +-1694, +-13741, +-1690, +-13758, +-1686, +-13774, +-1683, +-13791, +-1679, +-13808, +-1675, +-13824, +-1671, +-13841, +-1667, +-13858, +-1664, +-13875, +-1660, +-13891, +-1656, +-13908, +-1652, +-13925, +-1649, +-13942, +-1645, +-13958, +-1641, +-13975, +-1637, +-13992, +-1634, +-14009, +-1630, +-14026, +-1626, +-14043, +-1622, +-14060, +-1619, +-14077, +-1615, +-14093, +-1611, +-14110, +-1608, +-14127, +-1604, +-14144, +-1600, +-14161, +-1597, +-14178, +-1593, +-14195, +-1589, +-14212, +-1586, +-14229, +-1582, +-14246, +-1579, +-14263, +-1575, +-14280, +-1571, +-14297, +-1568, +-14315, +-1564, +-14332, +-1560, +-14349, +-1557, +-14366, +-1553, +-14383, +-1550, +-14400, +-1546, +-14417, +-1543, +-14435, +-1539, +-14452, +-1535, +-14469, +-1532, +-14486, +-1528, +-14503, +-1525, +-14521, +-1521, +-14538, +-1518, +-14555, +-1514, +-14572, +-1511, +-14590, +-1507, +-14607, +-1504, +-14624, +-1500, +-14642, +-1497, +-14659, +-1493, +-14676, +-1490, +-14694, +-1486, +-14711, +-1483, +-14729, +-1479, +-14746, +-1476, +-14763, +-1473, +-14781, +-1469, +-14798, +-1466, +-14816, +-1462, +-14833, +-1459, +-14851, +-1455, +-14868, +-1452, +-14886, +-1449, +-14903, +-1445, +-14921, +-1442, +-14938, +-1439, +-14956, +-1435, +-14973, +-1432, +-14991, +-1428, +-15009, +-1425, +-15026, +-1422, +-15044, +-1418, +-15062, +-1415, +-15079, +-1412, +-15097, +-1408, +-15115, +-1405, +-15132, +-1402, +-15150, +-1398, +-15168, +-1395, +-15186, +-1392, +-15203, +-1389, +-15221, +-1385, +-15239, +-1382, +-15257, +-1379, +-15274, +-1376, +-15292, +-1372, +-15310, +-1369, +-15328, +-1366, +-15346, +-1363, +-15364, +-1359, +-15382, +-1356, +-15399, +-1353, +-15417, +-1350, +-15435, +-1346, +-15453, +-1343, +-15471, +-1340, +-15489, +-1337, +-15507, +-1334, +-15525, +-1330, +-15543, +-1327, +-15561, +-1324, +-15579, +-1321, +-15597, +-1318, +-15615, +-1315, +-15633, +-1311, +-15651, +-1308, +-15669, +-1305, +-15688, +-1302, +-15706, +-1299, +-15724, +-1296, +-15742, +-1293, +-15760, +-1290, +-15778, +-1287, +-15796, +-1283, +-15815, +-1280, +-15833, +-1277, +-15851, +-1274, +-15869, +-1271, +-15888, +-1268, +-15906, +-1265, +-15924, +-1262, +-15942, +-1259, +-15961, +-1256, +-15979, +-1253, +-15997, +-1250, +-16016, +-1247, +-16034, +-1244, +-16053, +-1241, +-16071, +-1238, +-16089, +-1235, +-16108, +-1232, +-16126, +-1229, +-16145, +-1226, +-16163, +-1223, +-16182, +-1220, +-16200, +-1217, +-16218, +-1214, +-16237, +-1211, +-16256, +-1208, +-16274, +-1205, +-16293, +-1202, +-16311, +-1199, +-16330, +-1196, +-16348, +-1193, +-16367, +-1190, +-16386, +-1188, +-16404, +-1185, +-16423, +-1182, +-16441, +-1179, +-16460, +-1176, +-16479, +-1173, +-16497, +-1170, +-16516, +-1167, +-16535, +-1164, +-16554, +-1162, +-16572, +-1159, +-16591, +-1156, +-16610, +-1153, +-16629, +-1150, +-16647, +-1147, +-16666, +-1145, +-16685, +-1142, +-16704, +-1139, +-16723, +-1136, +-16742, +-1133, +-16761, +-1130, +-16779, +-1128, +-16798, +-1125, +-16817, +-1122, +-16836, +-1119, +-16855, +-1117, +-16874, +-1114, +-16893, +-1111, +-16912, +-1108, +-16931, +-1105, +-16950, +-1103, +-16969, +-1100, +-16988, +-1097, +-17007, +-1095, +-17026, +-1092, +-17045, +-1089, +-17064, +-1086, +-17084, +-1084, +-17103, +-1081, +-17122, +-1078, +-17141, +-1076, +-17160, +-1073, +-17179, +-1070, +-17198, +-1068, +-17218, +-1065, +-17237, +-1062, +-17256, +-1060, +-17275, +-1057, +-17295, +-1054, +-17314, +-1052, +-17333, +-1049, +-17352, +-1046, +-17372, +-1044, +-17391, +-1041, +-17410, +-1038, +-17430, +-1036, +-17449, +-1033, +-17469, +-1031, +-17488, +-1028, +-17507, +-1025, +-17527, +-1023, +-17546, +-1020, +-17566, +-1018, +-17585, +-1015, +-17605, +-1013, +-17624, +-1010, +-17643, +-1007, +-17663, +-1005, +-17683, +-1002, +-17702, +-1000, +-17722, +-997, +-17741, +-995, +-17761, +-992, +-17780, +-990, +-17800, +-987, +-17820, +-985, +-17839, +-982, +-17859, +-980, +-17879, +-977, +-17898, +-975, +-17918, +-972, +-17938, +-970, +-17957, +-967, +-17977, +-965, +-17997, +-962, +-18016, +-960, +-18036, +-957, +-18056, +-955, +-18076, +-952, +-18096, +-950, +-18115, +-948, +-18135, +-945, +-18155, +-943, +-18175, +-940, +-18195, +-938, +-18215, +-935, +-18235, +-933, +-18255, +-931, +-18275, +-928, +-18294, +-926, +-18314, +-923, +-18334, +-921, +-18354, +-919, +-18374, +-916, +-18394, +-914, +-18414, +-912, +-18434, +-909, +-18454, +-907, +-18475, +-905, +-18495, +-902, +-18515, +-900, +-18535, +-897, +-18555, +-895, +-18575, +-893, +-18595, +-891, +-18615, +-888, +-18636, +-886, +-18656, +-884, +-18676, +-881, +-18696, +-879, +-18716, +-877, +-18737, +-874, +-18757, +-872, +-18777, +-870, +-18797, +-868, +-18818, +-865, +-18838, +-863, +-18858, +-861, +-18879, +-859, +-18899, +-856, +-18919, +-854, +-18940, +-852, +-18960, +-850, +-18981, +-847, +-19001, +-845, +-19021, +-843, +-19042, +-841, +-19062, +-838, +-19083, +-836, +-19103, +-834, +-19124, +-832, +-19144, +-830, +-19165, +-827, +-19185, +-825, +-19206, +-823, +-19226, +-821, +-19247, +-819, +-19268, +-817, +-19288, +-814, +-19309, +-812, +-19330, +-810, +-19350, +-808, +-19371, +-806, +-19392, +-804, +-19412, +-802, +-19433, +-799, +-19454, +-797, +-19474, +-795, +-19495, +-793, +-19516, +-791, +-19537, +-789, +-19557, +-787, +-19578, +-785, +-19599, +-783, +-19620, +-781, +-19641, +-778, +-19662, +-776, +-19682, +-774, +-19703, +-772, +-19724, +-770, +-19745, +-768, +-19766, +-766, +-19787, +-764, +-19808, +-762, +-19829, +-760, +-19850, +-758, +-19871, +-756, +-19892, +-754, +-19913, +-752, +-19934, +-750, +-19955, +-748, +-19976, +-746, +-19997, +-744, +-20018, +-742, +-20039, +-740, +-20060, +-738, +-20082, +-736, +-20103, +-734, +-20124, +-732, +-20145, +-730, +-20166, +-728, +-20187, +-726, +-20209, +-724, +-20230, +-722, +-20251, +-720, +-20272, +-718, +-20294, +-716, +-20315, +-714, +-20336, +-712, +-20357, +-710, +-20379, +-708, +-20400, +-706, +-20421, +-704, +-20443, +-703, +-20464, +-701, +-20486, +-699, +-20507, +-697, +-20528, +-695, +-20550, +-693, +-20571, +-691, +-20593, +-689, +-20614, +-687, +-20636, +-685, +-20657, +-684, +-20679, +-682, +-20700, +-680, +-20722, +-678, +-20743, +-676, +-20765, +-674, +-20787, +-672, +-20808, +-671, +-20830, +-669, +-20851, +-667, +-20873, +-665, +-20895, +-663, +-20916, +-661, +-20938, +-660, +-20960, +-658, +-20981, +-656, +-21003, +-654, +-21025, +-652, +-21047, +-650, +-21068, +-649, +-21090, +-647, +-21112, +-645, +-21134, +-643, +-21156, +-642, +-21177, +-640, +-21199, +-638, +-21221, +-636, +-21243, +-634, +-21265, +-633, +-21287, +-631, +-21309, +-629, +-21331, +-627, +-21353, +-626, +-21375, +-624, +-21396, +-622, +-21418, +-620, +-21440, +-619, +-21462, +-617, +-21485, +-615, +-21507, +-614, +-21529, +-612, +-21551, +-610, +-21573, +-608, +-21595, +-607, +-21617, +-605, +-21639, +-603, +-21661, +-602, +-21683, +-600, +-21706, +-598, +-21728, +-597, +-21750, +-595, +-21772, +-593, +-21794, +-592, +-21817, +-590, +-21839, +-588, +-21861, +-587, +-21883, +-585, +-21906, +-583, +-21928, +-582, +-21950, +-580, +-21973, +-578, +-21995, +-577, +-22017, +-575, +-22040, +-573, +-22062, +-572, +-22084, +-570, +-22107, +-569, +-22129, +-567, +-22152, +-565, +-22174, +-564, +-22197, +-562, +-22219, +-561, +-22242, +-559, +-22264, +-557, +-22287, +-556, +-22309, +-554, +-22332, +-553, +-22354, +-551, +-22377, +-549, +-22400, +-548, +-22422, +-546, +-22445, +-545, +-22467, +-543, +-22490, +-542, +-22513, +-540, +-22535, +-539, +-22558, +-537, +-22581, +-536, +-22604, +-534, +-22626, +-532, +-22649, +-531, +-22672, +-529, +-22695, +-528, +-22717, +-526, +-22740, +-525, +-22763, +-523, +-22786, +-522, +-22809, +-520, +-22832, +-519, +-22854, +-517, +-22877, +-516, +-22900, +-514, +-22923, +-513, +-22946, +-511, +-22969, +-510, +-22992, +-508, +-23015, +-507, +-23038, +-505, +-23061, +-504, +-23084, +-503, +-23107, +-501, +-23130, +-500, +-23153, +-498, +-23176, +-497, +-23199, +-495, +-23222, +-494, +-23245, +-492, +-23269, +-491, +-23292, +-490, +-23315, +-488, +-23338, +-487, +-23361, +-485, +-23384, +-484, +-23408, +-482, +-23431, +-481, +-23454, +-480, +-23477, +-478, +-23501, +-477, +-23524, +-475, +-23547, +-474, +-23571, +-473, +-23594, +-471, +-23617, +-470, +-23641, +-469, +-23664, +-467, +-23687, +-466, +-23711, +-464, +-23734, +-463, +-23758, +-462, +-23781, +-460, +-23804, +-459, +-23828, +-458, +-23851, +-456, +-23875, +-455, +-23898, +-454, +-23922, +-452, +-23945, +-451, +-23969, +-450, +-23993, +-448, +-24016, +-447, +-24040, +-446, +-24063, +-444, +-24087, +-443, +-24111, +-442, +-24134, +-440, +-24158, +-439, +-24182, +-438, +-24205, +-436, +-24229, +-435, +-24253, +-434, +-24276, +-433, +-24300, +-431, +-24324, +-430, +-24348, +-429, +-24372, +-427, +-24395, +-426, +-24419, +-425, +-24443, +-424, +-24467, +-422, +-24491, +-421, +-24515, +-420, +-24538, +-419, +-24562, +-417, +-24586, +-416, +-24610, +-415, +-24634, +-414, +-24658, +-412, +-24682, +-411, +-24706, +-410, +-24730, +-409, +-24754, +-407, +-24778, +-406, +-24802, +-405, +-24826, +-404, +-24850, +-402, +-24874, +-401, +-24898, +-400, +-24923, +-399, +-24947, +-398, +-24971, +-396, +-24995, +-395, +-25019, +-394, +-25043, +-393, +-25068, +-392, +-25092, +-390, +-25116, +-389, +-25140, +-388, +-25165, +-387, +-25189, +-386, +-25213, +-385, +-25237, +-383, +-25262, +-382, +-25286, +-381, +-25310, +-380, +-25335, +-379, +-25359, +-378, +-25383, +-376, +-25408, +-375, +-25432, +-374, +-25457, +-373, +-25481, +-372, +-25506, +-371, +-25530, +-370, +-25555, +-369, +-25579, +-367, +-25604, +-366, +-25628, +-365, +-25653, +-364, +-25677, +-363, +-25702, +-362, +-25726, +-361, +-25751, +-360, +-25776, +-358, +-25800, +-357, +-25825, +-356, +-25849, +-355, +-25874, +-354, +-25899, +-353, +-25924, +-352, +-25948, +-351, +-25973, +-350, +-25998, +-349, +-26022, +-348, +-26047, +-347, +-26072, +-345, +-26097, +-344, +-26122, +-343, +-26146, +-342, +-26171, +-341, +-26196, +-340, +-26221, +-339, +-26246, +-338, +-26271, +-337, +-26296, +-336, +-26321, +-335, +-26346, +-334, +-26370, +-333, +-26395, +-332, +-26420, +-331, +-26445, +-330, +-26470, +-329, +-26495, +-328, +-26520, +-327, +-26546, +-326, +-26571, +-325, +-26596, +-324, +-26621, +-323, +-26646, +-322, +-26671, +-321, +-26696, +-320, +-26721, +-319, +-26746, +-318, +-26772, +-317, +-26797, +-316, +-26822, +-315, +-26847, +-314, +-26873, +-313, +-26898, +-312, +-26923, +-311, +-26948, +-310, +-26974, +-309, +-26999, +-308, +-27024, +-307, +-27050, +-306, +-27075, +-305, +-27100, +-304, +-27126, +-303, +-27151, +-302, +-27176, +-301, +-27202, +-300, +-27227, +-299, +-27253, +-298, +-27278, +-297, +-27304, +-296, +-27329, +-295, +-27355, +-294, +-27380, +-293, +-27406, +-292, +-27431, +-292, +-27457, +-291, +-27483, +-290, +-27508, +-289, +-27534, +-288, +-27559, +-287, +-27585, +-286, +-27611, +-285, +-27636, +-284, +-27662, +-283, +-27688, +-282, +-27713, +-281, +-27739, +-281, +-27765, +-280, +-27791, +-279, +-27816, +-278, +-27842, +-277, +-27868, +-276, +-27894, +-275, +-27920, +-274, +-27945, +-273, +-27971, +-273, +-27997, +-272, +-28023, +-271, +-28049, +-270, +-28075, +-269, +-28101, +-268, +-28127, +-267, +-28153, +-267, +-28179, +-266, +-28205, +-265, +-28231, +-264, +-28257, +-263, +-28283, +-262, +-28309, +-261, +-28335, +-261, +-28361, +-260, +-28387, +-259, +-28413, +-258, +-28439, +-257, +-28465, +-256, +-28491, +-256, +-28518, +-255, +-28544, +-254, +-28570, +-253, +-28596, +-252, +-28622, +-251, +-28649, +-251, +-28675, +-250, +-28701, +-249, +-28727, +-248, +-28754, +-247, +-28780, +-247, +-28806, +-246, +-28832, +-245, +-28859, +-244, +-28885, +-243, +-28912, +-243, +-28938, +-242, +-28964, +-241, +-28991, +-240, +-29017, +-239, +-29044, +-239, +-29070, +-238, +-29097, +-237, +-29123, +-236, +-29150, +-235, +-29176, +-235, +-29203, +-234, +-29229, +-233, +-29256, +-232, +-29282, +-232, +-29309, +-231, +-29335, +-230, +-29362, +-229, +-29389, +-229, +-29415, +-228, +-29442, +-227, +-29469, +-226, +-29495, +-226, +-29522, +-225, +-29549, +-224, +-29576, +-223, +-29602, +-223, +-29629, +-222, +-29656, +-221, +-29683, +-220, +-29709, +-220, +-29736, +-219, +-29763, +-218, +-29790, +-217, +-29817, +-217, +-29844, +-216, +-29871, +-215, +-29897, +-215, +-29924, +-214, +-29951, +-213, +-29978, +-212, +-30005, +-212, +-30032, +-211, +-30059, +-210, +-30086, +-210, +-30113, +-209, +-30140, +-208, +-30167, +-208, +-30194, +-207, +-30221, +-206, +-30249, +-205, +-30276, +-205, +-30303, +-204, +-30330, +-203, +-30357, +-203, +-30384, +-202, +-30411, +-201, +-30439, +-201, +-30466, +-200, +-30493, +-199, +-30520, +-199, +-30547, +-198, +-30575, +-197, +-30602, +-197, +-30629, +-196, +-30657, +-195, +-30684, +-195, +-30711, +-194, +-30739, +-193, +-30766, +-193, +-30793, +-192, +-30821, +-191, +-30848, +-191, +-30876, +-190, +-30903, +-189, +-30931, +-189, +-30958, +-188, +-30985, +-188, +-31013, +-187, +-31040, +-186, +-31068, +-186, +-31096, +-185, +-31123, +-184, +-31151, +-184, +-31178, +-183, +-31206, +-182, +-31233, +-182, +-31261, +-181, +-31289, +-181, +-31316, +-180, +-31344, +-179, +-31372, +-179, +-31399, +-178, +-31427, +-178, +-31455, +-177, +-31483, +-176, +-31510, +-176, +-31538, +-175, +-31566, +-175, +-31594, +-174, +-31622, +-173, +-31649, +-173, +-31677, +-172, +-31705, +-172, +-31733, +-171, +-31761, +-170, +-31789, +-170, +-31817, +-169, +-31845, +-169, +-31873, +-168, +-31901, +-167, +-31929, +-167, +-31957, +-166, +-31985, +-166, +-32013, +-165, +-32041, +-165, +-32069, +-164, +-32097, +-163, +-32125, +-163, +-32153, +-162, +-32181, +-162, +-32209, +-161, +-32237, +-161, +-32265, +-160, +-32294, +-159, +-32322, +-159, +-32350, +-158, +-32378, +-158, +-32406, +-157, +-32435, +-157, +-32463, +-156, +-32491, +-156, +-32519, +-155, +-32548, +-155, +-32576, +-154, +-32604, +-153, +-32633, +-153, +-32661, +-152, +-32689, +-152, +-32718, +-151, +-32746, +-151, +-32775, +-150, +-32803, +-150, +-32832, +-149, +-32860, +-149, +-32888, +-148, +-32917, +-148, +-32945, +-147, +-32974, +-147, +-33003, +-146, +-33031, +-146, +-33060, +-145, +-33088, +-145, +-33117, +-144, +-33145, +-144, +-33174, +-143, +-33203, +-143, +-33231, +-142, +-33260, +-142, +-33289, +-141, +-33317, +-141, +-33346, +-140, +-33375, +-140, +-33404, +-139, +-33432, +-139, +-33461, +-138, +-33490, +-138, +-33519, +-137, +-33547, +-137, +-33576, +-136, +-33605, +-136, +-33634, +-135, +-33663, +-135, +-33692, +-134, +-33721, +-134, +-33750, +-133, +-33778, +-133, +-33807, +-132, +-33836, +-132, +-33865, +-131, +-33894, +-131, +-33923, +-130, +-33952, +-130, +-33981, +-129, +-34010, +-129, +-34039, +-129, +-34069, +-128, +-34098, +-128, +-34127, +-127, +-34156, +-127, +-34185, +-126, +-34214, +-126, +-34243, +-125, +-34272, +-125, +-34302, +-124, +-34331, +-124, +-34360, +-124, +-34389, +-123, +-34419, +-123, +-34448, +-122, +-34477, +-122, +-34506, +-121, +-34536, +-121, +-34565, +-120, +-34594, +-120, +-34624, +-120, +-34653, +-119, +-34682, +-119, +-34712, +-118, +-34741, +-118, +-34771, +-117, +-34800, +-117, +-34830, +-117, +-34859, +-116, +-34889, +-116, +-34918, +-115, +-34948, +-115, +-34977, +-114, +-35007, +-114, +-35036, +-114, +-35066, +-113, +-35095, +-113, +-35125, +-112, +-35155, +-112, +-35184, +-112, +-35214, +-111, +-35243, +-111, +-35273, +-110, +-35303, +-110, +-35333, +-110, +-35362, +-109, +-35392, +-109, +-35422, +-108, +-35452, +-108, +-35481, +-108, +-35511, +-107, +-35541, +-107, +-35571, +-106, +-35601, +-106, +-35630, +-106, +-35660, +-105, +-35690, +-105, +-35720, +-104, +-35750, +-104, +-35780, +-104, +-35810, +-103, +-35840, +-103, +-35870, +-103, +-35900, +-102, +-35930, +-102, +-35960, +-101, +-35990, +-101, +-36020, +-101, +-36050, +-100, +-36080, +-100, +-36110, +-100, +-36140, +-99, +-36170, +-99, +-36200, +-98, +-36231, +-98, +-36261, +-98, +-36291, +-97, +-36321, +-97, +-36351, +-97, +-36381, +-96, +-36412, +-96, +-36442, +-96, +-36472, +-95, +-36503, +-95, +-36533, +-94, +-36563, +-94, +-36593, +-94, +-36624, +-93, +-36654, +-93, +-36684, +-93, +-36715, +-92, +-36745, +-92, +-36776, +-92, +-36806, +-91, +-36837, +-91, +-36867, +-91, +-36897, +-90, +-36928, +-90, +-36958, +-90, +-36989, +-89, +-37020, +-89, +-37050, +-89, +-37081, +-88, +-37111, +-88, +-37142, +-88, +-37172, +-87, +-37203, +-87, +-37234, +-87, +-37264, +-86, +-37295, +-86, +-37326, +-86, +-37356, +-85, +-37387, +-85, +-37418, +-85, +-37448, +-84, +-37479, +-84, +-37510, +-84, +-37541, +-83, +-37572, +-83, +-37602, +-83, +-37633, +-82, +-37664, +-82, +-37695, +-82, +-37726, +-82, +-37757, +-81, +-37788, +-81, +-37818, +-81, +-37849, +-80, +-37880, +-80, +-37911, +-80, +-37942, +-79, +-37973, +-79, +-38004, +-79, +-38035, +-78, +-38066, +-78, +-38097, +-78, +-38128, +-78, +-38160, +-77, +-38191, +-77, +-38222, +-77, +-38253, +-76, +-38284, +-76, +-38315, +-76, +-38346, +-75, +-38377, +-75, +-38409, +-75, +-38440, +-75, +-38471, +-74, +-38502, +-74, +-38534, +-74, +-38565, +-73, +-38596, +-73, +-38627, +-73, +-38659, +-73, +-38690, +-72, +-38721, +-72, +-38753, +-72, +-38784, +-72, +-38816, +-71, +-38847, +-71, +-38878, +-71, +-38910, +-70, +-38941, +-70, +-38973, +-70, +-39004, +-70, +-39036, +-69, +-39067, +-69, +-39099, +-69, +-39130, +-69, +-39162, +-68, +-39193, +-68, +-39225, +-68, +-39257, +-67, +-39288, +-67, +-39320, +-67, +-39351, +-67, +-39383, +-66, +-39415, +-66, +-39446, +-66, +-39478, +-66, +-39510, +-65, +-39542, +-65, +-39573, +-65, +-39605, +-65, +-39637, +-64, +-39669, +-64, +-39700, +-64, +-39732, +-64, +-39764, +-63, +-39796, +-63, +-39828, +-63, +-39860, +-63, +-39892, +-62, +-39924, +-62, +-39955, +-62, +-39987, +-62, +-40019, +-61, +-40051, +-61, +-40083, +-61, +-40115, +-61, +-40147, +-60, +-40179, +-60, +-40211, +-60, +-40243, +-60, +-40276, +-59, +-40308, +-59, +-40340, +-59, +-40372, +-59, +-40404, +-59, +-40436, +-58, +-40468, +-58, +-40500, +-58, +-40533, +-58, +-40565, +-57, +-40597, +-57, +-40629, +-57, +-40662, +-57, +-40694, +-56, +-40726, +-56, +-40758, +-56, +-40791, +-56, +-40823, +-56, +-40855, +-55, +-40888, +-55, +-40920, +-55, +-40952, +-55, +-40985, +-54, +-41017, +-54, +-41050, +-54, +-41082, +-54, +-41115, +-54, +-41147, +-53, +-41180, +-53, +-41212, +-53, +-41245, +-53, +-41277, +-53, +-41310, +-52, +-41342, +-52, +-41375, +-52, +-41407, +-52, +-41440, +-52, +-41473, +-51, +-41505, +-51, +-41538, +-51, +-41571, +-51, +-41603, +-50, +-41636, +-50, +-41669, +-50, +-41701, +-50, +-41734, +-50, +-41767, +-49, +-41800, +-49, +-41832, +-49, +-41865, +-49, +-41898, +-49, +-41931, +-48, +-41964, +-48, +-41997, +-48, +-42030, +-48, +-42062, +-48, +-42095, +-47, +-42128, +-47, +-42161, +-47, +-42194, +-47, +-42227, +-47, +-42260, +-47, +-42293, +-46, +-42326, +-46, +-42359, +-46, +-42392, +-46, +-42425, +-46, +-42458, +-45, +-42491, +-45, +-42524, +-45, +-42558, +-45, +-42591, +-45, +-42624, +-44, +-42657, +-44, +-42690, +-44, +-42723, +-44, +-42757, +-44, +-42790, +-44, +-42823, +-43, +-42856, +-43, +-42890, +-43, +-42923, +-43, +-42956, +-43, +-42989, +-43, +-43023, +-42, +-43056, +-42, +-43089, +-42, +-43123, +-42, +-43156, +-42, +-43190, +-41, +-43223, +-41, +-43256, +-41, +-43290, +-41, +-43323, +-41, +-43357, +-41, +-43390, +-40, +-43424, +-40, +-43457, +-40, +-43491, +-40, +-43524, +-40, +-43558, +-40, +-43592, +-39, +-43625, +-39, +-43659, +-39, +-43692, +-39, +-43726, +-39, +-43760, +-39, +-43793, +-38, +-43827, +-38, +-43861, +-38, +-43895, +-38, +-43928, +-38, +-43962, +-38, +-43996, +-38, +-44030, +-37, +-44063, +-37, +-44097, +-37, +-44131, +-37, +-44165, +-37, +-44199, +-37, +-44233, +-36, +-44266, +-36, +-44300, +-36, +-44334, +-36, +-44368, +-36, +-44402, +-36, +-44436, +-36, +-44470, +-35, +-44504, +-35, +-44538, +-35, +-44572, +-35, +-44606, +-35, +-44640, +-35, +-44674, +-35, +-44708, +-34, +-44742, +-34, +-44776, +-34, +-44811, +-34, +-44845, +-34, +-44879, +-34, +-44913, +-33, +-44947, +-33, +-44981, +-33, +-45016, +-33, +-45050, +-33, +-45084, +-33, +-45118, +-33, +-45153, +-33, +-45187, +-32, +-45221, +-32, +-45255, +-32, +-45290, +-32, +-45324, +-32, +-45358, +-32, +-45393, +-32, +-45427, +-31, +-45462, +-31, +-45496, +-31, +-45531, +-31, +-45565, +-31, +-45599, +-31, +-45634, +-31, +-45668, +-30, +-45703, +-30, +-45737, +-30, +-45772, +-30, +-45807, +-30, +-45841, +-30, +-45876, +-30, +-45910, +-30, +-45945, +-29, +-45980, +-29, +-46014, +-29, +-46049, +-29, +-46084, +-29, +-46118, +-29, +-46153, +-29, +-46188, +-29, +-46222, +-28, +-46257, +-28, +-46292, +-28, +-46327, +-28, +-46361, +-28, +-46396, +-28, +-46431, +-28, +-46466, +-28, +-46501, +-27, +-46536, +-27, +-46571, +-27, +-46606, +-27, +-46640, +-27, +-46675, +-27, +-46710, +-27, +-46745, +-27, +-46780, +-27, +-46815, +-26, +-46850, +-26, +-46885, +-26, +-46920, +-26, +-46955, +-26, +-46990, +-26, +-47026, +-26, +-47061, +-26, +-47096, +-26, +-47131, +-25, +-47166, +-25, +-47201, +-25, +-47236, +-25, +-47272, +-25, +-47307, +-25, +-47342, +-25, +-47377, +-25, +-47412, +-25, +-47448, +-24, +-47483, +-24, +-47518, +-24, +-47554, +-24, +-47589, +-24, +-47624, +-24, +-47660, +-24, +-47695, +-24, +-47730, +-24, +-47766, +-23, +-47801, +-23, +-47837, +-23, +-47872, +-23, +-47907, +-23, +-47943, +-23, +-47978, +-23, +-48014, +-23, +-48049, +-23, +-48085, +-23, +-48121, +-22, +-48156, +-22, +-48192, +-22, +-48227, +-22, +-48263, +-22, +-48299, +-22, +-48334, +-22, +-48370, +-22, +-48406, +-22, +-48441, +-22, +-48477, +-21, +-48513, +-21, +-48548, +-21, +-48584, +-21, +-48620, +-21, +-48656, +-21, +-48691, +-21, +-48727, +-21, +-48763, +-21, +-48799, +-21, +-48835, +-21, +-48871, +-20, +-48907, +-20, +-48942, +-20, +-48978, +-20, +-49014, +-20, +-49050, +-20, +-49086, +-20, +-49122, +-20, +-49158, +-20, +-49194, +-20, +-49230, +-20, +-49266, +-19, +-49302, +-19, +-49338, +-19, +-49374, +-19, +-49410, +-19, +-49447, +-19, +-49483, +-19, +-49519, +-19, +-49555, +-19, +-49591, +-19, +-49627, +-19, +-49664, +-19, +-49700, +-18, +-49736, +-18, +-49772, +-18, +-49809, +-18, +-49845, +-18, +-49881, +-18, +-49917, +-18, +-49954, +-18, +-49990, +-18, +-50026, +-18, +-50063, +-18, +-50099, +-18, +-50136, +-17, +-50172, +-17, +-50208, +-17, +-50245, +-17, +-50281, +-17, +-50318, +-17, +-50354, +-17, +-50391, +-17, +-50427, +-17, +-50464, +-17, +-50500, +-17, +-50537, +-17, +-50574, +-17, +-50610, +-16, +-50647, +-16, +-50683, +-16, +-50720, +-16, +-50757, +-16, +-50793, +-16, +-50830, +-16, +-50867, +-16, +-50903, +-16, +-50940, +-16, +-50977, +-16, +-51014, +-16, +-51050, +-16, +-51087, +-15, +-51124, +-15, +-51161, +-15, +-51198, +-15, +-51235, +-15, +-51271, +-15, +-51308, +-15, +-51345, +-15, +-51382, +-15, +-51419, +-15, +-51456, +-15, +-51493, +-15, +-51530, +-15, +-51567, +-15, +-51604, +-14, +-51641, +-14, +-51678, +-14, +-51715, +-14, +-51752, +-14, +-51789, +-14, +-51826, +-14, +-51863, +-14, +-51900, +-14, +-51938, +-14, +-51975, +-14, +-52012, +-14, +-52049, +-14, +-52086, +-14, +-52124, +-14, +-52161, +-14, +-52198, +-13, +-52235, +-13, +-52273, +-13, +-52310, +-13, +-52347, +-13, +-52384, +-13, +-52422, +-13, +-52459, +-13, +-52497, +-13, +-52534, +-13, +-52571, +-13, +-52609, +-13, +-52646, +-13, +-52684, +-13, +-52721, +-13, +-52759, +-13, +-52796, +-12, +-52834, +-12, +-52871, +-12, +-52909, +-12, +-52946, +-12, +-52984, +-12, +-53021, +-12, +-53059, +-12, +-53097, +-12, +-53134, +-12, +-53172, +-12, +-53209, +-12, +-53247, +-12, +-53285, +-12, +-53323, +-12, +-53360, +-12, +-53398, +-12, +-53436, +-11, +-53473, +-11, +-53511, +-11, +-53549, +-11, +-53587, +-11, +-53625, +-11, +-53663, +-11, +-53700, +-11, +-53738, +-11, +-53776, +-11, +-53814, +-11, +-53852, +-11, +-53890, +-11, +-53928, +-11, +-53966, +-11, +-54004, +-11, +-54042, +-11, +-54080, +-11, +-54118, +-11, +-54156, +-10, +-54194, +-10, +-54232, +-10, +-54270, +-10, +-54308, +-10, +-54346, +-10, +-54384, +-10, +-54423, +-10, +-54461, +-10, +-54499, +-10, +-54537, +-10, +-54575, +-10, +-54613, +-10, +-54652, +-10, +-54690, +-10, +-54728, +-10, +-54767, +-10, +-54805, +-10, +-54843, +-10, +-54881, +-10, +-54920, +-10, +-54958, +-9, +-54997, +-9, +-55035, +-9, +-55073, +-9, +-55112, +-9, +-55150, +-9, +-55189, +-9, +-55227, +-9, +-55266, +-9, +-55304, +-9, +-55343, +-9, +-55381, +-9, +-55420, +-9, +-55458, +-9, +-55497, +-9, +-55535, +-9, +-55574, +-9, +-55613, +-9, +-55651, +-9, +-55690, +-9, +-55729, +-9, +-55767, +-9, +-55806, +-8, +-55845, +-8, +-55883, +-8, +-55922, +-8, +-55961, +-8, +-56000, +-8, +-56038, +-8, +-56077, +-8, +-56116, +-8, +-56155, +-8, +-56194, +-8, +-56233, +-8, +-56271, +-8, +-56310, +-8, +-56349, +-8, +-56388, +-8, +-56427, +-8, +-56466, +-8, +-56505, +-8, +-56544, +-8, +-56583, +-8, +-56622, +-8, +-56661, +-8, +-56700, +-8, +-56739, +-8, +-56778, +-7, +-56817, +-7, +-56856, +-7, +-56896, +-7, +-56935, +-7, +-56974, +-7, +-57013, +-7, +-57052, +-7, +-57091, +-7, +-57131, +-7, +-57170, +-7, +-57209, +-7, +-57248, +-7, +-57288, +-7, +-57327, +-7, +-57366, +-7, +-57405, +-7, +-57445, +-7, +-57484, +-7, +-57524, +-7, +-57563, +-7, +-57602, +-7, +-57642, +-7, +-57681, +-7, +-57721, +-7, +-57760, +-7, +-57800, +-7, +-57839, +-7, +-57879, +-6, +-57918, +-6, +-57958, +-6, +-57997, +-6, +-58037, +-6, +-58076, +-6, +-58116, +-6, +-58155, +-6, +-58195, +-6, +-58235, +-6, +-58274, +-6, +-58314, +-6, +-58354, +-6, +-58393, +-6, +-58433, +-6, +-58473, +-6, +-58513, +-6, +-58552, +-6, +-58592, +-6, +-58632, +-6, +-58672, +-6, +-58712, +-6, +-58751, +-6, +-58791, +-6, +-58831, +-6, +-58871, +-6, +-58911, +-6, +-58951, +-6, +-58991, +-6, +-59031, +-6, +-59071, +-6, +-59111, +-5, +-59151, +-5, +-59191, +-5, +-59231, +-5, +-59271, +-5, +-59311, +-5, +-59351, +-5, +-59391, +-5, +-59431, +-5, +-59471, +-5, +-59511, +-5, +-59551, +-5, +-59592, +-5, +-59632, +-5, +-59672, +-5, +-59712, +-5, +-59752, +-5, +-59793, +-5, +-59833, +-5, +-59873, +-5, +-59913, +-5, +-59954, +-5, +-59994, +-5, +-60034, +-5, +-60075, +-5, +-60115, +-5, +-60156, +-5, +-60196, +-5, +-60236, +-5, +-60277, +-5, +-60317, +-5, +-60358, +-5, +-60398, +-5, +-60439, +-5, +-60479, +-5, +-60520, +-5, +-60560, +-5, +-60601, +-4, +-60641, +-4, +-60682, +-4, +-60722, +-4, +-60763, +-4, +-60804, +-4, +-60844, +-4, +-60885, +-4, +-60926, +-4, +-60966, +-4, +-61007, +-4, +-61048, +-4, +-61088, +-4, +-61129, +-4, +-61170, +-4, +-61211, +-4, +-61251, +-4, +-61292, +-4, +-61333, +-4, +-61374, +-4, +-61415, +-4, +-61456, +-4, +-61497, +-4, +-61537, +-4, +-61578, +-4, +-61619, +-4, +-61660, +-4, +-61701, +-4, +-61742, +-4, +-61783, +-4, +-61824, +-4, +-61865, +-4, +-61906, +-4, +-61947, +-4, +-61988, +-4, +-62029, +-4, +-62071, +-4, +-62112, +-4, +-62153, +-4, +-62194, +-4, +-62235, +-4, +-62276, +-4, +-62317, +-4, +-62359, +-4, +-62400, +-4, +-62441, +-3, +-62482, +-3, +-62524, +-3, +-62565, +-3, +-62606, +-3, +-62647, +-3, +-62689, +-3, +-62730, +-3, +-62772, +-3, +-62813, +-3, +-62854, +-3, +-62896, +-3, +-62937, +-3, +-62979, +-3, +-63020, +-3, +-63061, +-3, +-63103, +-3, +-63144, +-3, +-63186, +-3, +-63227, +-3, +-63269, +-3, +-63311, +-3, +-63352, +-3, +-63394, +-3, +-63435, +-3, +-63477, +-3, +-63519, +-3, +-63560, +-3, +-63602, +-3, +-63644, +-3, +-63685, +-3, +-63727, +-3, +-63769, +-3, +-63810, +-3, +-63852, +-3, +-63894, +-3, +-63936, +-3, +-63978, +-3, +-64019, +-3, +-64061, +-3, +-64103, +-3, +-64145, +-3, +-64187, +-3, +-64229, +-3, +-64271, +-3, +-64313, +-3, +-64355, +-3, +-64397, +-3, +-64438, +-3, +-64480, +-3, +-64522, +-3, +-64565, +-3, +-64607, +-3, +-64649, +-3, +-64691, +-3, +-64733, +-3, +-64775, +-2, +-64817, +-2, +-64859, +-2, +-64901, +-2, +-64943, +-2, +-64986, +-2, +-65028, +-2, +-65070, +-2, +-65112, +-2, +-65154, +-2, +-65197, +-2, +-65239, +-2, +-65281, +-2, +-65324, +-2, +-65366, +-2, +-65408, +-2, +-65450, +-2, +-65493, +-2, +-65535, +-2, +-65578, +-2, +-65620, +-2, +-65662, +-2, +-65705, +-2, +-65747, +-2, +-65790, +-2, +-65832, +-2, +-65875, +-2, +-65917, +-2, +-65960, +-2, +-66002, +-2, +-66045, +-2, +-66088, +-2, +-66130, +-2, +-66173, +-2, +-66215, +-2, +-66258, +-2, +-66301, +-2, +-66343, +-2, +-66386, +-2, +-66429, +-2, +-66471, +-2, +-66514, +-2, +-66557, +-2, +-66600, +-2, +-66642, +-2, +-66685, +-2, +-66728, +-2, +-66771, +-2, +-66814, +-2, +-66856, +-2, +-66899, +-2, +-66942, +-2, +-66985, +-2, +-67028, +-2, +-67071, +-2, +-67114, +-2, +-67157, +-2, +-67200, +-2, +-67243, +-2, +-67286, +-2, +-67329, +-2, +-67372, +-2, +-67415, +-2, +-67458, +-2, +-67501, +-2, +-67544, +-2, +-67587, +-2, +-67630, +-2, +-67674, +-2, +-67717, +-2, +-67760, +-2, +-67803, +-2, +-67846, +-2, +-67890, +-2, +-67933, +-2, +-67976, +-2, +-68019, +-2, +-68063, +-2, +-68106, +-1, +-68149, +-1, +-68193, +-1, +-68236, +-1, +-68279, +-1, +-68323, +-1, +-68366, +-1, +-68409, +-1, +-68453, +-1, +-68496, +-1, +-68540, +-1, +-68583, +-1, +-68627, +-1, +-68670, +-1, +-68714, +-1, +-68757, +-1, +-68801, +-1, +-68844, +-1, +-68888, +-1, +-68932, +-1, +-68975, +-1, +-69019, +-1, +-69062, +-1, +-69106, +-1, +-69150, +-1, +-69193, +-1, +-69237, +-1, +-69281, +-1, +-69325, +-1, +-69368, +-1, +-69412, +-1, +-69456, +-1, +-69500, +-1, +-69544, +-1, +-69587, +-1, +-69631, +-1, +-69675, +-1, +-69719, +-1, +-69763, +-1, +-69807, +-1, +-69851, +-1, +-69895, +-1, +-69939, +-1, +-69982, +-1, +-70026, +-1, +-70070, +-1, +-70114, +-1, +-70159, +-1, +-70203, +-1, +-70247, +-1, +-70291, +-1, +-70335, +-1, +-70379, +-1, +-70423, +-1, +-70467, +-1, +-70511, +-1, +-70555, +-1, +-70600, +-1, +-70644, +-1, +-70688, +-1, +-70732, +-1, +-70776, +-1, +-70821, +-1, +-70865, +-1, +-70909, +-1, +-70954, +-1, +-70998, +-1, +-71042, +-1, +-71087, +-1, +-71131, +-1, +-71175, +-1, +-71220, +-1, +-71264, +-1, +-71309, +-1, +-71353, +-1, +-71398, +-1, +-71442, +-1, +-71487, +-1, +-71531, +-1, +-71576, +-1, +-71620, +-1, +-71665, +-1, +-71709, +-1, +-71754, +-1, +-71798, +-1, +-71843, +-1, +-71888, +-1, +-71932, +-1, +-71977, +-1, +-72022, +-1, +-72066, +-1, +-72111, +-1, +-72156, +-1, +-72200, +-1, +-72245, +-1, +-72290, +-1, +-72335, +-1, +-72380, +-1, +-72424, +-1, +-72469, +-1, +-72514, +-1, +-72559, +-1, +-72604, +-1, +-72649, +-1, +-72694, +-1, +-72739, +-1, +-72783, +-1, +-72828, +-1, +-72873, +-1, +-72918, +-1, +-72963, +-1, +-73008, +-1, +-73053, +-1, +-73099, +-1, +-73144, +-1, +-73189, +-1, +-73234, +-1, +-73279, +-1, +-73324, +-1, +-73369, +-1, +-73414, +-1, +-73459, +-1, +-73505, +-1, +-73550, +-1, +-73595, +-1, +-73640, +-1, +-73686, +-1, +-73731, +-1, +-73776, +0, +-73821, +0, +-73867, +0, +-73912, +0, +-73957, +0, +-74003, +0, +-74048, +0, +-74094, +0, +-74139, +0, +-74184, +0, +-74230, +0, +-74275, +0, +-74321, +0, +-74366, +0, +-74412, +0, +-74457, +0, +-74503, +0, +-74548, +0, +-74594, +0, +-74639, +0, +-74685, +0, +-74731, +0, +-74776, +0, +-74822, +0, +-74868, +0, +-74913, +0, +-74959, +0, +-75005, +0, +-75050, +0, +-75096, +0, +-75142, +0, +-75188, +0, +-75233, +0, +-75279, +0, +-75325, +0, +-75371, +0, +-75417, +0, +-75462, +0, +-75508, +0, +-75554, +0, +-75600, +0, +-75646, +0, +-75692, +0, +-75738, +0, +-75784, +0, +-75830, +0, +-75876, +0, +-75922, +0, +-75968, +0, +-76014, +0, +-76060, +0, +-76106, +0, +-76152, +0, +-76198, +0, +-76244, +0, +-76291, +0, +-76337, +0, +-76383, +0, +-76429, +0, +-76475, +0, +-76521, +0, +-76568, +0, +-76614, +0, +-76660, +0, +-76706, +0, +-76753, +0, +-76799, +0, +-76845, +0, +-76892, +0, +-76938, +0, +-76984, +0, +-77031, +0, +-77077, +0, +-77124, +0, +-77170, +0, +-77217, +0, +-77263, +0, +-77309, +0, +-77356, +0, +-77402, +0, +-77449, +0, +-77496, +0, +-77542, +0, +-77589, +0, +-77635, +0, +-77682, +0, +-77728, +0, +-77775, +0, +-77822, +0, +-77868, +0, +-77915, +0, +-77962, +0, +-78008, +0, +-78055, +0, +-78102, +0, +-78149, +0, +-78195, +0, +-78242, +0, +-78289, +0, +-78336, +0, +-78383, +0, +-78430, +0, +-78476, +0, +-78523, +0, +-78570, +0, +-78617, +0, +-78664, +0, +-78711, +0, +-78758, +0, +-78805, +0, +-78852, +0, +-78899, +0, +-78946, +0, +-78993, +0, +-79040, +0, +-79087, +0, +-79134, +0, +-79181, +0, +-79228, +0, +-79276, +0, +-79323, +0, +-79370, +0, +-79417, +0, +-79464, +0, +-79511, +0, +-79559, +0, +-79606, +0, +-79653, +0, +-79700, +0, +-79748, +0, +-79795, +0, +-79842, +0, +-79890, +0, +-79937, +0, +-79984, +0, +-80032, +0, +-80079, +0, +-80127, +0, +-80174, +0, +-80221, +0, +-80269, +0, +-80316, +0, +-80364, +0, +-80411, +0, +-80459, +0, +-80506, +0, +-80554, +0, +-80602, +0, +-80649, +0, +-80697, +0, +-80744, +0, +-80792, +0, +-80840, +0, +-80887, +0, +-80935, +0, +-80983, +0, +-81030, +0, +-81078, +0, +-81126, +0, +-81174, +0, +-81221, +0, +-81269, +0, +-81317, +0, +-81365, +0, +-81413, +0, +-81460, +0, +-81508, +0, +-81556, +0, +-81604, +0, +-81652, +0, +-81700, +0, +-81748, +0, +-81796, +0, +-81844, +0, +-81892, +0, +-81940, +0, +-81988, +0, +-82036, +0, +-82084, +0, +-82132, +0, +-82180, +0, +-82228, +0, +-82276, +0, +-82324, +0, +-82373, +0, +-82421, +0, +-82469, +0, +-82517, +0, +-82565, +0, +-82613, +0, +-82662, +0, +-82710, +0, +-82758, +0, +-82807, +0, +-82855, +0, +-82903, +0, +-82951, +0, +-83000, +0, +-83048, +0, +-83097, +0, +-83145, +0, +-83193, +0, +-83242, +0, +-83290, +0, +-83339, +0, +-83387, +0, +-83436, +0, +-83484, +0, +-83533, +0, +-83581, +0, +-83630, +0, +-83678, +0, +-83727, +0, +-83775, +0, +-83824, +0, +-83873, +0, +-83921, +0, +-83970, +0, +-84019, +0, +-84067, +0, +-84116, +0, +-84165, +0, +-84214, +0, +-84262, +0, +-84311, +0, +-84360, +0, +-84409, +0, +-84457, +0, +-84506, +0, +-84555, +0, +-84604, +0, +-84653, +0, +-84702, +0, +-84751, +0, +-84800, +0, +-84849, +0, +-84898, +0, +-84946, +0, +-84995, +0, +-85044, +0, +-85093, +0, +-85143, +0, +-85192, +0, +-85241, +0, +-85290, +0, +-85339, +0, +-85388, +0, +-85437, +0, +-85486, +0, +-85535, +0, +-85585, +0, +-85634, +0, +-85683, +0, +-85732, +0, +-85781, +0, +-85831, +0, +-85880, +0, +-85929, +0, +-85978, +0, +-86028, +0, +-86077, +0, +-86126, +0, +-86176, +0, +-86225, +0, +-86275, +0, +-86324, +0, +-86373, +0, +-86423, +0, +-86472, +0, +-86522, +0, +-86571, +0, +-86621, +0, +-86670, +0, +-86720, +0, +-86769, +0, +-86819, +0, +-86869, +0, +-86918, +0, +-86968, +0, +-87017, +0, +-87067, +0, +-87117, +0, +-87166, +0, +-87216, +0, +-87266, +0, +-87315, +0, +-87365, +0, +-87415, +0, +-87465, +0, +-87515, +0, +-87564, +0, +-87614, +0, +-87664, +0, +-87714, +0, +-87764, +0, +-87814, +0, +-87863, +0, +-87913, +0, +-87963, +0, +-88013, +0, +-88063, +0, +-88113, +0, +-88163, +0, +-88213, +0, +-88263, +0, +-88313, +0, +-88363, +0, +-88413, +0, +-88463, +0, +-88513, +0, +-88564, +0, +-88614, +0, +-88664, +0, +-88714, +0, +-88764, +0, +-88814, +0, +-88865, +0, +-88915, +0, +-88965, +0, +-89015, +0, +-89066, +0, +-89116, +0, +-89166, +0, +-89216, +0, +-89267, +0, +-89317, +0, +-89368, +0, +-89418, +0, +-89468, +0, +-89519, +0, +-89569, +0, +-89620, +0, +-89670, +0, +-89721, +0, +-89771, +0, +-89822, +0, +-89872, +0, +-89923, +0, +-89973, +0, +-90024, +0, +-90074, +0, +-90125, +0, +-90175, +0, +-90226, +0, +-90277, +0, +-90327, +0, +-90378, +0, +-90429, +0, +-90479, +0, +-90530, +0, +-90581, +0, +-90632, +0, +-90682, +0, +-90733, +0, +-90784, +0, +-90835, +0, +-90886, +0, +-90937, +0, +-90987, +0, +-91038, +0, +-91089, +0, +-91140, +0, +-91191, +0, +-91242, +0, +-91293, +0, +-91344, +0, +-91395, +0, +-91446, +0, +-91497, +0, +-91548, +0, +-91599, +0, +-91650, +0, +-91701, +0, +-91752, +0, +-91803, +0, +-91855, +0, +-91906, +0, +-91957, +0, +-92008, +0, +-92059, +0, +-92110, +0, +-92162, +0, +-92213, +0, +-92264, +0, +-92315, +0, +-92367, +0, +-92418, +0, +-92469, +0, +-92521, +0, +-92572, +0, +-92623, +0, +-92675, +0, +-92726, +0, +-92778, +0, +-92829, +0, +-92880, +0, +-92932, +0, +-92983, +0, +-93035, +0, +-93086, +0, +-93138, +0, +-93189, +0, +-93241, +0, +-93293, +0, +-93344, +0, +-93396, +0, +-93447, +0, +-93499, +0, +-93551, +0, +-93602, +0, +-93654, +0, +-93706, +0, +-93757, +0, +-93809, +0, +-93861, +0, +-93913, +0, +-93964, +0, +-94016, +0, +-94068, +0, +-94120, +0, +-94172, +0, +-94223, +0, +-94275, +0, +-94327, +0, +-94379, +0, +-94431, +0, +-94483, +0, +-94535, +0, +-94587, +0, +-94639, +0, +-94691, +0, +-94743, +0, +-94795, +0, +-94847, +0, +-94899, +0, +-94951, +0, +-95003, +0, +-95055, +0, +-95107, +0, +-95160, +0, +-95212, +0, +-95264, +0, +-95316, +0, +-95368, +0, +-95420, +0, +-95473, +0, +-95525, +0, +-95577, +0, +-95629, +0, +-95682, +0, +-95734, +0, +-95786, +0, +-95839, +0, +-95891, +0, +-95943, +0, +-95996, +0, +-96048, +0, +-96101, +0, +-96153, +0, +-96205, +0, +-96258, +0, +-96310, +0, +-96363, +0, +-96415, +0, +-96468, +0, +-96521, +0, +-96573, +0, +-96626, +0, +-96678, +0, +-96731, +0, +-96783, +0, +-96836, +0, +-96889, +0, +-96941, +0, +-96994, +0, +-97047, +0, +-97100, +0, +-97152, +0, +-97205, +0, +-97258, +0, +-97311, +0, +-97363, +0, +-97416, +0, +-97469, +0, +-97522, +0, +-97575, +0, +-97628, +0, +-97680, +0, +-97733, +0, +-97786, +0, +-97839, +0, +-97892, +0, +-97945, +0, +-97998, +0, +-98051, +0, +-98104, +0, +-98157, +0, +-98210, +0, +-98263, +0, +-98316, +0, +-98369, +0, +-98423, +0, +-98476, +0, +-98529, +0, +-98582, +0, +-98635, +0, +-98688, +0, +-98742, +0, +-98795, +0, +-98848, +0, +-98901, +0, +-98954, +0, +-99008, +0, +-99061, +0, +-99114, +0, +-99168, +0, +-99221, +0, +-99274, +0, +-99328, +0, +-99381, +0, +-99435, +0, +-99488, +0, +-99541, +0, +-99595, +0, +-99648, +0, +-99702, +0, +-99755, +0, +-99809, +0, +-99862, +0, +-99916, +0, +-99970, +0, +-100023, +0, +-100077, +0, +-100130, +0, +-100184, +0, +-100238, +0, +-100291, +0, +-100345, +0, +-100399, +0, +-100452, +0, +-100506, +0, +-100560, +0, +-100614, +0, +-100667, +0, +-100721, +0, +-100775, +0, +-100829, +0, +-100883, +0, +-100936, +0, +-100990, +0, +-101044, +0, +-101098, +0, +-101152, +0, +-101206, +0, +-101260, +0, +-101314, +0, +-101368, +0, +-101422, +0, +-101476, +0, +-101530, +0, +-101584, +0, +-101638, +0, +-101692, +0, +-101746, +0, +-101800, +0, +-101854, +0, +-101908, +0, +-101962, +0, +-102017, +0, +-102071, +0, +-102125, +0, +-102179, +0, +-102233, +0, +-102288, +0, +-102342, +0, +-102396, +0, +-102450, +0, +-102505, +0, +-102559, +0, +-102613, +0, +-102668, +0, +-102722, +0, +-102777, +0, +-102831, +0, +-102885, +0, +-102940, +0, +-102994, +0, +-103049, +0, +-103103, +0, +-103158, +0, +-103212, +0, +-103267, +0, +-103321, +0, +-103376, +0, +-103430, +0, +-103485, +0, +-103540, +0, +-103594, +0, +-103649, +0, +-103703, +0, +-103758, +0, +-103813, +0, +-103868, +0, +-103922, +0, +-103977, +0, +-104032, +0, +-104086, +0, +-104141, +0, +-104196, +0, +-104251, +0, +-104306, +0, +-104361, +0, +-104415, +0, +-104470, +0, +-104525, +0, +-104580, +0, +-104635, +0, +-104690, +0, +-104745, +0, +-104800, +0, +-104855, +0, +-104910, +0, +-104965, +0, +-105020, +0, +-105075, +0, +-105130, +0, +-105185, +0, +-105240, +0, +-105295, +0, +-105350, +0, +-105405, +0, +-105461, +0, +-105516, +0, +-105571, +0, +-105626, +0, +-105681, +0, +-105737, +0, +-105792, +0, +-105847, +0, +-105902, +0, +-105958, +0, +-106013, +0, +-106068, +0, +-106124, +0, +-106179, +0, +-106234, +0, +-106290, +0, +-106345, +0, +-106401, +0, +-106456, +0, +-106512, +0, +-106567, +0, +-106622, +0, +-106678, +0, +-106734, +0, +-106789, +0, +-106845, +0, +-106900, +0, +-106956, +0, +-107011, +0, +-107067, +0, +-107123, +0, +-107178, +0, +-107234, +0, +-107290, +0, +-107345, +0, +-107401, +0, +-107457, +0, +-107512, +0, +-107568, +0, +-107624, +0, +-107680, +0, +-107736, +0, +-107791, +0, +-107847, +0, +-107903, +0, +-107959, +0, +-108015, +0, +-108071, +0, +-108127, +0, +-108182, +0, +-108238, +0, +-108294, +0, +-108350, +0, +-108406, +0, +-108462, +0, +-108518, +0, +-108574, +0, +-108630, +0, +-108687, +0, +-108743, +0, +-108799, +0, +-108855, +0, +-108911, +0, +-108967, +0, +-109023, +0, +-109079, +0, +-109136, +0, +-109192, +0, +-109248, +0, +-109304, +0, +-109361, +0, +-109417, +0, +-109473, +0, +-109529, +0, +-109586, +0, +-109642, +0, +-109699, +0, +-109755, +0, +-109811, +0, +-109868, +0, +-109924, +0, +-109981, +0, +-110037, +0, +-110093, +0, +-110150, +0, +-110206, +0, +-110263, +0, +-110319, +0, +-110376, +0, +-110433, +0, +-110489, +0, +-110546, +0, +-110602, +0, +-110659, +0, +-110716, +0, +-110772, +0, +-110829, +0, +-110886, +0, +-110942, +0, +-110999, +0, +-111056, +0, +-111112, +0, +-111169, +0, +-111226, +0, +-111283, +0, +-111340, +0, +-111396, +0, +-111453, +0, +-111510, +0, +-111567, +0, +-111624, +0, +-111681, +0, +-111738, +0, +-111795, +0, +-111852, +0, +-111909, +0, +-111966, +0, +-112023, +0, +-112080, +0, +-112137, +0, +-112194, +0, +-112251, +0, +-112308, +0, +-112365, +0, +-112422, +0, +-112479, +0, +-112536, +0, +-112593, +0, +-112651, +0, +-112708, +0, +-112765, +0, +-112822, +0, +-112880, +0, +-112937, +0, +-112994, +0, +-113051, +0, +-113109, +0, +-113166, +0, +-113223, +0, +-113281, +0, +-113338, +0, +-113395, +0, +-113453, +0, +-113510, +0, +-113568, +0, +-113625, +0, +-113682, +0, +-113740, +0, +-113797, +0, +-113855, +0, +-113912, +0, +-113970, +0, +-114028, +0, +-114085, +0, +-114143, +0, +-114200, +0, +-114258, +0, +-114316, +0, +-114373, +0, +-114431, +0, +-114489, +0, +-114546, +0, +-114604, +0, +-114662, +0, +-114719, +0, +-114777, +0, +-114835, +0, +-114893, +0, +-114951, +0, +-115008, +0, +-115066, +0, +-115124, +0, +-115182, +0, +-115240, +0, +-115298, +0, +-115356, +0, +-115414, +0, +-115472, +0, +-115530, +0, +-115588, +0, +-115646, +0, +-115704, +0, +-115762, +0, +-115820, +0, +-115878, +0, +-115936, +0, +-115994, +0, +-116052, +0, +-116110, +0, +-116168, +0, +-116226, +0, +-116285, +0, +-116343, +0, +-116401, +0, +-116459, +0, +-116517, +0, +-116576, +0, +-116634, +0, +-116692, +0, +-116750, +0, +-116809, +0, +-116867, +0, +-116925, +0, +-116984, +0, +-117042, +0, +-117101, +0, +-117159, +0, +-117217, +0, +-117276, +0, +-117334, +0, +-117393, +0, +-117451, +0, +-117510, +0, +-117568, +0, +-117627, +0, +-117685, +0, +-117744, +0, +-117803, +0, +-117861, +0, +-117920, +0, +-117978, +0, +-118037, +0, +-118096, +0, +-118154, +0, +-118213, +0, +-118272, +0, +-118330, +0, +-118389, +0, +-118448, +0, +-118507, +0, +-118566, +0, +-118624, +0, +-118683, +0, +-118742, +0, +-118801, +0, +-118860, +0, +-118919, +0, +-118977, +0, +-119036, +0, +-119095, +0, +-119154, +0, +-119213, +0, +-119272, +0, +-119331, +0, +-119390, +0, +-119449, +0, +-119508, +0, +-119567, +0, +-119626, +0, +-119685, +0, +-119745, +0, +-119804, +0, +-119863, +0, +-119922, +0, +-119981, +0, +-120040, +0, +-120100, +0, +-120159, +0, +-120218, +0, +-120277, +0, +-120336, +0, +-120396, +0, +-120455, +0, +-120514, +0, +-120574, +0, +-120633, +0, +-120692, +0, +-120752, +0, +-120811, +0, +-120871, +0, +-120930, +0, +-120989, +0, +-121049, +0, +-121108, +0, +-121168, +0, +-121227, +0, +-121287, +0, +-121346, +0, +-121406, +0, +-121465, +0, +-121525, +0, +-121585, +0, +-121644, +0, +-121704, +0, +-121764, +0, +-121823, +0, +-121883, +0, +-121943, +0, +-122002, +0, +-122062, +0, +-122122, +0, +-122181, +0, +-122241, +0, +-122301, +0, +-122361, +0, +-122421, +0, +-122480, +0, +-122540, +0, +-122600, +0, +-122660, +0, +-122720, +0, +-122780, +0, +-122840, +0, +-122900, +0, +-122960, +0, +-123020, +0, +-123080, +0, +-123140, +0, +-123200, +0, +-123260, +0, +-123320, +0, +-123380, +0, +-123440, +0, +-123500, +0, +-123560, +0, +-123620, +0, +-123680, +0, +-123741, +0, +-123801, +0, +-123861, +0, +-123921, +0, +-123981, +0, +-124042, +0, +-124102, +0, +-124162, +0, +-124223, +0, +-124283, +0, +-124343, +0, +-124404, +0, +-124464, +0, +-124524, +0, +-124585, +0, +-124645, +0, +-124705, +0, +-124766, +0, +-124826, +0, +-124887, +0, +-124947, +0, +-125008, +0, +-125068, +0, +-125129, +0, +-125189, +0, +-125250, +0, +-125311, +0, +-125371, +0, +-125432, +0, +-125492, +0, +-125553, +0, +-125614, +0, +-125674, +0, +-125735, +0, +-125796, +0, +-125856, +0, +-125917, +0, +-125978, +0, +-126039, +0, +-126099, +0, +-126160, +0, +-126221, +0, +-126282, +0, +-126343, +0, +-126404, +0, +-126465, +0, +-126525, +0, +-126586, +0, +-126647, +0, +-126708, +0, +-126769, +0, +-126830, +0, +-126891, +0, +-126952, +0, +-127013, +0, +-127074, +0, +-127135, +0, +-127196, +0, +-127257, +0, +-127318, +0, +-127380, +0, +-127441, +0, +-127502, +0, +-127563, +0, +-127624, +0, +-127685, +0, +-127747, +0, +-127808, +0, +-127869, +0, +-127930, +0, +-127992, +0, +-128053, +0, +-128114, +0, +-128176, +0, +-128237, +0, +-128298, +0, +-128360, +0, +-128421, +0, +-128482, +0, +-128544, +0, +-128605, +0, +-128667, +0, +-128728, +0, +-128790, +0, +-128851, +0, +-128913, +0, +-128974, +0, +-129036, +0, +-129097, +0, +-129159, +0, +-129220, +0, +-129282, +0, +-129344, +0, +-129405, +0, +-129467, +0, +-129529, +0, +-129590, +0, +-129652, +0, +-129714, +0, +-129776, +0, +-129837, +0, +-129899, +0, +-129961, +0, +-130023, +0, +-130084, +0, +-130146, +0, +-130208, +0, +-130270, +0, +-130332, +0, +-130394, +0, +-130456, +0, +-130518, +0, +-130580, +0, +-130642, +0, +-130703, +0, +-130765, +0, +-130827, +0, +-130889, +0, +-130952, +0, +-131014, +0, +-131076, +0, +-131138, +0, +-131200, +0, +-131262, +0, +-131324, +0, +-131386, +0, +-131448, +0, +-131511, +0, +-131573, +0, +-131635, +0, +-131697, +0, +-131759, +0, +-131822, +0, +-131884, +0, +-131946, +0, +-132009, +0, +-132071, +0, +-132133, +0, +-132196, +0, +-132258, +0, +-132320, +0, +-132383, +0, +-132445, +0, +-132508, +0, +-132570, +0, +-132633, +0, +-132695, +0, +-132758, +0, +-132820, +0, +-132883, +0, +-132945, +0, +-133008, +0, +-133070, +0, +-133133, +0, +-133195, +0, +-133258, +0, +-133321, +0, +-133383, +0, +-133446, +0, +-133509, +0, +-133571, +0, +-133634, +0, +-133697, +0, +-133760, +0, +-133822, +0, +-133885, +0, +-133948, +0, +-134011, +0, +-134074, +0, +-134137, +0, +-134199, +0, +-134262, +0, +-134325, +0, +-134388, +0, +-134451, +0, +-134514, +0, +-134577, +0, +-134640, +0, +-134703, +0, +-134766, +0, +-134829, +0, +-134892, +0, +-134955, +0, +-135018, +0, +-135081, +0, +-135144, +0, +-135207, +0, +-135270, +0, +-135334, +0, +-135397, +0, +-135460, +0, +-135523, +0, +-135586, +0, +-135650, +0, +-135713, +0, +-135776, +0, +-135839, +0, +-135903, +0, +-135966, +0, +-136029, +0, +-136093, +0, +-136156, +0, +-136219, +0, +-136283, +0, +-136346, +0, +-136410, +0, +-136473, +0, +-136536, +0, +-136600, +0, +-136663, +0, +-136727, +0, +-136790, +0, +-136854, +0, +-136918, +0, +-136981, +0, +-137045, +0, +-137108, +0, +-137172, +0, +-137236, +0, +-137299, +0, +-137363, +0, +-137426, +0, +-137490, +0, +-137554, +0, +-137618, +0, +-137681, +0, +-137745, +0, +-137809, +0, +-137873, +0, +-137936, +0, +-138000, +0, +-138064, +0, +-138128, +0, +-138192, +0, +-138256, +0, +-138320, +0, +-138384, +0, +-138447, +0, +-138511, +0, +-138575, +0, +-138639, +0, +-138703, +0, +-138767, +0, +-138831, +0, +-138895, +0, +-138959, +0, +-139024, +0, +-139088, +0, +-139152, +0, +-139216, +0, +-139280, +0, +-139344, +0, +-139408, +0, +-139472, +0, +-139537, +0, +-139601, +0, +-139665, +0, +-139729, +0, +-139794, +0, +-139858, +0, +-139922, +0, +-139986, +0, +-140051, +0, +-140115, +0, +-140180, +0, +-140244, +0, +-140308, +0, +-140373, +0, +-140437, +0, +-140502, +0, +-140566, +0, +-140630, +0, +-140695, +0, +-140759, +0, +-140824, +0, +-140889, +0, +-140953, +0, +-141018, +0, +-141082, +0, +-141147, +0, +-141211, +0, +-141276, +0, +-141341, +0, +-141405, +0, +-141470, +0, +-141535, +0, +-141599, +0, +-141664, +0, +-141729, +0, +-141794, +0, +-141858, +0, +-141923, +0, +-141988, +0, +-142053, +0, +-142118, +0, +-142183, +0, +-142247, +0, +-142312, +0, +-142377, +0, +-142442, +0, +-142507, +0, +-142572, +0, +-142637, +0, +-142702, +0, +-142767, +0, +-142832, +0, +-142897, +0, +-142962, +0, +-143027, +0, +-143092, +0, +-143157, +0, +-143222, +0, +-143287, +0, +-143353, +0, +-143418, +0, +-143483, +0, +-143548, +0, +-143613, +0, +-143678, +0, +-143744, +0, +-143809, +0, +-143874, +0, +-143940, +0, +-144005, +0, +-144070, +0, +-144135, +0, +-144201, +0, +-144266, +0, +-144332, +0, +-144397, +0, +-144462, +0, +-144528, +0, +-144593, +0, +-144659, +0, +-144724, +0, +-144790, +0, +-144855, +0, +-144921, +0, +-144986, +0, +-145052, +0, +-145117, +0, +-145183, +0, +-145248, +0, +-145314, +0, +-145380, +0, +-145445, +0, +-145511, +0, +-145577, +0, +-145642, +0, +-145708, +0, +-145774, +0, +-145840, +0, +-145905, +0, +-145971, +0, +-146037, +0, +-146103, +0, +-146169, +0, +-146234, +0, +-146300, +0, +-146366, +0, +-146432, +0, +-146498, +0, +-146564, +0, +-146630, +0, +-146696, +0, +-146762, +0, +-146828, +0, +-146894, +0, +-146960, +0, +-147026, +0, +-147092, +0, +-147158, +0, +-147224, +0, +-147290, +0, +-147356, +0, +-147422, +0, +-147488, +0, +-147555, +0, +-147621, +0, +-147687, +0, +-147753, +0, +-147819, +0, +-147886, +0, +-147952, +0, +-148018, +0, +-148084, +0, +-148151, +0, +-148217, +0, +-148283, +0, +-148350, +0, +-148416, +0, +-148482, +0, +-148549, +0, +-148615, +0, +-148682, +0, +-148748, +0, +-148815, +0, +-148881, +0, +-148948, +0, +-149014, +0, +-149081, +0, +-149147, +0, +-149214, +0, +-149280, +0, +-149347, +0, +-149413, +0, +-149480, +0, +-149547, +0, +-149613, +0, +-149680, +0, +-149747, +0, +-149813, +0, +-149880, +0, +-149947, +0, +-150014, +0, +-150080, +0, +-150147, +0, +-150214, +0, +-150281, +0, +-150348, +0, +-150414, +0, +-150481, +0, +-150548, +0, +-150615, +0, +-150682, +0, +-150749, +0, +-150816, +0, +-150883, +0, +-150950, +0, +-151017, +0, +-151084, +0, +-151151, +0, +-151218, +0, +-151285, +0, +-151352, +0, +-151419, +0, +-151486, +0, +-151553, +0, +-151620, +0, +-151687, +0, +-151755, +0, +-151822, +0, +-151889, +0, +-151956, +0, +-152023, +0, +-152091, +0, +-152158, +0, +-152225, +0, +-152292, +0, +-152360, +0, +-152427, +0, +-152494, +0, +-152562, +0, +-152629, +0, +-152696, +0, +-152764, +0, +-152831, +0, +-152899, +0, +-152966, +0, +-153034, +0, +-153101, +0, +-153169, +0, +-153236, +0, +-153304, +0, +-153371, +0, +-153439, +0, +-153506, +0, +-153574, +0, +-153642, +0, +-153709, +0, +-153777, +0, +-153844, +0, +-153912, +0, +-153980, +0, +-154048, +0, +-154115, +0, +-154183, +0, +-154251, +0, +-154319, +0, +-154386, +0, +-154454, +0, +-154522, +0, +-154590, +0, +-154658, +0, +-154725, +0, +-154793, +0, +-154861, +0, +-154929, +0, +-154997, +0, +-155065, +0, +-155133, +0, +-155201, +0, +-155269, +0, +-155337, +0, +-155405, +0, +-155473, +0, +-155541, +0, +-155609, +0, +-155677, +0, +-155745, +0, +-155813, +0, +-155882, +0, +-155950, +0, +-156018, +0, +-156086, +0, +-156154, +0, +-156222, +0, +-156291, +0, +-156359, +0, +-156427, +0, +-156495, +0, +-156564, +0, +-156632, +0, +-156700, +0, +-156769, +0, +-156837, +0, +-156905, +0, +-156974, +0, +-157042, +0, +-157111, +0, +-157179, +0, +-157248, +0, +-157316, +0, +-157385, +0, +-157453, +0, +-157522, +0, +-157590, +0, +-157659, +0, +-157727, +0, +-157796, +0, +-157864, +0, +-157933, +0, +-158002, +0, +-158070, +0, +-158139, +0, +-158208, +0, +-158276, +0, +-158345, +0, +-158414, +0, +-158482, +0, +-158551, +0, +-158620, +0, +-158689, +0, +-158758, +0, +-158826, +0, +-158895, +0, +-158964, +0, +-159033, +0, +-159102, +0, +-159171, +0, +-159240, +0, +-159309, +0, +-159378, +0, +-159447, +0, +-159516, +0, +-159516 diff --git a/rce/rcecalib/dataproc/fit/logx_ext_int.dat b/rce/rcecalib/dataproc/fit/logx_ext_int.dat new file mode 100644 index 00000000..66719838 --- /dev/null +++ b/rce/rcecalib/dataproc/fit/logx_ext_int.dat @@ -0,0 +1,14002 @@ +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-13122363, +-2, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12716898, +-3, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12429216, +-4, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12206073, +-5, +-12023751, +-6, +-12023751, +-6, +-12023751, +-6, +-12023751, +-6, +-12023751, +-6, +-12023751, +-6, +-12023751, +-6, +-12023751, +-6, +-12023751, +-6, +-12023751, +-6, +-12023751, +-6, +-12023751, +-6, +-12023751, +-6, +-12023751, +-6, +-12023751, +-6, +-12023751, +-6, +-12023751, +-6, +-12023751, +-6, +-12023751, +-6, +-12023751, +-6, +-12023751, +-6, +-12023751, +-6, +-12023751, +-6, +-12023751, +-6, +-12023751, +-6, +-12023751, +-6, +-11869600, +-7, +-11869600, +-7, +-11869600, +-7, +-11869600, +-7, +-11869600, +-7, +-11869600, +-7, +-11869600, +-7, +-11869600, +-7, +-11869600, +-7, +-11869600, +-7, +-11869600, +-7, +-11869600, +-7, +-11869600, +-7, +-11869600, +-7, +-11869600, +-7, +-11869600, +-7, +-11869600, +-7, +-11869600, +-7, +-11869600, +-7, +-11869600, +-7, +-11869600, +-7, +-11869600, +-7, +-11736069, +-8, +-11736069, +-8, +-11736069, +-8, +-11736069, +-8, +-11736069, +-8, +-11736069, +-8, +-11736069, +-8, +-11736069, +-8, +-11736069, +-8, +-11736069, +-8, +-11736069, +-8, +-11736069, +-8, +-11736069, +-8, +-11736069, +-8, +-11736069, +-8, +-11736069, +-8, +-11736069, +-8, +-11736069, +-8, +-11736069, +-8, +-11618286, +-9, +-11618286, +-9, +-11618286, +-9, +-11618286, +-9, +-11618286, +-9, +-11618286, +-9, +-11618286, +-9, +-11618286, +-9, +-11618286, +-9, +-11618286, +-9, +-11618286, +-9, +-11618286, +-9, +-11618286, +-9, +-11618286, +-9, +-11618286, +-9, +-11618286, +-9, +-11618286, +-9, +-11618286, +-9, +-11512925, +-10, +-11512925, +-10, +-11512925, +-10, +-11512925, +-10, +-11512925, +-10, +-11512925, +-10, +-11512925, +-10, +-11512925, +-10, +-11512925, +-10, +-11512925, +-10, +-11512925, +-10, +-11512925, +-10, +-11512925, +-10, +-11512925, +-10, +-11512925, +-10, +-11512925, +-10, +-11417615, +-11, +-11417615, +-11, +-11417615, +-11, +-11417615, +-11, +-11417615, +-11, +-11417615, +-11, +-11417615, +-11, +-11417615, +-11, +-11417615, +-11, +-11417615, +-11, +-11417615, +-11, +-11417615, +-11, +-11417615, +-11, +-11417615, +-11, +-11330604, +-12, +-11330604, +-12, +-11330604, +-12, +-11330604, +-12, +-11330604, +-12, +-11330604, +-12, +-11330604, +-12, +-11330604, +-12, +-11330604, +-12, +-11330604, +-12, +-11330604, +-12, +-11330604, +-12, +-11330604, +-12, +-11250561, +-13, +-11250561, +-13, +-11250561, +-13, +-11250561, +-13, +-11250561, +-13, +-11250561, +-13, +-11250561, +-13, +-11250561, +-13, +-11250561, +-13, +-11250561, +-13, +-11250561, +-13, +-11250561, +-13, +-11176453, +-14, +-11176453, +-14, +-11176453, +-14, +-11176453, +-14, +-11176453, +-14, +-11176453, +-14, +-11176453, +-14, +-11176453, +-14, +-11176453, +-14, +-11176453, +-14, +-11176453, +-14, +-11176453, +-14, +-11107460, +-15, +-11107460, +-15, +-11107460, +-15, +-11107460, +-15, +-11107460, +-15, +-11107460, +-15, +-11107460, +-15, +-11107460, +-15, +-11107460, +-15, +-11107460, +-15, +-11107460, +-15, +-11042922, +-16, +-11042922, +-16, +-11042922, +-16, +-11042922, +-16, +-11042922, +-16, +-11042922, +-16, +-11042922, +-16, +-11042922, +-16, +-11042922, +-16, +-11042922, +-16, +-10982297, +-17, +-10982297, +-17, +-10982297, +-17, +-10982297, +-17, +-10982297, +-17, +-10982297, +-17, +-10982297, +-17, +-10982297, +-17, +-10982297, +-17, +-10925139, +-18, +-10925139, +-18, +-10925139, +-18, +-10925139, +-18, +-10925139, +-18, +-10925139, +-18, +-10925139, +-18, +-10925139, +-18, +-10925139, +-18, +-10871072, +-19, +-10871072, +-19, +-10871072, +-19, +-10871072, +-19, +-10871072, +-19, +-10871072, +-19, +-10871072, +-19, +-10871072, +-19, +-10871072, +-19, +-10819778, +-20, +-10819778, +-20, +-10819778, +-20, +-10819778, +-20, +-10819778, +-20, +-10819778, +-20, +-10819778, +-20, +-10819778, +-20, +-10770988, +-21, +-10770988, +-21, +-10770988, +-21, +-10770988, +-21, +-10770988, +-21, +-10770988, +-21, +-10770988, +-21, +-10770988, +-21, +-10724468, +-22, +-10724468, +-22, +-10724468, +-22, +-10724468, +-22, +-10724468, +-22, +-10724468, +-22, +-10724468, +-22, +-10680016, +-23, +-10680016, +-23, +-10680016, +-23, +-10680016, +-23, +-10680016, +-23, +-10680016, +-23, +-10680016, +-23, +-10680016, +-23, +-10637457, +-24, +-10637457, +-24, +-10637457, +-24, +-10637457, +-24, +-10637457, +-24, +-10637457, +-24, +-10596635, +-25, +-10596635, +-25, +-10596635, +-25, +-10596635, +-25, +-10596635, +-25, +-10596635, +-25, +-10596635, +-25, +-10557414, +-26, +-10557414, +-26, +-10557414, +-26, +-10557414, +-26, +-10557414, +-26, +-10557414, +-26, +-10519674, +-27, +-10519674, +-27, +-10519674, +-27, +-10519674, +-27, +-10519674, +-27, +-10519674, +-27, +-10483306, +-28, +-10483306, +-28, +-10483306, +-28, +-10483306, +-28, +-10483306, +-28, +-10483306, +-28, +-10483306, +-28, +-10448215, +-29, +-10448215, +-29, +-10448215, +-29, +-10448215, +-29, +-10448215, +-29, +-10414313, +-30, +-10414313, +-30, +-10414313, +-30, +-10414313, +-30, +-10414313, +-30, +-10414313, +-30, +-10381523, +-31, +-10381523, +-31, +-10381523, +-31, +-10381523, +-31, +-10381523, +-31, +-10349775, +-32, +-10349775, +-32, +-10349775, +-32, +-10349775, +-32, +-10349775, +-32, +-10319003, +-33, +-10319003, +-33, +-10319003, +-33, +-10319003, +-33, +-10319003, +-33, +-10319003, +-33, +-10289150, +-34, +-10289150, +-34, +-10289150, +-34, +-10289150, +-34, +-10260162, +-35, +-10260162, +-35, +-10260162, +-35, +-10260162, +-35, +-10260162, +-35, +-10231992, +-36, +-10231992, +-36, +-10231992, +-36, +-10231992, +-36, +-10231992, +-36, +-10204593, +-37, +-10204593, +-37, +-10204593, +-37, +-10204593, +-37, +-10177924, +-38, +-10177924, +-38, +-10177924, +-38, +-10177924, +-38, +-10177924, +-38, +-10151949, +-39, +-10151949, +-39, +-10151949, +-39, +-10151949, +-39, +-10126631, +-40, +-10126631, +-40, +-10126631, +-40, +-10126631, +-40, +-10101939, +-41, +-10101939, +-41, +-10101939, +-41, +-10101939, +-41, +-10101939, +-41, +-10077841, +-42, +-10077841, +-42, +-10077841, +-42, +-10077841, +-42, +-10054310, +-43, +-10054310, +-43, +-10054310, +-43, +-10054310, +-43, +-10031321, +-44, +-10031321, +-44, +-10031321, +-44, +-10031321, +-44, +-10008848, +-45, +-10008848, +-45, +-10008848, +-45, +-9986869, +-46, +-9986869, +-46, +-9986869, +-46, +-9986869, +-46, +-9965363, +-47, +-9965363, +-47, +-9965363, +-47, +-9965363, +-47, +-9944310, +-48, +-9944310, +-48, +-9944310, +-48, +-9923690, +-49, +-9923690, +-49, +-9923690, +-49, +-9923690, +-49, +-9903488, +-50, +-9903488, +-50, +-9903488, +-50, +-9883685, +-51, +-9883685, +-51, +-9883685, +-51, +-9883685, +-51, +-9864267, +-52, +-9864267, +-52, +-9864267, +-52, +-9845219, +-53, +-9845219, +-53, +-9845219, +-53, +-9826527, +-54, +-9826527, +-54, +-9826527, +-54, +-9808177, +-55, +-9808177, +-55, +-9808177, +-55, +-9790159, +-56, +-9790159, +-56, +-9790159, +-56, +-9772459, +-57, +-9772459, +-57, +-9772459, +-57, +-9772459, +-57, +-9755068, +-58, +-9755068, +-58, +-9737973, +-59, +-9737973, +-59, +-9737973, +-59, +-9721166, +-60, +-9721166, +-60, +-9721166, +-60, +-9704637, +-61, +-9704637, +-61, +-9704637, +-61, +-9688376, +-62, +-9688376, +-62, +-9688376, +-62, +-9672376, +-63, +-9672376, +-63, +-9672376, +-63, +-9656627, +-64, +-9656627, +-64, +-9641123, +-65, +-9641123, +-65, +-9641123, +-65, +-9625856, +-66, +-9625856, +-66, +-9625856, +-66, +-9610818, +-67, +-9610818, +-67, +-9596003, +-68, +-9596003, +-68, +-9596003, +-68, +-9581404, +-69, +-9581404, +-69, +-9567015, +-70, +-9567015, +-70, +-9567015, +-70, +-9552831, +-71, +-9552831, +-71, +-9538844, +-72, +-9538844, +-72, +-9538844, +-72, +-9525051, +-73, +-9525051, +-73, +-9511445, +-74, +-9511445, +-74, +-9511445, +-74, +-9498022, +-75, +-9498022, +-75, +-9484777, +-76, +-9484777, +-76, +-9471705, +-77, +-9471705, +-77, +-9471705, +-77, +-9458802, +-78, +-9458802, +-78, +-9446063, +-79, +-9446063, +-79, +-9433484, +-80, +-9433484, +-80, +-9421061, +-81, +-9421061, +-81, +-9408791, +-82, +-9408791, +-82, +-9408791, +-82, +-9396670, +-83, +-9396670, +-83, +-9384694, +-84, +-9384694, +-84, +-9372859, +-85, +-9372859, +-85, +-9361163, +-86, +-9361163, +-86, +-9349602, +-87, +-9349602, +-87, +-9338174, +-88, +-9338174, +-88, +-9326874, +-89, +-9326874, +-89, +-9315701, +-90, +-9315701, +-90, +-9304651, +-91, +-9304651, +-91, +-9293722, +-92, +-9293722, +-92, +-9282911, +-93, +-9282911, +-93, +-9272216, +-94, +-9272216, +-94, +-9261634, +-95, +-9261634, +-95, +-9251162, +-96, +-9240800, +-97, +-9240800, +-97, +-9230543, +-98, +-9230543, +-98, +-9220391, +-99, +-9220391, +-99, +-9210340, +-100, +-9210340, +-100, +-9200390, +-101, +-9190538, +-102, +-9190538, +-102, +-9180782, +-103, +-9180782, +-103, +-9171120, +-104, +-9171120, +-104, +-9161550, +-105, +-9152071, +-106, +-9152071, +-106, +-9142682, +-107, +-9142682, +-107, +-9133379, +-108, +-9124163, +-109, +-9124163, +-109, +-9115030, +-110, +-9115030, +-110, +-9105980, +-111, +-9097012, +-112, +-9097012, +-112, +-9088123, +-113, +-9079312, +-114, +-9079312, +-114, +-9070578, +-115, +-9070578, +-115, +-9061920, +-116, +-9053337, +-117, +-9053337, +-117, +-9044826, +-118, +-9036387, +-119, +-9036387, +-119, +-9028019, +-120, +-9019720, +-121, +-9019720, +-121, +-9011490, +-122, +-9003326, +-123, +-9003326, +-123, +-8995229, +-124, +-8987197, +-125, +-8987197, +-125, +-8979229, +-126, +-8971323, +-127, +-8963480, +-128, +-8963480, +-128, +-8955698, +-129, +-8947976, +-130, +-8947976, +-130, +-8940313, +-131, +-8932709, +-132, +-8925161, +-133, +-8925161, +-133, +-8917671, +-134, +-8910236, +-135, +-8910236, +-135, +-8902856, +-136, +-8895530, +-137, +-8888257, +-138, +-8888257, +-138, +-8881037, +-139, +-8873868, +-140, +-8866751, +-141, +-8859683, +-142, +-8859683, +-142, +-8852666, +-143, +-8845697, +-144, +-8838777, +-145, +-8838777, +-145, +-8831904, +-146, +-8825078, +-147, +-8818298, +-148, +-8811564, +-149, +-8804875, +-150, +-8804875, +-150, +-8798231, +-151, +-8791630, +-152, +-8785073, +-153, +-8778558, +-154, +-8778558, +-154, +-8772085, +-155, +-8765655, +-156, +-8759265, +-157, +-8752916, +-158, +-8746606, +-159, +-8740337, +-160, +-8740337, +-160, +-8734106, +-161, +-8727914, +-162, +-8721760, +-163, +-8715644, +-164, +-8709565, +-165, +-8703523, +-166, +-8697517, +-167, +-8691547, +-168, +-8685612, +-169, +-8685612, +-169, +-8679712, +-170, +-8673847, +-171, +-8668016, +-172, +-8662219, +-173, +-8656455, +-174, +-8650725, +-175, +-8645027, +-176, +-8639361, +-177, +-8633727, +-178, +-8628125, +-179, +-8622554, +-180, +-8617014, +-181, +-8611504, +-182, +-8606024, +-183, +-8600575, +-184, +-8595155, +-185, +-8589764, +-186, +-8584402, +-187, +-8579069, +-188, +-8573764, +-189, +-8568486, +-190, +-8563237, +-191, +-8558015, +-192, +-8552820, +-193, +-8547652, +-194, +-8542511, +-195, +-8537396, +-196, +-8532307, +-197, +-8527244, +-198, +-8522206, +-199, +-8517193, +-200, +-8512206, +-201, +-8507243, +-202, +-8502305, +-203, +-8492501, +-205, +-8487634, +-206, +-8482792, +-207, +-8477972, +-208, +-8473176, +-209, +-8468403, +-210, +-8463652, +-211, +-8458924, +-212, +-8449535, +-214, +-8444873, +-215, +-8440232, +-216, +-8435613, +-217, +-8431015, +-218, +-8426439, +-219, +-8421883, +-220, +-8412833, +-222, +-8408339, +-223, +-8403864, +-224, +-8399410, +-225, +-8394976, +-226, +-8386165, +-228, +-8381788, +-229, +-8377431, +-230, +-8373093, +-231, +-8368772, +-232, +-8360189, +-234, +-8355924, +-235, +-8351679, +-236, +-8347450, +-237, +-8339047, +-239, +-8334872, +-240, +-8330714, +-241, +-8322449, +-243, +-8318341, +-244, +-8314252, +-245, +-8310179, +-246, +-8302082, +-248, +-8298057, +-248, +-8294050, +-250, +-8286080, +-252, +-8282121, +-253, +-8278176, +-254, +-8270333, +-256, +-8266434, +-257, +-8262551, +-258, +-8254829, +-260, +-8250990, +-261, +-8247166, +-262, +-8239561, +-264, +-8235780, +-265, +-8228262, +-267, +-8224524, +-268, +-8217089, +-270, +-8213392, +-271, +-8209707, +-272, +-8202382, +-274, +-8198739, +-275, +-8191492, +-277, +-8187889, +-278, +-8180721, +-280, +-8177156, +-281, +-8170064, +-283, +-8166536, +-284, +-8159518, +-286, +-8156027, +-287, +-8149084, +-289, +-8145630, +-290, +-8138757, +-292, +-8135338, +-293, +-8128534, +-295, +-8125151, +-296, +-8118417, +-298, +-8115067, +-299, +-8108400, +-301, +-8105084, +-302, +-8098483, +-304, +-8091925, +-306, +-8088663, +-307, +-8082169, +-309, +-8078938, +-310, +-8072507, +-312, +-8066117, +-314, +-8062938, +-315, +-8056609, +-317, +-8050319, +-319, +-8047190, +-320, +-8040959, +-322, +-8034767, +-324, +-8031684, +-325, +-8025550, +-327, +-8019453, +-329, +-8016418, +-330, +-8010376, +-332, +-8004370, +-334, +-8001379, +-335, +-7995428, +-337, +-7989510, +-339, +-7983628, +-341, +-7980700, +-342, +-7974869, +-344, +-7969072, +-346, +-7963308, +-348, +-7957577, +-350, +-7954724, +-351, +-7949042, +-353, +-7943393, +-355, +-7937775, +-357, +-7932188, +-359, +-7926633, +-361, +-7923866, +-362, +-7918357, +-364, +-7912877, +-366, +-7907428, +-368, +-7902008, +-370, +-7896617, +-372, +-7891255, +-374, +-7885921, +-376, +-7880616, +-378, +-7875339, +-380, +-7870090, +-382, +-7864868, +-384, +-7862267, +-385, +-7857086, +-387, +-7851931, +-389, +-7846803, +-391, +-7841701, +-393, +-7834096, +-396, +-7829059, +-398, +-7824046, +-400, +-7819058, +-402, +-7814096, +-404, +-7809157, +-406, +-7804243, +-408, +-7799353, +-410, +-7794487, +-412, +-7789645, +-414, +-7784825, +-416, +-7780029, +-418, +-7775256, +-420, +-7768138, +-423, +-7763421, +-425, +-7758727, +-427, +-7754054, +-429, +-7749402, +-431, +-7742466, +-434, +-7737868, +-436, +-7733292, +-438, +-7728736, +-440, +-7724201, +-442, +-7717436, +-445, +-7712952, +-447, +-7708488, +-449, +-7704043, +-451, +-7697413, +-454, +-7693018, +-456, +-7688641, +-458, +-7682113, +-461, +-7677783, +-463, +-7673473, +-465, +-7667042, +-468, +-7662778, +-470, +-7658532, +-472, +-7652196, +-475, +-7647994, +-477, +-7641724, +-480, +-7637566, +-482, +-7631362, +-485, +-7627246, +-487, +-7623148, +-488, +-7617032, +-492, +-7612975, +-494, +-7606921, +-497, +-7602904, +-499, +-7596910, +-501, +-7592934, +-504, +-7587000, +-506, +-7581100, +-510, +-7577186, +-512, +-7571344, +-515, +-7567468, +-517, +-7561682, +-520, +-7557843, +-522, +-7552112, +-525, +-7546414, +-528, +-7542634, +-530, +-7536989, +-533, +-7531376, +-536, +-7527652, +-538, +-7522091, +-541, +-7516561, +-544, +-7511062, +-547, +-7507412, +-549, +-7501962, +-552, +-7496542, +-555, +-7491152, +-558, +-7487574, +-560, +-7482231, +-563, +-7476916, +-566, +-7471630, +-569, +-7466372, +-572, +-7462881, +-574, +-7457668, +-577, +-7452482, +-580, +-7447323, +-583, +-7442191, +-586, +-7437084, +-589, +-7432004, +-592, +-7426949, +-595, +-7421920, +-598, +-7416916, +-601, +-7411936, +-604, +-7406982, +-607, +-7402052, +-610, +-7397146, +-613, +-7392264, +-616, +-7387405, +-619, +-7382570, +-622, +-7377759, +-625, +-7372970, +-628, +-7368205, +-631, +-7363462, +-634, +-7358741, +-637, +-7352481, +-641, +-7347812, +-644, +-7343164, +-647, +-7338538, +-650, +-7333933, +-653, +-7327827, +-657, +-7323271, +-660, +-7318736, +-663, +-7314221, +-666, +-7308233, +-670, +-7303765, +-673, +-7299317, +-676, +-7293418, +-680, +-7289016, +-683, +-7284633, +-686, +-7278819, +-690, +-7274481, +-693, +-7270161, +-696, +-7264430, +-700, +-7260154, +-703, +-7254480, +-707, +-7250246, +-710, +-7244628, +-714, +-7240435, +-717, +-7234871, +-721, +-7230719, +-724, +-7225209, +-728, +-7221097, +-731, +-7215640, +-735, +-7210213, +-739, +-7206161, +-742, +-7200785, +-746, +-7196772, +-749, +-7191445, +-753, +-7186147, +-757, +-7182192, +-760, +-7176943, +-764, +-7171721, +-768, +-7166526, +-772, +-7162647, +-775, +-7157500, +-779, +-7152378, +-783, +-7147282, +-787, +-7142213, +-791, +-7138427, +-794, +-7133402, +-798, +-7128402, +-802, +-7123427, +-806, +-7118476, +-810, +-7113550, +-814, +-7108648, +-818, +-7103770, +-822, +-7098916, +-826, +-7094085, +-830, +-7089277, +-834, +-7084492, +-838, +-7079731, +-842, +-7074991, +-846, +-7070274, +-850, +-7065579, +-854, +-7060906, +-858, +-7055096, +-863, +-7050472, +-867, +-7045869, +-871, +-7041287, +-875, +-7036726, +-879, +-7031054, +-884, +-7026539, +-888, +-7022044, +-892, +-7017570, +-896, +-7012005, +-901, +-7007576, +-905, +-7003165, +-909, +-6997680, +-914, +-6993313, +-918, +-6987881, +-923, +-6983557, +-927, +-6979251, +-931, +-6973895, +-936, +-6969631, +-940, +-6964326, +-945, +-6960102, +-949, +-6954847, +-954, +-6949619, +-959, +-6945457, +-963, +-6940278, +-968, +-6936155, +-972, +-6931024, +-977, +-6925919, +-982, +-6921854, +-985, +-6916796, +-990, +-6911763, +-995, +-6906756, +-1002, +-6902768, +-1006, +-6897805, +-1011, +-6892867, +-1016, +-6887953, +-1021, +-6883063, +-1026, +-6878196, +-1031, +-6874321, +-1035, +-6869497, +-1040, +-6864696, +-1045, +-6859918, +-1050, +-6855163, +-1055, +-6850430, +-1060, +-6845720, +-1065, +-6841032, +-1070, +-6836365, +-1075, +-6830794, +-1081, +-6826175, +-1086, +-6821578, +-1091, +-6817001, +-1096, +-6812445, +-1101, +-6807910, +-1106, +-6802495, +-1112, +-6798004, +-1117, +-6793534, +-1122, +-6789084, +-1127, +-6783769, +-1133, +-6779362, +-1138, +-6774974, +-1143, +-6769734, +-1149, +-6765388, +-1154, +-6760198, +-1160, +-6755893, +-1165, +-6750752, +-1171, +-6746487, +-1176, +-6741394, +-1182, +-6737169, +-1187, +-6732123, +-1193, +-6727937, +-1198, +-6722937, +-1204, +-6717962, +-1210, +-6713835, +-1215, +-6708904, +-1221, +-6703998, +-1227, +-6699116, +-1233, +-6695066, +-1238, +-6690227, +-1244, +-6685412, +-1250, +-6680620, +-1256, +-6675850, +-1262, +-6671103, +-1268, +-6666379, +-1274, +-6662459, +-1279, +-6657775, +-1285, +-6653113, +-1291, +-6648473, +-1297, +-6643086, +-1304, +-6638492, +-1310, +-6633919, +-1316, +-6629366, +-1322, +-6624835, +-1328, +-6620323, +-1334, +-6615832, +-1340, +-6610618, +-1347, +-6606170, +-1353, +-6601742, +-1359, +-6597334, +-1365, +-6592215, +-1372, +-6587848, +-1378, +-6582777, +-1385, +-6578452, +-1391, +-6573428, +-1398, +-6569142, +-1404, +-6564875, +-1410, +-6559919, +-1417, +-6554988, +-1424, +-6550780, +-1430, +-6545894, +-1437, +-6541724, +-1443, +-6536882, +-1450, +-6532062, +-1457, +-6527266, +-1464, +-6523173, +-1470, +-6518420, +-1477, +-6513688, +-1484, +-6508979, +-1491, +-6504292, +-1498, +-6500292, +-1504, +-6495646, +-1511, +-6491021, +-1518, +-6486417, +-1525, +-6481834, +-1532, +-6477272, +-1539, +-6472084, +-1547, +-6467567, +-1554, +-6463069, +-1561, +-6458592, +-1568, +-6454135, +-1575, +-6449698, +-1582, +-6444650, +-1590, +-6440255, +-1597, +-6435878, +-1604, +-6430900, +-1612, +-6426564, +-1619, +-6422247, +-1626, +-6417336, +-1634, +-6413059, +-1641, +-6408193, +-1649, +-6403954, +-1656, +-6399132, +-1664, +-6394932, +-1671, +-6390153, +-1679, +-6385396, +-1687, +-6381253, +-1694, +-6376539, +-1702, +-6371847, +-1710, +-6367177, +-1718, +-6362528, +-1726, +-6358478, +-1734, +-6353870, +-1742, +-6349283, +-1750, +-6344717, +-1758, +-6340171, +-1766, +-6335646, +-1774, +-6331142, +-1782, +-6326658, +-1790, +-6322193, +-1798, +-6317195, +-1807, +-6312772, +-1815, +-6308369, +-1823, +-6303986, +-1831, +-6299621, +-1839, +-6294734, +-1848, +-6290410, +-1856, +-6285567, +-1865, +-6281282, +-1873, +-6277016, +-1881, +-6272237, +-1890, +-6268009, +-1898, +-6263273, +-1907, +-6258560, +-1916, +-6254389, +-1924, +-6249717, +-1933, +-6245067, +-1942, +-6240952, +-1950, +-6236343, +-1958, +-6231754, +-1968, +-6227187, +-1977, +-6222640, +-1986, +-6218114, +-1994, +-6214108, +-2003, +-6209621, +-2012, +-6204658, +-2022, +-6200212, +-2030, +-6195786, +-2040, +-6191380, +-2049, +-6186993, +-2058, +-6182625, +-2067, +-6178276, +-2076, +-6173466, +-2086, +-6169157, +-2095, +-6164866, +-2104, +-6160120, +-2114, +-6155868, +-2123, +-6151164, +-2133, +-6146949, +-2142, +-6142287, +-2152, +-6138110, +-2161, +-6133489, +-2171, +-6128889, +-2181, +-6124767, +-2190, +-6120207, +-2200, +-6115668, +-2210, +-6111149, +-2220, +-6106651, +-2230, +-6102173, +-2241, +-6097714, +-2251, +-6093719, +-2260, +-6088857, +-2271, +-6084457, +-2281, +-6080077, +-2291, +-6075716, +-2301, +-6071374, +-2311, +-6067051, +-2321, +-6062316, +-2332, +-6058032, +-2342, +-6053766, +-2352, +-6049094, +-2363, +-6044865, +-2373, +-6040235, +-2384, +-6036044, +-2394, +-6031454, +-2405, +-6027299, +-2415, +-6022749, +-2426, +-6018219, +-2437, +-6014119, +-2447, +-6009628, +-2458, +-6005158, +-2469, +-6000707, +-2480, +-5996276, +-2491, +-5991865, +-2502, +-5987473, +-2513, +-5983100, +-2524, +-5978746, +-2535, +-5974411, +-2546, +-5970095, +-2557, +-5965797, +-2568, +-5961517, +-2579, +-5956870, +-2591, +-5952629, +-2602, +-5948022, +-2614, +-5943818, +-2625, +-5939631, +-2636, +-5935084, +-2649, +-5930558, +-2661, +-5926426, +-2672, +-5921939, +-2684, +-5917471, +-2696, +-5913393, +-2707, +-5908963, +-2719, +-5904553, +-2731, +-5900162, +-2743, +-5895791, +-2755, +-5891438, +-2767, +-5887105, +-2779, +-5882790, +-2791, +-5878493, +-2803, +-5874215, +-2815, +-5869955, +-2827, +-5865361, +-2840, +-5861138, +-2852, +-5856934, +-2864, +-5852399, +-2877, +-5848230, +-2889, +-5843734, +-2902, +-5839602, +-2914, +-5835145, +-2927, +-5830707, +-2940, +-5826628, +-2952, +-5822228, +-2965, +-5817847, +-2978, +-5813486, +-2991, +-5809143, +-3005, +-5804819, +-3018, +-5800514, +-3031, +-5796227, +-3044, +-5791958, +-3057, +-5787708, +-3070, +-5783475, +-3083, +-5779261, +-3096, +-5774742, +-3110, +-5770564, +-3123, +-5766083, +-3137, +-5761941, +-3150, +-5757500, +-3164, +-5753393, +-3177, +-5748989, +-3191, +-5744917, +-3204, +-5740550, +-3218, +-5736202, +-3232, +-5731873, +-3246, +-5727563, +-3260, +-5723271, +-3274, +-5718998, +-3288, +-5714742, +-3302, +-5710505, +-3316, +-5706286, +-3331, +-5702084, +-3345, +-5697602, +-3360, +-5693436, +-3374, +-5689288, +-3388, +-5684863, +-3403, +-5680750, +-3417, +-5676362, +-3432, +-5672284, +-3446, +-5667933, +-3461, +-5663601, +-3476, +-5659287, +-3491, +-5655278, +-3505, +-5651000, +-3520, +-5646741, +-3535, +-5642499, +-3550, +-5638276, +-3565, +-5634070, +-3580, +-5629603, +-3596, +-5625434, +-3612, +-5621281, +-3627, +-5617146, +-3642, +-5612754, +-3658, +-5608654, +-3673, +-5604299, +-3689, +-5600234, +-3704, +-5595915, +-3720, +-5591615, +-3736, +-5587334, +-3752, +-5583336, +-3767, +-5579090, +-3783, +-5574862, +-3799, +-5570651, +-3815, +-5566458, +-3831, +-5562283, +-3847, +-5557866, +-3864, +-5553726, +-3881, +-5549603, +-3897, +-5545498, +-3913, +-5541154, +-3930, +-5537082, +-3946, +-5532775, +-3963, +-5528486, +-3980, +-5524465, +-3996, +-5520212, +-4013, +-5515976, +-4029, +-5511758, +-4047, +-5507558, +-4064, +-5503375, +-4081, +-5499210, +-4098, +-5495062, +-4115, +-5490932, +-4133, +-5486818, +-4150, +-5482721, +-4167, +-5478401, +-4185, +-5474339, +-4202, +-5470055, +-4220, +-5466026, +-4237, +-5461778, +-4255, +-5457548, +-4273, +-5453335, +-4291, +-5449373, +-4308, +-5445195, +-4326, +-5441034, +-4344, +-5436890, +-4363, +-5432763, +-4381, +-5428426, +-4400, +-5424334, +-4418, +-5420259, +-4436, +-5416200, +-4454, +-5411934, +-4473, +-5407909, +-4491, +-5403678, +-4510, +-5399465, +-4529, +-5395489, +-4547, +-5391310, +-4566, +-5387149, +-4585, +-5383004, +-4605, +-5378877, +-4624, +-5374767, +-4643, +-5370673, +-4662, +-5366596, +-4681, +-5362323, +-4701, +-5358280, +-4720, +-5354253, +-4739, +-5350032, +-4759, +-5346038, +-4778, +-5341851, +-4798, +-5337682, +-4819, +-5333530, +-4839, +-5329602, +-4858, +-5325483, +-4878, +-5321381, +-4898, +-5317296, +-4918, +-5313025, +-4939, +-5308974, +-4959, +-5304939, +-4979, +-5300921, +-4999, +-5296719, +-5021, +-5292733, +-5041, +-5288565, +-5062, +-5284414, +-5083, +-5280477, +-5103, +-5276360, +-5124, +-5272260, +-5145, +-5268176, +-5166, +-5264109, +-5187, +-5260059, +-5209, +-5256024, +-5230, +-5251816, +-5252, +-5247814, +-5273, +-5243829, +-5294, +-5239671, +-5316, +-5235530, +-5338, +-5231594, +-5359, +-5227486, +-5381, +-5223395, +-5404, +-5219321, +-5426, +-5215264, +-5448, +-5211223, +-5470, +-5207198, +-5492, +-5203189, +-5514, +-5199196, +-5536, +-5195039, +-5559, +-5191079, +-5582, +-5186955, +-5605, +-5183026, +-5627, +-5178936, +-5650, +-5174862, +-5673, +-5170804, +-5696, +-5166763, +-5719, +-5162738, +-5742, +-5158729, +-5766, +-5154737, +-5789, +-5150760, +-5812, +-5146627, +-5836, +-5142682, +-5859, +-5138582, +-5883, +-5134669, +-5906, +-5130602, +-5931, +-5126551, +-5955, +-5122517, +-5979, +-5118666, +-6002, +-5114497, +-6027, +-5110511, +-6051, +-5106541, +-6075, +-5102586, +-6100, +-5098483, +-6125, +-5094561, +-6149, +-5090491, +-6174, +-5086599, +-6198, +-5082561, +-6223, +-5078539, +-6248, +-5074534, +-6274, +-5070545, +-6299, +-5066571, +-6324, +-5062613, +-6349, +-5058671, +-6374, +-5054744, +-6399, +-5050676, +-6426, +-5046781, +-6451, +-5042745, +-6477, +-5038726, +-6503, +-5034877, +-6528, +-5030889, +-6554, +-5026917, +-6581, +-5022961, +-6607, +-5018869, +-6634, +-5014945, +-6660, +-5011035, +-6686, +-5006992, +-6713, +-5003114, +-6740, +-4999102, +-6767, +-4995254, +-6793, +-4991274, +-6820, +-4987309, +-6847, +-4983361, +-6875, +-4979427, +-6902, +-4975509, +-6929, +-4971463, +-6957, +-4967576, +-6984, +-4963561, +-7013, +-4959705, +-7040, +-4955721, +-7068, +-4951753, +-7096, +-4947942, +-7123, +-4944005, +-7152, +-4940084, +-7180, +-4936038, +-7209, +-4932148, +-7237, +-4928272, +-7265, +-4924274, +-7295, +-4920429, +-7323, +-4916462, +-7352, +-4912647, +-7380, +-4908711, +-7409, +-4904790, +-7439, +-4900884, +-7468, +-4896994, +-7497, +-4892986, +-7527, +-4889126, +-7556, +-4885281, +-7586, +-4881319, +-7616, +-4877373, +-7646, +-4873573, +-7675, +-4869657, +-7706, +-4865756, +-7736, +-4861870, +-7766, +-4858000, +-7796, +-4854144, +-7827, +-4850176, +-7858, +-4846350, +-7887, +-4842413, +-7919, +-4838490, +-7951, +-4834709, +-7981, +-4830817, +-8012, +-4826940, +-8043, +-4823077, +-8075, +-4819230, +-8106, +-4815274, +-8137, +-4811457, +-8168, +-4807531, +-8202, +-4803743, +-8233, +-4799848, +-8265, +-4795968, +-8297, +-4792102, +-8330, +-4788252, +-8362, +-4784416, +-8394, +-4780596, +-8426, +-4776671, +-8460, +-4772879, +-8492, +-4768984, +-8525, +-4765222, +-8558, +-4761356, +-8591, +-4757506, +-8624, +-4753670, +-8657, +-4749849, +-8691, +-4745928, +-8725, +-4742136, +-8758, +-4738245, +-8793, +-4734482, +-8826, +-4730620, +-8860, +-4726773, +-8894, +-4722941, +-8929, +-4719123, +-8963, +-4715320, +-8997, +-4711531, +-9032, +-4707646, +-9067, +-4703886, +-9101, +-4700030, +-9137, +-4696190, +-9172, +-4692473, +-9206, +-4688661, +-9242, +-4684863, +-9277, +-4680972, +-9313, +-4677203, +-9349, +-4673449, +-9384, +-4669602, +-9420, +-4665770, +-9457, +-4661952, +-9493, +-4658255, +-9528, +-4654360, +-9566, +-4650586, +-9602, +-4646826, +-9638, +-4643080, +-9675, +-4639244, +-9712, +-4635423, +-9749, +-4631720, +-9786, +-4627927, +-9823, +-4624149, +-9860, +-4620385, +-9898, +-4616535, +-9936, +-4612799, +-9974, +-4609078, +-10011, +-4605270, +-10049, +-4601477, +-10088, +-4597698, +-10126, +-4593934, +-10164, +-4590183, +-10203, +-4586447, +-10241, +-4582724, +-10280, +-4578918, +-10319, +-4575126, +-10358, +-4571445, +-10397, +-4567682, +-10436, +-4563932, +-10476, +-4560197, +-10515, +-4556380, +-10556, +-4552673, +-10595, +-4548884, +-10635, +-4545205, +-10675, +-4541445, +-10715, +-4537698, +-10756, +-4533966, +-10796, +-4530248, +-10837, +-4526544, +-10877, +-4522761, +-10918, +-4519084, +-10959, +-4515329, +-11000, +-4511589, +-11042, +-4507862, +-11083, +-4504149, +-11125, +-4500450, +-11166, +-4496675, +-11209, +-4493003, +-11250, +-4489256, +-11293, +-4485611, +-11334, +-4481891, +-11376, +-4478185, +-11419, +-4474405, +-11462, +-4470727, +-11505, +-4467062, +-11547, +-4463323, +-11591, +-4459599, +-11634, +-4455975, +-11677, +-4452277, +-11720, +-4448508, +-11765, +-4444839, +-11808, +-4441182, +-11852, +-4437455, +-11896, +-4433825, +-11940, +-4430125, +-11985, +-4426438, +-12029, +-4422765, +-12074, +-4419023, +-12119, +-4415377, +-12164, +-4411661, +-12209, +-4408042, +-12254, +-4404354, +-12299, +-4400680, +-12345, +-4397018, +-12390, +-4393371, +-12436, +-4389656, +-12483, +-4386035, +-12528, +-4382347, +-12575, +-4378672, +-12621, +-4375011, +-12668, +-4371364, +-12714, +-4367729, +-12761, +-4364108, +-12808, +-4360422, +-12855, +-4356749, +-12903, +-4353089, +-12950, +-4349443, +-12998, +-4345810, +-13046, +-4342191, +-13093, +-4338584, +-13141, +-4334914, +-13190, +-4331257, +-13238, +-4327614, +-13287, +-4323984, +-13336, +-4320367, +-13384, +-4316763, +-13433, +-4313098, +-13482, +-4309520, +-13531, +-4305881, +-13581, +-4302255, +-13630, +-4298642, +-13680, +-4294969, +-13731, +-4291382, +-13781, +-4287735, +-13831, +-4284174, +-13881, +-4280554, +-13932, +-4276946, +-13982, +-4273352, +-14033, +-4269698, +-14085, +-4266130, +-14135, +-4262503, +-14187, +-4258889, +-14239, +-4255288, +-14291, +-4251700, +-14342, +-4248125, +-14394, +-4244493, +-14447, +-4240944, +-14499, +-4237338, +-14551, +-4233745, +-14604, +-4230164, +-14657, +-4226597, +-14710, +-4222974, +-14763, +-4219432, +-14816, +-4215834, +-14870, +-4212250, +-14924, +-4208679, +-14978, +-4205120, +-15031, +-4201573, +-15085, +-4197973, +-15140, +-4194386, +-15195, +-4190811, +-15250, +-4187249, +-15305, +-4183700, +-15359, +-4180164, +-15414, +-4176574, +-15470, +-4172997, +-15526, +-4169499, +-15581, +-4165948, +-15637, +-4162345, +-15694, +-4158819, +-15749, +-4155242, +-15806, +-4151741, +-15862, +-4148189, +-15919, +-4144649, +-15976, +-4141059, +-16034, +-4137544, +-16091, +-4133980, +-16149, +-4130490, +-16206, +-4126950, +-16264, +-4123423, +-16320, +-4119847, +-16379, +-4116345, +-16438, +-4112794, +-16497, +-4109315, +-16555, +-4105790, +-16614, +-4102216, +-16674, +-4098714, +-16733, +-4095225, +-16792, +-4091688, +-16852, +-4088164, +-16912, +-4084652, +-16972, +-4081152, +-17032, +-4077664, +-17092, +-4074130, +-17153, +-4070608, +-17214, +-4067099, +-17275, +-4063602, +-17336, +-4060117, +-17397, +-4056644, +-17459, +-4053126, +-17521, +-4049620, +-17583, +-4046126, +-17645, +-4042644, +-17707, +-4039175, +-17769, +-4035661, +-17832, +-4032159, +-17895, +-4028669, +-17958, +-4025191, +-18021, +-4021726, +-18085, +-4018272, +-18148, +-4014776, +-18212, +-4011291, +-18276, +-4007818, +-18340, +-4004358, +-18404, +-4000854, +-18470, +-3997417, +-18534, +-3993938, +-18599, +-3990471, +-18664, +-3987016, +-18729, +-3983573, +-18795, +-3980088, +-18861, +-3976615, +-18927, +-3973154, +-18993, +-3969705, +-19059, +-3966268, +-19126, +-3962843, +-19192, +-3959377, +-19259, +-3955923, +-19327, +-3952480, +-19394, +-3949050, +-19461, +-3945580, +-19529, +-3942173, +-19597, +-3938726, +-19665, +-3935292, +-19733, +-3931818, +-19803, +-3928407, +-19871, +-3924956, +-19940, +-3921568, +-20009, +-3918142, +-20078, +-3914677, +-20149, +-3911273, +-20218, +-3907832, +-20288, +-3904452, +-20358, +-3900984, +-20429, +-3897578, +-20500, +-3894183, +-20570, +-3890751, +-20642, +-3887330, +-20713, +-3883922, +-20785, +-3880524, +-20856, +-3877139, +-20927, +-3873716, +-21000, +-3870305, +-21072, +-3866906, +-21145, +-3863519, +-21218, +-3860142, +-21290, +-3856730, +-21364, +-3853330, +-21437, +-3849941, +-21511, +-3846563, +-21584, +-3843150, +-21659, +-3839795, +-21732, +-3836405, +-21807, +-3833027, +-21882, +-3829614, +-21957, +-3826258, +-22032, +-3822868, +-22108, +-3819489, +-22183, +-3816122, +-22259, +-3812721, +-22336, +-3809376, +-22411, +-3805998, +-22488, +-3802631, +-22565, +-3799275, +-22641, +-3795886, +-22719, +-3792552, +-22796, +-3789186, +-22874, +-3785831, +-22951, +-3782487, +-23029, +-3779111, +-23108, +-3775745, +-23187, +-3772392, +-23266, +-3769049, +-23344, +-3765717, +-23423, +-3762354, +-23503, +-3759002, +-23583, +-3755661, +-23663, +-3752331, +-23743, +-3749012, +-23823, +-3745661, +-23903, +-3742322, +-23984, +-3738994, +-24065, +-3735678, +-24146, +-3732330, +-24228, +-3728993, +-24310, +-3725668, +-24392, +-3722354, +-24474, +-3719009, +-24557, +-3715716, +-24639, +-3712394, +-24722, +-3709082, +-24805, +-3705741, +-24889, +-3702451, +-24972, +-3699132, +-25056, +-3695824, +-25140, +-3692486, +-25226, +-3689199, +-25310, +-3685884, +-25395, +-3682579, +-25480, +-3679286, +-25565, +-3676003, +-25650, +-3672691, +-25736, +-3669391, +-25823, +-3666101, +-25909, +-3662822, +-25995, +-3659515, +-26082, +-3656219, +-26169, +-3652933, +-26257, +-3649659, +-26344, +-3646356, +-26432, +-3643065, +-26521, +-3639785, +-26609, +-3636515, +-26697, +-3633256, +-26786, +-3629969, +-26875, +-3626694, +-26964, +-3623429, +-27054, +-3620137, +-27144, +-3616894, +-27233, +-3613624, +-27324, +-3610364, +-27414, +-3607078, +-27506, +-3603840, +-27596, +-3600576, +-27688, +-3597322, +-27779, +-3594042, +-27872, +-3590809, +-27963, +-3587551, +-28056, +-3584303, +-28148, +-3581066, +-28241, +-3577803, +-28335, +-3574551, +-28428, +-3571310, +-28522, +-3568079, +-28616, +-3564823, +-28710, +-3561577, +-28805, +-3558343, +-28900, +-3555118, +-28994, +-3551904, +-29089, +-3548665, +-29185, +-3545437, +-29281, +-3542185, +-29377, +-3538978, +-29473, +-3535746, +-29570, +-3532525, +-29667, +-3529315, +-29764, +-3526081, +-29861, +-3522857, +-29959, +-3519643, +-30057, +-3516440, +-30155, +-3513213, +-30254, +-3510031, +-30352, +-3506825, +-30451, +-3503596, +-30551, +-3500410, +-30650, +-3497202, +-30750, +-3494004, +-30850, +-3490783, +-30951, +-3487605, +-31051, +-3484405, +-31152, +-3481215, +-31253, +-3478003, +-31355, +-3474833, +-31457, +-3471641, +-31558, +-3468428, +-31662, +-3465256, +-31764, +-3462063, +-31867, +-3458879, +-31971, +-3455706, +-32074, +-3452543, +-32176, +-3449359, +-32280, +-3446184, +-32385, +-3443020, +-32489, +-3439834, +-32596, +-3436659, +-32701, +-3433493, +-32806, +-3430338, +-32912, +-3427162, +-33018, +-3423995, +-33125, +-3420839, +-33231, +-3417693, +-33338, +-3414526, +-33445, +-3411369, +-33553, +-3408222, +-33660, +-3405055, +-33769, +-3401898, +-33877, +-3398750, +-33986, +-3395613, +-34095, +-3392456, +-34204, +-3389338, +-34313, +-3386171, +-34424, +-3383043, +-34533, +-3379896, +-34644, +-3376758, +-34755, +-3373631, +-34866, +-3370513, +-34977, +-3367376, +-35088, +-3364248, +-35200, +-3361102, +-35313, +-3357994, +-35425, +-3354867, +-35538, +-3351750, +-35651, +-3348614, +-35765, +-3345488, +-35879, +-3342372, +-35993, +-3339265, +-36107, +-3336140, +-36222, +-3333053, +-36336, +-3329919, +-36452, +-3326823, +-36568, +-3323709, +-36684, +-3320604, +-36800, +-3317509, +-36916, +-3314396, +-37033, +-3311293, +-37151, +-3308199, +-37268, +-3305115, +-37385, +-3302013, +-37504, +-3298921, +-37622, +-3295838, +-37740, +-3292738, +-37860, +-3289647, +-37979, +-3286566, +-38099, +-3283494, +-38218, +-3280406, +-38339, +-3277326, +-38459, +-3274230, +-38581, +-3271170, +-38701, +-3268092, +-38823, +-3265024, +-38945, +-3261940, +-39067, +-3258865, +-39190, +-3255799, +-39313, +-3252743, +-39435, +-3249670, +-39559, +-3246607, +-39683, +-3243553, +-39807, +-3240483, +-39932, +-3237422, +-40057, +-3234370, +-40182, +-3231303, +-40308, +-3228270, +-40432, +-3225221, +-40558, +-3222156, +-40686, +-3219126, +-40812, +-3216080, +-40939, +-3213018, +-41067, +-3209990, +-41194, +-3206947, +-41322, +-3203913, +-41450, +-3200864, +-41580, +-3197824, +-41709, +-3194793, +-41838, +-3191771, +-41967, +-3188735, +-42098, +-3185707, +-42228, +-3182689, +-42359, +-3179655, +-42490, +-3176631, +-42622, +-3173616, +-42753, +-3170586, +-42886, +-3167565, +-43018, +-3164553, +-43151, +-3161527, +-43284, +-3158534, +-43417, +-3155502, +-43552, +-3152503, +-43685, +-3149490, +-43820, +-3146485, +-43955, +-3143490, +-44090, +-3140481, +-44226, +-3137480, +-44362, +-3134489, +-44497, +-3131483, +-44634, +-3128487, +-44771, +-3125499, +-44908, +-3122498, +-45047, +-3119506, +-45185, +-3116522, +-45323, +-3113548, +-45461, +-3110560, +-45600, +-3107558, +-45740, +-3104588, +-45880, +-3101604, +-46020, +-3098629, +-46160, +-3095663, +-46301, +-3092684, +-46442, +-3089713, +-46583, +-3086730, +-46726, +-3083755, +-46868, +-3080789, +-47011, +-3077832, +-47153, +-3074862, +-47297, +-3071901, +-47441, +-3068948, +-47584, +-3065983, +-47729, +-3063027, +-47874, +-3060079, +-48019, +-3057118, +-48165, +-3054167, +-48310, +-3051203, +-48457, +-3048268, +-48603, +-3045322, +-48750, +-3042363, +-48898, +-3039433, +-49045, +-3036492, +-49193, +-3033538, +-49343, +-3030614, +-49491, +-3027677, +-49640, +-3024729, +-49790, +-3021809, +-49939, +-3018878, +-50090, +-3015935, +-50241, +-3013021, +-50392, +-3010075, +-50544, +-3007157, +-50696, +-3004228, +-50848, +-3001308, +-51001, +-2998396, +-51153, +-2995472, +-51307, +-2992557, +-51461, +-2989651, +-51614, +-2986733, +-51769, +-2983823, +-51924, +-2980922, +-52079, +-2978010, +-52235, +-2975106, +-52391, +-2972192, +-52548, +-2969305, +-52704, +-2966387, +-52862, +-2963497, +-53019, +-2960597, +-53177, +-2957705, +-53335, +-2954802, +-53495, +-2951926, +-53653, +-2949020, +-53813, +-2946142, +-53973, +-2943254, +-54133, +-2940373, +-54294, +-2937482, +-54455, +-2934600, +-54617, +-2931725, +-54778, +-2928840, +-54941, +-2925964, +-55104, +-2923095, +-55266, +-2920217, +-55430, +-2917346, +-55594, +-2914484, +-55758, +-2911612, +-55923, +-2908748, +-56088, +-2905873, +-56254, +-2903025, +-56419, +-2900149, +-56586, +-2897300, +-56752, +-2894440, +-56920, +-2891588, +-57087, +-2888727, +-57255, +-2885874, +-57424, +-2883029, +-57592, +-2880174, +-57762, +-2877327, +-57931, +-2874489, +-58101, +-2871640, +-58271, +-2868800, +-58442, +-2865950, +-58614, +-2863126, +-58784, +-2860275, +-58957, +-2857450, +-59129, +-2854615, +-59302, +-2851788, +-59475, +-2848952, +-59649, +-2846123, +-59823, +-2843303, +-59997, +-2840474, +-60173, +-2837652, +-60348, +-2834822, +-60524, +-2831999, +-60701, +-2829185, +-60877, +-2826378, +-61053, +-2823562, +-61231, +-2820737, +-61410, +-2817938, +-61587, +-2815129, +-61766, +-2812311, +-61946, +-2809502, +-62125, +-2806700, +-62305, +-2803906, +-62485, +-2801103, +-62666, +-2798292, +-62848, +-2795505, +-63029, +-2792710, +-63211, +-2789906, +-63395, +-2787126, +-63576, +-2784321, +-63761, +-2781541, +-63945, +-2778752, +-64129, +-2775970, +-64312, +-2773181, +-64499, +-2770399, +-64685, +-2767625, +-64870, +-2764843, +-65057, +-2762068, +-65244, +-2759286, +-65432, +-2756511, +-65620, +-2753743, +-65808, +-2750968, +-65997, +-2748201, +-66186, +-2745441, +-66375, +-2742673, +-66565, +-2739912, +-66755, +-2737144, +-66947, +-2734384, +-67138, +-2731631, +-67330, +-2728870, +-67522, +-2726117, +-67715, +-2723357, +-67908, +-2720604, +-68102, +-2717858, +-68296, +-2715105, +-68491, +-2712359, +-68686, +-2709621, +-68881, +-2706876, +-69077, +-2704138, +-69273, +-2701392, +-69470, +-2698655, +-69667, +-2695924, +-69865, +-2693186, +-70063, +-2690456, +-70262, +-2687718, +-70461, +-2684988, +-70661, +-2682266, +-70860, +-2679536, +-71061, +-2676813, +-71262, +-2674098, +-71463, +-2671376, +-71665, +-2668647, +-71868, +-2665939, +-72070, +-2663211, +-72274, +-2660504, +-72477, +-2657790, +-72681, +-2655083, +-72886, +-2652370, +-73091, +-2649663, +-73297, +-2646950, +-73503, +-2644259, +-73709, +-2641546, +-73917, +-2638855, +-74124, +-2636158, +-74331, +-2633453, +-74540, +-2630756, +-74749, +-2628066, +-74958, +-2625369, +-75169, +-2622680, +-75379, +-2619998, +-75589, +-2617310, +-75801, +-2614614, +-76013, +-2611940, +-76225, +-2609260, +-76437, +-2606573, +-76651, +-2603893, +-76865, +-2601220, +-77079, +-2598541, +-77294, +-2595870, +-77509, +-2593191, +-77725, +-2590534, +-77940, +-2587857, +-78157, +-2585187, +-78375, +-2582524, +-78592, +-2579868, +-78809, +-2577206, +-79028, +-2574538, +-79248, +-2571877, +-79468, +-2569223, +-79687, +-2566577, +-79907, +-2563924, +-80128, +-2561265, +-80350, +-2558613, +-80573, +-2555969, +-80795, +-2553318, +-81018, +-2550675, +-81242, +-2548038, +-81465, +-2545396, +-81690, +-2542748, +-81915, +-2540119, +-82140, +-2537472, +-82367, +-2534845, +-82593, +-2532212, +-82820, +-2529574, +-83048, +-2526954, +-83275, +-2524317, +-83504, +-2521699, +-83733, +-2519076, +-83962, +-2516447, +-84193, +-2513825, +-84423, +-2511210, +-84654, +-2508589, +-84886, +-2505975, +-85118, +-2503356, +-85351, +-2500743, +-85584, +-2498138, +-85817, +-2495527, +-86051, +-2492911, +-86287, +-2490313, +-86521, +-2487711, +-86757, +-2485103, +-86994, +-2482502, +-87230, +-2479907, +-87467, +-2477308, +-87705, +-2474703, +-87944, +-2472117, +-88182, +-2469526, +-88421, +-2466929, +-88662, +-2464340, +-88902, +-2461757, +-89143, +-2459169, +-89384, +-2456587, +-89626, +-2454001, +-89869, +-2451422, +-90112, +-2448837, +-90356, +-2446259, +-90600, +-2443688, +-90844, +-2441112, +-91089, +-2438542, +-91335, +-2435968, +-91581, +-2433400, +-91828, +-2430828, +-92076, +-2428262, +-92324, +-2425702, +-92572, +-2423138, +-92821, +-2420581, +-93070, +-2418018, +-93320, +-2415463, +-93570, +-2412902, +-93822, +-2410349, +-94073, +-2407801, +-94325, +-2405249, +-94578, +-2402704, +-94831, +-2400154, +-95085, +-2397610, +-95339, +-2395062, +-95594, +-2392521, +-95849, +-2389975, +-96106, +-2387446, +-96361, +-2384902, +-96619, +-2382365, +-96877, +-2379833, +-97134, +-2377298, +-97393, +-2374769, +-97653, +-2372246, +-97912, +-2369719, +-98172, +-2367188, +-98433, +-2364663, +-98695, +-2362144, +-98957, +-2359621, +-99219, +-2357105, +-99482, +-2354584, +-99746, +-2352069, +-100010, +-2349551, +-100276, +-2347039, +-100541, +-2344533, +-100806, +-2342023, +-101073, +-2339519, +-101340, +-2337011, +-101608, +-2334509, +-101875, +-2332004, +-102145, +-2329504, +-102414, +-2327001, +-102684, +-2324504, +-102955, +-2322013, +-103225, +-2319518, +-103497, +-2317019, +-103770, +-2314536, +-104041, +-2312040, +-104316, +-2309559, +-104589, +-2307075, +-104863, +-2304587, +-105138, +-2302105, +-105414, +-2299620, +-105691, +-2297140, +-105967, +-2294667, +-106244, +-2292189, +-106522, +-2289718, +-106800, +-2287243, +-107080, +-2284775, +-107359, +-2282302, +-107640, +-2279836, +-107920, +-2277376, +-108201, +-2274912, +-108483, +-2272444, +-108766, +-2269982, +-109050, +-2267527, +-109333, +-2265068, +-109617, +-2262615, +-109902, +-2260158, +-110188, +-2257707, +-110474, +-2255253, +-110761, +-2252805, +-111048, +-2250353, +-111336, +-2247908, +-111625, +-2245468, +-111913, +-2243025, +-112203, +-2240587, +-112493, +-2238147, +-112784, +-2235702, +-113076, +-2233274, +-113367, +-2230832, +-113660, +-2228406, +-113953, +-2225976, +-114247, +-2223543, +-114541, +-2221116, +-114836, +-2218685, +-115133, +-2216261, +-115429, +-2213842, +-115725, +-2211420, +-116023, +-2209004, +-116320, +-2206584, +-116619, +-2204171, +-116918, +-2201754, +-117218, +-2199343, +-117519, +-2196929, +-117820, +-2194520, +-118122, +-2192109, +-118424, +-2189703, +-118727, +-2187303, +-119030, +-2184900, +-119334, +-2182494, +-119640, +-2180093, +-119945, +-2177698, +-120251, +-2175301, +-120558, +-2172909, +-120865, +-2170514, +-121173, +-2168124, +-121481, +-2165732, +-121790, +-2163345, +-122100, +-2160955, +-122411, +-2158571, +-122721, +-2156193, +-123032, +-2153812, +-123345, +-2151427, +-123658, +-2149049, +-123972, +-2146676, +-124285, +-2144300, +-124600, +-2141921, +-124916, +-2139557, +-125231, +-2137181, +-125548, +-2134811, +-125866, +-2132446, +-126183, +-2130078, +-126502, +-2127716, +-126820, +-2125360, +-127140, +-2123001, +-127460, +-2120639, +-127782, +-2118282, +-128104, +-2115923, +-128427, +-2113569, +-128750, +-2111221, +-129073, +-2108870, +-129397, +-2106525, +-129722, +-2104177, +-130047, +-2101826, +-130373, +-2099481, +-130701, +-2097141, +-131028, +-2094799, +-131357, +-2092461, +-131685, +-2090122, +-132015, +-2087788, +-132345, +-2085459, +-132675, +-2083120, +-133007, +-2080794, +-133338, +-2078466, +-133671, +-2076134, +-134005, +-2073808, +-134339, +-2071489, +-134673, +-2069166, +-135008, +-2066841, +-135344, +-2064521, +-135681, +-2062207, +-136018, +-2059890, +-136356, +-2057578, +-136694, +-2055264, +-137034, +-2052954, +-137373, +-2050644, +-137714, +-2048331, +-138056, +-2046030, +-138397, +-2043727, +-138739, +-2041421, +-139083, +-2039121, +-139426, +-2036819, +-139771, +-2034522, +-140116, +-2032222, +-140463, +-2029928, +-140809, +-2027639, +-141156, +-2025347, +-141504, +-2023054, +-141853, +-2020765, +-142202, +-2018482, +-142551, +-2016195, +-142902, +-2013907, +-143254, +-2011632, +-143605, +-2009348, +-143958, +-2007069, +-144312, +-2004794, +-144665, +-2002517, +-145020, +-2000246, +-145375, +-1997972, +-145731, +-1995703, +-146088, +-1993433, +-146445, +-1991167, +-146803, +-1988899, +-147162, +-1986636, +-147521, +-1984379, +-147881, +-1982112, +-148242, +-1979857, +-148603, +-1977600, +-148965, +-1975341, +-149329, +-1973087, +-149692, +-1970838, +-150056, +-1968587, +-150421, +-1966334, +-150787, +-1964086, +-151153, +-1961843, +-151520, +-1959598, +-151887, +-1957351, +-152256, +-1955109, +-152626, +-1952872, +-152995, +-1950633, +-153366, +-1948399, +-153736, +-1946163, +-154109, +-1943932, +-154481, +-1941699, +-154854, +-1939471, +-155228, +-1937241, +-155603, +-1935016, +-155978, +-1932789, +-156354, +-1930567, +-156731, +-1928342, +-157109, +-1926123, +-157487, +-1923902, +-157866, +-1921686, +-158246, +-1919475, +-158625, +-1917261, +-159006, +-1915046, +-159389, +-1912836, +-159771, +-1910631, +-160153, +-1908417, +-160539, +-1906215, +-160923, +-1904010, +-161308, +-1901811, +-161693, +-1899610, +-162080, +-1897407, +-162468, +-1895208, +-162857, +-1893015, +-163245, +-1890820, +-163635, +-1888629, +-164025, +-1886437, +-164416, +-1884243, +-164809, +-1882061, +-165200, +-1879870, +-165594, +-1877690, +-165987, +-1875502, +-166383, +-1873325, +-166777, +-1871140, +-167174, +-1868967, +-167570, +-1866785, +-167969, +-1864614, +-168367, +-1862442, +-168765, +-1860267, +-169166, +-1858098, +-169566, +-1855927, +-169968, +-1853760, +-170370, +-1851592, +-170773, +-1849429, +-171176, +-1847270, +-171580, +-1845110, +-171985, +-1842947, +-172391, +-1840790, +-172797, +-1838637, +-173204, +-1836483, +-173612, +-1834327, +-174021, +-1832175, +-174431, +-1830028, +-174840, +-1827880, +-175251, +-1825736, +-175663, +-1823591, +-176075, +-1821444, +-176489, +-1819307, +-176902, +-1817163, +-177317, +-1815024, +-177733, +-1812889, +-178149, +-1810753, +-178566, +-1808621, +-178983, +-1806487, +-179402, +-1804358, +-179821, +-1802228, +-180241, +-1800102, +-180661, +-1797975, +-181083, +-1795852, +-181505, +-1793733, +-181927, +-1791607, +-182352, +-1789492, +-182776, +-1787375, +-183201, +-1785257, +-183627, +-1783143, +-184054, +-1781033, +-184481, +-1778922, +-184909, +-1776810, +-185338, +-1774702, +-185768, +-1772598, +-186198, +-1770493, +-186630, +-1768387, +-187062, +-1766285, +-187495, +-1764187, +-187928, +-1762088, +-188363, +-1759988, +-188799, +-1757897, +-189234, +-1755800, +-189671, +-1753707, +-190109, +-1751618, +-190547, +-1749528, +-190986, +-1747442, +-191426, +-1745355, +-191867, +-1743272, +-192308, +-1741188, +-192750, +-1739108, +-193193, +-1737027, +-193637, +-1734950, +-194081, +-1732878, +-194526, +-1730804, +-194972, +-1728728, +-195419, +-1726657, +-195866, +-1724585, +-196315, +-1722517, +-196765, +-1720453, +-197214, +-1718388, +-197665, +-1716322, +-198117, +-1714260, +-198569, +-1712202, +-199022, +-1710143, +-199476, +-1708082, +-199931, +-1706026, +-200387, +-1703974, +-200843, +-1701921, +-201300, +-1699872, +-201758, +-1697821, +-202217, +-1695775, +-202676, +-1693728, +-203136, +-1691684, +-203597, +-1689640, +-204059, +-1687599, +-204522, +-1685558, +-204986, +-1683521, +-205450, +-1681482, +-205915, +-1679447, +-206381, +-1677417, +-206847, +-1675385, +-207314, +-1673353, +-207783, +-1671324, +-208252, +-1669294, +-208723, +-1667268, +-209194, +-1665247, +-209665, +-1663224, +-210137, +-1661205, +-210610, +-1659185, +-211084, +-1657164, +-211560, +-1655152, +-212034, +-1653134, +-212512, +-1651120, +-212989, +-1649110, +-213467, +-1647098, +-213946, +-1645091, +-214425, +-1643083, +-214906, +-1641078, +-215387, +-1639078, +-215869, +-1637071, +-216353, +-1635074, +-216836, +-1633075, +-217321, +-1631075, +-217807, +-1629080, +-218293, +-1627088, +-218779, +-1625095, +-219267, +-1623101, +-219757, +-1621111, +-220246, +-1619125, +-220736, +-1617137, +-221228, +-1615154, +-221720, +-1613170, +-222213, +-1611189, +-222706, +-1609208, +-223201, +-1607230, +-223696, +-1605252, +-224193, +-1603277, +-224690, +-1601301, +-225188, +-1599329, +-225687, +-1597361, +-226186, +-1595392, +-226686, +-1593422, +-227188, +-1591456, +-227690, +-1589493, +-228193, +-1587530, +-228696, +-1585565, +-229202, +-1583609, +-229706, +-1581648, +-230213, +-1579690, +-230721, +-1577736, +-231229, +-1575781, +-231738, +-1573829, +-232247, +-1571882, +-232757, +-1569934, +-233268, +-1567984, +-233781, +-1566038, +-234294, +-1564092, +-234809, +-1562149, +-235324, +-1560210, +-235839, +-1558270, +-236355, +-1556333, +-236872, +-1554396, +-237391, +-1552458, +-237911, +-1550528, +-238430, +-1548592, +-238952, +-1546665, +-239472, +-1544737, +-239995, +-1542808, +-240519, +-1540882, +-241043, +-1538956, +-241569, +-1537034, +-242094, +-1535115, +-242621, +-1533195, +-243149, +-1531279, +-243677, +-1529361, +-244206, +-1527443, +-244738, +-1525533, +-245268, +-1523618, +-245801, +-1521711, +-246333, +-1519803, +-246866, +-1517894, +-247402, +-1515989, +-247937, +-1514082, +-248474, +-1512180, +-249012, +-1510281, +-249549, +-1508381, +-250087, +-1506484, +-250628, +-1504587, +-251168, +-1502693, +-251710, +-1500799, +-252253, +-1498908, +-252796, +-1497016, +-253340, +-1495128, +-253886, +-1493243, +-254432, +-1491357, +-254979, +-1489471, +-255527, +-1487588, +-256076, +-1485708, +-256625, +-1483828, +-257176, +-1481951, +-257726, +-1480073, +-258280, +-1478199, +-258832, +-1476324, +-259388, +-1474453, +-259942, +-1472585, +-260498, +-1470716, +-261054, +-1468846, +-261612, +-1466984, +-262170, +-1465117, +-262731, +-1463257, +-263290, +-1461393, +-263852, +-1459536, +-264414, +-1457679, +-264976, +-1455820, +-265541, +-1453965, +-266106, +-1452114, +-266671, +-1450261, +-267238, +-1448412, +-267805, +-1446563, +-268374, +-1444716, +-268943, +-1442869, +-269513, +-1441025, +-270084, +-1439181, +-270657, +-1437339, +-271230, +-1435501, +-271803, +-1433663, +-272378, +-1431827, +-272954, +-1429991, +-273531, +-1428159, +-274108, +-1426325, +-274687, +-1424495, +-275266, +-1422668, +-275846, +-1420840, +-276427, +-1419012, +-277010, +-1417191, +-277592, +-1415365, +-278177, +-1413546, +-278761, +-1411727, +-279346, +-1409907, +-279934, +-1408090, +-280521, +-1406277, +-281109, +-1404462, +-281699, +-1402651, +-282289, +-1400840, +-282880, +-1399031, +-283472, +-1397222, +-284066, +-1395416, +-284660, +-1393613, +-285254, +-1391810, +-285850, +-1390009, +-286447, +-1388208, +-287045, +-1386410, +-287643, +-1384612, +-288244, +-1382816, +-288844, +-1381024, +-289445, +-1379231, +-290048, +-1377438, +-290652, +-1375651, +-291255, +-1373864, +-291860, +-1372076, +-292467, +-1370291, +-293074, +-1368509, +-293681, +-1366727, +-294291, +-1364944, +-294901, +-1363168, +-295511, +-1361391, +-296123, +-1359613, +-296736, +-1357839, +-297350, +-1356068, +-297964, +-1354296, +-298580, +-1352527, +-299196, +-1350757, +-299814, +-1348991, +-300432, +-1347224, +-301052, +-1345463, +-301671, +-1343699, +-302294, +-1341941, +-302915, +-1340178, +-303539, +-1338423, +-304162, +-1336666, +-304788, +-1334909, +-305414, +-1333159, +-306040, +-1331405, +-306669, +-1329657, +-307297, +-1327908, +-307927, +-1326159, +-308558, +-1324417, +-309189, +-1322670, +-309823, +-1320930, +-310455, +-1319185, +-311091, +-1317448, +-311726, +-1315709, +-312363, +-1313974, +-313000, +-1312237, +-313639, +-1310504, +-314278, +-1308771, +-314919, +-1307040, +-315560, +-1305312, +-316202, +-1303583, +-316846, +-1301858, +-317490, +-1300135, +-318134, +-1298412, +-318781, +-1296688, +-319429, +-1294970, +-320076, +-1293249, +-320726, +-1291533, +-321375, +-1289818, +-322026, +-1288105, +-322678, +-1286391, +-323331, +-1284680, +-323985, +-1282969, +-324641, +-1281261, +-325297, +-1279555, +-325953, +-1277849, +-326611, +-1276146, +-327270, +-1274442, +-327931, +-1272744, +-328590, +-1271043, +-329253, +-1269347, +-329915, +-1267648, +-330580, +-1265955, +-331244, +-1264261, +-331910, +-1262570, +-332576, +-1260878, +-333244, +-1259190, +-333913, +-1257504, +-334582, +-1255817, +-335253, +-1254133, +-335925, +-1252449, +-336598, +-1250767, +-337272, +-1249089, +-337946, +-1247409, +-338622, +-1245733, +-339298, +-1244059, +-339975, +-1242384, +-340654, +-1240709, +-341335, +-1239041, +-342014, +-1237371, +-342696, +-1235701, +-343379, +-1234037, +-344062, +-1232369, +-344748, +-1230707, +-345433, +-1229045, +-346119, +-1227385, +-346807, +-1225724, +-347496, +-1224067, +-348185, +-1222412, +-348875, +-1220756, +-349567, +-1219103, +-350260, +-1217450, +-350954, +-1215799, +-351649, +-1214151, +-352344, +-1212502, +-353042, +-1210856, +-353739, +-1209213, +-354437, +-1207569, +-355138, +-1205928, +-355838, +-1204290, +-356539, +-1202650, +-357242, +-1201014, +-357946, +-1199377, +-358651, +-1197742, +-359357, +-1196111, +-360064, +-1194478, +-360772, +-1192848, +-361481, +-1191221, +-362190, +-1189593, +-362901, +-1187968, +-363613, +-1186346, +-364326, +-1184723, +-365040, +-1183102, +-365755, +-1181481, +-366471, +-1179866, +-367187, +-1178247, +-367906, +-1176633, +-368625, +-1175019, +-369345, +-1173408, +-370066, +-1171796, +-370788, +-1170187, +-371512, +-1168580, +-372235, +-1166973, +-372961, +-1165368, +-373687, +-1163765, +-374414, +-1162163, +-375143, +-1160562, +-375872, +-1158964, +-376602, +-1157366, +-377334, +-1155770, +-378066, +-1154174, +-378801, +-1152580, +-379536, +-1150988, +-380271, +-1149399, +-381007, +-1147810, +-381745, +-1146223, +-382484, +-1144638, +-383223, +-1143053, +-383964, +-1141471, +-384706, +-1139887, +-385449, +-1138307, +-386193, +-1136729, +-386938, +-1135153, +-387684, +-1133576, +-388431, +-1132003, +-389179, +-1130428, +-389929, +-1128856, +-390679, +-1127286, +-391431, +-1125719, +-392182, +-1124152, +-392936, +-1122586, +-393690, +-1121024, +-394445, +-1119460, +-395202, +-1117899, +-395959, +-1116337, +-396719, +-1114781, +-397478, +-1113225, +-398238, +-1111667, +-399001, +-1110112, +-399764, +-1108560, +-400528, +-1107009, +-401293, +-1105459, +-402059, +-1103910, +-402827, +-1102364, +-403594, +-1100821, +-404363, +-1099277, +-405133, +-1097732, +-405906, +-1096192, +-406677, +-1094652, +-407451, +-1093114, +-408225, +-1091576, +-409002, +-1090043, +-409777, +-1088510, +-410555, +-1086975, +-411335, +-1085443, +-412115, +-1083914, +-412896, +-1082387, +-413678, +-1080859, +-414461, +-1079336, +-415244, +-1077810, +-416031, +-1076289, +-416816, +-1074768, +-417604, +-1073249, +-418392, +-1071729, +-419183, +-1070214, +-419972, +-1068699, +-420764, +-1067183, +-421558, +-1065673, +-422351, +-1064162, +-423146, +-1062653, +-423942, +-1061143, +-424740, +-1059636, +-425538, +-1058131, +-426337, +-1056628, +-427137, +-1055125, +-427939, +-1053624, +-428742, +-1052125, +-429545, +-1050625, +-430351, +-1049131, +-431155, +-1047633, +-431964, +-1046140, +-432771, +-1044647, +-433581, +-1043156, +-434391, +-1041666, +-435202, +-1040180, +-436013, +-1038693, +-436827, +-1037207, +-437642, +-1035725, +-438457, +-1034241, +-439274, +-1032759, +-440092, +-1031280, +-440911, +-1029801, +-441732, +-1028326, +-442552, +-1026851, +-443374, +-1025374, +-444199, +-1023903, +-445022, +-1022432, +-445848, +-1020963, +-446675, +-1019495, +-447502, +-1018027, +-448331, +-1016561, +-449162, +-1015098, +-449992, +-1013636, +-450824, +-1012173, +-451658, +-1010713, +-452492, +-1009255, +-453327, +-1007798, +-454165, +-1006343, +-455002, +-1004890, +-455840, +-1003438, +-456680, +-1001984, +-457522, +-1000534, +-458364, +-999086, +-459208, +-997639, +-460052, +-996195, +-460896, +-994750, +-461743, +-993307, +-462591, +-991866, +-463440, +-990424, +-464290, +-988985, +-465142, +-987548, +-465994, +-986113, +-466847, +-984679, +-467701, +-983246, +-468557, +-981814, +-469413, +-980384, +-470271, +-978954, +-471131, +-977525, +-471991, +-976102, +-472851, +-974675, +-473715, +-973253, +-474577, +-971830, +-475442, +-970409, +-476308, +-968990, +-477175, +-967574, +-478042, +-966156, +-478912, +-964743, +-479781, +-963327, +-480654, +-961916, +-481526, +-960506, +-482399, +-959096, +-483274, +-957688, +-484150, +-956282, +-485026, +-954876, +-485905, +-953474, +-486784, +-952071, +-487664, +-950670, +-488546, +-949271, +-489428, +-947872, +-490312, +-946474, +-491198, +-945079, +-492084, +-943685, +-492971, +-942293, +-493859, +-940901, +-494749, +-939511, +-495640, +-938122, +-496532, +-936736, +-497424, +-935351, +-498318, +-933966, +-499213, +-932583, +-500110, +-931201, +-501007, +-929822, +-501905, +-928442, +-502806, +-927064, +-503708, +-925690, +-504607, +-924313, +-505513, +-922940, +-506417, +-921570, +-507322, +-920198, +-508229, +-918829, +-509136, +-917461, +-510046, +-916096, +-510955, +-914729, +-511868, +-913365, +-512781, +-912005, +-513692, +-910642, +-514609, +-909283, +-515525, +-907926, +-516441, +-906568, +-517360, +-905212, +-518279, +-903858, +-519201, +-902506, +-520122, +-901156, +-521043, +-899805, +-521969, +-898456, +-522895, +-897108, +-523821, +-895763, +-524749, +-894419, +-525677, +-893075, +-526608, +-891735, +-527538, +-890394, +-528470, +-889055, +-529404, +-887718, +-530338, +-886380, +-531275, +-885046, +-532211, +-883712, +-533150, +-882380, +-534089, +-881049, +-535030, +-879720, +-535971, +-878393, +-536913, +-877065, +-537858, +-875739, +-538803, +-874415, +-539750, +-873092, +-540697, +-871772, +-541646, +-870453, +-542595, +-869133, +-543547, +-867817, +-544498, +-866501, +-545452, +-865187, +-546406, +-863874, +-547362, +-862560, +-548320, +-861251, +-549277, +-859941, +-550237, +-858633, +-551198, +-857326, +-552160, +-856021, +-553123, +-854718, +-554086, +-853417, +-555051, +-852115, +-556018, +-850817, +-556985, +-849518, +-557954, +-848221, +-558924, +-846926, +-559895, +-845630, +-560869, +-844338, +-561842, +-843047, +-562816, +-841756, +-563792, +-840467, +-564770, +-839179, +-565748, +-837893, +-566728, +-836609, +-567708, +-835326, +-568690, +-834043, +-569674, +-832763, +-570657, +-831483, +-571643, +-830205, +-572630, +-828928, +-573618, +-827653, +-574607, +-826379, +-575597, +-825105, +-576590, +-823835, +-577582, +-822564, +-578576, +-821297, +-579570, +-820029, +-580567, +-818763, +-581565, +-817498, +-582563, +-816235, +-583563, +-814971, +-584565, +-813712, +-585567, +-812451, +-586572, +-811195, +-587575, +-809937, +-588582, +-808681, +-589589, +-807427, +-590598, +-806175, +-591607, +-804924, +-592618, +-803674, +-593630, +-802424, +-594644, +-801178, +-595658, +-799931, +-596674, +-798688, +-597690, +-797444, +-598708, +-796201, +-599728, +-794961, +-600749, +-793721, +-601770, +-792484, +-602793, +-791245, +-603818, +-790011, +-604843, +-788777, +-605869, +-787544, +-606898, +-786311, +-607928, +-785083, +-608957, +-783853, +-609989, +-782626, +-611022, +-781399, +-612056, +-780175, +-613091, +-778951, +-614127, +-777729, +-615164, +-776507, +-616205, +-775288, +-617244, +-774069, +-618286, +-772853, +-619328, +-771636, +-620373, +-770424, +-621416, +-769210, +-622463, +-767998, +-623511, +-766787, +-624560, +-765578, +-625610, +-764370, +-626661, +-763164, +-627713, +-761959, +-628767, +-760754, +-629823, +-759552, +-630879, +-758352, +-631935, +-757150, +-632995, +-755953, +-634054, +-754755, +-635116, +-753558, +-636179, +-752364, +-637241, +-751170, +-638307, +-749978, +-639373, +-748787, +-640441, +-747597, +-641510, +-746409, +-642580, +-745222, +-643651, +-744036, +-644723, +-742852, +-645796, +-741670, +-646871, +-740488, +-647946, +-739308, +-649023, +-738128, +-650103, +-736951, +-651182, +-735773, +-652264, +-734599, +-653346, +-733426, +-654429, +-732252, +-655514, +-731082, +-656599, +-729911, +-657687, +-728741, +-658777, +-727575, +-659865, +-726408, +-660957, +-725243, +-662050, +-724079, +-663144, +-722918, +-664237, +-721757, +-665334, +-720596, +-666431, +-719438, +-667530, +-718280, +-668630, +-717124, +-669731, +-715970, +-670834, +-714816, +-671938, +-713664, +-673043, +-712514, +-674149, +-711364, +-675256, +-710216, +-676365, +-709069, +-677475, +-707924, +-678586, +-706780, +-679698, +-705637, +-680812, +-704495, +-681926, +-703355, +-683042, +-702214, +-684162, +-701077, +-685280, +-699940, +-686400, +-698805, +-687521, +-697671, +-688643, +-696539, +-689767, +-695406, +-690894, +-694276, +-692020, +-693147, +-693147, +-693147, +-693147, +-693147, +-693147, +-692020, +-694276, +-690894, +-695406, +-689767, +-696539, +-688643, +-697671, +-687521, +-698805, +-686400, +-699940, +-685280, +-701077, +-684162, +-702214, +-683042, +-703355, +-681926, +-704495, +-680812, +-705637, +-679698, +-706780, +-678586, +-707924, +-677475, +-709069, +-676365, +-710216, +-675256, +-711364, +-674149, +-712514, +-673043, +-713664, +-671938, +-714816, +-670834, +-715970, +-669731, +-717124, +-668630, +-718280, +-667530, +-719438, +-666431, +-720596, +-665334, +-721757, +-664237, +-722918, +-663144, +-724079, +-662050, +-725243, +-660957, +-726408, +-659865, +-727575, +-658777, +-728741, +-657687, +-729911, +-656599, +-731082, +-655514, +-732252, +-654429, +-733426, +-653346, +-734599, +-652264, +-735773, +-651182, +-736951, +-650103, +-738128, +-649023, +-739308, +-647946, +-740488, +-646871, +-741670, +-645796, +-742852, +-644723, +-744036, +-643651, +-745222, +-642580, +-746409, +-641510, +-747597, +-640441, +-748787, +-639373, +-749978, +-638307, +-751170, +-637241, +-752364, +-636179, +-753558, +-635116, +-754755, +-634054, +-755953, +-632995, +-757150, +-631935, +-758351, +-630879, +-759552, +-629823, +-760754, +-628767, +-761959, +-627713, +-763164, +-626661, +-764370, +-625610, +-765578, +-624560, +-766787, +-623511, +-767998, +-622463, +-769210, +-621416, +-770424, +-620373, +-771636, +-619328, +-772853, +-618286, +-774069, +-617244, +-775288, +-616205, +-776507, +-615164, +-777730, +-614127, +-778951, +-613091, +-780175, +-612056, +-781399, +-611022, +-782626, +-609989, +-783853, +-608957, +-785083, +-607928, +-786311, +-606898, +-787544, +-605869, +-788777, +-604843, +-790011, +-603818, +-791245, +-602793, +-792484, +-601770, +-793721, +-600749, +-794961, +-599728, +-796201, +-598708, +-797444, +-597690, +-798688, +-596674, +-799931, +-595658, +-801178, +-594644, +-802424, +-593630, +-803674, +-592618, +-804924, +-591607, +-806175, +-590598, +-807427, +-589589, +-808681, +-588582, +-809937, +-587575, +-811195, +-586572, +-812451, +-585567, +-813712, +-584565, +-814971, +-583563, +-816235, +-582563, +-817498, +-581565, +-818763, +-580567, +-820029, +-579570, +-821297, +-578576, +-822564, +-577582, +-823835, +-576590, +-825105, +-575597, +-826379, +-574607, +-827653, +-573618, +-828928, +-572630, +-830205, +-571643, +-831483, +-570657, +-832763, +-569674, +-834043, +-568690, +-835326, +-567708, +-836609, +-566728, +-837893, +-565748, +-839179, +-564770, +-840467, +-563792, +-841756, +-562816, +-843047, +-561842, +-844338, +-560869, +-845630, +-559895, +-846926, +-558924, +-848221, +-557954, +-849518, +-556985, +-850817, +-556018, +-852115, +-555051, +-853417, +-554086, +-854718, +-553123, +-856022, +-552160, +-857326, +-551198, +-858633, +-550237, +-859941, +-549277, +-861251, +-548320, +-862560, +-547362, +-863874, +-546406, +-865187, +-545452, +-866501, +-544498, +-867817, +-543547, +-869133, +-542595, +-870452, +-541646, +-871772, +-540697, +-873092, +-539750, +-874415, +-538803, +-875739, +-537858, +-877065, +-536913, +-878393, +-535971, +-879720, +-535030, +-881049, +-534089, +-882380, +-533150, +-883712, +-532211, +-885046, +-531275, +-886380, +-530338, +-887718, +-529404, +-889055, +-528470, +-890394, +-527538, +-891735, +-526608, +-893075, +-525677, +-894419, +-524749, +-895763, +-523821, +-897108, +-522895, +-898456, +-521969, +-899805, +-521043, +-901156, +-520122, +-902506, +-519201, +-903858, +-518279, +-905212, +-517360, +-906568, +-516441, +-907926, +-515525, +-909283, +-514609, +-910642, +-513692, +-912005, +-512781, +-913365, +-511868, +-914729, +-510955, +-916096, +-510046, +-917461, +-509136, +-918829, +-508229, +-920198, +-507322, +-921570, +-506417, +-922940, +-505513, +-924313, +-504607, +-925690, +-503708, +-927064, +-502806, +-928442, +-501905, +-929822, +-501007, +-931201, +-500110, +-932583, +-499213, +-933966, +-498318, +-935351, +-497424, +-936736, +-496532, +-938122, +-495640, +-939511, +-494749, +-940901, +-493859, +-942293, +-492971, +-943685, +-492084, +-945079, +-491198, +-946474, +-490312, +-947872, +-489428, +-949271, +-488546, +-950670, +-487664, +-952071, +-486784, +-953474, +-485905, +-954876, +-485026, +-956282, +-484150, +-957688, +-483274, +-959097, +-482399, +-960506, +-481526, +-961916, +-480654, +-963327, +-479781, +-964743, +-478912, +-966156, +-478042, +-967574, +-477175, +-968990, +-476308, +-970409, +-475442, +-971830, +-474577, +-973253, +-473714, +-974675, +-472851, +-976102, +-471991, +-977525, +-471131, +-978954, +-470271, +-980384, +-469413, +-981814, +-468557, +-983245, +-467701, +-984679, +-466847, +-986113, +-465994, +-987548, +-465142, +-988985, +-464290, +-990424, +-463440, +-991866, +-462591, +-993307, +-461743, +-994750, +-460896, +-996195, +-460052, +-997639, +-459208, +-999086, +-458364, +-1000534, +-457522, +-1001984, +-456680, +-1003438, +-455840, +-1004890, +-455002, +-1006343, +-454165, +-1007798, +-453327, +-1009255, +-452492, +-1010713, +-451658, +-1012173, +-450824, +-1013636, +-449992, +-1015098, +-449162, +-1016561, +-448331, +-1018027, +-447502, +-1019495, +-446675, +-1020963, +-445848, +-1022432, +-445022, +-1023903, +-444199, +-1025374, +-443374, +-1026851, +-442552, +-1028326, +-441732, +-1029801, +-440911, +-1031280, +-440092, +-1032759, +-439274, +-1034241, +-438457, +-1035725, +-437642, +-1037207, +-436827, +-1038693, +-436013, +-1040180, +-435202, +-1041666, +-434391, +-1043156, +-433581, +-1044647, +-432771, +-1046140, +-431964, +-1047633, +-431155, +-1049131, +-430351, +-1050625, +-429545, +-1052125, +-428742, +-1053624, +-427939, +-1055125, +-427137, +-1056628, +-426337, +-1058131, +-425538, +-1059636, +-424740, +-1061143, +-423942, +-1062653, +-423146, +-1064162, +-422351, +-1065673, +-421558, +-1067183, +-420764, +-1068699, +-419972, +-1070214, +-419183, +-1071729, +-418392, +-1073249, +-417604, +-1074768, +-416816, +-1076289, +-416031, +-1077810, +-415244, +-1079336, +-414461, +-1080859, +-413678, +-1082387, +-412896, +-1083914, +-412115, +-1085443, +-411335, +-1086975, +-410555, +-1088509, +-409777, +-1090043, +-409002, +-1091576, +-408225, +-1093114, +-407451, +-1094652, +-406677, +-1096192, +-405906, +-1097732, +-405133, +-1099277, +-404363, +-1100821, +-403594, +-1102364, +-402827, +-1103910, +-402059, +-1105459, +-401293, +-1107009, +-400528, +-1108560, +-399764, +-1110112, +-399001, +-1111667, +-398238, +-1113225, +-397478, +-1114781, +-396719, +-1116338, +-395959, +-1117899, +-395202, +-1119460, +-394445, +-1121024, +-393690, +-1122586, +-392936, +-1124152, +-392182, +-1125719, +-391431, +-1127286, +-390679, +-1128856, +-389929, +-1130428, +-389179, +-1132003, +-388431, +-1133577, +-387684, +-1135153, +-386938, +-1136729, +-386194, +-1138307, +-385449, +-1139888, +-384706, +-1141471, +-383964, +-1143053, +-383223, +-1144638, +-382484, +-1146223, +-381745, +-1147810, +-381007, +-1149399, +-380271, +-1150988, +-379536, +-1152580, +-378801, +-1154174, +-378066, +-1155770, +-377334, +-1157366, +-376602, +-1158964, +-375872, +-1160562, +-375143, +-1162163, +-374414, +-1163765, +-373687, +-1165368, +-372961, +-1166972, +-372235, +-1168580, +-371512, +-1170187, +-370788, +-1171796, +-370066, +-1173408, +-369345, +-1175019, +-368625, +-1176633, +-367906, +-1178247, +-367187, +-1179866, +-366471, +-1181481, +-365755, +-1183102, +-365040, +-1184723, +-364326, +-1186346, +-363613, +-1187968, +-362901, +-1189593, +-362190, +-1191221, +-361481, +-1192848, +-360772, +-1194478, +-360064, +-1196111, +-359357, +-1197742, +-358651, +-1199377, +-357946, +-1201014, +-357242, +-1202650, +-356539, +-1204290, +-355838, +-1205928, +-355138, +-1207569, +-354437, +-1209213, +-353739, +-1210857, +-353042, +-1212503, +-352344, +-1214151, +-351649, +-1215799, +-350954, +-1217450, +-350260, +-1219103, +-349567, +-1220756, +-348875, +-1222412, +-348185, +-1224067, +-347496, +-1225724, +-346807, +-1227385, +-346119, +-1229044, +-345433, +-1230707, +-344748, +-1232369, +-344062, +-1234037, +-343379, +-1235701, +-342696, +-1237371, +-342014, +-1239041, +-341335, +-1240709, +-340654, +-1242385, +-339975, +-1244059, +-339298, +-1245733, +-338622, +-1247409, +-337946, +-1249089, +-337272, +-1250768, +-336598, +-1252449, +-335925, +-1254133, +-335253, +-1255817, +-334582, +-1257504, +-333913, +-1259190, +-333244, +-1260878, +-332576, +-1262570, +-331910, +-1264261, +-331244, +-1265955, +-330580, +-1267648, +-329915, +-1269347, +-329253, +-1271043, +-328590, +-1272744, +-327931, +-1274442, +-327270, +-1276146, +-326611, +-1277849, +-325953, +-1279555, +-325297, +-1281261, +-324641, +-1282969, +-323985, +-1284680, +-323331, +-1286391, +-322678, +-1288105, +-322026, +-1289818, +-321375, +-1291533, +-320726, +-1293249, +-320076, +-1294970, +-319429, +-1296688, +-318781, +-1298412, +-318134, +-1300135, +-317490, +-1301858, +-316846, +-1303583, +-316202, +-1305312, +-315560, +-1307040, +-314919, +-1308771, +-314278, +-1310504, +-313639, +-1312237, +-313000, +-1313974, +-312363, +-1315709, +-311726, +-1317448, +-311091, +-1319185, +-310455, +-1320930, +-309823, +-1322670, +-309189, +-1324417, +-308558, +-1326159, +-307927, +-1327909, +-307297, +-1329657, +-306669, +-1331405, +-306040, +-1333159, +-305414, +-1334910, +-304788, +-1336666, +-304162, +-1338423, +-303539, +-1340178, +-302915, +-1341941, +-302294, +-1343699, +-301671, +-1345463, +-301052, +-1347224, +-300432, +-1348991, +-299814, +-1350757, +-299196, +-1352527, +-298580, +-1354296, +-297964, +-1356068, +-297350, +-1357839, +-296736, +-1359613, +-296123, +-1361391, +-295511, +-1363168, +-294901, +-1364944, +-294290, +-1366727, +-293681, +-1368509, +-293074, +-1370291, +-292467, +-1372076, +-291860, +-1373864, +-291255, +-1375651, +-290652, +-1377438, +-290048, +-1379231, +-289445, +-1381024, +-288844, +-1382816, +-288244, +-1384612, +-287643, +-1386410, +-287045, +-1388208, +-286447, +-1390009, +-285850, +-1391810, +-285254, +-1393613, +-284660, +-1395416, +-284066, +-1397222, +-283472, +-1399031, +-282880, +-1400840, +-282289, +-1402651, +-281699, +-1404462, +-281109, +-1406277, +-280521, +-1408090, +-279934, +-1409907, +-279346, +-1411727, +-278761, +-1413546, +-278177, +-1415365, +-277592, +-1417191, +-277010, +-1419012, +-276427, +-1420840, +-275846, +-1422668, +-275266, +-1424495, +-274687, +-1426325, +-274108, +-1428158, +-273531, +-1429991, +-272954, +-1431827, +-272378, +-1433663, +-271803, +-1435501, +-271230, +-1437339, +-270657, +-1439181, +-270084, +-1441025, +-269513, +-1442869, +-268943, +-1444716, +-268374, +-1446562, +-267805, +-1448412, +-267238, +-1450261, +-266671, +-1452114, +-266106, +-1453965, +-265541, +-1455820, +-264976, +-1457679, +-264414, +-1459536, +-263852, +-1461393, +-263290, +-1463257, +-262731, +-1465117, +-262170, +-1466984, +-261612, +-1468846, +-261054, +-1470716, +-260498, +-1472585, +-259942, +-1474453, +-259386, +-1476324, +-258832, +-1478199, +-258280, +-1480073, +-257726, +-1481951, +-257176, +-1483828, +-256625, +-1485708, +-256076, +-1487588, +-255527, +-1489471, +-254979, +-1491357, +-254432, +-1493243, +-253886, +-1495128, +-253340, +-1497016, +-252796, +-1498908, +-252253, +-1500799, +-251710, +-1502693, +-251168, +-1504587, +-250628, +-1506484, +-250087, +-1508381, +-249549, +-1510280, +-249012, +-1512180, +-248474, +-1514082, +-247937, +-1515988, +-247402, +-1517894, +-246866, +-1519803, +-246333, +-1521711, +-245801, +-1523618, +-245268, +-1525534, +-244738, +-1527443, +-244206, +-1529361, +-243677, +-1531279, +-243149, +-1533195, +-242621, +-1535115, +-242094, +-1537034, +-241568, +-1538956, +-241043, +-1540883, +-240519, +-1542808, +-239995, +-1544737, +-239472, +-1546665, +-238952, +-1548592, +-238430, +-1550528, +-237911, +-1552457, +-237391, +-1554396, +-236872, +-1556333, +-236355, +-1558270, +-235839, +-1560210, +-235324, +-1562149, +-234809, +-1564092, +-234294, +-1566038, +-233781, +-1567984, +-233268, +-1569934, +-232757, +-1571882, +-232247, +-1573829, +-231738, +-1575781, +-231229, +-1577736, +-230721, +-1579690, +-230214, +-1581648, +-229706, +-1583609, +-229202, +-1585565, +-228696, +-1587530, +-228193, +-1589493, +-227690, +-1591455, +-227188, +-1593422, +-226686, +-1595392, +-226186, +-1597361, +-225687, +-1599329, +-225188, +-1601301, +-224690, +-1603277, +-224193, +-1605252, +-223696, +-1607230, +-223201, +-1609208, +-222706, +-1611189, +-222213, +-1613170, +-221720, +-1615154, +-221228, +-1617137, +-220736, +-1619125, +-220246, +-1621111, +-219757, +-1623101, +-219267, +-1625095, +-218779, +-1627088, +-218293, +-1629080, +-217807, +-1631075, +-217321, +-1633075, +-216836, +-1635074, +-216353, +-1637071, +-215869, +-1639078, +-215387, +-1641078, +-214906, +-1643083, +-214425, +-1645091, +-213946, +-1647098, +-213467, +-1649110, +-212989, +-1651120, +-212512, +-1653134, +-212034, +-1655152, +-211560, +-1657164, +-211084, +-1659185, +-210610, +-1661205, +-210137, +-1663224, +-209665, +-1665247, +-209194, +-1667268, +-208723, +-1669294, +-208252, +-1671324, +-207783, +-1673353, +-207315, +-1675385, +-206847, +-1677417, +-206381, +-1679447, +-205915, +-1681482, +-205450, +-1683520, +-204986, +-1685558, +-204522, +-1687600, +-204059, +-1689640, +-203597, +-1691684, +-203136, +-1693728, +-202676, +-1695775, +-202217, +-1697821, +-201758, +-1699871, +-201300, +-1701921, +-200843, +-1703974, +-200387, +-1706026, +-199931, +-1708082, +-199476, +-1710143, +-199022, +-1712202, +-198569, +-1714260, +-198117, +-1716322, +-197665, +-1718388, +-197214, +-1720453, +-196765, +-1722517, +-196315, +-1724585, +-195867, +-1726657, +-195419, +-1728728, +-194972, +-1730803, +-194526, +-1732878, +-194081, +-1734950, +-193637, +-1737027, +-193193, +-1739108, +-192750, +-1741188, +-192308, +-1743272, +-191867, +-1745355, +-191426, +-1747442, +-190986, +-1749528, +-190547, +-1751618, +-190109, +-1753707, +-189671, +-1755800, +-189234, +-1757897, +-188799, +-1759987, +-188363, +-1762088, +-187928, +-1764187, +-187495, +-1766285, +-187062, +-1768387, +-186630, +-1770493, +-186198, +-1772598, +-185768, +-1774702, +-185338, +-1776810, +-184909, +-1778922, +-184481, +-1781033, +-184054, +-1783143, +-183627, +-1785257, +-183201, +-1787375, +-182776, +-1789492, +-182352, +-1791607, +-181927, +-1793733, +-181505, +-1795852, +-181083, +-1797975, +-180661, +-1800102, +-180241, +-1802228, +-179821, +-1804359, +-179402, +-1806487, +-178983, +-1808621, +-178566, +-1810753, +-178149, +-1812889, +-177733, +-1815024, +-177317, +-1817163, +-176902, +-1819308, +-176489, +-1821444, +-176075, +-1823591, +-175663, +-1825736, +-175251, +-1827880, +-174840, +-1830029, +-174431, +-1832175, +-174021, +-1834327, +-173612, +-1836483, +-173204, +-1838637, +-172797, +-1840790, +-172391, +-1842948, +-171985, +-1845110, +-171580, +-1847270, +-171176, +-1849429, +-170773, +-1851592, +-170370, +-1853760, +-169968, +-1855927, +-169566, +-1858098, +-169166, +-1860267, +-168765, +-1862442, +-168367, +-1864614, +-167969, +-1866785, +-167570, +-1868967, +-167174, +-1871140, +-166777, +-1873325, +-166383, +-1875502, +-165987, +-1877690, +-165594, +-1879870, +-165200, +-1882061, +-164809, +-1884243, +-164416, +-1886437, +-164025, +-1888630, +-163635, +-1890820, +-163245, +-1893015, +-162857, +-1895209, +-162468, +-1897407, +-162080, +-1899610, +-161693, +-1901811, +-161308, +-1904010, +-160923, +-1906215, +-160539, +-1908417, +-160154, +-1910631, +-159771, +-1912836, +-159389, +-1915046, +-159006, +-1917261, +-158625, +-1919475, +-158246, +-1921686, +-157866, +-1923902, +-157487, +-1926123, +-157109, +-1928342, +-156731, +-1930566, +-156354, +-1932789, +-155978, +-1935016, +-155603, +-1937241, +-155228, +-1939471, +-154854, +-1941699, +-154481, +-1943932, +-154109, +-1946163, +-153736, +-1948399, +-153366, +-1950633, +-152995, +-1952872, +-152626, +-1955109, +-152256, +-1957351, +-151887, +-1959599, +-151520, +-1961843, +-151153, +-1964086, +-150787, +-1966334, +-150421, +-1968587, +-150056, +-1970838, +-149692, +-1973087, +-149329, +-1975341, +-148965, +-1977600, +-148603, +-1979857, +-148242, +-1982112, +-147881, +-1984379, +-147521, +-1986636, +-147162, +-1988899, +-146803, +-1991167, +-146445, +-1993433, +-146088, +-1995703, +-145731, +-1997972, +-145375, +-2000246, +-145020, +-2002517, +-144665, +-2004794, +-144312, +-2007069, +-143958, +-2009348, +-143605, +-2011632, +-143254, +-2013907, +-142902, +-2016195, +-142551, +-2018482, +-142202, +-2020765, +-141853, +-2023053, +-141504, +-2025347, +-141156, +-2027639, +-140809, +-2029928, +-140463, +-2032222, +-140116, +-2034522, +-139771, +-2036819, +-139426, +-2039121, +-139083, +-2041421, +-138739, +-2043727, +-138397, +-2046030, +-138056, +-2048331, +-137714, +-2050644, +-137373, +-2052954, +-137034, +-2055264, +-136694, +-2057579, +-136356, +-2059890, +-136018, +-2062207, +-135681, +-2064522, +-135344, +-2066841, +-135008, +-2069167, +-134673, +-2071489, +-134339, +-2073808, +-134005, +-2076134, +-133671, +-2078466, +-133338, +-2080794, +-133007, +-2083120, +-132675, +-2085459, +-132345, +-2087789, +-132015, +-2090122, +-131685, +-2092461, +-131357, +-2094799, +-131028, +-2097141, +-130701, +-2099481, +-130373, +-2101826, +-130047, +-2104177, +-129722, +-2106525, +-129397, +-2108870, +-129073, +-2111221, +-128750, +-2113570, +-128427, +-2115923, +-128104, +-2118282, +-127782, +-2120639, +-127460, +-2123001, +-127140, +-2125360, +-126820, +-2127716, +-126502, +-2130078, +-126183, +-2132446, +-125866, +-2134811, +-125548, +-2137181, +-125231, +-2139557, +-124916, +-2141921, +-124600, +-2144300, +-124285, +-2146676, +-123971, +-2149049, +-123658, +-2151428, +-123345, +-2153812, +-123032, +-2156193, +-122721, +-2158571, +-122411, +-2160955, +-122100, +-2163345, +-121790, +-2165732, +-121481, +-2168124, +-121173, +-2170514, +-120865, +-2172909, +-120558, +-2175300, +-120251, +-2177699, +-119945, +-2180093, +-119640, +-2182494, +-119334, +-2184900, +-119030, +-2187303, +-118727, +-2189703, +-118424, +-2192109, +-118122, +-2194520, +-117820, +-2196929, +-117519, +-2199343, +-117218, +-2201754, +-116918, +-2204170, +-116619, +-2206584, +-116320, +-2209004, +-116023, +-2211420, +-115725, +-2213842, +-115429, +-2216261, +-115133, +-2218685, +-114836, +-2221115, +-114541, +-2223543, +-114247, +-2225976, +-113953, +-2228406, +-113660, +-2230832, +-113367, +-2233273, +-113076, +-2235702, +-112784, +-2238146, +-112493, +-2240587, +-112203, +-2243025, +-111913, +-2245468, +-111625, +-2247907, +-111336, +-2250353, +-111048, +-2252805, +-110761, +-2255253, +-110474, +-2257707, +-110188, +-2260158, +-109902, +-2262615, +-109617, +-2265068, +-109333, +-2267527, +-109050, +-2269983, +-108766, +-2272444, +-108483, +-2274912, +-108201, +-2277375, +-107920, +-2279836, +-107640, +-2282302, +-107359, +-2284775, +-107080, +-2287243, +-106800, +-2289718, +-106522, +-2292189, +-106244, +-2294667, +-105967, +-2297140, +-105691, +-2299620, +-105414, +-2302105, +-105138, +-2304587, +-104863, +-2307075, +-104589, +-2309560, +-104315, +-2312040, +-104041, +-2314536, +-103770, +-2317019, +-103497, +-2319517, +-103225, +-2322013, +-102955, +-2324503, +-102684, +-2327001, +-102414, +-2329504, +-102145, +-2332004, +-101876, +-2334509, +-101608, +-2337011, +-101340, +-2339519, +-101073, +-2342023, +-100806, +-2344533, +-100541, +-2347039, +-100276, +-2349551, +-100010, +-2352070, +-99746, +-2354584, +-99482, +-2357104, +-99219, +-2359621, +-98957, +-2362144, +-98695, +-2364662, +-98433, +-2367188, +-98172, +-2369719, +-97912, +-2372246, +-97653, +-2374769, +-97393, +-2377298, +-97134, +-2379833, +-96877, +-2382364, +-96619, +-2384902, +-96361, +-2387446, +-96106, +-2389975, +-95849, +-2392521, +-95594, +-2395063, +-95339, +-2397610, +-95085, +-2400154, +-94831, +-2402704, +-94578, +-2405249, +-94325, +-2407801, +-94073, +-2410348, +-93822, +-2412902, +-93570, +-2415462, +-93320, +-2418019, +-93070, +-2420581, +-92821, +-2423138, +-92572, +-2425703, +-92324, +-2428261, +-92076, +-2430828, +-91828, +-2433400, +-91581, +-2435968, +-91335, +-2438542, +-91090, +-2441111, +-90844, +-2443688, +-90600, +-2446259, +-90356, +-2448837, +-90112, +-2451422, +-89869, +-2454001, +-89626, +-2456588, +-89384, +-2459168, +-89143, +-2461757, +-88902, +-2464340, +-88662, +-2466929, +-88421, +-2469525, +-88182, +-2472117, +-87944, +-2474703, +-87705, +-2477308, +-87467, +-2479907, +-87230, +-2482502, +-86994, +-2485103, +-86757, +-2487710, +-86521, +-2490313, +-86287, +-2492910, +-86051, +-2495527, +-85817, +-2498138, +-85584, +-2500744, +-85351, +-2503356, +-85118, +-2505975, +-84886, +-2508589, +-84654, +-2511209, +-84423, +-2513825, +-84193, +-2516447, +-83962, +-2519076, +-83733, +-2521700, +-83504, +-2524317, +-83275, +-2526954, +-83048, +-2529573, +-82820, +-2532212, +-82593, +-2534845, +-82367, +-2537473, +-82140, +-2540119, +-81915, +-2542748, +-81690, +-2545396, +-81465, +-2548039, +-81241, +-2550675, +-81018, +-2553318, +-80795, +-2555969, +-80573, +-2558613, +-80350, +-2561265, +-80128, +-2563924, +-79907, +-2566576, +-79687, +-2569223, +-79468, +-2571877, +-79248, +-2574538, +-79028, +-2577206, +-78809, +-2579868, +-78592, +-2582524, +-78375, +-2585187, +-78157, +-2587857, +-77940, +-2590534, +-77725, +-2593191, +-77509, +-2595869, +-77294, +-2598541, +-77079, +-2601220, +-76865, +-2603893, +-76651, +-2606573, +-76437, +-2609259, +-76225, +-2611941, +-76013, +-2614615, +-75801, +-2617310, +-75589, +-2619998, +-75379, +-2622680, +-75169, +-2625369, +-74958, +-2628066, +-74749, +-2630756, +-74540, +-2633453, +-74331, +-2636157, +-74124, +-2638855, +-73917, +-2641547, +-73709, +-2644259, +-73503, +-2646950, +-73297, +-2649663, +-73091, +-2652370, +-72886, +-2655083, +-72681, +-2657790, +-72477, +-2660503, +-72274, +-2663210, +-72070, +-2665939, +-71868, +-2668647, +-71665, +-2671376, +-71463, +-2674098, +-71262, +-2676814, +-71061, +-2679536, +-70860, +-2682265, +-70661, +-2684988, +-70461, +-2687718, +-70262, +-2690456, +-70063, +-2693187, +-69865, +-2695924, +-69667, +-2698654, +-69470, +-2701392, +-69273, +-2704137, +-69077, +-2706876, +-68881, +-2709621, +-68686, +-2712359, +-68491, +-2715105, +-68296, +-2717858, +-68102, +-2720604, +-67908, +-2723357, +-67715, +-2726117, +-67522, +-2728870, +-67330, +-2731631, +-67138, +-2734384, +-66947, +-2737144, +-66755, +-2739912, +-66565, +-2742673, +-66375, +-2745440, +-66186, +-2748201, +-65997, +-2750968, +-65808, +-2753744, +-65620, +-2756511, +-65432, +-2759285, +-65244, +-2762068, +-65057, +-2764843, +-64870, +-2767625, +-64685, +-2770400, +-64499, +-2773181, +-64312, +-2775970, +-64129, +-2778751, +-63945, +-2781541, +-63761, +-2784322, +-63576, +-2787126, +-63395, +-2789906, +-63211, +-2792710, +-63029, +-2795506, +-62848, +-2798293, +-62666, +-2801104, +-62485, +-2803906, +-62305, +-2806700, +-62125, +-2809501, +-61946, +-2812312, +-61766, +-2815129, +-61587, +-2817938, +-61410, +-2820737, +-61231, +-2823562, +-61053, +-2826378, +-60877, +-2829185, +-60701, +-2831999, +-60524, +-2834822, +-60348, +-2837652, +-60173, +-2840473, +-59997, +-2843303, +-59823, +-2846123, +-59649, +-2848951, +-59475, +-2851788, +-59302, +-2854614, +-59129, +-2857450, +-58957, +-2860275, +-58784, +-2863127, +-58614, +-2865951, +-58442, +-2868800, +-58271, +-2871640, +-58101, +-2874489, +-57931, +-2877327, +-57762, +-2880174, +-57592, +-2883029, +-57424, +-2885874, +-57255, +-2888727, +-57087, +-2891589, +-56920, +-2894440, +-56752, +-2897299, +-56586, +-2900149, +-56419, +-2903025, +-56254, +-2905874, +-56088, +-2908748, +-55923, +-2911612, +-55758, +-2914484, +-55594, +-2917346, +-55430, +-2920217, +-55266, +-2923095, +-55104, +-2925964, +-54941, +-2928840, +-54778, +-2931726, +-54617, +-2934599, +-54455, +-2937482, +-54294, +-2940373, +-54133, +-2943253, +-53973, +-2946143, +-53813, +-2949021, +-53653, +-2951926, +-53495, +-2954802, +-53335, +-2957705, +-53177, +-2960597, +-53019, +-2963497, +-52862, +-2966387, +-52704, +-2969305, +-52548, +-2972192, +-52391, +-2975106, +-52235, +-2978010, +-52079, +-2980922, +-51924, +-2983824, +-51769, +-2986733, +-51614, +-2989651, +-51461, +-2992558, +-51307, +-2995472, +-51153, +-2998396, +-51001, +-3001307, +-50848, +-3004228, +-50696, +-3007158, +-50544, +-3010075, +-50392, +-3013021, +-50241, +-3015934, +-50090, +-3018878, +-49940, +-3021809, +-49790, +-3024729, +-49640, +-3027677, +-49491, +-3030613, +-49343, +-3033538, +-49193, +-3036491, +-49045, +-3039434, +-48898, +-3042363, +-48750, +-3045321, +-48603, +-3048268, +-48457, +-3051203, +-48310, +-3054167, +-48165, +-3057118, +-48019, +-3060079, +-47874, +-3063026, +-47729, +-3065984, +-47584, +-3068949, +-47441, +-3071901, +-47297, +-3074862, +-47153, +-3077832, +-47011, +-3080789, +-46868, +-3083756, +-46726, +-3086729, +-46583, +-3089713, +-46442, +-3092684, +-46301, +-3095663, +-46160, +-3098629, +-46020, +-3101604, +-45880, +-3104587, +-45740, +-3107559, +-45600, +-3110560, +-45461, +-3113548, +-45323, +-3116523, +-45185, +-3119505, +-45047, +-3122498, +-44908, +-3125500, +-44771, +-3128486, +-44634, +-3131483, +-44497, +-3134489, +-44362, +-3137480, +-44226, +-3140481, +-44090, +-3143490, +-43955, +-3146485, +-43820, +-3149490, +-43685, +-3152503, +-43552, +-3155502, +-43417, +-3158534, +-43284, +-3161527, +-43151, +-3164554, +-43018, +-3167566, +-42886, +-3170585, +-42753, +-3173616, +-42622, +-3176631, +-42490, +-3179655, +-42359, +-3182689, +-42228, +-3185707, +-42098, +-3188735, +-41967, +-3191771, +-41838, +-3194794, +-41709, +-3197824, +-41580, +-3200864, +-41450, +-3203914, +-41322, +-3206947, +-41194, +-3209991, +-41067, +-3213018, +-40939, +-3216079, +-40812, +-3219126, +-40686, +-3222156, +-40558, +-3225221, +-40432, +-3228270, +-40308, +-3231302, +-40182, +-3234370, +-40057, +-3237422, +-39932, +-3240483, +-39807, +-3243553, +-39683, +-3246607, +-39559, +-3249670, +-39435, +-3252743, +-39313, +-3255799, +-39190, +-3258865, +-39067, +-3261940, +-38945, +-3265024, +-38823, +-3268092, +-38701, +-3271169, +-38581, +-3274229, +-38459, +-3277326, +-38339, +-3280406, +-38218, +-3283495, +-38099, +-3286566, +-37979, +-3289646, +-37860, +-3292738, +-37740, +-3295837, +-37622, +-3298921, +-37504, +-3302012, +-37385, +-3305115, +-37268, +-3308199, +-37151, +-3311293, +-37033, +-3314397, +-36916, +-3317508, +-36800, +-3320603, +-36684, +-3323708, +-36567, +-3326824, +-36452, +-3329919, +-36336, +-3333053, +-36222, +-3336140, +-36107, +-3339266, +-35993, +-3342372, +-35879, +-3345489, +-35765, +-3348614, +-35651, +-3351751, +-35538, +-3354867, +-35425, +-3357994, +-35313, +-3361102, +-35200, +-3364249, +-35088, +-3367377, +-34977, +-3370514, +-34866, +-3373631, +-34755, +-3376759, +-34644, +-3379896, +-34533, +-3383043, +-34424, +-3386172, +-34313, +-3389338, +-34204, +-3392455, +-34095, +-3395614, +-33986, +-3398750, +-33877, +-3401898, +-33769, +-3405056, +-33660, +-3408222, +-33553, +-3411369, +-33445, +-3414526, +-33338, +-3417693, +-33231, +-3420840, +-33125, +-3423996, +-33018, +-3427162, +-32912, +-3430338, +-32806, +-3433493, +-32701, +-3436658, +-32595, +-3439835, +-32489, +-3443020, +-32385, +-3446183, +-32280, +-3449359, +-32176, +-3452542, +-32074, +-3455706, +-31971, +-3458880, +-31867, +-3462063, +-31764, +-3465255, +-31662, +-3468427, +-31558, +-3471641, +-31457, +-3474833, +-31355, +-3478003, +-31253, +-3481215, +-31152, +-3484405, +-31051, +-3487605, +-30951, +-3490783, +-30850, +-3494004, +-30750, +-3497201, +-30650, +-3500411, +-30551, +-3503595, +-30451, +-3506825, +-30352, +-3510030, +-30254, +-3513213, +-30155, +-3516440, +-30057, +-3519644, +-29959, +-3522856, +-29861, +-3526080, +-29764, +-3529315, +-29667, +-3532525, +-29570, +-3535746, +-29473, +-3538977, +-29377, +-3542186, +-29280, +-3545438, +-29185, +-3548666, +-29089, +-3551904, +-28994, +-3555119, +-28900, +-3558342, +-28805, +-3561578, +-28710, +-3564822, +-28616, +-3568079, +-28522, +-3571309, +-28428, +-3574551, +-28335, +-3577803, +-28241, +-3581067, +-28148, +-3584304, +-28056, +-3587552, +-27963, +-3590808, +-27872, +-3594043, +-27779, +-3597323, +-27688, +-3600576, +-27596, +-3603840, +-27506, +-3607078, +-27414, +-3610365, +-27324, +-3613624, +-27234, +-3616893, +-27144, +-3620137, +-27054, +-3623428, +-26964, +-3626694, +-26875, +-3629970, +-26786, +-3633255, +-26697, +-3636515, +-26609, +-3639785, +-26521, +-3643066, +-26432, +-3646358, +-26344, +-3649658, +-26257, +-3652932, +-26169, +-3656220, +-26082, +-3659516, +-25995, +-3662823, +-25909, +-3666101, +-25823, +-3669390, +-25736, +-3672690, +-25650, +-3676003, +-25565, +-3679285, +-25480, +-3682580, +-25395, +-3685883, +-25310, +-3689200, +-25225, +-3692487, +-25140, +-3695823, +-25056, +-3699132, +-24972, +-3702452, +-24889, +-3705740, +-24805, +-3709082, +-24722, +-3712393, +-24639, +-3715716, +-24557, +-3719008, +-24474, +-3722353, +-24392, +-3725667, +-24310, +-3728994, +-24228, +-3732330, +-24146, +-3735678, +-24065, +-3738994, +-23984, +-3742323, +-23903, +-3745661, +-23822, +-3749013, +-23743, +-3752330, +-23663, +-3755661, +-23583, +-3759000, +-23503, +-3762354, +-23423, +-3765718, +-23344, +-3769050, +-23266, +-3772391, +-23187, +-3775745, +-23108, +-3779110, +-23029, +-3782487, +-22951, +-3785831, +-22874, +-3789186, +-22796, +-3792552, +-22719, +-3795885, +-22641, +-3799274, +-22565, +-3802631, +-22488, +-3805998, +-22411, +-3809375, +-22336, +-3812721, +-22259, +-3816122, +-22183, +-3819490, +-22108, +-3822868, +-22032, +-3826259, +-21957, +-3829613, +-21882, +-3833027, +-21807, +-3836406, +-21732, +-3839794, +-21659, +-3843149, +-21584, +-3846563, +-21511, +-3849940, +-21437, +-3853330, +-21364, +-3856730, +-21290, +-3860143, +-21218, +-3863518, +-21145, +-3866905, +-21073, +-3870304, +-21000, +-3873717, +-20927, +-3877139, +-20856, +-3880524, +-20784, +-3883923, +-20713, +-3887330, +-20642, +-3890749, +-20570, +-3894183, +-20500, +-3897579, +-20429, +-3900984, +-20358, +-3904453, +-20288, +-3907831, +-20218, +-3911273, +-20149, +-3914677, +-20078, +-3918143, +-20009, +-3921567, +-19941, +-3924955, +-19871, +-3928406, +-19803, +-3931817, +-19733, +-3935291, +-19665, +-3938726, +-19597, +-3942172, +-19529, +-3945581, +-19461, +-3949051, +-19394, +-3952480, +-19327, +-3955922, +-19259, +-3959378, +-19192, +-3962843, +-19126, +-3966267, +-19059, +-3969705, +-18993, +-3973153, +-18927, +-3976615, +-18861, +-3980086, +-18795, +-3983573, +-18729, +-3987017, +-18664, +-3990470, +-18599, +-3993938, +-18534, +-3997418, +-18470, +-4000854, +-18404, +-4004359, +-18340, +-4007818, +-18276, +-4011292, +-18212, +-4014776, +-18148, +-4018274, +-18085, +-4021727, +-18021, +-4025191, +-17958, +-4028669, +-17895, +-4032158, +-17832, +-4035659, +-17769, +-4039176, +-17707, +-4042644, +-17645, +-4046124, +-17583, +-4049620, +-17521, +-4053124, +-17459, +-4056644, +-17397, +-4060116, +-17336, +-4063602, +-17275, +-4067100, +-17214, +-4070608, +-17153, +-4074131, +-17092, +-4077666, +-17032, +-4081151, +-16972, +-4084651, +-16912, +-4088163, +-16852, +-4091688, +-16792, +-4095226, +-16733, +-4098715, +-16674, +-4102216, +-16614, +-4105790, +-16555, +-4109315, +-16497, +-4112793, +-16438, +-4116344, +-16379, +-4119849, +-16320, +-4123425, +-16264, +-4126951, +-16206, +-4130489, +-16149, +-4133981, +-16091, +-4137544, +-16034, +-4141060, +-15976, +-4144649, +-15919, +-4148187, +-15862, +-4151741, +-15806, +-4155242, +-15749, +-4158818, +-15692, +-4162345, +-15637, +-4165946, +-15581, +-4169498, +-15526, +-4172996, +-15470, +-4176574, +-15414, +-4180164, +-15359, +-4183702, +-15304, +-4187251, +-15250, +-4190813, +-15195, +-4194388, +-15140, +-4197975, +-15085, +-4201575, +-15031, +-4205121, +-14978, +-4208679, +-14924, +-4212250, +-14870, +-4215833, +-14816, +-4219430, +-14763, +-4222974, +-14710, +-4226596, +-14657, +-4230166, +-14604, +-4233745, +-14551, +-4237336, +-14499, +-4240945, +-14447, +-4244492, +-14394, +-4248126, +-14342, +-4251699, +-14291, +-4255288, +-14239, +-4258890, +-14187, +-4262501, +-14135, +-4266130, +-14085, +-4269699, +-14033, +-4273350, +-13982, +-4276945, +-13932, +-4280553, +-13881, +-4284174, +-13831, +-4287734, +-13781, +-4291382, +-13731, +-4294968, +-13680, +-4298642, +-13630, +-4302255, +-13581, +-4305880, +-13531, +-4309519, +-13482, +-4313100, +-13433, +-4316765, +-13384, +-4320368, +-13336, +-4323983, +-13287, +-4327616, +-13238, +-4331258, +-13190, +-4334913, +-13141, +-4338582, +-13093, +-4342191, +-13046, +-4345813, +-12998, +-4349443, +-12950, +-4353091, +-12903, +-4356748, +-12855, +-4360423, +-12808, +-4364107, +-12761, +-4367730, +-12714, +-4371365, +-12668, +-4375009, +-12621, +-4378672, +-12575, +-4382347, +-12528, +-4386036, +-12483, +-4389657, +-12436, +-4393369, +-12390, +-4397017, +-12345, +-4400678, +-12299, +-4404353, +-12254, +-4408041, +-12209, +-4411659, +-12164, +-4415374, +-12119, +-4419024, +-12074, +-4422767, +-12029, +-4426439, +-11985, +-4430125, +-11940, +-4433824, +-11896, +-4437457, +-11852, +-4441183, +-11808, +-4444837, +-11765, +-4448510, +-11720, +-4452278, +-11677, +-4455973, +-11634, +-4459599, +-11591, +-4463322, +-11547, +-4467063, +-11505, +-4470724, +-11462, +-4474405, +-11419, +-4478183, +-11376, +-4481890, +-11334, +-4485612, +-11292, +-4489257, +-11250, +-4493001, +-11209, +-4496674, +-11166, +-4500451, +-11125, +-4504151, +-11083, +-4507865, +-11042, +-4511587, +-11000, +-4515328, +-10959, +-4519084, +-10918, +-4522760, +-10877, +-4526543, +-10837, +-4530247, +-10796, +-4533965, +-10756, +-4537697, +-10715, +-4541442, +-10675, +-4545207, +-10635, +-4548885, +-10595, +-4552673, +-10556, +-4556379, +-10515, +-4560195, +-10476, +-4563934, +-10436, +-4567682, +-10397, +-4571444, +-10358, +-4575127, +-10319, +-4578917, +-10280, +-4582722, +-10241, +-4586447, +-10203, +-4590180, +-10164, +-4593933, +-10126, +-4597701, +-10088, +-4601477, +-10049, +-4605272, +-10011, +-4609077, +-9974, +-4612800, +-9936, +-4616537, +-9898, +-4620384, +-9860, +-4624149, +-9823, +-4627929, +-9786, +-4631717, +-9749, +-4635420, +-9712, +-4639243, +-9675, +-4643080, +-9638, +-4646826, +-9602, +-4650587, +-9566, +-4654361, +-9528, +-4658257, +-9493, +-4661953, +-9457, +-4665771, +-9420, +-4669603, +-9384, +-4673450, +-9349, +-4677203, +-9313, +-4680971, +-9277, +-4684862, +-9242, +-4688658, +-9206, +-4692475, +-9172, +-4696189, +-9137, +-4700029, +-9101, +-4703883, +-9067, +-4707647, +-9032, +-4711531, +-8997, +-4715317, +-8963, +-4719124, +-8929, +-4722939, +-8894, +-4726775, +-8860, +-4730619, +-8826, +-4734485, +-8793, +-4738243, +-8758, +-4742138, +-8725, +-4745925, +-8691, +-4749851, +-8657, +-4753667, +-8624, +-4757506, +-8591, +-4761358, +-8558, +-4765219, +-8525, +-4768983, +-8492, +-4772880, +-8460, +-4776672, +-8426, +-4780593, +-8394, +-4784415, +-8362, +-4788251, +-8330, +-4792102, +-8297, +-4795969, +-8265, +-4799850, +-8233, +-4803746, +-8202, +-4807533, +-8168, +-4811460, +-8137, +-4815277, +-8106, +-4819234, +-8074, +-4823080, +-8043, +-4826942, +-8012, +-4830818, +-7981, +-4834710, +-7951, +-4838489, +-7919, +-4842410, +-7887, +-4846347, +-7858, +-4850178, +-7827, +-4854146, +-7796, +-4857999, +-7766, +-4861867, +-7736, +-4865758, +-7706, +-4869656, +-7675, +-4873569, +-7646, +-4877373, +-7616, +-4881317, +-7586, +-4885284, +-7556, +-4889125, +-7527, +-4892988, +-7497, +-4896994, +-7468, +-4900888, +-7439, +-4904789, +-7409, +-4908714, +-7380, +-4912646, +-7352, +-4916463, +-7323, +-4920425, +-7295, +-4924273, +-7265, +-4928274, +-7237, +-4932144, +-7209, +-4936036, +-7180, +-4940085, +-7151, +-4944009, +-7123, +-4947940, +-7096, +-4951751, +-7068, +-4955720, +-7040, +-4959706, +-7013, +-4963562, +-6984, +-4967579, +-6957, +-4971466, +-6929, +-4975507, +-6902, +-4979425, +-6875, +-4983358, +-6847, +-4987307, +-6820, +-4991272, +-6793, +-4995252, +-6767, +-4999098, +-6740, +-5003110, +-6713, +-5006995, +-6686, +-5011039, +-6660, +-5014946, +-6634, +-5018869, +-6607, +-5022961, +-6581, +-5026915, +-6554, +-5030885, +-6528, +-5034880, +-6503, +-5038725, +-6477, +-5042743, +-6451, +-5046785, +-6426, +-5050677, +-6399, +-5054743, +-6374, +-5058675, +-6349, +-5062613, +-6324, +-5066567, +-6299, +-5070546, +-6274, +-5074531, +-6248, +-5078542, +-6223, +-5082560, +-6198, +-5086603, +-6174, +-5090488, +-6149, +-5094564, +-6125, +-5098480, +-6100, +-5102589, +-6075, +-5106537, +-6051, +-5110510, +-6027, +-5114500, +-6002, +-5118665, +-5979, +-5122517, +-5955, +-5126555, +-5931, +-5130599, +-5906, +-5134669, +-5883, +-5138584, +-5859, +-5142687, +-5836, +-5146623, +-5812, +-5150759, +-5789, +-5154738, +-5766, +-5158732, +-5742, +-5162742, +-5719, +-5166768, +-5696, +-5170800, +-5673, +-5174859, +-5650, +-5178934, +-5627, +-5183026, +-5605, +-5186953, +-5582, +-5191078, +-5559, +-5195038, +-5536, +-5199196, +-5514, +-5203188, +-5492, +-5207196, +-5470, +-5211220, +-5448, +-5215260, +-5426, +-5219316, +-5404, +-5223400, +-5381, +-5227490, +-5359, +-5231596, +-5338, +-5235529, +-5316, +-5239669, +-5294, +-5243826, +-5273, +-5247819, +-5252, +-5251816, +-5230, +-5256024, +-5209, +-5260054, +-5187, +-5264113, +-5166, +-5268176, +-5145, +-5272256, +-5124, +-5276364, +-5103, +-5280478, +-5083, +-5284420, +-5062, +-5288567, +-5041, +-5292731, +-5021, +-5296722, +-4999, +-5300920, +-4979, +-5304944, +-4959, +-5308973, +-4939, +-5313029, +-4918, +-5317297, +-4898, +-5321387, +-4878, +-5325482, +-4858, +-5329606, +-4839, +-5333525, +-4819, +-5337683, +-4799, +-5341846, +-4778, +-5346038, +-4759, +-5350035, +-4739, +-5354249, +-4720, +-5358279, +-4701, +-5362325, +-4681, +-5366591, +-4662, +-5370671, +-4643, +-5374767, +-4624, +-5378881, +-4605, +-5382998, +-4586, +-5387145, +-4566, +-5391310, +-4547, +-5395492, +-4529, +-5399468, +-4510, +-5403684, +-4491, +-5407905, +-4473, +-5411930, +-4454, +-5416200, +-4436, +-5420258, +-4418, +-5424334, +-4400, +-5428426, +-4381, +-5432766, +-4362, +-5436893, +-4344, +-5441037, +-4326, +-5445198, +-4308, +-5449376, +-4291, +-5453336, +-4273, +-5457548, +-4255, +-5461779, +-4237, +-5466027, +-4220, +-5470053, +-4202, +-5474337, +-4185, +-5478396, +-4167, +-5482716, +-4150, +-5486824, +-4133, +-5490935, +-4115, +-5495063, +-4098, +-5499208, +-4081, +-5503370, +-4064, +-5507564, +-4047, +-5511761, +-4029, +-5515975, +-4013, +-5520208, +-3996, +-5524459, +-3980, +-5528487, +-3963, +-5532773, +-3946, +-5537077, +-3930, +-5541157, +-3913, +-5545498, +-3897, +-5549597, +-3881, +-5553728, +-3864, +-5557861, +-3847, +-5562275, +-3831, +-5566459, +-3815, +-5570646, +-3799, +-5574865, +-3783, +-5579086, +-3767, +-5583342, +-3752, +-5587328, +-3736, +-5591619, +-3720, +-5595912, +-3704, +-5600240, +-3689, +-5604294, +-3673, +-5608659, +-3658, +-5612748, +-3642, +-5617149, +-3627, +-5621273, +-3612, +-5625431, +-3596, +-5629606, +-3580, +-5634066, +-3565, +-5638278, +-3550, +-5642507, +-3535, +-5646737, +-3520, +-5651003, +-3505, +-5655286, +-3491, +-5659280, +-3476, +-5663600, +-3461, +-5667938, +-3446, +-5672277, +-3432, +-5676357, +-3417, +-5680751, +-3403, +-5684866, +-3388, +-5689280, +-3374, +-5693430, +-3360, +-5697598, +-3345, +-5702086, +-3331, +-5706290, +-3316, +-5710512, +-3302, +-5714751, +-3288, +-5718990, +-3274, +-5723266, +-3260, +-5727560, +-3246, +-5731873, +-3232, +-5736204, +-3218, +-5740554, +-3204, +-5744923, +-3191, +-5748993, +-3177, +-5753399, +-3164, +-5757504, +-3150, +-5761948, +-3137, +-5766088, +-3123, +-5770570, +-3110, +-5774746, +-3096, +-5779268, +-3083, +-5783480, +-3070, +-5787711, +-3057, +-5791959, +-3044, +-5796226, +-3031, +-5800511, +-3018, +-5804814, +-3005, +-5809136, +-2991, +-5813477, +-2978, +-5817856, +-2965, +-5822235, +-2952, +-5826633, +-2940, +-5830705, +-2927, +-5835141, +-2914, +-5839596, +-2902, +-5843742, +-2889, +-5848236, +-2877, +-5852397, +-2864, +-5856930, +-2852, +-5861128, +-2840, +-5865365, +-2827, +-5869957, +-2815, +-5874210, +-2803, +-5878502, +-2791, +-5882792, +-2779, +-5887100, +-2767, +-5891448, +-2755, +-5895793, +-2743, +-5900158, +-2731, +-5904563, +-2719, +-5908966, +-2707, +-5913389, +-2696, +-5917477, +-2684, +-5921937, +-2672, +-5926417, +-2661, +-5930559, +-2649, +-5935078, +-2636, +-5939641, +-2625, +-5943815, +-2614, +-5948029, +-2602, +-5952628, +-2591, +-5956880, +-2579, +-5961520, +-2568, +-5965787, +-2557, +-5970095, +-2546, +-5974422, +-2535, +-5978744, +-2524, +-5983108, +-2513, +-5987468, +-2502, +-5991871, +-2491, +-5996269, +-2480, +-6000711, +-2469, +-6005149, +-2458, +-6009630, +-2447, +-6014107, +-2437, +-6018213, +-2426, +-6022754, +-2415, +-6027290, +-2405, +-6031450, +-2394, +-6036052, +-2384, +-6040223, +-2373, +-6044865, +-2363, +-6049099, +-2352, +-6053757, +-2342, +-6058029, +-2332, +-6062320, +-2321, +-6067040, +-2311, +-6071369, +-2301, +-6075717, +-2291, +-6080084, +-2281, +-6084470, +-2271, +-6088850, +-2260, +-6093723, +-2251, +-6097719, +-2240, +-6102184, +-2231, +-6106641, +-2220, +-6111146, +-2210, +-6115671, +-2200, +-6120216, +-2190, +-6124755, +-2181, +-6128877, +-2171, +-6133483, +-2161, +-6138110, +-2152, +-6142288, +-2142, +-6146956, +-2133, +-6151171, +-2123, +-6155881, +-2114, +-6160133, +-2104, +-6164858, +-2095, +-6169149, +-2086, +-6173458, +-2076, +-6178275, +-2067, +-6182624, +-2058, +-6186992, +-2049, +-6191379, +-2040, +-6195785, +-2030, +-6200211, +-2022, +-6204657, +-2012, +-6209627, +-2003, +-6214114, +-1994, +-6218114, +-1986, +-6222640, +-1977, +-6227187, +-1968, +-6231754, +-1958, +-6236343, +-1950, +-6240953, +-1942, +-6245061, +-1933, +-6249711, +-1924, +-6254383, +-1916, +-6258547, +-1907, +-6263261, +-1898, +-6267996, +-1890, +-6272249, +-1881, +-6277028, +-1873, +-6281288, +-1865, +-6285566, +-1856, +-6290408, +-1848, +-6294726, +-1839, +-6299613, +-1831, +-6303971, +-1823, +-6308380, +-1815, +-6312775, +-1807, +-6317191, +-1798, +-6322189, +-1790, +-6326646, +-1782, +-6331157, +-1774, +-6335654, +-1766, +-6340172, +-1758, +-6344710, +-1750, +-6349268, +-1741, +-6353882, +-1733, +-6358483, +-1727, +-6362518, +-1718, +-6367193, +-1710, +-6371856, +-1702, +-6376541, +-1694, +-6381247, +-1687, +-6385410, +-1679, +-6390159, +-1671, +-6394930, +-1664, +-6399115, +-1656, +-6403965, +-1649, +-6408187, +-1641, +-6413046, +-1634, +-6417344, +-1626, +-6422247, +-1619, +-6426547, +-1612, +-6430904, +-1604, +-6435874, +-1597, +-6440271, +-1590, +-6444650, +-1582, +-6449689, +-1575, +-6454148, +-1568, +-6458588, +-1561, +-6463087, +-1554, +-6467567, +-1547, +-6472068, +-1539, +-6477286, +-1532, +-6481831, +-1525, +-6486435, +-1518, +-6491022, +-1511, +-6495630, +-1504, +-6500298, +-1498, +-6504312, +-1491, +-6508981, +-1484, +-6513673, +-1477, +-6518426, +-1470, +-6523162, +-1464, +-6527269, +-1457, +-6532047, +-1450, +-6536889, +-1443, +-6541714, +-1437, +-6545897, +-1430, +-6550765, +-1424, +-6554987, +-1417, +-6559900, +-1410, +-6564879, +-1404, +-6569161, +-1398, +-6573418, +-1391, +-6578466, +-1385, +-6582763, +-1378, +-6587858, +-1372, +-6592196, +-1365, +-6597339, +-1359, +-6601762, +-1353, +-6606161, +-1347, +-6610624, +-1340, +-6615819, +-1334, +-6620325, +-1328, +-6624851, +-1322, +-6629353, +-1316, +-6633920, +-1310, +-6638509, +-1304, +-6643073, +-1297, +-6648485, +-1291, +-6653095, +-1285, +-6657773, +-1279, +-6662472, +-1274, +-6666397, +-1268, +-6671091, +-1262, +-6675854, +-1256, +-6680639, +-1250, +-6685400, +-1244, +-6690231, +-1238, +-6695086, +-1233, +-6699094, +-1227, +-6703992, +-1221, +-6708914, +-1215, +-6713812, +-1210, +-6717945, +-1204, +-6722936, +-1198, +-6727953, +-1193, +-6732145, +-1187, +-6737158, +-1182, +-6741388, +-1176, +-6746499, +-1171, +-6750769, +-1165, +-6755877, +-1160, +-6760187, +-1154, +-6765395, +-1149, +-6769747, +-1143, +-6774952, +-1138, +-6779346, +-1133, +-6783759, +-1127, +-6789091, +-1122, +-6793548, +-1117, +-6798024, +-1112, +-6802521, +-1106, +-6807900, +-1101, +-6812442, +-1096, +-6817004, +-1091, +-6821587, +-1086, +-6826191, +-1081, +-6830816, +-1075, +-6836350, +-1070, +-6841023, +-1065, +-6845718, +-1060, +-6850434, +-1055, +-6855173, +-1050, +-6859935, +-1045, +-6864719, +-1040, +-6869469, +-1035, +-6874300, +-1031, +-6878169, +-1026, +-6883042, +-1021, +-6887939, +-1016, +-6892859, +-1011, +-6897804, +-1005, +-6902774, +-1002, +-6906755, +-995, +-6911770, +-990, +-6916809, +-985, +-6921874, +-982, +-6925933, +-977, +-6931045, +-972, +-6936183, +-968, +-6940300, +-963, +-6945486, +-959, +-6949641, +-954, +-6954876, +-949, +-6960075, +-945, +-6964355, +-940, +-6969604, +-936, +-6973925, +-931, +-6979225, +-927, +-6983588, +-923, +-6987905, +-918, +-6993345, +-914, +-6997704, +-909, +-7003198, +-905, +-7007601, +-901, +-7012023, +-896, +-7017596, +-892, +-7022063, +-888, +-7026550, +-884, +-7031057, +-879, +-7036737, +-875, +-7041291, +-871, +-7045866, +-867, +-7050461, +-863, +-7055078, +-858, +-7060896, +-854, +-7065561, +-850, +-7070249, +-846, +-7074958, +-842, +-7079760, +-838, +-7084514, +-834, +-7089291, +-830, +-7094091, +-826, +-7098914, +-822, +-7103761, +-818, +-7108631, +-814, +-7113525, +-810, +-7118443, +-806, +-7123459, +-802, +-7128426, +-798, +-7133418, +-794, +-7138435, +-791, +-7142196, +-787, +-7147257, +-783, +-7152344, +-779, +-7157534, +-775, +-7162674, +-772, +-7166527, +-768, +-7171713, +-764, +-7176927, +-760, +-7182167, +-757, +-7186175, +-753, +-7191465, +-749, +-7196782, +-746, +-7200769, +-742, +-7206137, +-739, +-7210242, +-735, +-7215661, +-731, +-7221109, +-728, +-7225194, +-724, +-7230695, +-721, +-7234902, +-717, +-7240457, +-714, +-7244622, +-710, +-7250231, +-707, +-7254521, +-703, +-7260186, +-700, +-7264435, +-696, +-7270156, +-693, +-7274447, +-690, +-7278843, +-686, +-7284648, +-683, +-7289002, +-680, +-7293375, +-676, +-7299353, +-673, +-7303771, +-670, +-7308209, +-666, +-7314187, +-663, +-7318762, +-660, +-7323267, +-657, +-7327793, +-653, +-7333890, +-650, +-7338556, +-647, +-7343151, +-644, +-7347768, +-641, +-7352499, +-637, +-7358749, +-634, +-7363439, +-631, +-7368245, +-628, +-7372979, +-625, +-7377736, +-622, +-7382612, +-619, +-7387415, +-616, +-7392241, +-613, +-7397188, +-610, +-7402062, +-607, +-7406959, +-604, +-7411980, +-601, +-7416926, +-598, +-7421897, +-595, +-7426994, +-592, +-7432015, +-589, +-7437062, +-586, +-7442236, +-583, +-7447335, +-580, +-7452460, +-577, +-7457715, +-574, +-7462894, +-572, +-7466327, +-569, +-7471655, +-566, +-7476906, +-563, +-7482186, +-560, +-7487599, +-558, +-7491118, +-555, +-7496581, +-552, +-7501965, +-549, +-7507379, +-547, +-7511077, +-544, +-7516540, +-541, +-7522143, +-538, +-7527668, +-536, +-7531331, +-533, +-7537018, +-530, +-7542625, +-528, +-7546456, +-525, +-7552117, +-522, +-7557809, +-520, +-7561699, +-517, +-7567447, +-515, +-7571374, +-512, +-7577178, +-510, +-7581144, +-506, +-7587005, +-504, +-7592901, +-501, +-7596930, +-499, +-7602884, +-497, +-7606954, +-494, +-7612968, +-492, +-7617079, +-488, +-7623155, +-487, +-7627186, +-485, +-7631355, +-482, +-7637519, +-480, +-7641732, +-477, +-7647961, +-475, +-7652218, +-472, +-7658512, +-470, +-7662815, +-468, +-7667009, +-465, +-7673525, +-463, +-7677764, +-461, +-7682151, +-458, +-7688637, +-456, +-7693071, +-454, +-7697394, +-451, +-7703980, +-449, +-7708484, +-447, +-7713007, +-445, +-7717418, +-442, +-7724137, +-440, +-7728732, +-438, +-7733349, +-436, +-7737850, +-434, +-7742509, +-431, +-7749400, +-429, +-7754113, +-427, +-7758709, +-425, +-7763466, +-423, +-7768105, +-420, +-7775317, +-418, +-7780011, +-416, +-7784871, +-414, +-7789611, +-412, +-7794518, +-410, +-7799304, +-408, +-7804259, +-406, +-7809091, +-404, +-7814095, +-402, +-7819124, +-400, +-7824029, +-398, +-7829108, +-396, +-7834063, +-393, +-7841769, +-391, +-7846786, +-389, +-7851983, +-387, +-7857052, +-385, +-7862303, +-384, +-7864938, +-382, +-7870074, +-380, +-7875393, +-378, +-7880583, +-376, +-7885958, +-374, +-7891204, +-372, +-7896637, +-370, +-7901938, +-368, +-7907430, +-366, +-7912952, +-364, +-7918341, +-362, +-7923924, +-361, +-7926562, +-359, +-7932192, +-357, +-7937853, +-355, +-7943378, +-353, +-7949103, +-351, +-7954691, +-350, +-7957582, +-348, +-7963389, +-346, +-7969057, +-344, +-7974932, +-342, +-7980666, +-341, +-7983633, +-339, +-7989594, +-337, +-7995414, +-335, +-8001445, +-334, +-8004296, +-332, +-8010382, +-330, +-8016505, +-329, +-8019399, +-327, +-8025577, +-325, +-8031611, +-324, +-8034734, +-322, +-8041008, +-320, +-8047135, +-319, +-8050307, +-317, +-8056680, +-315, +-8062904, +-314, +-8066126, +-312, +-8072601, +-310, +-8078925, +-309, +-8082200, +-307, +-8088585, +-306, +-8091892, +-304, +-8098537, +-302, +-8105028, +-301, +-8108389, +-299, +-8115144, +-298, +-8118339, +-296, +-8125162, +-295, +-8128591, +-293, +-8135282, +-292, +-8138745, +-290, +-8145709, +-289, +-8149005, +-287, +-8156041, +-286, +-8159578, +-284, +-8166480, +-283, +-8170054, +-281, +-8177239, +-280, +-8180640, +-278, +-8187904, +-277, +-8191554, +-275, +-8198682, +-274, +-8202373, +-272, +-8209797, +-271, +-8213309, +-270, +-8217055, +-268, +-8224589, +-267, +-8228154, +-265, +-8235772, +-264, +-8239603, +-262, +-8247082, +-261, +-8250957, +-260, +-8254846, +-258, +-8262440, +-257, +-8266375, +-256, +-8270325, +-254, +-8278273, +-253, +-8282035, +-252, +-8286047, +-250, +-8294122, +-248, +-8297943, +-248, +-8302021, +-246, +-8310226, +-245, +-8314354, +-244, +-8318255, +-243, +-8322416, +-241, +-8330790, +-240, +-8334754, +-239, +-8338986, +-237, +-8347500, +-236, +-8351786, +-235, +-8355835, +-234, +-8360156, +-232, +-8368854, +-231, +-8372973, +-230, +-8377369, +-229, +-8381784, +-228, +-8386219, +-226, +-8394883, +-225, +-8399377, +-224, +-8403890, +-223, +-8408424, +-222, +-8412710, +-220, +-8421880, +-219, +-8426496, +-218, +-8431134, +-217, +-8435519, +-216, +-8440199, +-215, +-8444901, +-214, +-8449625, +-212, +-8458860, +-211, +-8463650, +-210, +-8468464, +-209, +-8473301, +-208, +-8477875, +-207, +-8482758, +-206, +-8487665, +-205, +-8492596, +-203, +-8502238, +-202, +-8507242, +-201, +-8512271, +-200, +-8517325, +-199, +-8522106, +-198, +-8527210, +-197, +-8532341, +-196, +-8537498, +-195, +-8542376, +-194, +-8547585, +-193, +-8552821, +-192, +-8558085, +-191, +-8563377, +-190, +-8568383, +-189, +-8573730, +-188, +-8579106, +-187, +-8584510, +-186, +-8589624, +-185, +-8595085, +-184, +-8600577, +-183, +-8606099, +-182, +-8611652, +-181, +-8616907, +-180, +-8622520, +-179, +-8628165, +-178, +-8633842, +-177, +-8639215, +-176, +-8644955, +-175, +-8650729, +-174, +-8656536, +-173, +-8662377, +-172, +-8667906, +-171, +-8673814, +-170, +-8679757, +-169, +-8685735, +-169, +-8685735, +-168, +-8691395, +-167, +-8697444, +-166, +-8703529, +-165, +-8709652, +-164, +-8715813, +-163, +-8721646, +-162, +-8727881, +-161, +-8734155, +-160, +-8740469, +-160, +-8740469, +-159, +-8746448, +-158, +-8752840, +-157, +-8759273, +-156, +-8765748, +-155, +-8772266, +-154, +-8778438, +-154, +-8778438, +-153, +-8785039, +-152, +-8791684, +-151, +-8798373, +-150, +-8804709, +-150, +-8804709, +-149, +-8811486, +-148, +-8818310, +-147, +-8825180, +-146, +-8832097, +-145, +-8838652, +-145, +-8838652, +-144, +-8845664, +-143, +-8852725, +-142, +-8859837, +-142, +-8859837, +-141, +-8866576, +-140, +-8873787, +-139, +-8881051, +-138, +-8888367, +-138, +-8888367, +-137, +-8895738, +-136, +-8902725, +-135, +-8910202, +-135, +-8910202, +-134, +-8917736, +-133, +-8925327, +-133, +-8925327, +-132, +-8932525, +-131, +-8940229, +-130, +-8947994, +-130, +-8947994, +-129, +-8955819, +-128, +-8963706, +-128, +-8963706, +-127, +-8971186, +-126, +-8979195, +-125, +-8987269, +-125, +-8987269, +-124, +-8995409, +-123, +-9003131, +-123, +-9003131, +-122, +-9011402, +-121, +-9019741, +-121, +-9019741, +-120, +-9028151, +-119, +-9036632, +-119, +-9036632, +-118, +-9044680, +-117, +-9053303, +-117, +-9053303, +-116, +-9062001, +-115, +-9070775, +-115, +-9070775, +-114, +-9079104, +-114, +-9079104, +-113, +-9088031, +-112, +-9097037, +-112, +-9097037, +-111, +-9106126, +-110, +-9115298, +-110, +-9115298, +-109, +-9124008, +-109, +-9124008, +-108, +-9133346, +-107, +-9142772, +-107, +-9142772, +-106, +-9152288, +-106, +-9152288, +-105, +-9161328, +-104, +-9171022, +-104, +-9171022, +-103, +-9180812, +-103, +-9180812, +-102, +-9190699, +-102, +-9190699, +-101, +-9200684, +-100, +-9210174, +-100, +-9210174, +-99, +-9220357, +-99, +-9220357, +-98, +-9230645, +-98, +-9230645, +-97, +-9241039, +-97, +-9241039, +-96, +-9250922, +-95, +-9261530, +-95, +-9261530, +-94, +-9272253, +-94, +-9272253, +-93, +-9283091, +-93, +-9283091, +-92, +-9293401, +-92, +-9293401, +-91, +-9304472, +-91, +-9304472, +-90, +-9315667, +-90, +-9315667, +-89, +-9326990, +-89, +-9326990, +-88, +-9338441, +-88, +-9338441, +-87, +-9349341, +-87, +-9349341, +-86, +-9361053, +-86, +-9361053, +-85, +-9372904, +-85, +-9372904, +-84, +-9384897, +-84, +-9384897, +-83, +-9396317, +-83, +-9396317, +-82, +-9408596, +-82, +-9408596, +-82, +-9408596, +-81, +-9421028, +-81, +-9421028, +-80, +-9433616, +-80, +-9433616, +-79, +-9446365, +-79, +-9446365, +-78, +-9458514, +-78, +-9458514, +-77, +-9471586, +-77, +-9471586, +-77, +-9471586, +-76, +-9484831, +-76, +-9484831, +-75, +-9498254, +-75, +-9498254, +-74, +-9511054, +-74, +-9511054, +-74, +-9511054, +-73, +-9524836, +-73, +-9524836, +-72, +-9538811, +-72, +-9538811, +-72, +-9538811, +-71, +-9552984, +-71, +-9552984, +-70, +-9567360, +-70, +-9567360, +-70, +-9567360, +-69, +-9581083, +-69, +-9581083, +-68, +-9595872, +-68, +-9595872, +-68, +-9595872, +-67, +-9610883, +-67, +-9610883, +-66, +-9626123, +-66, +-9626123, +-66, +-9626123, +-65, +-9640682, +-65, +-9640682, +-65, +-9640682, +-64, +-9656387, +-64, +-9656387, +-63, +-9672342, +-63, +-9672342, +-63, +-9672342, +-62, +-9688556, +-62, +-9688556, +-62, +-9688556, +-61, +-9705038, +-61, +-9705038, +-61, +-9705038, +-60, +-9720801, +-60, +-9720801, +-60, +-9720801, +-59, +-9737827, +-59, +-9737827, +-59, +-9737827, +-58, +-9755148, +-58, +-9755148, +-57, +-9772774, +-57, +-9772774, +-57, +-9772774, +-57, +-9772774, +-56, +-9789652, +-56, +-9789652, +-56, +-9789652, +-55, +-9807903, +-55, +-9807903, +-55, +-9807903, +-54, +-9826493, +-54, +-9826493, +-54, +-9826493, +-53, +-9845435, +-53, +-9845435, +-53, +-9845435, +-52, +-9864743, +-52, +-9864743, +-52, +-9864743, +-51, +-9883262, +-51, +-9883262, +-51, +-9883262, +-51, +-9883262, +-50, +-9903322, +-50, +-9903322, +-50, +-9903322, +-49, +-9923792, +-49, +-9923792, +-49, +-9923792, +-49, +-9923792, +-48, +-9944690, +-48, +-9944690, +-48, +-9944690, +-47, +-9964766, +-47, +-9964766, +-47, +-9964766, +-47, +-9964766, +-46, +-9986548, +-46, +-9986548, +-46, +-9986548, +-46, +-9986548, +-45, +-10008815, +-45, +-10008815, +-45, +-10008815, +-44, +-10031589, +-44, +-10031589, +-44, +-10031589, +-44, +-10031589, +-43, +-10054893, +-43, +-10054893, +-43, +-10054893, +-43, +-10054893, +-42, +-10077335, +-42, +-10077335, +-42, +-10077335, +-42, +-10077335, +-41, +-10101743, +-41, +-10101743, +-41, +-10101743, +-41, +-10101743, +-41, +-10101743, +-40, +-10126763, +-40, +-10126763, +-40, +-10126763, +-40, +-10126763, +-39, +-10152425, +-39, +-10152425, +-39, +-10152425, +-39, +-10152425, +-38, +-10177194, +-38, +-10177194, +-38, +-10177194, +-38, +-10177194, +-38, +-10177194, +-37, +-10204201, +-37, +-10204201, +-37, +-10204201, +-37, +-10204201, +-36, +-10231958, +-36, +-10231958, +-36, +-10231958, +-36, +-10231958, +-36, +-10231958, +-35, +-10260508, +-35, +-10260508, +-35, +-10260508, +-35, +-10260508, +-35, +-10260508, +-34, +-10289896, +-34, +-10289896, +-34, +-10289896, +-34, +-10289896, +-33, +-10318368, +-33, +-10318368, +-33, +-10318368, +-33, +-10318368, +-33, +-10318368, +-33, +-10318368, +-32, +-10349534, +-32, +-10349534, +-32, +-10349534, +-32, +-10349534, +-32, +-10349534, +-31, +-10381704, +-31, +-10381704, +-31, +-10381704, +-31, +-10381704, +-31, +-10381704, +-30, +-10414942, +-30, +-10414942, +-30, +-10414942, +-30, +-10414942, +-30, +-10414942, +-30, +-10414942, +-29, +-10447268, +-29, +-10447268, +-29, +-10447268, +-29, +-10447268, +-29, +-10447268, +-28, +-10482800, +-28, +-10482800, +-28, +-10482800, +-28, +-10482800, +-28, +-10482800, +-28, +-10482800, +-28, +-10482800, +-27, +-10519640, +-27, +-10519640, +-27, +-10519640, +-27, +-10519640, +-27, +-10519640, +-27, +-10519640, +-26, +-10557890, +-26, +-10557890, +-26, +-10557890, +-26, +-10557890, +-26, +-10557890, +-26, +-10557890, +-25, +-10597661, +-25, +-10597661, +-25, +-10597661, +-25, +-10597661, +-25, +-10597661, +-25, +-10597661, +-25, +-10597661, +-24, +-10636596, +-24, +-10636596, +-24, +-10636596, +-24, +-10636596, +-24, +-10636596, +-24, +-10636596, +-23, +-10679695, +-23, +-10679695, +-23, +-10679695, +-23, +-10679695, +-23, +-10679695, +-23, +-10679695, +-23, +-10679695, +-23, +-10679695, +-22, +-10724736, +-22, +-10724736, +-22, +-10724736, +-22, +-10724736, +-22, +-10724736, +-22, +-10724736, +-22, +-10724736, +-21, +-10771901, +-21, +-10771901, +-21, +-10771901, +-21, +-10771901, +-21, +-10771901, +-21, +-10771901, +-21, +-10771901, +-21, +-10771901, +-20, +-10818421, +-20, +-10818421, +-20, +-10818421, +-20, +-10818421, +-20, +-10818421, +-20, +-10818421, +-20, +-10818421, +-20, +-10818421, +-19, +-10870341, +-19, +-10870341, +-19, +-10870341, +-19, +-10870341, +-19, +-10870341, +-19, +-10870341, +-19, +-10870341, +-19, +-10870341, +-19, +-10870341, +-18, +-10925105, +-18, +-10925105, +-18, +-10925105, +-18, +-10925105, +-18, +-10925105, +-18, +-10925105, +-18, +-10925105, +-18, +-10925105, +-18, +-10925105, +-17, +-10983043, +-17, +-10983043, +-17, +-10983043, +-17, +-10983043, +-17, +-10983043, +-17, +-10983043, +-17, +-10983043, +-17, +-10983043, +-17, +-10983043, +-16, +-11044545, +-16, +-11044545, +-16, +-11044545, +-16, +-11044545, +-16, +-11044545, +-16, +-11044545, +-16, +-11044545, +-16, +-11044545, +-16, +-11044545, +-16, +-11044545, +-15, +-11106103, +-15, +-11106103, +-15, +-11106103, +-15, +-11106103, +-15, +-11106103, +-15, +-11106103, +-15, +-11106103, +-15, +-11106103, +-15, +-11106103, +-15, +-11106103, +-15, +-11106103, +-14, +-11175947, +-14, +-11175947, +-14, +-11175947, +-14, +-11175947, +-14, +-11175947, +-14, +-11175947, +-14, +-11175947, +-14, +-11175947, +-14, +-11175947, +-14, +-11175947, +-14, +-11175947, +-14, +-11175947, +-13, +-11251037, +-13, +-11251037, +-13, +-11251037, +-13, +-11251037, +-13, +-11251037, +-13, +-11251037, +-13, +-11251037, +-13, +-11251037, +-13, +-11251037, +-13, +-11251037, +-13, +-11251037, +-13, +-11251037, +-12, +-11332227, +-12, +-11332227, +-12, +-11332227, +-12, +-11332227, +-12, +-11332227, +-12, +-11332227, +-12, +-11332227, +-12, +-11332227, +-12, +-11332227, +-12, +-11332227, +-12, +-11332227, +-12, +-11332227, +-12, +-11332227, +-11, +-11415177, +-11, +-11415177, +-11, +-11415177, +-11, +-11415177, +-11, +-11415177, +-11, +-11415177, +-11, +-11415177, +-11, +-11415177, +-11, +-11415177, +-11, +-11415177, +-11, +-11415177, +-11, +-11415177, +-11, +-11415177, +-11, +-11415177, +-10, +-11511568, +-10, +-11511568, +-10, +-11511568, +-10, +-11511568, +-10, +-11511568, +-10, +-11511568, +-10, +-11511568, +-10, +-11511568, +-10, +-11511568, +-10, +-11511568, +-10, +-11511568, +-10, +-11511568, +-10, +-11511568, +-10, +-11511568, +-10, +-11511568, +-10, +-11511568, +-9, +-11618252, +-9, +-11618252, +-9, +-11618252, +-9, +-11618252, +-9, +-11618252, +-9, +-11618252, +-9, +-11618252, +-9, +-11618252, +-9, +-11618252, +-9, +-11618252, +-9, +-11618252, +-9, +-11618252, +-9, +-11618252, +-9, +-11618252, +-9, +-11618252, +-9, +-11618252, +-9, +-11618252, +-9, +-11618252, +-8, +-11737693, +-8, +-11737693, +-8, +-11737693, +-8, +-11737693, +-8, +-11737693, +-8, +-11737693, +-8, +-11737693, +-8, +-11737693, +-8, +-11737693, +-8, +-11737693, +-8, +-11737693, +-8, +-11737693, +-8, +-11737693, +-8, +-11737693, +-8, +-11737693, +-8, +-11737693, +-8, +-11737693, +-8, +-11737693, +-8, +-11737693, +-7, +-11873358, +-7, +-11873358, +-7, +-11873358, +-7, +-11873358, +-7, +-11873358, +-7, +-11873358, +-7, +-11873358, +-7, +-11873358, +-7, +-11873358, +-7, +-11873358, +-7, +-11873358, +-7, +-11873358, +-7, +-11873358, +-7, +-11873358, +-7, +-11873358, +-7, +-11873358, +-7, +-11873358, +-7, +-11873358, +-7, +-11873358, +-7, +-11873358, +-7, +-11873358, +-7, +-11873358, +-6, +-12020412, +-6, +-12020412, +-6, +-12020412, +-6, +-12020412, +-6, +-12020412, +-6, +-12020412, +-6, +-12020412, +-6, +-12020412, +-6, +-12020412, +-6, +-12020412, +-6, +-12020412, +-6, +-12020412, +-6, +-12020412, +-6, +-12020412, +-6, +-12020412, +-6, +-12020412, +-6, +-12020412, +-6, +-12020412, +-6, +-12020412, +-6, +-12020412, +-6, +-12020412, +-6, +-12020412, +-6, +-12020412, +-6, +-12020412, +-6, +-12020412, +-6, +-12020412, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-5, +-12204716, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-4, +-12430840, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-3, +-12723509, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-2, +-13109172, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13802319, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511, +-1, +-13815511 diff --git a/rce/rcecalib/eudaq/BufferSerializer.cc b/rce/rcecalib/eudaq/BufferSerializer.cc new file mode 100644 index 00000000..fe71c3a0 --- /dev/null +++ b/rce/rcecalib/eudaq/BufferSerializer.cc @@ -0,0 +1,32 @@ +#include "eudaq/BufferSerializer.hh" + +namespace eudaq { + + BufferSerializer::BufferSerializer(Deserializer & des) : m_offset(0) { + des.read(m_data); + } + + void BufferSerializer::Serialize(Serializer & ser) const { + ser.write(m_data); + } + + void BufferSerializer::Serialize(const unsigned char * data, size_t len) { + m_data.insert(m_data.end(), data, data+len); + } + + void BufferSerializer::Deserialize(unsigned char * data, size_t len) { + if (!len) return; + if (len+m_offset > m_data.size()) { + std::cout<<"Deserialize asked for " + to_string(len) + + ", only have " + to_string(m_data.size()-m_offset)<<std::endl; + } + std::copy(&m_data[m_offset], &m_data[m_offset] + len, data); + //m_data.erase(m_data.begin(), m_data.begin() + len); + m_offset += len; + //std::string tmp(data, data+len); + //std::cout << "Deserialize: " << len << /*" \"" << tmp << "\"" <<*/ std::endl; + //tmp = std::string(begin(), end()); + //std::cout << "Remaining: " << (end()-begin()) << /*" \"" << tmp << "\"" <<*/ std::endl; + } + +} diff --git a/rce/rcecalib/eudaq/BufferSerializer.hh b/rce/rcecalib/eudaq/BufferSerializer.hh new file mode 100644 index 00000000..34ae6481 --- /dev/null +++ b/rce/rcecalib/eudaq/BufferSerializer.hh @@ -0,0 +1,33 @@ +#ifndef EUDAQ_INCLUDED_BufferSerializer +#define EUDAQ_INCLUDED_BufferSerializer + +#include <deque> +#include <algorithm> +#include <iostream> +#include "eudaq/Serializer.hh" +#include "eudaq/Exception.hh" + +namespace eudaq { + + class BufferSerializer : public Serializer, public Deserializer, public Serializable { + public: + BufferSerializer() : m_offset(0) {} + template<typename InIt> + BufferSerializer(InIt first, InIt last) : m_data(first, last), m_offset(0) { + } + BufferSerializer(Deserializer &); + void clear() { m_data.clear(); m_offset = 0; } + const unsigned char & operator [] (size_t i) const { return m_data[i]; } + size_t size() const { return m_data.size(); } + virtual bool HasData() { return m_data.size() != 0; } + virtual void Serialize(Serializer &) const; + private: + virtual void Serialize(const unsigned char * data, size_t len); + virtual void Deserialize(unsigned char * data, size_t len); + std::vector<unsigned char> m_data; + size_t m_offset; + }; + +} + +#endif // EUDAQ_INCLUDED_BufferSerializer diff --git a/rce/rcecalib/eudaq/CommandReceiver.cc b/rce/rcecalib/eudaq/CommandReceiver.cc new file mode 100644 index 00000000..796afb87 --- /dev/null +++ b/rce/rcecalib/eudaq/CommandReceiver.cc @@ -0,0 +1,154 @@ +#include "eudaq/CommandReceiver.hh" +#include "eudaq/TransportFactory.hh" +#include "eudaq/BufferSerializer.hh" +#include "eudaq/Exception.hh" +#include "eudaq/Utils.hh" +#include <iostream> +#include <ostream> + +namespace eudaq { + + namespace { + + void * CommandReceiver_thread(void * arg) { + CommandReceiver * cr = static_cast<CommandReceiver *>(arg); + try { + cr->CommandThread(); + } catch (const std::exception & e) { + std::cout << "Command Thread exiting due to exception:\n" << e.what() << std::endl; + } catch (...) { + std::cout << "Command Thread exiting due to unknown exception." << std::endl; + } + return 0; + } + + } // anonymous namespace + + CommandReceiver::CommandReceiver(const std::string & type, const std::string & name, + const std::string & runcontrol, bool startthread) + : m_cmdclient(TransportFactory::CreateClient(runcontrol)), + m_done(false), + m_type(type), + m_name(name), + m_threadcreated(false) + { + if (!m_cmdclient->IsNull()) { + std::string packet; + if (!m_cmdclient->ReceivePacket(&packet, 1000000)) EUDAQ_THROW("No response from RunControl server"); + // check packet is OK ("EUDAQ.CMD.RunControl nnn") + size_t i0 = 0, i1 = packet.find(' '); + if (i1 == std::string::npos) EUDAQ_THROW("Invalid response from RunControl server: '" + packet + "'"); + std::string part(packet, i0, i1); + if (part != "OK") EUDAQ_THROW("Invalid response from RunControl server: '" + packet + "'"); + i0 = i1+1; + i1 = packet.find(' ', i0); + if (i1 == std::string::npos) EUDAQ_THROW("Invalid response from RunControl server: '" + packet + "'"); + part = std::string(packet, i0, i1-i0); + if (part != "EUDAQ") EUDAQ_THROW("Invalid response from RunControl server: '" + packet + "'"); + i0 = i1+1; + i1 = packet.find(' ', i0); + if (i1 == std::string::npos) EUDAQ_THROW("Invalid response from RunControl server: '" + packet + "'"); + part = std::string(packet, i0, i1-i0); + if (part != "CMD") EUDAQ_THROW("Invalid response from RunControl server: '" + packet + "'"); + i0 = i1+1; + i1 = packet.find(' ', i0); + part = std::string(packet, i0, i1-i0); + if (part != "RunControl") EUDAQ_THROW("Invalid response from RunControl server: '" + packet + "'"); + + m_cmdclient->SendPacket("OK EUDAQ CMD " + m_type + " " + m_name); + packet = ""; + if (!m_cmdclient->ReceivePacket(&packet, 1000000)) EUDAQ_THROW("No response from RunControl server"); + i1 = packet.find(' '); + if (std::string(packet, 0, i1) != "OK") EUDAQ_THROW("Connection refused by RunControl server: " + packet); + } + + m_cmdclient->SetCallback(TransportCallback(this, &CommandReceiver::CommandHandler)); + + if (startthread) StartThread(); + } + + void CommandReceiver::StartThread() { + size_t stacksize=256000; + pthread_attr_init(&m_threadattr); + pthread_attr_setstacksize(&m_threadattr, stacksize); + if (pthread_create(&m_thread, &m_threadattr, CommandReceiver_thread, this) != 0) { + m_threadcreated = true; + } + } + + void CommandReceiver::SetStatus(Status::Level level, const std::string & info) { + m_status = Status(level, info); + } + + void CommandReceiver::Process(int timeout) { + m_cmdclient->Process(timeout); + } + + void CommandReceiver::OnLog(const std::string & param) { + //EUDAQ_LOG_CONNECT(m_type, m_name, param); + std::cout<<"Logging "<<param<<std::endl; + //return false; + } + + void CommandReceiver::OnIdle() { + mSleep(1); + } + + void CommandReceiver::CommandThread() { + while (!m_done) { + m_cmdclient->Process(); + OnIdle(); + } + } + + void CommandReceiver::CommandHandler(TransportEvent & ev) { + if (ev.etype == TransportEvent::RECEIVE) { + std::string cmd = ev.packet, param; + size_t i = cmd.find('\0'); + if (i != std::string::npos) { + param = std::string(cmd, i+1); + cmd = std::string(cmd, 0, i); + } + //std::cout << "(" << cmd << ")(" << param << ")" << std::endl; + if (cmd == "CONFIG") { + std::string section = m_type; + if (m_name != "") section += "." + m_name; + Configuration conf(param, section); + OnConfigure(conf); + } else if (cmd == "PREPARE") { + OnPrepareRun(from_string(param, 0)); + } else if (cmd == "START") { + OnStartRun(from_string(param, 0)); + } else if (cmd == "STOP") { + OnStopRun(); + } else if (cmd == "TERMINATE") { + OnTerminate(); + } else if (cmd == "RESET") { + OnReset(); + } else if (cmd == "STATUS") { + OnStatus(); + } else if (cmd == "DATA") { + OnData(param); + } else if (cmd == "LOG") { + OnLog(param); + } else if (cmd == "SERVER") { + OnServer(); + } else if (cmd == "GETRUN") { + OnGetRun(); + } else { + OnUnrecognised(cmd, param); + } + //std::cout << "Response = " << m_status << std::endl; + BufferSerializer ser; + m_status.Serialize(ser); + m_cmdclient->SendPacket(ser); + } + } + + CommandReceiver::~CommandReceiver() { + m_done = true; + if (m_threadcreated) pthread_join(m_thread, 0); + delete m_cmdclient; + } + +} diff --git a/rce/rcecalib/eudaq/CommandReceiver.hh b/rce/rcecalib/eudaq/CommandReceiver.hh new file mode 100644 index 00000000..fc042e86 --- /dev/null +++ b/rce/rcecalib/eudaq/CommandReceiver.hh @@ -0,0 +1,51 @@ +#ifndef EUDAQ_INCLUDED_CommandReceiver +#define EUDAQ_INCLUDED_CommandReceiver + +#include "eudaq/TransportClient.hh" +#include "eudaq/Configuration.hh" +#include "eudaq/Status.hh" +#include <pthread.h> +#include <string> +#include <iosfwd> + +namespace eudaq { + + class CommandReceiver { + public: + CommandReceiver(const std::string & type, const std::string & name, const std::string & runcontrol, + bool startthread = true); + void SetStatus(Status::Level level, const std::string & info = ""); + virtual ~CommandReceiver(); + + virtual void OnConfigure(const Configuration & param) { std::cout << "Config:\n" << param << std::endl; } + virtual void OnPrepareRun(unsigned /*runnumber*/) {} + virtual void OnStartRun(unsigned /*runnumber*/) {} + virtual void OnStopRun() {} + virtual void OnTerminate() {} + virtual void OnReset() {} + virtual void OnStatus() {} + virtual void OnData(const std::string & /*param*/) {} + virtual void OnLog(const std::string & /*param*/); + virtual void OnServer() {} + virtual void OnGetRun() {} + virtual void OnIdle(); + virtual void OnUnrecognised(const std::string & /*cmd*/, const std::string & /*param*/) {} + + void Process(int timeout); + void CommandThread(); + void StartThread(); + protected: + Status m_status; + TransportClient * m_cmdclient; + private: + bool m_done; + std::string m_type, m_name; + void CommandHandler(TransportEvent &); + pthread_t m_thread; + pthread_attr_t m_threadattr; + bool m_threadcreated; + }; + +} + +#endif // EUDAQ_INCLUDED_CommandReceiver diff --git a/rce/rcecalib/eudaq/Configuration.cc b/rce/rcecalib/eudaq/Configuration.cc new file mode 100644 index 00000000..85ecec7c --- /dev/null +++ b/rce/rcecalib/eudaq/Configuration.cc @@ -0,0 +1,153 @@ +#include "eudaq/Configuration.hh" + +#include <fstream> +#include <iostream> +#include <cstdlib> + +namespace eudaq { + + Configuration::Configuration(const std::string & config, const std::string & section) + : m_cur(&m_config[""]) { + std::istringstream confstr(config); + Load(confstr, section); + } + + Configuration::Configuration(std::istream & conffile, const std::string & section) + : m_cur(&m_config[""]) { + Load(conffile, section); + } + + Configuration::Configuration(const Configuration & other) + : m_config(other.m_config) + { + SetSection(other.m_section); + } + + std::string Configuration::Name() const { + map_t::const_iterator it = m_config.find(""); + if (it == m_config.end()) return ""; + section_t::const_iterator it2 = it->second.find("Name"); + if (it2 == it->second.end()) return ""; + return it2->second; + } + + void Configuration::Save(std::ostream & stream) const { + for (map_t::const_iterator i = m_config.begin(); i != m_config.end(); ++i) { + if (i->first != "") { + stream << "[" << i->first << "]\n"; + } + for (section_t::const_iterator j = i->second.begin(); j != i->second.end(); ++j) { + stream << j->first << " = " << j->second << "\n"; + } + stream << "\n"; + } + } + + Configuration & Configuration::operator = (const Configuration & other) { + m_config = other.m_config; + SetSection(other.m_section); + return *this; + } + + void Configuration::Load(std::istream & stream, const std::string & section) { + map_t config; + section_t * cur_sec = &config[""]; + for (;;) { + std::string line; + std::getline(stream, line); + if (stream.eof()) break; + size_t equals = line.find('='); + if (equals == std::string::npos) { + line = trim(line); + if (line == "" || line[0] == ';' || line[0] == '#') continue; + if (line[0] == '[' && line[line.length()-1] == ']') { + line = std::string(line, 1, line.length()-2); + // TODO: check name is alphanumeric? + //std::cerr << "Section " << line << std::endl; + cur_sec = &config[line]; + } + } else { + std::string key = trim(std::string(line, 0, equals)); + // TODO: check key does not already exist + // handle lines like: blah = "foo said ""bar""; ok." # not "baz" + line = trim(std::string(line, equals+1)); + if ((line[0] == '\'' && line[line.length()-1] == '\'') || + (line[0] == '\"' && line[line.length()-1] == '\"')) { + line = std::string(line, 1, line.length()-2); + } else { + size_t i = line.find_first_of(";#"); + if (i != std::string::npos) line = trim(std::string(line, 0, i)); + } + //std::cerr << "Key " << key << " = " << line << std::endl; + (*cur_sec)[key] = line; + } + } + m_config = config; + SetSection(section); + } + + bool Configuration::SetSection(const std::string & section) const { + map_t::const_iterator i = m_config.find(section); + if (i == m_config.end()) return false; + m_section = section; + m_cur = const_cast<section_t*>(&i->second); + return true; + } + + bool Configuration::SetSection(const std::string & section) { + m_section = section; + m_cur = &m_config[section]; + return true; + } + + std::string Configuration::Get(const std::string & key, const std::string & def) const { + try { + return GetString(key); + } catch (const Exception &) { + // ignore: return default + } + return def; + } + + double Configuration::Get(const std::string & key, double def) const { + try { + return from_string(GetString(key), def); + } catch (const Exception &) { + // ignore: return default + } + return def; + } + + long long Configuration::Get(const std::string & key, long long def) const { + try { + std::string s = GetString(key); + return strtoll(s.c_str(), 0, 0); + } catch (const Exception &) { + // ignore: return default + } + return def; + } + + int Configuration::Get(const std::string & key, int def) const { + try { + std::string s = GetString(key); + return std::strtol(s.c_str(), 0, 0); + } catch (const Exception &) { + // ignore: return default + } + return def; + } + + std::string Configuration::GetString(const std::string & key) const { + section_t::const_iterator i = m_cur->find(key); + if (i != m_cur->end()) { + return i->second; + } + throw Exception("Configuration: key not found"); + } + + void Configuration::SetString(const std::string & key, const std::string & val) { + (*m_cur)[key] = val; + } + +} diff --git a/rce/rcecalib/eudaq/Configuration.hh b/rce/rcecalib/eudaq/Configuration.hh new file mode 100644 index 00000000..a62a7d7e --- /dev/null +++ b/rce/rcecalib/eudaq/Configuration.hh @@ -0,0 +1,59 @@ +#ifndef EUDAQ_INCLUDED_Configuration +#define EUDAQ_INCLUDED_Configuration + +#include "eudaq/Utils.hh" +#include "eudaq/Exception.hh" +#include <string> +#include <map> + +namespace eudaq { + + class Configuration { + public: + Configuration(const std::string & config = "", const std::string & section = ""); + Configuration(std::istream & conffile, const std::string & section = ""); + Configuration(const Configuration & other); + void Save(std::ostream & file) const; + void Load(std::istream & file, const std::string & section); + bool SetSection(const std::string & section) const; + bool SetSection(const std::string & section); + std::string operator [] (const std::string & key) const { return GetString(key); } + std::string Get(const std::string & key, const std::string & def) const; + double Get(const std::string & key, double def) const; + long long Get(const std::string & key, long long def) const; + int Get(const std::string & key, int def) const; + template <typename T> + T Get(const std::string & key, const std::string fallback, const T & def) const { + return Get(key, Get(fallback, def)); + } + std::string Get(const std::string & key, const std::string fallback, const char * def) const { + return Get(key, Get(fallback, def)); + } + //std::string Get(const std::string & key, const std::string & def = ""); + template <typename T> + void Set(const std::string & key, const T & val); + std::string Name() const; + Configuration & operator = (const Configuration & other); + private: + std::string GetString(const std::string & key) const; + void SetString(const std::string & key, const std::string & val); + typedef std::map<std::string, std::string> section_t; + typedef std::map<std::string, section_t> map_t; + map_t m_config; + mutable std::string m_section; + mutable section_t * m_cur; + }; + + inline std::ostream & operator << (std::ostream & os, const Configuration & c) { + c.Save(os); + return os; + } + + template <typename T> + inline void Configuration::Set(const std::string & key, const T & val) { + SetString(key, to_string(val)); + } + +} + +#endif // EUDAQ_INCLUDED_Configuration diff --git a/rce/rcecalib/eudaq/DataSender.cc b/rce/rcecalib/eudaq/DataSender.cc new file mode 100644 index 00000000..3ef2e920 --- /dev/null +++ b/rce/rcecalib/eudaq/DataSender.cc @@ -0,0 +1,63 @@ +#include "eudaq/DataSender.hh" +#include "eudaq/TransportFactory.hh" +#include "eudaq/Exception.hh" + +namespace eudaq { + + DataSender::DataSender(const std::string & type, const std::string & name) + : m_type(type), + m_name(name), + m_dataclient(0) {} + + void DataSender::Connect(const std::string & server) { + delete m_dataclient; + m_dataclient = TransportFactory::CreateClient(server); + + std::string packet; + if (!m_dataclient->ReceivePacket(&packet, 1000000)) EUDAQ_THROW("No response from DataCollector server"); + size_t i0 = 0, i1 = packet.find(' '); + if (i1 == std::string::npos) EUDAQ_THROW("Invalid response from DataCollector server"); + std::string part(packet, i0, i1); + if (part != "OK") EUDAQ_THROW("Invalid response from DataCollector server: " + packet); + i0 = i1+1; + i1 = packet.find(' ', i0); + if (i1 == std::string::npos) EUDAQ_THROW("Invalid response from DataCollector server"); + part = std::string(packet, i0, i1-i0); + if (part != "EUDAQ") EUDAQ_THROW("Invalid response from DataCollector server, part=" + part); + i0 = i1+1; + i1 = packet.find(' ', i0); + if (i1 == std::string::npos) EUDAQ_THROW("Invalid response from DataCollector server"); + part = std::string(packet, i0, i1-i0); + if (part != "DATA") EUDAQ_THROW("Invalid response from DataCollector server, part=" + part); + i0 = i1+1; + i1 = packet.find(' ', i0); + part = std::string(packet, i0, i1-i0); + if (part != "DataCollector" ) EUDAQ_THROW("Invalid response from DataCollector server, part=" + part); + + m_dataclient->SendPacket("OK EUDAQ DATA " + m_type + " " + m_name); + packet = ""; + if (!m_dataclient->ReceivePacket(&packet, 1000000)) EUDAQ_THROW("No response from DataCollector server"); + i1 = packet.find(' '); + if (std::string(packet, 0, i1) != "OK") EUDAQ_THROW("Connection refused by DataCollector server: " + packet); + } + + void DataSender::SendEvent(const Event &ev) { + if (!m_dataclient) EUDAQ_THROW("Transport not connected error"); + //EUDAQ_DEBUG("Serializing event"); + //BufferSerializer ser; + m_ser.clear(); + ev.Serialize(m_ser); + //EUDAQ_DEBUG("Sending event"); + m_dataclient->SendPacket(m_ser); + //EUDAQ_DEBUG("Sent event"); + } + + void DataSender::SendEvent(unsigned char* data, int size){ + m_dataclient->SendPacket((unsigned char*)data, size); + } + + DataSender::~DataSender() { + delete m_dataclient; + } + +} diff --git a/rce/rcecalib/eudaq/DataSender.hh b/rce/rcecalib/eudaq/DataSender.hh new file mode 100644 index 00000000..e3a6b18e --- /dev/null +++ b/rce/rcecalib/eudaq/DataSender.hh @@ -0,0 +1,27 @@ +#ifndef EUDAQ_INCLUDED_DataSender +#define EUDAQ_INCLUDED_DataSender + +#include "eudaq/Event.hh" +#include "eudaq/TransportClient.hh" +#include "eudaq/Serializer.hh" +#include "eudaq/BufferSerializer.hh" +#include <string> + +namespace eudaq { + + class DataSender { + public: + DataSender(const std::string & type, const std::string & name); + ~DataSender(); + void Connect(const std::string & server); + void SendEvent(const Event &); + void SendEvent(unsigned char* data, int size); + private: + std::string m_type, m_name; + TransportClient * m_dataclient; + BufferSerializer m_ser; + }; + +} + +#endif // EUDAQ_INCLUDED_DataSender diff --git a/rce/rcecalib/eudaq/DataSenderIF.cc b/rce/rcecalib/eudaq/DataSenderIF.cc new file mode 100644 index 00000000..9d2da306 --- /dev/null +++ b/rce/rcecalib/eudaq/DataSenderIF.cc @@ -0,0 +1,25 @@ +#include "rcecalib/eudaq/DataSenderIF.hh" + +#include "rcecalib/eudaq/DataSender.hh" + +eudaq::DataSender * DataSenderIF::m_dataSender = 0; + +void DataSenderIF::setDataSender(eudaq::DataSender * dataSender) +{ m_dataSender = dataSender; return; } + +void DataSenderIF::SendEvent(eudaq::Event * event) +{ + if (m_dataSender != 0) + { + m_dataSender->SendEvent(*event); + } + return; +} +void DataSenderIF::SendEvent(unsigned char *data, int size) +{ + if (m_dataSender != 0) + { + m_dataSender->SendEvent(data, size); + } + return; +} diff --git a/rce/rcecalib/eudaq/DataSenderIF.hh b/rce/rcecalib/eudaq/DataSenderIF.hh new file mode 100644 index 00000000..4a4ba583 --- /dev/null +++ b/rce/rcecalib/eudaq/DataSenderIF.hh @@ -0,0 +1,27 @@ +#ifndef DATASENDER_HH +#define DATASENDER_HH + + /* +A static interface to the DataSender eudaq class so that one instance may be easily shared across an +entire object-oritented application. + */ + +namespace eudaq +{ + class Event; + class DataSender; +} + +class DataSenderIF +{ + public: + static void SendEvent(eudaq::Event * event); + static void SendEvent(unsigned char *data, int size); + static void setDataSender(eudaq::DataSender * dataSender); + static bool hasInstance() {return m_dataSender != 0;} + + private: + static eudaq::DataSender * m_dataSender; +}; + +#endif diff --git a/rce/rcecalib/eudaq/DetectorEvent.cc b/rce/rcecalib/eudaq/DetectorEvent.cc new file mode 100644 index 00000000..a766443e --- /dev/null +++ b/rce/rcecalib/eudaq/DetectorEvent.cc @@ -0,0 +1,45 @@ +#include "eudaq/DetectorEvent.hh" + +#include <ostream> + +namespace eudaq { + + EUDAQ_DEFINE_EVENT(DetectorEvent, str2id("_DET")); + + DetectorEvent::DetectorEvent(Deserializer & ds) : + Event(ds) + { + unsigned n; + ds.read(n); + //std::cout << "Num=" << n << std::endl; + for (size_t i = 0; i < n; ++i) { + counted_ptr<Event> ev(EventFactory::Create(ds)); + m_events.push_back(ev); + } + } + + void DetectorEvent::AddEvent(counted_ptr<Event> evt) { + if (!evt.get()) std::cout<<"Adding null event!"<<std::endl; + m_events.push_back(evt); + SetFlags(evt->GetFlags()); + } + + void DetectorEvent::Print(std::ostream & os) const { + Event::Print(os); + os << " {\n"; + for (size_t i = 0; i < NumEvents(); ++i) { + os << " " << *GetEvent(i) << std::endl; + } + os << "}"; + } + + void DetectorEvent::Serialize(Serializer & ser) const { + Event::Serialize(ser); + ser.write((unsigned)m_events.size()); + for (size_t i = 0; i < m_events.size(); ++i) { + m_events[i]->Serialize(ser); + } + } + + +} diff --git a/rce/rcecalib/eudaq/DetectorEvent.hh b/rce/rcecalib/eudaq/DetectorEvent.hh new file mode 100644 index 00000000..ae15267a --- /dev/null +++ b/rce/rcecalib/eudaq/DetectorEvent.hh @@ -0,0 +1,51 @@ +#ifndef EUDAQ_INCLUDED_DetectorEvent +#define EUDAQ_INCLUDED_DetectorEvent + +#include <vector> +#include "eudaq/Event.hh" +#include "eudaq/counted_ptr.hh" + +namespace eudaq { + + class DetectorEvent : public Event { + EUDAQ_DECLARE_EVENT(DetectorEvent); + public: + virtual void Serialize(Serializer &) const; + explicit DetectorEvent(unsigned runnumber, unsigned eventnumber, unsigned long long timestamp) : + Event(runnumber, eventnumber, timestamp) + {} +// explicit DetectorEvent(const TLUEvent & tluev) : +// Event(tluev.GetRunNumber(), tluev.GetEventNumber(), tluev.GetTimestamp()) +// {} + explicit DetectorEvent(Deserializer&); + void AddEvent(counted_ptr<Event> evt); + virtual void Print(std::ostream &) const; + + /// Return "DetectorEvent" as type. + virtual std::string GetType() const {return "DetectorEvent";} + + size_t NumEvents() const { return m_events.size(); } + Event * GetEvent(size_t i) { return m_events[i].get(); } + const Event * GetEvent(size_t i) const { return m_events[i].get(); } + counted_ptr<Event> GetEventPtr(size_t i) { return m_events[i]; } + template <typename T> + const T * GetSubEvent(int n = 0) const { + for (size_t i = 0; i < NumEvents(); i++) { + const T * sev = dynamic_cast<const T*>(GetEvent(i)); + if (sev) { + if (n > 0) { + --n; + } else { + return sev; + } + } + } + return 0; + } + private: + std::vector<counted_ptr<Event> > m_events; + }; + +} + +#endif // EUDAQ_INCLUDED_TLUEvent diff --git a/rce/rcecalib/eudaq/Event.cc b/rce/rcecalib/eudaq/Event.cc new file mode 100644 index 00000000..9f4fe07d --- /dev/null +++ b/rce/rcecalib/eudaq/Event.cc @@ -0,0 +1,117 @@ +#include <ostream> +#include <iostream> + +#include "eudaq/Event.hh" + +namespace eudaq { + + namespace { + + static const char * const FLAGNAMES[] = { + "BORE", + "EORE", + "HITS" + }; + + } + + Event::Event(Deserializer & ds) { + ds.read(m_flags); + ds.read(m_runnumber); + ds.read(m_eventnumber); + ds.read(m_timestamp); + ds.read(m_tags); + } + + void Event::Serialize(Serializer & ser) const { + //std::cout << "Serialize id = " << std::hex << get_id() << std::endl; + ser.write(get_id()); + ser.write(m_flags); + ser.write(m_runnumber); + ser.write(m_eventnumber); + ser.write(m_timestamp); + ser.write(m_tags); + } + + void Event::Print(std::ostream & os) const { + os << "Type=" << id2str(get_id()) << ":" << GetSubType() + << ", Number=" << m_runnumber << "." << m_eventnumber; + if (m_timestamp != NOTIMESTAMP) + os << ", Time=0x" << to_hex(m_timestamp, 16); + if (m_flags) { + unsigned f = m_flags; + bool first = true; + for (size_t i = 0; f > 0; ++i, f >>= 1) { + if (f & 1) { + os << (first ? ", Flags=" : ",") + << (i < sizeof FLAGNAMES / sizeof *FLAGNAMES ? std::string(FLAGNAMES[i]) : to_string(i)); + first = false; + } + } + } + if (m_tags.size() > 0) { + for (map_t::const_iterator i = m_tags.begin(); i != m_tags.end(); ++i) { + os << (i == m_tags.begin() ? ", {" : ", ") << i->first << "=" << i->second; + } + os << "}"; + } + } + + unsigned Event::str2id(const std::string & str) { + unsigned long result = 0; + for (size_t i = 0; i < 4; ++i) { + if (i < str.length()) result |= str[i] << (8*i); + } + //std::cout << "str2id(" << str << ") = " << std::hex << result << std::dec << std::endl; + return result; + } + + std::string Event::id2str(unsigned id) { + //std::cout << "id2str(" << std::hex << id << std::dec << ")" << std::flush; + std::string result(4, '\0'); + for (int i = 0; i < 4; ++i) { + result[i] = (char)(id & 0xff); + id >>= 8; + } + for (int i = 3; i >= 0; --i) { + if (result[i] == '\0') { + result.erase(i); + break; + } + } + //std::cout << " = " << result << std::endl; + return result; + } + + Event & Event::SetTag(const std::string & name, const std::string & val) { + m_tags[name] = val; + return *this; + } + + std::string Event::GetTag(const std::string & name, const std::string & def) const { + std::map<std::string, std::string>::const_iterator i = m_tags.find(name); + if (i == m_tags.end()) return def; + return i->second; + } + + std::ostream & operator << (std::ostream &os, const Event &ev) { + ev.Print(os); + return os; + } + + EventFactory::map_t & EventFactory::get_map() { + static map_t s_map; + return s_map; + } + + void EventFactory::Register(unsigned long id, EventFactory::event_creator func) { + // TODO: check id is not already in map + get_map()[id] = func; + } + + EventFactory::event_creator EventFactory::GetCreator(unsigned long id) { + // TODO: check it exists... + return get_map()[id]; + } + +} diff --git a/rce/rcecalib/eudaq/Event.hh b/rce/rcecalib/eudaq/Event.hh new file mode 100644 index 00000000..af074d0d --- /dev/null +++ b/rce/rcecalib/eudaq/Event.hh @@ -0,0 +1,119 @@ +#ifndef EUDAQ_INCLUDED_Event +#define EUDAQ_INCLUDED_Event + +#include <string> +#include <vector> +#include <map> +#include <iosfwd> +#include <iostream> + +#include "eudaq/Serializable.hh" +#include "eudaq/Serializer.hh" +#include "eudaq/Exception.hh" +#include "eudaq/Utils.hh" + +#define EUDAQ_DECLARE_EVENT(type) \ + public: \ + static unsigned eudaq_static_id(); \ + virtual unsigned get_id() const { \ + return eudaq_static_id(); \ + } \ + private: \ + static const int EUDAQ_DUMMY_VAR_DONT_USE = 0 + +#define EUDAQ_DEFINE_EVENT(type, id) \ + unsigned type::eudaq_static_id() { \ + static const unsigned id_(id); \ + return id_; \ + } \ + namespace _eudaq_dummy_ { \ + static RegisterEventType<type> eudaq_reg;\ + } \ + static const int EUDAQ_DUMMY_VAR_DONT_USE = 0 + +namespace eudaq { + + static const unsigned long long NOTIMESTAMP = (unsigned long long)-1; + + class Event : public Serializable { + public: + enum Flags { FLAG_BORE=1, FLAG_EORE=2, FLAG_HITS=4, FLAG_ALL=(unsigned)-1 }; // Matches FLAGNAMES in .cc file + Event(unsigned run, unsigned event, unsigned long long timestamp = NOTIMESTAMP, unsigned flags=0) + : m_flags(flags), m_runnumber(run), m_eventnumber(event), m_timestamp(timestamp) {} + Event(Deserializer & ds); + virtual void Serialize(Serializer &) const = 0; + + unsigned GetRunNumber() const { return m_runnumber; } + unsigned GetEventNumber() const { return m_eventnumber; } + void SetEventNumber(unsigned event){m_eventnumber=event;} + unsigned long long GetTimestamp() const { return m_timestamp; } + + /** Returns the type string of the event implementation. + * Used by the plugin mechanism to identfy the event type. + */ + virtual std::string GetSubType() const { return ""; } + + virtual void Print(std::ostream & os) const = 0; + + Event & SetTag(const std::string & name, const std::string & val); + std::string GetTag(const std::string & name, const std::string & def = "") const; + std::string GetTag(const std::string & name, const char * def) const { return GetTag(name, std::string(def)); } + template <typename T> + T GetTag(const std::string & name, T def) const { + return eudaq::from_string(GetTag(name), def); + } + + bool IsBORE() const { return GetFlags(FLAG_BORE) != 0; } + bool IsEORE() const { return GetFlags(FLAG_EORE) != 0; } + bool HasHits() const { return GetFlags(FLAG_HITS) != 0; } + + static unsigned str2id(const std::string & idstr); + static std::string id2str(unsigned id); + unsigned GetFlags(unsigned f = FLAG_ALL) const { return m_flags & f; } + void SetFlags(unsigned f) { m_flags |= f; } + void ClearFlags(unsigned f = FLAG_ALL) { m_flags &= ~f; } + virtual unsigned get_id() const = 0; + protected: + typedef std::map<std::string, std::string> map_t; + + unsigned m_flags, m_runnumber, m_eventnumber; + unsigned long long m_timestamp; + map_t m_tags; ///< Metadata tags in (name=value) pairs of strings + }; + + std::ostream & operator << (std::ostream &, const Event &); + + class EventFactory { + public: + static Event * Create(Deserializer & ds) { + unsigned id = 0; + ds.read(id); + //std::cout << "Create id = " << std::hex << id << std::dec << std::endl; + event_creator cr = GetCreator(id); + if (!cr) std::cout<<"Unrecognised Event type (" + Event::id2str(id) + ")"<<std::endl; + return cr(ds); + } + + typedef Event * (* event_creator)(Deserializer & ds); + static void Register(unsigned long id, event_creator func); + static event_creator GetCreator(unsigned long id); + + private: + typedef std::map<unsigned long, event_creator> map_t; + static map_t & get_map(); + }; + + /** A utility template class for registering an Event type. + */ + template <typename T_Evt> + struct RegisterEventType { + RegisterEventType() { + EventFactory::Register(T_Evt::eudaq_static_id(), &factory_func); + } + static Event * factory_func(Deserializer & ds) { + return new T_Evt(ds); + } + }; +} + +#endif // EUDAQ_INCLUDED_Event diff --git a/rce/rcecalib/eudaq/Exception.cc b/rce/rcecalib/eudaq/Exception.cc new file mode 100644 index 00000000..65fd69c4 --- /dev/null +++ b/rce/rcecalib/eudaq/Exception.cc @@ -0,0 +1,48 @@ +#include "eudaq/Exception.hh" +#include <iostream> + + +namespace eudaq { + + Exception::Exception(const std::string & msg) + : m_msg(msg), m_line(0) + {} + + const Exception & Exception::SetLocation(const std::string & file, + unsigned line, + const std::string & func) const { + m_file = file; + m_line = line; + m_func = func; + return *this; + } + + void Exception::make_text() const { + m_text = m_msg; + if (m_file.length() > 0) { + m_text += "\n From " + m_file; + if (m_line > 0) { + m_text += ":" + to_string(m_line); + } + } + if (m_func.length() > 0) m_text += "\n In " + m_func; + } + LoggedException::LoggedException(const std::string & msg) + : Exception(msg), m_logged(false) + { + } + + void LoggedException::Log() const { + if (m_logged) return; + // Only log the message once + m_logged = true; + } + + LoggedException::~LoggedException() throw() { + // Make sure the message has been logged before we die + if(m_logged==false) { + // Log(); + } + } +} + diff --git a/rce/rcecalib/eudaq/Exception.hh b/rce/rcecalib/eudaq/Exception.hh new file mode 100644 index 00000000..d52629a3 --- /dev/null +++ b/rce/rcecalib/eudaq/Exception.hh @@ -0,0 +1,84 @@ +#ifndef EUDAQ_INCLUDED_Exception +#define EUDAQ_INCLUDED_Exception + +#include "eudaq/Utils.hh" +#include <exception> +#include <string> +#include <iostream> + +#ifndef EUDAQ_FUNC +# define EUDAQ_FUNC "" +#endif + +#define EUDAQ_THROWX(exc, msg) throw ::eudaq::InitException(exc(msg), __FILE__, __LINE__, EUDAQ_FUNC) +#define EUDAQ_THROW(msg) EUDAQ_THROWX(::eudaq::LoggedException, (msg)) + +#define EUDAQ_EXCEPTIONX(name, base) \ + class name : public base { \ + public: \ + name(const std::string & msg) \ + : base(msg) {} \ + } + +#define EUDAQ_EXCEPTION(name) EUDAQ_EXCEPTIONX(name, ::eudaq::Exception) + +namespace eudaq { + + class Exception : public std::exception { + public: + Exception(const std::string & msg); + const char * what() const throw() { + if (m_text.length() == 0) make_text(); + return m_text.c_str(); + } + // This shouldn't really be const, but it must be callable on temporary objects... + const Exception & SetLocation(const std::string & file = "", + unsigned line = 0, + const std::string & func = "") const; + virtual ~Exception() throw() { + } + protected: + std::string m_msg; + private: + void make_text() const; + mutable std::string m_text; + mutable std::string m_file, m_func; + mutable unsigned m_line; + }; + class LoggedException : public Exception { + public: + LoggedException(const std::string & msg); + void Log() const; + virtual ~LoggedException() throw(); + private: + mutable bool m_logged; + }; + + namespace { + void do_log(const Exception &) { + } + void do_log(const LoggedException & e) { + std::cout<<e.what()<<std::endl; + } + } + + + template <typename T> + const T & InitException(const T & e, const std::string & file, int line = 0, const std::string func = "") { + e.SetLocation(file, line, func); + return e; + } + + // Some useful predefined exceptions + EUDAQ_EXCEPTION(FileNotFoundException); + EUDAQ_EXCEPTION(FileExistsException); + EUDAQ_EXCEPTION(FileNotWritableException); + EUDAQ_EXCEPTION(FileReadException); + EUDAQ_EXCEPTION(FileWriteException); + EUDAQ_EXCEPTION(FileFormatException); + EUDAQ_EXCEPTION(CommunicationException); + EUDAQ_EXCEPTIONX(BusError, CommunicationException); + +} + +#endif // EUDAQ_INCLUDED_Exception diff --git a/rce/rcecalib/eudaq/FileSerializer.cc b/rce/rcecalib/eudaq/FileSerializer.cc new file mode 100644 index 00000000..5261ea67 --- /dev/null +++ b/rce/rcecalib/eudaq/FileSerializer.cc @@ -0,0 +1,123 @@ +#include "eudaq/FileSerializer.hh" +#include "eudaq/Exception.hh" +#include "eudaq/Utils.hh" +#include <sys/types.h> +#include <sys/stat.h> +#include <iostream> + +namespace eudaq { + + FileSerializer::FileSerializer(const std::string & fname, bool overwrite, int wprot) + : m_file(0), m_filebytes(0), m_wprot(wprot) + { + if (!overwrite) { + FILE * fd = fopen(fname.c_str(), "rb"); + if (fd) { + fclose(fd); + EUDAQ_THROWX(FileExistsException, "File already exists: " + fname); + } + } + m_file = fopen(fname.c_str(), "wb"); + if (!m_file) EUDAQ_THROWX(FileNotFoundException, "Unable to open file: " + fname); + if (m_wprot == WP_ONOPEN) { + WriteProtect(); + } + } + + FileSerializer::~FileSerializer() { + if (m_wprot == WP_ONCLOSE) { + WriteProtect(); + } + if (m_file) { + fclose(m_file); + } + } + + void FileSerializer::Serialize(const unsigned char * data, size_t len) { + size_t written = std::fwrite(reinterpret_cast<const char *>(data), 1, len, m_file); + m_filebytes += written; + if (written != len) { + std::cout<<"Error writing to file: " + to_string(errno) + ", " + strerror(errno)<<std::endl; + } + } + + void FileSerializer::Flush() { + fflush(m_file); + } + + void FileSerializer::WriteProtect() { + fchmod(fileno(m_file), S_IRUSR | S_IRGRP | S_IROTH); + } + + FileDeserializer::FileDeserializer(const std::string & fname, bool faileof, size_t buffersize) : + m_file(0), m_faileof(faileof), m_buf(buffersize), m_start(&m_buf[0]), m_stop(m_start) + { + m_file = fopen(fname.c_str(), "rb"); + if (!m_file) EUDAQ_THROWX(FileNotFoundException, "Unable to open file: " + fname); + } + + bool FileDeserializer::HasData() { + if (level() == 0) FillBuffer(); + return level() > 0; + } + + size_t FileDeserializer::FillBuffer(size_t min) { + clearerr(m_file); + if (level() == 0) m_start = m_stop = &m_buf[0]; + unsigned char * end = &m_buf[0] + m_buf.size(); + if (size_t(end - m_stop) < min) { + // not enough space remaining before end of buffer, + // so shift everything back to the beginning of the buffer + std::memmove(m_start, &m_buf[0], level()); + m_stop -= (m_start - &m_buf[0]); + m_start = &m_buf[0]; + if (size_t(end - m_stop) < min) { + // still not enough space? nothing we can do, reduce the required amount + min = end - m_stop; + } + } + size_t read = fread(reinterpret_cast<char *>(m_stop), 1, end - m_stop, m_file); + m_stop += read; + while (read < min) { + if (feof(m_file) && m_faileof) { + throw FileReadException("End of File encountered"); + } else if (int err = ferror(m_file)) { + EUDAQ_THROWX(FileReadException, "Error reading from file: " + to_string(err)); + } else if (m_interrupting) { + m_interrupting = false; + throw InterruptedException(); + } + mSleep(10); + clearerr(m_file); + size_t bytes = fread(reinterpret_cast<char *>(m_stop), 1, end - m_stop, m_file); + read += bytes; + m_stop += bytes; + } + return read; + } + + void FileDeserializer::Deserialize(unsigned char * data, size_t len) { + if (len <= level()) { + // The buffer contains enough data + memcpy(data, m_start, len); + m_start += len; + } else if (level() > 0) { + // The buffer contains some data, so use it up first + size_t tmp = level(); + memcpy(data, m_start, tmp); + m_start = m_stop; + // Then deserialise what remains + Deserialize(data + tmp, len - tmp); + //} else if (len >= m_buf.size()/2) { + // The buffer must be empty, and we have a lot of data to read + // So read directly into the destination + //FillBuffer(data, len); + } else { + // Otherwise fill up the buffer, making sure we have at least enough data + FillBuffer(len); + // Now we have enough data in the buffer, just call deserialize again + Deserialize(data, len); + } + } + +} diff --git a/rce/rcecalib/eudaq/FileSerializer.hh b/rce/rcecalib/eudaq/FileSerializer.hh new file mode 100644 index 00000000..8ad5beba --- /dev/null +++ b/rce/rcecalib/eudaq/FileSerializer.hh @@ -0,0 +1,52 @@ +#ifndef EUDAQ_INCLUDED_FileSerializer +#define EUDAQ_INCLUDED_FileSerializer + +#include <string> +#include <cstdio> +#include "eudaq/Serializer.hh" +#include "eudaq/Exception.hh" +#include "eudaq/BufferSerializer.hh" + +namespace eudaq { + + class FileSerializer : public Serializer { + public: + enum WPROT { WP_NONE, WP_ONCLOSE, WP_ONOPEN }; + FileSerializer(const std::string & fname, bool overwrite = false, int writeprotect = WP_ONCLOSE); + virtual void Flush(); + unsigned long long FileBytes() const { return m_filebytes; } + void WriteProtect(); + ~FileSerializer(); + private: + virtual void Serialize(const unsigned char * data, size_t len); + FILE * m_file; + unsigned long long m_filebytes; + int m_wprot; + }; + + class FileDeserializer : public Deserializer { + public: + FileDeserializer(const std::string & fname, bool faileof = false, size_t buffersize = 65536); + virtual bool HasData(); + template <typename T> + T peek() { + FillBuffer(); + BufferSerializer buf(m_start, m_stop); + T result; + buf.read(result); + return result; + } + private: + virtual void Deserialize(unsigned char * data, size_t len); + size_t FillBuffer(size_t min = 0); + size_t level() const { return m_stop - m_start; } + typedef unsigned char *ptr_t; + FILE * m_file; + bool m_faileof; + std::vector<unsigned char> m_buf; + ptr_t m_start, m_stop; + }; + +} + +#endif // EUDAQ_INCLUDED_FileSerializer diff --git a/rce/rcecalib/eudaq/Makefile b/rce/rcecalib/eudaq/Makefile new file mode 100644 index 00000000..3cd076af --- /dev/null +++ b/rce/rcecalib/eudaq/Makefile @@ -0,0 +1,21 @@ +# Package level makefile +# ---------------------- +%.mk:; + +# Checks +# ------ +# Check release location variables +ifeq ($(RELEASE_DIR),) +export RELEASE_DIR := $(PWD)/../.. +endif + +include $(RELEASE_DIR)/make/share/setup.mk +include ../flags.mk + +ifndef PREMAKE_DONE +include $(RELEASE_DIR)/make/share/premake.mk +else +include constituents.mk +include $(RELEASE_DIR)/make/sw/package.mk +include $(RELEASE_DIR)/make/sw/rootcint.mk +endif diff --git a/rce/rcecalib/eudaq/Mutex.cc b/rce/rcecalib/eudaq/Mutex.cc new file mode 100644 index 00000000..ab08699f --- /dev/null +++ b/rce/rcecalib/eudaq/Mutex.cc @@ -0,0 +1,84 @@ +#include "eudaq/Mutex.hh" +#include "eudaq/Exception.hh" +#include <pthread.h> + +namespace eudaq { + + class Mutex::Impl { + public: + Impl() { + if (pthread_mutexattr_init(&m_attr)) { + EUDAQ_THROW("Unable to create mutex attributes"); + } + // pthread_mutexattr_settype(&m_attr, PTHREAD_MUTEX_RECURSIVE); + if (pthread_mutex_init(&m_mutex, &m_attr)) { + EUDAQ_THROW("Unable to create mutex"); + } + } + ~Impl() { + if (pthread_mutex_destroy(&m_mutex)) { + // error + } + } + pthread_mutexattr_t m_attr; + pthread_mutex_t m_mutex; + }; + + Mutex::Mutex() : m_impl(new Mutex::Impl) {} + + Mutex::~Mutex() { delete m_impl; } + + int Mutex::Lock() { + return pthread_mutex_lock(&m_impl->m_mutex); + } + + int Mutex::TryLock() { + return pthread_mutex_trylock(&m_impl->m_mutex); + } + + int Mutex::UnLock() { + return pthread_mutex_unlock(&m_impl->m_mutex); + } + + MutexLock::MutexLock(Mutex & m, bool lock) : m_mutex(m), m_locked(lock) { + if (lock && m_mutex.TryLock()) { + EUDAQ_THROW("Unable to lock mutex"); + } + } + + void MutexLock::Lock() { + if (m_mutex.TryLock()) { + EUDAQ_THROW("Unable to lock mutex"); + } + m_locked = true; + } + + void MutexLock::Release() { + if (m_locked) m_mutex.UnLock(); + m_locked = false; + } + + MutexLock::~MutexLock() { + Release(); + } + +// MutexTryLock::MutexTryLock(Mutex & m) : m_mutex(m), m_locked(true) { +// if (m_mutex.TryLock()) { +// m_locked = false; +// } +// } + +// void MutexTryLock::Release() { +// m_mutex.UnLock(); +// m_locked = false; +// } + +// MutexTryLock::~MutexTryLock() { +// if (m_locked) Release(); +// } + +// MutexTryLock::operator bool () const { +// return m_locked; +// } + +} diff --git a/rce/rcecalib/eudaq/Mutex.hh b/rce/rcecalib/eudaq/Mutex.hh new file mode 100644 index 00000000..9f6199b4 --- /dev/null +++ b/rce/rcecalib/eudaq/Mutex.hh @@ -0,0 +1,42 @@ +#ifndef H_EUDAQ_MUTEX +#define H_EUDAQ_MUTEX + +namespace eudaq { + + class Mutex { + public: + Mutex(); + ~Mutex(); + int Lock(); + int TryLock(); + int UnLock(); + private: + class Impl; + Impl * m_impl; + }; + + class MutexLock { + public: + MutexLock(Mutex & m, bool lock = true); + ~MutexLock(); + void Lock(); + void Release(); + private: + Mutex & m_mutex; + bool m_locked; + }; + +// class MutexTryLock { +// public: +// MutexTryLock(Mutex & m); +// ~MutexTryLock(); +// void Release(); +// operator bool () const; +// private: +// Mutex & m_mutex; +// bool m_locked; +// }; + +} + +#endif // H_EUDAQ_MUTEX diff --git a/rce/rcecalib/eudaq/Producer.cc b/rce/rcecalib/eudaq/Producer.cc new file mode 100644 index 00000000..84283f4f --- /dev/null +++ b/rce/rcecalib/eudaq/Producer.cc @@ -0,0 +1,14 @@ +#include "eudaq/Producer.hh" + +namespace eudaq { + + Producer::Producer(const std::string & name, const std::string & runcontrol) + : CommandReceiver("Producer", name, runcontrol), + DataSender("Producer", name) + { + } + + void Producer::OnData(const std::string & param) { + Connect(param); + } +} diff --git a/rce/rcecalib/eudaq/Producer.hh b/rce/rcecalib/eudaq/Producer.hh new file mode 100644 index 00000000..0ef779f0 --- /dev/null +++ b/rce/rcecalib/eudaq/Producer.hh @@ -0,0 +1,30 @@ +#ifndef EUDAQ_INCLUDED_Producer +#define EUDAQ_INCLUDED_Producer + +#include "eudaq/CommandReceiver.hh" +#include "eudaq/DataSender.hh" +#include <string> + +namespace eudaq { + + /** + * The base class from which all Producers should inherit. + * It is both a CommandReceiver, listening to commands from RunControl, + * and a DataSender, sending data to a DataCollector. + */ + class Producer : public CommandReceiver, public DataSender { + public: + /** + * The constructor. + * \param runcontrol A string containing the address of the RunControl to connect to. + */ + Producer(const std::string & name, const std::string & runcontrol); + virtual ~Producer() {} + + virtual void OnData(const std::string & param); + private: + }; + +} + +#endif // EUDAQ_INCLUDED_Producer diff --git a/rce/rcecalib/eudaq/ProducerIF.cc b/rce/rcecalib/eudaq/ProducerIF.cc new file mode 100644 index 00000000..69a130bd --- /dev/null +++ b/rce/rcecalib/eudaq/ProducerIF.cc @@ -0,0 +1,15 @@ +#include "rcecalib/eudaq/ProducerIF.hh" + +#include "rcecalib/eudaq/Producer.hh" + +eudaq::Producer* ProducerIF::m_producer=0; + +void ProducerIF::setProducer(eudaq::Producer* producer){ + m_producer=producer; +} + +void ProducerIF::sendEvent(eudaq::Event* ev){ + if(m_producer!=0){ + m_producer->SendEvent(*ev); + } +} diff --git a/rce/rcecalib/eudaq/ProducerIF.hh b/rce/rcecalib/eudaq/ProducerIF.hh new file mode 100644 index 00000000..0a12ca86 --- /dev/null +++ b/rce/rcecalib/eudaq/ProducerIF.hh @@ -0,0 +1,18 @@ +#ifndef PRODUCERIF_HH +#define PRODUCERIF_HH + +namespace eudaq{ + class Event; + class Producer; +} + +class ProducerIF{ +public: + static void sendEvent(eudaq::Event *ev); + static void setProducer(eudaq::Producer* producer); +private: + static eudaq::Producer *m_producer; + +}; + +#endif diff --git a/rce/rcecalib/eudaq/RawDataEvent.cc b/rce/rcecalib/eudaq/RawDataEvent.cc new file mode 100644 index 00000000..d152f7b4 --- /dev/null +++ b/rce/rcecalib/eudaq/RawDataEvent.cc @@ -0,0 +1,60 @@ +#include "eudaq/RawDataEvent.hh" + +#include <ostream> + +namespace eudaq { + + EUDAQ_DEFINE_EVENT(RawDataEvent, str2id("_RAW")); + + RawDataEvent::block_t::block_t(Deserializer & des) { + des.read(id); + des.read(data); + } + + void RawDataEvent::block_t::Serialize(Serializer & ser) const { + ser.write(id); + ser.write(data); + } + + void RawDataEvent::block_t::Append(const RawDataEvent::data_t & d) { + data.insert(data.end(), d.begin(), d.end()); + } + + RawDataEvent::RawDataEvent(std::string type, unsigned run, unsigned event) : + Event(run, event), + m_type(type) + { + } + + RawDataEvent::RawDataEvent(Deserializer & ds) : + Event(ds) + { + ds.read(m_type); + ds.read(m_blocks); + } + + unsigned RawDataEvent::GetID(size_t i) const { + return m_blocks.at(i).id; + } + + const RawDataEvent::data_t & RawDataEvent::GetBlock(size_t i) const { + return m_blocks.at(i).data; + } + + RawDataEvent::byte_t RawDataEvent::GetByte(size_t block, size_t index) const { + return GetBlock(block).at(index); + } + + void RawDataEvent::Print(std::ostream & os) const { + Event::Print(os); + std::string tluevstr = "unknown"; + os << ", " << m_blocks.size() << " blocks, tluev=" << tluevstr; + } + + void RawDataEvent::Serialize(Serializer & ser) const { + Event::Serialize(ser); + ser.write(m_type); + ser.write(m_blocks); + } + +} diff --git a/rce/rcecalib/eudaq/RawDataEvent.hh b/rce/rcecalib/eudaq/RawDataEvent.hh new file mode 100644 index 00000000..d75fa050 --- /dev/null +++ b/rce/rcecalib/eudaq/RawDataEvent.hh @@ -0,0 +1,112 @@ +#ifndef EUDAQ_INCLUDED_RawDataEvent +#define EUDAQ_INCLUDED_RawDataEvent + +#include <sstream> + +#include <vector> +#include "eudaq/Event.hh" + +namespace eudaq { + + /** An Event type consisting of just a vector of bytes. + * + */ + class RawDataEvent : public Event { + EUDAQ_DECLARE_EVENT(RawDataEvent); + public: + typedef unsigned char byte_t; + typedef std::vector<byte_t> data_t; + struct block_t : public Serializable { + block_t(unsigned id = (unsigned)-1, data_t data = data_t()) : id(id), data(data) {} + block_t(Deserializer &); + void Serialize(Serializer &) const; + void Append(const data_t & data); + unsigned id; + data_t data; + }; + + RawDataEvent(std::string type, unsigned run, unsigned event); + RawDataEvent(Deserializer &); + + /// Add an empty block + size_t AddBlock(unsigned id) { + m_blocks.push_back(block_t(id)); + return m_blocks.size() - 1; + } + + /// Add a data block as std::vector + template <typename T> + size_t AddBlock(unsigned id, const std::vector<T> & data) { + m_blocks.push_back(block_t(id, make_vector(data))); + return m_blocks.size() - 1; + } + + /// Add a data block as array with given size + template <typename T> + size_t AddBlock(unsigned id, const T * data, size_t bytes) { + m_blocks.push_back(block_t(id, make_vector(data, bytes))); + return m_blocks.size() - 1; + } + + /// Append data to a block as std::vector + template <typename T> + void AppendBlock(size_t index, const std::vector<T> & data) { + m_blocks[index].Append(make_vector(data)); + } + + /// Append data to a block as array with given size + template <typename T> + void AppendBlock(size_t index, const T * data, size_t bytes) { + m_blocks[index].Append(make_vector(data, bytes)); + } + + unsigned GetID(size_t i) const; + /** Get the data block number i as vector of \c{unsigned char}, which is the byte sequence which + * which has been serialised. This is the recommended way to retrieve your + * data from the RawDataEvent since the other GetBlock functions might + * give different results depending on the endiannes of your mashine. + */ + const data_t & GetBlock(size_t i) const; + byte_t GetByte(size_t block, size_t index) const; + + /// Return the number of data blocks in the RawDataEvent + size_t NumBlocks() const { return m_blocks.size(); } + + virtual void Print(std::ostream &) const; + static RawDataEvent BORE(std::string type, unsigned run) { + return RawDataEvent(type, run, (unsigned)-1, Event::FLAG_BORE); + } + static RawDataEvent EORE(std::string type, unsigned run, unsigned event) { + return RawDataEvent(type, run, event, Event::FLAG_EORE); + } + virtual void Serialize(Serializer &) const; + + /// Return the type string. + virtual std::string GetSubType() const { return m_type; } + + private: + // private constructor to create BORE and EORE + // make sure that event number is 0 for BORE + RawDataEvent(std::string type, unsigned run, unsigned event, Event::Flags flag) + : Event(run, event, NOTIMESTAMP, flag) , m_type(type) + {} + + template <typename T> + static data_t make_vector(const T * data, size_t bytes) { + const unsigned char * ptr = reinterpret_cast<const byte_t *>(data); + return data_t(ptr, ptr + bytes); + } + + template <typename T> + static data_t make_vector(const std::vector<T> & data) { + const unsigned char * ptr = reinterpret_cast<const byte_t *>(&data[0]); + return data_t(ptr, ptr + data.size() * sizeof(T)); + } + + std::string m_type; + std::vector<block_t> m_blocks; + }; + +} + +#endif // EUDAQ_INCLUDED_RawDataEvent diff --git a/rce/rcecalib/eudaq/Serializable.hh b/rce/rcecalib/eudaq/Serializable.hh new file mode 100644 index 00000000..bce5dc0c --- /dev/null +++ b/rce/rcecalib/eudaq/Serializable.hh @@ -0,0 +1,22 @@ +#ifndef EUDAQ_INCLUDED_Serializable +#define EUDAQ_INCLUDED_Serializable + +//#include <string> +//#include <vector> +//#include <map> +//#include <iosfwd> + +namespace eudaq { + + class Serializer; + + class Serializable { + public: + virtual void Serialize(Serializer &) const = 0; + virtual ~Serializable() {} + + }; + +} + +#endif // EUDAQ_INCLUDED_Serializable diff --git a/rce/rcecalib/eudaq/Serializer.hh b/rce/rcecalib/eudaq/Serializer.hh new file mode 100644 index 00000000..8ef72c6c --- /dev/null +++ b/rce/rcecalib/eudaq/Serializer.hh @@ -0,0 +1,262 @@ +#ifndef EUDAQ_INCLUDED_Serializer +#define EUDAQ_INCLUDED_Serializer + +#include <string> +#include <vector> +#include <map> +#include "eudaq/Serializable.hh" +#include "eudaq/counted_ptr.hh" +#include "eudaq/Time.hh" +#include "eudaq/Exception.hh" + +namespace eudaq { + + class InterruptedException : public std::exception { + const char * what() const throw() { return "InterruptedException"; } + }; + + class Serializer { + public: + virtual void Flush() {} + void write(const Serializable & t) { + t.Serialize(*this); + } + template<typename T> + void write(const T & t); + template<typename T> + void write(const std::vector<T> & t); + template<typename T, typename U> + void write(const std::map<T, U> & t); + + virtual ~Serializer() {} + private: + template <typename T> + friend struct WriteHelper; + virtual void Serialize(const unsigned char *, size_t) = 0; + }; + + template <typename T> + struct WriteHelper { + typedef void (*writer)(Serializer & ser, const T & v); + static writer GetFunc(Serializable *) { return write_ser; } + static writer GetFunc(float *) { return write_float; } + static writer GetFunc(double *) { return write_double; } + static writer GetFunc(...) { return write_int; } + + static void write_ser(Serializer & sr, const T & v) { + v.Serialize(sr); + } + static void write_int(Serializer & sr, const T & v) { + T t = v; + unsigned char buf[sizeof t]; + for (size_t i = 0; i < sizeof t; ++i) { + buf[i] = t & 0xff; + t >>= 8; + } + sr.Serialize(buf, sizeof t); + } + static void write_float(Serializer & sr, const float & v) { + unsigned t = *(unsigned *)&v; + unsigned char buf[sizeof t]; + for (size_t i = 0; i < sizeof t; ++i) { + buf[i] = t & 0xff; + t >>= 8; + } + sr.Serialize(buf, sizeof t); + } + static void write_double(Serializer & sr, const double & v) { + unsigned long long t = *(unsigned long long *)&v; + unsigned char buf[sizeof t]; + for (size_t i = 0; i < sizeof t; ++i) { + buf[i] = t & 0xff; + t >>= 8; + } + sr.Serialize(buf, sizeof t); + } + }; + + template <typename T> + inline void Serializer::write(const T & v) { + WriteHelper<T>::GetFunc(static_cast<T*>(0))(*this, v); + } + + template <> + inline void Serializer::write(const std::string & t) { + write((unsigned)t.length()); + Serialize(reinterpret_cast<const unsigned char *>(&t[0]), t.length()); + } + + template <> + inline void Serializer::write(const Time & t) { + write((int)timeval(t).tv_sec); + write((int)timeval(t).tv_usec); + } + + template <typename T> + inline void Serializer::write(const std::vector<T> & t) { + unsigned len = t.size(); + write(len); + for (size_t i = 0; i < len; ++i) { + write(t[i]); + } + } + + template <> + inline void Serializer::write<unsigned char>(const std::vector<unsigned char> & t) { + write((unsigned)t.size()); + Serialize(&t[0], t.size()); + } + + template <> + inline void Serializer::write<char>(const std::vector<char> & t) { + write((unsigned)t.size()); + Serialize(reinterpret_cast<const unsigned char *>(&t[0]), t.size()); + } + + template <typename T, typename U> + inline void Serializer::write(const std::map<T, U> & t) { + unsigned len = (unsigned)t.size(); + write(len); + for (typename std::map<T, U>::const_iterator i = t.begin(); i != t.end(); ++i) { + write(i->first); + write(i->second); + } + } + + class Deserializer { + public: + Deserializer() : m_interrupting(false) {} + virtual bool HasData() = 0; + void Interrupt() { m_interrupting = true; } + + template <typename T> + void read(T & t); + + template <typename T> + void read(std::vector<T> & t); + + template <typename T, typename U> + void read(std::map<T, U> & t); + + template <typename T> + T read() { + T t; + read(t); + return t; + } + + virtual ~Deserializer() {} + protected: + bool m_interrupting; + private: + template <typename T> + friend struct ReadHelper; + virtual void Deserialize(unsigned char *, size_t) = 0; + }; + + template <typename T> + struct ReadHelper { + typedef T (*reader)(Deserializer & ser); + static reader GetFunc(Serializable *) { return read_ser; } + static reader GetFunc(float *) { return read_float; } + static reader GetFunc(double *) { return read_double; } + static reader GetFunc(...) { return read_int; } + + static T read_ser(Deserializer & ds) { + return T(ds); + } + static T read_int(Deserializer & ds) { + unsigned char buf[sizeof (T)]; + ds.Deserialize(buf, sizeof (T)); + T t = 0; + for (size_t i = 0; i < sizeof t; ++i) { + t <<= 8; + t += buf[sizeof t - 1 - i]; + } + return t; + } + static float read_float(Deserializer & ds) { + unsigned char buf[sizeof (float)]; + ds.Deserialize(buf, sizeof buf); + unsigned t = 0; + for (size_t i = 0; i < sizeof t; ++i) { + t <<= 8; + t += buf[sizeof t - 1 - i]; + } + return *(float *)&t; + } + static double read_double(Deserializer & ds) { + union { double d; unsigned long long i; unsigned char b[sizeof (double)]; } u; + //unsigned char buf[sizeof (double)]; + ds.Deserialize(u.b, sizeof u.b); + unsigned long long t = 0; + for (size_t i = 0; i < sizeof t; ++i) { + t <<= 8; + t += u.b[sizeof t - 1 - i]; + } + u.i = t; + return u.d; + } + }; + + template <typename T> + inline void Deserializer::read(T & t) { + t = ReadHelper<T>::GetFunc(static_cast<T*>(0))(*this); + } + + template <> + inline void Deserializer::read(std::string & t) { + unsigned len = 0; + read(len); + t = std::string(len, ' '); + if (len) Deserialize(reinterpret_cast<unsigned char *>(&t[0]), len); + } + + template <> + inline void Deserializer::read(Time & t) { + int sec, usec; + read(sec); + read(usec); + t = Time(sec, usec); + } + + template <typename T> + inline void Deserializer::read(std::vector<T> & t) { + unsigned len = 0; + read(len); + t.reserve(len); + for (size_t i = 0; i < len; ++i) { + t.push_back(read<T>()); + } + } + + template <> + inline void Deserializer::read<unsigned char>(std::vector<unsigned char> & t) { + unsigned len = 0; + read(len); + t.resize(len); + Deserialize(&t[0], len); + } + + template <> + inline void Deserializer::read<char>(std::vector<char> & t) { + unsigned len = 0; + read(len); + t.resize(len); + Deserialize(reinterpret_cast<unsigned char *>(&t[0]), len); + } + + template<typename T, typename U> + inline void Deserializer::read(std::map<T, U> & t) { + unsigned len = 0; + read(len); + for (size_t i = 0; i < len; ++i) { + std::string name = read<std::string>(); + std::string val = read<std::string>(); + t[name]=val; + } + } + +} + +#endif // EUDAQ_INCLUDED_Serializer diff --git a/rce/rcecalib/eudaq/Status.cc b/rce/rcecalib/eudaq/Status.cc new file mode 100644 index 00000000..d58c6466 --- /dev/null +++ b/rce/rcecalib/eudaq/Status.cc @@ -0,0 +1,63 @@ +#include "eudaq/Status.hh" +#include "eudaq/Exception.hh" +#include "eudaq/Utils.hh" + +namespace eudaq { + + Status::Status(Deserializer & ds) { + ds.read(m_level); + ds.read(m_msg); + ds.read(m_tags); + } + + void Status::Serialize(Serializer & ser) const { + ser.write(m_level); + ser.write(m_msg); + ser.write(m_tags); + } + + std::string Status::Level2String(int level) { + static const char * const strings[] = { + "DEBUG", + "OK", + "THROW", + "EXTRA", + "INFO", + "WARN", + "ERROR", + "USER", + "NONE" + }; + if (level < LVL_DEBUG || level > LVL_NONE) return ""; + return strings[level]; + } + + int Status::String2Level(const std::string & str) { + int lvl = 0; + std::string tmpstr1, tmpstr2 = ucase(str); + while ((tmpstr1 = Level2String(lvl)) != "") { + if (tmpstr1 == tmpstr2) return lvl; + lvl++; + } + EUDAQ_THROW("Unrecognised level: " + str); + } + + Status & Status::SetTag(const std::string & name, const std::string & val) { + m_tags[name] = val; + return *this; + } + + std::string Status::GetTag(const std::string & name, const std::string & def) const { + std::map<std::string, std::string>::const_iterator i = m_tags.find(name); + if (i == m_tags.end()) return def; + return i->second; + } + + void Status::print(std::ostream & os) const { + os << Level2String(m_level); + if (m_msg != "") { + os << ": " << m_msg; + } + } + +} diff --git a/rce/rcecalib/eudaq/Status.hh b/rce/rcecalib/eudaq/Status.hh new file mode 100644 index 00000000..5dc0bb79 --- /dev/null +++ b/rce/rcecalib/eudaq/Status.hh @@ -0,0 +1,51 @@ +#ifndef EUDAQ_INCLUDED_Status +#define EUDAQ_INCLUDED_Status + +#include "eudaq/Serializable.hh" +#include "eudaq/Serializer.hh" +#include <string> +#include <ostream> + +namespace eudaq { + + class Status : public Serializable { + public: + enum Level { + LVL_DEBUG, + LVL_OK, + LVL_THROW, + LVL_EXTRA, + LVL_INFO, + LVL_WARN, + LVL_ERROR, + LVL_USER, + LVL_NONE + }; + Status(int level = LVL_OK, const std::string & msg = "") + : m_level(level), m_msg(msg) {} + Status(Deserializer &); + virtual void Serialize(Serializer &) const; + + Status & SetTag(const std::string & name, const std::string & val); + std::string GetTag(const std::string & name, const std::string & def = "") const; + static std::string Level2String(int level); + static int String2Level(const std::string &); + virtual ~Status() {} + virtual void print(std::ostream &) const; + int GetLevel() const { return m_level; } + protected: + typedef std::map<std::string, std::string> map_t; + int m_level; + std::string m_msg; + map_t m_tags; ///< Metadata tags in (name=value) pairs of strings + }; + + inline std::ostream & operator << (std::ostream & os, const Status & s) { + s.print(os); + return os; + } + + +} + +#endif // EUDAQ_INCLUDED_Status diff --git a/rce/rcecalib/eudaq/TLUEvent.cc b/rce/rcecalib/eudaq/TLUEvent.cc new file mode 100644 index 00000000..7147975c --- /dev/null +++ b/rce/rcecalib/eudaq/TLUEvent.cc @@ -0,0 +1,26 @@ +#include "eudaq/TLUEvent.hh" + +#include <ostream> + +namespace eudaq { + + EUDAQ_DEFINE_EVENT(TLUEvent, str2id("_TLU")); + + TLUEvent::TLUEvent(Deserializer & ds) : + Event(ds) + { + ds.read(m_extratimes); + } + + void TLUEvent::Print(std::ostream & os) const { + Event::Print(os); + if (m_extratimes.size() > 0) { + os << " [" << m_extratimes.size() << " extra]"; + } + } + + void TLUEvent::Serialize(Serializer & ser) const { + Event::Serialize(ser); + ser.write(m_extratimes); + } +} diff --git a/rce/rcecalib/eudaq/TLUEvent.hh b/rce/rcecalib/eudaq/TLUEvent.hh new file mode 100644 index 00000000..a4aaf987 --- /dev/null +++ b/rce/rcecalib/eudaq/TLUEvent.hh @@ -0,0 +1,39 @@ +#ifndef EUDAQ_INCLUDED_TLUEvent +#define EUDAQ_INCLUDED_TLUEvent + +#include <vector> +#include "eudaq/Event.hh" + +namespace eudaq { + + class TLUEvent : public Event { + EUDAQ_DECLARE_EVENT(TLUEvent); + public: + typedef std::vector<unsigned long long> vector_t; + virtual void Serialize(Serializer &) const; + explicit TLUEvent(unsigned run, unsigned event, unsigned long long timestamp, + const vector_t & extratimes = vector_t()) : + Event(run, event, timestamp), + m_extratimes(extratimes) {} + explicit TLUEvent(Deserializer &); + virtual void Print(std::ostream &) const; + + /// Return "TLUEvent" as type. + virtual std::string GetType() const {return "TLUEvent";} + + static TLUEvent BORE(unsigned run) { + return TLUEvent(run); + } + static TLUEvent EORE(unsigned run, unsigned event) { + return TLUEvent(run, event); + } + private: + TLUEvent(unsigned run, unsigned event = 0) + : Event(run, event, NOTIMESTAMP, event ? Event::FLAG_EORE : Event::FLAG_BORE) + {} + vector_t m_extratimes; + }; + +} + +#endif // EUDAQ_INCLUDED_TLUEvent diff --git a/rce/rcecalib/eudaq/Time.cc b/rce/rcecalib/eudaq/Time.cc new file mode 100644 index 00000000..00331841 --- /dev/null +++ b/rce/rcecalib/eudaq/Time.cc @@ -0,0 +1,60 @@ +#include "eudaq/Time.hh" +#include "eudaq/Exception.hh" +#include <ctime> +#include <iostream> + + +namespace eudaq { + + const std::string Time::DEFAULT_FORMAT = "%Y-%m-%d %H:%M:%S.%3"; + + Time Time::Current() { + timeval tv; + if (gettimeofday(&tv, 0)) { + std::cout<<"Error getting current time: "<< strerror(errno)<<std::endl; + } + return tv; + } + + + Time::Time(int year, int month, int date, int hour, int minute, int sec, int usec) { + struct tm time; + //time.tm_gmtoff = 0; + time.tm_isdst = -1; + time.tm_year = year - 1900; + time.tm_mon = month - 1; + time.tm_mday = date; + time.tm_hour = hour; + time.tm_min = minute; + time.tm_sec = sec + usec / 1000000; + tv_sec = mktime(&time); + tv_usec = usec % 1000000; + } + + std::string Time::Formatted(const std::string & format) const { + char buf[256]; + std::string fmt = format; + size_t i, pos = 0; + while ((i = fmt.find('%', pos)) != std::string::npos) { + //std::cout << "i=" << i << std::endl; + if (i >= fmt.length() - 1) break; + pos = i+2; + //std::cout << "pos=" << pos << std::endl; + int c = fmt[i+1] - '0'; + if (c >= 1 && c <= 6) { + //std::cout << "c=" << c << std::endl; + std::string usecs = to_string(tv_usec, 6); + //std::cout << "fmt=" << fmt << std::endl; + fmt = std::string(fmt, 0, i) + std::string(usecs, 0, c) + std::string(fmt, i+2); + //std::cout << "fmt=" << fmt << std::endl; + pos += c - 2; + //std::cout << "pos=" << pos << std::endl; + } + } + time_t t = tv_sec; + struct tm * tm = std::localtime(&t); + std::strftime(buf, sizeof buf, fmt.c_str(), tm); + return std::string(buf); + } + +} diff --git a/rce/rcecalib/eudaq/Time.hh b/rce/rcecalib/eudaq/Time.hh new file mode 100644 index 00000000..2d854da4 --- /dev/null +++ b/rce/rcecalib/eudaq/Time.hh @@ -0,0 +1,89 @@ +#ifndef EUDAQ_INCLUDED_Time +#define EUDAQ_INCLUDED_Time + +#include <errno.h> +#include <ostream> +#include <iomanip> +#include <string> +#include <cstring> + +# include <sys/time.h> + +namespace eudaq { + + class Time { + public: + static const std::string DEFAULT_FORMAT; + explicit Time(long sec, long usec = 0) { + tv_usec = usec % 1000000; + tv_sec = sec + usec / 1000000; + } + Time(int year, int month, int date, int hour = 0, int minute = 0, int sec = 0, int usec = 0); + Time(timeval tv) { + tv_usec = tv.tv_usec % 1000000; + tv_sec = tv.tv_sec + tv.tv_usec / 1000000; + } + double Seconds() const { return tv_sec + tv_usec / 1e6; } + Time & operator += (const timeval & other) { + tv_usec += other.tv_usec; + tv_sec += other.tv_sec + tv_usec / 1000000; + tv_usec %= 1000000; + return *this; + } + Time & operator -= (const timeval & other) { + if (tv_usec < other.tv_usec) { + tv_usec += 1000000 - other.tv_usec; + tv_sec -= other.tv_sec + 1; + } else { + tv_usec -= other.tv_usec; + tv_sec -= other.tv_sec; + } + return *this; + } + bool operator < (const timeval & other) { + return tv_sec < other.tv_sec || + (tv_sec == other.tv_sec && tv_usec < other.tv_usec); + } + bool operator > (const timeval & other) { + return tv_sec > other.tv_sec || + (tv_sec == other.tv_sec && tv_usec > other.tv_usec); + } + operator const timeval () const { + timeval tv; + tv.tv_sec = tv_sec; + tv.tv_usec = tv_usec; + return tv; + } + std::string Formatted(const std::string & format = DEFAULT_FORMAT) const; + static Time Current(); + private: + long tv_sec; + long tv_usec; + }; + + inline Time operator + (const timeval & lhs, const timeval rhs) { + Time t(lhs); + t += rhs; + return t; + } + + inline Time operator - (const timeval & lhs, const timeval rhs) { + Time t(lhs); + t -= rhs; + return t; + } + + inline bool operator == (const timeval & lhs, const timeval rhs) { + return (lhs.tv_sec == rhs.tv_sec) && (lhs.tv_usec == rhs.tv_usec); + } + + inline std::ostream & operator << (std::ostream & os, const timeval & tv) { + if (tv.tv_sec < 0) { + return os << '-' << Time(-tv.tv_sec - 1, 1000000 - tv.tv_usec); + } + return os << tv.tv_sec << '.' << std::setw(6) << std::setfill('0') << tv.tv_usec << std::setfill(' '); + } + +} + +#endif // EUDAQ_INCLUDED_Time diff --git a/rce/rcecalib/eudaq/TransportBase.cc b/rce/rcecalib/eudaq/TransportBase.cc new file mode 100644 index 00000000..bfcc2a59 --- /dev/null +++ b/rce/rcecalib/eudaq/TransportBase.cc @@ -0,0 +1,103 @@ +#include "eudaq/TransportBase.hh" +#include <ostream> +#include <iostream> + +namespace eudaq { + + const ConnectionInfo ConnectionInfo::ALL("ALL"); + static const int DEFAULT_TIMEOUT = 1000; + + void ConnectionInfo::Print(std::ostream & os) const { + if (m_state == -1) { + os << "(disconnected)"; + } else if (m_state == 0) { + os << "(waiting)"; + } else { + os << m_type; + if (m_name != "") os << "." << m_name; + } + } + + bool ConnectionInfo::Matches(const ConnectionInfo & /*other*/) const { + //std::cout << " [Match: all] " << std::flush; + return true; + } + + TransportBase::TransportBase() + : m_callback(0) + {} + + void TransportBase::SetCallback(const TransportCallback & callback) { + m_callback = callback; + } + + void TransportBase::Process(int timeout) { + if (timeout == -1) timeout = DEFAULT_TIMEOUT; + MutexLock m(m_mutex); + ProcessEvents(timeout); + m.Release(); + for (;;) { + MutexLock m(m_mutex); + if (m_events.empty()) break; + //std::cout << "Got packet" << std::endl; + TransportEvent evt(m_events.front()); + m_events.pop(); + m.Release(); + m_callback(evt); + } + } + + bool TransportBase::ReceivePacket(std::string * packet, int timeout, const ConnectionInfo & conn) { + if (timeout == -1) timeout = DEFAULT_TIMEOUT; + //std::cout << "ReceivePacket()" << std::flush; + while (!m_events.empty() && m_events.front().etype != TransportEvent::RECEIVE) { + m_events.pop(); + } + //std::cout << " current level=" << m_events.size() << std::endl; + if (m_events.empty()) { + //std::cout << "Getting more" << std::endl; + ProcessEvents(timeout); + //std::cout << "Temp level=" << m_events.size() << std::endl; + while (!m_events.empty() && m_events.front().etype != TransportEvent::RECEIVE) { + m_events.pop(); + } + //std::cout << "New level=" << m_events.size() << std::endl; + } + bool ret = false; + if (!m_events.empty() && conn.Matches(m_events.front().id)) { + ret = true; + *packet = m_events.front().packet; + m_events.pop(); + } + //std::cout << "ReceivePacket() return " << (ret ? "true" : "false") << std::endl; + return ret; + } + + bool TransportBase::SendReceivePacket(const std::string & sendpacket, + std::string * recpacket, + const ConnectionInfo & connection, + int timeout) + { + // acquire mutex... + if (timeout == -1) timeout = DEFAULT_TIMEOUT; + //std::cout << "DEBUG: SendReceive: Acquiring mutex" << std::endl; + std::cout<<"Before lock 3"<<std::endl; + MutexLock m(m_mutex, false); + std::cout<<"After lock 3"<<std::endl; + try { + m.Lock(); + } catch (const eudaq::Exception &) { + // swallow it + } + //std::cout << "DEBUG: SendReceive: got mutex" << std::endl; + SendPacket(sendpacket, connection); + //std::cout << "DEBUG: SendReceive sent packet " << sendpacket << std::endl; + bool ret = ReceivePacket(recpacket, timeout, connection); + //std::cout << "SendReceivePacket() return '" << *recpacket << "' " << (ret ? "true" : "false") << std::endl; + return ret; + } + + TransportBase::~TransportBase() { + } + +} diff --git a/rce/rcecalib/eudaq/TransportBase.hh b/rce/rcecalib/eudaq/TransportBase.hh new file mode 100644 index 00000000..f31ec1fd --- /dev/null +++ b/rce/rcecalib/eudaq/TransportBase.hh @@ -0,0 +1,206 @@ +#ifndef EUDAQ_INCLUDED_TransportBase +#define EUDAQ_INCLUDED_TransportBase + +/** \file TransportBase.hh + * Defines TransportBase along with a number of related classes. + */ + +#include "eudaq/Mutex.hh" +#include "eudaq/Exception.hh" +#include "eudaq/BufferSerializer.hh" +#include <string> +#include <queue> +#include <iosfwd> +#include <cstring> +#include <iostream> + +namespace eudaq { + + /** Represents an individual connection on a Transport. + * + */ + class ConnectionInfo { + public: + explicit ConnectionInfo(const std::string & name = "") : m_state(0), m_name(name) {} + virtual ~ConnectionInfo() {} + virtual void Print(std::ostream &) const; + virtual bool Matches(const ConnectionInfo & other) const; + bool IsEnabled() const { return m_state >= 0; } + int GetState() const { return m_state; } + void SetState(int state) { m_state = state; } + std::string GetType() const { return m_type; } + void SetType(const std::string & type) { m_type = type; } + std::string GetName() const { return m_name; } + void SetName(const std::string & name) { m_name = name; } + virtual std::string GetRemote() const { return ""; } + static const ConnectionInfo ALL; + + virtual ConnectionInfo * Clone() const { return new ConnectionInfo(*this); } + protected: + int m_state; + std::string m_type, m_name; + /* + public: + virtual bool operator = (const ClientID & other) = 0; + virtual std::string Name() const = 0; + */ + }; + + inline std::ostream & operator << (std::ostream & os, const ConnectionInfo & id) { + id.Print(os); + return os; + } + + /** Represents an event such as a connection, or receipt of data on a Transport. + */ + struct TransportEvent { + enum EventType { CONNECT, DISCONNECT, RECEIVE }; + TransportEvent(EventType et, ConnectionInfo & i, const std::string & p = "") + : etype(et), id(i), packet(p) {} + EventType etype; ///< The type of event + ConnectionInfo & id; ///< The id of the connection + std::string packet; ///< The packet of data in case of a RECEIVE event + }; + + /** Represents a callback function for the Transport system. + * It can hold a pointer to a callback function which can be + * either a free function or an object and a member function. + * It is like a simplified and less flexible version of boost::function. + * I didn't use boost::function because I didn't want to rely + * on too many external dependencies. + */ + class TransportCallback { + /** A helper class for TransportCallback. + * It specifies an interface from which the actual helpers inherit. + */ + class Helper { + public: + virtual void call(TransportEvent &) = 0; + virtual ~Helper() { } + virtual Helper * Clone() const = 0; + }; + /** A helper class for TransportCallback for normal function pointers. + * It performs the actual function call for a normal function pointer. + */ + class HelperFunction : public Helper { + public: + typedef void (*FuncType)(TransportEvent &); + HelperFunction(FuncType func) : m_func(func) { } + virtual void call(TransportEvent & ev) { m_func(ev); } + virtual Helper * Clone() const { return new HelperFunction(*this); } + private: + FuncType m_func; ///< A pointer to the function to call + }; + /** A helper class for TransportCallback for member function pointers. + * It performs the actual function call for a member function pointer. + * It also stores a pointer to the object on which to call the member function. + */ + template <typename T> + class HelperMember : public Helper { + public: + typedef T ObjType; + typedef void (ObjType::*FuncType)(TransportEvent &); + HelperMember(ObjType * obj, FuncType func) : m_obj(obj), m_func(func) {} + virtual void call(TransportEvent & ev) { + (m_obj->*m_func)(ev); + } + virtual Helper * Clone() const { return new HelperMember(*this); } + private: + ObjType *m_obj; ///< A pointer to the object + FuncType m_func; ///< A pointer to the member function + }; + public: + TransportCallback() : m_helper(0) {} + TransportCallback(HelperFunction::FuncType funcptr) + : m_helper(new HelperFunction(funcptr)) {} + template <typename T> + TransportCallback(T * obj, typename HelperMember<T>::FuncType func) + : m_helper(new HelperMember<T>(obj, func)) {} + void operator () (TransportEvent & ev) { + if(m_helper) m_helper->call(ev); + } + TransportCallback(const TransportCallback & other) + : m_helper(other.m_helper->Clone()) {} + TransportCallback & operator=(const TransportCallback & other) { + delete m_helper; + m_helper = other.m_helper->Clone(); + return *this; + } + ~TransportCallback() { delete m_helper; } + private: + Helper * m_helper; ///< The helper class to perform the actual function call + }; + + /** A base class from which all types of Transport should inherit. + * They must implement the two pure virtual member functions SendPacket and ProcessEvents. + * A Transport is a means of transferring data or commands from one + * process to another, possibly on another machine. + */ + class TransportBase { + public: + TransportBase(); + virtual ~TransportBase(); + + /** Pure virtual function to send a packet of data. + * This function must be implemented by the concrete Transport class to send a + * packet of data to the remote Transport instance. + */ + virtual void SendPacket(const unsigned char * data, size_t len, + const ConnectionInfo & = ConnectionInfo::ALL, + bool duringconnect = false) = 0; + void SendPacket(const std::string & data, const ConnectionInfo & inf = ConnectionInfo::ALL, bool duringconnect = false) { + //std::cout << "SendPacket (string)" << std::endl; + SendPacket(reinterpret_cast<const unsigned char *>(&data[0]), data.length(), inf, duringconnect); + } + void SendPacket(const char * str, const ConnectionInfo & inf = ConnectionInfo::ALL, bool duringconnect = false) { + //std::cout << "SendPacket (char*)" << std::endl; + SendPacket(reinterpret_cast<const unsigned char *>(str), std::strlen(str), inf, duringconnect); + } + void SendPacket(const BufferSerializer & t, const ConnectionInfo & inf = ConnectionInfo::ALL, bool duringconnect = false) { + SendPacket(&t[0], t.size(), inf, duringconnect); + } + + /** Pure virtual function to close a connection. + * This function should be implemented by the concrete Transport class to close + * the connection to the specified remote Transport instance. + */ + virtual void Close(const ConnectionInfo &) {} + + /** Pure virtual function to receive data. + * This function must be implemented by the concrete Transport class to receive + * all pending data from the remote Transport instance, and fill the queue of + * events so that they may be handled. + */ + virtual void ProcessEvents(int timeout) = 0; + + void Process(int timeout = -1); + bool ReceivePacket(std::string * packet, int timeout = -1, const ConnectionInfo & = ConnectionInfo::ALL); + bool SendReceivePacket(const std::string & sendpacket, + std::string * recpacket, + const ConnectionInfo & connection, + int timeout = -1); + template <typename T> + T SendReceivePacket(const std::string & packet, const ConnectionInfo & connection, int timeout = -1); + void SetCallback(const TransportCallback &); + virtual bool IsNull() const { return false; } + protected: + std::queue<TransportEvent> m_events; ///< A buffer to queue up events until they are handled + TransportCallback m_callback; ///< The callback function to invoke on a transport event + Mutex m_mutex; + }; + + template <typename T> + inline T TransportBase::SendReceivePacket(const std::string & packet, const ConnectionInfo & connection, int timeout) { + std::string buf; + bool ok = SendReceivePacket(packet, &buf, connection, timeout); + if (!ok) EUDAQ_THROW("Timeout: No response in SendReceivePacket"); + BufferSerializer ser(buf.begin(), buf.end()); + T result; + ser.read(result); + return result; + } + + +} + +#endif // EUDAQ_INCLUDED_TransportBase diff --git a/rce/rcecalib/eudaq/TransportClient.cc b/rce/rcecalib/eudaq/TransportClient.cc new file mode 100644 index 00000000..ce859fb2 --- /dev/null +++ b/rce/rcecalib/eudaq/TransportClient.cc @@ -0,0 +1,8 @@ +#include "eudaq/TransportFactory.hh" + +namespace eudaq { + + TransportClient::~TransportClient() { + } + +} diff --git a/rce/rcecalib/eudaq/TransportClient.hh b/rce/rcecalib/eudaq/TransportClient.hh new file mode 100644 index 00000000..525d15bc --- /dev/null +++ b/rce/rcecalib/eudaq/TransportClient.hh @@ -0,0 +1,19 @@ +#ifndef EUDAQ_INCLUDED_TransportClient +#define EUDAQ_INCLUDED_TransportClient + +#include "eudaq/TransportBase.hh" +#include <string> + +namespace eudaq { + + class TransportClient : public TransportBase { + public: + //virtual void SendPacket(const std::string & packet) = 0; + //virtual bool ReceivePacket(std::string * packet, int timeout = -1) = 0; + + virtual ~TransportClient(); + }; + +} + +#endif // EUDAQ_INCLUDED_TransportClient diff --git a/rce/rcecalib/eudaq/TransportFactory.cc b/rce/rcecalib/eudaq/TransportFactory.cc new file mode 100644 index 00000000..a0f0f1ca --- /dev/null +++ b/rce/rcecalib/eudaq/TransportFactory.cc @@ -0,0 +1,86 @@ +#include "eudaq/TransportFactory.hh" +#include "eudaq/Exception.hh" +#include <iostream> +#include <ostream> +#include <string> +#include <map> + +// All transport header files must be included here +#include "eudaq/TransportNULL.hh" +#include "eudaq/TransportTCP.hh" + +namespace eudaq { + + /** Stores the name and factory methods for a type of Transport. + */ + struct TransportFactory::TransportInfo { + typedef TransportServer * (*ServerFactory)(const std::string &); + typedef TransportClient * (*ClientFactory)(const std::string &); + TransportInfo() : name(""), serverfactory(0), clientfactory(0) {} + TransportInfo(const std::string & nm, ServerFactory sf, ClientFactory cf): + name(nm), serverfactory(sf), clientfactory(cf) {} + std::string name; + ServerFactory serverfactory; + ClientFactory clientfactory; + }; + + namespace { + + template <typename T_Server, typename T_Client> + struct MakeTransportInfo : public TransportFactory::TransportInfo { + MakeTransportInfo(const std::string & thename) : + TransportInfo(thename, theserverfactory, theclientfactory) { + } + static TransportServer * theserverfactory(const std::string & param) { + return new T_Server(param); + } + static TransportClient * theclientfactory(const std::string & param) { + return new T_Client(param); + } + }; + + typedef std::map<std::string, TransportFactory::TransportInfo> map_t; + + static map_t & TransportMap() { + static bool initialised = false; + if (!initialised) { + initialised = true; + // All transports have to be registered here + TransportFactory::Register(MakeTransportInfo<NULLServer, NULLClient>(NULLServer::name)); + TransportFactory::Register(MakeTransportInfo<TCPServer, TCPClient>(TCPServer::name)); + } + static map_t m; + return m; + } + } + + void TransportFactory::Register(const TransportInfo & info) { + //std::cout << "DEBUG: TransportFactory::Register " << info.name << std::endl; + TransportMap()[info.name] = info; + } + + TransportServer * TransportFactory::CreateServer(const std::string & name) { + std::string proto = "tcp", param = name; + size_t i = name.find("://"); + if (i != std::string::npos) { + proto = std::string(name, 0, i); + param = std::string(name, i+3); + } + map_t::const_iterator it = TransportMap().find(proto); + if (it == TransportMap().end()) EUDAQ_THROW("Unknown protocol: " + proto); + return (it->second.serverfactory)(param); + } + + TransportClient * TransportFactory::CreateClient(const std::string & name) { + std::string proto = "tcp", param = name; + size_t i = name.find("://"); + if (i != std::string::npos) { + proto = std::string(name, 0, i); + param = std::string(name, i+3); + } + map_t::const_iterator it = TransportMap().find(proto); + if (it == TransportMap().end()) EUDAQ_THROW("Unknown protocol: " + proto); + return (it->second.clientfactory)(param); + } + +} diff --git a/rce/rcecalib/eudaq/TransportFactory.hh b/rce/rcecalib/eudaq/TransportFactory.hh new file mode 100644 index 00000000..9b6059a4 --- /dev/null +++ b/rce/rcecalib/eudaq/TransportFactory.hh @@ -0,0 +1,22 @@ +#ifndef EUDAQ_INCLUDED_TransportFactory +#define EUDAQ_INCLUDED_TransportFactory + +#include "eudaq/TransportClient.hh" +#include "eudaq/TransportServer.hh" + +namespace eudaq { + + /** Creates Transport instances from a name without needing to know the concrete type at compile time. + */ + class TransportFactory { + public: + static TransportServer * CreateServer(const std::string & name); + static TransportClient * CreateClient(const std::string & name); + + struct TransportInfo; + static void Register(const TransportInfo & info); + }; + +} + +#endif // EUDAQ_INCLUDED_TransportFactory diff --git a/rce/rcecalib/eudaq/TransportNULL.cc b/rce/rcecalib/eudaq/TransportNULL.cc new file mode 100644 index 00000000..097acc71 --- /dev/null +++ b/rce/rcecalib/eudaq/TransportNULL.cc @@ -0,0 +1,45 @@ +#include "eudaq/TransportNULL.hh" +#include "eudaq/Utils.hh" + +#include <iostream> + +namespace eudaq { + + const std::string NULLServer::name = "null"; + + NULLServer::NULLServer(const std::string &) { + } + + NULLServer::~NULLServer() { + } + + void NULLServer::Close(const ConnectionInfo &) { + } + + void NULLServer::SendPacket(const unsigned char *, size_t, const ConnectionInfo &, bool) { + } + + void NULLServer::ProcessEvents(int timeout) { + mSleep(timeout); + } + + std::string NULLServer::ConnectionString() const { + return "null://"; + } + + NULLClient::NULLClient(const std::string & /*param*/) { + } + + void NULLClient::SendPacket(const unsigned char *, size_t, const ConnectionInfo &, bool) { + } + + void NULLClient::ProcessEvents(int timeout) { + //std::cout << "NULLClient::ProcessEvents " << timeout << std::endl; + mSleep(timeout); + //std::cout << "ok" << std::endl; + } + + NULLClient::~NULLClient() { + } + +} diff --git a/rce/rcecalib/eudaq/TransportNULL.hh b/rce/rcecalib/eudaq/TransportNULL.hh new file mode 100644 index 00000000..ceb6978f --- /dev/null +++ b/rce/rcecalib/eudaq/TransportNULL.hh @@ -0,0 +1,45 @@ +#ifndef EUDAQ_INCLUDED_TransportNULL +#define EUDAQ_INCLUDED_TransportNULL + +#include "eudaq/TransportFactory.hh" + +#include <vector> +#include <string> +#include <map> + +namespace eudaq { + + class NULLServer : public TransportServer { + public: + NULLServer(const std::string & param); + virtual ~NULLServer(); + + virtual void Close(const ConnectionInfo & id); + virtual void SendPacket(const unsigned char * data, size_t len, + const ConnectionInfo & id = ConnectionInfo::ALL, + bool duringconnect = false); + virtual void ProcessEvents(int timeout); + + virtual std::string ConnectionString() const; + virtual bool IsNull() const { return true; } + static const std::string name; + private: + }; + + class NULLClient: public TransportClient { + public: + NULLClient(const std::string & param); + virtual ~NULLClient(); + + virtual void SendPacket(const unsigned char * data, size_t len, + const ConnectionInfo & id = ConnectionInfo::ALL, + bool = false); + virtual void ProcessEvents(int timeout = -1); + virtual bool IsNull() const { return true; } + private: + ConnectionInfo m_buf; + }; + +} + +#endif // EUDAQ_INCLUDED_TransportNULL diff --git a/rce/rcecalib/eudaq/TransportServer.cc b/rce/rcecalib/eudaq/TransportServer.cc new file mode 100644 index 00000000..334fe77f --- /dev/null +++ b/rce/rcecalib/eudaq/TransportServer.cc @@ -0,0 +1,12 @@ +#include "eudaq/TransportFactory.hh" +#include "eudaq/Utils.hh" + +#include <iostream> +#include <ostream> + +namespace eudaq { + + TransportServer::~TransportServer() { + } + +} diff --git a/rce/rcecalib/eudaq/TransportServer.hh b/rce/rcecalib/eudaq/TransportServer.hh new file mode 100644 index 00000000..17576138 --- /dev/null +++ b/rce/rcecalib/eudaq/TransportServer.hh @@ -0,0 +1,22 @@ +#ifndef EUDAQ_INCLUDED_TransportServer +#define EUDAQ_INCLUDED_TransportServer + +#include "eudaq/TransportBase.hh" +#include "eudaq/counted_ptr.hh" +#include <string> + +namespace eudaq { + + class TransportServer : public TransportBase { + public: + virtual ~TransportServer(); + virtual std::string ConnectionString() const = 0; + size_t NumConnections() const { return m_conn.size(); } + const ConnectionInfo & GetConnection(size_t i) const { return *m_conn[i]; } + protected: + std::vector<counted_ptr<ConnectionInfo> > m_conn; + }; + +} + +#endif // EUDAQ_INCLUDED_TransportServer diff --git a/rce/rcecalib/eudaq/TransportTCP.cc b/rce/rcecalib/eudaq/TransportTCP.cc new file mode 100644 index 00000000..f5e4986d --- /dev/null +++ b/rce/rcecalib/eudaq/TransportTCP.cc @@ -0,0 +1,473 @@ +#include "eudaq/TransportTCP.hh" +#include "eudaq/Exception.hh" +#include "eudaq/Time.hh" +#include "eudaq/Utils.hh" + +#include <boost/regex.hpp> +# include "eudaq/TransportTCP_POSIX.inc" + +#include <sys/types.h> +#include <sys/socket.h> +#include <errno.h> +//#include <unistd.h> +#ifdef __rtems__ + #define MSG_NOSIGNAL 0 + #include <netinet/in.h> + #include <sys/systm.h> +#endif + +#include <iostream> +#include <ostream> +#include <iostream> +#include "boost/assign.hpp" + +namespace eudaq { + + const std::string TCPServer::name = "tcp"; + + std::map<std::string, std::string> TCPClient::m_hosts=boost::assign::map_list_of + ("rdcds105", "172.21.6.45") + ("eudetmac001", "129.194.52.98") + ("rddev108", "172.21.7.146") + ("mac-atlas-tb-01", "137.138.113.225") + ("pc-atlas-tb-02", "137.138.115.189") + ("eudet","129.194.52.98"); + + namespace { + + static const int MAXPENDING = 16; + static const int MAX_BUFFER_SIZE = 10000; + + static int to_int(char c) { + return static_cast<unsigned char>(c); + } + +#ifdef MSG_NOSIGNAL + // On Linux (and cygwin?) send(...) can be told to + // ignore signals by setting the flag below + static const int FLAGS = MSG_NOSIGNAL; + static void setup_signal() { + } +#else +# include <signal.h> + // On Mac OS X (BSD?) this flag is not available, + // so we have to set the signal handler to ignore + static const int FLAGS = 0; + static void setup_signal() { + // static so that it is only done once + static sig_t sig = signal(SIGPIPE, SIG_IGN); + (void)sig; + } +#endif + + static void do_send_data(SOCKET sock, const unsigned char * data, size_t len) { + //if (len > 500000) std::cout << "Starting send" << std::endl; + size_t sent = 0; + do { + int result = send(sock, + reinterpret_cast<const char*>(data+sent), + static_cast<int>(len-sent), + FLAGS); + if (result > 0) { + sent += result; + } else if (result < 0 && (LastSockError() == EAGAIN || LastSockError() == EINTR)) { + // continue + } else if (result == 0) { + EUDAQ_THROW("Connection reset by peer"); + } else if (result < 0) { + EUDAQ_THROW(LastSockErrorString("Error sending data")); + } + } while (sent < len); + //if (len > 500000) std::cout << "Done send" << std::endl; + } + + static void do_send_packet(SOCKET sock, const unsigned char * data, size_t length) { + //if (length > 500000) std::cout << "Starting send packet" << std::endl; + if (length < 1020) { + size_t len = length; + std::string buffer(len+4, '\0'); + for (int i = 0; i < 4; ++i) { + buffer[i] = static_cast<char>(len & 0xff); + len >>= 8; + } + std::copy(data, data+length, &buffer[4]); + do_send_data(sock, reinterpret_cast<const unsigned char *>(&buffer[0]), buffer.length()); + } else { + size_t len = length; + unsigned char buffer[4] = {0}; + for (int i = 0; i < 4; ++i) { + buffer[i] = static_cast<unsigned char>(len & 0xff); + len >>= 8; + } + do_send_data(sock, buffer, 4); + do_send_data(sock, data, length); + } + //if (length > 500000) std::cout << "Done send packet" << std::endl; + } + +// static void send_data(SOCKET sock, unsigned long data) { +// std::string str; +// for (int i = 0; i < 4; ++i) { +// str += static_cast<char>(data & 0xff); +// data >>= 8; +// } +// send_data(sock, str); +// } + + } // anonymous namespace + + bool ConnectionInfoTCP::Matches(const ConnectionInfo & other) const { + const ConnectionInfoTCP * ptr = dynamic_cast<const ConnectionInfoTCP *>(&other); + //std::cout << " [Match: " << m_fd << " == " << (ptr ? to_string(ptr->m_fd) : "null") << "] " << std::flush; + if (ptr && (ptr->m_fd == m_fd)) return true; + return false; + } + + void ConnectionInfoTCP::Print(std::ostream & os) const { + ConnectionInfo::Print(os); + os << " (" /*<< m_fd << ","*/ << m_host << ")"; + } + + void ConnectionInfoTCP::append(size_t length, const char * data) { + m_buf += std::string(data, length); + update_length(); + //std::cout << *this << " - append: " << m_len << ", " << m_buf.size() << std::endl; + } + + bool ConnectionInfoTCP::havepacket() const { + return m_buf.length() >= m_len + 4; + } + + std::string ConnectionInfoTCP::getpacket() { + if (!havepacket()) EUDAQ_THROW("No packet available"); + std::string packet(m_buf, 4, m_len); + m_buf.erase(0, m_len+4); + update_length(true); + //std::cout << *this << " - getpacket: " << m_len << ", " << m_buf.size() << std::endl; + return packet; + } + + void ConnectionInfoTCP::update_length(bool force) { + //std::cout << "DBG: len=" << m_len << ", buf=" << m_buf.length(); + if (force || m_len == 0) { + m_len = 0; + if (m_buf.length() >= 4) { + for (int i = 0; i < 4; ++i) { + m_len |= to_int(m_buf[i]) << (8*i); + } +// std::cout << " (" << to_hex(m_buf[3], 2) +// << " " << to_hex(m_buf[2], 2) +// << " " << to_hex(m_buf[1], 2) +// << " " << to_hex(m_buf[0], 2) +// << ")"; + } + } + //std::cout << ", len=" << m_len << std::endl; + } + + TCPServer::TCPServer(const std::string & param) + : m_port(from_string(param, 44000)), + m_srvsock(socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)), + m_maxfd(m_srvsock) + { + if (m_srvsock == (SOCKET)-1) EUDAQ_THROW(LastSockErrorString("Failed to create socket")); + setup_signal(); + FD_ZERO(&m_fdset); + FD_SET(m_srvsock, &m_fdset); + + setup_socket(m_srvsock); + + sockaddr_in addr; + memset(&addr, 0, sizeof addr); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_port = htons(m_port); + + if (bind(m_srvsock, (sockaddr *) &addr, sizeof addr)) { + closesocket(m_srvsock); + EUDAQ_THROW(LastSockErrorString("Failed to bind socket: " + param)); + } + if (listen(m_srvsock, MAXPENDING)) { + closesocket(m_srvsock); + EUDAQ_THROW(LastSockErrorString("Failed to listen on socket: " + param)); + } + } + + TCPServer::~TCPServer() { + for (size_t i = 0; i < m_conn.size(); ++i) { + ConnectionInfoTCP * inf = + dynamic_cast<ConnectionInfoTCP *>(m_conn[i].get()); + if (inf && inf->IsEnabled()) { + closesocket(inf->GetFd()); + } + } + closesocket(m_srvsock); + } + + ConnectionInfoTCP & TCPServer::GetInfo(SOCKET fd) const { + const ConnectionInfoTCP tofind(fd); + for (size_t i = 0; i < m_conn.size(); ++i) { + if (tofind.Matches(*m_conn[i]) && m_conn[i]->GetState() >= 0) { + ConnectionInfoTCP * inf = + dynamic_cast<ConnectionInfoTCP *>(m_conn[i].get()); + return *inf; + } + } + EUDAQ_THROW("BUG: please report it"); + } + + void TCPServer::Close(const ConnectionInfo & id) { + for (size_t i = 0; i < m_conn.size(); ++i) { + if (id.Matches(*m_conn[i])) { + ConnectionInfoTCP * inf = + dynamic_cast<ConnectionInfoTCP *>(m_conn[i].get()); + if (inf && inf->IsEnabled()) { + SOCKET fd = inf->GetFd(); + inf->Disable(); + FD_CLR(fd, &m_fdset); + closesocket(fd); + } + } + } + } + + void TCPServer::SendPacket(const unsigned char * data, size_t len, const ConnectionInfo & id, bool duringconnect) { + //std::cout << "SendPacket to " << id << std::endl; + for (size_t i = 0; i < m_conn.size(); ++i) { + //std::cout << "- " << i << ": " << *m_conn[i] << std::flush; + if (id.Matches(*m_conn[i])) { + ConnectionInfoTCP * inf = + dynamic_cast<ConnectionInfoTCP *>(m_conn[i].get()); + if (inf && inf->IsEnabled() && (inf->GetState() > 0 || duringconnect)) { + //std::cout << " ok" << std::endl; + do_send_packet(inf->GetFd(), data, len); + } //else std::cout << " not quite" << std::endl; + } //else std::cout << " nope" << std::endl; + } + } + + void TCPServer::ProcessEvents(int timeout) { + //std::cout << "DEBUG: Process..." << std::endl; + Time t_start = Time::Current(), /*t_curr = t_start,*/ t_remain = Time(0, timeout); + bool done = false; + do { + fd_set tempset; + memcpy(&tempset, &m_fdset, sizeof(tempset)); + //std::cout << "select timeout=" << t_remain << std::endl; + timeval timeremain = t_remain; + int result = select(static_cast<int>(m_maxfd + 1), &tempset, NULL, NULL, &timeremain); + //std::cout << "select done" << std::endl; + + if (result == 0) { + //std::cout << "timeout" << std::endl; + } else if (result < 0 && LastSockError() != EINTR) { + std::cout << LastSockErrorString("Error in select()") << std::endl; + } else if (result > 0) { + + if (FD_ISSET(m_srvsock, &tempset)) { + sockaddr_in addr; + socklen_t len = sizeof(addr); + SOCKET peersock = accept(static_cast<int>(m_srvsock), (sockaddr*)&addr, &len); + if (peersock == INVALID_SOCKET) { + std::cout << LastSockErrorString("Error in accept()") << std::endl; + } else { + //std::cout << "Connect " << peersock << " from " << inet_ntoa(addr.sin_addr) << std::endl; + FD_SET(peersock, &m_fdset); + m_maxfd = (m_maxfd < peersock) ? peersock : m_maxfd; + setup_socket(peersock); + std::string host = inet_ntoa(addr.sin_addr); + host += ":" + to_string(ntohs(addr.sin_port)); + counted_ptr<ConnectionInfo> ptr(new ConnectionInfoTCP(peersock, host)); + bool inserted = false; + for (size_t i = 0; i < m_conn.size(); ++i) { + if (m_conn[i]->GetState() < 0) { + m_conn[i] = ptr; + inserted = true; + } + } + if (!inserted) m_conn.push_back(ptr); + m_events.push(TransportEvent(TransportEvent::CONNECT, *ptr)); + FD_CLR(m_srvsock, &tempset); + } + } + for (SOCKET j=0; j < m_maxfd+1; j++) { + if (FD_ISSET(j, &tempset)) { + char buffer[MAX_BUFFER_SIZE+1]; + + do { + result = recv(j, buffer, MAX_BUFFER_SIZE, 0); + } while (result == -1 && LastSockError() == EINTR); + + if (result > 0) { + buffer[result] = 0; + //std::cout << "Received bits " << j << std::endl; + ConnectionInfoTCP & m = GetInfo(j); + m.append(result, buffer); + while (m.havepacket()) { + done = true; + //std::cout << "Received packet " << j << std::endl; + m_events.push(TransportEvent(TransportEvent::RECEIVE, m, m.getpacket())); + } + } else /*if (result == 0)*/ { + //std::cout << "Disconnect " << j << std::endl; + ConnectionInfoTCP & m = GetInfo(j); + m_events.push(TransportEvent(TransportEvent::DISCONNECT, m)); + m.Disable(); + closesocket(j); + FD_CLR(j, &m_fdset); + /*} else { + std::cout << LastSockErrorString("Error in recv()") << std::endl;*/ + } + } // end if (FD_ISSET(j, &tempset)) + } // end for (j=0;...) + } // end else if (result > 0) + t_remain = Time(0, timeout) + t_start - Time::Current(); + } while (!done && t_remain > Time(0)); + } + + std::string TCPServer::ConnectionString() const { + const char * host = getenv("HOSTNAME"); + if (!host) host = "localhost"; + //gethostname(buf, sizeof buf); + return name + "://" + host + ":" + to_string(m_port); + } + + TCPClient::TCPClient(const std::string & param) + : m_server(param), + m_port(44000), + m_sock(socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)), + m_buf(ConnectionInfoTCP(m_sock, param)) + { + if (m_sock == (SOCKET)-1) EUDAQ_THROW(LastSockErrorString("Failed to create socket")); + + size_t i = param.find(':'); + if (i != std::string::npos) { + m_server = trim(std::string(param, 0, i)); + m_port = from_string(std::string(param, i+1), 44000); + } + boost::regex re("[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+"); + if(boost::regex_match(m_server,re)==0){ + if(m_hosts.find(m_server)!=m_hosts.end()) { + std::cout<<"Did lookup: "<<m_server; + m_server=m_hosts[m_server]; + std::cout<<": "<<m_server<<std::endl; + } + } + if (m_server == "") m_server = "localhost"; + std::cout<<m_server<<" "<<m_port<<std::endl; + + bool success; + do{ + try{ + std::cout<<"Constructor"<<std::endl; + OpenConnection(); + success=true; + std::cout<<"Server has started."<<std::endl; + }catch(::eudaq::LoggedException e){ + std::cout<<"Server is not running. Waiting one second."<<std::endl; + std::cout<<"Constructor loc"<<std::endl; + success=false; + close(m_sock); + m_sock=socket(PF_INET, SOCK_STREAM, IPPROTO_TCP), + sleep(1); + } + }while (success==false); + } + + void TCPClient::OpenConnection() { + sockaddr_in addr; + std::memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(m_port); + + hostent * host = gethostbyname(m_server.c_str()); + std::cout<<m_server<<std::endl; + if (!host) { + closesocket(m_sock); + EUDAQ_THROW(LastSockErrorString("Error looking up address \'" + m_server + "\'")); + } + memcpy((char *) &addr.sin_addr.s_addr, host->h_addr_list[0], host->h_length); + if (connect(m_sock, (sockaddr *) &addr, sizeof(addr)) && + LastSockError() != EINPROGRESS && + LastSockError() != EWOULDBLOCK) { + EUDAQ_THROW("The server is not running."); + //+ to_string(LastSockError()) + " connecting to " + + //m_server + ":" + to_string(m_port))); + } + setup_socket(m_sock); // set to non-blocking + } + + void TCPClient::SendPacket(const unsigned char * data, size_t len, const ConnectionInfo & id, bool) { + //std::cout << "Sending packet to " << id << std::endl; + if (id.Matches(m_buf)) { + //std::cout << " ok" << std::endl; + do_send_packet(m_buf.GetFd(), data, len); + } + //std::cout << "Sent" << std::endl; + } + + void TCPClient::ProcessEvents(int timeout) { + //std::cout << "ProcessEvents()" << std::endl; + Time t_start = Time::Current(), /*t_curr = t_start,*/ t_remain = Time(0, timeout); + bool done = false; + do { + fd_set tempset; + FD_ZERO(&tempset); + FD_SET(m_sock, &tempset); + timeval timeremain = t_remain; + SOCKET result = select(static_cast<int>(m_sock+1), &tempset, NULL, NULL, &timeremain); + //std::cout << "Select result=" << result << std::endl; + + bool donereading = false; + do { + char buffer[MAX_BUFFER_SIZE+1]; + do { + result = recv(m_sock, buffer, MAX_BUFFER_SIZE, 0); + } while (result == (SOCKET)-1 && LastSockError() == EINTR); + if (result == (SOCKET)-1 && LastSockError() == EWOULDBLOCK) { + //std::cout << "no more data" << std::endl; + donereading = true; + } else if (result == 0) { + std::cerr << "WARN: Connection closed (?)" << std::endl; + bool success; + do{ + try{ + std::cout<<"Process events"<<std::endl; + OpenConnection(); + success=true; + std::cout<<"Server has started."<<std::endl; + }catch(::eudaq::LoggedException e){ + std::cout<<"Server is not running. Waiting one second."<<std::endl; + std::cout<<"Process events loc"<<std::endl; + success=false; + close(m_sock); + m_sock=socket(PF_INET, SOCK_STREAM, IPPROTO_TCP), + sleep(1); + } + }while (success==false); + donereading = true; + } else if (result == (SOCKET)-1) { + //std::cout << "disconnect or error" << std::endl; + // disconnect || error + EUDAQ_THROW(LastSockErrorString("Socket Error (" + to_string(LastSockError()) + ")")); + } else { + //std::cout << "received bytes: " << escape(std::string(buffer, result)) << std::endl; + m_buf.append(result, buffer); + while (m_buf.havepacket()) { + m_events.push(TransportEvent(TransportEvent::RECEIVE, m_buf, m_buf.getpacket())); + done = true; + } + } + } while (!donereading); + t_remain = Time(0, timeout) + t_start - Time::Current(); + //std::cout << "Remaining: " << t_remain << (t_remain > Time(0) ? " >0" : " <0")<< std::endl; + } while (!done && t_remain > Time(0)); + //std::cout << "done" << std::endl; + } + + TCPClient::~TCPClient() { + closesocket(m_sock); + } + Profiler::Timer TCPClient::m_timer; + +} diff --git a/rce/rcecalib/eudaq/TransportTCP.hh b/rce/rcecalib/eudaq/TransportTCP.hh new file mode 100644 index 00000000..5c273af3 --- /dev/null +++ b/rce/rcecalib/eudaq/TransportTCP.hh @@ -0,0 +1,81 @@ +#ifndef EUDAQ_INCLUDED_TransportTCP +#define EUDAQ_INCLUDED_TransportTCP + +#include "eudaq/TransportFactory.hh" +#include "rcecalib/profiler/Profiler.hh" + +# include <sys/select.h> + typedef int SOCKET; + +#include <vector> +#include <string> +#include <map> + +namespace eudaq { + + class ConnectionInfoTCP : public ConnectionInfo { + public: + ConnectionInfoTCP(SOCKET fd, const std::string & host = "") : m_fd(fd), m_host(host), m_len(0), m_buf("") {} + void append(size_t length, const char * data); + bool havepacket() const; + std::string getpacket(); + SOCKET GetFd() const { return m_fd; } + void Disable() { m_state = -1; m_len = 0; m_buf = ""; } + virtual bool Matches(const ConnectionInfo & other) const; + virtual void Print(std::ostream &) const; + virtual std::string GetRemote() const { return m_host; } + virtual ConnectionInfo * Clone() const { return new ConnectionInfoTCP(*this); } + private: + void update_length(bool = false); + SOCKET m_fd; + std::string m_host; + size_t m_len; + std::string m_buf; + }; + + class TCPServer : public TransportServer { + public: + TCPServer(const std::string & param); + virtual ~TCPServer(); + + virtual void Close(const ConnectionInfo & id); + virtual void SendPacket(const unsigned char * data, size_t len, + const ConnectionInfo & id = ConnectionInfo::ALL, + bool duringconnect = false); + virtual void ProcessEvents(int timeout); + + virtual std::string ConnectionString() const; + static const std::string name; + private: + int m_port; + SOCKET m_srvsock; + SOCKET m_maxfd; + fd_set m_fdset; + + ConnectionInfoTCP & GetInfo(SOCKET fd) const; + //typedef std::map<int, TCPConnection> map_t; + //map_t m_map; + }; + + class TCPClient: public TransportClient { + public: + TCPClient(const std::string & param); + virtual ~TCPClient(); + + virtual void SendPacket(const unsigned char * data, size_t len, + const ConnectionInfo & id = ConnectionInfo::ALL, + bool = false); + virtual void ProcessEvents(int timeout = -1); + static Profiler::Timer m_timer; + private: + void OpenConnection(); + std::string m_server; + int m_port; + SOCKET m_sock; + ConnectionInfoTCP m_buf; + static std::map<std::string, std::string> m_hosts; + }; + +} + +#endif // EUDAQ_INCLUDED_TransportTCP diff --git a/rce/rcecalib/eudaq/TransportTCP_POSIX.inc b/rce/rcecalib/eudaq/TransportTCP_POSIX.inc new file mode 100644 index 00000000..6f1f9c4f --- /dev/null +++ b/rce/rcecalib/eudaq/TransportTCP_POSIX.inc @@ -0,0 +1,51 @@ +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <netdb.h> +#include <arpa/inet.h> +#include <fcntl.h> +#include <unistd.h> + +#ifndef INVALID_SOCKET +#define INVALID_SOCKET -1 +#endif + +namespace eudaq { + + namespace { + + static inline void closesocket(SOCKET s) { + close(s); + } + + static inline int LastSockError() { + return errno; + } + + static inline std::string LastSockErrorString(const std::string & msg) { + return msg + ": " + strerror(errno); + } + + static void setup_socket(SOCKET sock) { + /// Set non-blocking mode + int iof = fcntl(sock, F_GETFL, 0); + if (iof != -1) + fcntl(sock, F_SETFL, iof | O_NONBLOCK); + + /// Allow the socket to rebind to an address that is still shutting down + /// Useful if the server is quickly shut down then restarted + int one = 1; + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one); + + /// Periodically send packets to keep the connection open + setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof one); + + /// Try to send any remaining data when a socket is closed + linger ling; + ling.l_onoff = 1; ///< Enable linger mode + ling.l_linger = 1; ///< Linger timeout in seconds + setsockopt(sock, SOL_SOCKET, SO_LINGER, &ling, sizeof ling); + } + + } + +} diff --git a/rce/rcecalib/eudaq/Utils.cc b/rce/rcecalib/eudaq/Utils.cc new file mode 100644 index 00000000..867782b3 --- /dev/null +++ b/rce/rcecalib/eudaq/Utils.cc @@ -0,0 +1,135 @@ +#include "eudaq/Utils.hh" +#include "eudaq/Exception.hh" +#include <cstring> +#include <cstdlib> +#include <iostream> +#include <cctype> + +# include <unistd.h> + +namespace eudaq { + + std::string ucase(const std::string & str) { + std::string result(str); + for (size_t i = 0; i < result.length(); ++i) { + result[i] = std::toupper(result[i]); + } + return result; + } + + std::string lcase(const std::string & str) { + std::string result(str); + for (size_t i = 0; i < result.length(); ++i) { + result[i] = std::tolower(result[i]); + } + return result; + } + + /** Trims the leading and trainling white space from a string + */ + std::string trim(const std::string & s) { + static const std::string spaces = " \t\n\r\v"; + size_t b = s.find_first_not_of(spaces); + size_t e = s.find_last_not_of(spaces); + if (b == std::string::npos || e == std::string::npos) { + return ""; + } + return std::string(s, b, e - b + 1); + } + + std::string escape(const std::string & s) { + std::ostringstream ret; + ret << std::setfill('0') << std::hex; + for (size_t i = 0; i < s.length(); ++i) { + if (s[i] == '\\') + ret << "\\\\"; + else if (s[i] < 32) + ret << "\\x" << std::setw(2) << int(s[i]); + else + ret << s[i]; + } + return ret.str(); + } + + std::string firstline(const std::string & s) { + size_t i = s.find('\n'); + return s.substr(0, i); + } + + std::vector<std::string> split(const std::string & str, const std::string & delim) { + return split(str, delim, false); + } + + std::vector<std::string> split(const std::string & str, const std::string & delim, bool dotrim) { + std::string s(str); + std::vector<std::string> result; + if (str == "") return result; + size_t i; + while ((i = s.find_first_of(delim)) != std::string::npos) { + result.push_back(dotrim ? trim(s.substr(0, i)) : s.substr(0, i)); + s = s.substr(i + 1); + } + result.push_back(s); + return result; + } + + void mSleep(unsigned ms) { + usleep(ms * 1000); + } + + template<> + long from_string(const std::string & x, const long & def) { + if (x == "") return def; + const char * start = x.c_str(); + char * end = 0; + int base = 10; + std::string bases("box"); + if (x.length() > 2 && x[0] == '0' && bases.find(x[1]) != std::string::npos) { + if (x[1] == 'b') base = 2; + else if (x[1] == 'o') base = 8; + else if (x[1] == 'x') base = 16; + start += 2; + } + long result = std::strtol(start, &end, base); + if (*end) throw std::invalid_argument("Invalid argument: " + x); + return result; + } + + template<> + unsigned long from_string(const std::string & x, const unsigned long & def) { + if (x == "") return def; + const char * start = x.c_str(); + char * end = 0; + int base = 10; + std::string bases("box"); + if (x.length() > 2 && x[0] == '0' && bases.find(x[1]) != std::string::npos) { + if (x[1] == 'b') base = 2; + else if (x[1] == 'o') base = 8; + else if (x[1] == 'x') base = 16; + start += 2; + } + unsigned long result = std::strtoul(start, &end, base); + if (*end) throw std::invalid_argument("Invalid argument: " + x); + return result; + } + + void WriteStringToFile(const std::string & fname, const std::string & val) { + std::ofstream file(fname.c_str()); + if (!file.is_open()) std::cout<<"Unable to open file " + fname + " for writing"<<std::endl; + file << val << std::endl; + if (file.fail()) std::cout<<"Error writing to file " + fname<<std::endl; + } + + std::string ReadLineFromFile(const std::string & fname) { + std::ifstream file(fname.c_str()); + std::string result; + if (file.is_open()) { + std::getline(file, result); + if (file.fail()) { + std::cout<<"Error reading from file " + fname<<std::endl; + } + } + return result; + } + +} diff --git a/rce/rcecalib/eudaq/Utils.hh b/rce/rcecalib/eudaq/Utils.hh new file mode 100644 index 00000000..751f4475 --- /dev/null +++ b/rce/rcecalib/eudaq/Utils.hh @@ -0,0 +1,261 @@ +#ifndef EUDAQ_INCLUDED_Utils +#define EUDAQ_INCLUDED_Utils + +/** + * \file Utils.hh + * Contains generally useful utility functions. + */ + +#include <string> +#include <vector> +#include <sstream> +#include <iomanip> +#include <stdexcept> +#include <fstream> +#include <sys/types.h> + +namespace eudaq { + + std::string ucase(const std::string &); + std::string lcase(const std::string &); + std::string trim(const std::string & s); + std::string firstline(const std::string & s); + std::string escape(const std::string &); + std::vector<std::string> split(const std::string & str, const std::string & delim = "\t"); + std::vector<std::string> split(const std::string & str, const std::string & delim, bool dotrim); + + /** Sleep for a specified number of milliseconds. + * \param ms The number of milliseconds + */ + void mSleep(unsigned ms); + + /** Converts any type to a string. + * There must be a compatible streamer defined, which this function will make use of. + * \param x The value to be converted. + * \return A string representing the passed in parameter. + */ + template <typename T> + inline std::string to_string(const T & x, int digits = 0) { + std::ostringstream s; + s << std::setfill('0') << std::setw(digits) << x; + return s.str(); + } + + template <typename T> + inline std::string to_string(const std::vector<T> & x, const std::string & sep, int digits = 0) { + std::ostringstream s; + if (x.size() > 0) s << to_string(x[0], digits); + for (size_t i = 1; i < x.size(); ++i) { + s << sep << to_string(x[i], digits); + } + return s.str(); + } + + template <typename T> + inline std::string to_string(const std::vector<T> & x, int digits = 0) { + return to_string(x, ",", digits); + } + + inline std::string to_string(const std::string & x, int /*digits*/ = 0) { + return x; + } + inline std::string to_string(const char * x, int /*digits*/ = 0) { + return x; + } + + /** Converts any type that has an ostream streamer to a string in hexadecimal. + * \param x The value to be converted. + * \param digits The minimum number of digits, shorter numbers are padded with zeroes. + * \return A string representing the passed in parameter in hex. + */ + template <typename T> + inline std::string to_hex(const T & x, int digits = 0) { + std::ostringstream s; + s << std::hex << std::setfill('0') << std::setw(digits) << x; + return s.str(); + } + + template<> + inline std::string to_hex(const unsigned char & x, int digits) { + return to_hex((int)x, digits); + } + + template<> + inline std::string to_hex(const signed char & x, int digits) { + return to_hex((int)x, digits); + } + + template<> + inline std::string to_hex(const char & x, int digits) { + return to_hex((unsigned char)x, digits); + } + + /** Converts a string to any type. + * \param x The string to be converted. + * \param def The default value to be used in case of an invalid string, + * this can also be useful to select the correct template type + * without having to specify it explicitly. + * \return An object of type T with the value represented in x, or if + * that is not valid then the value of def. + */ + template <typename T> + inline T from_string(const std::string & x, const T & def = 0) { + if (x == "") return def; + T ret = def; + std::istringstream s(x); + s >> ret; + char remain = '\0'; + s >> remain; + if (remain) throw std::invalid_argument("Invalid argument: " + x); + return ret; + } + + template<> + inline std::string from_string(const std::string & x, const std::string & def) { + return x == "" ? def : x; + } + + template<> + long from_string(const std::string & x, const long & def); + template<> + unsigned long from_string(const std::string & x, const unsigned long & def); + template<> + inline int from_string(const std::string & x, const int & def) { + return from_string(x, (long)def); + } + template<> + inline unsigned int from_string(const std::string & x, const unsigned int & def) { + return from_string(x, (unsigned long)def); + } + + template <typename T> + struct Holder { + Holder(T val) : m_val(val) {} + T m_val; + }; + + template <typename T> + struct hexdec_t { + enum { DIGITS = 2 * sizeof (T) }; + hexdec_t(T val, unsigned hexdigits) : m_val(val), m_dig(hexdigits) {} + T m_val; + unsigned m_dig; + }; + + template <typename T> + inline hexdec_t<T> hexdec(T val, unsigned hexdigits = hexdec_t<T>::DIGITS) { + return hexdec_t<T>(val, hexdigits); + } + + template <typename T> + inline std::ostream & operator << (std::ostream & os, const hexdec_t<T> & h) { + return os << "0x" << to_hex(h.m_val, h.m_dig) << " (" << h.m_val << ")"; + } + + template <> + inline std::ostream & operator << (std::ostream & os, const hexdec_t<unsigned char> & h) { + return os << (int)h.m_val << " (0x" << to_hex(h.m_val, h.m_dig) << ")"; + } + + template <> + inline std::ostream & operator << (std::ostream & os, const hexdec_t<signed char> & h) { + return os << (int)h.m_val << " (0x" << to_hex(h.m_val, h.m_dig) << ")"; + } + + template <> + inline std::ostream & operator << (std::ostream & os, const hexdec_t<char> & h) { + return os << (int)(unsigned char)h.m_val + << " (0x" << to_hex(h.m_val, h.m_dig) << ")"; + } + + template <typename T> unsigned char * uchar_cast(T * x) { + return reinterpret_cast<unsigned char *>(x); + } + + template <typename T> unsigned char * uchar_cast(std::vector<T> & x) { + return uchar_cast(&x[0]); + } + + template <typename T> const unsigned char * constuchar_cast(const T * x) { + return reinterpret_cast<const unsigned char *>(x); + } + + template <typename T> const unsigned char * constuchar_cast(const std::vector<T> & x) { + return constuchar_cast(&x[0]); + } + + template <typename T> + inline T getbigendian(const unsigned char * ptr) { +#if (defined( __BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN) || \ + (defined(__DARWIN_BYTE_ORDER) && __DARWIN_BYTE_ORDER == __DARWIN_BIG_ENDIAN) + return *reinterpret_cast<const T *>(ptr); +#else + T result = 0; + for (size_t i = 0; i < sizeof (T); ++i) { + result <<= 8; + result += *ptr++; + } + return result; +#endif + } + + template <typename T> + inline T getlittleendian(const unsigned char * ptr) { +#if (defined( __BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN) || \ + (defined(__DARWIN_BYTE_ORDER) && __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN) + return *reinterpret_cast<const T *>(ptr); +#else + T result = 0; + for (size_t i = 0; i < sizeof (T); ++i) { + result += *ptr++ << (8*i); + } + return result; +#endif + } + + template <typename T> + inline void setbigendian(unsigned char * ptr, const T & val) { +#if (defined( __BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN) || \ + (defined(__DARWIN_BYTE_ORDER) && __DARWIN_BYTE_ORDER == __DARWIN_BIG_ENDIAN) + *reinterpret_cast<T *>(ptr) = val; +#else + T tmp = val; + ptr += sizeof (T); + for (size_t i = 0; i < sizeof (T); ++i) { + *--ptr = tmp & 0xff; + tmp >>= 8; + } +#endif + } + + template <typename T> + inline void setlittleendian(unsigned char * ptr, const T & val) { +#if (defined( __BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN) || \ + (defined(__DARWIN_BYTE_ORDER) && __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN) + *reinterpret_cast<T *>(ptr) = val; +#else + T tmp = val; + for (size_t i = 0; i < sizeof (T); ++i) { + *ptr++ = tmp & 0xff; + tmp >>= 8; + } +#endif + } + + std::string ReadLineFromFile(const std::string & fname); + + template <typename T> + inline T ReadFromFile(const std::string & fname, const T & def = 0) { + return from_string(ReadLineFromFile(fname), def); + } + + void WriteStringToFile(const std::string & fname, const std::string & val); + + template <typename T> + inline void WriteToFile(const std::string & fname, const T & val) { + WriteStringToFile(fname, to_string(val)); + } + +} + +#endif // EUDAQ_INCLUDED_Utils diff --git a/rce/rcecalib/eudaq/constituents.mk b/rce/rcecalib/eudaq/constituents.mk new file mode 100644 index 00000000..4be9e524 --- /dev/null +++ b/rce/rcecalib/eudaq/constituents.mk @@ -0,0 +1,61 @@ +ifneq ($(findstring ppc-rtems-rce,$(tgt_arch)),) +modlibnames := eudaq +endif + +libsrcs_eudaq := BufferSerializer.cc \ + DetectorEvent.cc \ + Event.cc \ + Exception.cc \ + FileSerializer.cc \ + RawDataEvent.cc \ + Time.cc \ + Utils.cc \ + Producer.cc \ + CommandReceiver.cc \ + DataSender.cc \ + DataSenderIF.cc \ + TransportClient.cc \ + Configuration.cc \ + Status.cc \ + TransportBase.cc \ + TransportFactory.cc \ + TransportTCP.cc \ + TransportServer.cc \ + TransportNULL.cc \ + ProducerIF.cc \ + Mutex.cc + +libincs_eudaq := rcecalib + + +ifneq ($(findstring linux,$(tgt_os)),) + +libnames := eudaq +tgtnames := testread testreadp testwrite + +tgtsrcs_testread := testread.cc +tgtincs_testread := rcecalib + + +tgtlibs_testread := \ + rcecalib/eudaq +tgtslib_testread := $(boost_regex_lib) + +tgtsrcs_testreadp := testreadp.cc +tgtincs_testreadp := rcecalib + + +tgtlibs_testreadp := \ + rcecalib/eudaq +tgtslib_testreadp := $(boost_regex_lib) + +tgtsrcs_testwrite := testwrite.cc +tgtincs_testwrite := rcecalib + +tgtlibs_testwrite := \ + rcecalib/eudaq +tgtslib_testwrite := $(boost_regex_lib) + +LXFLAGS +=-L$(RELEASE_DIR)/build/root/lib -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread -lGui -pthread -lm -ldl -rdynamic +endif + diff --git a/rce/rcecalib/eudaq/counted_ptr.hh b/rce/rcecalib/eudaq/counted_ptr.hh new file mode 100644 index 00000000..6c8dc111 --- /dev/null +++ b/rce/rcecalib/eudaq/counted_ptr.hh @@ -0,0 +1,113 @@ +/* + * counted_ptr - simple reference counted pointer. + * + * The is a non-intrusive implementation that allocates an additional + * int and pointer for every counted object. + * + * From: http://ootips.org/yonat/4dev/ + * Thanks to Yonat Sharon for this code + * + */ + +#ifndef COUNTED_PTR_H +#define COUNTED_PTR_H + +#ifdef _GLIBCXX_DEBUG +#include <vector> +#define EUDAQ_DIE std::vector<char>(1)[100] +#endif + +/* For ANSI-challenged compilers, you may want to #define + * NO_MEMBER_TEMPLATES or explicit */ + +template <class X> class counted_ptr +{ +public: + typedef X element_type; + + explicit counted_ptr(X* p = 0) // allocate a new counter + : itsCounter(0) {if (p) itsCounter = new counter(p);} + ~counted_ptr() + {release();} + counted_ptr(const counted_ptr& r) throw() + {acquire(r.itsCounter);} + counted_ptr& operator=(const counted_ptr& r) + { + if (this != &r) { + release(); + acquire(r.itsCounter); + } + return *this; + } + counted_ptr& operator=(X * p) + { + release(); + if (p) itsCounter = new counter(p); + return *this; + } + operator bool () const { + return get(); + } +#ifndef NO_MEMBER_TEMPLATES + template <class Y> friend class counted_ptr; + template <class Y> counted_ptr(const counted_ptr<Y>& r) throw() + {acquire(r.itsCounter);} + template <class Y> counted_ptr& operator=(const counted_ptr<Y>& r) + { + if (this != &r) { + release(); + acquire(r.itsCounter); + } + return *this; + } +#endif // NO_MEMBER_TEMPLATES + + X& operator*() const throw() { +#ifdef _GLIBCXX_DEBUG + if (!itsCounter || !itsCounter->ptr) EUDAQ_DIE; +#endif + return *itsCounter->ptr; + } + X* operator->() const throw() { +#ifdef _GLIBCXX_DEBUG + if (!itsCounter || !itsCounter->ptr) EUDAQ_DIE; +#endif + return itsCounter->ptr; + } + X* get() const throw() { +#ifdef _GLIBCXX_DEBUG + //if (!itsCounter || !itsCounter->ptr) EUDAQ_DIE; +#endif + return itsCounter ? itsCounter->ptr : 0; + } + bool unique() const throw() + {return (itsCounter ? itsCounter->count == 1 : true);} + +private: + + struct counter { + counter(X* p = 0, unsigned c = 1) : ptr(p), count(c) {} + X* ptr; + unsigned count; + }* itsCounter; + + void acquire(counter* c) throw() + { // increment the count + itsCounter = c; + if (c) ++c->count; + } + + void release() + { // decrement the count, delete if it is 0 + if (itsCounter) { + if (--itsCounter->count == 0) { + delete itsCounter->ptr; + delete itsCounter; + } + itsCounter = 0; + } + } +}; + +#endif // COUNTED_PTR_H + diff --git a/rce/rcecalib/eudaq/testread.cc b/rce/rcecalib/eudaq/testread.cc new file mode 100644 index 00000000..3a5e7b69 --- /dev/null +++ b/rce/rcecalib/eudaq/testread.cc @@ -0,0 +1,245 @@ +#include "eudaq/Event.hh" +#include "config/FormattedRecord.hh" +#include "eudaq/DetectorEvent.hh" +#include "eudaq/RawDataEvent.hh" +#include "eudaq/FileSerializer.hh" +#include "eudaq/counted_ptr.hh" + +#include <TApplication.h> +#include <TROOT.h> +#include <TStyle.h> +#include <TCanvas.h> +#include <TH2F.h> +#include <TF1.h> +#include <TFile.h> + +unsigned indx=0; + +unsigned nextcurrent(unsigned char* p){ + unsigned current=*(unsigned*)&p[indx]; + //unsigned current=(p[indx]<<24) | (p[indx+1]<<16) | (p[indx+2]<<8) | p[indx+3]; + indx+=4; + return current; +} +unsigned getWord(unsigned char *p, int word){ + return *(unsigned*)&p[word*4]; + //return (p[word*4]<<24) | (p[word*4+1]<<16) | (p[word*4+2]<<8) | p[word*4+3]; +} + +int main(int argc, char **argv){ + int linkmap[]={4,0,0,0,0,0,0,0,0,0,0,0,1,2,3}; + TApplication *tapp; + const char* filename=argv[1]; + int nevt=100000000; + if(argc==3)nevt=atoi(argv[2]); + tapp=new TApplication("bla", &argc, argv); + gROOT->SetStyle("Plain"); + gStyle->SetOptStat(1); + gStyle->SetPalette(1); + gStyle->SetOptFit(111); + gStyle->SetErrorX(0); + + unsigned noisy[5][16][160][18]; + unsigned hitmap[5][16][160][18]; + for(int i=0;i<5;i++){ + for(int j=0;j<16;j++){ + for(int k=0;k<160;k++){ + for(int l=0;l<18;l++){ + hitmap[i][j][k][l]=0; + noisy[i][j][k][l]=0; + } + } + } + } + // std::ifstream nos("noisypixels3.txt"); + //int md, chp, r, c; + //while(!nos.eof()){ + // nos>>md>>chp>>r>>c; + // noisy[md][chp][r][c]=1; + //} + TCanvas *co[5]; + TCanvas *ct[5]; + TH2F* occ[5]; + TH1F* toth[5]; + TCanvas *tdcc; + TH1F* tdc; + char name[128], title[128]; + for (int i=0;i<5;i++){ + sprintf(name,"co%d",i); + co[i]=new TCanvas(name,"Canvas",600,600); + sprintf(name,"occ%d",i); + sprintf(title,"Occupancy module %d",i+1); + //occ[i]=new TH2F(name,title, 18,-.5,17.5,160,-.5,159.5); + if(i==4) + occ[i]=new TH2F(name,title, 80,0,80,336,0, 336); //FEI4 + else + occ[i]=new TH2F(name,title, 8*18,0,8*18,2*160,0, 2*160); + co[i]->Draw(); + occ[i]->Draw("colz"); + occ[i]->SetMinimum(0); + sprintf(name,"ct%d",i); + ct[i]=new TCanvas(name,"Canvas",600,600); + sprintf(name,"tot%d",i); + sprintf(title,"ToT module %d",i+1); + toth[i]=new TH1F(name,title, 256,-.5,255.5); + //sprintf(title,"Timing module %d",i+1); + //toth[i]=new TH1F(name,title, 16,-.5,15.5); + ct[i]->Draw(); + toth[i]->Draw(); + } + tdcc=new TCanvas("TDCC","Canvas",600,600); + tdc=new TH1F("TDC","TDC",64,-.5,63.5); + tdcc->Draw(); + tdc->Draw(); + + int l1id=0; + int link=0; + int bxid=0; + int firstbxid=0; + int highesttot=0; + int ntrg=0; + int nev=0; + eudaq::FileDeserializer fs(filename); + while(fs.HasData()){ + eudaq::DetectorEvent* dev=(eudaq::DetectorEvent*)eudaq::EventFactory::Create(fs); + nev++; + if(nev>nevt)break; + //if(nev==10)break; + // dev->Print(std::cout); + if(dev->IsEORE() || dev->IsBORE())continue; + eudaq::RawDataEvent::data_t pixblock; + int modtot[5]; + for(int i=0;i<5;i++)modtot[i]=0; + for(unsigned k=0;k<dev->NumEvents();k++){ + int oldl1id=-1; + eudaq::RawDataEvent* rev=(eudaq::RawDataEvent*)dev->GetEvent(k); + if(rev->GetSubType()=="APIX-CT"){ + eudaq::RawDataEvent::data_t block0=rev->GetBlock(0); + // std::cout<<"Block 0 size: "<<std::dec<<block0.size()<<std::endl; + //for(int i=0;i<9;i++){ + // std::cout<<std::hex<<getWord(&block0[0],i)<<std::endl; + //} + unsigned counter1=getWord(&block0[0],2); + unsigned counter2=getWord(&block0[0],3); + unsigned long long counter=counter2; + counter=(counter<<32) | counter1; + //printf("%llx\n",counter); + int bitpos=-1; + for (int j=0;j<64;j++){ + if(((counter>>j)&1)==0){ + bitpos=j; + break; + } + } + // if(bitpos!=-1)std::cout<<"Phase is " <<bitpos*.4<<" ns"<<std::endl; + if(bitpos!=-1)tdc->Fill(bitpos); + unsigned trgtime1=getWord(&block0[0],4); + unsigned trgtime2=getWord(&block0[0],5); + unsigned deadtime1=getWord(&block0[0],6); + unsigned deadtime2=getWord(&block0[0],7); + unsigned long long trgtime=trgtime1; + trgtime=(trgtime<<32) | trgtime2; + unsigned long long deadtime=deadtime1; + deadtime=(deadtime<<32) | deadtime2; + // std::cout<<"Trgtime: "<<trgtime<<std::endl; + //std::cout<<"Deadtime: "<<deadtime<<std::endl; + //unsigned eudaqtrg=getWord(&block0[0],8); + // std::cout<<"Eudaq trigger word: "<<eudaqtrg<<std::endl; + + pixblock=rev->GetBlock(1); + }else if(rev->GetSubType()=="CTEL"){ + pixblock=rev->GetBlock(0); + }else{ + //std::cout<<"Unknown data block. Skipping."<<std::endl; + continue; + } + // std::cout<<"Pixblock size "<<pixblock.size()<<std::endl; + indx=0; + while (indx<pixblock.size()){ + unsigned currentu=nextcurrent(&pixblock[0]); + FormattedRecord current(currentu); + if(current.isHeader()){ + ntrg++; + link=current.getLink(); + //std::cout<<"Data from link "<<link<<std::endl; + l1id=current.getL1id(); + bxid=current.getBxid(); + if(l1id!=oldl1id){ + oldl1id=l1id; + firstbxid=bxid; + } + }else if(current.isData()){ + int chip=current.getFE(); + //std::cout<<"Chip "<<chip<<std::endl; + int tot=current.getToT(); + if(tot>highesttot)highesttot=tot; + int col=current.getCol(); + int row=current.getRow(); + //if(col>17)std::cout<<"Bad column "<<col<<" in module "<<link<<" chip "<<chip<<std::endl; + // if(chip!=8 || row<150){ + // if(chip!=6 || col<16){ + int diffbx=bxid-firstbxid; + //std::cout<<diffbx<<std::endl; + if (diffbx<0)diffbx+=256; + // if(chip!=8||col>0){ + // if(row<156){ + //if(diffbx>5&&diffbx<9){ + if(noisy[linkmap[link]][chip][row][col]==0){// && diffbx>5&&diffbx<12){ + float x,y; + if (chip<8){ + x=18*chip+col; + y=row; + } else { + x=(15-chip)*18+17-col; + y= 319-row; + } + // occ[linkmap[link]]->Fill(chip/2*18+col,(chip%2)*160+row); + + occ[linkmap[link]]->Fill(x,y); + hitmap[linkmap[link]][chip][row][col]++; + //std::cout<<chip/2*18+col<<" "<<(chip%2)*160+row<<" "<<tot<<" "<<l1id<<" "<<firstbxid<<" "<<bxid<<std::endl; + if(link==0&&col<78)std::cout<<col<<" "<<row<<" "<<tot<<" "<<l1id<<" "<<firstbxid<<" "<<bxid<<std::endl; + + if(tot!=14&&col<78)modtot[linkmap[link]]+=tot; + //toth[linkmap[link]]->Fill(tot); + //if(col<78)toth[linkmap[link]]->Fill(diffbx); + //if(link==8 && col<6)std::cout<<"Tot "<<diffbx<<std::endl; + //toth->Fill(diffbx); + //std::cout<<chip<<" "<<row<<" "<<col<<" "<<tot<<std::endl; + } + // } + // } + } + } + } + for(int i=0;i<5;i++)if(modtot[i]!=0)toth[i]->Fill(modtot[i]); + } + // std::cout<<"Highest ToT: "<<highesttot<<std::endl; + for (int i=0;i<5;i++){ + occ[i]->Draw("colz"); + toth[i]->Draw(); + //toth[i]->Fit("gaus"); + co[i]->Update(); + ct[i]->Update(); + } + tdc->Draw(); + tdcc->Update(); + std::cout<<nev<<" events and "<<ntrg<<" triggers."<<std::endl; + std::cout<<"Noisy pixels:"<<std::endl; + for(int i=0;i<5;i++){ + for(int j=0;j<16;j++){ + for(int k=0;k<160;k++){ + for(int l=0;l<18;l++){ + if( hitmap[i][j][k][l]>5){ + std::cout<<i<<" "<<j<<" "<<k<<" "<<l<<" "<<std::endl; + } + } + } + } + } +// TFile a("out.root","recreate"); +// tdc->Write(); + // a.Close(); + tapp->Run(); +} + diff --git a/rce/rcecalib/eudaq/testreadp.cc b/rce/rcecalib/eudaq/testreadp.cc new file mode 100644 index 00000000..708bb502 --- /dev/null +++ b/rce/rcecalib/eudaq/testreadp.cc @@ -0,0 +1,258 @@ +#include "config/FormattedRecord.hh" +#include <stdlib.h> +#include <fstream> + +#include <TApplication.h> +#include <TROOT.h> +#include <TStyle.h> +#include <TCanvas.h> +#include <TH2F.h> +#include <TF1.h> +#include <TFile.h> + +int indx=0; + +unsigned nextcurrent(char* p){ + unsigned current=*(unsigned*)&p[indx]; + //unsigned current=(p[indx]<<24) | (p[indx+1]<<16) | (p[indx+2]<<8) | p[indx+3]; + indx+=4; + return current; +} +unsigned getWord(char *p, int word){ + return *(unsigned*)&p[word*4]; + //return (p[word*4]<<24) | (p[word*4+1]<<16) | (p[word*4+2]<<8) | p[word*4+3]; +} + +int main(int argc, char **argv){ + int linkmap[]={0,1,2,3,4,5,0,0,0,0,0,4,1,2,3}; + TApplication *tapp; + const char* filename=argv[1]; + int nevt=100000000; + if(argc==3)nevt=atoi(argv[2]); + tapp=new TApplication("bla", &argc, argv); + gROOT->SetStyle("Plain"); + gStyle->SetOptStat(1); + gStyle->SetPalette(1); + gStyle->SetOptFit(111); + gStyle->SetErrorX(0); + + unsigned noisy[5][16][160][18]; + unsigned hitmap[5][16][160][18]; + for(int i=0;i<5;i++){ + for(int j=0;j<16;j++){ + for(int k=0;k<160;k++){ + for(int l=0;l<18;l++){ + hitmap[i][j][k][l]=0; + noisy[i][j][k][l]=0; + } + } + } + } + // std::ifstream nos("noisypixels3.txt"); + //int md, chp, r, c; + //while(!nos.eof()){ + // nos>>md>>chp>>r>>c; + // noisy[md][chp][r][c]=1; + //} + TCanvas *co[15]; + TCanvas *ct[15]; + TH2F* occ[15]; + TH1F* toth[15]; + TCanvas *tdcc; + TH1F* tdc; + char name[128], title[128]; + for (int i=0;i<6;i++){ + sprintf(name,"co%d",i); + co[i]=new TCanvas(name,"Canvas",600,600); + sprintf(name,"occ%d",i); + sprintf(title,"Occupancy module %d",i+1); + //occ[i]=new TH2F(name,title, 18,-.5,17.5,160,-.5,159.5); + //if(i!=4) + occ[i]=new TH2F(name,title, 80,0,80,336,0, 336); //FEI4 + //else + //occ[i]=new TH2F(name,title, 8*18,0,8*18,2*160,0, 2*160); + co[i]->Draw(); + occ[i]->Draw("colz"); + occ[i]->SetMinimum(0); + sprintf(name,"ct%d",i); + ct[i]=new TCanvas(name,"Canvas",600,600); + sprintf(name,"tot%d",i); + //sprintf(title,"ToT module %d",i+1); + //toth[i]=new TH1F(name,title, 256,-.5,255.5); + sprintf(title,"Timing module %d",i+1); + toth[i]=new TH1F(name,title, 16,-.5,15.5); + ct[i]->Draw(); + toth[i]->Draw(); + } + tdcc=new TCanvas("TDCC","Canvas",600,600); + tdc=new TH1F("TDC","TDC",64,-.5,63.5); + tdcc->Draw(); + tdc->Draw(); + + int l1id=0; + int link=0; + int bxid=0; + int firstbxid=0; + int highesttot=0; + int ntrg=0; + int nev=0; + std::ifstream fs(filename, std::ios::binary); + char block0[9*sizeof(unsigned)] ; + char* pixblock=0; + unsigned size, evtno; + int modtot[15]; + if(!fs.good()){ + std::cout<<"Error opening file."<<std::endl; + exit(0); + } + unsigned timestamp; + unsigned nRCE; + fs.read((char*)×tamp,4); + std::cout<<"Timestamp at start of file: "<<timestamp<<std::endl; + fs.read((char*)&nRCE,4); + std::cout<<"Number of RCEs: "<<nRCE<<std::endl; + while(fs.good()){ + fs.read((char*)&size, 4); + if(fs.eof())break; + nev++; + if(nev>nevt)break; + //if(nev==10)break; + // dev->Print(std::cout); + for(int i=0;i<6;i++)modtot[i]=0; + int oldl1id=-1; + fs.read((char*)&evtno, 4); + //std::cout<<"Size "<<size<<std::endl; + //std::cout<<"Event number "<<evtno<<std::endl; + unsigned tdcsize; + fs.read((char*)&tdcsize, 4); + std::cout<<"RCE: "<<tdcsize<<std::endl; + fs.read(block0,9*sizeof(unsigned)); + // TDC readout. + unsigned counter1=getWord(&block0[0],2); + unsigned counter2=getWord(&block0[0],3); + unsigned long long counter=counter2; + counter=(counter<<32) | counter1; + //printf("TDC value: %llx\n",counter); + int bitpos=-1; + for (int j=0;j<64;j++){ + if(((counter>>j)&1)==0){ + bitpos=j; + break; + } + } + // if(bitpos!=-1)std::cout<<"Phase is " <<bitpos*.4<<" ns"<<std::endl; + if(bitpos!=-1)tdc->Fill(bitpos); + unsigned trgtime1=getWord(&block0[0],4); + unsigned trgtime2=getWord(&block0[0],5); + unsigned deadtime1=getWord(&block0[0],6); + unsigned deadtime2=getWord(&block0[0],7); + unsigned long long trgtime=trgtime1; + trgtime=(trgtime<<32) | trgtime2; + unsigned long long deadtime=deadtime1; + deadtime=(deadtime<<32) | deadtime2; + std::cout<<"Trgtime: "<<trgtime<<std::endl; + std::cout<<"Deadtime: "<<deadtime<<std::endl; + unsigned eudaqtrg=getWord(&block0[0],8); + //std::cout<<"Eudaq trigger word: "<<std::hex<<eudaqtrg<<std::dec<<std::endl; + + int pixblocksize=size-12*sizeof(unsigned); + pixblock=new char[pixblocksize]; + fs.read(pixblock,pixblocksize); + indx=0; + while (indx<pixblocksize){ + unsigned currentu=nextcurrent(&pixblock[0]); + FormattedRecord current(currentu); + if(current.isHeader()){ + ntrg++; + link=current.getLink(); + //std::cout<<"Data from link "<<link<<std::endl; + l1id=current.getL1id(); + bxid=current.getBxid(); + //std::cout<<l1id<<" "<<bxid<<std::endl; + if(l1id!=oldl1id){ + oldl1id=l1id; + firstbxid=bxid; + } + }else if(current.isHeaderTwo()){ + int rce = current.getRCE(); + std::cout<<"New RCE "<<rce<<std::endl; + }else if(current.isData()){ + int chip=current.getFE(); + //std::cout<<"Chip "<<chip<<std::endl; + int tot=current.getToT(); + if(tot>highesttot)highesttot=tot; + int col=current.getCol(); + int row=current.getRow(); + //std::cout<<"Hit "<<chip<<" "<<row<<" "<<col<<std::endl; + //if(col>17)std::cout<<"Bad column "<<col<<" in module "<<link<<" chip "<<chip<<std::endl; + // if(chip!=8 || row<150){ + // if(chip!=6 || col<16){ + int diffbx=bxid-firstbxid; + //std::cout<<diffbx<<std::endl; + if (diffbx<0)diffbx+=256; + // if(chip!=8||col>0){ + // if(row<156){ + //if(diffbx>5&&diffbx<9){ + //if(diffbx>15)std::cout<<firstbxid<<" "<<bxid<<std::endl; + //if(noisy[linkmap[link]][chip][row][col]==0){// && diffbx>5&&diffbx<12){ + float x,y; + if (chip<8){ + x=18*chip+col; + y=row; + } else { + x=(15-chip)*18+17-col; + y= 319-row; + } + // occ[linkmap[link]]->Fill(chip/2*18+col,(chip%2)*160+row); + + occ[linkmap[link]]->Fill(x,y); + //hitmap[linkmap[link]][chip][row][col]++; + //std::cout<<chip/2*18+col<<" "<<(chip%2)*160+row<<" "<<tot<<" "<<l1id<<" "<<firstbxid<<" "<<bxid<<std::endl; + //if(link==0&&col<78)std::cout<<col<<" "<<row<<" "<<tot<<" "<<l1id<<" "<<firstbxid<<" "<<bxid<<std::endl; + + if(tot!=14&&col<78)modtot[linkmap[link]]+=tot; + //toth[linkmap[link]]->Fill(tot); + toth[linkmap[link]]->Fill(diffbx); + //if(link==8 && col<6)std::cout<<"Tot "<<diffbx<<std::endl; + //toth->Fill(diffbx); + //std::cout<<chip<<" "<<row<<" "<<col<<" "<<tot<<std::endl; + //} + // } + // } + } + } + //for(int i=0;i<5;i++)if(modtot[i]!=0)toth[i]->Fill(modtot[i]); + delete [] pixblock; + } + // std::cout<<"Highest ToT: "<<highesttot<<std::endl; + for (int i=0;i<6;i++){ + occ[i]->Draw("colz"); + //toth[i]->Draw(); + //toth[i]->Fit("gaus"); + //co[i]->Update(); + ct[i]->Update(); + } + tdc->Draw(); + tdcc->Update(); + std::cout<<nev<<" events and "<<ntrg<<" triggers."<<std::endl; + std::cout<<"Noisy pixels:"<<std::endl; + /* + for(int i=0;i<5;i++){ + for(int j=0;j<16;j++){ + for(int k=0;k<160;k++){ + for(int l=0;l<18;l++){ + if( hitmap[i][j][k][l]>5){ + // std::cout<<i<<" "<<j<<" "<<k<<" "<<l<<" "<<std::endl; + } + } + } + } + } + */ + // TFile a("out.root","recreate"); + // tdc->Write(); + // a.Close(); + tapp->Run(); +} + + diff --git a/rce/rcecalib/eudaq/testwrite.cc b/rce/rcecalib/eudaq/testwrite.cc new file mode 100644 index 00000000..44257454 --- /dev/null +++ b/rce/rcecalib/eudaq/testwrite.cc @@ -0,0 +1,19 @@ +#include "eudaq/Event.hh" +#include "eudaq/DetectorEvent.hh" +#include "eudaq/RawDataEvent.hh" +#include "eudaq/FileSerializer.hh" +#include "eudaq/counted_ptr.hh" + + +int main(){ + char data[]="bla"; + eudaq::DetectorEvent dev(100,1,0); + eudaq::RawDataEvent* rev=new eudaq::RawDataEvent("CTEL",100,1); + counted_ptr<eudaq::Event> cp(rev); + rev->AddBlock(0,data,3); + dev.AddEvent(cp); + dev.Print(std::cout); + eudaq::FileSerializer fs("test.out"); + dev.Serialize(fs); + +} diff --git a/rce/rcecalib/flags.mk b/rce/rcecalib/flags.mk new file mode 100644 index 00000000..94ac456b --- /dev/null +++ b/rce/rcecalib/flags.mk @@ -0,0 +1,86 @@ +include $(RELEASE_DIR)/make/sw/flags.mk + +BOOST_VERSION:=1_42 +ifeq ($(TDAQ_VERSION),4) +CPPFLAGS+=-DTDAQ_RELEASE_4 +BOOST_VERSION=1_44 +endif + +ifneq ($(findstring ppc-rtems-rce,$(tgt_arch)),) + +DEPFLAGS+= -D__powerpc__ -D__GNU__ -D__GLIBC__=2 -DBOOST_THREAD_POSIX +DEFINES+= -D__powerpc__ -D__GNU__ -D__GLIBC__=2 -DBOOST_THREAD_POSIX +MDEFINES+= -D__powerpc__ -D__GNU__ -D__GLIBC__=2 -DBOOST_THREAD_POSIX -DERS_NO_DEBUG -mlongcall + +endif + +ifneq ($(findstring x86_64-linux,$(tgt_arch)),) +DEFINES+= -D__LITTLE_ENDIAN__ +DEPFLAGS+= -D__LITTLE_ENDIAN__ +endif + +CPPFLAGS += -I$(RELEASE_DIR)/build/rcecalib/obj/$(tgt_arch)/idl +CPPFLAGS += -I$(RELEASE_DIR)/build/rcecalib/modobj/$(tgt_arch)/idl +CPPFLAGS += -I$(RELEASE_DIR)/build/rcecalib/obj/$(tgt_arch)/idl +CPPFLAGS += -I$(RELEASE_DIR)/build/rcecalib/modobj/$(tgt_arch)/idl +CPPFLAGS += -I$(RCE_CORE)/include +CPPFLAGS += -I$(PIXLIBINTERFACE) +LXFLAGS += -L$(RCE_CORE)/$(tgt_arch)/lib + +rdb_lib:= +ers_lib:=$(TDAQC_INST_PATH)/$(tgt_arch)/lib/ers +ers_stream_lib:= +owl_lib:=$(TDAQ_INST_PATH)/$(tgt_arch)/lib/owl +ipc_lib:=$(TDAQ_INST_PATH)/$(tgt_arch)/lib/ipc +oh_lib:=$(TDAQ_INST_PATH)/$(tgt_arch)/lib/oh +ifneq ($(findstring i686,$(tgt_arch)),) +oh_root_lib:=$(TDAQ_INST_PATH)/$(tgt_arch)/lib/ohroot +else +oh_root_lib:= +endif +is_lib:=$(TDAQ_INST_PATH)/$(tgt_arch)/lib/is +tdaq_cmdline_lib=$(TDAQ_INST_PATH)/$(tgt_arch)/lib/cmdline +ifneq ($(findstring i686,$(tgt_arch)),) +boost_thread_lib:=$(TDAQ_BOOST)/$(tgt_arch)/lib/boost_thread-gcc43-mt-$(BOOST_VERSION) +boost_date_time_lib:=$(TDAQ_BOOST)/$(tgt_arch)/lib/boost_date_time-gcc43-mt-$(BOOST_VERSION) +boost_regex_lib:=$(TDAQ_BOOST)/$(tgt_arch)/lib/boost_regex-gcc43-mt-$(BOOST_VERSION) +else +boost_thread_lib:=$(TDAQ_BOOST)/$(tgt_arch)/lib/boost_thread +boost_date_time_lib:=$(TDAQ_BOOST)/$(tgt_arch)/lib/boost_date_time +boost_regex_lib:=$(TDAQ_BOOST)/$(tgt_arch)/lib/boost_regex +endif +omniorb_lib:=$(TDAQ_INST_PATH)/$(tgt_arch)/lib/omniORB4 +omnithread_lib:=$(TDAQ_INST_PATH)/$(tgt_arch)/lib/omnithread +mysql_lib:=$(TDAQ_MYSQL)/$(tgt_arch)/lib/mysqlclient +#zlib hack for rtems - avoid clash with internal rtems zlib +ifneq ($(findstring i686,$(tgt_arch)),) +z_lib:=$(TDAQC_EXT_PATH)/$(tgt_arch)/lib/z +else +z_lib:=/daq/slc5/sw/lcg/external/zlib/1.2.3p1/ppc-rtems-rce405-opt/lib/zz +ifeq ($(TDAQ_VERSION),4) +rdb_lib:=$(TDAQ_INST_PATH)/$(tgt_arch)/lib/rdb +ers_lib=$(TDAQC_INST_PATH)/$(tgt_arch)/lib/ers +ers_stream_lib:=$(TDAQC_INST_PATH)/$(tgt_arch)/lib/ErsBaseStreams +endif +endif + +ARCH=$(tgt_arch) +ifneq ($(findstring i686,$(tgt_arch)),) +CPPFLAGS+=-I$(TDAQ_BOOST)/$(ARCH)/include/boost-$(BOOST_VERSION) +else +CPPFLAGS+=-I$(TDAQ_BOOST)/$(ARCH)/include +endif +CPPFLAGS+=-I$(TDAQC_INST_PATH)/include +CPPFLAGS+=-I$(TDAQ_INST_PATH)/include -I$(TDAQ_INST_PATH)/$(ARCH)/include +CPPFLAGS+=-I$(TDAQ_INST_PATH)/$(ARCH)/include/ipc +CPPFLAGS+=-I$(ROOTSYS)/include +CPPFLAGS+=-I$(TDAQ_MYSQL)/$(ARCH)/include +IDLFLAGS+=-I$(TDAQ_INST_PATH)/include +ifneq ($(findstring i686,$(tgt_arch)),) +LXFLAGS+=-Wl,-rpath=$(TDAQC_INST_PATH)/$(ARCH) +LXFLAGS+=-Wl,-rpath=$(TDAQ_INST_PATH)/$(ARCH)/lib +LXFLAGS+=-Wl,-rpath=$(TDAQ_BOOST)/$(ARCH)/lib +LXFLAGS+=-Wl,-rpath=$(TDAQ_MYSQL)/$(ARCH)/lib +endif + + diff --git a/rce/rcecalib/idl/AFPHPTDCModuleConfig.idl b/rce/rcecalib/idl/AFPHPTDCModuleConfig.idl new file mode 100644 index 00000000..2e8f6c58 --- /dev/null +++ b/rce/rcecalib/idl/AFPHPTDCModuleConfig.idl @@ -0,0 +1,120 @@ +#ifndef AFPHPTDCMODULECONFIG_IDL +#define AFPHPTDCMODULECONFIG_IDL + +module ipc{ + + const long IPC_N_CALIBVALS = 1024; + + + struct AFPHPTDCModuleConfig{ + //Module ID string + char idStr[16]; + //Fpga registers + unsigned short test; + octet tdcControl; + octet run; + octet bypassLut; + octet localClockEn; + octet calClockEn; + octet refEn; + octet hitTestEn; + octet inputSel; + octet address; + octet fanspeed; + unsigned short channelEn; + //calibration constants. Inl=0, Dnl=1; + float calib[2][12][IPC_N_CALIBVALS]; + // Tdc Chip setup + octet test_select[3]; + octet enable_error_mark[3]; + octet enable_error_bypass[3]; + unsigned short enable_error[3]; + octet readout_single_cycle_speed[3]; + octet serial_delay[3]; + octet strobe_select[3]; + octet readout_speed_select[3]; + octet token_delay[3]; + octet enable_local_trailer[3]; + octet enable_local_header[3]; + octet enable_global_trailer[3]; + octet enable_global_header[3]; + octet keep_token[3]; + octet master[3]; + octet enable_bytewise[3]; + octet enable_serial[3]; + octet enable_jtag_readout[3]; + octet tdc_id[3]; + octet select_bypass_inputs[3]; + octet readout_fifo_size[3]; + unsigned short reject_count_offset[3]; + unsigned short search_window[3]; + unsigned short match_window[3]; + octet leading_resolution[3]; + unsigned long fixed_pattern[3]; + octet enable_fixed_pattern[3]; + octet max_event_size[3]; + octet reject_readout_fifo_full[3]; + octet enable_readout_occupancy[3]; + octet enable_readout_separator[3]; + octet enable_overflow_detect[3]; + octet enable_relative[3]; + octet enable_automatic_reject[3]; + unsigned short event_count_offset[3]; + unsigned short trigger_count_offset[3]; + octet enable_set_counters_on_bunch_reset[3]; + octet enable_master_reset_code[3]; + octet enable_master_reset_code_on_event_reset[3]; + octet enable_reset_channel_buffer_when_separator[3]; + octet enable_separator_on_event_reset[3]; + octet enable_separator_on_bunch_reset[3]; + octet enable_direct_event_reset[3]; + octet enable_direct_bunch_reset[3]; + octet enable_direct_trigger[3]; + unsigned short offset[32][3]; + unsigned short coarse_count_offset[3]; + unsigned short dll_tap_adjust3_0[3]; + unsigned short dll_tap_adjust7_4[3]; + unsigned short dll_tap_adjust11_8[3]; + unsigned short dll_tap_adjust15_12[3]; + unsigned short dll_tap_adjust19_16[3]; + unsigned short dll_tap_adjust23_20[3]; + unsigned short dll_tap_adjust27_24[3]; + unsigned short dll_tap_adjust31_28[3]; + unsigned short rc_adjust[3]; + octet not_used[3]; + octet low_power_mode[3]; + octet width_select[3]; + octet vernier_offset[3]; + octet dll_control[3]; + octet dead_time[3]; + octet test_invert[3]; + octet test_mode[3]; + octet enable_trailing[3]; + octet enable_leading[3]; + octet mode_rc_compression[3]; + octet mode_rc[3]; + octet dll_mode[3]; + octet pll_control[3]; + octet serial_clock_delay[3]; + octet io_clock_delay[3]; + octet core_clock_delay[3]; + octet dll_clock_delay[3]; + octet serial_clock_source[3]; + octet io_clock_source[3]; + octet core_clock_source[3]; + octet dll_clock_source[3]; + unsigned short roll_over[3]; + octet enable_matching[3]; + octet enable_pair[3]; + octet enable_ttl_serial[3]; + octet enable_ttl_control[3]; + octet enable_ttl_reset[3]; + octet enable_ttl_clock[3]; + octet enable_ttl_hit[3]; +}; + +}; + +#endif /* multiple inclusion protection */ + + diff --git a/rce/rcecalib/idl/Callback.idl b/rce/rcecalib/idl/Callback.idl new file mode 100644 index 00000000..89a37307 --- /dev/null +++ b/rce/rcecalib/idl/Callback.idl @@ -0,0 +1,26 @@ +#ifndef CALLBACK_IDL +#define CALLBACK_IDL + +#include <ipc/ipc.idl> + +module ipc +{ + enum Priority{LOW, MEDIUM, HIGH, NONE}; + enum ScanStatus{IDLE, CONFIGURED, SCANNING, FITTING, STOPPED, DOWNLOADING, FAILED}; + + struct CallbackParams{ + long rce; + ScanStatus status; + long maskStage; + long loop0; + long loop1; + }; + + interface Callback + { + oneway void notify ( in CallbackParams msg ); + oneway void stopServer(); + }; +}; + +#endif diff --git a/rce/rcecalib/idl/HitbusModuleConfig.idl b/rce/rcecalib/idl/HitbusModuleConfig.idl new file mode 100644 index 00000000..00f35526 --- /dev/null +++ b/rce/rcecalib/idl/HitbusModuleConfig.idl @@ -0,0 +1,25 @@ +#ifndef HITBUSMODULECONFIG_IDL +#define HITBUSMODULECONFIG_IDL + +module ipc{ + +struct HitbusModuleConfig{ + octet bpm ; + octet delay_tam1 ; + octet delay_tam2 ; + octet delay_tam3 ; + octet delay_tbm1 ; + octet delay_tbm2 ; + octet delay_tbm3 ; + octet bypass_delay ; + octet clock ; + octet function_A ; + octet function_B ; + char idStr[16] ;//Module ID string +}; + +}; + +#endif /* multiple inclusion protection */ + + diff --git a/rce/rcecalib/idl/IPCAFPHPTDCAdapter.idl b/rce/rcecalib/idl/IPCAFPHPTDCAdapter.idl new file mode 100644 index 00000000..3a754bdb --- /dev/null +++ b/rce/rcecalib/idl/IPCAFPHPTDCAdapter.idl @@ -0,0 +1,16 @@ +#ifndef IPCAFPHPTDCADAPTER_IDL +#define IPCAFPHPTDCADAPTER_IDL + +#include <ipc/ipc.idl> +#include "AFPHPTDCModuleConfig.idl" + +module ipc +{ + interface IPCAFPHPTDCAdapter : ipc::servant + { + long IPCdownloadConfig(in AFPHPTDCModuleConfig config); + + }; +}; + +#endif diff --git a/rce/rcecalib/idl/IPCConfigIFAdapter.idl b/rce/rcecalib/idl/IPCConfigIFAdapter.idl new file mode 100644 index 00000000..1f3e7350 --- /dev/null +++ b/rce/rcecalib/idl/IPCConfigIFAdapter.idl @@ -0,0 +1,42 @@ +#ifndef IPCCONFIGIF_IDL +#define IPCCONFIGIF_IDL + +#include <ipc/ipc.idl> + +module ipc +{ + struct ModSetup{ + long id; + long inLink; + long outLink; + }; + + typedef sequence<unsigned long> blockdata; + typedef sequence<octet> chardata; + + interface IPCConfigIFAdapter : ipc::servant + { + oneway void IPCsendTrigger(); + //oneway void IPCsetupParameter(in string name, in long val); + unsigned long IPCsetupParameter(in string name, in long val); + oneway void IPCsetupMaskStage(in long stage); + oneway void IPCenableTrigger(); + oneway void IPCdisableTrigger(); + oneway void IPCresetFE(); + oneway void IPCconfigureModulesHW(); + unsigned long IPCwriteHWregister(in unsigned long addr, in unsigned long val); + unsigned long IPCreadHWregister(in unsigned long addr, out unsigned long val); + unsigned long IPCsendHWcommand(in octet opcode); + unsigned long IPCwriteHWblockData(in blockdata data); + unsigned long IPCreadHWblockData(in blockdata data, out blockdata retv); + unsigned long IPCreadHWbuffers(out chardata retv); + long IPCverifyModuleConfigHW(in long id); + long IPCdeleteModules(); + long IPCnTrigger(); + long IPCsetupTriggerIF(in string type); + long IPCsetupModule(in string name, in string type, in ModSetup par, in string formatter); + + }; +}; + +#endif diff --git a/rce/rcecalib/idl/IPCFEI3Adapter.idl b/rce/rcecalib/idl/IPCFEI3Adapter.idl new file mode 100644 index 00000000..6305f3f3 --- /dev/null +++ b/rce/rcecalib/idl/IPCFEI3Adapter.idl @@ -0,0 +1,16 @@ +#ifndef IPCFEI3ADAPTER_IDL +#define IPCFEI3ADAPTER_IDL + +#include <ipc/ipc.idl> +#include "PixelModuleConfig.idl" + +module ipc +{ + interface IPCFEI3Adapter : ipc::servant + { + long IPCdownloadConfig(in PixelModuleConfig config); + + }; +}; + +#endif diff --git a/rce/rcecalib/idl/IPCFEI4AAdapter.idl b/rce/rcecalib/idl/IPCFEI4AAdapter.idl new file mode 100644 index 00000000..2ceb0576 --- /dev/null +++ b/rce/rcecalib/idl/IPCFEI4AAdapter.idl @@ -0,0 +1,20 @@ +#ifndef IPCFEI4AADAPTER_IDL +#define IPCFEI4AADAPTER_IDL + +#include <ipc/ipc.idl> +#include "PixelFEI4AConfig.idl" + +module ipc +{ + interface IPCFEI4AAdapter : ipc::servant + { + long IPCdownloadConfig(in PixelFEI4AConfig config); + oneway void IPCsetChipAddress(in unsigned long val); + unsigned long IPCwriteHWglobalRegister(in long reg, in unsigned short val); + unsigned long IPCreadHWglobalRegister(in long reg, out unsigned short val); + unsigned long IPCwriteDoubleColumnHW(in unsigned long bit, in unsigned long dcol, in uvec data, out uvec readback); + unsigned long IPCreadDoubleColumnHW(in unsigned long bit, in unsigned long dcol, out uvec readback); + }; +}; + +#endif diff --git a/rce/rcecalib/idl/IPCFEI4BAdapter.idl b/rce/rcecalib/idl/IPCFEI4BAdapter.idl new file mode 100644 index 00000000..798e8b4c --- /dev/null +++ b/rce/rcecalib/idl/IPCFEI4BAdapter.idl @@ -0,0 +1,20 @@ +#ifndef IPCFEI4BADAPTER_IDL +#define IPCFEI4BADAPTER_IDL + +#include <ipc/ipc.idl> +#include "PixelFEI4BConfig.idl" + +module ipc +{ + interface IPCFEI4BAdapter : ipc::servant + { + long IPCdownloadConfig(in PixelFEI4BConfig config); + oneway void IPCsetChipAddress(in unsigned long val); + unsigned long IPCwriteHWglobalRegister(in long reg, in unsigned short val); + unsigned long IPCreadHWglobalRegister(in long reg, out unsigned short val); + unsigned long IPCwriteDoubleColumnHW(in unsigned long bit, in unsigned long dcol, in uvec data, out uvec readback); + unsigned long IPCreadDoubleColumnHW(in unsigned long bit, in unsigned long dcol, out uvec readback); + }; +}; + +#endif diff --git a/rce/rcecalib/idl/IPCHitbusAdapter.idl b/rce/rcecalib/idl/IPCHitbusAdapter.idl new file mode 100644 index 00000000..eb0ac8e8 --- /dev/null +++ b/rce/rcecalib/idl/IPCHitbusAdapter.idl @@ -0,0 +1,16 @@ +#ifndef IPCHITBUSADAPTER_IDL +#define IPCHITBUSADAPTER_IDL + +#include <ipc/ipc.idl> +#include "HitbusModuleConfig.idl" + +module ipc +{ + interface IPCHitbusAdapter : ipc::servant + { + long IPCdownloadConfig(in HitbusModuleConfig config); + + }; +}; + +#endif diff --git a/rce/rcecalib/idl/IPCScanAdapter.idl b/rce/rcecalib/idl/IPCScanAdapter.idl new file mode 100644 index 00000000..ab7e3688 --- /dev/null +++ b/rce/rcecalib/idl/IPCScanAdapter.idl @@ -0,0 +1,21 @@ +#ifndef IPCSCANADAPTER_IDL +#define IPCSCANADAPTER_IDL + +#include <ipc/ipc.idl> +#include "ScanOptions.idl" + +module ipc +{ + interface IPCScanAdapter : ipc::servant + { + oneway void IPCstartScan(); + oneway void IPCpause(); + oneway void IPCresume(); + oneway void IPCwaitForData(); + oneway void IPCstopWaiting(); + long IPCgetStatus(); + oneway void IPCabort(); + }; +}; + +#endif diff --git a/rce/rcecalib/idl/IPCScanRootAdapter.idl b/rce/rcecalib/idl/IPCScanRootAdapter.idl new file mode 100644 index 00000000..a6e5d897 --- /dev/null +++ b/rce/rcecalib/idl/IPCScanRootAdapter.idl @@ -0,0 +1,23 @@ +#ifndef IPCSCANROOTADAPTER_IDL +#define IPCSCANROOTADAPTER_IDL + +#include <ipc/ipc.idl> +#include "ScanOptions.idl" +#include "Callback.idl" + +module ipc +{ + typedef sequence<string> StringVect; + + interface IPCScanRootAdapter : ipc::servant + { + long IPCconfigureScan(in ScanOptions options); + StringVect IPCgetHistoNames(in string reg); + StringVect IPCgetPublishedHistoNames(); + unsigned long IPCnEvents(); + oneway void IPCresynch(); + oneway void IPCconfigureCallback(in Callback cb, in Priority pr); + }; +}; + +#endif diff --git a/rce/rcecalib/idl/Makefile b/rce/rcecalib/idl/Makefile new file mode 100644 index 00000000..15090487 --- /dev/null +++ b/rce/rcecalib/idl/Makefile @@ -0,0 +1,21 @@ +# Package level makefile +# ---------------------- +%.mk:; + +# Checks +# ------ +# Check release location variables +ifeq ($(RELEASE_DIR),) +export RELEASE_DIR := $(PWD)/../.. +endif + +include $(RELEASE_DIR)/make/share/setup.mk +include ../flags.mk + +ifndef PREMAKE_DONE +include $(RELEASE_DIR)/make/share/premake.mk +else +include constituents.mk +include $(RELEASE_DIR)/make/sw/package.mk +include $(RELEASE_DIR)/make/sw/idl.mk +endif diff --git a/rce/rcecalib/idl/PixelFEI4AConfig.idl b/rce/rcecalib/idl/PixelFEI4AConfig.idl new file mode 100644 index 00000000..ea9da12e --- /dev/null +++ b/rce/rcecalib/idl/PixelFEI4AConfig.idl @@ -0,0 +1,117 @@ +#ifndef PixelFEI4AConfig_IDL +#define PixelFEI4AConfig_IDL + +#include "PixelFEI4GenConfig.idl" + +module ipc{ + +struct PixelFEI4AGlobal{ //FE global register + unsigned short TrigCnt; + unsigned short Conf_AddrEnable; + unsigned short Reg2Spare; + unsigned short ErrMask0; + unsigned short ErrMask1; + unsigned short PrmpVbpRight; + unsigned short Vthin; + unsigned short DisVbn_CPPM; + unsigned short PrmpVbp; + unsigned short TdacVbp; + unsigned short DisVbn; + unsigned short Amp2Vbn; + unsigned short Amp2VbpFol; + unsigned short PrmpVbpTop; + unsigned short Amp2Vbp; + unsigned short FdacVbn; + unsigned short Amp2Vbpf; + unsigned short PrmpVbnFol; + unsigned short PrmpVbpLeft; + unsigned short PrmpVbpf; + unsigned short PrmpVbnLcc; + unsigned short Reg13Spare; + unsigned short PxStrobes; + unsigned short S0; + unsigned short S1; + unsigned short LVDSDrvIref; + unsigned short BonnDac; + unsigned short PllIbias; + unsigned short LVDSDrvVos; + unsigned short TempSensBias; + unsigned short PllIcp; + unsigned short Reg17Spare; + unsigned short PlsrIdacRamp; + unsigned short Reg18Spare; + unsigned short PlsrVgOPamp; + unsigned short PlsrDacBias; + unsigned short Reg19Spare; + unsigned short Vthin_AltCoarse; + unsigned short Vthin_AltFine; + unsigned short PlsrDAC; + unsigned short DIGHITIN_Sel; + unsigned short DINJ_Override; + unsigned short HITLD_In; + unsigned short Reg21Spare; + unsigned short Reg22Spare2; + unsigned short Colpr_Addr; + unsigned short Colpr_Mode; + unsigned short Reg22Spare1; + unsigned short DisableColumnCnfg0; + unsigned short DisableColumnCnfg1; + unsigned short DisableColumnCnfg2; + unsigned short TrigLat; + unsigned short CMDcnt; + unsigned short StopModeCnfg; + unsigned short HitDiscCnfg; + unsigned short EN_PLL; + unsigned short Efuse_sense; + unsigned short Stop_Clk; + unsigned short ReadErrorReq; + unsigned short ReadSkipped; + unsigned short Reg27Spare; + unsigned short GateHitOr; + unsigned short CalEn; + unsigned short SR_clr; + unsigned short Latch_en; + unsigned short SR_Clock; + unsigned short LVDSDrvSet06; + unsigned short Reg28Spare; + unsigned short EN40M; + unsigned short EN80M; + unsigned short CLK1; + unsigned short CLK0; + unsigned short EN160M; + unsigned short EN320M; + unsigned short Reg29Spare1; + unsigned short no8b10b; + unsigned short Clk2OutCnfg; + unsigned short EmptyRecord; + unsigned short Reg29Spare2; + unsigned short LVDSDrvEn; + unsigned short LVDSDrvSet30; + unsigned short LVDSDrvSet12; + unsigned short PlsrRiseUpTau; + unsigned short PlsrPwr; + unsigned short PlsrDelay; + unsigned short ExtDigCalSW; + unsigned short ExtAnaCalSW; + unsigned short Reg31Spare; + unsigned short SELB0; + unsigned short SELB1; + unsigned short SELB2; + unsigned short EfuseCref; + unsigned short EfuseVref; + unsigned short Chip_SN; +} ; + +struct PixelFEI4AConfig{ //FE level parameters + char idStr[16]; //Module ID string + unsigned long FEIndex; + PixelFECommand FECommand; + PixelFEI4AGlobal FEGlobal; + octet FEMasks[IPC_N_I4_PIXEL_COLUMNS][IPC_N_I4_PIXEL_ROWS]; // all masks combined, i.e. 4 bits per pixel + PixelFEI4Trims FETrims; + PixelFECalibFEI4 FECalib; +} ; + +}; + +#endif diff --git a/rce/rcecalib/idl/PixelFEI4BConfig.idl b/rce/rcecalib/idl/PixelFEI4BConfig.idl new file mode 100644 index 00000000..84c3b106 --- /dev/null +++ b/rce/rcecalib/idl/PixelFEI4BConfig.idl @@ -0,0 +1,128 @@ +#ifndef PixelFEI4BConfig_IDL +#define PixelFEI4BConfig_IDL + +#include "PixelFEI4GenConfig.idl" + +module ipc{ + +struct PixelFEI4BGlobal{ //FE global register + unsigned short TrigCnt; + unsigned short Conf_AddrEnable; + unsigned short Reg2Spare; + unsigned short ErrMask0; + unsigned short ErrMask1; + unsigned short PrmpVbpRight; + unsigned short BufVgOpAmp; + unsigned short Reg6Spare; + unsigned short PrmpVbp; + unsigned short TdacVbp; + unsigned short DisVbn; + unsigned short Amp2Vbn; + unsigned short Amp2VbpFol; + unsigned short Reg9Spare; + unsigned short Amp2Vbp; + unsigned short FdacVbn; + unsigned short Amp2Vbpf; + unsigned short PrmpVbnFol; + unsigned short PrmpVbpLeft; + unsigned short PrmpVbpf; + unsigned short PrmpVbnLcc; + unsigned short Reg13Spare; + unsigned short PxStrobes; + unsigned short S0; + unsigned short S1; + unsigned short LVDSDrvIref; + unsigned short GADCOpAmp; + unsigned short PllIbias; + unsigned short LVDSDrvVos; + unsigned short TempSensBias; + unsigned short PllIcp; + unsigned short Reg17Spare; + unsigned short PlsrIdacRamp; + unsigned short VrefDigTune; + unsigned short PlsrVgOPamp; + unsigned short PlsrDacBias; + unsigned short VrefAnTune; + unsigned short Vthin_AltCoarse; + unsigned short Vthin_AltFine; + unsigned short PlsrDAC; + unsigned short DIGHITIN_Sel; + unsigned short DINJ_Override; + unsigned short HITLD_In; + unsigned short Reg21Spare; + unsigned short Reg22Spare2; + unsigned short Colpr_Addr; + unsigned short Colpr_Mode; + unsigned short Reg22Spare1; + unsigned short DisableColumnCnfg0; + unsigned short DisableColumnCnfg1; + unsigned short DisableColumnCnfg2; + unsigned short TrigLat; + unsigned short CMDcnt; + unsigned short StopModeCnfg; + unsigned short HitDiscCnfg; + unsigned short EN_PLL; + unsigned short Efuse_sense; + unsigned short Stop_Clk; + unsigned short ReadErrorReq; + unsigned short Reg27Spare1; + unsigned short GADC_Enable; + unsigned short ShiftReadBack; + unsigned short Reg27Spare2; + unsigned short GateHitOr; + unsigned short CalEn; + unsigned short SR_clr; + unsigned short Latch_en; + unsigned short SR_Clock; + unsigned short LVDSDrvSet06; + unsigned short Reg28Spare; + unsigned short EN40M; + unsigned short EN80M; + unsigned short CLK1; + unsigned short CLK0; + unsigned short EN160M; + unsigned short EN320M; + unsigned short Reg29Spare1; + unsigned short no8b10b; + unsigned short Clk2OutCnfg; + unsigned short EmptyRecord; + unsigned short Reg29Spare2; + unsigned short LVDSDrvEn; + unsigned short LVDSDrvSet30; + unsigned short LVDSDrvSet12; + unsigned short TempSensDiodeSel; + unsigned short TempSensDisable; + unsigned short IleakRange; + unsigned short Reg30Spare; + unsigned short PlsrRiseUpTau; + unsigned short PlsrPwr; + unsigned short PlsrDelay; + unsigned short ExtDigCalSW; + unsigned short ExtAnaCalSW; + unsigned short Reg31Spare; + unsigned short GADCSel; + unsigned short SELB0; + unsigned short SELB1; + unsigned short SELB2; + unsigned short Reg34Spare1; + unsigned short PrmpVbpMsnEn; + unsigned short Reg34Spare2; + unsigned short Chip_SN; + unsigned short Reg1Spare; + unsigned short SmallHitErase; + unsigned short Eventlimit; +} ; + +struct PixelFEI4BConfig{ //FE level parameters + char idStr[16]; //Module ID string + unsigned long FEIndex; + PixelFECommand FECommand; + PixelFEI4BGlobal FEGlobal; + octet FEMasks[IPC_N_I4_PIXEL_COLUMNS][IPC_N_I4_PIXEL_ROWS]; // all masks combined, i.e. 4 bits per pixel + PixelFEI4Trims FETrims; + PixelFECalibFEI4 FECalib; +} ; + +}; + +#endif diff --git a/rce/rcecalib/idl/PixelFEI4GenConfig.idl b/rce/rcecalib/idl/PixelFEI4GenConfig.idl new file mode 100644 index 00000000..b6b5210d --- /dev/null +++ b/rce/rcecalib/idl/PixelFEI4GenConfig.idl @@ -0,0 +1,40 @@ +#ifndef PixelFEI4Config_IDL +#define PixelFEI4Config_IDL + +module ipc{ + + typedef sequence<unsigned long> uvec; + + const long IPC_N_I4_PIXEL_COLUMNS = 80; + const long IPC_N_I4_PIXEL_ROWS = 336; + const long enable = 0; + const long largeCap = 1; + const long smallCap = 2; + const long hitbus = 3; + +struct PixelFECommand{ //FE Command register + octet address; /* 5 bits */ + unsigned long command; /* 32 bits */ +} ; + +struct PixelFECalibFEI4{ +/* Sub-structure for calibration of injection-capacitors, VCAL-DAC and + leakage current measurement */ + float cinjLo; + float cinjHi; + float vcalCoeff[4]; + float chargeCoeffClo; + float chargeCoeffChi; + float chargeOffsetClo; + float chargeOffsetChi; + float monleakCoeff; +} ; + +struct PixelFEI4Trims{ //Trim DACs: + octet dacThresholdTrim[IPC_N_I4_PIXEL_COLUMNS][IPC_N_I4_PIXEL_ROWS]; /* 5 bits per pixel */ + octet dacFeedbackTrim [IPC_N_I4_PIXEL_COLUMNS][IPC_N_I4_PIXEL_ROWS]; /* 4 bits per pixel */ +} ; + +}; + +#endif diff --git a/rce/rcecalib/idl/PixelModuleConfig.idl b/rce/rcecalib/idl/PixelModuleConfig.idl new file mode 100644 index 00000000..a2fce8d6 --- /dev/null +++ b/rce/rcecalib/idl/PixelModuleConfig.idl @@ -0,0 +1,216 @@ +/************************************************************************** + * + * Title: Master/PIX moduleConfigStructures.h + * Version: 11th November 2002 + * + * Description: + * ROD Master DSP Pixel module configuration structures + * and constant definitions. + **************************************************************************/ +#ifndef PIXELMODULECONFIG_IDL +#define PIXELMODULECONFIG_IDL + +module ipc{ + + const long IPC_N_PIXEL_COLUMNS =18; + const long IPC_N_PIXEL_ROWS =160; + const long IPC_N_PIXEL_FE_CHIPS=16; + + const long IPC_FE_I1 =1; + const long IPC_FE_I2 =2; + const long IPC_MCC_I1 =1; + const long IPC_MCC_I2 =2; + + /* MCC options */ + + const long IPC_MCC_SINGLE_40 =0; + const long IPC_MCC_DOUBLE_40 =1; + const long IPC_MCC_SINGLE_80 =2; + const long IPC_MCC_DOUBLE_80 =3; + + +struct PixelFEGlobal{ //FE global register + //This is valid for both FE-I1 & 2, since the FE-I1 is a sub-set. + octet latency ; + octet dacIVDD2 ; + octet dacIP2 ; + octet dacID ; + + octet dacIP ; + octet dacITRIMTH ; + octet dacIF ; + octet dacITH1 ; + + octet dacITH2 ; + octet dacIL ; + octet dacIL2 ; + octet dacITRIMIF ; + + octet dacSpare ; + octet threshTOTMinimum ; + octet threshTOTDouble ; + octet hitbusScaler ; + + octet capMeasure ; + octet gdac ; + octet selfWidth ; + octet selfLatency ; + octet muxTestPixel ; + octet aregTrim ; + octet aregMeas ; + octet dregTrim ; + octet dregMeas ; + octet parity ; + + octet dacMonLeakADC ; + /* was defined as octet, but needs 10 bits */ + unsigned long dacVCAL ; /* extended to 10 bit for FE2/3 */ + octet widthSelfTrigger ; + octet muxDO ; /* note: dynamically defined */ + octet muxMonHit ; + octet muxEOC ; + + octet frequencyCEU ; + octet modeTOTThresh ; + octet enableTimestamp ; + octet enableSelfTrigger ; + octet enableHitParity ; + octet monMonLeakADC ; + octet monADCRef ; + octet enableMonLeak ; + octet statusMonLeak ; + octet enableCapTest ; + octet enableBuffer ; + octet enableVcalMeasure ; + octet enableLeakMeasure ; + octet enableBufferBoost ; + octet enableCP8 ; + octet monIVDD2 ; + octet monID ; + octet enableCP7 ; + octet monIP2 ; + octet monIP ; + octet enableCP6 ; + octet monITRIMTH ; + octet monIF ; + octet enableCP5 ; + octet monITRIMIF ; + octet monVCAL ; + octet enableCP4 ; + octet enableCinjHigh ; + octet enableExternal ; + octet enableTestAnalogRef ; + + octet enableDigital ; + octet enableCP3 ; + octet monITH1 ; + octet monITH2 ; + octet enableCP2 ; + octet monIL ; + octet monIL2 ; + octet enableCP1 ; + octet enableCP0 ; + octet enableHitbus ; + octet monSpare ; + octet enableAregMeas ; + octet enableAreg ; + octet enableLvdsRegMeas ; + octet enableDregMeas ; + octet enableTune ; + octet enableBiasComp ; + octet enableIpMonitor ; +} ; + + +struct PixelFEMasks{ //Pixel-level control bits + unsigned long maskEnable[5][IPC_N_PIXEL_COLUMNS]; /* 32 bits, one bit per pixel thus 5 words per column */ + unsigned long maskSelect[5][IPC_N_PIXEL_COLUMNS]; + unsigned long maskPreamp[5][IPC_N_PIXEL_COLUMNS]; + unsigned long maskHitbus[5][IPC_N_PIXEL_COLUMNS]; +} ; + + +struct PixelFETrims{ //Trim DACs: + octet dacThresholdTrim[IPC_N_PIXEL_ROWS][IPC_N_PIXEL_COLUMNS]; + octet dacFeedbackTrim[IPC_N_PIXEL_ROWS][IPC_N_PIXEL_COLUMNS]; +} ; + + +struct PixelFECalib{ +/* Sub-structure for calibration of injection-capacitors, VCAL-DAC and + leakage current measurement */ + float cinjLo; + float cinjHi; + float vcalCoeff[4]; + float chargeCoeffClo; + float chargeCoeffChi; + float chargeOffsetClo; + float chargeOffsetChi; + float monleakCoeff; +} ; + + +struct PixelMCCRegisters{ //MCC registers + unsigned short regCSR; + unsigned short regLV1; + unsigned short regFEEN; + unsigned short regWFE; + + unsigned short regWMCC; + unsigned short regCNT; + unsigned short regCAL; + unsigned short regPEF; + + unsigned short regWBITD; + unsigned short regWRECD; + unsigned short regSBSR; + + /* Strobe duration is a virtual register (shared with CNT); when preparing the + modules for data this value is substituted for the count. */ + unsigned short regSTR; +} ; + +struct PixelFEConfig{ //FE level parameters + unsigned long FEIndex; + PixelFEGlobal FEGlobal; + PixelFEMasks FEMasks; + PixelFETrims FETrims; + PixelFECalib FECalib; +} ; + + +struct PixelModuleConfig{ + /* FE module-level options: */ + unsigned short maskEnableFEConfig; /* 16 bits, one per FE */ + unsigned short maskEnableFEScan; + unsigned short maskEnableFEDacs; + octet feFlavour; + octet mccFlavour; + + /* FE configurations: */ + PixelFEConfig FEConfig[IPC_N_PIXEL_FE_CHIPS]; + + /* MCC configuration */ + PixelMCCRegisters MCCRegisters; + + char idStr[256]; /* Module identification string */ + octet present; /* Module is physically present. Does not need setting + externally; handled by the Master DSP. */ + + octet active; /* 1 -> participates in scans */ + /* 0 -> registers unchanged during scanning */ + octet moduleIdx; /* Copy of the module's index for access from a pointer */ + octet groupId; /* The ID of the module's group. This is used to indicate + which slave DSP will receive the module's data (if group + based distribution is set), and also to allow different + module groups to be triggered independently (for + cross-talk studies). valid range: [0,7] */ + octet pTTC; /* primary TX channel */ + octet rx; /* data link used by module */ + +} ; /* declare N_PIXEL_CONFIG_SETS structure for each of N_PIXEL_MODULES */ +}; + +#endif /* multiple inclusion protection */ + + diff --git a/rce/rcecalib/idl/ScanOptions.idl b/rce/rcecalib/idl/ScanOptions.idl new file mode 100644 index 00000000..a2af1560 --- /dev/null +++ b/rce/rcecalib/idl/ScanOptions.idl @@ -0,0 +1,96 @@ +#ifndef SCANOPTIONS_IDL +#define SCANOPTIONS_IDL + +module ipc{ + +typedef sequence<string> StringList; + +/* Trigger setup */ +/* bit mask optionsMask selects TriggerOptions */ +/* Override of global VCAL and delays with individual values */ +/* from ModuleConfig via special USE_MODULECONFIG_DEFAULT value */ +/* custom bitstream for cal trigger command sequence */ +/* define Triggermodes compatible with RODregisters */ + +struct TriggerOptions{ + string triggerMode; + unsigned short triggerMask; + unsigned short moduleTrgMask; + unsigned long nEvents; + octet triggerDataOn; + octet nL1AperEvent; + octet nTriggersPerGroup; + octet Lvl1_Latency; + octet Lvl1_Latency_Secondary; + octet injectForTrigger; + octet hitbusConfig; + unsigned short strobeDuration; + unsigned short deadtime; + unsigned long strobeMCCDelay; + unsigned long strobeMCCDelayRange; + unsigned long CalL1ADelay; + unsigned long eventInterval; + unsigned long vcal_charge; + unsigned short threshold; + unsigned long nTriggers; + StringList optionsMask; /* this is TriggOptions */ +}; + +struct PixelScanFE { + octet phi; + octet totThresholdMode; + octet totMinimum; + octet totTwalk; + octet totLeMode; + octet hitbus; + +}; + +/* Action to be performed after the scan, provision for different fit functions */ + +struct ActionOptions { + string Action; + string fitFunction; + unsigned long targetThreshold; +}; + + +struct ScanLoopDef{ + string scanParameter; + ActionOptions endofLoopAction; + unsigned long nPoints; + sequence<long> dataPoints; +}; + +typedef sequence<ScanLoopDef> ScanLoops; + +struct timeoutstruct{ + unsigned long seconds; + unsigned long nanoseconds; + long allowedTimeouts; +}; + + +struct ScanOptions{ + string stagingMode; + string maskStages; + unsigned short nMaskStages; + unsigned short firstStage; + unsigned short stepStage; + octet nLoops; + unsigned long runNumber; + TriggerOptions trigOpt; + PixelScanFE feOpt; + ScanLoops scanLoop; + string scanType; + string receiver; + string dataHandler; + string dataProc; + string name; + timeoutstruct timeout; + StringList histos; +}; + +}; + +#endif diff --git a/rce/rcecalib/idl/constituents.mk b/rce/rcecalib/idl/constituents.mk new file mode 100644 index 00000000..84165448 --- /dev/null +++ b/rce/rcecalib/idl/constituents.mk @@ -0,0 +1,33 @@ + +ifneq ($(findstring linux,$(tgt_os)),) +libnames := idl +endif +ifneq ($(findstring ppc-rtems-rce,$(tgt_arch)),) + modlibnames := idl +endif + + +libsrcs_idl := ScanOptionsSK.cc \ + CallbackSK.cc \ + PixelModuleConfigSK.cc \ + PixelFEI4GenConfigSK.cc \ + PixelFEI4AConfigSK.cc \ + PixelFEI4BConfigSK.cc \ + HitbusModuleConfigSK.cc \ + AFPHPTDCModuleConfigSK.cc \ + IPCScanRootAdapterSK.cc \ + IPCFEI3AdapterSK.cc \ + IPCFEI4AAdapterSK.cc \ + IPCFEI4BAdapterSK.cc \ + IPCHitbusAdapterSK.cc \ + IPCAFPHPTDCAdapterSK.cc \ + IPCScanAdapterSK.cc \ + IPCConfigIFAdapterSK.cc + + + + +libincs_idl := $(ipc_include_path) \ + $(omniorb_include_path) + + diff --git a/rce/rcecalib/namespace_aliases.hh b/rce/rcecalib/namespace_aliases.hh new file mode 100644 index 00000000..f84c5291 --- /dev/null +++ b/rce/rcecalib/namespace_aliases.hh @@ -0,0 +1,61 @@ +#ifndef __NAMESPACE_ALIASES_H__ +#define __NAMESPACE_ALIASES_H__ +#ifdef RCE_V2 +namespace service { + namespace fci { + class Exception; + } + namespace debug { + + } + namespace dynalink { + class RunnableModule; + class Linker; + class LinkingError; + } +} + +namespace oldPpi{ + namespace pic { + class Pool; + class Tds; + class Params; + } + + + namespace net { + class ipAddress; + } + namespace pgp { + class Driver; + } +} + +/* define aliases to map new core 2.2 namespaces to core 1.4 */ +namespace RcePic=oldPpi::pic; +namespace RcePgp=oldPpi::pgp; +namespace RceSvc=service::fci; +namespace RceNet=oldPpi::net; +namespace RceDebug=service::debug; +namespace RCE { + namespace ELF=service::dynalink; + namespace Dynalink=service::dynalink; +} +#else +/* forward declaration for old core 1.4 */ +namespace RcePic { + class Pool; + class Tds; + class Params; +} +namespace RceNet { + class ipAddress; +} +namespace RcePgp { + class Driver; +} +namespace RceSvc { + class Exception; +} +#endif +#endif diff --git a/rce/rcecalib/packages.mk b/rce/rcecalib/packages.mk new file mode 100644 index 00000000..235117dc --- /dev/null +++ b/rce/rcecalib/packages.mk @@ -0,0 +1,5 @@ +# List of packages (low level first) +#ifneq ($(findstring ppc-rtems-rce,$(tgt_arch)),) +packages := idl profiler util HW dataproc scanctrl config eudaq analysis server +#endif + diff --git a/rce/rcecalib/profiler/Makefile b/rce/rcecalib/profiler/Makefile new file mode 100644 index 00000000..3cd076af --- /dev/null +++ b/rce/rcecalib/profiler/Makefile @@ -0,0 +1,21 @@ +# Package level makefile +# ---------------------- +%.mk:; + +# Checks +# ------ +# Check release location variables +ifeq ($(RELEASE_DIR),) +export RELEASE_DIR := $(PWD)/../.. +endif + +include $(RELEASE_DIR)/make/share/setup.mk +include ../flags.mk + +ifndef PREMAKE_DONE +include $(RELEASE_DIR)/make/share/premake.mk +else +include constituents.mk +include $(RELEASE_DIR)/make/sw/package.mk +include $(RELEASE_DIR)/make/sw/rootcint.mk +endif diff --git a/rce/rcecalib/profiler/Profiler.cc b/rce/rcecalib/profiler/Profiler.cc new file mode 100644 index 00000000..6477e14e --- /dev/null +++ b/rce/rcecalib/profiler/Profiler.cc @@ -0,0 +1,1221 @@ +#define __PROFILER_CONSOLIDATE_THREADS__ + +#define css_outline_color "#848484" +#define css_thread_style "background-color:#EEEEEE;margin-top:8px;" +#define css_title_row "<tr class=\"header\"><td class=\"left\">Function</td><td>Calls</td><td>MCycles</td><td>Avg</td><td>Self MCycles</td><td class=\"right\">Self Avg</td></tr>\n" +#define css_totals_row "<tr class=\"header\"><td class=\"left\">Function</td><td>Calls</td><td>Self MCycles</td><td class=\"right\">Self Avg</td></tr>\n" + +#if defined(_WIN32) + #define _CRT_SECURE_NO_WARNINGS + #define copystring _strdup + #include <windows.h> +#else + #define copystring strdup + #include <unistd.h> +#endif + +#include <stdio.h> +#include <string.h> +#include <malloc.h> +#include <time.h> + +#include "Profiler.hh" + +#if defined(__ICC) || defined(__ICL) + #pragma warning( disable: 1684 ) // (size_t )name >> 5 + #pragma warning( disable: 1011 ) // missing return statement at end of non-void function +#endif + +#undef threadlocal + +#if defined(_MSC_VER) + #define YIELD() Sleep(0); + #define PRINTFU64() "%I64u" + #define PATHSLASH() '\\' + #define threadlocal __declspec(thread) + #define snprintf _snprintf + + #undef inline + #define inline __forceinline +#else + #include <sched.h> + #define YIELD() sched_yield(); + #define PRINTFU64() "%llu" + #define PATHSLASH() '/' + #define threadlocal __thread +#endif + +#if !defined(__PROFILER_SMP__) + #undef threadlocal + #define threadlocal +#endif + +namespace Profiler { + + #if defined(__PROFILER_SMP__) + #if defined(_MSC_VER) + + template< class type > + inline bool CAS( volatile type &ptr_, const type old_, const type new_ ) { + __asm { + mov eax, [old_] + mov edx, [new_] + mov ecx, [ptr_] + lock cmpxchg dword ptr [ecx], edx + sete al + } + } + + #elif defined(__GNUC__) || defined(__ICC) + + template< class type > + inline bool CAS( volatile type &ptr_, const type old_, const type new_ ) { + u8 ret; + __asm__ __volatile__ ( + " lock\n" + " cmpxchgl %2,%1\n" + " sete %0\n" + : "=q" (ret), "=m" (ptr_) + : "r" (new_), "m" (ptr_), "a" (old_) + : "memory" + ); + return ret; + } + + #else + #error Define a compare-and-swap / full memory barrier implementation! + #endif + + struct CASLock { + void Acquire() { while ( !CAS( mLock, u32(0), u32(1) ) ) YIELD() } + void Release() { while ( !CAS( mLock, u32(1), u32(0) ) ) YIELD() } + bool TryAcquire() { return CAS( mLock, u32(0), u32(1) ); } + bool TryRelease() { return CAS( mLock, u32(1), u32(0) ); } + u32 Value() const { return mLock; } + //protected: + volatile u32 mLock; + }; + #else + struct CASLock { + void Acquire() {} + void Release() {} + bool TryAcquire() { return false; } + bool TryRelease() { return false; } + u32 Value() const { return 0; } + u32 dummy; + }; + #endif + + u32 nextpow2( u32 x ) { + x |= ( x >> 1 ); + x |= ( x >> 2 ); + x |= ( x >> 4 ); + x |= ( x >> 8 ); + x |= ( x >> 16 ); + return ( x + 1 ); + } + + template< class type > + inline void zeroarray( type *array, size_t count ) { + memset( array, 0, count * sizeof( type ) ); + } + + template< class type > + inline type *makepointer( type *base, size_t byteoffset ) { + return (type *)((const char *)base + byteoffset); + } + + template< class type > + inline void swapitems( type &a, type &b ) { + type tmp = a; + a = b; + b = tmp; + } + + #undef min + #undef max + + template< class type > + inline const type &min( const type &a, const type &b ) { + return ( a < b ) ? a : b; + } + + template< class type > + inline const type &max( const type &a, const type &b ) { + return ( a < b ) ? b : a; + } + + /* + ============= + Buffer - Don't use for anything with a constructor/destructor. Doesn't shrink on popping + ============= + */ + + template< class type > + struct Buffer { + Buffer() : mBuffer(NULL), mAlloc(0), mItems(0) { Resize( 4 ); } + Buffer( u32 size ) : mBuffer(NULL), mAlloc(0), mItems(0) { Resize( size ); } + ~Buffer() { free( mBuffer ); } + + void Clear() { mItems = ( 0 ); } + type *Data() { return ( mBuffer ); } + void EnsureCapacity( u32 capacity ) { if ( capacity >= mAlloc ) Resize( capacity * 2 ); } + type *Last() { return ( &mBuffer[ mItems - 1 ] ); } + void Push( const type &item ) { EnsureCapacity( mItems + 1 ); mBuffer[ mItems++ ] = ( item ); } + type &Pop() { return ( mBuffer[ --mItems ] ); } + + void Resize( u32 newsize ) { + mAlloc = nextpow2( newsize ); + mBuffer = (type *)realloc( mBuffer, mAlloc * sizeof( type ) ); + } + + u32 Size() const { return mItems; } + + template< class Compare > + void Sort( Compare comp ) { + if ( mItems <= 1 ) + return; + + Buffer scratch( mItems ); + + // merge sort with scratch buffer + type *src = Data(), *dst = scratch.Data(); + for( u32 log = 2; log < mItems * 2; log *= 2 ) { + type *out = dst; + for( u32 i = 0; i < mItems; i += log ) { + u32 lo = i, lo2 = min( i + log / 2, mItems ); + u32 hi = lo2, hi2 = min( lo + log, mItems ); + while ( ( lo < lo2 ) && ( hi < hi2 ) ) + *out++ = ( comp( src[lo], src[hi] ) ) ? src[lo++] : src[hi++]; + while ( lo < lo2 ) *out++ = src[lo++]; + while ( hi < hi2 ) *out++ = src[hi++]; + } + + swapitems( src, dst ); + } + + if ( src != mBuffer ) + swapitems( mBuffer, scratch.mBuffer ); + } + + template< class Mapto > + void ForEachByRef( Mapto &mapto, u32 limit ) { + limit = ( limit < mItems ) ? limit : mItems; + u32 last = limit - 1; + for ( u32 i = 0; i < limit; ++i ) + mapto( mBuffer[ i ], i == last ); + } + + template< class Mapto > void ForEach( Mapto mapto, u32 limit ) { ForEachByRef( mapto, limit ); } + template< class Mapto > void ForEach( Mapto mapto ) { ForEachByRef( mapto, mItems ); } + + type &operator[] ( u32 index ) { return ( mBuffer[ index ] ); } + const type &operator[] ( u32 index ) const { return ( mBuffer[ index ] ); } + + protected: + type *mBuffer; + u32 mAlloc, mItems; + }; + + + /* + =================== + ColorRamp for HTML + =================== + */ +#ifdef ENABLE_HTML + struct ColorF { + ColorF() {} + ColorF( f32 r_, f32 g_, f32 b_ ) : r(r_), g(g_), b(b_) {} + f32 r, g, b; + }; + + struct ColorRamp { + struct Marker { + Marker() {} + Marker( const ColorF &color_, f32 value_ ) : color(color_), value(value_) {} + ColorF color; + f32 value; + }; + + ColorRamp() {} + + void clear() { + mColors.Clear(); + } + + const char *value( f32 pos ) const { + ColorF base(0, 0, 0); + u32 pre = 0, post = 0; + for ( pre = 0; pre < mColors.Size() - 1; pre++ ) + if ( mColors[pre+1].value >= pos ) + break; + post = pre + 1; + if ( ( pre < mColors.Size() ) && ( post < mColors.Size() ) ) { + const Marker &a = mColors[pre], &b = mColors[post]; + f32 dist = ( b.value - a.value ), posw = ( pos - a.value ), bw = ( posw / dist ), aw = 1 - bw; + base = ColorF( a.color.r * aw + b.color.r * bw, a.color.g * aw + b.color.g * bw, a.color.b * aw + b.color.b * bw ); + } + u8 r = u8(base.r * 255.0f), g = u8(base.g * 255.0f), b = u8(base.b * 255.0f); + static threadlocal char buffer[8][32], bufferon = 0; + sprintf( buffer[bufferon&7], "#%02x%02x%02x", r, g, b ); + return buffer[bufferon++&7]; + } + + ColorRamp &push( const ColorF &color, f32 value ) { mColors.Push( Marker( color, value ) ); return *this; } + + Buffer<Marker> mColors; + }; +#endif + /* + ============= + Caller + ============= + */ + + #pragma pack(push,1) + struct Caller { + struct foreach { + // Adds each Caller to the specified buckets + struct AddToNewBuckets { + AddToNewBuckets( Caller **buckets, u32 bucket_count ) : mBuckets(buckets), mBucketCount(bucket_count) {} + void operator()( Caller *item ) { + FindEmptyChildSlot( mBuckets, mBucketCount, item->mName ) = item; + } + Caller **mBuckets; + u32 mBucketCount; + }; + + + // Destructs a Caller + struct Deleter { + void operator()( Caller *item ) { + delete item; + } + }; + + // Merges a Caller with the root + struct Merger { + Merger( Caller *root ) : mRoot(root) {} + void addFrom( Caller *item ) { (*this)( item ); } + void operator()( Caller *item ) { + Caller *child = mRoot->FindOrCreate( item->GetName() ); + child->GetTimer() += item->GetTimer(); + child->SetParent( item->GetParent() ); + item->ForEachNonEmpty( Merger( child ) ); + } + Caller *mRoot; + }; + + // Prints a Caller + struct Printer { + Printer( u32 indent ) : mIndent(indent) { } + void operator()( Caller *item, bool islast ) const { + item->Print( mIndent, islast ); + } + u32 mIndent; + }; +#ifdef ENABLE_HTML + struct PrinterHtml { + PrinterHtml( FILE *f, u32 indent ) : mFile(f), mIndent(indent) { } + void operator()( Caller *item, bool islast ) const { + item->PrintHtml( mFile, mIndent, islast ); + } + FILE *mFile; + u32 mIndent; + }; +#endif + struct SoftReset { + void operator()( Caller *item ) { + item->GetTimer().SoftReset(); + item->ForEach( SoftReset() ); + } + }; + + // Sums Caller's ticks + struct SumTicks { + SumTicks() : sum(0) {} + void operator()( Caller *item ) { + sum += ( item->mTimer.ticks ); + } + u64 sum; + }; + + struct UpdateTopMaxStats { + UpdateTopMaxStats() { maxStats.reset(); } + void operator()( Caller *item, bool islast ) { + if ( !item->GetParent() ) + return; + maxStats.check( Max::Calls, item->mTimer.calls ); + maxStats.check( Max::Ms, Timer::ms( item->mTimer.ticks ) ); + maxStats.check( Max::Avg, item->mTimer.avgms() ); + } + }; + }; // foreach + + + struct compare { + struct Ticks { + bool operator()( const Caller *a, const Caller *b ) const { + return ( a->mTimer.ticks > b->mTimer.ticks ); + } + }; + + struct SelfTicks { + bool operator()( const Caller *a, const Caller *b ) const { + return ( ( a->mTimer.ticks - a->mChildTicks ) > ( b->mTimer.ticks - b->mChildTicks ) ); + } + }; + + struct Calls { + bool operator()( const Caller *a, const Caller *b ) const { + return ( a->mTimer.calls > b->mTimer.calls ); + } + }; + }; // sort + + + /* + Since Caller.mTimer.ticks is inclusive of all children, summing the first level + children of a Caller to Caller.mChildTicks is an accurate total of the complete + child tree. + + mTotals is used to keep track of total ticks by Caller excluding children + */ + struct ComputeChildTicks { + ComputeChildTicks( Caller &totals ) : mTotals(totals) { maxStats.reset(); } + void operator()( Caller *item ) { + foreach::SumTicks sumchildren; + item->ForEachByRefNonEmpty( sumchildren ); + item->mChildTicks = ( sumchildren.sum ); + + u64 selfticks = ( item->mTimer.ticks >= item->mChildTicks ) ? ( item->mTimer.ticks - item->mChildTicks ) : 0; + Caller &totalitem = ( *mTotals.FindOrCreate( item->mName ) ); + totalitem.mTimer.ticks += selfticks; + totalitem.mTimer.calls += item->mTimer.calls; + totalitem.SetParent( item->GetParent() ); + + // don't include the root node in the max stats + if ( item->GetParent() ) { + maxStats.check( Max::SelfMs, Timer::ms( selfticks ) ); + maxStats.check( Max::Calls, item->mTimer.calls ); + maxStats.check( Max::Ms, Timer::ms( item->mTimer.ticks ) ); + maxStats.check( Max::Avg, item->mTimer.avgms() ); + maxStats.check( Max::SelfAvg, average( Timer::ms( selfticks ), item->mTimer.calls ) ); + } + + // compute child ticks for all children of children of this caller + item->ForEachByRefNonEmpty( *this ); + } + Caller &mTotals; + }; + + /* + Format a Caller's information. ComputeChildTicks will need to be used on the Root + to generate mChildTicks for all Callers + */ + struct Format { + Format( const char *prefix ) : mPrefix(prefix) {} + void operator()( Caller *item, bool islast ) const { + u64 ticks = item->mTimer.ticks; + f64 ms = Timer::ms( ticks ); + printf( "%s "PRINTFF64(".2")" mcycles, %d calls, "PRINTFF64(".0")" cycles avg, "PRINTFF64(".2")"%%: %s\n", + mPrefix, ms, item->mTimer.calls, item->mTimer.avg(), average( ticks * 100, mGlobalDuration ), item->mName ); + } + const char *mPrefix; + }; +#ifdef ENABLE_HTML + struct FormatHtml { + FormatHtml( FILE *f, Buffer<const char *> &prefix ) : mFile(f), mPrefix(prefix) {} + void operator()( Caller *item ) const { + fprintf( mFile, "\t<tr %s><td><table class=\"tree\"><tr>", !item->GetParent() ? "style=\"" css_thread_style "\"": "class=\"h\"" ); + for ( u32 i = 0; i < mPrefix.Size(); i++ ) + fprintf( mFile, "<td><img src=\"%s\" /></td>", mPrefix[i] ); + u64 ticks = item->mTimer.ticks; + f64 ms = Timer::ms( ticks ), globalpct = average( ticks * 100, mGlobalDuration ); + f64 childms = Timer::ms( item->mChildTicks ), selfms = ( ms - childms ), avg = item->mTimer.avgms(), selfavg = average( selfms, item->mTimer.calls ); + if ( !item->GetParent() ) + fprintf( mFile, "<td class=\"text\">%s</td></tr></table></td><td class=\"number\">%u</td><td class=\"number\">"PRINTFF64("0.4")" ("PRINTFF64("3.0")"%%)</td><td class=\"number\">"PRINTFF64("0.4")"</td><td class=\"number\">"PRINTFF64("0.4")"</td><td class=\"number\">"PRINTFF64("0.4")"</td></tr>\n", + item->mName, + item->mTimer.calls, + ms, + globalpct, + avg, + selfms, + selfavg + ); + else + fprintf( mFile, "<td class=\"text\">%s</td></tr></table></td><td class=\"number\" style=\"background-color:%s\">%u</td><td class=\"number\" style=\"background-color:%s\">"PRINTFF64("0.4")" ("PRINTFF64("0.3")"%%)</td><td class=\"number\" style=\"background-color:%s\">"PRINTFF64("0.4")"</td><td class=\"number\" style=\"background-color:%s\">"PRINTFF64("0.4")"</td><td class=\"number\" style=\"background-color:%s\">"PRINTFF64("0.4")"</td></tr>\n", + item->mName, + maxStats.color( Max::Calls, item->mTimer.calls ), item->mTimer.calls, + maxStats.color( Max::Ms, ms ), ms, + globalpct, + maxStats.color( Max::Avg, avg ), avg, + maxStats.color( Max::SelfMs, selfms ), selfms, + maxStats.color( Max::SelfAvg, selfavg ), selfavg + ); + } + FILE *mFile; + Buffer<const char *> &mPrefix; + }; + + struct FormatHtmlTop { + FormatHtmlTop( FILE *f ) : mFile(f) {} + void operator()( Caller *item, bool islast ) const { + fprintf( mFile, "\t<tr %s><td><table class=\"tree\"><tr>", !item->GetParent() ? "style=\"" css_thread_style "\"": "class=\"h\"" ); + fprintf( mFile, "<td><img src=\"%s\" /></td>", islast ? "img/last-empty.gif" : "img/empty.gif" ); + u64 ticks = item->mTimer.ticks; + f64 ms = Timer::ms( ticks ), globalpct = average( ticks * 100, mGlobalDuration ), avg = item->mTimer.avgms(); + if ( !item->GetParent() ) { + fprintf( mFile, "<td class=\"text\">%s</td></tr></table></td><td class=\"number\">%u</td><td class=\"number\">"PRINTFF64("0.4f")" ("PRINTFF64(".0")"%%)</td><td class=\"number\">"PRINTFF64(".4")"</td></tr>\n", + item->mName, + item->mTimer.calls, + ms, + globalpct, + avg + ); + } else { + fprintf( mFile, "<td class=\"text\">%s</td></tr></table></td><td class=\"number\" style=\"background-color:%s\">%u</td><td class=\"number\" style=\"background-color:%s\">"PRINTFF64("0.4")" ("PRINTFF64("0")"%%)</td><td class=\"number\" style=\"background-color:%s\">"PRINTFF64("0.4")"</td></tr>\n", + item->mName, + maxStats.color( Max::Calls, item->mTimer.calls ), item->mTimer.calls, + maxStats.color( Max::Ms, ms ), ms, + globalpct, + maxStats.color( Max::Avg, avg ), avg + ); + } + } + FILE *mFile; + }; +#endif + /* + Methods + */ + + // we're guaranteed to be null because of calloc. ONLY create Callers with "new"! + Caller( const char *name, Caller *parent = NULL ) { + mName = name; + mParent = parent; + Resize( 2 ); // mBuckets must always exist and mBucketCount >= 2! + } + + ~Caller() { + ForEach( foreach::Deleter() ); + free( mBuckets ); + } + + void CopyToListNonEmpty( Buffer<Caller *> &list ) { + list.Clear(); + + for ( u32 i = 0; i < mBucketCount; ++i ) + if ( mBuckets[ i ] && !mBuckets[ i ]->GetTimer().IsEmpty() ) + list.Push( mBuckets[ i ] ); + } + + inline Caller *FindOrCreate( const char *name ) { + u32 index = ( GetBucket( name, mBucketCount ) ), mask = ( mBucketCount - 1 ); + for ( Caller *caller = mBuckets[index]; caller; caller = mBuckets[index & mask] ) { + if ( caller->mName == name ) + return caller; + + index = ( index + 1 ); + } + + // didn't find the caller, lock this thread and mutate + AcquirePerThreadLock(); + EnsureCapacity( ++mNumChildren ); + Caller *&slot = FindEmptyChildSlot( mBuckets, mBucketCount, name ); + slot = new Caller( name, this ); + ReleasePerThreadLock(); + return slot; + } + + template< class Mapto > + void ForEachByRef( Mapto &mapto ) { + for ( u32 i = 0; i < mBucketCount; ++i ) + if ( mBuckets[ i ] ) + mapto( mBuckets[ i ] ); + } + + template< class Mapto > + void ForEachByRefNonEmpty( Mapto &mapto ) { + for ( u32 i = 0; i < mBucketCount; ++i ) + if ( mBuckets[ i ] && !mBuckets[ i ]->GetTimer().IsEmpty() ) + mapto( mBuckets[ i ] ); + } + + template< class Mapto > + void ForEach( Mapto mapto ) { + ForEachByRef( mapto ); + } + + template< class Mapto > + void ForEachNonEmpty( Mapto mapto ) { + ForEachByRefNonEmpty( mapto ); + } + + inline Caller *GetParent() { + return mParent; + } + + Timer &GetTimer() { + return mTimer; + } + + const char *GetName() const { + return mName; + } + + bool IsActive() const { + return mActive; + } + + void Print( u32 indent = 0, bool islast = false ) { + Buffer<Caller *> children( mNumChildren ); + CopyToListNonEmpty( children ); + + mFormatter.EnsureCapacity( indent + 3 ); + char *fmt = ( &mFormatter[indent] ); + + if ( indent ) { + fmt[-2] = ( islast ) ? ' ' : '|'; + fmt[-1] = ( islast ) ? '\\' : ' '; + } + fmt[0] = ( children.Size() ) ? '+' : '-'; + fmt[1] = ( '-' ); + fmt[2] = ( 0 ); + + Format(mFormatter.Data())( this, islast ); + + if ( indent && islast ) + fmt[-2] = fmt[-1] = ' '; + + if ( children.Size() ) { + children.Sort( compare::Ticks() ); + children.ForEach( foreach::Printer(indent+2) ); + } + } +#ifdef ENABLE_HTML + void PrintHtml( FILE *f, u32 indent = 0, bool islast = false ) { + Buffer<Caller *> children( mNumChildren ); + CopyToListNonEmpty( children ); + + if ( !indent ) { + mHTMLFormatter.Push( "img/root.gif" ); + } else if ( children.Size() ) { + mHTMLFormatter.Push( ( ( islast ) || ( children.Size() == 1 ) ) ? "img/last-child-open.gif" : "img/open.gif" ); + } else { + mHTMLFormatter.Push( ( islast ) ? "img/last-empty.gif" : "img/empty.gif" ); + } + + FormatHtml(f, mHTMLFormatter)( this ); + + mHTMLFormatter[indent] = ( islast || !indent ) ? "img/blank.gif" : "img/vertical.gif"; + + if ( children.Size() ) { + children.Sort( compare::Ticks() ); + children.ForEach( foreach::PrinterHtml(f,indent+1) ); + } + + mHTMLFormatter.Pop(); + } +#endif + void PrintTopStats( u32 nitems ) { + nitems = ( nitems > mNumChildren ) ? mNumChildren : nitems; + printf( "\ntop %d functions (self time)\n", (u32 )nitems ); + Buffer<Caller *> sorted( mNumChildren ); + CopyToListNonEmpty( sorted ); + sorted.Sort( compare::SelfTicks() ); + sorted.ForEach( Format(">"), nitems ); + } + + void Resize( u32 new_size ) { + new_size = ( new_size < mBucketCount ) ? mBucketCount << 1 : nextpow2( new_size - 1 ); + Caller **new_buckets = (Caller **)calloc( new_size, sizeof( Caller* ) ); + ForEach( foreach::AddToNewBuckets( new_buckets, new_size ) ); + + free( mBuckets ); + mBuckets = ( new_buckets ); + mBucketCount = ( new_size ); + } + + void Reset() { + ForEach( foreach::Deleter() ); + zeroarray( mBuckets, mBucketCount ); + mNumChildren = ( 0 ); + mTimer.Reset(); + } + + void SetActive( bool active ) { + mActive = active; + } + + void SetParent( Caller *parent ) { + mParent = parent; + } + + void SoftReset() { + mTimer.SoftReset(); + ForEach( foreach::SoftReset() ); + } + + void Start() { + mTimer.Start(); + } + + void Stop() { + mTimer.Stop(); + } + + void *operator new ( size_t size ) { + return calloc( size, 1 ); + } + + void operator delete ( void *p ) { + free( p ); + } + + + /* Acquire the caller lock for this thread */ + + inline static void AcquirePerThreadLock() { +#if defined(__PROFILER_SMP__) + if ( thisThread.requireThreadLock ) + thisThread.threadLock.Acquire(); +#endif + } + + inline static void ReleasePerThreadLock() { +#if defined(__PROFILER_SMP__) + if ( thisThread.requireThreadLock ) + thisThread.threadLock.Release(); +#endif + } + + protected: + static inline Caller *&FindEmptyChildSlot( Caller **buckets, u32 bucket_count, const char *name ) { + u32 index = ( GetBucket( name, bucket_count ) ), mask = ( bucket_count - 1 ); + Caller **caller = &buckets[index]; + for ( ; *caller; caller = &buckets[index & mask] ) + index = ( index + 1 ); + return *caller; + } + + inline static u32 GetBucket( const char *name, u32 bucket_count ) { + return u32( ( ( (size_t )name >> 5 ) /* * 2654435761 */ ) & ( bucket_count - 1 ) ); + } + + inline void EnsureCapacity( u32 capacity ) { + if ( capacity < ( mBucketCount / 2 ) ) + return; + Resize( capacity ); + } + + protected: + const char *mName; + Timer mTimer; + u32 mBucketCount, mNumChildren; + Caller **mBuckets, *mParent; + + bool mActive; + u64 mChildTicks; + + public: + // caller + static Buffer<char> mFormatter; +#ifdef ENABLE_HTML + static Buffer<const char *> mHTMLFormatter; + static ColorRamp mColors; +#endif + // global + static f64 mTimerOverhead, mRdtscOverhead; + static u64 mGlobalDuration; + static struct Max { + enum f64Enum { SelfMs = 0, Ms, Avg, SelfAvg, f64Enums }; + enum u64Enum { Calls = 0, TotalCalls, u64Enums }; + + void reset() { + memset( this, 0, sizeof( *this ) ); + } + + void check( u64Enum e, u64 u ) { if ( u64fields[e] < u ) u64fields[e] = u; if ( e == Calls ) u64fields[TotalCalls] += u; } + void check( f64Enum e, f64 f ) { if ( f64fields[e] < f ) f64fields[e] = f; } +#ifdef ENABLE_HTML + const char *color( u64Enum e, u64 u ) const { return mColors.value( f32(f64(u)/f64(u64fields[e])) ); } + const char *color( f64Enum e, f64 f ) const { return mColors.value( f32(f/f64fields[e]) ); } +#endif + const u64 &operator() ( u64Enum e ) const { return u64fields[e]; } + const f64 &operator() ( f64Enum e ) const { return f64fields[e]; } + + protected: + u64 u64fields[u64Enums]; + f64 f64fields[f64Enums]; + } maxStats; + + // per thread state + struct ThreadState { + CASLock threadLock; + bool requireThreadLock; + Caller *activeCaller; + }; + + static threadlocal ThreadState thisThread; + }; + #pragma pack(pop) + + + + + + +#if defined(__PROFILER_ENABLED__) + threadlocal Caller::ThreadState Caller::thisThread = { {0}, 0, 0 }; + f64 Caller::mTimerOverhead = 0, Caller::mRdtscOverhead = 0; + u64 Caller::mGlobalDuration = 0; + Caller::Max Caller::maxStats; + Buffer<char> Caller::mFormatter( 64 ); +#ifdef ENABLE_HTML + Buffer<const char *> Caller::mHTMLFormatter( 64 ); + ColorRamp Caller::mColors; +#endif + char *programName = NULL, *commandLine = NULL; + + void detectByArgs( int argc, const char *argv[] ) { + const char *path = argv[0], *finalSlash = path, *iter = path; + for ( ; *iter; ++iter ) + finalSlash = ( *iter == PATHSLASH() ) ? iter + 1 : finalSlash; + if ( !*finalSlash ) + finalSlash = path; + programName = copystring( finalSlash ); + + size_t width = 0; + for ( int i = 1; i < argc; i++ ) { + size_t len = strlen( argv[i] ); + commandLine = (char *)realloc( commandLine, width + len + 1 ); + memcpy( commandLine + width, argv[i], len ); + commandLine[width + len] = ' '; + width += len + 1; + } + if ( width ) + commandLine[width - 1] = '\x0'; + } + + void detectWinMain( const char *cmdLine ) { +#if defined(_MSC_VER) + char path[1024], *finalSlash = path, *iter = path; + GetModuleFileName( NULL, path, 1023 ); + for ( ; *iter; ++iter ) + finalSlash = ( *iter == PATHSLASH() ) ? iter + 1 : finalSlash; + if ( !*finalSlash ) + finalSlash = path; + programName = copystring( finalSlash ); + commandLine = copystring( cmdLine ); +#else + programName = copystring( "only_for_win32" ); + commandLine = copystring( "" ); +#endif + } + + /* + ============ + Root - Holds the root caller and the thread state for a thread + ============ + */ + + struct Root { + Root( Caller *caller, Caller::ThreadState *ts ) : root(caller), threadState(ts) {} + Caller *root; + Caller::ThreadState *threadState; + }; + + struct GlobalThreadList { + ~GlobalThreadList() { + if ( list ) { + Buffer<Root> &threadsref = *list; + u32 cnt = threadsref.Size(); + for ( u32 i = 0; i < cnt; i++ ) + delete threadsref[i].root; + } + delete list; + } + + void AcquireGlobalLock() { + threadsLock.Acquire(); + if ( !list ) + list = new Buffer<Root>; + } + + void ReleaseGlobalLock() { + threadsLock.Release(); + } + + Buffer<Root> *list; + CASLock threadsLock; + }; + + u64 globalStart = Timer::getticks(); + GlobalThreadList threads = { NULL, {0} }; + threadlocal Caller *root = NULL; + + + /* + Thread Dumping + */ + + struct PrintfDumper { + void Init() { + } + + void GlobalInfo( u64 rawCycles ) { + printf( "> Raw run time "PRINTFF64(".2")" mcycles\n", Timer::ms( rawCycles ) ); + } + + void ThreadsInfo( u64 totalCalls, f64 timerOverhead, f64 rdtscOverhead ) { + printf( "> Total calls " PRINTFU64() ", per call overhead "PRINTFF64(".0")" cycles, rdtsc overhead "PRINTFF64(".0")" cycles, estimated overhead "PRINTFF64(".2")" mcycles\n\n", + totalCalls, timerOverhead, rdtscOverhead, Timer::ms( timerOverhead * totalCalls ) ); + } + + void PrintThread( Caller *root ) { + root->Print(); + printf( "\n\n" ); + } + + void PrintAccumulated( Caller *accumulated ) { + accumulated->PrintTopStats( 50 ); + } + + void Finish() { + } + }; +#ifdef ENABLE_HTML + struct HTMLDumper { + void Init() { + Caller::mColors.clear(); + Caller::mColors.push( ColorF( 255.0f/255.0f, 255.0f/255.0f, 255.0f/255.0f ), 0.00f ); + //Caller::mColors.push( ColorF( 255.0f/255.0f, 212.0f/255.0f, 129.0f/255.0f ), 0.50f ); + Caller::mColors.push( ColorF( 255.0f/255.0f, 203.0f/255.0f, 203.0f/255.0f ), 0.20f ); + Caller::mColors.push( ColorF( 255.0f/255.0f, 128.0f/255.0f, 128.0f/255.0f ), 1.00f ); + + time_t now; + time( &now ); + tm *now_tm = localtime( &now ); + strftime( timeFormat, 255, "%Y%m%d_%H%M%S", now_tm ); + snprintf( fileFormat, 255, "%s-profile-%s.html", programName ? programName : "no-info-given", timeFormat ); + strftime( timeFormat, 255, "%#c", now_tm ); + f = fopen( fileFormat, "wb+" ); + + Caller::mHTMLFormatter.Clear(); + fputs( + "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" + "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\" class=\"\">\n" + "<head>\n" + " <style type=\"text/css\">\n" + " body {font-family: arial;font-size: 11px;}\n" + " table {padding: 0px;margin: 0px;border-spacing: 0pt 0pt;}\n" + " table.tree td {padding: 0px; margin: 0px;}\n" + " tr {padding: 0px;margin: 0px;}\n" + " tr.h:hover {background-color: #EEEEEE; color:blue;}\n" + " tr.header {background-image: url(img/tile.gif); background-position: left bottom; background-repeat: repeat-x; height: 24px;}\n" + " tr.header td { padding-left: 8px; padding-right:8px; border-right:1px solid " css_outline_color "; border-top:1px solid " css_outline_color "; }\n" + " tr.header td.left { border-left:1px solid " css_outline_color "; }\n" + " tr.header td.right { border-right:1px solid " css_outline_color "; }\n" + " tr.spacer {height: 24px;}\n" + " td {padding: 0px;padding-left:3px;padding-right:3px;margin: 0px;}\n" + " td.text {text-align: left;}\n" + " td.number {text-align: right;}\n" + " div.overall { background-color: #F0F0F0; width: 98%; color: #A31212; font-size: 16px; padding: 5px; padding-left: 20px; margin-bottom: 15px; }\n" + " div.thread { margin-bottom: 15px; }\n" + " div.overall td.title { padding-left: 10px; font-weight: bold; }\n" + " </style>\n" + "</head>\n" + "<body>\n\n", + f + ); + } + + void GlobalInfo( u64 rawCycles ) { + fputs( "<div class=\"overall\"><table>", f ); + if ( programName ) { + fprintf( f, "<tr><td class=\"title\">Command Line: </td><td>%s", programName ); + if ( commandLine ) + fprintf( f, " %s", commandLine ); + fputs( "</td></tr>", f ); + } + fprintf( f, "<tr><td class=\"title\">Date: </td><td>%s</td></tr><tr><td class=\"title\">Raw run time: </td><td>"PRINTFF64(".2")" mcycles</td></tr>\n", + timeFormat, Timer::ms( rawCycles ) ); + } + + void ThreadsInfo( u64 totalCalls, f64 timerOverhead, f64 rdtscOverhead ) { + fprintf( f, "<tr><td class=\"title\">Total calls: </td><td>" PRINTFU64() "</td></tr>\n", totalCalls ); + fprintf( f, "<tr><td class=\"title\">rdtsc overhead: </td><td>"PRINTFF64(".2")" cycles</td></tr>\n", rdtscOverhead ); + fprintf( f, "<tr><td class=\"title\">Per call overhead: </td><td>"PRINTFF64(".0")" cycles</td></tr>\n", timerOverhead ); + fprintf( f, "<tr><td class=\"title\">Estimated overhead: </td><td>"PRINTFF64(".4")" mcycles</td></tr>\n", Timer::ms( totalCalls * timerOverhead ) ); + fprintf( f, "</table></div>\n" ); + } + + void PrintThread( Caller *root ) { + fputs( "<div class=\"thread\"><table>\n", f ); + fputs( css_title_row, f ); + root->PrintHtml( f ); + fputs( "</table></div>\n", f ); + } + + void PrintAccumulated( Caller *accumulated ) { + fputs( "<div class=\"thread\"><table>\n", f ); + fputs( css_totals_row, f ); + fputs( "<tr style=\"" css_thread_style "\"><td><table><tr><td><img src=\"img/root.gif\" /></td><td>Functions sorted by self time</td></tr></table></td><td></td><td></td><td></td></tr>\n", f ); + Buffer<Caller *> sorted; + accumulated->CopyToListNonEmpty( sorted ); + sorted.ForEach( Caller::foreach::UpdateTopMaxStats() ); + sorted.Sort( Caller::compare::SelfTicks() ); + sorted.ForEach( Caller::FormatHtmlTop(f) ); + fputs( "</table></div>\n", f ); + } + + void Finish() { + fputs( "</div>\n", f ); + fputs( "</body></html>", f ); + fclose( f ); + } + + protected: + FILE *f; + char timeFormat[256], fileFormat[256]; + }; +#endif + + template< class Dumper > + void dumpThreads( Dumper dumper ) { + u64 rawDuration = ( Timer::getticks() - globalStart ); + + Caller *accumulate = new Caller( "/Top Callers" ), *packer = new Caller( "/Thread Packer" ); + Buffer<Caller *> packedThreads; + + dumper.Init(); + dumper.GlobalInfo( rawDuration ); + + threads.AcquireGlobalLock(); + + // crawl the list of theads and store their data in to packer + Buffer<Root> &threadsref = *threads.list; + for ( u32 i = 0; i < threadsref.Size(); i++ ) { + Root &thread = threadsref[i]; + + // if the thread is no longer active, the lock won't be valid + bool active = ( thread.root->IsActive() ); + if ( active ) { + thread.threadState->threadLock.Acquire(); + // disable requiring our local lock in case the caller is in our thread, accumulate will try to set it otherwise + Caller::thisThread.requireThreadLock = false; + for ( Caller *walk = thread.threadState->activeCaller; walk; walk = walk->GetParent() ) + walk->GetTimer().SoftStop(); + } + +#if defined(__PROFILER_CONSOLIDATE_THREADS__) + // merge the thread into the packer object, will result in 1 caller per thread name, not 1 caller per thread instance + Caller::foreach::Merger( packer ).addFrom( thread.root ); + Caller *child = packer->FindOrCreate( thread.root->GetName() ); + + // add the child to the list of threads to dump (use the active flag to indicate if it's been added) + if ( !child->IsActive() ) { + packedThreads.Push( child ); + child->SetActive( true ); + } +#else + // create a dummy entry for each thread (fake a name with the address of the thread root) + Caller *stub = packer->FindOrCreate( (const char *)thread.root ); + Caller::foreach::Merger( stub ).addFrom( thread.root ); + Caller *stubroot = stub->FindOrCreate( thread.root->GetName() ); + stubroot->SetParent( NULL ); // for proper crawling + packedThreads.Push( stubroot ); +#endif + + if ( active ) { + Caller::thisThread.requireThreadLock = true; + thread.threadState->threadLock.Release(); + } + } + + // working on local data now, don't need the threads lock any more + threads.ReleaseGlobalLock(); + + // do the pre-computations on the gathered threads + Caller::ComputeChildTicks preprocessor( *accumulate ); + for ( u32 i = 0; i < packedThreads.Size(); i++ ) + preprocessor( packedThreads[i] ); + + dumper.ThreadsInfo( Caller::maxStats( Caller::Max::TotalCalls ), Caller::mTimerOverhead, Caller::mRdtscOverhead ); + + // print the gathered threads + u64 sumTicks = 0; + for ( u32 i = 0; i < packedThreads.Size(); i++ ) { + Caller *root = packedThreads[i]; + u64 threadTicks = root->GetTimer().ticks; + sumTicks += threadTicks; + Caller::mGlobalDuration = threadTicks; + dumper.PrintThread( root ); + } + + // print the totals, use the summed total of ticks to adjust percentages + Caller::mGlobalDuration = sumTicks; + dumper.PrintAccumulated( accumulate ); + dumper.Finish(); + + delete accumulate; + delete packer; + } + + void resetThreads() { + globalStart = Timer::getticks(); + +#if defined(__PROFILER_SMP__) + threads.AcquireGlobalLock(); + + Buffer<Root> &threadsref = *threads.list; + u32 cnt = threadsref.Size(), last = cnt - 1; + for ( u32 i = 0; i < cnt; i++ ) { + Root &thread = threadsref[i]; + if ( !thread.root->IsActive() ) { + // thread isn't active, remove it + delete thread.root; + Root removed = threadsref.Pop(); + if ( i != last ) + thread = removed; + last--; + cnt--; + i--; + } else { + thread.threadState->threadLock.Acquire(); + thread.root->SoftReset(); + thread.threadState->threadLock.Release(); + } + } + + threads.ReleaseGlobalLock(); +#else + if ( root ) + root->SoftReset(); +#endif + } + + void enterThread( const char *name ) { + Caller *tmp = new Caller( name ); + + threads.AcquireGlobalLock(); + threads.list->Push( Root( tmp, &Caller::thisThread ) ); + + Caller::AcquirePerThreadLock(); + Caller::thisThread.activeCaller = tmp; + tmp->Start(); + tmp->SetActive( true ); + root = tmp; + Caller::ReleasePerThreadLock(); + + threads.ReleaseGlobalLock(); + } + + void exitThread() { + threads.AcquireGlobalLock(); + + Caller::AcquirePerThreadLock(); + root->Stop(); + root->SetActive( false ); + Caller::thisThread.activeCaller = NULL; + Caller::ReleasePerThreadLock(); + + threads.ReleaseGlobalLock(); + } + + inline void fastcall enterCaller( const char *name ) { + Caller *parent = Caller::thisThread.activeCaller; + if ( !parent ) + return; + + Caller *active = parent->FindOrCreate( name ); + active->Start(); + Caller::thisThread.activeCaller = active; + } + + inline void exitCaller() { + Caller *active = Caller::thisThread.activeCaller; + if ( !active ) + return; + + active->Stop(); + Caller::thisThread.activeCaller = active->GetParent(); + } + + inline void pauseCaller() { + u64 curticks = Timer::getticks(); + Caller *iter = Caller::thisThread.activeCaller; + for ( ; iter; iter = iter->GetParent() ) + iter->GetTimer().Pause( curticks ); + } + + inline void unpauseCaller() { + u64 curticks = Timer::getticks(); + Caller *iter = Caller::thisThread.activeCaller; + for ( ; iter; iter = iter->GetParent() ) + iter->GetTimer().Unpause( curticks ); + } + + // enter the main thread automatically + struct MakeRoot { + MakeRoot() { + // get an idea of how long timer calls / rdtsc takes + const u32 reps = 1000; + Caller::mTimerOverhead = Caller::mRdtscOverhead = 1000000; + for ( u32 tries = 0; tries < 20; tries++ ) { + Timer t, t2; + t.Start(); + for ( u32 i = 0; i < reps; i++ ) { + t2.Start(); + t2.Stop(); + } + t.Stop(); + f64 avg = f64(t2.ticks)/f64(reps); + if ( avg < Caller::mRdtscOverhead ) + Caller::mRdtscOverhead = avg; + avg = f64(t.ticks)/f64(reps); + if ( avg < Caller::mTimerOverhead ) + Caller::mTimerOverhead = avg; + } + + enterThread( "/Main" ); + } + + ~MakeRoot() { + free( programName ); + free( commandLine ); + } + } makeRoot; + + void detect( int argc, const char *argv[] ) { detectByArgs( argc, argv ); } + void detect( const char *commandLine ) { detectWinMain( commandLine ); } + void dump() { dumpThreads( PrintfDumper() ); } +#ifdef ENABLE_HTML + void dumphtml() { dumpThreads( HTMLDumper() ); } +#else + void dumphtml() {}; +#endif + void fastcall enter( const char *name ) { enterCaller( name ); } + void fastcall exit() { exitCaller(); } + void fastcall pause() { pauseCaller(); } + void fastcall unpause() { unpauseCaller(); } + void threadenter( const char *name ) { enterThread( name ); } + void threadexit() { exitThread(); } + void reset() { resetThreads(); } +#else + void detect( int argc, const char *argv[] ) {} + void detect( const char *commandLine ) {} + void dump() {} + void dumphtml() {} + void fastcall enter( const char *name ) {} + void fastcall exit() {} + void fastcall pause() {} + void fastcall unpause() {} + void threadenter( const char *name ) {} + void threadexit() {} + void reset() {} +#endif + +}; // namespace Profiler diff --git a/rce/rcecalib/profiler/Profiler.hh b/rce/rcecalib/profiler/Profiler.hh new file mode 100644 index 00000000..26e463c6 --- /dev/null +++ b/rce/rcecalib/profiler/Profiler.hh @@ -0,0 +1,258 @@ +#ifndef __PROFILER_H__ +#define __PROFILER_H__ + +#include <iostream> + +//#define __PROFILER_ENABLED__ +#define __PROFILER_FULL_TYPE_EXPANSION__ + +#undef noinline +#undef fastcall + +#if ! defined(__rtems__) || ! defined(__PPC__) +#define __PROFILER_SMP__ +#endif +#if !defined(NO_FLOAT) && defined(__PPC__) +#define NO_FLOAT +#endif + + +#if defined(_MSC_VER) + #undef __PRETTY_FUNCTION__ + #define __PRETTY_FUNCTION__ __FUNCSIG__ + #define PROFILE_CONCAT( a, b ) a "/" b + + #define noinline __declspec(noinline) + #define fastcall __fastcall +#else + #define PROFILE_CONCAT( a, b ) b + + #define noinline __attribute__ ((noinline)) + #define fastcall +#endif + +#if defined(__PROFILER_FULL_TYPE_EXPANSION__) + #define PROFILE_FUNCTION() __PRETTY_FUNCTION__ +#else + #define PROFILE_FUNCTION() __FUNCTION__ +#endif + +#if defined(__PROFILER_ENABLED__) + // thread + #define PROFILE_THREAD_START_RAW( text ) Profiler::threadenter( text ) + #define PROFILE_THREAD_START() PROFILE_THREAD_START_RAW( PROFILE_FUNCTION() ) + #define PROFILE_THREAD_START_DESC( desc ) PROFILE_THREAD_START_RAW( PROFILE_CONCAT( PROFILE_FUNCTION(), desc ) ) + + #define PROFILE_THREAD_SCOPED_RAW( text ) Profiler::ScopedThread profiler##__LINE__ ( text ) + #define PROFILE_THREAD_SCOPED() PROFILE_THREAD_SCOPED_RAW( PROFILE_FUNCTION() ) + #define PROFILE_THREAD_SCOPED_DESC( desc ) PROFILE_THREAD_SCOPED_RAW( PROFILE_CONCAT( PROFILE_FUNCTION(), desc ) ) + + #define PROFILE_THREAD_STOP() Profiler::threadexit() + + // function + #define PROFILE_PAUSE() Profiler::pause() + #define PROFILE_UNPAUSE() Profiler::unpause() + #define PROFILE_PAUSE_SCOPED() Profiler::ScopedPause profilerpause##__LINE__ + + #define PROFILE_START_RAW( text ) Profiler::enter( text ); + #define PROFILE_START() PROFILE_START_RAW( PROFILE_FUNCTION() ) + #define PROFILE_START_DESC( desc ) PROFILE_START_RAW( PROFILE_CONCAT( PROFILE_FUNCTION(), desc ) ) + + #define PROFILE_SCOPED_RAW( text ) Profiler::Scoped profiler##__LINE__ ( text ) + #define PROFILE_SCOPED() PROFILE_SCOPED_RAW( PROFILE_FUNCTION() ) + #define PROFILE_SCOPED_DESC( desc ) PROFILE_SCOPED_RAW( PROFILE_CONCAT( PROFILE_FUNCTION(), desc ) ) + + #define PROFILE_STOP() Profiler::exit() + #define PROFILE_RESET() Profiler::reset() + #define PROFILE_DUMP() Profiler::dump() +#else + #define PROFILE_THREAD_START_RAW( text ) + #define PROFILE_THREAD_START() + #define PROFILE_THREAD_START_DESC( desc ) + + #define PROFILE_THREAD_SCOPED_RAW( text ) + #define PROFILE_THREAD_SCOPED() + #define PROFILE_THREAD_SCOPED_DESC( desc ) + + #define PROFILE_THREAD_STOP() + + #define PROFILE_PAUSE() + #define PROFILE_UNPAUSE() + #define PROFILE_PAUSE_SCOPED() + + #define PROFILE_START_RAW( text ) + #define PROFILE_START() + #define PROFILE_START_DESC( desc ) + + #define PROFILE_SCOPED_RAW( text ) + #define PROFILE_SCOPED() + #define PROFILE_SCOPED_DESC( desc ) + + #define PROFILE_STOP() + #define PROFILE_RESET() + #define PROFILE_DUMP() +#endif + +namespace Profiler { + /* + ============= + Types that won't conflict with the rest of the system + ============= + */ + + + typedef unsigned char u8; + typedef unsigned short u16; + typedef unsigned int u32; + #if defined(_MSC_VER) + typedef unsigned __int64 u64; + #else + typedef unsigned long long u64; + #endif +#ifdef NO_FLOAT + typedef u64 f64; + #define MCYCLE 1 + #define PRINTFF64(x) "%lld" +#else + typedef double f64; + #define MCYCLE 1000000.0 + #define PRINTFF64(x) "%" x "f" +#endif + + template< class type1, class type2 > + f64 average( type1 sum, type2 count ) { + return ( count ) ? f64(sum)/f64(count) : 0; + } + + /* + ============= + Timer + ============= + */ + #pragma pack(push,1) + struct Timer { + Timer() { Reset(); } + void Print(const char* title){ + std::cout<<"Timing for module "<<title<<std::endl; + std::cout<<"Timer recorded a total of "<<calls<<" calls and "<<ticks<<" ticks."<<" or "<<(float)ticks/350000<<" milliseconds"<<std::endl; + //std::cout<<"Timer recorded a total of "<<calls<<" calls and "<<ticks<<" ticks."<<std::endl; + std::cout<<"The average number of ticks was "<<avg()<<" or "<<(float)avg()/350000.<<" milliseconds."<<std::endl; + //std::cout<<"The average number of ticks was "<<avg()<<" or "<<(float)(unsigned)avg()/350000.<<" milliseconds."<<std::endl; + } + inline bool IsEmpty() const { return ticks == 0; } + inline bool IsPaused() const { return paused; } + inline void Unpause( u64 curticks ) { started = curticks; paused = false; } + inline void Unpause() { Unpause( getticks() ); } + inline void Pause( u64 curticks ) { ticks += ( curticks - started ); paused = true; } + inline void Pause() { Pause( getticks() ); } + inline void Start() { ++calls; started = getticks(); } + inline void Stop() { ticks += ( getticks() - started ); } + inline void Reset() { ticks = started = calls = 0; paused = false; } + inline void SoftStop() { if ( !paused ) { u64 t = getticks(); ticks += ( t - started ); started = t; } } + inline void SoftReset() { ticks = 0; calls = 1; started = getticks(); } + + template< class type > static f64 ms( const type &t ) { return f64( t ) / MCYCLE; } + f64 millicycles() { return ms( ticks ); } + f64 currentmillicycles() { return ms( ticks + ( getticks() - started ) ); } + f64 avg() { return average( ticks, calls ); } + f64 avgms() { return ms( average( ticks, calls ) ); } + + void operator+= ( const Timer &b ) { + ticks += b.ticks; + calls += b.calls; + } + + static inline u64 getticks_serial() { + #if defined(__i386__) || defined(__x86_64__) + #if defined(__GNUC__) + asm volatile("cpuid" : : : "%eax", "%ebx", "%ecx", "%edx" ); + #else + __asm cpuid; + #endif + return getticks(); + #endif + return getticks(); + } + #if defined(__i386__) || defined(__x86_64__) + #if defined(__GNUC__) + static inline u64 getticks() { + u32 __a,__d; + asm volatile("rdtsc" : "=a" (__a), "=d" (__d)); + return ( u64(__a) | u64(__d) << 32 ); + } + #elif defined(__ICC) || defined(__ICL) + static inline u64 getticks() { return _rdtsc(); } + #else + static inline u64 getticks() { __asm { rdtsc }; } + #endif + #elif defined(__PPC__) + static inline u64 getticks() { + union {struct { u32 upper,lower;}; u64 U64;} result; + u32 upper0,upper1; +// read time base registers + __asm__ volatile("\ + mfspr %[upper0], 269 \n \ + mfspr %[lower] , 268 \n \ + mfspr %[upper1], 269 " + : [lower] "=r" (result.lower), // result.lower is output. + [upper0] "=r" (upper0), // upper0 is output. + [upper1] "=r" (upper1) // upper1 is output. + ); + u32 mask = (int) result.lower >> 31; + result.upper = upper1 ^ ((upper0 ^ upper1) & mask); + return result.U64; + } + #else + #error Unsupported CPU Architecture + #endif + + u64 ticks, started; + u32 calls; + bool paused; + }; + #pragma pack(pop) + + + /* + ============= + Interface functions + ============= + */ + + void detect( int argc, const char *argv[] ); + void detect( const char *commandLine ); + void dump(); + void dumphtml(); + void fastcall enter( const char *name ); + void fastcall exit(); + void fastcall pause(); + void fastcall unpause(); + void threadenter( const char *name ); + void threadexit(); + void reset(); + + struct Scoped { + Scoped( const char *name ) { PROFILE_START_RAW( name ); } + ~Scoped() { PROFILE_STOP(); } + }; + + struct ScopedPause { + ScopedPause() { PROFILE_PAUSE(); } + ~ScopedPause() { PROFILE_UNPAUSE(); } + }; + + struct ScopedThread { + ScopedThread( const char *name ) { PROFILE_THREAD_START_RAW( name ); } + ~ScopedThread() { PROFILE_THREAD_STOP(); } + }; +}; // namespace Profiler + + +struct ScopedTimer { + ScopedTimer( Profiler::Timer &t ) : mTimer(t) { mTimer.Start(); } + ~ScopedTimer() { mTimer.Stop(); } +protected: + Profiler::Timer &mTimer; +}; + +#endif // __PROFILER_H__ diff --git a/rce/rcecalib/profiler/README b/rce/rcecalib/profiler/README new file mode 100644 index 00000000..172fe55b --- /dev/null +++ b/rce/rcecalib/profiler/README @@ -0,0 +1,64 @@ +---- +INFO +---- + +My site: http://www.team5150.com/~andrew/ +Project site: http://code.google.com/p/high-performance-cplusplus-profiler/ + + +------------ +WHAT IS THIS +------------ + +A high performance multi-threaded C++ profiler, currently for x86 (32bit) +under Windows and Linux. + + +---------- +QUICKSTART +---------- + +Add Profiler.cpp to your project, and #include "Profiler.h" to any file +you wish to profile. + +(OPTIONAL) +Call Profiler::detect( argc, argv ) under any OS or +Profiler::detect( commandLine ) under Win32 non-console apps to autodetect +program name and startup parameters (only used for html dumps). + +Use PROFILE_SCOPED() at the start of any function you wish to profile. + +Use PROFILE_THREAD_SCOPED() at the entry point of any thread you wish to +profile. The main thread is instantiated automatically. + +Use Profiler::reset(); to reset the profile stats at any time + +Use Profiler::dump(); to generate an ASCII report of the current profile + +Use Profiler::dumphtml(); to generate an HTML report of the current profile +to the current directory. + + +--------------- +Minimal Example +--------------- + +#include <stdlib.h> +#include "Profiler.h" + +int test() { + PROFILE_SCOPED() + + int i = 1; + while ( i < 1000 ) + i *= ( rand() & 7 ) + 1; + return i; +} + +int main( int argc, const char *argv[] ) { + Profiler::detect( argc, argv ); + for ( int i = 0; i < 100; i++ ) + test(); + Profiler::dump(); + return 0; +} diff --git a/rce/rcecalib/profiler/constituents.mk b/rce/rcecalib/profiler/constituents.mk new file mode 100644 index 00000000..b5b8b028 --- /dev/null +++ b/rce/rcecalib/profiler/constituents.mk @@ -0,0 +1,13 @@ + +CPPFLAGS+='-D__PROFILER_ENABLED__' + +ifneq ($(findstring ppc-rtems-rce,$(tgt_arch)),) +modlibnames := profiler +libsrcs_profiler := Profiler.cc +endif + +ifneq ($(findstring linux,$(tgt_os)),) +libnames := profiler +libsrcs_profiler := Profiler.cc +endif + diff --git a/rce/rcecalib/projects.mk.template b/rce/rcecalib/projects.mk.template new file mode 100644 index 00000000..110d0f70 --- /dev/null +++ b/rce/rcecalib/projects.mk.template @@ -0,0 +1,34 @@ +# List of projects (low level first) +projects := rtems \ + boost \ + omniorb \ + tdaq \ + root \ + rce \ + rceusr \ + rceapp \ + rceers \ + rceowl \ + rceipc \ + rceis \ + rceoh \ + rcecalib + + + +rtems_use := /reg/common/package/rtems/4.9.2 + +rce_use := release +rceusr_use := release +rceapp_use := release +rcehw_use := release +rceowl_use := release +rceers_use := release +rceipc_use := release +rceis_use := release +rceoh_use := release +rcecalib_use := release +root_use := /reg/g/atlas/root_5_22_00b +boost_use := /reg/g/atlas/boost_1_41_0 +omniorb_use := /reg/g/atlas/omniorb +tdaq_use := /reg/g/atlas/tdaq diff --git a/rce/rcecalib/scanctrl/AbsScan.hh b/rce/rcecalib/scanctrl/AbsScan.hh new file mode 100644 index 00000000..ce5b0830 --- /dev/null +++ b/rce/rcecalib/scanctrl/AbsScan.hh @@ -0,0 +1,29 @@ +#ifndef ABSSCAN_HH +#define ABSSCAN_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include <iostream> +#include "rcecalib/scanctrl/NestedLoop.hh" +#include "rcecalib/config/ConfigIF.hh" + +class AbsDataProcessor; + +class AbsScan{ + +public: + AbsScan(ConfigIF* cif): m_configIF(cif){}; + virtual ~AbsScan(){} + virtual int configureScan(boost::property_tree::ptree* scanOptions)=0; + virtual int pause()=0; + virtual int resume()=0; + virtual int abort()=0; + virtual int startScan()=0; + //virtual std::vector<Histo*> getHistos(const char* type, int module)=0; + +protected: + ConfigIF* m_configIF; + //AbsDataProcessor* m_dataprocessor; + NestedLoop m_loops; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/ActionFactory.cc b/rce/rcecalib/scanctrl/ActionFactory.cc new file mode 100644 index 00000000..94c77027 --- /dev/null +++ b/rce/rcecalib/scanctrl/ActionFactory.cc @@ -0,0 +1,90 @@ + +#include "rcecalib/scanctrl/ActionFactory.hh" + +#include "rcecalib/config/ConfigIF.hh" +#include "rcecalib/dataproc/AbsDataProc.hh" +#include "rcecalib/scanctrl/Scan.hh" + + +// Loop actions +#include "rcecalib/scanctrl/SetupMaskStageAction.hh" +#include "rcecalib/scanctrl/SetupParamAction.hh" +#include "rcecalib/scanctrl/ChangeBinAction.hh" +#include "rcecalib/scanctrl/SendTriggerAction.hh" +#include "rcecalib/scanctrl/EnableTriggerAction.hh" +#include "rcecalib/scanctrl/DisableTriggerAction.hh" +#include "rcecalib/scanctrl/DisableAllChannelsAction.hh" +#include "rcecalib/scanctrl/ConfigureModulesAction.hh" +#include "rcecalib/scanctrl/ConfigureModulesNEAction.hh" +#include "rcecalib/scanctrl/CosmicSetInputDelayAction.hh" +#include "rcecalib/scanctrl/CosmicEnableTDCAction.hh" +#include "rcecalib/scanctrl/SetupTriggerAction.hh" +#include "rcecalib/scanctrl/CosmicEnableScintillatorTriggerAction.hh" +#include "rcecalib/scanctrl/PauseAction.hh" +#include "rcecalib/scanctrl/IfWaitAction.hh" +#include "rcecalib/scanctrl/SetChannelMaskAction.hh" + +// End of loop actions +#include "rcecalib/scanctrl/FitEoLAction.hh" +#include "rcecalib/scanctrl/CloseFileEoLAction.hh" +#include "rcecalib/scanctrl/DisableTriggerEoLAction.hh" +#include "rcecalib/scanctrl/DisableAllChannelsEoLAction.hh" +#include "rcecalib/scanctrl/ResetFEEoLAction.hh" + +LoopAction* ActionFactory::createLoopAction(std::string action, boost::property_tree::ptree* pt){ + // create various loop actions based on action string + if(action=="SETUP_MASK") + return new SetupMaskStageAction(action,m_configIF,m_dataProc, pt); + else if (action=="SETUP_PARAM") + return new SetupParamAction(action,m_configIF, pt); + else if (action=="CHANGE_BIN") + return new ChangeBinAction(action,m_dataProc); + else if (action == "SEND_TRIGGER") + return new SendTriggerAction(action,m_configIF); + else if (action == "SETUP_CHANNELMASK") + return new SetChannelMaskAction(action,m_configIF); + else if (action == "DISABLE_ALL_CHANNELS") + return new DisableAllChannelsAction(action,m_configIF); + else if (action == "CONFIGURE_MODULES") + return new ConfigureModulesAction(action,m_configIF); + else if (action == "CONFIGURE_MODULES_NO_ENABLE") + return new ConfigureModulesNEAction(action,m_configIF); + else if (action == "ENABLE_TRIGGER") + return new EnableTriggerAction(action,m_configIF); + else if (action == "DISABLE_TRIGGER") + return new DisableTriggerAction(action,m_configIF); + else if (action == "PAUSE") + return new PauseAction(action,m_scan); + else if (action == "COSMIC_SET_INPUT_DELAY") + return new CosmicSetInputDelayAction(action,m_configIF,pt); + else if (action == "COSMIC_ENABLE_TDC") + return new CosmicEnableTDCAction(action,m_configIF); + else if (action == "COSMIC_ENABLE_SCINTILLATOR_TRIGGER") + return new CosmicEnableScintillatorTriggerAction(action,m_configIF); + else if (action == "SETUP_TRIGGER") + return new SetupTriggerAction(action,m_configIF, pt); + else if (action == "IF_WAIT") + return new IfWaitAction(action); + else{ + std::cerr<<"Unknown Action"<<std::endl; + return 0; + } +} + +EndOfLoopAction* ActionFactory::createEndOfLoopAction(std::string action, std::string fitfunc){ + if(action=="FIT") + return new FitEoLAction(action,m_dataProc,fitfunc); + if(action=="CALCULATE_MEAN_SIGMA") + return new FitEoLAction(action,m_dataProc,fitfunc); + if(action=="CLOSE_FILE") + return new CloseFileEoLAction(action,m_dataProc); + if(action=="DISABLE_TRIGGER") + return new DisableTriggerEoLAction(action,m_configIF); + if(action=="DISABLE_ALL_CHANNELS") + return new DisableAllChannelsEoLAction(action,m_configIF); + if(action=="RESET_FE") + return new ResetFEEoLAction(action,m_configIF); + else if(action=="NO_ACTION") + return 0; + else return 0; +} diff --git a/rce/rcecalib/scanctrl/ActionFactory.hh b/rce/rcecalib/scanctrl/ActionFactory.hh new file mode 100644 index 00000000..fe34b0dc --- /dev/null +++ b/rce/rcecalib/scanctrl/ActionFactory.hh @@ -0,0 +1,26 @@ +#ifndef ACTIONFACTORY_HH +#define ACTIONFACTORY_HH + +#include <string> +#include <boost/property_tree/ptree_fwd.hpp> + +#include "rcecalib/scanctrl/LoopAction.hh" +#include "rcecalib/scanctrl/EndOfLoopAction.hh" + +class Scan; +class ConfigIF; +class AbsDataProc; + +class ActionFactory{ +public: + ActionFactory(ConfigIF* cif, AbsDataProc* proc,Scan* scan): + m_configIF(cif),m_dataProc(proc),m_scan(scan){} + ~ActionFactory(){}; + LoopAction* createLoopAction(std::string action,boost::property_tree::ptree* pt=0); + EndOfLoopAction* createEndOfLoopAction(std::string action, std::string fitfunc); +private: + ConfigIF *m_configIF; + AbsDataProc *m_dataProc; + Scan* m_scan; +}; +#endif diff --git a/rce/rcecalib/scanctrl/ChangeBinAction.hh b/rce/rcecalib/scanctrl/ChangeBinAction.hh new file mode 100644 index 00000000..1b2f999b --- /dev/null +++ b/rce/rcecalib/scanctrl/ChangeBinAction.hh @@ -0,0 +1,19 @@ +#ifndef CHANGEBINACTION_HH +#define CHANGEBINACTION_HH + +#include "rcecalib/scanctrl/LoopAction.hh" +#include "rcecalib/dataproc/AbsDataProc.hh" + +class ChangeBinAction: public LoopAction{ +public: + ChangeBinAction(std::string name, AbsDataProc* proc): + LoopAction(name),m_dataProc(proc){} + int execute(int i){ + //std::cout<<"Changed bin"<<std::endl; + return m_dataProc->changeBin(i); + } +private: + AbsDataProc* m_dataProc; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/CloseFileEoLAction.hh b/rce/rcecalib/scanctrl/CloseFileEoLAction.hh new file mode 100644 index 00000000..6d80f0b9 --- /dev/null +++ b/rce/rcecalib/scanctrl/CloseFileEoLAction.hh @@ -0,0 +1,19 @@ +#ifndef CLOSEFILEEOLACTION_HH +#define CLOSEFILEEOLACTION_HH + +#include "rcecalib/scanctrl/EndOfLoopAction.hh" +#include "rcecalib/dataproc/AbsDataProc.hh" + +class CloseFileEoLAction: public EndOfLoopAction{ +public: + CloseFileEoLAction(std::string name, AbsDataProc* proc): + EndOfLoopAction(name),m_dataProc(proc){} + int execute(){ + std::cout<<"Closing file"<<std::endl; + return m_dataProc->fit("CloseFile"); + } +private: + AbsDataProc* m_dataProc; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/ConfigureModulesAction.hh b/rce/rcecalib/scanctrl/ConfigureModulesAction.hh new file mode 100644 index 00000000..62c019d7 --- /dev/null +++ b/rce/rcecalib/scanctrl/ConfigureModulesAction.hh @@ -0,0 +1,19 @@ +#ifndef CONFIGUREMODULESACTION_HH +#define CONFIGUREMODULESACTION_HH + +#include "rcecalib/scanctrl/LoopAction.hh" +#include "rcecalib/config/ConfigIF.hh" + +class ConfigureModulesAction: public LoopAction{ +public: + ConfigureModulesAction(std::string name, ConfigIF* cif): + LoopAction(name),m_configIF(cif){} + int execute(int i){ + m_configIF->configureModulesHW(); + return 0; + } +private: + ConfigIF* m_configIF; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/ConfigureModulesNEAction.hh b/rce/rcecalib/scanctrl/ConfigureModulesNEAction.hh new file mode 100644 index 00000000..8863ca4e --- /dev/null +++ b/rce/rcecalib/scanctrl/ConfigureModulesNEAction.hh @@ -0,0 +1,19 @@ +#ifndef CONFIGUREMODULESNEACTION_HH +#define CONFIGUREMODULESNEACTION_HH + +#include "rcecalib/scanctrl/LoopAction.hh" +#include "rcecalib/config/ConfigIF.hh" + +class ConfigureModulesNEAction: public LoopAction{ +public: + ConfigureModulesNEAction(std::string name, ConfigIF* cif): + LoopAction(name),m_configIF(cif){} + int execute(int i){ + m_configIF->configureModulesHW(false); + return 0; + } +private: + ConfigIF* m_configIF; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/CosmicDataSetup.cc b/rce/rcecalib/scanctrl/CosmicDataSetup.cc new file mode 100644 index 00000000..e1b2f98f --- /dev/null +++ b/rce/rcecalib/scanctrl/CosmicDataSetup.cc @@ -0,0 +1,45 @@ +#include "rcecalib/scanctrl/CosmicDataSetup.hh" +#include "rcecalib/scanctrl/ScanLoop.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/scanctrl/ActionFactory.hh" +#include "rcecalib/scanctrl/LoopAction.hh" +#include "rcecalib/scanctrl/EndOfLoopAction.hh" +#include "rcecalib/util/exceptions.hh" + +int CosmicDataSetup::setupLoops( NestedLoop& loop, boost::property_tree::ptree *scanOptions, ActionFactory* af){ + int retval=0; + loop.clear(); + try{ //catch bad scan option parameters + // Data Taking has a single loop with one entry + ScanLoop *scanloop=new ScanLoop("data",1); + LoopAction* conf=af->createLoopAction("CONFIGURE_MODULES"); + scanloop->addLoopAction(conf); + LoopAction* linkmask=af->createLoopAction("SETUP_TRIGGER", scanOptions); + scanloop->addLoopAction(linkmask); + LoopAction* enabletdc=0; + if(scanOptions->get<int>("trigOpt.triggerDataOn")){ + enabletdc=af->createLoopAction("COSMIC_ENABLE_TDC"); + scanloop->addLoopAction(enabletdc); + } + LoopAction* enable=af->createLoopAction("ENABLE_TRIGGER"); + scanloop->addLoopAction(enable); + // End of loop actions + EndOfLoopAction* disabletrigger=af->createEndOfLoopAction("DISABLE_TRIGGER",""); + scanloop->addEndOfLoopAction(disabletrigger); + EndOfLoopAction* closefile=af->createEndOfLoopAction("CLOSE_FILE",""); + scanloop->addEndOfLoopAction(closefile); + EndOfLoopAction* resetfe=af->createEndOfLoopAction("RESET_FE",""); + scanloop->addEndOfLoopAction(resetfe); + EndOfLoopAction* disablechannels=af->createEndOfLoopAction("DISABLE_ALL_CHANNELS",""); + scanloop->addEndOfLoopAction(disablechannels); + // loop is the nested loop object + loop.addNewInnermostLoop(scanloop); + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + retval=1; + } + // loop.print(); + return retval; +} diff --git a/rce/rcecalib/scanctrl/CosmicDataSetup.hh b/rce/rcecalib/scanctrl/CosmicDataSetup.hh new file mode 100644 index 00000000..d00bfd0a --- /dev/null +++ b/rce/rcecalib/scanctrl/CosmicDataSetup.hh @@ -0,0 +1,18 @@ +#ifndef COSMICDATASETUP_HH +#define COSMICDATASETUP_HH + +#include "rcecalib/scanctrl/NestedLoop.hh" +#include "rcecalib/scanctrl/LoopSetup.hh" +#include "rcecalib/scanctrl/ActionFactory.hh" +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/config/ConfigIF.hh" + +class CosmicDataSetup: public LoopSetup{ +public: + CosmicDataSetup():LoopSetup(){}; + virtual ~CosmicDataSetup(){} + int setupLoops(NestedLoop& loop, boost::property_tree::ptree *scanOptions, ActionFactory* af); +}; + + +#endif diff --git a/rce/rcecalib/scanctrl/CosmicEnableScintillatorTriggerAction.hh b/rce/rcecalib/scanctrl/CosmicEnableScintillatorTriggerAction.hh new file mode 100644 index 00000000..94ee756e --- /dev/null +++ b/rce/rcecalib/scanctrl/CosmicEnableScintillatorTriggerAction.hh @@ -0,0 +1,21 @@ +#ifndef COSMICENABLESCINTILLATORTRIGGER_HH +#define COSMICENABLESCINTILLATORTRIGGER_HH + +#include "rcecalib/scanctrl/LoopAction.hh" +#include "rcecalib/config/ConfigIF.hh" + +class CosmicEnableScintillatorTriggerAction: public LoopAction{ +public: + CosmicEnableScintillatorTriggerAction(std::string name, ConfigIF* cif): + LoopAction(name),m_configIF(cif){} + int execute(int i){ + unsigned serstat= m_configIF->writeHWregister(11,1); + assert(serstat==0); + // std::cout<<"Enabled scintillator trigger"<<std::endl; + return 0; + } +private: + ConfigIF* m_configIF; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/CosmicEnableTDCAction.hh b/rce/rcecalib/scanctrl/CosmicEnableTDCAction.hh new file mode 100644 index 00000000..766d2b00 --- /dev/null +++ b/rce/rcecalib/scanctrl/CosmicEnableTDCAction.hh @@ -0,0 +1,20 @@ +#ifndef COSMICENABLETDC_HH +#define COSMICENABLETDC_HH + +#include "rcecalib/scanctrl/LoopAction.hh" +#include "rcecalib/config/ConfigIF.hh" + +class CosmicEnableTDCAction: public LoopAction{ +public: + CosmicEnableTDCAction(std::string name, ConfigIF* cif): + LoopAction(name),m_configIF(cif){} + int execute(int i){ + unsigned serstat= m_configIF->writeHWregister(4,1); + assert(serstat==0); + return 0; + } +private: + ConfigIF* m_configIF; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/CosmicSetInputDelayAction.hh b/rce/rcecalib/scanctrl/CosmicSetInputDelayAction.hh new file mode 100644 index 00000000..1ba8b0ad --- /dev/null +++ b/rce/rcecalib/scanctrl/CosmicSetInputDelayAction.hh @@ -0,0 +1,51 @@ +#ifndef COSMICSETINPUTDELAYACTION_HH +#define COSMICSETINPUTDELAYACTION_HH + +#include <boost/property_tree/ptree.hpp> +#include <boost/foreach.hpp> +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/scanctrl/LoopAction.hh" +#include "rcecalib/config/ConfigIF.hh" +#include <string> +#include <vector> + +class CosmicSetInputDelayAction: public LoopAction{ +public: + CosmicSetInputDelayAction(std::string name, ConfigIF* cif, boost::property_tree::ptree *pt ): + LoopAction(name),m_configIF(cif){ + try{ + int nPoints=pt->get<int>("nPoints"); + BOOST_FOREACH(boost::property_tree::ptree::value_type &v, pt->get_child("dataPoints")){ + ERS_DEBUG(2, v.second.data()); + int data = boost::lexical_cast<int>(v.second.data()); + dataPoints.push_back(data); + } + ERS_ASSERT_MSG((int)dataPoints.size()==nPoints,"of an inconsistency in the number of scan points."); + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + } + } + + int execute(int i){ + ERS_DEBUG(2,"CosmicSetInputDelayAction "<<i); + //std::cout<<"Set input delay "<<i<<std::endl; + unsigned serstat; + serstat=m_configIF->writeHWregister(7,0);//reset delays + assert(serstat==0); + int reg=5; + if(dataPoints[i]<0)reg=6; + for (int j=0;j<abs(dataPoints[i]);j++) { + serstat=m_configIF->writeHWregister(reg,0); //increment delay + assert(serstat==0); + } + return 0; + } + +private: + ConfigIF* m_configIF; + std::vector<int> dataPoints; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/DelayScanSetup.cc b/rce/rcecalib/scanctrl/DelayScanSetup.cc new file mode 100644 index 00000000..91396868 --- /dev/null +++ b/rce/rcecalib/scanctrl/DelayScanSetup.cc @@ -0,0 +1,43 @@ +#include "rcecalib/scanctrl/DelayScanSetup.hh" +#include "rcecalib/scanctrl/ScanLoop.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/scanctrl/ActionFactory.hh" +#include "rcecalib/scanctrl/LoopAction.hh" +#include "rcecalib/scanctrl/EndOfLoopAction.hh" +#include "rcecalib/util/exceptions.hh" + +int DelayScanSetup::setupLoops( NestedLoop& loop, boost::property_tree::ptree *scanOptions, ActionFactory* af){ + int retval=0; + loop.clear(); + try{ //catch bad scan option parameters + // This calibration has a single loop + int nPoints = scanOptions->get<int>("scanLoop_0.nPoints"); + ScanLoop *scanloop=new ScanLoop("scanLoop_0",nPoints); + LoopAction* disable=af->createLoopAction("DISABLE_TRIGGER"); + scanloop->addLoopAction(disable); + LoopAction* setdelay=af->createLoopAction("COSMIC_SET_INPUT_DELAY",&scanOptions->get_child("scanLoop_0")); + scanloop->addLoopAction(setdelay); + LoopAction* changebin=af->createLoopAction("CHANGE_BIN"); + scanloop->addLoopAction(changebin); + LoopAction* enabletdc=af->createLoopAction("COSMIC_ENABLE_TDC"); + scanloop->addLoopAction(enabletdc); + LoopAction* enablesc=af->createLoopAction("COSMIC_ENABLE_SCINTILLATOR_TRIGGER"); + scanloop->addLoopAction(enablesc); + LoopAction* enable=af->createLoopAction("ENABLE_TRIGGER"); + scanloop->addLoopAction(enable); + // End of loop actions + EndOfLoopAction* disabletrigger=af->createEndOfLoopAction("DISABLE_TRIGGER",""); + scanloop->addEndOfLoopAction(disabletrigger); + EndOfLoopAction* disablechannels=af->createEndOfLoopAction("DISABLE_ALL_CHANNELS",""); + scanloop->addEndOfLoopAction(disablechannels); + // loop is the nested loop object + loop.addNewInnermostLoop(scanloop); + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + retval=1; + } + // loop.print(); + return retval; +} diff --git a/rce/rcecalib/scanctrl/DelayScanSetup.hh b/rce/rcecalib/scanctrl/DelayScanSetup.hh new file mode 100644 index 00000000..3a910a13 --- /dev/null +++ b/rce/rcecalib/scanctrl/DelayScanSetup.hh @@ -0,0 +1,18 @@ +#ifndef DELAYSCANSETUP_HH +#define DELAYSCANSETUP_HH + +#include "rcecalib/scanctrl/NestedLoop.hh" +#include "rcecalib/scanctrl/LoopSetup.hh" +#include "rcecalib/scanctrl/ActionFactory.hh" +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/config/ConfigIF.hh" + +class DelayScanSetup: public LoopSetup{ +public: + DelayScanSetup():LoopSetup(){}; + virtual ~DelayScanSetup(){} + int setupLoops(NestedLoop& loop, boost::property_tree::ptree *scanOptions, ActionFactory* af); +}; + + +#endif diff --git a/rce/rcecalib/scanctrl/DisableAllChannelsAction.hh b/rce/rcecalib/scanctrl/DisableAllChannelsAction.hh new file mode 100644 index 00000000..a9ef1681 --- /dev/null +++ b/rce/rcecalib/scanctrl/DisableAllChannelsAction.hh @@ -0,0 +1,19 @@ +#ifndef DISABLEALLCHANNELSACTION_HH +#define DISABLEALLCHANNELSACTION_HH + +#include "rcecalib/scanctrl/LoopAction.hh" +#include "rcecalib/config/ConfigIF.hh" + +class DisableAllChannelsAction: public LoopAction{ +public: + DisableAllChannelsAction(std::string name, ConfigIF* cif): + LoopAction(name),m_configIF(cif){} + int execute(int i){ + m_configIF->disableAllChannels(); + return 0; + } +private: + ConfigIF* m_configIF; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/DisableAllChannelsEoLAction.hh b/rce/rcecalib/scanctrl/DisableAllChannelsEoLAction.hh new file mode 100644 index 00000000..b27cd186 --- /dev/null +++ b/rce/rcecalib/scanctrl/DisableAllChannelsEoLAction.hh @@ -0,0 +1,19 @@ +#ifndef DISABLEALLCHANNELSEOLACTION_HH +#define DISABLEALLCHANNELSEOLACTION_HH + +#include "rcecalib/scanctrl/EndOfLoopAction.hh" +#include "rcecalib/config/ConfigIF.hh" + +class DisableAllChannelsEoLAction: public EndOfLoopAction{ +public: + DisableAllChannelsEoLAction(std::string name, ConfigIF* cif) : + EndOfLoopAction(name),m_configIF(cif){} + int execute(){ + m_configIF->disableAllChannels(); + return 0; + } +private: + ConfigIF* m_configIF; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/DisableTriggerAction.hh b/rce/rcecalib/scanctrl/DisableTriggerAction.hh new file mode 100644 index 00000000..ccdcb5f7 --- /dev/null +++ b/rce/rcecalib/scanctrl/DisableTriggerAction.hh @@ -0,0 +1,19 @@ +#ifndef DISABLETRIGGERACTION_HH +#define DISABLETRIGGERACTION_HH + +#include "rcecalib/scanctrl/LoopAction.hh" +#include "rcecalib/config/ConfigIF.hh" + +class DisableTriggerAction: public LoopAction{ +public: + DisableTriggerAction(std::string name, ConfigIF* cif): + LoopAction(name),m_configIF(cif){} + int execute(int i){ + //std::cout<<"Disabled trigger"<<std::endl; + return m_configIF->disableTrigger(); + } +private: + ConfigIF* m_configIF; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/DisableTriggerEoLAction.hh b/rce/rcecalib/scanctrl/DisableTriggerEoLAction.hh new file mode 100644 index 00000000..aee14eae --- /dev/null +++ b/rce/rcecalib/scanctrl/DisableTriggerEoLAction.hh @@ -0,0 +1,20 @@ +#ifndef DISABLETRIGGEREOLACTION_HH +#define DISABLETRIGGEREOLACTION_HH + +#include "rcecalib/scanctrl/EndOfLoopAction.hh" +#include "rcecalib/config/ConfigIF.hh" + +class DisableTriggerEoLAction: public EndOfLoopAction{ +public: + DisableTriggerEoLAction(std::string name, ConfigIF* cif) : + EndOfLoopAction(name),m_configIF(cif){} + int execute(){ + std::cout<<"Disabling trigger"<<std::endl; + m_configIF->disableTrigger(); + return 0; + } +private: + ConfigIF* m_configIF; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/EnableTriggerAction.hh b/rce/rcecalib/scanctrl/EnableTriggerAction.hh new file mode 100644 index 00000000..9be093ff --- /dev/null +++ b/rce/rcecalib/scanctrl/EnableTriggerAction.hh @@ -0,0 +1,20 @@ +#ifndef ENABLETRIGGERACTION_HH +#define ENABLETRIGGERACTION_HH + +#include "rcecalib/scanctrl/LoopAction.hh" +#include "rcecalib/config/ConfigIF.hh" + +class EnableTriggerAction: public LoopAction{ +public: + EnableTriggerAction(std::string name, ConfigIF* cif): + LoopAction(name),m_configIF(cif){} + int execute(int i){ + m_configIF->sendHWcommand(17); // tell HSIO trigger logic that this RCE is in control. + m_configIF->enableTrigger(); + return 0; + } +private: + ConfigIF* m_configIF; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/EndOfLoopAction.hh b/rce/rcecalib/scanctrl/EndOfLoopAction.hh new file mode 100644 index 00000000..92d80eb7 --- /dev/null +++ b/rce/rcecalib/scanctrl/EndOfLoopAction.hh @@ -0,0 +1,17 @@ +#ifndef ENDOFLOOPACTION_HH +#define ENDOFLOOPACTION_HH + +#include <string> + +class EndOfLoopAction{ +public: + EndOfLoopAction(std::string name): + m_name(name){} + virtual ~EndOfLoopAction(){} + std::string name(){return m_name;} + virtual int execute() = 0; +protected: + std::string m_name; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/FitEoLAction.hh b/rce/rcecalib/scanctrl/FitEoLAction.hh new file mode 100644 index 00000000..8946b962 --- /dev/null +++ b/rce/rcecalib/scanctrl/FitEoLAction.hh @@ -0,0 +1,27 @@ +#ifndef SCANFITACTION_HH +#define SCANFITACTION_HH + +#include "rcecalib/scanctrl/EndOfLoopAction.hh" +#include "rcecalib/dataproc/AbsDataProc.hh" +#include "rcecalib/scanctrl/RceCallback.hh" + +class FitEoLAction: public EndOfLoopAction{ +public: + FitEoLAction(std::string name, AbsDataProc* proc, std::string fitfunc): + EndOfLoopAction(name),m_dataProc(proc),m_fitfunc(fitfunc){} + int execute(){ + ipc::CallbackParams cbp; + cbp.rce=RceName::getRceNumber(); + cbp.status=ipc::FITTING; + cbp.maskStage=-1; + cbp.loop0=-1; + cbp.loop1=-1; + RceCallback::instance()->sendMsg(ipc::HIGH,&cbp); + return m_dataProc->fit(m_fitfunc); + } +private: + AbsDataProc* m_dataProc; + std::string m_fitfunc; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/IPCScan.cc b/rce/rcecalib/scanctrl/IPCScan.cc new file mode 100644 index 00000000..a506e4d6 --- /dev/null +++ b/rce/rcecalib/scanctrl/IPCScan.cc @@ -0,0 +1,99 @@ +#ifndef IPCSCAN_CC +#define IPCSCAN_CC + +#include "rcecalib/scanctrl/IPCScan.hh" +#include "ers/ers.h" +#include "ipc/partition.h" +#include <boost/property_tree/ptree.hpp> + +#include <string> +#include <iostream> +#include "rcecalib/profiler/Profiler.hh" + +template <class TP> +void* IPCScan<TP>::startScanStatic(void* arg){ + ((IPCScan<TP>*)arg)->startScan(); + return 0; +} + +template <class TP> +IPCScan<TP>::IPCScan(IPCPartition & p, const char * name): + IPCNamedObject<POA_ipc::IPCScanAdapter, TP>( p, name ) , + Scan() { + + try { + IPCNamedObject<POA_ipc::IPCScanAdapter,TP>::publish(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } +} + + + +template <class TP> +IPCScan<TP>::~IPCScan(){ + try { + IPCNamedObject<POA_ipc::IPCScanAdapter,TP>::withdraw(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::warning( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } +} + +template <class TP> +void IPCScan<TP>::IPCpause(){ + std::cout<<"Pause"<<std::endl; + pause(); +} +template <class TP> +void IPCScan<TP>::IPCresume(){ + std::cout<<"Resume"<<std::endl; + resume(); +} +template <class TP> +void IPCScan<TP>::IPCabort(){ + std::cout<<"Abort"<<std::endl; + abort(); +} +template <class TP> +void IPCScan<TP>::IPCstartScan(){ + pthread_t mthread; + pthread_attr_t attr; + int ret; + // setting a new size + int stacksize = (PTHREAD_STACK_MIN + 0x20000); + pthread_attr_init(&attr); + ret=pthread_attr_setstacksize(&attr, stacksize); + pthread_create( &mthread, &attr , startScanStatic, this); + pthread_detach(mthread); + //startScan(); +} +template <class TP> +void IPCScan<TP>::IPCwaitForData(){ + waitForData(); +} +template <class TP> +void IPCScan<TP>::IPCstopWaiting(){ + stopWaiting(); +} +template <class TP> +CORBA::Long IPCScan<TP>::IPCgetStatus(){ + return getStatus(); +} + +template <class TP> +void IPCScan<TP>::shutdown(){ + std::cout<<"Shutdown"<<std::endl; +} + +#endif diff --git a/rce/rcecalib/scanctrl/IPCScan.hh b/rce/rcecalib/scanctrl/IPCScan.hh new file mode 100644 index 00000000..060fc210 --- /dev/null +++ b/rce/rcecalib/scanctrl/IPCScan.hh @@ -0,0 +1,29 @@ +#ifndef IPCSCAN_HH +#define IPCSCAN_HH + +#include "rcecalib/scanctrl/Scan.hh" +#include "ipc/object.h" +#include "ScanOptions.hh" +#include "IPCScanAdapter.hh" + +class IPCPartition; + +template <class TP = ipc::single_thread> +class IPCScan: public IPCNamedObject<POA_ipc::IPCScanAdapter,TP>, public Scan { +public: + IPCScan(IPCPartition & p, const char * name); + ~IPCScan(); + void IPCpause(); + void IPCresume(); + void IPCwaitForData(); + void IPCstopWaiting(); + void IPCabort(); + void IPCstartScan(); + CORBA::Long IPCgetStatus(); + void shutdown(); + static void *startScanStatic(void *arg); + +}; + + +#endif diff --git a/rce/rcecalib/scanctrl/IPCScanRoot.cc b/rce/rcecalib/scanctrl/IPCScanRoot.cc new file mode 100644 index 00000000..6694922d --- /dev/null +++ b/rce/rcecalib/scanctrl/IPCScanRoot.cc @@ -0,0 +1,184 @@ +#ifndef IPCSCANROOT_CC +#define IPCSCANROOT_CC + +#include "rcecalib/scanctrl/IPCScanRoot.hh" +#include "ers/ers.h" +#include "ipc/partition.h" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/dataproc/AbsDataProc.hh" +#include "rcecalib/dataproc/AbsReceiver.hh" +#include "rcecalib/config/ConfigIF.hh" +#include "rcecalib/scanctrl/Scan.hh" +#include "rcecalib/util/IPCHistoManager.hh" +#include "rcecalib/scanctrl/RceCallback.hh" + +#include <string> +#include <iostream> + + +template <class TP> +IPCScanRoot<TP>::IPCScanRoot(IPCPartition & p, const char * name, ConfigIF* cif, Scan* scan): + IPCNamedObject<POA_ipc::IPCScanRootAdapter, TP>( p, name ) , ScanRoot(cif,scan){ + try { + IPCNamedObject<POA_ipc::IPCScanRootAdapter,TP>::publish(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } +} + +template <class TP> +IPCScanRoot<TP>::~IPCScanRoot(){ + try { + IPCNamedObject<POA_ipc::IPCScanRootAdapter,TP>::withdraw(); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::warning( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } +} + +template <class TP> +CORBA::Long IPCScanRoot<TP>::IPCconfigureScan(const ipc::ScanOptions &options){ + //PixScan::dump(options); + //std::cout<<"Start IPCScanRoot "<<std::endl; + //convert struct into property tree + boost::property_tree::ptree *pt=new boost::property_tree::ptree; + //Top level + pt->put("Name",options.name); // scan name. Can be used as a file name, for example. + pt->put("scanType",options.scanType); // scan type. Determines what loop setup to use + pt->put("Receiver",options.receiver); + pt->put("DataHandler",options.dataHandler); + pt->put("DataProc",options.dataProc); + pt->put("Timeout.Seconds",options.timeout.seconds); + pt->put("Timeout.Nanoseconds",options.timeout.nanoseconds); + pt->put("Timeout.AllowedTimeouts",options.timeout.allowedTimeouts); + pt->put("runNumber", options.runNumber); + pt->put("stagingMode",options.stagingMode); + //maskStages is not used in NewDsp, only nMaskStages + pt->put("maskStages", options.maskStages); + pt->put("nMaskStages",options.nMaskStages); + pt->put("firstStage",options.firstStage); + pt->put("stepStage",options.stepStage); + pt->put("nLoops",options.nLoops); + //Loops + for(int i=0;i<options.nLoops;i++){ + char loopname[128]; + sprintf (loopname,"scanLoop_%d.",i); + pt->put(std::string(loopname)+"scanParameter", options.scanLoop[i].scanParameter); + pt->put(std::string(loopname)+"nPoints",options.scanLoop[i].nPoints); + pt->put(std::string(loopname)+"endofLoopAction.Action", options.scanLoop[i].endofLoopAction.Action); + pt->put(std::string(loopname)+"endofLoopAction.fitFunction", options.scanLoop[i].endofLoopAction.fitFunction); + pt->put(std::string(loopname)+"endofLoopAction.targetThreshold", options.scanLoop[i].endofLoopAction.targetThreshold); + if(options.scanLoop[i].dataPoints.length()>0){ + char pointname[10]; + for(unsigned int j=0;j<options.scanLoop[i].dataPoints.length();j++){ + sprintf(pointname,"P_%d",j); + pt->put(std::string(loopname)+"dataPoints."+pointname,options.scanLoop[i].dataPoints[j]); + } + } + } + //Trigger options + pt->put("trigOpt.nEvents",options.trigOpt.nEvents); + pt->put("trigOpt.triggerMask",options.trigOpt.triggerMask); + pt->put("trigOpt.moduleTrgMask",options.trigOpt.moduleTrgMask); + pt->put("trigOpt.triggerDataOn",options.trigOpt.triggerDataOn); + pt->put("trigOpt.deadtime",options.trigOpt.deadtime); + pt->put("trigOpt.nL1AperEvent",options.trigOpt.nL1AperEvent); + pt->put("trigOpt.nTriggersPerGroup",options.trigOpt.nTriggersPerGroup); + pt->put("trigOpt.nTriggers",options.trigOpt.nTriggers); + pt->put("trigOpt.Lvl1_Latency",options.trigOpt.Lvl1_Latency); + pt->put("trigOpt.Lvl1_Latency_Secondary",options.trigOpt.Lvl1_Latency_Secondary); + pt->put("trigOpt.strobeDuration",options.trigOpt.strobeDuration); + pt->put("trigOpt.strobeMCCDelay",options.trigOpt.strobeMCCDelay); + pt->put("trigOpt.strobeMCCDelayRange",options.trigOpt.strobeMCCDelayRange); + pt->put("trigOpt.CalL1ADelay",options.trigOpt.CalL1ADelay); + pt->put("trigOpt.eventInterval",options.trigOpt.eventInterval); + pt->put("trigOpt.injectForTrigger",options.trigOpt.injectForTrigger); + pt->put("trigOpt.vcal_charge",options.trigOpt.vcal_charge); + pt->put("trigOpt.threshold",options.trigOpt.threshold); + pt->put("trigOpt.hitbusConfig",options.trigOpt.hitbusConfig); + + // each option gets an entry in the tree below optionsMask with value 1 + for (unsigned int i=0;i<options.trigOpt.optionsMask.length();i++){ + pt->put(std::string("trigOpt.optionsMask.")+(const char*)options.trigOpt.optionsMask[i],1); + } + pt->put("trigOpt.triggerMode", options.trigOpt.triggerMode); + + // front-end options + pt->put("feOpt.phi",options.feOpt.phi); + pt->put("feOpt.totThresholdMode",options.feOpt.totThresholdMode); + pt->put("feOpt.totMinimum",options.feOpt.totMinimum); + pt->put("feOpt.totTwalk",options.feOpt.totTwalk); + pt->put("feOpt.totLeMode",options.feOpt.totLeMode); + pt->put("feOpt.hitbus",options.feOpt.hitbus); + + pt->put("nHistoNames",options.histos.length()); + if(options.histos.length()>0){ + char pointname[10]; + for(unsigned int j=0;j<options.histos.length();j++){ + sprintf(pointname,"Name_%d",j); + pt->put(std::string("HistoNames.")+pointname,options.histos[j]); + } + } + //Trigger options + //call the real initScan function + //std::cout<<"Calling ScanRoot "<<std::endl; + configureScan(pt); + delete pt; + return 0; +} + +template <class TP> +ipc::StringVect* IPCScanRoot<TP>::IPCgetHistoNames(const char* reg){ + std::vector<std::string> strvec=IPCHistoManager::instance()->getHistoNames(reg); + ipc::StringVect &ipcstringvect=*new ipc::StringVect; + ipcstringvect.length(strvec.size()); + for(size_t i=0;i<strvec.size();i++){ + ipcstringvect[i]=CORBA::string_dup(strvec[i].c_str()); + } + return &ipcstringvect; +} +template <class TP> +ipc::StringVect* IPCScanRoot<TP>::IPCgetPublishedHistoNames(){ + std::vector<std::string> strvec=IPCHistoManager::instance()->getPublishedHistoNames(); + ipc::StringVect &ipcstringvect=*new ipc::StringVect; + ipcstringvect.length(strvec.size()); + for(size_t i=0;i<strvec.size();i++){ + ipcstringvect[i]=CORBA::string_dup(strvec[i].c_str()); + } + return &ipcstringvect; +} + +template <class TP> +CORBA::ULong IPCScanRoot<TP>::IPCnEvents(){ + if(m_dataProc) + return m_dataProc->nEvents(); + else + return 0; +} +template <class TP> +void IPCScanRoot<TP>::IPCresynch(){ + if(m_receiver) + m_receiver->resynch(); +} + +template <class TP> +void IPCScanRoot<TP>::IPCconfigureCallback(ipc::Callback_ptr cb, ipc::Priority pr){ + RceCallback::instance()->configure(cb,pr); +} + +template <class TP> +void IPCScanRoot<TP>::shutdown(){ + std::cout<<"Shutdown"<<std::endl; +} + +#endif diff --git a/rce/rcecalib/scanctrl/IPCScanRoot.hh b/rce/rcecalib/scanctrl/IPCScanRoot.hh new file mode 100644 index 00000000..4606e88b --- /dev/null +++ b/rce/rcecalib/scanctrl/IPCScanRoot.hh @@ -0,0 +1,29 @@ +#ifndef IPCSCANROOT_HH +#define IPCSCANROOT_HH + +#include "rcecalib/scanctrl/ScanRoot.hh" +#include "ipc/object.h" +#include "ScanOptions.hh" +#include "IPCScanRootAdapter.hh" + +class IPCPartition; +class ConfigIF; +class Scan; + +template <class TP = ipc::single_thread> +class IPCScanRoot: public IPCNamedObject<POA_ipc::IPCScanRootAdapter,TP>, public ScanRoot { +public: + IPCScanRoot(IPCPartition & p, const char * name, ConfigIF* cif, Scan* scan); + ~IPCScanRoot(); + CORBA::Long IPCconfigureScan(const ipc::ScanOptions &options); + ipc::StringVect* IPCgetHistoNames(const char* reg); + ipc::StringVect* IPCgetPublishedHistoNames(); + CORBA::ULong IPCnEvents(); + void IPCresynch(); + void IPCconfigureCallback(ipc::Callback_ptr cb, ipc::Priority pr); + void shutdown(); + +}; + + +#endif diff --git a/rce/rcecalib/scanctrl/IfScanSetup.cc b/rce/rcecalib/scanctrl/IfScanSetup.cc new file mode 100644 index 00000000..709449e2 --- /dev/null +++ b/rce/rcecalib/scanctrl/IfScanSetup.cc @@ -0,0 +1,63 @@ +#include "rcecalib/scanctrl/IfScanSetup.hh" +#include "rcecalib/scanctrl/ScanLoop.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/scanctrl/ActionFactory.hh" +#include "rcecalib/scanctrl/LoopAction.hh" +#include "rcecalib/scanctrl/EndOfLoopAction.hh" +#include "rcecalib/util/exceptions.hh" + +#include <stdio.h> + +int IfScanSetup::setupLoops( NestedLoop& loop, boost::property_tree::ptree *scanOptions, ActionFactory* af){ + int retval=0; + loop.clear(); + try{ //catch bad scan option parameters + // Start with the trigger loop + int nEvents = scanOptions->get<int>("trigOpt.nEvents"); + ScanLoop* triggerloop=new ScanLoop("Triggerloop",nEvents); + // LoopAction* pause=af->createLoopAction("PAUSE"); + LoopAction* sendtrigger=af->createLoopAction("SEND_TRIGGER",scanOptions); + //triggerloop->addLoopAction(pause); + triggerloop->addLoopAction(sendtrigger); + // loop is the nested loop object + loop.addNewInnermostLoop(triggerloop); + + // The position of the mask stage loop is not + // explicitely specified by PixLib. Implicitely it's the innermost loop + // if there is no other scan variable (nLoops==0) and next-to-innermost otherwise. + int nLoops = scanOptions->get<int>("nLoops"); + assert(nLoops==1); + // now it's time for the mask stage loop + int nMaskStages= scanOptions->get<int>("nMaskStages"); + ScanLoop* maskStageLoop = new ScanLoop("MaskStageLoop",nMaskStages); + LoopAction* maskaction=af->createLoopAction("SETUP_MASK", scanOptions); + maskStageLoop->addLoopAction(maskaction); + loop.addNewOutermostLoop(maskStageLoop); + //parameter loop is next + int nPoints = scanOptions->get<int>("scanLoop_0.nPoints"); + ScanLoop *firstparloop=new ScanLoop("scanLoop_0",nPoints); + LoopAction* wait=af->createLoopAction("IF_WAIT"); + LoopAction* setuppar0=af->createLoopAction("SETUP_PARAM",&scanOptions->get_child("scanLoop_0")); + LoopAction* chgbin0=af->createLoopAction("CHANGE_BIN"); + firstparloop->addLoopAction(wait); + firstparloop->addLoopAction(setuppar0); + firstparloop->addLoopAction(chgbin0); + loop.addNewOutermostLoop(firstparloop); + std::string action=scanOptions->get<std::string>("scanLoop_0.endofLoopAction.Action"); + std::string fitfunc=scanOptions->get<std::string>("scanLoop_0.endofLoopAction.fitFunction"); + EndOfLoopAction* fitaction=af->createEndOfLoopAction(action,fitfunc); + /* protect against no loop action returned */ + if(fitaction)maskStageLoop->addEndOfLoopAction(fitaction); + ScanLoop *configloop=new ScanLoop("Configure modules",1); + LoopAction* configaction=af->createLoopAction("CONFIGURE_MODULES_NO_ENABLE"); + configloop->addLoopAction(configaction); + loop.addNewOutermostLoop(configloop); + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + retval=1; + } + // loop.print(); + return retval; +} diff --git a/rce/rcecalib/scanctrl/IfScanSetup.hh b/rce/rcecalib/scanctrl/IfScanSetup.hh new file mode 100644 index 00000000..e819150b --- /dev/null +++ b/rce/rcecalib/scanctrl/IfScanSetup.hh @@ -0,0 +1,18 @@ +#ifndef IFSCANSETUP_HH +#define IFSCANSETUP_HH + +#include "rcecalib/scanctrl/NestedLoop.hh" +#include "rcecalib/scanctrl/LoopSetup.hh" +#include "rcecalib/scanctrl/ActionFactory.hh" +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/config/ConfigIF.hh" + +class IfScanSetup: public LoopSetup{ +public: + IfScanSetup():LoopSetup(){}; + virtual ~IfScanSetup(){} + int setupLoops(NestedLoop& loop, boost::property_tree::ptree *scanOptions, ActionFactory* af); +}; + + +#endif diff --git a/rce/rcecalib/scanctrl/IfWaitAction.hh b/rce/rcecalib/scanctrl/IfWaitAction.hh new file mode 100644 index 00000000..5c3d5e51 --- /dev/null +++ b/rce/rcecalib/scanctrl/IfWaitAction.hh @@ -0,0 +1,22 @@ +#ifndef IFWAITACTION_HH +#define IFWAITACTION_HH + +#include "rcecalib/scanctrl/LoopAction.hh" +#include "rcecalib/scanctrl/Scan.hh" + +class IfWaitAction: public LoopAction{ +public: + IfWaitAction(std::string name): + LoopAction(name){} + enum del{DELAY=100000}; + int execute(int i){ + //std::cout<<"Pausing scan"<<std::endl; + usleep(DELAY); + return 0; + //std::cout<<"Done pausing scan"<<std::endl; + } +private: + Scan* m_scan; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/LoopAction.hh b/rce/rcecalib/scanctrl/LoopAction.hh new file mode 100644 index 00000000..c84e088c --- /dev/null +++ b/rce/rcecalib/scanctrl/LoopAction.hh @@ -0,0 +1,19 @@ +#ifndef LOOPACTION_HH +#define LOOPACTION_HH + +#include <string> + + +class LoopAction{ +public: + LoopAction(std::string name): + m_name(name){} + std::string name(){return m_name;} + virtual ~LoopAction(){} + virtual int execute(int i) = 0; + +protected: + std::string m_name; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/LoopFactory.cc b/rce/rcecalib/scanctrl/LoopFactory.cc new file mode 100644 index 00000000..b01ac2eb --- /dev/null +++ b/rce/rcecalib/scanctrl/LoopFactory.cc @@ -0,0 +1,38 @@ +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/scanctrl/LoopFactory.hh" +#include "rcecalib/scanctrl/RegularScanSetup.hh" +#include "rcecalib/scanctrl/RegularCfgScanSetup.hh" +#include "rcecalib/scanctrl/IfScanSetup.hh" +#include "rcecalib/scanctrl/SelftriggerSetup.hh" +#include "rcecalib/scanctrl/DelayScanSetup.hh" +#include "rcecalib/scanctrl/CosmicDataSetup.hh" +#include "rcecalib/scanctrl/NoiseScanSetup.hh" +#include <stdio.h> /* for sprintf */ + +LoopFactory::LoopFactory(){} + + +LoopSetup* LoopFactory::createLoopSetup(const char* type){ + + if(std::string(type)=="Regular") + return new RegularScanSetup; + else if(std::string(type)=="RegularCfg") + return new RegularCfgScanSetup; + else if(std::string(type)=="IfScan") + return new IfScanSetup; + else if(std::string(type)=="Delay") + return new DelayScanSetup; + else if(std::string(type)=="CosmicData") + return new CosmicDataSetup; + else if(std::string(type)=="Selftrigger") + return new SelftriggerSetup; + else if(std::string(type)=="Noisescan") + return new NoiseScanSetup; + else { + char message[128]; + sprintf(message, "Scan loop setup for %s is not defined.", type); + ERS_ASSERT_MSG(0, message); + } + return 0; +} + diff --git a/rce/rcecalib/scanctrl/LoopFactory.hh b/rce/rcecalib/scanctrl/LoopFactory.hh new file mode 100644 index 00000000..d96fd0f8 --- /dev/null +++ b/rce/rcecalib/scanctrl/LoopFactory.hh @@ -0,0 +1,16 @@ +#ifndef LOOPFACTORY_HH +#define LOOPFACTORY_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/scanctrl/LoopSetup.hh" +class NestedLoop; + + +class LoopFactory{ +public: + LoopFactory(); + LoopSetup* createLoopSetup(const char* type); +}; + + +#endif diff --git a/rce/rcecalib/scanctrl/LoopSetup.hh b/rce/rcecalib/scanctrl/LoopSetup.hh new file mode 100644 index 00000000..4c352bb3 --- /dev/null +++ b/rce/rcecalib/scanctrl/LoopSetup.hh @@ -0,0 +1,17 @@ +#ifndef LOOPSETUP_HH +#define LOOPSETUP_HH + +#include "rcecalib/scanctrl/NestedLoop.hh" +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/config/ConfigIF.hh" +#include "rcecalib/scanctrl/ActionFactory.hh" + +class LoopSetup{ +public: + LoopSetup(){}; + virtual ~LoopSetup(){}; + virtual int setupLoops(NestedLoop& loop, boost::property_tree::ptree *scanOptions, ActionFactory* af)=0; +}; + + +#endif diff --git a/rce/rcecalib/scanctrl/Makefile b/rce/rcecalib/scanctrl/Makefile new file mode 100644 index 00000000..c73fd5ec --- /dev/null +++ b/rce/rcecalib/scanctrl/Makefile @@ -0,0 +1,20 @@ +# Package level makefile +# ---------------------- +%.mk:; + +# Checks +# ------ +# Check release location variables +ifeq ($(RELEASE_DIR),) +export RELEASE_DIR := $(PWD)/../.. +endif + +include $(RELEASE_DIR)/make/share/setup.mk +include ../flags.mk + +ifndef PREMAKE_DONE +include $(RELEASE_DIR)/make/share/premake.mk +else +include constituents.mk +include $(RELEASE_DIR)/make/sw/package.mk +endif diff --git a/rce/rcecalib/scanctrl/NestedLoop.cc b/rce/rcecalib/scanctrl/NestedLoop.cc new file mode 100644 index 00000000..24b16074 --- /dev/null +++ b/rce/rcecalib/scanctrl/NestedLoop.cc @@ -0,0 +1,81 @@ + +#include "ScanLoop.hh" +#include "NestedLoop.hh" +#include <iostream> +#include <sstream> + +void NestedLoop::addNewInnermostLoop(ScanLoop* loop){ + ScanLoop *oldinnermost; + if(m_looplist.empty()){ + oldinnermost=0; + }else{ + oldinnermost=m_looplist.front(); + } + m_looplist.push_front(loop); + loop->setNextOuterLoop(oldinnermost); +} +void NestedLoop::addNewOutermostLoop(ScanLoop* loop){ + ScanLoop *oldoutermost; + if(!m_looplist.empty()){ + oldoutermost=m_looplist.back(); + oldoutermost->setNextOuterLoop(loop); + } + m_looplist.push_back(loop); +} + +void NestedLoop::next(){ // all for loops are chained together and call each other. + // the first event is special because all loop actions have to be performed for setup + if(!m_looplist.empty()){ + if(m_init==false){ + firstEvent(); + m_init=true; + }else{ + m_done=m_looplist.front()->next(); //done comes from the outermost loop + } + } +} + +void NestedLoop::firstEvent(){ + std::list<ScanLoop*>::reverse_iterator listit; + // has to go from the outside to the inside + for(listit = m_looplist.rbegin(); listit != m_looplist.rend(); listit++){ + (*listit)->firstEvent(); + } +} + +void NestedLoop::clear(){ + std::list<ScanLoop*>::iterator listit; + for(listit = m_looplist.begin(); listit != m_looplist.end(); listit++){ + delete *listit; + } + m_looplist.clear(); + m_init=false; + m_done=false; +} +void NestedLoop::reset(){ + m_init=false; + m_done=false; + std::list<ScanLoop*>::iterator listit; + for(listit = m_looplist.begin(); listit != m_looplist.end(); listit++){ + (*listit)->reset(); + } +} + +NestedLoop::~NestedLoop(){ + std::list<ScanLoop*>::iterator listit; + for(listit = m_looplist.begin(); listit != m_looplist.end(); listit++){ + delete *listit; + } +} + +void NestedLoop::print(){ + std::cout<<std::endl; + std::list<ScanLoop*>::iterator listit; + std::stringstream spaces(" "); + for(listit = m_looplist.begin(); listit != m_looplist.end(); listit++){ + ScanLoop* loop=(*listit); + loop->print(spaces.str().c_str()); + spaces<<" "; + std::cout<<std::endl; + } +} diff --git a/rce/rcecalib/scanctrl/NestedLoop.hh b/rce/rcecalib/scanctrl/NestedLoop.hh new file mode 100644 index 00000000..4b263fbf --- /dev/null +++ b/rce/rcecalib/scanctrl/NestedLoop.hh @@ -0,0 +1,32 @@ +#ifndef NESTED_LOOP_HH +#define NESTED_LOOP_HH + +// Implements a nested for loop. +// Works together with ScanLoop.hh + +// C 2009 SLAC Author: Martin Kocian + +#include <list> + +class ScanLoop; + +class NestedLoop{ + +public: + NestedLoop():m_done(false),m_init(false){} + ~NestedLoop(); + bool done(){return m_done;} + void clear(); + void reset(); + void addNewInnermostLoop(ScanLoop*); + void addNewOutermostLoop(ScanLoop*); + void firstEvent(); + void next(); + void print(); +private: + std::list<ScanLoop*> m_looplist; + bool m_done; + bool m_init; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/NoiseScanSetup.cc b/rce/rcecalib/scanctrl/NoiseScanSetup.cc new file mode 100644 index 00000000..224811b9 --- /dev/null +++ b/rce/rcecalib/scanctrl/NoiseScanSetup.cc @@ -0,0 +1,42 @@ +#include "rcecalib/scanctrl/NoiseScanSetup.hh" +#include "rcecalib/scanctrl/ScanLoop.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/scanctrl/ActionFactory.hh" +#include "rcecalib/scanctrl/LoopAction.hh" +#include "rcecalib/scanctrl/EndOfLoopAction.hh" +#include "rcecalib/util/exceptions.hh" + +int NoiseScanSetup::setupLoops( NestedLoop& loop, boost::property_tree::ptree *scanOptions, ActionFactory* af){ + int retval=0; + loop.clear(); + try{ //catch bad scan option parameters + // Data Taking has a single loop with one entry + ScanLoop *scanloop=new ScanLoop("scan",1); + LoopAction* conf=af->createLoopAction("CONFIGURE_MODULES"); + scanloop->addLoopAction(conf); + // LoopAction* linkmask=af->createLoopAction("SETUP_CHANNELMASK"); + //scanloop->addLoopAction(linkmask); + LoopAction* setupcyclic=af->createLoopAction("SETUP_TRIGGER", scanOptions); + scanloop->addLoopAction(setupcyclic); + LoopAction* enable=af->createLoopAction("ENABLE_TRIGGER"); + scanloop->addLoopAction(enable); + // End of loop actions + EndOfLoopAction* disabletrigger=af->createEndOfLoopAction("DISABLE_TRIGGER",""); + scanloop->addEndOfLoopAction(disabletrigger); + EndOfLoopAction* closefile=af->createEndOfLoopAction("CLOSE_FILE",""); + scanloop->addEndOfLoopAction(closefile); + EndOfLoopAction* resetfe=af->createEndOfLoopAction("RESET_FE",""); + scanloop->addEndOfLoopAction(resetfe); + EndOfLoopAction* disablechannels=af->createEndOfLoopAction("DISABLE_ALL_CHANNELS",""); + scanloop->addEndOfLoopAction(disablechannels); + // loop is the nested loop object + loop.addNewInnermostLoop(scanloop); + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + retval=1; + } + // loop.print(); + return retval; +} diff --git a/rce/rcecalib/scanctrl/NoiseScanSetup.hh b/rce/rcecalib/scanctrl/NoiseScanSetup.hh new file mode 100644 index 00000000..d0fd9140 --- /dev/null +++ b/rce/rcecalib/scanctrl/NoiseScanSetup.hh @@ -0,0 +1,18 @@ +#ifndef NOISESCANSETUP_HH +#define NOISESCANSETUP_HH + +#include "rcecalib/scanctrl/NestedLoop.hh" +#include "rcecalib/scanctrl/LoopSetup.hh" +#include "rcecalib/scanctrl/ActionFactory.hh" +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/config/ConfigIF.hh" + +class NoiseScanSetup: public LoopSetup{ +public: + NoiseScanSetup():LoopSetup(){}; + virtual ~NoiseScanSetup(){} + int setupLoops(NestedLoop& loop, boost::property_tree::ptree *scanOptions, ActionFactory* af); +}; + + +#endif diff --git a/rce/rcecalib/scanctrl/PauseAction.hh b/rce/rcecalib/scanctrl/PauseAction.hh new file mode 100644 index 00000000..26dcd3b3 --- /dev/null +++ b/rce/rcecalib/scanctrl/PauseAction.hh @@ -0,0 +1,20 @@ +#ifndef PAUSEACTION_HH +#define PAUSEACTION_HH + +#include "rcecalib/scanctrl/LoopAction.hh" +#include "rcecalib/scanctrl/Scan.hh" + +class PauseAction: public LoopAction{ +public: + PauseAction(std::string name, Scan* scan): + LoopAction(name),m_scan(scan){} + int execute(int i){ + //std::cout<<"Pausing scan"<<std::endl; + return m_scan->pause(); + //std::cout<<"Done pausing scan"<<std::endl; + } +private: + Scan* m_scan; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/RceCallback.cc b/rce/rcecalib/scanctrl/RceCallback.cc new file mode 100644 index 00000000..fd803de6 --- /dev/null +++ b/rce/rcecalib/scanctrl/RceCallback.cc @@ -0,0 +1,47 @@ +#include "rcecalib/scanctrl/RceCallback.hh" +#include <iostream> + +RceCallback* RceCallback::m_instance=0; +omni_mutex RceCallback::m_guard; + +RceCallback* RceCallback::instance(){ + if( ! m_instance){ + omni_mutex_lock ml(m_guard); + if( ! m_instance){ + m_instance=new RceCallback; + } + } + return m_instance; +} + +RceCallback::RceCallback(): m_configured(false){} + +void RceCallback::configure(ipc::Callback_ptr cb, ipc::Priority pr){ + m_cb = ipc::Callback::_duplicate( cb ); + m_pr=pr; + m_configured=true; +} + +void RceCallback::sendMsg(ipc::Priority pr, const ipc::CallbackParams *msg){ + if(m_configured==true){ + if(pr>=m_pr){ + try { + m_cb->notify( *msg ); + } + catch(...) { + std::cout << "callback : notification fails" << std::endl; + } + } + } +} +void RceCallback::shutdown(){ + if(m_configured==true){ + try { + m_cb->stopServer(); + } + catch(...) { + std::cout << "callback : notification fails" << std::endl; + } + m_configured=false; + } +} diff --git a/rce/rcecalib/scanctrl/RceCallback.hh b/rce/rcecalib/scanctrl/RceCallback.hh new file mode 100644 index 00000000..a79ab8c8 --- /dev/null +++ b/rce/rcecalib/scanctrl/RceCallback.hh @@ -0,0 +1,24 @@ +#ifndef RCEMSG_HH +#define RCEMSG_HH + +#include "Callback.hh" +#include <omnithread.h> + +class RceCallback{ +public: + enum Priority {LOW, MEDIUM, HIGH}; + static RceCallback* instance(); + void sendMsg(ipc::Priority pr, const ipc::CallbackParams *msg); + void shutdown(); + void configure( ipc::Callback_ptr cb, ipc::Priority pr); +private: + RceCallback(); + ipc::Callback_var m_cb; + ipc::Priority m_pr; + bool m_configured; + static omni_mutex m_guard; + static RceCallback* m_instance; + +}; + +#endif diff --git a/rce/rcecalib/scanctrl/RegularCfgScanSetup.cc b/rce/rcecalib/scanctrl/RegularCfgScanSetup.cc new file mode 100644 index 00000000..2db88060 --- /dev/null +++ b/rce/rcecalib/scanctrl/RegularCfgScanSetup.cc @@ -0,0 +1,110 @@ +#include "rcecalib/scanctrl/RegularCfgScanSetup.hh" +#include "rcecalib/scanctrl/ScanLoop.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/scanctrl/ActionFactory.hh" +#include "rcecalib/scanctrl/LoopAction.hh" +#include "rcecalib/scanctrl/EndOfLoopAction.hh" +#include "rcecalib/util/exceptions.hh" + +#include <stdio.h> + +int RegularCfgScanSetup::setupLoops( NestedLoop& loop, boost::property_tree::ptree *scanOptions, ActionFactory* af){ + int retval=0; + loop.clear(); + try{ //catch bad scan option parameters + // Start with the trigger loop + int nEvents = scanOptions->get<int>("trigOpt.nEvents"); + ScanLoop* triggerloop=new ScanLoop("Triggerloop",nEvents); + // LoopAction* pause=af->createLoopAction("PAUSE"); + LoopAction* sendtrigger=af->createLoopAction("SEND_TRIGGER",scanOptions); + //triggerloop->addLoopAction(pause); + triggerloop->addLoopAction(sendtrigger); + // loop is the nested loop object + loop.addNewInnermostLoop(triggerloop); + + // The position of the mask stage loop is not + // explicitely specified by PixLib. Implicitely it's the innermost loop + // if there is no other scan variable (nLoops==0) and next-to-innermost otherwise. + int nLoops = scanOptions->get<int>("nLoops"); + if(nLoops>0){ + //parameter loop is next + int nPoints = scanOptions->get<int>("scanLoop_0.nPoints"); + ScanLoop *firstparloop=new ScanLoop("scanLoop_0",nPoints); + //LoopAction* disable0=af->createLoopAction("DISABLE_TRIGGER"); + LoopAction* setuppar0=af->createLoopAction("SETUP_PARAM",&scanOptions->get_child("scanLoop_0")); + LoopAction* chgbin0=af->createLoopAction("CHANGE_BIN"); + //LoopAction* linkmask0=af->createLoopAction("SETUP_CHANNELMASK"); + // LoopAction* enable0=af->createLoopAction("ENABLE_TRIGGER"); + // End of loop action is deferred to mask stage + // firstparloop->addLoopAction(disable0); + firstparloop->addLoopAction(setuppar0); + firstparloop->addLoopAction(chgbin0); + //firstparloop->addLoopAction(linkmask0); + // firstparloop->addLoopAction(enable0); + loop.addNewOutermostLoop(firstparloop); + } + // now it's time for the mask stage loop + int nMaskStages= scanOptions->get<int>("nMaskStages"); + ScanLoop* maskStageLoop = new ScanLoop("MaskStageLoop",nMaskStages); + //LoopAction* disablem=af->createLoopAction("DISABLE_TRIGGER"); + LoopAction* maskaction=af->createLoopAction("SETUP_MASK", scanOptions); + //LoopAction* linkmaskm=af->createLoopAction("SETUP_CHANNELMASK"); + //LoopAction* enablem=af->createLoopAction("ENABLE_TRIGGER"); + //maskStageLoop->addLoopAction(disablem); + maskStageLoop->addLoopAction(maskaction); + //maskStageLoop->addLoopAction(linkmaskm); + //maskStageLoop->addLoopAction(enablem); + // The end of loop action from the parameter loop above if there is one + /* add calculation of ToT/BCID mean and sigma to end-of-loop sction */ + if(scanOptions->get<std::string>("DataProc")=="BCID" || scanOptions->get<std::string>("DataProc")=="TOT") { + std::cout << "Add BCID calculation as end-of-loop action" << std::endl; + EndOfLoopAction* action=af->createEndOfLoopAction("CALCULATE_MEAN_SIGMA","CALCULATE_MEAN_SIGMA"); + if(action) maskStageLoop->addEndOfLoopAction(action); + } + + + if(nLoops>0){ + std::string action=scanOptions->get<std::string>("scanLoop_0.endofLoopAction.Action"); + std::string fitfunc=scanOptions->get<std::string>("scanLoop_0.endofLoopAction.fitFunction"); + EndOfLoopAction* fitaction=af->createEndOfLoopAction(action,fitfunc); + /* protect against no loop action returned */ + if(fitaction)maskStageLoop->addEndOfLoopAction(fitaction); + } + loop.addNewOutermostLoop(maskStageLoop); + // now add any additional loops + char desc[128]; + for (int i=1;i<nLoops;i++){ + sprintf(desc,"scanLoop_%d",i); + int nPoints = scanOptions->get<int>(std::string(desc)+".nPoints"); + ScanLoop *parloop=new ScanLoop(desc,nPoints); + // LoopAction* disable=af->createLoopAction("DISABLE_TRIGGER"); + LoopAction* setuppar=af->createLoopAction("SETUP_PARAM",&scanOptions->get_child(desc)); + LoopAction* chgbin=af->createLoopAction("CHANGE_BIN"); + //LoopAction* enable=af->createLoopAction("ENABLE_TRIGGER"); + //LoopAction* linkmask=af->createLoopAction("SETUP_CHANNELMASK"); + // End of loop action is deferred to mask stage + // parloop->addLoopAction(disable); + parloop->addLoopAction(setuppar); + parloop->addLoopAction(chgbin); + //maskStageLoop->addLoopAction(linkmask); + // parloop->addLoopAction(enable); + std::string action=scanOptions->get<std::string>(std::string(desc)+".endofLoopAction.Action"); + std::string fitfunc=scanOptions->get<std::string>(std::string(desc)+".endofLoopAction.fitFunction"); + EndOfLoopAction* fitaction=af->createEndOfLoopAction(action,fitfunc); + if(fitaction) + parloop->addEndOfLoopAction(fitaction); + loop.addNewOutermostLoop(parloop); + } + ScanLoop *configloop=new ScanLoop("Configure modules",1); + LoopAction* configaction=af->createLoopAction("CONFIGURE_MODULES_NO_ENABLE"); + configloop->addLoopAction(configaction); + loop.addNewOutermostLoop(configloop); + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + retval=1; + } + // loop.print(); + return retval; +} diff --git a/rce/rcecalib/scanctrl/RegularCfgScanSetup.hh b/rce/rcecalib/scanctrl/RegularCfgScanSetup.hh new file mode 100644 index 00000000..6be05ef1 --- /dev/null +++ b/rce/rcecalib/scanctrl/RegularCfgScanSetup.hh @@ -0,0 +1,18 @@ +#ifndef REGULARCFGSCANSETUP_HH +#define REGULARCFGSCANSETUP_HH + +#include "rcecalib/scanctrl/NestedLoop.hh" +#include "rcecalib/scanctrl/LoopSetup.hh" +#include "rcecalib/scanctrl/ActionFactory.hh" +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/config/ConfigIF.hh" + +class RegularCfgScanSetup: public LoopSetup{ +public: + RegularCfgScanSetup():LoopSetup(){}; + virtual ~RegularCfgScanSetup(){} + int setupLoops(NestedLoop& loop, boost::property_tree::ptree *scanOptions, ActionFactory* af); +}; + + +#endif diff --git a/rce/rcecalib/scanctrl/RegularScanSetup.cc b/rce/rcecalib/scanctrl/RegularScanSetup.cc new file mode 100644 index 00000000..3c5d97e2 --- /dev/null +++ b/rce/rcecalib/scanctrl/RegularScanSetup.cc @@ -0,0 +1,106 @@ +#include "rcecalib/scanctrl/RegularScanSetup.hh" +#include "rcecalib/scanctrl/ScanLoop.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/scanctrl/ActionFactory.hh" +#include "rcecalib/scanctrl/LoopAction.hh" +#include "rcecalib/scanctrl/EndOfLoopAction.hh" +#include "rcecalib/util/exceptions.hh" + +#include <stdio.h> + +int RegularScanSetup::setupLoops( NestedLoop& loop, boost::property_tree::ptree *scanOptions, ActionFactory* af){ + int retval=0; + loop.clear(); + try{ //catch bad scan option parameters + // Start with the trigger loop + int nEvents = scanOptions->get<int>("trigOpt.nEvents"); + ScanLoop* triggerloop=new ScanLoop("Triggerloop",nEvents); + // LoopAction* pause=af->createLoopAction("PAUSE"); + LoopAction* sendtrigger=af->createLoopAction("SEND_TRIGGER",scanOptions); + //triggerloop->addLoopAction(pause); + triggerloop->addLoopAction(sendtrigger); + // loop is the nested loop object + loop.addNewInnermostLoop(triggerloop); + + // The position of the mask stage loop is not + // explicitely specified by PixLib. Implicitely it's the innermost loop + // if there is no other scan variable (nLoops==0) and next-to-innermost otherwise. + int nLoops = scanOptions->get<int>("nLoops"); + if(nLoops>0){ + //parameter loop is next + int nPoints = scanOptions->get<int>("scanLoop_0.nPoints"); + ScanLoop *firstparloop=new ScanLoop("scanLoop_0",nPoints); + //LoopAction* disable0=af->createLoopAction("DISABLE_TRIGGER"); + LoopAction* setuppar0=af->createLoopAction("SETUP_PARAM",&scanOptions->get_child("scanLoop_0")); + LoopAction* chgbin0=af->createLoopAction("CHANGE_BIN"); + //LoopAction* linkmask0=af->createLoopAction("SETUP_CHANNELMASK"); + // LoopAction* enable0=af->createLoopAction("ENABLE_TRIGGER"); + // End of loop action is deferred to mask stage + // firstparloop->addLoopAction(disable0); + firstparloop->addLoopAction(setuppar0); + firstparloop->addLoopAction(chgbin0); + //firstparloop->addLoopAction(linkmask0); + // firstparloop->addLoopAction(enable0); + loop.addNewOutermostLoop(firstparloop); + } + // now it's time for the mask stage loop + int nMaskStages= scanOptions->get<int>("nMaskStages"); + ScanLoop* maskStageLoop = new ScanLoop("MaskStageLoop",nMaskStages); + //LoopAction* disablem=af->createLoopAction("DISABLE_TRIGGER"); + LoopAction* maskaction=af->createLoopAction("SETUP_MASK", scanOptions); + //LoopAction* linkmaskm=af->createLoopAction("SETUP_CHANNELMASK"); + //LoopAction* enablem=af->createLoopAction("ENABLE_TRIGGER"); + //maskStageLoop->addLoopAction(disablem); + maskStageLoop->addLoopAction(maskaction); + //maskStageLoop->addLoopAction(linkmaskm); + //maskStageLoop->addLoopAction(enablem); + // The end of loop action from the parameter loop above if there is one + /* add calculation of ToT/BCID mean and sigma to end-of-loop sction */ + if(scanOptions->get<std::string>("DataProc")=="BCID" || scanOptions->get<std::string>("DataProc")=="TOT") { + std::cout << "Add Mean/Sgima calculation as end-of-loop action" << std::endl; + EndOfLoopAction* action=af->createEndOfLoopAction("CALCULATE_MEAN_SIGMA","CALCULATE_MEAN_SIGMA"); + if(action) maskStageLoop->addEndOfLoopAction(action); + } + + + if(nLoops>0){ + std::string action=scanOptions->get<std::string>("scanLoop_0.endofLoopAction.Action"); + std::string fitfunc=scanOptions->get<std::string>("scanLoop_0.endofLoopAction.fitFunction"); + EndOfLoopAction* fitaction=af->createEndOfLoopAction(action,fitfunc); + /* protect against no loop action returned */ + if(fitaction)maskStageLoop->addEndOfLoopAction(fitaction); + } + loop.addNewOutermostLoop(maskStageLoop); + // now add any additional loops + char desc[128]; + for (int i=1;i<nLoops;i++){ + sprintf(desc,"scanLoop_%d",i); + int nPoints = scanOptions->get<int>(std::string(desc)+".nPoints"); + ScanLoop *parloop=new ScanLoop(desc,nPoints); + // LoopAction* disable=af->createLoopAction("DISABLE_TRIGGER"); + LoopAction* setuppar=af->createLoopAction("SETUP_PARAM",&scanOptions->get_child(desc)); + LoopAction* chgbin=af->createLoopAction("CHANGE_BIN"); + //LoopAction* enable=af->createLoopAction("ENABLE_TRIGGER"); + //LoopAction* linkmask=af->createLoopAction("SETUP_CHANNELMASK"); + // End of loop action is deferred to mask stage + // parloop->addLoopAction(disable); + parloop->addLoopAction(setuppar); + parloop->addLoopAction(chgbin); + //maskStageLoop->addLoopAction(linkmask); + // parloop->addLoopAction(enable); + std::string action=scanOptions->get<std::string>(std::string(desc)+".endofLoopAction.Action"); + std::string fitfunc=scanOptions->get<std::string>(std::string(desc)+".endofLoopAction.fitFunction"); + EndOfLoopAction* fitaction=af->createEndOfLoopAction(action,fitfunc); + if(fitaction) + parloop->addEndOfLoopAction(fitaction); + loop.addNewOutermostLoop(parloop); + } + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + retval=1; + } + // loop.print(); + return retval; +} diff --git a/rce/rcecalib/scanctrl/RegularScanSetup.hh b/rce/rcecalib/scanctrl/RegularScanSetup.hh new file mode 100644 index 00000000..d6077b06 --- /dev/null +++ b/rce/rcecalib/scanctrl/RegularScanSetup.hh @@ -0,0 +1,18 @@ +#ifndef REGULARSCANSETUP_HH +#define REGULARSCANSETUP_HH + +#include "rcecalib/scanctrl/NestedLoop.hh" +#include "rcecalib/scanctrl/LoopSetup.hh" +#include "rcecalib/scanctrl/ActionFactory.hh" +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/config/ConfigIF.hh" + +class RegularScanSetup: public LoopSetup{ +public: + RegularScanSetup():LoopSetup(){}; + virtual ~RegularScanSetup(){} + int setupLoops(NestedLoop& loop, boost::property_tree::ptree *scanOptions, ActionFactory* af); +}; + + +#endif diff --git a/rce/rcecalib/scanctrl/ResetFEEoLAction.hh b/rce/rcecalib/scanctrl/ResetFEEoLAction.hh new file mode 100644 index 00000000..1fa76f42 --- /dev/null +++ b/rce/rcecalib/scanctrl/ResetFEEoLAction.hh @@ -0,0 +1,19 @@ +#ifndef RESETFEEOLACTION_HH +#define RESETFEEOLACTION_HH + +#include "rcecalib/scanctrl/EndOfLoopAction.hh" +#include "rcecalib/config/ConfigIF.hh" + +class ResetFEEoLAction: public EndOfLoopAction{ +public: + ResetFEEoLAction(std::string name, ConfigIF* cif) : + EndOfLoopAction(name),m_configIF(cif){} + int execute(){ + m_configIF->resetFE(); + return 0; + } +private: + ConfigIF* m_configIF; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/Scan.cc b/rce/rcecalib/scanctrl/Scan.cc new file mode 100644 index 00000000..1684c1f1 --- /dev/null +++ b/rce/rcecalib/scanctrl/Scan.cc @@ -0,0 +1,242 @@ + +#include "rcecalib/scanctrl/Scan.hh" +#include "rcecalib/scanctrl/ActionFactory.hh" +#include "rcecalib/dataproc/AbsDataHandler.hh" +#include "rcecalib/scanctrl/LoopFactory.hh" +#include "rcecalib/scanctrl/RceCallback.hh" +#include "rcecalib/util/RceName.hh" +#include <pthread.h> +#include <stdio.h> /* for printf */ + +#include <boost/property_tree/ptree.hpp> +#include <boost/foreach.hpp> + +#include "rcecalib/util/exceptions.hh" + +#include "rcecalib/util/IPCHistoManager.hh" + +#include <string> +#include <iostream> +#include "rcecalib/profiler/Profiler.hh" +#include "rcecalib/HW/SerialIF.hh" + +#ifdef __rtems__ +extern "C"{ + #include <rtems/malloc.h> +} +#endif + +Scan::Scan(): + m_state(IDLE), m_pause_cond (&m_pause_mutex), + m_i(0), m_handler(0),m_timeout_seconds(0),m_timeout_nanoseconds(0), m_failed(false), m_timeouts(0){} + +Scan::~Scan(){ +} + +int Scan::configureScan(boost::property_tree::ptree *scanOptions, ActionFactory &af, AbsDataHandler* par){ + m_handler=par; + if(m_state!=IDLE && m_state!=CONFIGURED){ + std::cout<<"Warning: Scan was not in idle state. Trying to clean up..."<<std::endl; + // perhaps there is an old scan hanging in the main loop + abort(); + sleep(2); + if(m_state!=IDLE){ + std::cout<<"Could not recover situation. Starting anyway."<<std::endl; + m_state=IDLE; + }else{ + std::cout<<"Cleanup successful. Starting the run now"<<std::endl; + } + } + // in case we got stuck in the waiting state somehow in a previous run + stopWaiting(); + m_handler->timeoutOccurred(); + int retval=0; + try{ + // set up loops + //setup contains the code to build the concrete nested loop + LoopFactory lf; + std::string type = scanOptions->get<std::string>("scanType"); + std::cout<<"Scan Type "<<type<<std::endl; + LoopSetup* setup=lf.createLoopSetup(type.c_str()); + //m_loops gets configured + setup->setupLoops(m_loops,scanOptions, &af); + m_timeout_seconds=scanOptions->get<unsigned>("Timeout.Seconds"); + m_timeout_nanoseconds=scanOptions->get<unsigned>("Timeout.Nanoseconds"); + m_allowedTimeouts=scanOptions->get<int>("Timeout.AllowedTimeouts"); + m_state=CONFIGURED; + // get rid of the setup object + // m_loops.print(); + delete setup; + // histograms + int nHistoNames=scanOptions->get<int>("nHistoNames"); + m_histolist.clear(); + if(nHistoNames>0){ + BOOST_FOREACH(boost::property_tree::ptree::value_type &v, scanOptions->get_child("HistoNames")){ + ERS_DEBUG(2, v.second.data()); + std::string data = boost::lexical_cast<std::string>(v.second.data()); + std::cout<<"Histogram "<<data<<std::endl; + m_histolist.push_back(data); + } + } + + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + retval=1; + } + return retval; +} + +int Scan::waitForData(){ + if(m_dataCond.waitingForData!=false)return 1;// only makes sense if running + m_dataCond.mutex.lock(); + m_dataCond.waitingForData=true; + return 0; +} + +int Scan::stopWaiting(){ + if(m_dataCond.waitingForData!=true)return 1;// cannot go on unless waiting + omni_mutex_lock pl( m_dataCond.mutex ); + m_dataCond.waitingForData=false; + m_dataCond.cond.signal(); + return 0; +} + +int Scan::pause(){ + if(m_state!=RUNNING)return 1;// only pause if running + omni_mutex_lock pl( m_pause_mutex ); + m_state=PAUSED; + return 0; +} +int Scan::resume(){ + if(m_state!=PAUSED)return 1;// cannot resume unless paused + omni_mutex_lock pl( m_pause_mutex ); + m_state=RUNNING; + m_pause_cond.signal(); + return 0; +} + +int Scan::abort(){ + // abort must wake up the main thread when it is paused + omni_mutex_lock pl( m_pause_mutex ); + m_state=ABORT; + m_pause_cond.signal(); + stopWaiting(); + return 0; +} + +int Scan::startScan(){ + std::cout<<"Starting Scan"<<std::endl; + if(m_state!=IDLE && m_state!=CONFIGURED){ + std::cout<<"Bad state "<<m_state<<std::endl; + return 1; + } + int timeoutcount=0; + while(m_state!=CONFIGURED){ + if(timeoutcount>=CONFIG_TIMEOUT){ + std::cout<<"Configure timed out"<<std::endl; + return 1; //configure timed out + } + timeoutcount++; + usleep(10000); + } + std::cout<<"Running"<<std::endl; + m_state=RUNNING; + // m_loops.print(); + m_loops.reset(); + struct sched_param param; + int policy; + pthread_getschedparam(pthread_self(), &policy, ¶m); + param.sched_priority=254; + pthread_setschedparam(pthread_self(), policy, ¶m); +#ifdef __rtems__ + rtems_malloc_statistics_t stats; + malloc_get_statistics(&stats); + printf("*** malloc statistics\n"); + printf("space available: %uk\n",(unsigned int)stats.space_available/1024); + printf("space allocated: %uk\n",(unsigned int)(stats.lifetime_allocated-stats.lifetime_freed)/1024); + //malloc_report_statistics(); +#endif + m_timeouts=0; + m_failed=false; + do{ + // std::cout<<"pre event"<<std::endl; + + //Set the state to WAITINGFORDATA until the data is processed. + //The actual waiting happens at m_data_cond.wait() + //waitForData(); + m_loops.next(); + //std::cout<<"post event"<<std::endl; + //if(m_loops.done())stopWaiting(); //there is no data to wait for + if(!m_loops.done())waitForData(); //there is no data to wait for + //std::cout<<"before pause"<<std::endl; + //if paused go to sleep until resume() wakes the thread up + if(m_dataCond.waitingForData==true) { + unsigned long abs_sec,abs_nsec; + omni_thread::get_time(&abs_sec,&abs_nsec,m_timeout_seconds,m_timeout_nanoseconds); + int signalled=m_dataCond.cond.timedwait(abs_sec,abs_nsec); + m_dataCond.waitingForData=false; + if(signalled==0){ //timeout. Something went wrong with the data. + if(m_allowedTimeouts!=-1){ //-1 means any number is allowed + m_timeouts++; + if(m_timeouts>m_allowedTimeouts){ + std::cout<<"Timeout limit reached. Aborting scan"<<std::endl; + setFailed(); + abort(); + } + } + std::cout<<"Timeout"<<std::endl; + m_handler->timeoutOccurred(); + }else{ + //std::cout<<"Was restarted"<<std::endl; + } + } + m_dataCond.mutex.unlock(); + //std::cout<<"Unlocked data mutex "<<m_i++<<std::endl; + + m_pause_mutex.lock(); + if(m_state==PAUSED) m_pause_cond.wait(); + m_pause_mutex.unlock(); + + //std::cout<<"loop"<<std::endl; + }while(!m_loops.done() && m_state!=ABORT); + SerialIF::setChannelOutMask(0); + if(!failed()){ + std::cout<<"Publish histos "<<m_i<<std::endl; + ipc::CallbackParams cbp; + cbp.rce=RceName::getRceNumber(); + cbp.status=ipc::DOWNLOADING; + cbp.maskStage=-1; + cbp.loop0=-1; + cbp.loop1=-1; + RceCallback::instance()->sendMsg(ipc::HIGH,&cbp); + publishHistos(); + std::cout<<"Done "<<m_i++<<std::endl; + }else{ + std::cout<<"Failed"<<std::endl; + } + RceCallback::instance()->shutdown(); + m_state=IDLE; + return 0; +} + +void Scan::publishHistos(){ + // this scan has no histograms + if(m_histolist.size()==0)return; + for (size_t k=0;k<m_histolist.size();k++){ + IPCHistoManager::instance()->publish(m_histolist[k].c_str()); + } +} + +void Scan::setFailed(){ + m_failed=true; + ipc::CallbackParams cbp; + cbp.rce=RceName::getRceNumber(); + cbp.status=ipc::FAILED; + cbp.maskStage=-1; + cbp.loop0=-1; + cbp.loop1=-1; + RceCallback::instance()->sendMsg(ipc::HIGH,&cbp); +} + diff --git a/rce/rcecalib/scanctrl/Scan.hh b/rce/rcecalib/scanctrl/Scan.hh new file mode 100644 index 00000000..f6b3d16e --- /dev/null +++ b/rce/rcecalib/scanctrl/Scan.hh @@ -0,0 +1,47 @@ +#ifndef SCAN_HH +#define SCAN_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include <omnithread.h> +#include "rcecalib/scanctrl/NestedLoop.hh" +#include "rcecalib/util/DataCond.hh" +#include <vector> + +class ActionFactory; +class AbsDataHandler; + +class Scan{ +public: + Scan(); + ~Scan(); + int configureScan(boost::property_tree::ptree* scanOptions, ActionFactory& af, AbsDataHandler* par); + int waitForData(); + int stopWaiting(); + int pause(); + int resume(); + int abort(); + int startScan(); + int getStatus(){return (int)m_state;} + DataCond& getDataCond(){return m_dataCond;} + void setFailed(); + bool failed(){return m_failed;} + enum State{IDLE, CONFIGURED, RUNNING, PAUSED, ABORT}; + enum Timeout{CONFIG_TIMEOUT=500};//5 seconds +protected: + void publishHistos(); + State m_state; + NestedLoop m_loops; + omni_mutex m_pause_mutex ; + omni_condition m_pause_cond ; + DataCond m_dataCond; + int m_i; + AbsDataHandler *m_handler; + unsigned m_timeout_seconds; + unsigned m_timeout_nanoseconds; + bool m_failed; + int m_timeouts; + int m_allowedTimeouts; + std::vector<std::string> m_histolist; + +}; +#endif diff --git a/rce/rcecalib/scanctrl/ScanLoop.cc b/rce/rcecalib/scanctrl/ScanLoop.cc new file mode 100644 index 00000000..71051945 --- /dev/null +++ b/rce/rcecalib/scanctrl/ScanLoop.cc @@ -0,0 +1,83 @@ + +#include "ScanLoop.hh" +#include "ers/ers.h" +#include <stdio.h> + +ScanLoop::ScanLoop(const char* name, unsigned n): m_nPoints(n),m_nextOuterLoop(0),m_i(0){ + strcpy(m_name,name); + ERS_ASSERT_MSG(m_nPoints>0,"a scan loop must have at least one scan point"); + } +ScanLoop::~ScanLoop(){ + std::list<LoopAction*>::iterator listit; + for(listit = m_loopActions.begin(); listit != m_loopActions.end(); listit++){ + delete *listit; + } + std::list<EndOfLoopAction*>::iterator listit2; + for(listit2 = m_endOfLoopActions.begin(); listit2 != m_endOfLoopActions.end(); listit2++){ + delete *listit2; + } +} +void ScanLoop::addLoopAction(LoopAction *la){ + m_loopActions.push_back(la); +} + +void ScanLoop::addEndOfLoopAction(EndOfLoopAction *ea){ + m_endOfLoopActions.push_back(ea); +} + +bool ScanLoop::next(){ + m_i++; + bool done=false; + if(m_i>=m_nPoints){ // loop is over + endOfLoopAction(); + if(m_nextOuterLoop==0){ + done=true; + }else{ + done=m_nextOuterLoop->next(); + reset(); + } + } + if(done==false){ + loopAction(m_i); // perform loop action unless the nested loop is at its end + } + return done; +} + +void ScanLoop::loopAction(unsigned i){ + std::list<LoopAction*>::iterator listit; + for(listit = m_loopActions.begin(); listit != m_loopActions.end(); listit++){ + (*listit)->execute(i); + } +} +void ScanLoop::endOfLoopAction(){ + std::list<EndOfLoopAction*>::iterator listit; + for(listit = m_endOfLoopActions.begin(); listit != m_endOfLoopActions.end(); listit++){ + (*listit)->execute(); + } +} + +void ScanLoop::setNextOuterLoop(ScanLoop* loop){ + m_nextOuterLoop=loop; +} +void ScanLoop::firstEvent(){ + reset(); + loopAction(m_i); +} + +void ScanLoop::print(const char* prefix){ + std::cout<<prefix<<name()<<" 0 ... "<<m_nPoints - 1<<std::endl; + std::list<LoopAction*>::iterator lait=m_loopActions.begin(); + if(lait!=m_loopActions.end()){ + std::cout<<prefix<<"Loop Actions:"<<std::endl; + for(; lait != m_loopActions.end(); lait++){ + std::cout<<prefix<<" "<<(*lait)->name()<<std::endl; + } + } + std::list<EndOfLoopAction*>::iterator elait=m_endOfLoopActions.begin(); + if(elait!=m_endOfLoopActions.end()){ + std::cout<<prefix<<"End of Loop Actions:"<<std::endl; + for(; elait != m_endOfLoopActions.end(); elait++){ + std::cout<<prefix<<" "<<(*elait)->name()<<std::endl; + } + } +} diff --git a/rce/rcecalib/scanctrl/ScanLoop.hh b/rce/rcecalib/scanctrl/ScanLoop.hh new file mode 100644 index 00000000..f79ba283 --- /dev/null +++ b/rce/rcecalib/scanctrl/ScanLoop.hh @@ -0,0 +1,48 @@ +#ifndef SCANLOOP_HH +#define SCANLOOP_HH + +// Implements a nested for loop. Each loop object has a pointer to the next outer loop to call its next function. +// setupLoop is called every time the loop counter is incremented. endOfLoopAction is called at the end of the loop. +// next returns the return value of the next outer loop. The outermost loop returns if it's done (i.e. the nested +// loop is over. +// This class is the replacement for the NewDsp LoopCtrl structure. + +// C 2009 SLAC Author: Martin Kocian + +#include <string.h> +#include <vector> +#include <list> + +#include "rcecalib/scanctrl/LoopAction.hh" +#include "rcecalib/scanctrl/EndOfLoopAction.hh" + +class ScanLoop { + +public: + ScanLoop(const char* name, unsigned n); + ~ScanLoop(); + bool next(); + void reset(){m_i=0;}; + void firstEvent(); + void addLoopAction(LoopAction* la); + void addEndOfLoopAction(EndOfLoopAction* ea); + const char* name(){return m_name;} + void print(const char* prefix); + +protected: + void setNextOuterLoop(ScanLoop*); + void loopAction(unsigned); + void endOfLoopAction(); + + char m_name[128]; + unsigned m_nPoints; + ScanLoop* m_nextOuterLoop; + unsigned m_i; + std::vector<int> m_values; + std::list<LoopAction*> m_loopActions; + std::list<EndOfLoopAction*> m_endOfLoopActions; + + friend class NestedLoop; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/ScanRoot.cc b/rce/rcecalib/scanctrl/ScanRoot.cc new file mode 100644 index 00000000..35486496 --- /dev/null +++ b/rce/rcecalib/scanctrl/ScanRoot.cc @@ -0,0 +1,72 @@ + +#include "rcecalib/scanctrl/ScanRoot.hh" +#include "rcecalib/scanctrl/ActionFactory.hh" +#include "rcecalib/dataproc/AbsDataProc.hh" +#include "rcecalib/dataproc/AbsDataHandler.hh" +#include "rcecalib/dataproc/DataProcFactory.hh" +#include "rcecalib/scanctrl/Scan.hh" +#include "rcecalib/config/ConfigIF.hh" + +#include <boost/property_tree/ptree.hpp> +#include <boost/property_tree/info_parser.hpp> + +#include "rcecalib/util/DataCond.hh" +#include "rcecalib/util/exceptions.hh" + +#include <string> +#include <iostream> + + +ScanRoot::ScanRoot(ConfigIF* confif, Scan *scan): + m_configIF(confif),m_dataProc(0),m_scan(scan),m_formatter(0), m_handler(0),m_receiver(0){ +} +ScanRoot::~ScanRoot(){ +} + +int ScanRoot::configureScan(boost::property_tree::ptree *scanOptions){ + //std::cout<<"Start ScanRoot configureScan"<<std::endl; + int retval=0; + //print out configuration + //write_info(std::cout,*scanOptions); + + // set up pixel modules + retval+=m_configIF->configureScan(scanOptions); + // set up data processor + printf("configIF configured\n"); + DataProcFactory dfac; + try{ //catch bad scan option parameters + delete m_dataProc; + printf("Deleted old dataproc\n"); + m_dataProc=0; + std::string dataProc = scanOptions->get<std::string>("DataProc"); + m_dataProc=dfac.createDataProcessor(dataProc.c_str(),m_configIF, scanOptions); + printf("Created dataproc of type %s\n", dataProc.c_str()); + std::string ptype = scanOptions->get<std::string>("DataHandler"); + delete m_handler; + m_handler=0; + m_handler=dfac.createDataHandler(ptype.c_str(),m_dataProc, m_scan->getDataCond(), m_configIF, scanOptions); + printf("Created data handler of type %s\n", ptype.c_str()); + std::string rtype = scanOptions->get<std::string>("Receiver"); + delete m_receiver; + m_receiver=0; + m_receiver=dfac.createReceiver(rtype.c_str(),m_handler, scanOptions); + printf("Created receiver of type %s\n", rtype.c_str()); + ERS_ASSERT_MSG(m_handler!=0,"no data handler defined"); + + // set up Scan Loops + // The action factory contains all available loop and end-of-loop actions. + // These can depend on m_config, m_dataProc, m_scan. Therefore created here. + ActionFactory af(m_configIF, m_dataProc, m_scan); + m_scan->configureScan(scanOptions, af, m_handler); + + std::cout<<"Setup done"<<std::endl; + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + retval=1; + } + ERS_ASSERT_MSG(m_dataProc!=0,"no data processor defined"); + return retval; +} + diff --git a/rce/rcecalib/scanctrl/ScanRoot.hh b/rce/rcecalib/scanctrl/ScanRoot.hh new file mode 100644 index 00000000..07e5dc45 --- /dev/null +++ b/rce/rcecalib/scanctrl/ScanRoot.hh @@ -0,0 +1,28 @@ +#ifndef SCANROOT_HH +#define SCANROOT_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include <pthread.h> + +class ConfigIF; +class AbsDataProc; +class AbsDataHandler; +class AbsFormatter; +class AbsReceiver; +class Scan; + +class ScanRoot{ +public: + ScanRoot(ConfigIF*, Scan*); + virtual ~ScanRoot(); + virtual int configureScan(boost::property_tree::ptree* scanOptions); +protected: + ConfigIF* m_configIF; + AbsDataProc* m_dataProc; + Scan* m_scan; + AbsFormatter *m_formatter; + AbsDataHandler* m_handler; + AbsReceiver* m_receiver; + +}; +#endif diff --git a/rce/rcecalib/scanctrl/SelftriggerSetup.cc b/rce/rcecalib/scanctrl/SelftriggerSetup.cc new file mode 100644 index 00000000..bb8cca66 --- /dev/null +++ b/rce/rcecalib/scanctrl/SelftriggerSetup.cc @@ -0,0 +1,37 @@ +#include "rcecalib/scanctrl/SelftriggerSetup.hh" +#include "rcecalib/scanctrl/ScanLoop.hh" +#include <boost/property_tree/ptree.hpp> +#include "rcecalib/scanctrl/ActionFactory.hh" +#include "rcecalib/scanctrl/LoopAction.hh" +#include "rcecalib/scanctrl/EndOfLoopAction.hh" +#include "rcecalib/util/exceptions.hh" + +int SelftriggerSetup::setupLoops( NestedLoop& loop, boost::property_tree::ptree *scanOptions, ActionFactory* af){ + int retval=0; + loop.clear(); + try{ //catch bad scan option parameters + // Data Taking has a single loop with one entry + ScanLoop *scanloop=new ScanLoop("Selftrigger",1); + LoopAction* conf=af->createLoopAction("CONFIGURE_MODULES"); + scanloop->addLoopAction(conf); + // LoopAction* linkmask=af->createLoopAction("SETUP_CHANNELMASK"); + //scanloop->addLoopAction(linkmask); + // End of loop actions + //The fitaction is used here to close the file with the hits if available. + EndOfLoopAction* fitaction=af->createEndOfLoopAction("FIT","CLOSE_FILE"); + scanloop->addEndOfLoopAction(fitaction); + EndOfLoopAction* resetfe=af->createEndOfLoopAction("RESET_FE",""); + scanloop->addEndOfLoopAction(resetfe); + EndOfLoopAction* disablechannels=af->createEndOfLoopAction("DISABLE_ALL_CHANNELS",""); + scanloop->addEndOfLoopAction(disablechannels); + // loop is the nested loop object + loop.addNewInnermostLoop(scanloop); + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + retval=1; + } + // loop.print(); + return retval; +} diff --git a/rce/rcecalib/scanctrl/SelftriggerSetup.hh b/rce/rcecalib/scanctrl/SelftriggerSetup.hh new file mode 100644 index 00000000..3fcb42bd --- /dev/null +++ b/rce/rcecalib/scanctrl/SelftriggerSetup.hh @@ -0,0 +1,18 @@ +#ifndef SELFTRIGGERSETUP_HH +#define SELFTRIGGERSETUP_HH + +#include "rcecalib/scanctrl/NestedLoop.hh" +#include "rcecalib/scanctrl/LoopSetup.hh" +#include "rcecalib/scanctrl/ActionFactory.hh" +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/config/ConfigIF.hh" + +class SelftriggerSetup: public LoopSetup{ +public: + SelftriggerSetup():LoopSetup(){}; + virtual ~SelftriggerSetup(){} + int setupLoops(NestedLoop& loop, boost::property_tree::ptree *scanOptions, ActionFactory* af); +}; + + +#endif diff --git a/rce/rcecalib/scanctrl/SendTriggerAction.hh b/rce/rcecalib/scanctrl/SendTriggerAction.hh new file mode 100644 index 00000000..532c587a --- /dev/null +++ b/rce/rcecalib/scanctrl/SendTriggerAction.hh @@ -0,0 +1,19 @@ +#ifndef SENDTRIGGERACTION_HH +#define SENDTRIGGERACTION_HH + +#include "rcecalib/scanctrl/LoopAction.hh" +#include "rcecalib/config/ConfigIF.hh" + +class SendTriggerAction: public LoopAction{ +public: + SendTriggerAction(std::string name, ConfigIF* cif): + LoopAction(name),m_configIF(cif){} + int execute(int i){ + //std::cout<<"SendTriggerAction"<<std::endl; + return m_configIF->sendTrigger(); + } +private: + ConfigIF* m_configIF; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/SetChannelMaskAction.hh b/rce/rcecalib/scanctrl/SetChannelMaskAction.hh new file mode 100644 index 00000000..2a8ef252 --- /dev/null +++ b/rce/rcecalib/scanctrl/SetChannelMaskAction.hh @@ -0,0 +1,18 @@ +#ifndef SETCHANNELMASKACTION_HH +#define SETCHANNELMASKACTION_HH + +#include "rcecalib/scanctrl/LoopAction.hh" +#include "rcecalib/config/ConfigIF.hh" + +class SetChannelMaskAction: public LoopAction{ +public: + SetChannelMaskAction(std::string name, ConfigIF* cif): + LoopAction(name),m_configIF(cif){} + int execute(int i){ + return m_configIF->setChannelMask(); + } +private: + ConfigIF* m_configIF; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/SetupMaskStageAction.hh b/rce/rcecalib/scanctrl/SetupMaskStageAction.hh new file mode 100644 index 00000000..f35eaafd --- /dev/null +++ b/rce/rcecalib/scanctrl/SetupMaskStageAction.hh @@ -0,0 +1,52 @@ +#ifndef SETUPMASKSTAGEACTION_HH +#define SETUPMASKSTAGEACTION_HH + + +#include "rcecalib/scanctrl/LoopAction.hh" +#include "rcecalib/config/ConfigIF.hh" +#include "rcecalib/util/RceName.hh" +#include "rcecalib/dataproc/AbsDataProc.hh" +#include <boost/property_tree/ptree.hpp> +#include <string> +#include <stdio.h> +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/scanctrl/RceCallback.hh" + +class SetupMaskStageAction: public LoopAction{ +public: + SetupMaskStageAction(std::string name, ConfigIF* cif, AbsDataProc* proc, boost::property_tree::ptree *pt): + LoopAction(name),m_configIF(cif),m_dataProc(proc){ + try{ + m_firstStage=pt->get<int>("firstStage"); + m_stepStage=pt->get<int>("stepStage"); + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + } + } + int execute(int i){ + int stage=m_firstStage+i*m_stepStage; + //std::cout<<"Stage "<<stage<<std::endl; + m_dataProc->setMaskStage(stage); + ipc::CallbackParams cbp; + cbp.rce=RceName::getRceNumber(); + cbp.status=ipc::SCANNING; + cbp.maskStage=stage; + cbp.loop0=-1; + cbp.loop1=-1; + ipc::Priority pr=ipc::LOW; + if(stage%100==0)pr=ipc::HIGH; + else if(stage%10==0)pr=ipc::MEDIUM; + RceCallback::instance()->sendMsg(pr,&cbp); + return m_configIF->setupMaskStage(stage); + //std::cout<<"Post after SetupMaskStageAction"<<std::endl; + } +private: + ConfigIF* m_configIF; + AbsDataProc* m_dataProc; + unsigned short m_firstStage; + unsigned short m_stepStage; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/SetupParamAction.hh b/rce/rcecalib/scanctrl/SetupParamAction.hh new file mode 100644 index 00000000..b387bd26 --- /dev/null +++ b/rce/rcecalib/scanctrl/SetupParamAction.hh @@ -0,0 +1,45 @@ +#ifndef SETUPPARAMACTION_HH +#define SETUPPARAMACTION_HH + +#include <boost/property_tree/ptree.hpp> +#include <boost/foreach.hpp> +#include "rcecalib/util/exceptions.hh" +#include "rcecalib/scanctrl/LoopAction.hh" +#include "rcecalib/config/ConfigIF.hh" +#include <string> +#include <vector> + +class SetupParamAction: public LoopAction{ +public: + SetupParamAction(std::string name, ConfigIF* cif, boost::property_tree::ptree *pt ): + LoopAction(name),m_configIF(cif){ + try{ + m_scanParameter=pt->get<std::string>("scanParameter"); + int nPoints=pt->get<int>("nPoints"); + ERS_DEBUG(2,"scanParameter: "<<m_scanParameter); + BOOST_FOREACH(boost::property_tree::ptree::value_type &v, pt->get_child("dataPoints")){ + ERS_DEBUG(2, v.second.data()); + int data = boost::lexical_cast<int>(v.second.data()); + dataPoints.push_back(data); + } + ERS_ASSERT_MSG((int)dataPoints.size()==nPoints,"of an inconsistency in the number of scan points."); + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + } + } + + int execute(int i){ + ERS_DEBUG(2,"SetupParamAction "<<i); + //std::cout<<"Parameter is "<<dataPoints[i]<<std::endl; + return m_configIF->setupParameter(m_scanParameter.c_str(),dataPoints[i]); + } + +private: + ConfigIF* m_configIF; + std::string m_scanParameter; + std::vector<int> dataPoints; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/SetupTriggerAction.hh b/rce/rcecalib/scanctrl/SetupTriggerAction.hh new file mode 100644 index 00000000..99110980 --- /dev/null +++ b/rce/rcecalib/scanctrl/SetupTriggerAction.hh @@ -0,0 +1,53 @@ +#ifndef SETUPTRIGGERACTION_HH +#define SETUPTRIGGERACTION_HH + + +#include "rcecalib/scanctrl/LoopAction.hh" +#include "rcecalib/config/ConfigIF.hh" +#include <boost/property_tree/ptree.hpp> +#include <string> +#include "rcecalib/util/exceptions.hh" + +class SetupTriggerAction: public LoopAction{ +public: + SetupTriggerAction(std::string name, ConfigIF* cif, boost::property_tree::ptree *pt): + LoopAction(name),m_configIF(cif){ + try{ + m_interval=pt->get<int>("trigOpt.eventInterval"); + m_l1delay = pt->get<int>("trigOpt.CalL1ADelay"); + m_triggermask = pt->get<int>("trigOpt.triggerMask"); + m_repetitions = pt->get<int>("trigOpt.nTriggers"); + m_deadtime = pt->get<int>("trigOpt.deadtime"); + m_hitbusconfig = pt->get<int>("trigOpt.hitbusConfig"); + m_protectFifo = pt->get("trigOpt.optionsMask.PROTECT_FIFO", 0); + } + catch(boost::property_tree::ptree_bad_path ex){ + rcecalib::Bad_ptree_param issue( ERS_HERE, ex.what()); + ers::error(issue); + } + } + int execute(int i){ + std::cout<<"Configuring trigger with interval="<<std::dec<<m_interval<<", l1 delay="<<m_l1delay<< + ", number of repetitions="<<m_repetitions<<", triggermask="<<std::hex<<m_triggermask<< + ", hitbus config="<<m_hitbusconfig<<", protectFifo="<<m_protectFifo<<std::dec<<std::endl; + m_configIF->writeHWregister(9,(unsigned)m_interval); //period + m_configIF->writeHWregister(14,(unsigned)m_repetitions); //n-1 events only + m_configIF->writeHWregister(8,(unsigned)m_l1delay); + m_configIF->writeHWregister(15,(unsigned)m_deadtime); + //m_configIF->writeHWregister(21,(unsigned)m_hitbusconfig); // per RCE + m_configIF->writeHWregister(26,(unsigned)m_protectFifo); + m_configIF->writeHWregister(11,(unsigned)m_triggermask); //trigger mask 2=cyclic + return 0; + } +private: + ConfigIF* m_configIF; + int m_interval; + int m_l1delay; + int m_triggermask; + int m_repetitions; + int m_deadtime; + int m_hitbusconfig; + int m_protectFifo; +}; + +#endif diff --git a/rce/rcecalib/scanctrl/constituents.mk b/rce/rcecalib/scanctrl/constituents.mk new file mode 100644 index 00000000..cc8e9726 --- /dev/null +++ b/rce/rcecalib/scanctrl/constituents.mk @@ -0,0 +1,45 @@ + +ifneq ($(findstring linux,$(tgt_os)),) +libnames := scanctrl +endif +ifneq ($(findstring ppc-rtems-rce,$(tgt_arch)),) + modlibnames := scanctrl + endif +ifeq ($(profiler),y) +CPPFLAGS+='-D__PROFILER_ENABLED__' +endif + + +libsrcs_scanctrl := ActionFactory.cc \ + LoopFactory.cc \ + NestedLoop.cc \ + RegularScanSetup.cc \ + RegularCfgScanSetup.cc \ + IfScanSetup.cc \ + DelayScanSetup.cc \ + CosmicDataSetup.cc \ + SelftriggerSetup.cc \ + NoiseScanSetup.cc \ + Scan.cc \ + ScanLoop.cc \ + ScanRoot.cc \ + RceCallback.cc + + +libincs_scanctrl := $(ers_include_path) \ + $(owl_include_path) \ + $(ipc_include_path) \ + $(is_include_path) \ + $(oh_include_path) \ + $(boost_include_path) \ + $(omniorb_include_path) + + + + + + + + + + diff --git a/rce/rcecalib/server/.gitignore b/rce/rcecalib/server/.gitignore new file mode 100644 index 00000000..5761abcf --- /dev/null +++ b/rce/rcecalib/server/.gitignore @@ -0,0 +1 @@ +*.o diff --git a/rce/rcecalib/server/AFPHPTDCConfigFile.cc b/rce/rcecalib/server/AFPHPTDCConfigFile.cc new file mode 100644 index 00000000..9eae9479 --- /dev/null +++ b/rce/rcecalib/server/AFPHPTDCConfigFile.cc @@ -0,0 +1,566 @@ +#include "rcecalib/server/AFPHPTDCConfigFile.hh" +#include "rcecalib/util/exceptions.hh" +#include <boost/algorithm/string.hpp> +#include <iostream> +#include <fstream> +#include <vector> +#include <sys/stat.h> + +std::string AFPHPTDCConfigFile::getFullPath(std::string relPath){ + std::string newPath = relPath, basePath=m_moduleCfgFilePath, testName; + unsigned int pos; + // skip config file-name part of base path + pos = basePath.find_last_of('/'); + if(pos!=std::string::npos) basePath.erase(pos,basePath.length()-pos); + // skip "config" part of base path + pos = basePath.find_last_of('/'); + if(pos!=std::string::npos) basePath.erase(pos+1,basePath.length()-pos); + else basePath=""; + // then add relative path of DAC or mask file + newPath = basePath + "calib/"+newPath; + return newPath; +} + +AFPHPTDCConfigFile::~AFPHPTDCConfigFile(){} + +unsigned AFPHPTDCConfigFile::lookupToUnsigned(std::string par, int index, int size){ + if( m_params.find(par)==m_params.end()){ + std::cout<<"Parameter "<<par<<" does not exist."<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + std::string vals=m_params[par][index]; + unsigned val; + int success=convertToUnsigned(vals, val, size); + if(success==false){ + std::cout<<"Bad value "<<vals<< " for parameter "<<par<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + return val; +} +/* +float AFPHPTDCConfigFile::lookupToFloat(std::string par){ + if( m_params.find(par)==m_params.end()){ + std::cout<<"Parameter "<<par<<" does not exist."<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + std::string vals=m_params[par]; + float val; + char* end; + val=strtof(vals.c_str(), &end); + if(end-vals.c_str()!=(int)vals.size()){ + std::cout<<"Bad value "<<vals<< " for parameter "<<par<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + return val; +} +*/ + +int AFPHPTDCConfigFile::convertToUnsigned(std::string par, unsigned &val, int size){ + char* end; + val=strtoul(par.c_str(), &end, 0); + if(end-par.c_str()!=(int)par.size()){ + return 0; + } + if(size==0 && (val&0xffffff00)!=0){ + std::cout<<"Value "<<val<<" too large."<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + else if(size==1 && (val&0xffff0000)!=0){ + std::cout<<"Value "<<val<<" too large."<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + return 1; +} + + +void AFPHPTDCConfigFile::setupCalib(float cal[2][12][ipc::IPC_N_CALIBVALS] , std::string par, int i1, int i2){ + char pa[20]; + sprintf(pa, "%s_%d", par.c_str(), i2); + std::string pastr(pa); + if( m_params.find(pastr)==m_params.end()){ + std::cout<<"Parameter "<<pastr<<" does not exist."<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + std::string fullpath=getFullPath(m_params[pastr][0]); + std::ifstream dacfile(fullpath.c_str()); + if(!dacfile.good()){ + std::cout<<"Cannot open file with name "<<fullpath<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + for(int i=0;i<ipc::IPC_N_CALIBVALS;i++){ + dacfile>>cal[i1][i2][i]; + if(dacfile.eof()){ + std::cout<<"Not enough values in file "<<fullpath<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + } +} + +void AFPHPTDCConfigFile::writeModuleConfig(ipc::AFPHPTDCModuleConfig* config, const std::string &base, const std::string &confdir, + const std::string &configname, const std::string &key){ +/* + struct stat stFileInfo; + int intStat; + // Attempt to get the file attributes + intStat = stat(base.c_str(),&stFileInfo); + if(intStat != 0) { //File does not exist + std::cout<<"Directory "<<base<<" does not exist. Not writing config file"<<std::endl; + return; + } + intStat = stat((base+"/"+confdir).c_str(),&stFileInfo); + if(intStat != 0) { //File does not exist + //std::cout<<"Directory "<<base<<"/"<<confdir<<" does not exist. Creating."<<std::endl; + mkdir ((base+"/"+confdir).c_str(),0777); + mkdir ((base+"/"+confdir+"/configs").c_str(),0777); + mkdir ((base+"/"+confdir+"/masks").c_str(),0777); + mkdir ((base+"/"+confdir+"/tdacs").c_str(),0777); + mkdir ((base+"/"+confdir+"/fdacs").c_str(),0777); + } + std::string cfgname=configname; + if(key.size()!=0)cfgname+="__"+key; + std::string fullpath=base+"/"+confdir+"/configs/"+cfgname+".cfg"; + std::ofstream cfgfile(fullpath.c_str()); + cfgfile<<"# FEI4B Configuration"<<std::endl; + cfgfile<<std::endl; + cfgfile<<"# Module name"<<std::endl; + cfgfile<<std::endl; + cfgfile<<"ModuleID\t\t"<<config->idStr<<std::endl; + cfgfile<<std::endl; + cfgfile<<"# Geographical address"<<std::endl; + cfgfile<<std::endl; + cfgfile<<"Address\t\t\t"<<(unsigned)config->FECommand.address<<std::endl; + cfgfile<<std::endl; + cfgfile<<"# Global register"<<std::endl; + cfgfile<<std::endl; + //Global register + ipc::AFPHPTDCModuleGlobal* cfg=&config->FEGlobal; + cfgfile<<"TrigCnt\t\t\t"<<cfg->TrigCnt<<std::endl; + cfgfile<<"Conf_AddrEnable\t\t"<<cfg->Conf_AddrEnable <<std::endl; + cfgfile<<"Reg2Spare\t\t"<<cfg->Reg2Spare <<std::endl; + cfgfile<<"ErrMask0\t\t"<<"0x"<<std::hex<<cfg->ErrMask0 <<std::dec<<std::endl; + cfgfile<<"ErrMask1\t\t"<<"0x"<<std::hex<<cfg->ErrMask1 <<std::dec<<std::endl; + cfgfile<<"PrmpVbpRight\t\t"<< cfg->PrmpVbpRight <<std::endl; + cfgfile<<"BufVgOpAmp\t\t"<<cfg->BufVgOpAmp <<std::endl; + cfgfile<<"Reg6Spare\t\t"<<cfg->Reg6Spare <<std::endl; + cfgfile<<"PrmpVbp\t\t\t"<<cfg->PrmpVbp <<std::endl; + cfgfile<<"TdacVbp\t\t\t"<< cfg->TdacVbp <<std::endl; + cfgfile<<"DisVbn\t\t\t"<<cfg->DisVbn <<std::endl; + cfgfile<<"Amp2Vbn\t\t\t"<<cfg->Amp2Vbn <<std::endl; + cfgfile<<"Amp2VbpFol\t\t"<<cfg->Amp2VbpFol <<std::endl; + cfgfile<<"Reg9Spare\t\t"<<cfg->Reg9Spare <<std::endl; + cfgfile<<"Amp2Vbp\t\t\t"<<cfg->Amp2Vbp <<std::endl; + cfgfile<<"FdacVbn\t\t\t"<<cfg->FdacVbn <<std::endl; + cfgfile<<"Amp2Vbpf\t\t"<<cfg->Amp2Vbpf <<std::endl; + cfgfile<<"PrmpVbnFol\t\t"<<cfg->PrmpVbnFol <<std::endl; + cfgfile<<"PrmpVbpLeft\t\t"<<cfg->PrmpVbpLeft <<std::endl; + cfgfile<<"PrmpVbpf\t\t"<<cfg->PrmpVbpf <<std::endl; + cfgfile<<"PrmpVbnLcc\t\t"<<cfg->PrmpVbnLcc <<std::endl; + cfgfile<<"Reg13Spare\t\t"<<cfg->Reg13Spare <<std::endl; + cfgfile<<"PxStrobes\t\t"<<cfg->PxStrobes <<std::endl; + cfgfile<<"S0\t\t\t"<<cfg->S0 <<std::endl; + cfgfile<<"S1\t\t\t"<<cfg->S1 <<std::endl; + cfgfile<<"LVDSDrvIref\t\t"<<cfg->LVDSDrvIref <<std::endl; + cfgfile<<"GADCOpAmp\t\t"<<cfg->GADCOpAmp <<std::endl; + cfgfile<<"PllIbias\t\t"<<cfg->PllIbias <<std::endl; + cfgfile<<"LVDSDrvVos\t\t"<<cfg->LVDSDrvVos <<std::endl; + cfgfile<<"TempSensBias\t\t"<<cfg->TempSensBias <<std::endl; + cfgfile<<"PllIcp\t\t\t"<<cfg->PllIcp <<std::endl; + cfgfile<<"Reg17Spare\t\t"<<cfg->Reg17Spare <<std::endl; + cfgfile<<"PlsrIdacRamp\t\t"<<cfg->PlsrIdacRamp <<std::endl; + cfgfile<<"VrefDigTune\t\t"<<cfg->VrefDigTune <<std::endl; + cfgfile<<"PlsrVgOPamp\t\t"<<cfg->PlsrVgOPamp <<std::endl; + cfgfile<<"PlsrDacBias\t\t"<<cfg->PlsrDacBias <<std::endl; + cfgfile<<"VrefAnTune\t\t"<<cfg->VrefAnTune <<std::endl; + cfgfile<<"Vthin_AltCoarse\t\t"<<cfg->Vthin_AltCoarse <<std::endl; + cfgfile<<"Vthin_AltFine\t\t"<<cfg->Vthin_AltFine <<std::endl; + cfgfile<<"PlsrDAC\t\t\t"<<cfg->PlsrDAC <<std::endl; + cfgfile<<"DIGHITIN_Sel\t\t"<<cfg->DIGHITIN_Sel <<std::endl; + cfgfile<<"DINJ_Override\t\t"<<cfg->DINJ_Override <<std::endl; + cfgfile<<"HITLD_In\t\t"<<cfg->HITLD_In <<std::endl; + cfgfile<<"Reg21Spare\t\t"<<cfg->Reg21Spare <<std::endl; + cfgfile<<"Reg22Spare2\t\t"<<cfg->Reg22Spare2 <<std::endl; + cfgfile<<"Colpr_Addr\t\t"<<cfg->Colpr_Addr <<std::endl; + cfgfile<<"Colpr_Mode\t\t"<<cfg->Colpr_Mode <<std::endl; + cfgfile<<"Reg22Spare1\t\t"<<cfg->Reg22Spare1 <<std::endl; + cfgfile<<"DisableColumnCnfg0\t"<<"0x"<<std::hex<<cfg->DisableColumnCnfg0 <<std::dec<<std::endl; + cfgfile<<"DisableColumnCnfg1\t"<<"0x"<<std::hex<<cfg->DisableColumnCnfg1 <<std::dec<<std::endl; + cfgfile<<"DisableColumnCnfg2\t"<<"0x"<<std::hex<<cfg->DisableColumnCnfg2 <<std::dec<<std::endl; + cfgfile<<"TrigLat\t\t\t"<< cfg->TrigLat <<std::endl; + cfgfile<<"CMDcnt\t\t\t"<<cfg->CMDcnt <<std::endl; + cfgfile<<"StopModeCnfg\t\t"<<cfg->StopModeCnfg <<std::endl; + cfgfile<<"HitDiscCnfg\t\t"<<cfg->HitDiscCnfg <<std::endl; + cfgfile<<"EN_PLL\t\t\t"<<cfg->EN_PLL <<std::endl; + cfgfile<<"Efuse_sense\t\t"<<cfg->Efuse_sense <<std::endl; + cfgfile<<"Stop_Clk\t\t"<<cfg->Stop_Clk <<std::endl; + cfgfile<<"ReadErrorReq\t\t"<<cfg->ReadErrorReq <<std::endl; + cfgfile<<"Reg27Spare1\t\t"<<cfg->Reg27Spare1 <<std::endl; + cfgfile<<"GADC_Enable\t\t"<<cfg->GADC_Enable <<std::endl; + cfgfile<<"ShiftReadBack\t\t"<<cfg->ShiftReadBack <<std::endl; + cfgfile<<"Reg27Spare2\t\t"<<cfg->Reg27Spare2 <<std::endl; + cfgfile<<"GateHitOr\t\t"<<cfg->GateHitOr <<std::endl; + cfgfile<<"CalEn\t\t\t"<<cfg->CalEn <<std::endl; + cfgfile<<"SR_clr\t\t\t"<<cfg->SR_clr <<std::endl; + cfgfile<<"Latch_en\t\t"<<cfg->Latch_en <<std::endl; + cfgfile<<"SR_Clock\t\t"<<cfg->SR_Clock <<std::endl; + cfgfile<<"LVDSDrvSet06\t\t"<<cfg->LVDSDrvSet06 <<std::endl; + cfgfile<<"Reg28Spare\t\t"<<cfg->Reg28Spare <<std::endl; + cfgfile<<"EN40M\t\t\t"<<cfg->EN40M <<std::endl; + cfgfile<<"EN80M\t\t\t"<<cfg->EN80M <<std::endl; + cfgfile<<"CLK0_S2\t\t\t"<<(cfg->CLK0 &0x1)<<std::endl; + cfgfile<<"CLK0_S1\t\t\t"<<((cfg->CLK0>>1)&0x1 )<<std::endl; + cfgfile<<"CLK0_S0\t\t\t"<<((cfg->CLK0>>2)&0x1 )<<std::endl; + cfgfile<<"CLK1_S2\t\t\t"<<(cfg->CLK1&0x1 )<<std::endl; + cfgfile<<"CLK1_S1\t\t\t"<<((cfg->CLK1>>1)&0x1 )<<std::endl; + cfgfile<<"CLK1_S0\t\t\t"<<((cfg->CLK1>>2)&0x1 )<<std::endl; + cfgfile<<"EN160M\t\t\t"<<cfg->EN160M <<std::endl; + cfgfile<<"EN320M\t\t\t"<<cfg->EN320M <<std::endl; + cfgfile<<"Reg29Spare1\t\t"<<cfg->Reg29Spare1 <<std::endl; + cfgfile<<"no8b10b\t\t\t"<<cfg->no8b10b <<std::endl; + cfgfile<<"Clk2OutCnfg\t\t"<<cfg->Clk2OutCnfg <<std::endl; + cfgfile<<"EmptyRecord\t\t"<<cfg->EmptyRecord <<std::endl; + cfgfile<<"Reg29Spare2\t\t"<<cfg->Reg29Spare2 <<std::endl; + cfgfile<<"LVDSDrvEn\t\t"<<cfg->LVDSDrvEn <<std::endl; + cfgfile<<"LVDSDrvSet30\t\t"<<cfg->LVDSDrvSet30 <<std::endl; + cfgfile<<"LVDSDrvSet12\t\t"<<cfg->LVDSDrvSet12 <<std::endl; + cfgfile<<"TempSensDiodeSel\t"<<cfg->TempSensDiodeSel <<std::endl; + cfgfile<<"TempSensDisable\t\t"<<cfg->TempSensDisable <<std::endl; + cfgfile<<"IleakRange\t\t"<<cfg->IleakRange <<std::endl; + cfgfile<<"Reg30Spare\t\t"<<cfg->Reg30Spare <<std::endl; + cfgfile<<"PlsrRiseUpTau\t\t"<<cfg->PlsrRiseUpTau <<std::endl; + cfgfile<<"PlsrPwr\t\t\t"<<cfg->PlsrPwr <<std::endl; + cfgfile<<"PlsrDelay\t\t"<<cfg->PlsrDelay <<std::endl; + cfgfile<<"ExtDigCalSW\t\t"<<cfg->ExtDigCalSW <<std::endl; + cfgfile<<"ExtAnaCalSW\t\t"<<cfg->ExtAnaCalSW <<std::endl; + cfgfile<<"Reg31Spare\t\t"<<cfg->Reg31Spare <<std::endl; + cfgfile<<"GADCSel\t\t\t"<<cfg->GADCSel <<std::endl; + cfgfile<<"SELB0\t\t\t"<<cfg->SELB0 <<std::endl; + cfgfile<<"SELB1\t\t\t"<<cfg->SELB1 <<std::endl; + cfgfile<<"SELB2\t\t\t"<<cfg->SELB2 <<std::endl; + cfgfile<<"Reg34Spare1\t\t"<<cfg->Reg34Spare1 <<std::endl; + cfgfile<<"PrmpVbpMsnEn\t\t"<<cfg->PrmpVbpMsnEn <<std::endl; + cfgfile<<"Reg34Spare2\t\t"<<cfg->Reg34Spare2 <<std::endl; + cfgfile<<"Chip_SN\t\t\t"<<cfg->Chip_SN <<std::endl; + cfgfile<<"Reg1Spare\t\t"<<cfg->Reg1Spare <<std::endl; + cfgfile<<"SmallHitErase\t\t"<<cfg->SmallHitErase <<std::endl; + cfgfile<<"Eventlimit\t\t"<<cfg->Eventlimit <<std::endl; + cfgfile<<std::endl; + cfgfile<<"# Pixel register"<<std::endl; + cfgfile<<std::endl; + cfgfile<<"enable\t\t\t"<<confdir<<"/masks/enable_"<<cfgname<<".dat"<<std::endl; + cfgfile<<"largeCap\t\t"<<confdir<<"/masks/largeCap_"<<cfgname<<".dat"<<std::endl; + cfgfile<<"smallCap\t\t"<<confdir<<"/masks/smallCap_"<<cfgname<<".dat"<<std::endl; + cfgfile<<"hitbus\t\t\t"<<confdir<<"/masks/hitbus_"<<cfgname<<".dat"<<std::endl; + cfgfile<<std::endl; + cfgfile<<"tdac\t\t\t"<<confdir<<"/tdacs/tdac_"<<cfgname<<".dat"<<std::endl; + cfgfile<<"fdac\t\t\t"<<confdir<<"/fdacs/fdac_"<<cfgname<<".dat"<<std::endl; + cfgfile<<std::endl; + cfgfile<<std::endl; + cfgfile<<"# Charge injection parameters"<<std::endl; + cfgfile<<std::endl; + cfgfile<<"cinjLo\t\t\t"<<config->FECalib.cinjLo <<std::endl; + cfgfile<<"cinjHi\t\t\t"<<config->FECalib.cinjHi <<std::endl; + cfgfile<<"vcalCoeff[0]\t\t"<<config->FECalib.vcalCoeff[0] <<std::endl; + cfgfile<<"vcalCoeff[1]\t\t"<<config->FECalib.vcalCoeff[1] <<std::endl; + cfgfile<<"vcalCoeff[2]\t\t"<<config->FECalib.vcalCoeff[2] <<std::endl; + cfgfile<<"vcalCoeff[3]\t\t"<<config->FECalib.vcalCoeff[3] <<std::endl; + cfgfile<<"chargeCoeffClo\t\t"<<config->FECalib.chargeCoeffClo<<std::endl; + cfgfile<<"chargeCoeffChi\t\t"<<config->FECalib.chargeCoeffChi<<std::endl; + cfgfile<<"chargeOffsetClo\t\t"<<config->FECalib.chargeOffsetClo<<std::endl; + cfgfile<<"chargeOffsetChi\t\t"<<config->FECalib.chargeOffsetChi<<std::endl; + cfgfile<<"monleakCoeff\t\t"<<config->FECalib.monleakCoeff<<std::endl; + writeMaskFile(ipc::enable, config, base+"/"+confdir+"/masks/enable_"+cfgname+".dat"); + writeMaskFile(ipc::largeCap, config, base+"/"+confdir+"/masks/largeCap_"+cfgname+".dat"); + writeMaskFile(ipc::smallCap, config, base+"/"+confdir+"/masks/smallCap_"+cfgname+".dat"); + writeMaskFile(ipc::hitbus, config, base+"/"+confdir+"/masks/hitbus_"+cfgname+".dat"); + + writeDacFile(config->FETrims.dacThresholdTrim, base+"/"+confdir+"/tdacs/tdac_"+cfgname+".dat"); + writeDacFile(config->FETrims.dacFeedbackTrim, base+"/"+confdir+"/fdacs/fdac_"+cfgname+".dat"); + + */ + +} + +void AFPHPTDCConfigFile::writeCalibFile(float cal[2][12][ipc::IPC_N_CALIBVALS] , const std::string filename, int i1, int i2){ + std::ofstream maskfile(filename.c_str()); + for (int i=0;i<ipc::IPC_N_CALIBVALS;i++) + maskfile<<cal[i1][i2][i]; + maskfile<<std::endl; +} + +void AFPHPTDCConfigFile::readModuleConfig(ipc::AFPHPTDCModuleConfig* cfg, std::string filename){ + //clear structure + char* ccfg=(char*)cfg; + for (unsigned int i=0;i<sizeof(ipc::AFPHPTDCModuleConfig);i++)ccfg[i]=0; + //open file + m_moduleCfgFile=new std::ifstream(filename.c_str()); + if(!m_moduleCfgFile->good()){ + std::cout<<"Cannot open file with name "<<filename<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + m_moduleCfgFilePath = filename; + // parse config file + std::string inpline; + m_params.clear(); + while(true){ + getline(*m_moduleCfgFile, inpline); + if(m_moduleCfgFile->eof())break; + boost::trim(inpline); + if(inpline.size()!=0 && inpline[0]!='#'){ //remove comment lines and empty lines + std::vector<std::string> splitVec; + split( splitVec, inpline, boost::is_any_of(" \t"), boost::token_compress_on ); + if(splitVec.size()<2){ + std::cout<<"Bad input line "<<inpline<<std::endl; + continue; + } + for (size_t i=1;i<splitVec.size();i++) + m_params[splitVec[0]].push_back(splitVec[i]); + } + } + // Module name + std::string modname; + if( m_params.find("ModuleID")==m_params.end()){ + std::cout<<"No Module ID defined."<<std::endl; + }else{ + modname=m_params["ModuleID"][0]; + } + sprintf((char*)cfg->idStr, "%s", modname.c_str()); + cfg->test = lookupToUnsigned("test", 0, 1); + cfg->tdcControl = lookupToUnsigned("tdcControl", 0); + cfg->run = lookupToUnsigned("run", 0); + cfg->bypassLut = lookupToUnsigned("bypassLut", 0); + cfg->localClockEn = lookupToUnsigned("localClockEn", 0); + cfg->calClockEn = lookupToUnsigned("calClockEn", 0); + cfg->refEn = lookupToUnsigned("refEn", 0); + cfg->hitTestEn = lookupToUnsigned("hitTestEn", 0); + cfg->inputSel = lookupToUnsigned("inputSel", 0); + cfg->address = lookupToUnsigned("address", 0); + cfg->fanspeed = lookupToUnsigned("fanspeed", 0); + cfg->channelEn = lookupToUnsigned("channelEn", 0, 1); + + for (int i=0;i<3;i++){ + cfg->test_select[i] = lookupToUnsigned("test_select", i); + cfg->enable_error_mark[i] = lookupToUnsigned("enable_error_mark", i); + cfg->enable_error_bypass[i] = lookupToUnsigned("enable_error_bypass", i); + cfg->enable_error[i] = lookupToUnsigned("enable_error", i, 1); + cfg->readout_single_cycle_speed[i] = lookupToUnsigned("readout_single_cycle_speed", i); + cfg->serial_delay[i] = lookupToUnsigned("serial_delay", i); + cfg->strobe_select[i] = lookupToUnsigned("strobe_select", i); + cfg->readout_speed_select[i] = lookupToUnsigned("readout_speed_select", i); + cfg->token_delay[i] = lookupToUnsigned("token_delay", i); + cfg->enable_local_trailer[i] = lookupToUnsigned("enable_local_trailer", i); + cfg->enable_local_header[i] = lookupToUnsigned("enable_local_header", i); + cfg->enable_global_trailer[i] = lookupToUnsigned("enable_global_trailer", i); + cfg->enable_global_header[i] = lookupToUnsigned("enable_global_header", i); + cfg->keep_token[i] = lookupToUnsigned("keep_token", i); + cfg->master[i] = lookupToUnsigned("master", i); + cfg->enable_bytewise[i] = lookupToUnsigned("enable_bytewise", i); + cfg->enable_serial[i] = lookupToUnsigned("enable_serial", i); + cfg->enable_jtag_readout[i] = lookupToUnsigned("enable_jtag_readout", i); + cfg->tdc_id[i] = lookupToUnsigned("tdc_id", i); + cfg->select_bypass_inputs[i] = lookupToUnsigned("select_bypass_inputs", i); + cfg->readout_fifo_size[i] = lookupToUnsigned("readout_fifo_size", i); + cfg->reject_count_offset[i] = lookupToUnsigned("reject_count_offset", i, 1); + cfg->search_window[i] = lookupToUnsigned("search_window", i, 1); + cfg->match_window[i] = lookupToUnsigned("match_window", i, 1); + cfg->leading_resolution[i] = lookupToUnsigned("leading_resolution", i); + cfg->fixed_pattern[i] = lookupToUnsigned("fixed_pattern", i, 2); + cfg->enable_fixed_pattern[i] = lookupToUnsigned("enable_fixed_pattern", i); + cfg->max_event_size[i] = lookupToUnsigned("max_event_size", i); + cfg->reject_readout_fifo_full[i] = lookupToUnsigned("reject_readout_fifo_full", i); + cfg->enable_readout_occupancy[i] = lookupToUnsigned("enable_readout_occupancy", i); + cfg->enable_readout_separator[i] = lookupToUnsigned("enable_readout_separator", i); + cfg->enable_overflow_detect[i] = lookupToUnsigned("enable_overflow_detect", i); + cfg->enable_relative[i] = lookupToUnsigned("enable_relative", i); + cfg->enable_automatic_reject[i] = lookupToUnsigned("enable_automatic_reject", i); + cfg->event_count_offset[i] = lookupToUnsigned("event_count_offset", i, 1); + cfg->trigger_count_offset[i] = lookupToUnsigned("trigger_count_offset", i, 1); + cfg->enable_set_counters_on_bunch_reset[i] = lookupToUnsigned("enable_set_counters_on_bunch_reset", i); + cfg->enable_master_reset_code[i] = lookupToUnsigned("enable_master_reset_code", i); + cfg->enable_master_reset_code_on_event_reset[i] = lookupToUnsigned("enable_master_reset_code_on_event_reset", i); + cfg->enable_reset_channel_buffer_when_separator[i] = lookupToUnsigned("enable_reset_channel_buffer_when_separator", i); + cfg->enable_separator_on_event_reset[i] = lookupToUnsigned("enable_separator_on_event_reset", i); + cfg->enable_separator_on_bunch_reset[i] = lookupToUnsigned("enable_separator_on_bunch_reset", i); + cfg->enable_direct_event_reset[i] = lookupToUnsigned("enable_direct_event_reset", i); + cfg->enable_direct_bunch_reset[i] = lookupToUnsigned("enable_direct_bunch_reset", i); + cfg->enable_direct_trigger[i] = lookupToUnsigned("enable_direct_trigger", i); + for (int j=0;j<32;j++){ + char offs[32]; + sprintf(offs, "offset%d", j); + cfg->offset[j][i] = lookupToUnsigned(offs, i, 1); + } + cfg->coarse_count_offset[i] = lookupToUnsigned("coarse_count_offset", i, 1); + cfg->dll_tap_adjust3_0[i] = lookupToUnsigned("dll_tap_adjust3_0", i, 1); + cfg->dll_tap_adjust7_4[i] = lookupToUnsigned("dll_tap_adjust7_4", i, 1); + cfg->dll_tap_adjust11_8[i] = lookupToUnsigned("dll_tap_adjust11_8", i, 1); + cfg->dll_tap_adjust15_12[i] = lookupToUnsigned("dll_tap_adjust15_12", i, 1); + cfg->dll_tap_adjust19_16[i] = lookupToUnsigned("dll_tap_adjust19_16", i, 1); + cfg->dll_tap_adjust23_20[i] = lookupToUnsigned("dll_tap_adjust23_20", i, 1); + cfg->dll_tap_adjust27_24[i] = lookupToUnsigned("dll_tap_adjust27_24", i, 1); + cfg->dll_tap_adjust31_28[i] = lookupToUnsigned("dll_tap_adjust31_28", i, 1); + cfg->rc_adjust[i] = lookupToUnsigned("rc_adjust", i, 1); + cfg->not_used[i] = lookupToUnsigned("not_used", i); + cfg->low_power_mode[i] = lookupToUnsigned("low_power_mode", i); + cfg->width_select[i] = lookupToUnsigned("width_select", i); + cfg->vernier_offset[i] = lookupToUnsigned("vernier_offset", i); + cfg->dll_control[i] = lookupToUnsigned("dll_control", i); + cfg->dead_time[i] = lookupToUnsigned("dead_time", i); + cfg->test_invert[i] = lookupToUnsigned("test_invert", i); + cfg->test_mode[i] = lookupToUnsigned("test_mode", i); + cfg->enable_trailing[i] = lookupToUnsigned("enable_trailing", i); + cfg->enable_leading[i] = lookupToUnsigned("enable_leading", i); + cfg->mode_rc_compression[i] = lookupToUnsigned("mode_rc_compression", i); + cfg->mode_rc[i] = lookupToUnsigned("mode_rc", i); + cfg->dll_mode[i] = lookupToUnsigned("dll_mode", i); + cfg->pll_control[i] = lookupToUnsigned("pll_control", i); + cfg->serial_clock_delay[i] = lookupToUnsigned("serial_clock_delay", i); + cfg->io_clock_delay[i] = lookupToUnsigned("io_clock_delay", i); + cfg->core_clock_delay[i] = lookupToUnsigned("core_clock_delay", i); + cfg->dll_clock_delay[i] = lookupToUnsigned("dll_clock_delay", i); + cfg->serial_clock_source[i] = lookupToUnsigned("serial_clock_source", i); + cfg->io_clock_source[i] = lookupToUnsigned("io_clock_source", i); + cfg->core_clock_source[i] = lookupToUnsigned("core_clock_source", i); + cfg->dll_clock_source[i] = lookupToUnsigned("dll_clock_source", i); + cfg->roll_over[i] = lookupToUnsigned("roll_over", i, 1); + cfg->enable_matching[i] = lookupToUnsigned("enable_matching", i); + cfg->enable_pair[i] = lookupToUnsigned("enable_pair", i); + cfg->enable_ttl_serial[i] = lookupToUnsigned("enable_ttl_serial", i); + cfg->enable_ttl_control[i] = lookupToUnsigned("enable_ttl_control", i); + cfg->enable_ttl_reset[i] = lookupToUnsigned("enable_ttl_reset", i); + cfg->enable_ttl_clock[i] = lookupToUnsigned("enable_ttl_clock", i); + cfg->enable_ttl_hit[i] = lookupToUnsigned("enable_ttl_hit", i); + } + for(int i=0;i<12;i++){ + setupCalib(cfg->calib, "Inl", 0, i); + setupCalib(cfg->calib, "Dnl", 1, i); + } + delete m_moduleCfgFile; +} + +void AFPHPTDCConfigFile::dump(const ipc::AFPHPTDCModuleConfig *cfg){ +std::cout<<"FPGA Register Fields:"<<std::endl; +std::cout<<"====================="<<std::endl; +std::cout<<"idStr "<<cfg->idStr<<std::endl; +std::cout<<"test "<<(unsigned)cfg->test<<std::endl; +std::cout<<"tdcControl "<<(unsigned)cfg->tdcControl<<std::endl; +std::cout<<"run "<<(unsigned)cfg->run<<std::endl; +std::cout<<"bypassLut "<<(unsigned)cfg->bypassLut<<std::endl; +std::cout<<"localClockEn "<<(unsigned)cfg->localClockEn<<std::endl; +std::cout<<"calClockEn "<<(unsigned)cfg->calClockEn<<std::endl; +std::cout<<"refEn "<<(unsigned)cfg->refEn<<std::endl; +std::cout<<"hitTestEn "<<(unsigned)cfg->hitTestEn<<std::endl; +std::cout<<"inputSel "<<(unsigned)cfg->inputSel<<std::endl; +std::cout<<"address "<<(unsigned)cfg->address<<std::endl; +std::cout<<"fanspeed "<<(unsigned)cfg->fanspeed<<std::endl<<std::endl; +std::cout<<"channelEn "<<(unsigned)cfg->channelEn<<std::endl<<std::endl; + +std::cout<<"TDC Configuration Fields:"<<std::endl; +std::cout<<"========================="<<std::endl; +for(int i=0;i<2;i++){ + std::cout<<"test_select "<<(unsigned)cfg->test_select[0]<<" "<<(unsigned)cfg->test_select[1]<<" "<<(unsigned)cfg->test_select[2]<<std::endl; + std::cout<<"enable_error_mark "<<(unsigned)cfg->enable_error_mark[0]<<" "<<(unsigned)cfg->enable_error_mark[1]<<" "<<(unsigned)cfg->enable_error_mark[2]<<std::endl; + std::cout<<"enable_error_bypass "<<(unsigned)cfg->enable_error_bypass[0]<<" "<<(unsigned)cfg->enable_error_bypass[1]<<" "<<(unsigned)cfg->enable_error_bypass[2]<<std::endl; + std::cout<<"enable_error "<<(unsigned)cfg->enable_error[0]<<" "<<(unsigned)cfg->enable_error[1]<<" "<<(unsigned)cfg->enable_error[2]<<std::endl; + std::cout<<"readout_single_cycle_speed "<<(unsigned)cfg->readout_single_cycle_speed[0]<<" "<<(unsigned)cfg->readout_single_cycle_speed[1]<<" "<<(unsigned)cfg->readout_single_cycle_speed[2]<<std::endl; + std::cout<<"serial_delay "<<(unsigned)cfg->serial_delay[0]<<" "<<(unsigned)cfg->serial_delay[1]<<" "<<(unsigned)cfg->serial_delay[2]<<std::endl; + std::cout<<"strobe_select "<<(unsigned)cfg->strobe_select[0]<<" "<<(unsigned)cfg->strobe_select[1]<<" "<<(unsigned)cfg->strobe_select[2]<<std::endl; + std::cout<<"readout_speed_select "<<(unsigned)cfg->readout_speed_select[0]<<" "<<(unsigned)cfg->readout_speed_select[1]<<" "<<(unsigned)cfg->readout_speed_select[2]<<std::endl; + std::cout<<"token_delay "<<(unsigned)cfg->token_delay[0]<<" "<<(unsigned)cfg->token_delay[1]<<" "<<(unsigned)cfg->token_delay[2]<<std::endl; + std::cout<<"enable_local_trailer "<<(unsigned)cfg->enable_local_trailer[0]<<" "<<(unsigned)cfg->enable_local_trailer[1]<<" "<<(unsigned)cfg->enable_local_trailer[2]<<std::endl; + std::cout<<"enable_local_header "<<(unsigned)cfg->enable_local_header[0]<<" "<<(unsigned)cfg->enable_local_header[1]<<" "<<(unsigned)cfg->enable_local_header[2]<<std::endl; + std::cout<<"enable_global_trailer "<<(unsigned)cfg->enable_global_trailer[0]<<" "<<(unsigned)cfg->enable_global_trailer[1]<<" "<<(unsigned)cfg->enable_global_trailer[2]<<std::endl; + std::cout<<"enable_global_header "<<(unsigned)cfg->enable_global_header[0]<<" "<<(unsigned)cfg->enable_global_header[1]<<" "<<(unsigned)cfg->enable_global_header[2]<<std::endl; + std::cout<<"keep_token "<<(unsigned)cfg->keep_token[0]<<" "<<(unsigned)cfg->keep_token[1]<<" "<<(unsigned)cfg->keep_token[2]<<std::endl; + std::cout<<"master "<<(unsigned)cfg->master[0]<<" "<<(unsigned)cfg->master[1]<<" "<<(unsigned)cfg->master[2]<<std::endl; + std::cout<<"enable_bytewise "<<(unsigned)cfg->enable_bytewise[0]<<" "<<(unsigned)cfg->enable_bytewise[1]<<" "<<(unsigned)cfg->enable_bytewise[2]<<std::endl; + std::cout<<"enable_serial "<<(unsigned)cfg->enable_serial[0]<<" "<<(unsigned)cfg->enable_serial[1]<<" "<<(unsigned)cfg->enable_serial[2]<<std::endl; + std::cout<<"enable_jtag_readout "<<(unsigned)cfg->enable_jtag_readout[0]<<" "<<(unsigned)cfg->enable_jtag_readout[1]<<" "<<(unsigned)cfg->enable_jtag_readout[2]<<std::endl; + std::cout<<"tdc_id "<<(unsigned)cfg->tdc_id[0]<<" "<<(unsigned)cfg->tdc_id[1]<<" "<<(unsigned)cfg->tdc_id[2]<<std::endl; + std::cout<<"select_bypass_inputs "<<(unsigned)cfg->select_bypass_inputs[0]<<" "<<(unsigned)cfg->select_bypass_inputs[1]<<" "<<(unsigned)cfg->select_bypass_inputs[2]<<std::endl; + std::cout<<"readout_fifo_size "<<(unsigned)cfg->readout_fifo_size[0]<<" "<<(unsigned)cfg->readout_fifo_size[1]<<" "<<(unsigned)cfg->readout_fifo_size[2]<<std::endl; + std::cout<<"reject_count_offset "<<(unsigned)cfg->reject_count_offset[0]<<" "<<(unsigned)cfg->reject_count_offset[1]<<" "<<(unsigned)cfg->reject_count_offset[2]<<std::endl; + std::cout<<"search_window "<<(unsigned)cfg->search_window[0]<<" "<<(unsigned)cfg->search_window[1]<<" "<<(unsigned)cfg->search_window[2]<<std::endl; + std::cout<<"match_window "<<(unsigned)cfg->match_window[0]<<" "<<(unsigned)cfg->match_window[1]<<" "<<(unsigned)cfg->match_window[2]<<std::endl; + std::cout<<"leading_resolution "<<(unsigned)cfg->leading_resolution[0]<<" "<<(unsigned)cfg->leading_resolution[1]<<" "<<(unsigned)cfg->leading_resolution[2]<<std::endl; + std::cout<<"fixed_pattern "<<(unsigned)cfg->fixed_pattern[0]<<" "<<(unsigned)cfg->fixed_pattern[1]<<" "<<(unsigned)cfg->fixed_pattern[2]<<std::endl; + std::cout<<"enable_fixed_pattern "<<(unsigned)cfg->enable_fixed_pattern[0]<<" "<<(unsigned)cfg->enable_fixed_pattern[1]<<" "<<(unsigned)cfg->enable_fixed_pattern[2]<<std::endl; + std::cout<<"max_event_size "<<(unsigned)cfg->max_event_size[0]<<" "<<(unsigned)cfg->max_event_size[1]<<" "<<(unsigned)cfg->max_event_size[2]<<std::endl; + std::cout<<"reject_readout_fifo_full "<<(unsigned)cfg->reject_readout_fifo_full[0]<<" "<<(unsigned)cfg->reject_readout_fifo_full[1]<<" "<<(unsigned)cfg->reject_readout_fifo_full[2]<<std::endl; + std::cout<<"enable_readout_occupancy "<<(unsigned)cfg->enable_readout_occupancy[0]<<" "<<(unsigned)cfg->enable_readout_occupancy[1]<<" "<<(unsigned)cfg->enable_readout_occupancy[2]<<std::endl; + std::cout<<"enable_readout_separator "<<(unsigned)cfg->enable_readout_separator[0]<<" "<<(unsigned)cfg->enable_readout_separator[1]<<" "<<(unsigned)cfg->enable_readout_separator[2]<<std::endl; + std::cout<<"enable_overflow_detect "<<(unsigned)cfg->enable_overflow_detect[0]<<" "<<(unsigned)cfg->enable_overflow_detect[1]<<" "<<(unsigned)cfg->enable_overflow_detect[2]<<std::endl; + std::cout<<"enable_relative "<<(unsigned)cfg->enable_relative[0]<<" "<<(unsigned)cfg->enable_relative[1]<<" "<<(unsigned)cfg->enable_relative[2]<<std::endl; + std::cout<<"enable_automatic_reject "<<(unsigned)cfg->enable_automatic_reject[0]<<" "<<(unsigned)cfg->enable_automatic_reject[1]<<" "<<(unsigned)cfg->enable_automatic_reject[2]<<std::endl; + std::cout<<"event_count_offset "<<(unsigned)cfg->event_count_offset[0]<<" "<<(unsigned)cfg->event_count_offset[1]<<" "<<(unsigned)cfg->event_count_offset[2]<<std::endl; + std::cout<<"trigger_count_offset "<<(unsigned)cfg->trigger_count_offset[0]<<" "<<(unsigned)cfg->trigger_count_offset[1]<<" "<<(unsigned)cfg->trigger_count_offset[2]<<std::endl; + std::cout<<"enable_set_counters_on_bunch_reset "<<(unsigned)cfg->enable_set_counters_on_bunch_reset[0]<<" "<<(unsigned)cfg->enable_set_counters_on_bunch_reset[1]<<" "<<(unsigned)cfg->enable_set_counters_on_bunch_reset[2]<<std::endl; + std::cout<<"enable_master_reset_code "<<(unsigned)cfg->enable_master_reset_code[0]<<" "<<(unsigned)cfg->enable_master_reset_code[1]<<" "<<(unsigned)cfg->enable_master_reset_code[2]<<std::endl; + std::cout<<"enable_master_reset_code_on_event_reset "<<(unsigned)cfg->enable_master_reset_code_on_event_reset[0]<<" "<<(unsigned)cfg->enable_master_reset_code_on_event_reset[1]<<" "<<(unsigned)cfg->enable_master_reset_code_on_event_reset[2]<<std::endl; + std::cout<<"enable_reset_channel_buffer_when_separator "<<(unsigned)cfg->enable_reset_channel_buffer_when_separator[0]<<" "<<(unsigned)cfg->enable_reset_channel_buffer_when_separator[1]<<" "<<(unsigned)cfg->enable_reset_channel_buffer_when_separator[2]<<std::endl; + std::cout<<"enable_separator_on_event_reset "<<(unsigned)cfg->enable_separator_on_event_reset[0]<<" "<<(unsigned)cfg->enable_separator_on_event_reset[1]<<" "<<(unsigned)cfg->enable_separator_on_event_reset[2]<<std::endl; + std::cout<<"enable_separator_on_bunch_reset "<<(unsigned)cfg->enable_separator_on_bunch_reset[0]<<" "<<(unsigned)cfg->enable_separator_on_bunch_reset[1]<<" "<<(unsigned)cfg->enable_separator_on_bunch_reset[2]<<std::endl; + std::cout<<"enable_direct_event_reset "<<(unsigned)cfg->enable_direct_event_reset[0]<<" "<<(unsigned)cfg->enable_direct_event_reset[1]<<" "<<(unsigned)cfg->enable_direct_event_reset[2]<<std::endl; + std::cout<<"enable_direct_bunch_reset "<<(unsigned)cfg->enable_direct_bunch_reset[0]<<" "<<(unsigned)cfg->enable_direct_bunch_reset[1]<<" "<<(unsigned)cfg->enable_direct_bunch_reset[2]<<std::endl; + std::cout<<"enable_direct_trigger "<<(unsigned)cfg->enable_direct_trigger[0]<<" "<<(unsigned)cfg->enable_direct_trigger[1]<<" "<<(unsigned)cfg->enable_direct_trigger[2]<<std::endl; + for(int j=31;j>=0;j--){ + std::cout<<"offset"<<j<<" "<<(unsigned)cfg->offset[j][0]<<" "<<(unsigned)cfg->offset[j][1]<<" "<<(unsigned)cfg->offset[j][2]<<std::endl; + } + std::cout<<"coarse_count_offset "<<(unsigned)cfg->coarse_count_offset[0]<<" "<<(unsigned)cfg->coarse_count_offset[1]<<" "<<(unsigned)cfg->coarse_count_offset[2]<<std::endl; + std::cout<<"dll_tap_adjust3_0 "<<(unsigned)cfg->dll_tap_adjust3_0[0]<<" "<<(unsigned)cfg->dll_tap_adjust3_0[1]<<" "<<(unsigned)cfg->dll_tap_adjust3_0[2]<<std::endl; + std::cout<<"dll_tap_adjust7_4 "<<(unsigned)cfg->dll_tap_adjust7_4[0]<<" "<<(unsigned)cfg->dll_tap_adjust7_4[1]<<" "<<(unsigned)cfg->dll_tap_adjust7_4[2]<<std::endl; + std::cout<<"dll_tap_adjust11_8 "<<(unsigned)cfg->dll_tap_adjust11_8[0]<<" "<<(unsigned)cfg->dll_tap_adjust11_8[1]<<" "<<(unsigned)cfg->dll_tap_adjust11_8[2]<<std::endl; + std::cout<<"dll_tap_adjust15_12 "<<(unsigned)cfg->dll_tap_adjust15_12[0]<<" "<<(unsigned)cfg->dll_tap_adjust15_12[1]<<" "<<(unsigned)cfg->dll_tap_adjust15_12[2]<<std::endl; + std::cout<<"dll_tap_adjust19_16 "<<(unsigned)cfg->dll_tap_adjust19_16[0]<<" "<<(unsigned)cfg->dll_tap_adjust19_16[1]<<" "<<(unsigned)cfg->dll_tap_adjust19_16[2]<<std::endl; + std::cout<<"dll_tap_adjust23_20 "<<(unsigned)cfg->dll_tap_adjust23_20[0]<<" "<<(unsigned)cfg->dll_tap_adjust23_20[1]<<" "<<(unsigned)cfg->dll_tap_adjust23_20[2]<<std::endl; + std::cout<<"dll_tap_adjust27_24 "<<(unsigned)cfg->dll_tap_adjust27_24[0]<<" "<<(unsigned)cfg->dll_tap_adjust27_24[1]<<" "<<(unsigned)cfg->dll_tap_adjust27_24[2]<<std::endl; + std::cout<<"dll_tap_adjust31_28 "<<(unsigned)cfg->dll_tap_adjust31_28[0]<<" "<<(unsigned)cfg->dll_tap_adjust31_28[1]<<" "<<(unsigned)cfg->dll_tap_adjust31_28[2]<<std::endl; + std::cout<<"rc_adjust "<<(unsigned)cfg->rc_adjust[0]<<" "<<(unsigned)cfg->rc_adjust[1]<<" "<<(unsigned)cfg->rc_adjust[2]<<std::endl; + std::cout<<"not_used "<<(unsigned)cfg->not_used[0]<<" "<<(unsigned)cfg->not_used[1]<<" "<<(unsigned)cfg->not_used[2]<<std::endl; + std::cout<<"low_power_mode "<<(unsigned)cfg->low_power_mode[0]<<" "<<(unsigned)cfg->low_power_mode[1]<<" "<<(unsigned)cfg->low_power_mode[2]<<std::endl; + std::cout<<"width_select "<<(unsigned)cfg->width_select[0]<<" "<<(unsigned)cfg->width_select[1]<<" "<<(unsigned)cfg->width_select[2]<<std::endl; + std::cout<<"vernier_offset "<<(unsigned)cfg->vernier_offset[0]<<" "<<(unsigned)cfg->vernier_offset[1]<<" "<<(unsigned)cfg->vernier_offset[2]<<std::endl; + std::cout<<"dll_control "<<(unsigned)cfg->dll_control[0]<<" "<<(unsigned)cfg->dll_control[1]<<" "<<(unsigned)cfg->dll_control[2]<<std::endl; + std::cout<<"dead_time "<<(unsigned)cfg->dead_time[0]<<" "<<(unsigned)cfg->dead_time[1]<<" "<<(unsigned)cfg->dead_time[2]<<std::endl; + std::cout<<"test_invert "<<(unsigned)cfg->test_invert[0]<<" "<<(unsigned)cfg->test_invert[1]<<" "<<(unsigned)cfg->test_invert[2]<<std::endl; + std::cout<<"test_mode "<<(unsigned)cfg->test_mode[0]<<" "<<(unsigned)cfg->test_mode[1]<<" "<<(unsigned)cfg->test_mode[2]<<std::endl; + std::cout<<"enable_trailing "<<(unsigned)cfg->enable_trailing[0]<<" "<<(unsigned)cfg->enable_trailing[1]<<" "<<(unsigned)cfg->enable_trailing[2]<<std::endl; + std::cout<<"enable_leading "<<(unsigned)cfg->enable_leading[0]<<" "<<(unsigned)cfg->enable_leading[1]<<" "<<(unsigned)cfg->enable_leading[2]<<std::endl; + std::cout<<"mode_rc_compression "<<(unsigned)cfg->mode_rc_compression[0]<<" "<<(unsigned)cfg->mode_rc_compression[1]<<" "<<(unsigned)cfg->mode_rc_compression[2]<<std::endl; + std::cout<<"mode_rc "<<(unsigned)cfg->mode_rc[0]<<" "<<(unsigned)cfg->mode_rc[1]<<" "<<(unsigned)cfg->mode_rc[2]<<std::endl; + std::cout<<"dll_mode "<<(unsigned)cfg->dll_mode[0]<<" "<<(unsigned)cfg->dll_mode[1]<<" "<<(unsigned)cfg->dll_mode[2]<<std::endl; + std::cout<<"pll_control "<<(unsigned)cfg->pll_control[0]<<" "<<(unsigned)cfg->pll_control[1]<<" "<<(unsigned)cfg->pll_control[2]<<std::endl; + std::cout<<"serial_clock_delay "<<(unsigned)cfg->serial_clock_delay[0]<<" "<<(unsigned)cfg->serial_clock_delay[1]<<" "<<(unsigned)cfg->serial_clock_delay[2]<<std::endl; + std::cout<<"io_clock_delay "<<(unsigned)cfg->io_clock_delay[0]<<" "<<(unsigned)cfg->io_clock_delay[1]<<" "<<(unsigned)cfg->io_clock_delay[2]<<std::endl; + std::cout<<"core_clock_delay "<<(unsigned)cfg->core_clock_delay[0]<<" "<<(unsigned)cfg->core_clock_delay[1]<<" "<<(unsigned)cfg->core_clock_delay[2]<<std::endl; + std::cout<<"dll_clock_delay "<<(unsigned)cfg->dll_clock_delay[0]<<" "<<(unsigned)cfg->dll_clock_delay[1]<<" "<<(unsigned)cfg->dll_clock_delay[2]<<std::endl; + std::cout<<"serial_clock_source "<<(unsigned)cfg->serial_clock_source[0]<<" "<<(unsigned)cfg->serial_clock_source[1]<<" "<<(unsigned)cfg->serial_clock_source[2]<<std::endl; + std::cout<<"io_clock_source "<<(unsigned)cfg->io_clock_source[0]<<" "<<(unsigned)cfg->io_clock_source[1]<<" "<<(unsigned)cfg->io_clock_source[2]<<std::endl; + std::cout<<"core_clock_source "<<(unsigned)cfg->core_clock_source[0]<<" "<<(unsigned)cfg->core_clock_source[1]<<" "<<(unsigned)cfg->core_clock_source[2]<<std::endl; + std::cout<<"dll_clock_source "<<(unsigned)cfg->dll_clock_source[0]<<" "<<(unsigned)cfg->dll_clock_source[1]<<" "<<(unsigned)cfg->dll_clock_source[2]<<std::endl; + std::cout<<"roll_over "<<(unsigned)cfg->roll_over[0]<<" "<<(unsigned)cfg->roll_over[1]<<" "<<(unsigned)cfg->roll_over[2]<<std::endl; + std::cout<<"enable_matching "<<(unsigned)cfg->enable_matching[0]<<" "<<(unsigned)cfg->enable_matching[1]<<" "<<(unsigned)cfg->enable_matching[2]<<std::endl; + std::cout<<"enable_pair "<<(unsigned)cfg->enable_pair[0]<<" "<<(unsigned)cfg->enable_pair[1]<<" "<<(unsigned)cfg->enable_pair[2]<<std::endl; + std::cout<<"enable_ttl_serial "<<(unsigned)cfg->enable_ttl_serial[0]<<" "<<(unsigned)cfg->enable_ttl_serial[1]<<" "<<(unsigned)cfg->enable_ttl_serial[2]<<std::endl; + std::cout<<"enable_ttl_control "<<(unsigned)cfg->enable_ttl_control[0]<<" "<<(unsigned)cfg->enable_ttl_control[1]<<" "<<(unsigned)cfg->enable_ttl_control[2]<<std::endl; + std::cout<<"enable_ttl_reset "<<(unsigned)cfg->enable_ttl_reset[0]<<" "<<(unsigned)cfg->enable_ttl_reset[1]<<" "<<(unsigned)cfg->enable_ttl_reset[2]<<std::endl; + std::cout<<"enable_ttl_clock "<<(unsigned)cfg->enable_ttl_clock[0]<<" "<<(unsigned)cfg->enable_ttl_clock[1]<<" "<<(unsigned)cfg->enable_ttl_clock[2]<<std::endl; + std::cout<<"enable_ttl_hit "<<(unsigned)cfg->enable_ttl_hit[0]<<" "<<(unsigned)cfg->enable_ttl_hit[1]<<" "<<(unsigned)cfg->enable_ttl_hit[2]<<std::endl; +} + + //Calibrations + std::cout<<"Calibration constants"<<std::endl; + std::cout<<"---------------------"<<std::endl; + for (int i=0;i<12;i++){ + std::cout<<"Inl_"<<i<<" "; + dumpCalib(cfg->calib, 0, i); + } + for (int i=0;i<12;i++){ + std::cout<<"Dnl_"<<i<<" "; + dumpCalib(cfg->calib, 1, i); + } + +} + +void AFPHPTDCConfigFile::dumpCalib(const float cal[2][12][ipc::IPC_N_CALIBVALS], int i1, int i2){ + std::cout<<cal[i1][i2][0]<<" ... "<<(unsigned)cal[i1][i2][ipc::IPC_N_CALIBVALS-1]<<std::endl; +} + diff --git a/rce/rcecalib/server/AFPHPTDCConfigFile.hh b/rce/rcecalib/server/AFPHPTDCConfigFile.hh new file mode 100644 index 00000000..ab35a0a6 --- /dev/null +++ b/rce/rcecalib/server/AFPHPTDCConfigFile.hh @@ -0,0 +1,30 @@ +#ifndef AFPHPTDCCONFIGFILE_HH +#define AFPHPTDCCONFIGFILE_HH + +#include "AFPHPTDCModuleConfig.hh" +#include <string> +#include <map> +#include <vector> + +class AFPHPTDCConfigFile { +public: + AFPHPTDCConfigFile(){} + ~AFPHPTDCConfigFile(); + void readModuleConfig(ipc::AFPHPTDCModuleConfig* cfg, std::string filename); + void writeModuleConfig(ipc::AFPHPTDCModuleConfig* cfg, const std::string &base, const std::string &confdir, const std::string &configname, const std::string &key); + void writeCalibFile(float cal[2][12][ipc::IPC_N_CALIBVALS] , const std::string filename, int, int); + void dump(const ipc::AFPHPTDCModuleConfig *cfg); +private: + std::string getFullPath(std::string relPath); + void setupCalib(float cal[2][12][ipc::IPC_N_CALIBVALS] , std::string par, int i1, int i2); + unsigned lookupToUnsigned(std::string par, int index, int size=0); + int convertToUnsigned(std::string par, unsigned & val, int size); + //float lookupToFloat(std::string par); + void dumpCalib(const float cal[2][12][ipc::IPC_N_CALIBVALS], int i1, int i2); + + std::string m_moduleCfgFilePath; + std::ifstream *m_moduleCfgFile; + std::map<std::string, std::vector<std::string> > m_params; +}; + +#endif diff --git a/rce/rcecalib/server/BootLoaderPort.hh b/rce/rcecalib/server/BootLoaderPort.hh new file mode 100644 index 00000000..2332728a --- /dev/null +++ b/rce/rcecalib/server/BootLoaderPort.hh @@ -0,0 +1,6 @@ +#ifndef BOOTLOADERPORT_HH +#define BOOTLOADERPORT_HH + +const unsigned short BootloaderPort = 1350; + +#endif diff --git a/rce/rcecalib/server/CalibGui.cc b/rce/rcecalib/server/CalibGui.cc new file mode 100644 index 00000000..eeb0831e --- /dev/null +++ b/rce/rcecalib/server/CalibGui.cc @@ -0,0 +1,1856 @@ +#include <ipc/partition.h> +#include <ipc/core.h> +#include "rcecalib/server/FEI4AConfigFile.hh" +#include "rcecalib/server/PixScan.hh" +#include "rcecalib/server/CalibGui.hh" +#include "rcecalib/server/PrimListGui.hh" +#include "rcecalib/server/PrimList.hh" +#include "rcecalib/server/ScanGui.hh" +#include "rcecalib/server/IPCController.hh" +#include "rcecalib/server/IPCHistoController.hh" +#include "rcecalib/server/IPCGuiCallback.hh" +#include "rcecalib/analysis/CalibAnalysis.hh" +#include "rcecalib/analysis/AnalysisFactory.hh" +#include "rcecalib/server/DataExporter.hh" +#include "rcecalib/server/ScanLog.hh" +#include "rcecalib/util/VerifyErrors.hh" +#include "server/CallbackInfo.hh" + +//#include "rcecalib/server/atlasimage.hh" +#include "ScanOptions.hh" +#include "TApplication.h" +#include "TGMsgBox.h" +#include "TGIcon.h" +#include "TGTab.h" +#include "TGMenu.h" +#include "TCanvas.h" +#include "TGCanvas.h" +#include "TGListTree.h" +#include "TRootEmbeddedCanvas.h" +#include <TGFileDialog.h> +#include <TROOT.h> +#include <TH2F.h> +#include <TStyle.h> +#include <cmdl/cmdargs.h> +#include <boost/regex.hpp> +#include <iostream> +#include <time.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <fstream> +#include <list> +#include <pthread.h> +#include <time.h> + +#include <is/infoT.h> +#include <is/infodictionary.h> + +using namespace RCE; + + + + +void* CalibGui::runloop( void *ptr ){ + CalibGui* calibGui=(CalibGui*)ptr; + calibGui->runloop(); + return 0; +} + + +void CalibGui::runloop(){ +//Execute shell script before scan, if available +if(m_primList->isLoaded() && m_primList->getCurrentPreScript().compare("") != 0) +{ + std::string script = m_primList->getCurrentPreScript(); + if(script.find("RUNNUM")!=(unsigned)-1)script.replace(script.find("RUNNUM"), 6, + Form("%06d", m_globalconf->getRunNumber())); + + char directory[512]; + getcwd(directory,512); + int retval=system(script.c_str()); + chdir(directory); + if(retval!=0){ + std::cout<<"****Script "<<script<<" failed. Aborting run."<<std::endl; + m_primList->setFailed(true); + stopRun(); + return; + } + +} + ipc::ScanOptions *options; + PixScan *pixscan=currentScan(); + options=currentScanConfig(); + std::vector<float>loop1vals=pixscan->getLoopVarValues(1); + std::vector<float>loop2vals=pixscan->getLoopVarValues(2); + size_t loopsize1=loop1vals.size(); + size_t loopsize2=loop2vals.size(); + //even if the loops don't exist we have to run through once + if(pixscan->getLoopActive(1)==false || pixscan->getDspProcessing(1)==true)loopsize1=1; + if(pixscan->getLoopActive(2)==false || pixscan->getDspProcessing(2)==true)loopsize2=1; + char txt[128]; + TGListTreeItem* root=m_tree->FindChildByName(0,"Histos"); + TGListTreeItem *current1=0, *current2; + TGListTreeItem *old1; + old1=0; + m_dir=""; + current2=0; + std::string dir2=""; + PixLib::EnumScanParam parlist; + + for(size_t i=0;i<loopsize2;i++){ + m_nLoop2->SetText(i); + if(pixscan->getDspProcessing(2)==false && pixscan->getLoopActive(2)==true){ + sprintf(txt, "loop2_%d",i); + if(saveChecked()){ + m_file->cd(); + m_file->mkdir(txt,"Loop 2 directory"); + dir2=txt; + } + current2=m_tree->AddItem(root,txt); + updateTree(); + }else{ + current2=root; + } + for(size_t j=0;j<loopsize1;j++){ + m_nLoop1->SetText(j); + if(pixscan->getDspProcessing(1)==false && pixscan->getLoopActive(1)==true){ + sprintf(txt, "loop1_%d",j); + if(saveChecked()){ + m_file->cd(dir2.c_str()); + gDirectory->mkdir(txt,"Loop 1 directory"); + if(dir2!="") m_dir=dir2+"/"+txt; + else m_dir=txt; + } + if(j!=0 || i!=0)old1=current1; + current1=m_tree->AddItem(current2,txt); + updateTree(); + }else{ + current1=current2; + } + + m_controller.downloadScanConfig(*options); + if(pixscan->getDspProcessing(2)==false && pixscan->getLoopActive(2)==true){ + loopAction(2, i); + m_controller.setupParameter(parlist.lookup(pixscan->getLoopParam(2)).c_str(), (int)loop2vals[i]); + } + if(pixscan->getDspProcessing(1)==false && pixscan->getLoopActive(1)==true){ + loopAction(1, j); + m_controller.setupParameter(parlist.lookup(pixscan->getLoopParam(1)).c_str(), (int)loop1vals[j]); + } + m_cb=new IPCGuiCallback(m_cbinfo); + + runScan(pixscan->getCallbackPriority()); + if(m_cbinfo->failed()){ //Scan failed + m_status=FAILED; + m_primList->setFailed(true); + stopRun(); + return; + } + if(saveChecked()){ + + m_timers->Stop(); //TFile->Write() crashes sometimes when the timer is running + saveHistos(); + m_timers->Start(); + } + if(old1!=0 && saveChecked()==false){ + m_tree->DeleteChildren(old1); + updateTree(); + } + fillHistoTree(current1); + updateTree(); + if(m_primList->isLoaded() && m_primList->getCurrentPostScript().compare("") != 0) + { + std::string script = m_primList->getCurrentPostScript(); + if(script.find("RUNNUM")!=(unsigned)-1)script.replace(script.find("RUNNUM"), 6, + Form("%06d", m_globalconf->getRunNumber())); + int retval=system(script.c_str()); + if(retval!=0){ + std::cout<<"****Script "<<script<<" failed. Aborting run."<<std::endl; + m_primList->setFailed(true); + stopRun(); + return; + } + } + if(m_isrunning==false){ //Scan was aborted + m_primList->setFailed(true); + stopRun(); + return; + } + } + } + if(currentScan()->verifyConfig()==true)verifyConfiguration(); + if(saveChecked()&&std::string(pixscan->getAnalysisType())!="NONE"){ + m_file->ReOpen("read"); //re-open file for reading + analyze(); + } + if(exportChecked()){ + m_file->ReOpen("read"); //re-open file for reading + std::string topconfigname=m_globalconf->getConfigName()+".cfg"; + m_dataExporter->exportData(m_exportdir, topconfigname, m_rcdir, m_file, m_anfile); + } + //End of successful run loop + if(m_primList->isLoaded())//Running primlist, so check and see if there is another item + EndOfPrimListScan(); + else //Using ScanGui, so stop run + stopRun(); + +} + +CalibGui::~CalibGui(){ + Cleanup(); + delete m_dataExporter; +} + +CalibGui::CalibGui(IPCPartition *partition, const TGWindow *p,UInt_t w,UInt_t h) + : TGMainFrame(p,w,h), m_partition(partition), m_controller(*new IPCController(*partition)), + m_hcontroller(*new IPCHistoController(*partition)), + m_histo(0), m_file(0), m_anfile(0), m_delhisto(false) { + // connect x icon on window manager + ISInfoDictionary dict(*partition); + ISInfoInt gui_running(0); + try{ + dict.getValue("RceIsServer.GUI_running", gui_running); + }catch(daq::is::RepositoryNotFound){ + std::cout<<"RceIsServer not running in the partition"<<std::endl; + exit(0); + }catch(daq::is::InfoNotFound){ + //std::cout<<"No entry for GUI_running"<<std::endl; + } + if (gui_running){ + int retcode; + char msg[512]; + sprintf(msg, "Another GUI is already running in partition %s. Continue?", m_partition->name().c_str()); + new TGMsgBox(gClient->GetRoot(), 0, "Attention", msg, + kMBIconExclamation, kMBYes | kMBCancel,&retcode); + if(retcode!=kMBYes){ + exit(0); + } + } + gui_running=1; + dict.checkin("RceIsServer.GUI_running", gui_running); + Connect("CloseWindow()","CalibGui",this,"quit()"); + + TGMenuBar *menubar=new TGMenuBar(this,1,1,kHorizontalFrame | kRaisedFrame); + TGLayoutHints *menubarlayout=new TGLayoutHints(kLHintsTop|kLHintsLeft,0,4,0,0); + // menu "File" + TGPopupMenu* filepopup=new TGPopupMenu(gClient->GetRoot()); + filepopup->AddEntry("&Load Config",LOAD); + filepopup->AddEntry("&Save Config",SAVE); + filepopup->AddSeparator(); + filepopup->AddEntry("&Quit",QUIT); + menubar->AddPopup("&File",filepopup,menubarlayout); + + filepopup->Connect("Activated(Int_t)","CalibGui",this,"handleFileMenu(Int_t)"); + + TGPopupMenu* plotpopup=new TGPopupMenu(gClient->GetRoot()); + plotpopup->AddEntry("&Save as gif",GIF); + plotpopup->AddEntry("&Savefd as pdf",PDF); + menubar->AddPopup("&Plot",plotpopup,menubarlayout); + + + plotpopup->Connect("Activated(Int_t)","CalibGui",this,"handlePlotMenu(Int_t)"); + + AddFrame(menubar, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 0,0,0,2)); + + //TGVerticalFrame* datapanel=new TGVerticalFrame(this,1,1, kSunkenFrame); + TGTab* fTab = new TGTab(this); + AddFrame(fTab,new TGLayoutHints(kLHintsExpandX|kLHintsExpandY )) ; + TGCompositeFrame *datapanelt1 = fTab->AddTab("Scan"); + TGCompositeFrame *datapanelt2 = fTab->AddTab("Config Halfstave A"); + TGCompositeFrame *datapanelt2b = fTab->AddTab("Config Halfstave C"); + TGCompositeFrame *datapanelt2x = fTab->AddTab("Config Halfstave A (2)"); + TGCompositeFrame *datapanelt2bx = fTab->AddTab("Config Halfstave C (2)"); + TGCompositeFrame *datapanelt3 = fTab->AddTab("Plots"); + TGVerticalFrame *scanpanel=new TGVerticalFrame(datapanelt1); + datapanelt1->AddFrame(scanpanel,new TGLayoutHints(kLHintsExpandX |kLHintsExpandY)); + + // TGVerticalFrame *primlistpanel = new TGVerticalFrame(datapanelt1); + // datapanelt1->AddFrame(primlistpanel, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY)); + + // scan panel + TGHorizontalFrame *datapanel1a = new TGHorizontalFrame(scanpanel, 2, 2, kSunkenFrame); + scanpanel->AddFrame(datapanel1a,new TGLayoutHints(kLHintsExpandX )); + m_datapaneldd = new TGHorizontalFrame(scanpanel, 2, 2, kSunkenFrame); + scanpanel->AddFrame(m_datapaneldd, new TGLayoutHints(kLHintsExpandX, 2, 2, 0, 10)); + TGHorizontalFrame *datapanel1 = new TGHorizontalFrame(scanpanel, 2, 2, kSunkenFrame); + scanpanel->AddFrame(datapanel1,new TGLayoutHints(kLHintsExpandX )); + TGHorizontalFrame *datapanel2aa = new TGHorizontalFrame(scanpanel, 2, 2, kSunkenFrame); + scanpanel->AddFrame(datapanel2aa,new TGLayoutHints(kLHintsExpandX )); + TGHorizontalFrame *fwpanel = new TGHorizontalFrame(scanpanel, 2, 2, kSunkenFrame); + scanpanel->AddFrame(fwpanel, new TGLayoutHints(kLHintsExpandX)); + TGHorizontalFrame *datapanel2a = new TGHorizontalFrame(scanpanel, 2, 2, kSunkenFrame); + scanpanel->AddFrame(datapanel2a,new TGLayoutHints(kLHintsExpandX )); + TGHorizontalFrame *datapanelprim = new TGHorizontalFrame(scanpanel, 2, 2, kSunkenFrame); + scanpanel->AddFrame(datapanelprim, new TGLayoutHints(kLHintsExpandX)); + TGHorizontalFrame *datapanel2 = new TGHorizontalFrame(scanpanel, 2, 2, kSunkenFrame); + scanpanel->AddFrame(datapanel2,new TGLayoutHints(kLHintsExpandX )); + TGHorizontalFrame *datapanel3 = new TGHorizontalFrame(scanpanel, 2, 2, kSunkenFrame); + scanpanel->AddFrame(datapanel3,new TGLayoutHints(kLHintsExpandX)); + TGVerticalFrame *datapanel4[4]; + datapanel4[0] = new TGVerticalFrame(datapanelt2, 2, 2, kSunkenFrame); + datapanelt2->AddFrame(datapanel4[0],new TGLayoutHints(kLHintsExpandX)); + datapanel4[1] = new TGVerticalFrame(datapanelt2b, 2, 2, kSunkenFrame); + datapanelt2b->AddFrame(datapanel4[1],new TGLayoutHints(kLHintsExpandX)); + datapanel4[2] = new TGVerticalFrame(datapanelt2x, 2, 2, kSunkenFrame); + datapanelt2x->AddFrame(datapanel4[2],new TGLayoutHints(kLHintsExpandX)); + datapanel4[3] = new TGVerticalFrame(datapanelt2bx, 2, 2, kSunkenFrame); + datapanelt2bx->AddFrame(datapanel4[3],new TGLayoutHints(kLHintsExpandX)); + TGHorizontalFrame *datapanel5 = new TGHorizontalFrame(datapanelt3, 2, 2, kSunkenFrame); + datapanelt3->AddFrame(datapanel5,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY)); + //AddFrame(datapanel,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY)); + m_scan=new ScanGui("Scan Config", datapanel1, 1, 1, kSunkenFrame); + datapanel1->AddFrame(m_scan,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY,2,2,0,0)); + + //HSIO Firmware + + TGTextButton *mddd=new TGTextButton(fwpanel,"Print HSIO Firmware Version"); + mddd->Connect("Clicked()", "CalibGui", this,"getFirm()"); //todo: find and print FW + fwpanel->AddFrame(mddd,new TGLayoutHints(kLHintsCenterY | kLHintsExpandX ,2,2,5,5)); + + //primList Panel + + m_primList = new PrimListGui("Prim List", datapanelprim, 1, 1, kSunkenFrame); + m_primList->setScanTypes(m_scan->getScanTypes()); + datapanelprim->AddFrame(m_primList, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY,2,2,0,0)); + m_globalconf=new GlobalConfigGui(m_config, ".calibDaq.rc",datapanel1a, 1, 1, kSunkenFrame); + datapanel1a->AddFrame(m_globalconf,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY,2,2,2,2)); + + int modperpanel=ConfigGui::MAX_MODULES/4; + const char* fenames[]={"A1-1", "A1-2", "A2-1", "A2-2", "A3-1", "A3-2", + "A4-1", "A4-2", "A5-1", "A5-2", "A6-1", "A6-2", + "A7-1", "A7-2", "A8-1", "A8-2", + "C1-1", "C1-2", "C2-1", "C2-2", "C3-1", "C3-2", + "C4-1", "C4-2", "C5-1", "C5-2", "C6-1", "C6-2", + "C7-1", "C7-2", "C8-1", "C8-2"}; + + for(int j=0;j<4;j++){ + TGHorizontalFrame *datapanelb=new TGHorizontalFrame(datapanel4[j]); + datapanel4[j]->AddFrame(datapanelb,new TGLayoutHints(kLHintsExpandX )); + TGTextButton *alloff=new TGTextButton(datapanelb,"All Off"); + alloff->SetMargins(15,25,0,0); + datapanelb->AddFrame(alloff,new TGLayoutHints(kLHintsCenterY | kLHintsLeft ,2,2,2,2)); + TGTextButton *allon=new TGTextButton(datapanelb,"All On"); + allon->SetMargins(15,25,0,0); + datapanelb->AddFrame(allon,new TGLayoutHints(kLHintsCenterY | kLHintsLeft ,2,2,2,2)); + if(j==0){ + alloff->Connect("Clicked()", "CalibGui", this,"allOffA()"); + allon->Connect("Clicked()", "CalibGui", this,"allOnA()"); + }else if(j==1){ + alloff->Connect("Clicked()", "CalibGui", this,"allOffC()"); + allon->Connect("Clicked()", "CalibGui", this,"allOnC()"); + }else if(j==2){ + alloff->Connect("Clicked()", "CalibGui", this,"allOffA2()"); + allon->Connect("Clicked()", "CalibGui", this,"allOnA2()"); + }else if(j==3){ + alloff->Connect("Clicked()", "CalibGui", this,"allOffC2()"); + allon->Connect("Clicked()", "CalibGui", this,"allOnC2()"); + } + TGHorizontalFrame *datapanelc[4]; + for(int i=0;i<4;i++){ + datapanelc[i] = new TGHorizontalFrame(datapanel4[j]); + datapanel4[j]->AddFrame(datapanelc[i],new TGLayoutHints(kLHintsExpandX |kLHintsExpandY)); + } + char modname[128]; + for (int i=0;i<modperpanel;i++){ + sprintf(modname, "%s", fenames[(j%2)*modperpanel+i]); + m_config[i+modperpanel*j]=new ConfigGui(modname, datapanelc[i/(modperpanel/4)],1,1, kSunkenFrame); + datapanelc[i/(modperpanel/4)]->AddFrame(m_config[i+modperpanel*j],new TGLayoutHints(kLHintsExpandX | kLHintsExpandY,2,2,1,1)); + } + } + m_nevt=0; + m_timers=new TTimer; + m_timers->Connect("Timeout()","CalibGui",this,"timeouts()"); + m_start=new TGTextButton(datapanel2,"Start Run"); + FontStruct_t labelfont; + labelfont = gClient->GetFontByName("-adobe-helvetica-medium-r-*-*-18-*-*-*-*-*-iso8859-1"); + m_start->SetFont(labelfont); + m_start->SetMargins(10,40,10,10); + datapanel2->AddFrame(m_start,new TGLayoutHints(kLHintsCenterY | kLHintsLeft ,5,5,5,5)); + m_start->Connect("Clicked()", "CalibGui", this, "toggle()"); + m_save=new TGCheckButton(datapanel2,"Analyze/Save Histos"); + m_save->SetOn(true); + m_save->Connect("Clicked()", "CalibGui", this, "clearTree()"); + m_save->Connect("Clicked()", "CalibGui", this, "synchSave2()"); + datapanel2->AddFrame(m_save,new TGLayoutHints(kLHintsCenterY | kLHintsLeft ,10,2,5,5)); + m_export=new TGCheckButton(datapanel2,"Export Data"); + m_export->SetOn(false); + m_export->Connect("Clicked()", "CalibGui", this, "synchSave1()"); + datapanel2->AddFrame(m_export,new TGLayoutHints(kLHintsCenterY |kLHintsLeft, 0, 2, 5, 5)); + m_debug=new TGCheckButton(datapanel2,"Debugging Run"); + m_debug->SetOn(false); + datapanel2->AddFrame(m_debug,new TGLayoutHints(kLHintsCenterY |kLHintsLeft, 0, 2, 5, 5)); + //TGTextButton *quit=new TGTextButton(datapanel2,"&Quit","gApplication->Terminate(0)"); + m_quit=new TGTextButton(datapanel2,"Quit"); + m_quit->Connect("Clicked()", "CalibGui", this,"quit()"); + m_quit->SetFont(labelfont); + m_quit->SetMargins(15,25,10,10); + datapanel2->AddFrame(m_quit,new TGLayoutHints(kLHintsCenterY | kLHintsRight ,2,2,5,5)); + + m_print=new TGTextButton(datapanel2aa,"Print Scan"); + datapanel2aa->AddFrame(m_print,new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX ,2,2,5,0)); + m_print->Connect("Clicked()", "CalibGui", this, "printFromGui()"); + + TGLabel *commentlabel=new TGLabel(datapanel2a,"Comment:"); + datapanel2a->AddFrame(commentlabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 10, 0)); + m_comment=new TGTextEntry(datapanel2a); + datapanel2a->AddFrame(m_comment,new TGLayoutHints(kLHintsLeft|kLHintsCenterY|kLHintsExpandX, 2, 2, 10, 0)); + + TGLabel *timelabel=new TGLabel(datapanel3,"Time:"); + datapanel3->AddFrame(timelabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 10, 0)); + m_time=new TGLabel(datapanel3,"0 s "); + datapanel3->AddFrame(m_time,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 30, 0, 0)); + m_time->SetTextFont(labelfont); + + TGLabel *nevlabel=new TGLabel(datapanel3,"Mask Stage:"); + datapanel3->AddFrame(nevlabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 10, 0)); + m_nEvents=new TGLabel(datapanel3,"0 "); + datapanel3->AddFrame(m_nEvents,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 30, 0, 0)); + m_nEvents->SetTextFont(labelfont); + m_cbinfo=new CallbackInfo(m_nEvents); + + nevlabel=new TGLabel(datapanel3,"Loop 1:"); + datapanel3->AddFrame(nevlabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 20, 2, 10, 0)); + m_nLoop1=new TGLabel(datapanel3,"0 "); + datapanel3->AddFrame(m_nLoop1,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 30, 0, 0)); + m_nLoop1->SetTextFont(labelfont); + + nevlabel=new TGLabel(datapanel3,"Loop 2:"); + datapanel3->AddFrame(nevlabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 20, 2, 10, 0)); + m_nLoop2=new TGLabel(datapanel3,"0 "); + datapanel3->AddFrame(m_nLoop2,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 30, 0, 0)); + m_nLoop2->SetTextFont(labelfont); + + TGVerticalFrame *treepanel = new TGVerticalFrame(datapanel5, 150, 2, kSunkenFrame); + datapanel5->AddFrame(treepanel,new TGLayoutHints(kLHintsExpandY)); + TGVerticalFrame *plotpanel = new TGVerticalFrame(datapanel5, 2, 2, kSunkenFrame); + datapanel5->AddFrame(plotpanel,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY)); + + + + m_tgc=new TGCanvas(treepanel, 300,100); + m_tree=new TGListTree(m_tgc, kHorizontalFrame); + m_tree->AddItem(0,"Histos"); + m_tree->Connect("Clicked(TGListTreeItem*, Int_t)","CalibGui", this, "displayHisto(TGListTreeItem*, Int_t)"); + treepanel->AddFrame(m_tgc,new TGLayoutHints(kLHintsExpandY)); + m_canvas=new TRootEmbeddedCanvas("Canvas",plotpanel,100,100); + m_canvas->GetCanvas()->GetPad(0)->SetRightMargin(0.15); + plotpanel->AddFrame(m_canvas,new TGLayoutHints(kLHintsExpandY|kLHintsExpandX)); + + m_dataExporter=new DataExporter(m_config); + m_homedir=getenv("HOME"); + m_homedir+="/"; + readGuiConfig((m_homedir+".calibDaq.rc").Data()); + m_scanLog=new ScanLog; + + m_thp = gClient->GetPicture("h1_t.xpm"); + + SetWindowName("Calibration GUI"); + Resize(w,h); + Layout(); + MapSubwindows(); + MapWindow(); +} +void CalibGui::toggle(){ + setRun(!running()); +} +void CalibGui::synchSave1(){ + if(m_export->IsOn()==true && m_save->IsOn()==false){ + m_save->SetOn(true); + } +} +void CalibGui::synchSave2(){ + if(m_export->IsOn()==true && m_save->IsOn()==false){ + m_export->SetOn(false); + } +} +void CalibGui::setRun(Bool_t on){ + + if (on){ + + //load new top config, change includes for primlist + if(m_primList->isLoaded()){ + for(int i=0;i<ConfigGui::MAX_MODULES;i++){ + m_config[i]->enableControls(true); + } + if(m_primList->getCurrentTopConfig()!=""){ + std::cout<<"Loading top config "<<m_primList->getCurrentTopConfig().c_str()<<std::endl; + m_globalconf->load(m_primList->getCurrentTopConfig().c_str()); + } + m_primList->changeIncludes(m_config); + } + enableControls(false); + m_globalconf->incrementRunNumber(); + m_globalconf->updateAvailable(false); + int ret=setupScan(); + if(ret==-1){ + enableControls(true); + return; + } + if(saveChecked()){ + int stat=openFile(); + if(stat){ + enableControls(true); + return; + } + } + if(m_primList->isLoaded())//set Primlist update info + { + + if(!m_globalconf->oldFileLoaded())//if no global conf loaded, prompt user where to save + { + m_globalconf->filePrompt(); + + } + if(!m_globalconf->oldFileLoaded())//file loading canceled or failed + { + setRun(false); + m_primList->updateStatus("PrimList will not run because no valid cfg directory chosen!"); + return; + } + else + { + std::stringstream buf; + buf << "Running " << m_primList->getCurrScanName() << " Scan (" << m_primList->currentScan + 1<< "/"<< m_primList->getNumScans() << ")" ; + m_primList->updateStatus(buf.str()); + m_primList->setFailed(false); + } + } + m_timers->Start(1000,kFALSE); // update every second + m_starttime.Set(); + m_nevt=0; + m_start->SetDown(true); + m_isrunning=true; + m_status=OK; + m_start->SetText("Running"); + m_cbinfo->clear(); + m_cbinfo->addToMask(CallbackInfo::RUNNING); + clearTree(); + startRun(); + } else{ + std::cout<<"Aborting Scan"<<std::endl; + m_controller.abortScan(); + m_isrunning=false; + m_controller.resetFE(); + /* + m_timers->Stop(); + m_start->SetDown(false); + m_start->SetText("Start Run"); + if(m_save->IsDisabledAndSelected()){ + m_file->ReOpen("read"); //re-open file for reading + } + enableControls(); + */ + + } +} +void CalibGui::stopRun(){ + m_comment->Clear(); + finishLogFile(); + //m_controller.sendHWcommand(0, 111); + m_controller.resetFE(); + if(saveChecked()){ + m_file->ReOpen("read"); //re-open file for reading + } + if(m_primList->isLoaded()) + { + std::stringstream buf; + if(m_primList->failed()){ + buf << "Primlist failed in scan "<<m_primList->currentScan +1<<". Aborted Run."<<std::endl; + }else{ + buf << "Finished running " << m_primList->getNumScans() << " scans! "; + } + m_primList->updateStatus(buf.str()); + } + m_primList->currentScan=0;//reset PrimList to beginning + m_timers->Stop(); + m_start->SetDown(false); + m_start->SetText("Start Run"); + m_isrunning=false; + m_cbinfo->addToMask(CallbackInfo::DONE); + m_cbinfo->updateGui(); + enableControls(true); + std::cout<<"Done"<<std::endl; +} +void CalibGui::timeouts(){ + // 1 s timeout, update number of events + char labelstring[128]; + TTimeStamp currenttime; + currenttime.Set(); + int timediff=(int)(currenttime.AsDouble()-m_starttime.AsDouble()+.5); + //std::cout<<"starttime "<<m_starttime.AsDouble()<<std::endl; + //std::cout<<"currenttime "<<currenttime.AsDouble()<<std::endl; + //std::cout<<"Timediff "<<timediff<<std::endl; + sprintf(labelstring,"%d s",timediff); + //std::cout<<"Labelstring "<<labelstring<<std::endl; + m_time->SetText(labelstring); + m_cbinfo->updateGui(); +} + +int CalibGui::startRun(){ + + //clear is server + if( m_hcontroller.clearISServer(".*", false) == 0 ){ + std::cout<<"Clearing histograms off IS server at beginning of run failed! Not continuing"<<std::endl; + assert(0); + } + + //configure all valid modules + //set up RCEs first + + std::map<int,unsigned int> rcemap; + m_controller.removeAllRces(); + m_hcontroller.removeAllRces(); + for (int i=0;i<ConfigGui::MAX_MODULES;i++){ + if(m_config[i]->isIncluded()){ + m_controller.addRce(m_config[i]->getRce()); + m_hcontroller.addRce(m_config[i]->getRce()); + rcemap[m_config[i]->getRce()]=0; //value will be the phase word + } + } + // set up the trigger + + PixScan *pixscan=currentScan(); + //pixscan->dump(std::cout, *m_scan->getScanConfig()); + if(pixscan==0){ // no scan selected + stopRun(); + return 1; + } + + m_controller.setupTrigger(pixscan->getTriggerType()); + //now set up modules + m_controller.removeAllModules(); + bool valid=false; + std::map<int,unsigned int> linkmap; + std::map<int,unsigned int> idmap; + for (int i=0;i<ConfigGui::MAX_MODULES;i++){ + if(m_config[i]->isIncluded()){ + valid=true; + unsigned rce=m_config[i]->getRce(); + unsigned outlink=m_config[i]->getOutLink(); + if(linkmap.find(outlink+1000*rce)!=linkmap.end()){ + int retcode; + new TGMsgBox(gClient->GetRoot(), 0, "Attention",Form("Outlink %d used by more than one frontend. Fix in config tab.", outlink), + kMBIconExclamation, kMBClose,&retcode); + stopRun(); + return 1; + } + linkmap[outlink+1000*rce]=1; + unsigned inlink=m_config[i]->getInLink(); + //rcemap[rce]|=1<<(m_config[i]->getPhase()+outlink*4); + int id=m_config[i]->getId(); + if(idmap.find(id)!=idmap.end()){ + int retcode; + new TGMsgBox(gClient->GetRoot(), 0, "Attention",Form("ID %d used by more than one frontend. Fix configuration files.", id), + kMBIconExclamation, kMBClose,&retcode); + stopRun(); + return 1; + } + idmap[id]=1; + const char* modname=m_config[i]->getName(); + std::string formatter=pixscan->getFormatterType(); + if(m_config[i]->getType()=="FEI4A"){ + if(formatter=="FEI4")formatter+="A"; + printf("FEI4A: addModule (%s, %d, %d, %d, %d, %s)\n",modname, id, inlink, outlink, rce,formatter.c_str()); + m_controller.addModule(modname, "FEI4A",id, inlink, outlink, rce, formatter.c_str()); + ipc::PixelFEI4AConfig *cfg=m_config[i]->getFEI4AConfig(); + m_controller.downloadModuleConfig(rce, id ,*cfg); + } else if(m_config[i]->getType()=="FEI4B"){ + if(formatter=="FEI4")formatter+="B"; + printf("FEI4B: addModule (%s, %d, %d, %d, %d, %s)\n",modname, id, inlink, outlink, rce,formatter.c_str()); + m_controller.addModule(modname, "FEI4B",id, inlink, outlink, rce, formatter.c_str()); + ipc::PixelFEI4BConfig *cfg=m_config[i]->getFEI4BConfig(); + m_controller.downloadModuleConfig(rce, id ,*cfg); + } else if(m_config[i]->getType()=="FEI3"){ + printf("FEI3: addModule (%s, %d, %d, %d, %d, %s)\n",modname, id, inlink, outlink, rce,formatter.c_str()); + m_controller.addModule(modname, "FEI3",id, inlink, outlink, rce, formatter.c_str()); + ipc::PixelModuleConfig *cfg=m_config[i]->getModuleConfig(); + m_controller.downloadModuleConfig(rce, id ,*cfg); + } else if(m_config[i]->getType()=="Hitbus"){ + printf("Hitbus: addModule (%s, %d, %d, %d, %d %s)\n",modname, id, inlink, outlink, rce,formatter.c_str()); + m_controller.addModule(modname, "Hitbus",id, inlink, outlink, rce, ""); + ipc::HitbusModuleConfig *cfg=m_config[i]->getHitbusConfig(); + m_controller.downloadModuleConfig(rce, id ,*cfg); + } else { + std::cout<<"Unknown config type"<<std::endl; + assert(0); + } + } + } + if(valid==false){ + int retcode; + new TGMsgBox(gClient->GetRoot(), 0, "Attention", "No pixel module included in the calibration. Continue?", + kMBIconExclamation, kMBYes | kMBCancel,&retcode); + if(retcode!=kMBYes){ + stopRun(); + return 1; + } + } + unsigned goodHSIOconnection; + for (std::map <int, unsigned int>::const_iterator it = rcemap.begin(); it != rcemap.end(); ++it){ + int rce=it->first; + goodHSIOconnection=m_controller.writeHWregister(rce, 11,0x0); //Trigger mask 1=scint 2=cyclic 4=Eudet 8=HSIO + assert(goodHSIOconnection==0); + goodHSIOconnection=m_controller.writeHWregister(rce, 3,0); //Mode 0=normal 1=tdccalib 2=eudaq + assert(goodHSIOconnection==0); + goodHSIOconnection=m_controller.writeHWregister(rce, 27,0); //regular L1A + assert(goodHSIOconnection==0); + goodHSIOconnection=m_controller.writeHWregister(rce, 22,0); //don't optimize multiplexer + assert(goodHSIOconnection==0); + goodHSIOconnection=m_controller.writeHWregister(rce, 23,0); //don't optimize multiplexer + assert(goodHSIOconnection==0); + // Reset delays + goodHSIOconnection=m_controller.writeHWregister(rce, 7,0); + assert(goodHSIOconnection==0); + //assert(m_controller.writeHWregister(rce, 15,0x280)==0); //setup mux + //assert(m_controller.writeHWregister(rce, 20,0x0)==0); //no BPM encoding + //else assert(m_controller.writeHWregister(rce, 20,0x1)==0); //BPM encoding + //assert(m_controller.writeHWregister(rce,17,it->second)==0); // set up phase + //Delay 0 -- Delay for disc 0 + // for(int i=0;i<m_phase->GetIntNumber();i++){ + // serstat=m_controller.writeHWregister(rce, 5,0); + // assert(serstat==0); + //} + + } + if (currentScanConfig()==0){ + stopRun(); + return 1; + } + logScan(); + pthread_t mthread; + pthread_create( &mthread, 0, CalibGui::runloop, (void*)this); + pthread_detach(mthread); + + + return 0; +} + +void CalibGui::runScan(int pr){ + m_controller.runScan((ipc::Priority)pr, m_cb); +} + +void CalibGui::verifyConfiguration(){ + std::cout<<"Verifying HW configuration"<<std::endl; + m_cbinfo->addToMask(CallbackInfo::VERIFY); + for (int i=0;i<ConfigGui::MAX_MODULES;i++){ + if(m_config[i]->isIncluded()){ + unsigned rce=m_config[i]->getRce(); + unsigned id=m_config[i]->getId(); + std::cout<<"Frontend "<<id<<" on RCE "<<rce<<" Outlink "<<m_config[i]->getOutLink()<<":"<<std::endl; + int retval=m_controller.verifyModuleConfigHW(rce, id); + if(retval&ModuleVerify::NO_FORMATTER)std::cout<<"No formatter defined. Skipping register readback."<<std::endl; + if(retval&ModuleVerify::GLOBAL_READBACK_FAILED)std::cout<<"Global register readback failed for unknown reasons."<<std::endl; + if(retval&ModuleVerify::GLOBAL_READBACK_DIFFERENT)std::cout<<"Global register readback differs from original configuration."<<std::endl; + if(retval&ModuleVerify::PIXEL_WRONG_N_WORDS)std::cout<<"Pixel register read back wrong number of words."<<std::endl; + if(retval&ModuleVerify::PIXEL_READBACK_DIFFERENT)std::cout<<"Pixel register readback differs from original configuration."<<std::endl; + if(retval==ModuleVerify::OK)std::cout<<"Register verification successful."<<std::endl; + if(retval!=ModuleVerify::OK)m_status=FAILED; + } + } +} +void CalibGui::enableControls(bool on){ + m_print->SetEnabled(on); + m_quit->SetEnabled(on); + m_save->SetEnabled(on); + m_export->SetEnabled(on); + m_debug->SetEnabled(on); + m_comment->SetEnabled(on); + for(int i=0;i<ConfigGui::MAX_MODULES;i++) + m_config[i]->enableControls(on); + m_scan->enableControls(on); + m_globalconf->enableControls(on); +} + +void CalibGui::quit(){ + writeGuiConfig((m_homedir+".calibDaq.rc").Data()); + ISInfoDictionary dict(*m_partition); + ISInfoInt gui_running(0); + dict.checkin("RceIsServer.GUI_running", gui_running); + gApplication->Terminate(0); +} + + +void CalibGui::handlePlotMenu(int item){ + if(item==GIF){ + m_canvas->GetCanvas()->SaveAs("c1.gif"); + }else if(item==PDF){ + m_canvas->GetCanvas()->SaveAs("c1.pdf"); + } +} +void CalibGui::getFirm(){ + std::map<int,unsigned int> rcemap; + m_controller.removeAllRces(); + bool foundRce=false; + for (int i=0;i<ConfigGui::MAX_MODULES;i++){ + if(m_config[i]->isIncluded()){ + foundRce=true; + m_controller.addRce(m_config[i]->getRce()); + rcemap[m_config[i]->getRce()]=0; //value will be the phase word + } + } + unsigned firm; + for (std::map <int, unsigned int>::const_iterator it = rcemap.begin(); it != rcemap.end(); ++it){ + int rce=it->first; + unsigned value; + firm=m_controller.readHWregister(rce, 13, value); + if(firm==0){ + std::cout<<"RCE "<<rce<<": HSIO firmware version is "<<std::hex<<value<<std::dec<<"\n"; + }else{ + std::cout<<"RCE "<<rce<<": Firmware readout failed"<<"\n"; + } + } + if(foundRce==false){ + std::cout<<"***NO RCEs FOUND!***\n"<<std::endl; + }else{printf("Done\n");} +} + +void CalibGui::switchOn(int panel, bool on){ + int modperpanel=ConfigGui::MAX_MODULES/4; + for (int i=panel*modperpanel;i<(panel+1)*modperpanel;i++){ + m_config[i]->setIncluded(on); + } +} + + +void CalibGui::handleFileMenu(int item){ + TGFileInfo fileinfo; + const char* types[]={"Teststand config", "*.tcf", "All files", "*", 0, 0}; + fileinfo.fFileTypes=types; + if(item==QUIT)quit(); + else if(item==LOAD){ + new TGFileDialog(gClient->GetRoot(), 0, kFDOpen, &fileinfo); + if(!fileinfo.fFilename){ + printf("Scheisse\n"); + return; + } + readGuiConfig(fileinfo.fFilename); + } + else if(item==SAVE){ + new TGFileDialog(gClient->GetRoot(), 0, kFDSave, &fileinfo); + if(!fileinfo.fFilename){ + printf("Scheisse\n"); + return; + } + writeGuiConfig(fileinfo.fFilename); + } +} +void CalibGui::clearTree(){ + TGListTreeItem* root=m_tree->FindChildByName(0,"Histos"); + if(root) m_tree->DeleteChildren(root); + root->SetOpen(false); + updateTree(); +} +void CalibGui::updateTree(){ + int x=m_tgc->GetViewPort()->GetX(); + int y=m_tgc->GetViewPort()->GetY(); + int w=m_tgc->GetViewPort()->GetWidth(); + int h=m_tgc->GetViewPort()->GetHeight(); + m_tree->DrawRegion(x,y,w,h); +} + +void CalibGui::fillHistoTree(TGListTreeItem* branch){ + std::vector<std::string> names=m_hcontroller.getPublishedHistoNames(); + if(names.size()==0){ + std::cout<<"No Histograms available"<<std::endl; + return; + } + for(size_t i=0;i<names.size();i++){ + names[i]=CalibAnalysis::addPosition(names[i].c_str(), m_config); + } + std::sort(names.begin(), names.end()); + for(size_t i=0;i<names.size();i++){ + TGListTreeItem* item=m_tree->AddItem(branch,names[i].c_str()); + item->SetPictures(m_thp,m_thp); + } +} +void CalibGui::displayHisto(TGListTreeItem* item, int b){ + TGListTreeItem *parent=item->GetParent(); + if(parent==0)return; + std::string histonames=item->GetText(); + if(histonames[5]==':')histonames=histonames.substr(6); //remove position information + const char* histoname=histonames.c_str(); + if(std::string(histoname).substr(0,4)=="loop")return; + if(std::string(histoname).substr(0,8)=="Analysis")return; + //std::cout<<"Text "<<histoname<<std::endl; + if(std::string(parent->GetText())=="Analysis"){ + if(m_delhisto==true) delete m_histo; + m_delhisto=false; + m_anfile->cd(); + m_histo=(TH1*)gDirectory->Get(histoname); + //assert(m_histo!=0); + if(m_histo==0){ + std::cout<<"Histogram does not exist"<<std::endl; + return; + } + }else if(saveChecked()==false || + (m_save->IsEnabled()==true && m_save->IsOn()==false)){ + std::vector<TH1*> his=m_hcontroller.getHistosFromIS(histoname); + if(his.size()!=1)return; + if(m_delhisto==true) delete m_histo; + m_histo=his[0]; + m_delhisto=true; + //std::cout<<"Got histo from IS."<<std::endl; + }else{ + TGListTreeItem *parent1=parent->GetParent(); + if(parent1==0)m_file->cd(); + else{ + TGListTreeItem *parent2=parent1->GetParent(); + if(parent2==0)m_file->cd(parent->GetText()); + else{ + char dir[128]; + sprintf(dir, "%s/%s",parent1->GetText(), parent->GetText()); + m_file->cd(dir); + } + } + if(m_delhisto==true) delete m_histo; + m_delhisto=false; + m_histo=(TH1*)gDirectory->Get(histoname); + //assert(m_histo!=0); + if(m_histo==0){ + std::cout<<"Histogram does not exist"<<std::endl; + return; + } + //std::cout<<"Got histo from file."<<std::endl; + } + m_histo->SetMinimum(0); + if(m_histo->GetDimension()==1)m_histo->Draw(); + else { + std::cout<<"Drawing 2-d histogram"<<std::endl; + m_histo->Draw("colz"); + } + m_canvas->GetCanvas()->Update(); +} + +int CalibGui::openFile(){ + if(currentScan()==0){ + std::cout<<"No Scan selected."<<std::endl; + return 1; + } + TGFileInfo fileinfo; + char runnum[128]; + sprintf(runnum,"%06d",m_globalconf->getRunNumber()); + TString runname; + runname = (getScanName()+"_"+runnum); + TString rcdir("/"+runname); + rcdir=m_globalconf->getDataDir()+rcdir; + m_rcdir=std::string(rcdir.Data()); + m_exportdir=std::string(runname.Data()); + TString filename(rcdir+"/histos.root"); + TString anfilename(rcdir+"/analysis.root"); + TString rcconfig(rcdir+"/globalconfig.txt"); + std::string topconfigname=m_globalconf->getConfigName()+".cfg"; + TString topconfig(rcdir+"/"+topconfigname); + TString scanconfig(rcdir+"/scanconfig_"+m_exportdir+".txt"); + struct stat stFileInfo; + int intStat; + // Attempt to get the file attributes + + intStat = stat(rcdir.Data(),&stFileInfo); + if(intStat == 0) { //File exists + int retcode; + + new TGMsgBox(gClient->GetRoot(), 0, "Attention", "Data file exists. Overwrite?", + kMBIconExclamation, kMBYes | kMBCancel,&retcode); + if(retcode==kMBYes){ + char command[512]; + sprintf(command, "rm -rf %s",rcdir.Data()); + system(command); + } + else + { + if (!m_primList->isLoaded()) + return 1; + else + { + m_isrunning=false; + return 1; + } + } + } + // make new run directory + mkdir (rcdir.Data(),0777); + // copy configuration + writeGuiConfig(rcconfig.Data()); + m_globalconf->copyConfig(topconfig.Data()); + std::ofstream sc(scanconfig.Data()); + if (m_primList->isLoaded()){ + m_primList->getCurrentScan()->dump(sc, *m_primList->getCurrentScanConfig()); + }else{ + m_scan->print(sc); + } + std::string oldcfg=std::string(rcdir.Data())+"/config"; + std::string updcfg=std::string(rcdir.Data())+"/configUpdate/"; + mkdir (oldcfg.c_str(),0777); + mkdir (updcfg.c_str(),0777); + m_globalconf->setConfigDir(updcfg.c_str()); + for (int i=0;i<ConfigGui::MAX_MODULES;i++){ + if(m_config[i]->isIncluded()){ + m_config[i]->copyConfig(oldcfg.c_str()); + } + } + delete m_file; + TDatime dt; + m_file=new TFile(filename.Data(),"recreate", Form("Scan: %s Date: %s", runname.Data(), dt.AsString()) ); + delete m_anfile; + if(std::string(currentScan()->getAnalysisType())!="NONE") { + m_anfile=new TFile(anfilename.Data(),"recreate",Form("Scan: %s Date: %s", runname.Data(), dt.AsString()) ); + } + else m_anfile=0; + return 0; +} + +void CalibGui::writeGuiConfig(const char *filename){ + std::ofstream of(filename); + m_globalconf->writeGuiConfig(of); + of.close(); +} +void CalibGui::readGuiConfig(const char* filename){ + struct stat stFileInfo; + int intStat; + // Attempt to get the file attributes + intStat = stat(filename,&stFileInfo); + if(intStat == 0) { //File exists + std::ifstream fin(filename); + m_globalconf->readGuiConfig(fin); + fin.close(); + }else{ + std::cout<<"File "<<filename<<" does not exist"<<std::endl; + } +} + +void CalibGui::printFromGui(){ + setupScan(); + m_scan->print(std::cout); +} + +int CalibGui::setupScan(){ + if(m_primList->isLoaded()){//already setup when loaded primlist + m_primList->setRunNumber(m_globalconf->getRunNumber()); + return 0; + } + std::string fetype=""; + for (int i=0;i<ConfigGui::MAX_MODULES;i++){ + if(m_config[i]->isIncluded()){ + std::string type=m_config[i]->getType(); + if(fetype!="" && type!="Hitbus" && type.substr(0,4) != fetype.substr(0,4)){ + std::cout<<"No mixing of frontend flavors allowed."<<std::endl; + return -1; + } + if(type!="Hitbus" && fetype!="FEI4A")fetype=type; //FEI4A overrules FEI4B + } + } + m_scan->setupScan(fetype, m_globalconf->getRunNumber()); + return 0; +} + +void CalibGui::saveHistos(){ + m_cbinfo->addToMask(CallbackInfo::SAVE); + m_cbinfo->updateGui(); + m_file->cd(m_dir.c_str()); + + std::vector<TH1*> his = m_hcontroller.getHistosFromIS(".*"); + if(his.size()==0) + { + std::cout<<"CalibGui::saveHistos - Error, no histograms found on IS server"<<std::endl; + return; + } + for(size_t i=0;i<his.size();i++) + { + if(his.at(i)==0){ + std::cout<<"CalibGui::saveHistos - Error, empty histogram retrieved from IS server"<<std::endl; + continue; + } + //do we need to set histogram name? + his.at(i)->Write(); + delete his.at(i); + } +} + +void CalibGui::loopAction(int i, int j){ + PixScan* pixscan=currentScan(); + switch(pixscan->getLoopAction(i)){ + case PixScan::T0_SET: + m_controller.setupParameter( "CHARGE", pixscan->getTotTargetCharge()); + break; + case PixScan::TDAC_TUNING: + setupTdacTuning(j); + break; + case PixScan::TDAC_FAST_TUNING: + setupTdacFastTuning(j); + break; + case PixScan::GDAC_TUNING: + if(i==2)setupGdacTuningOuterLoop(); + else setupGdacTuning(j); + break; + case PixScan::OFFSET: + setupOffsetScan(j); + break; + case PixScan::GDAC_FAST_TUNING: + setupGdacFastTuning(j); + break; + case PixScan::GDAC_COARSE_FAST_TUNING: + setupGdacCoarseFastTuning(j); + break; + case PixScan::SETMASK: + setupMask(i,j); + break; + case PixScan::NO_ACTION: + break; + default: + break; + } +} + +void CalibGui::analyze(){ + std::cout<<"Analyzing"<<std::endl; + m_cbinfo->addToMask(CallbackInfo::ANALYZE); + std::string type=currentScan()->getAnalysisType(); + AnalysisFactory af; + CalibAnalysis* ana=af.getAnalysis(type); + if(ana){ + ana->analyze(m_file, m_anfile, currentScan(), m_globalconf->getRunNumber(), m_config); + m_anfile->ReOpen("read"); //re-open file for reading + TGListTreeItem* root=m_tree->FindChildByName(0,"Histos"); + TGListTreeItem* anroot=m_tree->AddItem(root,"Analysis"); + m_anfile->cd(); + TList* histos=gDirectory->GetListOfKeys(); + std::vector<std::string> namevec; + for(int i=0;i<histos->GetEntries();i++){ + std::string hname=((TH1*)histos->At(i))->GetName(); + hname=CalibAnalysis::addPosition(hname.c_str(), m_config); + namevec.push_back(hname); + } + std::sort(namevec.begin(), namevec.end()); + for(size_t i=0;i<namevec.size();i++){ + TGListTreeItem* item=m_tree->AddItem(anroot,namevec[i].c_str()); + item->SetPictures(m_thp,m_thp); + } + updateTree(); + if(ana->configUpdate()==true){ + m_globalconf->updateAvailable(true); + } + delete ana; + } +} + +void CalibGui::setupGdacTuningOuterLoop(){ + std::vector<float> varValues=currentScan()->getLoopVarValues(2); + if(varValues.size()<1){ + std::cout<<"No outer loop for GDAC tuning. Not setting up TDAC values"<<std::endl; + return; + } + int val=(int)varValues[0]; + for (int i=0;i<ConfigGui::MAX_MODULES;i++){ + if (m_config[i]->isIncluded()==false)continue; + int ncol, nrow, nchip; + if(m_config[i]->getType().substr(0,4)=="FEI4"){ + ncol=80; + nrow=336; + nchip=1; + }else{ + ncol=18; + nrow=160; + nchip=16; + } + for (int chip=0;chip<nchip;chip++){ + for (int col=0;col<ncol;col++){ + for (int row=0;row<nrow;row++){ + if(m_config[i]->getType()=="FEI4A")m_config[i]->getFEI4AConfig()->FETrims.dacThresholdTrim[col][row]=val; + else if(m_config[i]->getType()=="FEI4B")m_config[i]->getFEI4BConfig()->FETrims.dacThresholdTrim[col][row]=val; + else m_config[i]->getModuleConfig()->FEConfig[chip].FETrims.dacThresholdTrim[row][col]=val; + } + } + } + } +} + +void CalibGui::setupGdacTuning(int j){ + if(!saveChecked()){ + std::cout<<"**** Check Save/Analyze before running this scan. ***"<<std::endl; + return; + } + TGListTreeItem* root=m_tree->FindChildByName(0,"Histos"); + char subdir[128]; + sprintf(subdir, "loop1_%d", j); + for (int i=0;i<ConfigGui::MAX_MODULES;i++){ + if (m_config[i]->isIncluded()==false)continue; + int ncol, nrow, nchip, maxval, maxstage; + if(m_config[i]->getType().substr(0,4)=="FEI4"){ + ncol=80; + nrow=336; + nchip=1; + maxval=256; + maxstage=120; + }else{ + ncol=18; + nrow=160; + nchip=16; + maxval=32; + maxstage=32; + } + std::vector<float> varValues=currentScan()->getLoopVarValues(1); + int occlast=currentScan()->getLoopVarValues(0).size()-3; + int target=currentScan()->getThresholdTargetValue(); + int nstages=currentScan()->getMaskStageSteps(); + int npixtotal=nchip*ncol*nrow; + float npixused=float(nstages)/float(maxstage) * npixtotal; + float npixunused=(1.-float(nstages)/float(maxstage))*npixtotal; + TH2 *mean=0, *chi2=0, *occ0=0, *occmax=0; + char name[128]; + sprintf (name, "GDAC_settings_Mod_%d_it_%d", m_config[i]->getId(), j); + TH1F* threshhist=new TH1F(name, Form("GDAC settings module %d step %d", m_config[i]->getId(), j), + nchip, 0, nchip); + threshhist->SetMinimum(0); + threshhist->GetYaxis()->SetTitle("GDAC setting"); + threshhist->GetXaxis()->SetTitle("Chip"); + if(j!=0){ + mean=(TH2*)m_file->Get(Form( "loop2_0/loop1_%d/Mod_%d_Mean", j-1, m_config[i]->getId())); + chi2=(TH2*)m_file->Get(Form( "loop2_0/loop1_%d/Mod_%d_ChiSquare", j-1, m_config[i]->getId())); + occ0=(TH2*)m_file->Get(Form("loop2_0/loop1_%d/Mod_%d_Occupancy_Point_002", j-1, m_config[i]->getId())); + occmax=(TH2*)m_file->Get(Form( "loop2_0/loop1_%d/Mod_%d_Occupancy_Point_%03d", j-1, m_config[i]->getId(),occlast)); + if(mean==0 || chi2==0 || occ0==0 || occmax==0){ + std::cout<<"Did not find histo "<<mean<<" "<<chi2<<" "<<occ0<<" "<<occmax<<std::endl; + std::cout<<"occlast "<<occlast<<std::endl; + assert(0); + return; + } + } + for (int chip=0;chip<nchip;chip++){ + CORBA::Octet val=int(varValues[0]); //initial setting + if(varValues[0]==-1 || j!=0){ //val==-1 means retuning, use GDAC values from file + if(m_config[i]->getType()=="FEI4A") val=m_config[i]->getFEI4AConfig()->FEGlobal.Vthin_AltFine; + else if(m_config[i]->getType()=="FEI4B") val=m_config[i]->getFEI4BConfig()->FEGlobal.Vthin_AltFine; + else val=m_config[i]->getModuleConfig()->FEConfig[chip].FEGlobal.gdac; + } + if(j!=0){ //modify TDAC values appropriately + int repetitions = currentScan()->getRepetitions(); + int diffval=int(varValues[j]); + float empty=0; + float noisy=0; + float good=0; + float meanf=0; + for (int col=0;col<ncol;col++){ + for (int row=0;row<nrow;row++){ + if(occ0->GetBinContent(chip*ncol+col+1, row+1)!=0)noisy++; + else if (occmax->GetBinContent(chip*ncol+col+1, row+1)<repetitions*0.9)empty++; + else if (chi2->GetBinContent(chip*ncol+col+1, row+1)!=0){ + good++; + meanf+=mean->GetBinContent(chip*ncol+col+1, row+1); + } + } + } + if(good>0)meanf/=good; + if(noisy>npixused*0.50){ //more than 50 % of pixels in the noise + if((int)val+diffval<maxval)val+=diffval; + else { + val=maxval-1; + std::cout<<"Module "<< m_config[i]->getId()<<": GDAC already at "<<maxval-1<<std::endl; + } + std::cout<<"Module "<< m_config[i]->getId()<<": More than 50 % of the pixels are in the noise. Moving to higher threshold."<<std::endl; + }else if (empty>npixunused+npixused*0.5){ //more than 50 % never reach threshold + if((int)val-diffval>0)val-=diffval; + else { + std::cout<<"Module "<< m_config[i]->getId()<<": GDAC already at 0"<<std::endl; + val=0; + } + std::cout<<"Module "<< m_config[i]->getId()<<": More than 50 % of the pixels never reach threshold. Moving to lower threshold."<<std::endl; + }else if(good>0.3*npixused){ + if(meanf>target){ + if((int)val-diffval>0)val-=diffval; + else { + std::cout<<"Module "<< m_config[i]->getId()<<": GDAC already at 0"<<std::endl; + val=0; + } + } else { + if((int)val+diffval<maxval)val+=diffval; + else { + val=maxval-1; + std::cout<<"Module "<< m_config[i]->getId()<<": GDAC already at "<<maxval-1<<std::endl; + } + } + }else{ + std::cout<<"Module "<<m_config[i]->getId()<<": GDAC Tuning: No criteria match. Don't know what to do. good="<<good/npixused<<" empty="<<(empty-npixunused)/npixused<<" noisy="<<noisy/npixused<<std::endl; + } + } + std::cout<<"Setting GDAC to "<<(int)val<<std::endl; + if(m_config[i]->getType()=="FEI4A")m_config[i]->getFEI4AConfig()->FEGlobal.Vthin_AltFine=val; + else if(m_config[i]->getType()=="FEI4B")m_config[i]->getFEI4BConfig()->FEGlobal.Vthin_AltFine=val; + else m_config[i]->getModuleConfig()->FEConfig[chip].FEGlobal.gdac=val; + threshhist->SetBinContent(1, val); + } + if(saveChecked()){ + TGListTreeItem* branch2=m_tree->FindChildByName(root,"loop2_0"); + TGListTreeItem* branch=m_tree->FindChildByName(branch2, subdir); + TGListTreeItem* item=m_tree->AddItem(branch,CalibAnalysis::addPosition(name, m_config).c_str()); + item->SetPictures(m_thp,m_thp); + if(m_config[i]->getType()=="FEI4A") m_controller.downloadModuleConfig(m_config[i]->getRce(), m_config[i]->getId(), *m_config[i]->getFEI4AConfig()); + else if(m_config[i]->getType()=="FEI4B") m_controller.downloadModuleConfig(m_config[i]->getRce(), m_config[i]->getId(), *m_config[i]->getFEI4BConfig()); + else m_controller.downloadModuleConfig(m_config[i]->getRce(), m_config[i]->getId(), *m_config[i]->getModuleConfig()); + m_file->cd(Form("loop2_0/%s", subdir)); + threshhist->Write(); + threshhist->SetDirectory(gDirectory); + } + } + m_controller.downloadScanConfig(*(currentScanConfig())); +} + +void CalibGui::setupGdacFastTuning(int j){ + if(!saveChecked()){ + std::cout<<"**** Check Save/Analyze before running this scan. ***"<<std::endl; + return; + } + TGListTreeItem* root=m_tree->FindChildByName(0,"Histos"); + char subdir[128]; + sprintf(subdir, "loop1_%d", j); + for (int i=0;i<ConfigGui::MAX_MODULES;i++){ + if (m_config[i]->isIncluded()==false)continue; + int ncol, nrow, nchip, maxval, maxstage; + if(m_config[i]->getType()=="FEI4A"){ + ncol=80; + nrow=336; + nchip=1; + maxval=256; + maxstage=120; + } + else if(m_config[i]->getType()=="FEI4B"){ + ncol=80; + nrow=336; + nchip=1; + maxval=256; + maxstage=24; + } + else{ + ncol=18; + nrow=160; + nchip=16; + maxval=32; + maxstage=32; + } + currentScanConfig()->scanLoop[0].dataPoints[0] = currentScan()->getThresholdTargetValue(); + int nstages=currentScan()->getMaskStageSteps(); + int npixtotal=nchip*ncol*nrow; + float npixused=float(nstages)/float(maxstage)*npixtotal; + std::vector<float> varValues=currentScan()->getLoopVarValues(1); + int repetitions = currentScan()->getRepetitions(); + double targetEff = 0.5; + TH2 *occ0=0; + char name[128]; + sprintf (name, "GDAC_settings_Mod_%d_it_%d", m_config[i]->getId(), j); + TH1F* threshhist=new TH1F(name, Form("GDAC settings module %d step %d", m_config[i]->getId(), j), + nchip, 0, nchip); + threshhist->SetMinimum(0); + threshhist->GetYaxis()->SetTitle("GDAC setting"); + threshhist->GetXaxis()->SetTitle("Chip"); + if(j!=0){ + occ0=(TH2*)m_file->Get(Form("loop2_0/loop1_%d/Mod_%d_Occupancy_Point_000", j-1, m_config[i]->getId())); + if(occ0==0){ + std::cout<<"Did not find occupancy histo "<<occ0<<std::endl; + assert(0); + return; + } + } + for (int chip=0;chip<nchip;chip++){ + CORBA::Octet val=int(varValues[0]); //initial setting + if(varValues[0]==-1 || j!=0){ //val==-1 means retuning, use GDAC values from file + if(m_config[i]->getType()=="FEI4A") val=m_config[i]->getFEI4AConfig()->FEGlobal.Vthin_AltFine; + else if(m_config[i]->getType()=="FEI4B") val=m_config[i]->getFEI4BConfig()->FEGlobal.Vthin_AltFine; + else val=m_config[i]->getModuleConfig()->FEConfig[chip].FEGlobal.gdac; + } + if(j!=0){ //modify GDAC values appropriately + float meanEff = 0.0; + int diffval=int(varValues[j]); + for (int col=0;col<ncol;col++){ + for (int row=0;row<nrow;row++) meanEff += occ0->GetBinContent(chip*ncol+col+1, row+1) / repetitions; + } + meanEff /= npixused; + if (meanEff < targetEff) { + if ((int)val-diffval > 0) { + val-=diffval; + } + else { + std::cout<<"Module "<< m_config[i]->getId()<<": GDAC already at 0"<<std::endl; + val=0; + } + } + else if (meanEff > targetEff) { + if ((int)val+diffval < maxval){ + val+=diffval; + } + else { + val=maxval-1; + std::cout<<"Module "<< m_config[i]->getId()<<": GDAC already at "<<maxval-1<<std::endl; + } + } + } + std::cout<<"Setting GDAC for module " << m_config[i]->getId() << " to " << (int)val << std::endl; + if(m_config[i]->getType()=="FEI4A")m_config[i]->getFEI4AConfig()->FEGlobal.Vthin_AltFine=val; + else if(m_config[i]->getType()=="FEI4B")m_config[i]->getFEI4BConfig()->FEGlobal.Vthin_AltFine=val; + else m_config[i]->getModuleConfig()->FEConfig[chip].FEGlobal.gdac=val; + threshhist->SetBinContent(1, val); + } + if(saveChecked()){ + TGListTreeItem* branch2=m_tree->FindChildByName(root,"loop2_0"); + TGListTreeItem* branch=m_tree->FindChildByName(branch2, subdir); + TGListTreeItem* item=m_tree->AddItem(branch,CalibAnalysis::addPosition(name, m_config).c_str()); + item->SetPictures(m_thp,m_thp); + if(m_config[i]->getType()=="FEI4A") m_controller.downloadModuleConfig(m_config[i]->getRce(), m_config[i]->getId(), *m_config[i]->getFEI4AConfig()); + else if(m_config[i]->getType()=="FEI4B") m_controller.downloadModuleConfig(m_config[i]->getRce(), m_config[i]->getId(), *m_config[i]->getFEI4BConfig()); + else m_controller.downloadModuleConfig(m_config[i]->getRce(), m_config[i]->getId(), *m_config[i]->getModuleConfig()); + m_file->cd(Form("loop2_0/%s", subdir)); + threshhist->Write(); + threshhist->SetDirectory(gDirectory); + } + } + m_controller.downloadScanConfig(*(currentScanConfig())); +} + +void CalibGui::setupGdacCoarseFastTuning(int j){ + if(!saveChecked()){ + std::cout<<"**** Check Save/Analyze before running this scan. ***"<<std::endl; + return; + } + TGListTreeItem* root=m_tree->FindChildByName(0,"Histos"); + char subdir[128]; + sprintf(subdir, "loop1_%d", j); + for (int i=0;i<ConfigGui::MAX_MODULES;i++){ + if (m_config[i]->isIncluded()==false)continue; + int ncol, nrow, nchip, maxval, maxstage; + if(m_config[i]->getType()=="FEI4A"){ + ncol=80; + nrow=336; + nchip=1; + maxval=256; + maxstage=120; + } + else { + ncol=80; + nrow=336; + nchip=1; + maxval=256; + maxstage=24; + } + currentScanConfig()->scanLoop[0].dataPoints[0] = currentScan()->getThresholdTargetValue(); + std::vector<float> varValues=currentScan()->getLoopVarValues(1); + char name[128]; + sprintf (name, "GDACCoarse_settings_Mod_%d_it_%d", m_config[i]->getId(), j); + TH1F* threshhist=new TH1F(name, Form("GDACCoarse settings module %d step %d", m_config[i]->getId(), j), + nchip, 0, nchip); + threshhist->SetMinimum(0); + threshhist->GetYaxis()->SetTitle("GDACCoarse setting"); + threshhist->GetXaxis()->SetTitle("Chip"); + for (int chip=0;chip<nchip;chip++) { + CORBA::Octet val = int(varValues[j]); //initial setting + CORBA::Octet fineval = int(maxval-1); + if ((int)val > maxval-1) { + val = maxval-1; + std::cout << "Module " << m_config[i]->getId() << ": GDACCoarse cannot be higher than " << (int)val << std::endl; + } + else if ((int)val < 0) { + val = int(0); + std::cout << "Module " << m_config[i]->getId() << ": GDACCoarse cannot be lower than " << (int)val << std::endl; + } + std::cout<<"Setting GDACCoarse for module " << m_config[i]->getId() << " to " << (int)val << std::endl; + if (m_config[i]->getType() == "FEI4A") { + m_config[i]->getFEI4AConfig()->FEGlobal.Vthin_AltCoarse = val; + m_config[i]->getFEI4AConfig()->FEGlobal.Vthin_AltFine = fineval; + } + else if (m_config[i]->getType() == "FEI4B") { + m_config[i]->getFEI4BConfig()->FEGlobal.Vthin_AltCoarse = val; + m_config[i]->getFEI4BConfig()->FEGlobal.Vthin_AltFine = fineval; + } + threshhist->SetBinContent(1, val); + } + if(saveChecked()){ + TGListTreeItem* branch2=m_tree->FindChildByName(root,"loop2_0"); + TGListTreeItem* branch=m_tree->FindChildByName(branch2, subdir); + TGListTreeItem* item=m_tree->AddItem(branch,CalibAnalysis::addPosition(name, m_config).c_str()); + item->SetPictures(m_thp,m_thp); + if(m_config[i]->getType()=="FEI4A") m_controller.downloadModuleConfig(m_config[i]->getRce(), m_config[i]->getId(), *m_config[i]->getFEI4AConfig()); + else if(m_config[i]->getType()=="FEI4B") m_controller.downloadModuleConfig(m_config[i]->getRce(), m_config[i]->getId(), *m_config[i]->getFEI4BConfig()); + m_file->cd(Form("loop2_0/%s", subdir)); + threshhist->Write(); + threshhist->SetDirectory(gDirectory); + } + } + m_controller.downloadScanConfig(*(currentScanConfig())); +} + +void CalibGui::setupTdacTuning(int j){ + TGListTreeItem* root=m_tree->FindChildByName(0,"Histos"); + char subdir[128]; + sprintf(subdir, "loop1_%d", j); + for (int i=0;i<ConfigGui::MAX_MODULES;i++){ + if (m_config[i]->isIncluded()==false)continue; + int ncol, nrow, nchip, maxval; + if(m_config[i]->getType().substr(0,4)=="FEI4"){ + ncol=80; + nrow=336; + nchip=1; + maxval=32; + }else{ + ncol=18; + nrow=160; + nchip=16; + maxval=128; + } + //ipc::PixelFEI4Config *cfg=m_config[i]->getFEI4Config(); + std::vector<float> varValues=currentScan()->getLoopVarValues(1); + int occlast=currentScan()->getLoopVarValues(0).size()-3; + int target=currentScan()->getThresholdTargetValue(); + TH2 *mean=0, *chi2=0, *occ0=0, *occmax=0; + char name[128]; + sprintf (name, "TDAC_settings_Mod_%d_it_%d", m_config[i]->getId(), j); + TH2F* threshhist=new TH2F(name, Form("TDAC settings module %d step %d", m_config[i]->getId(), j), + nchip*ncol, 0, nchip*ncol, nrow, 0, nrow); + threshhist->SetMinimum(0); + threshhist->GetXaxis()->SetTitle("Column"); + threshhist->GetYaxis()->SetTitle("Row"); + if(j!=0){ + mean=(TH2*)m_file->Get(Form( "loop1_%d/Mod_%d_Mean", j-1, m_config[i]->getId())); + chi2=(TH2*)m_file->Get(Form( "loop1_%d/Mod_%d_ChiSquare", j-1, m_config[i]->getId())); + occ0=(TH2*)m_file->Get(Form("loop1_%d/Mod_%d_Occupancy_Point_002", j-1, m_config[i]->getId())); + occmax=(TH2*)m_file->Get(Form( "loop1_%d/Mod_%d_Occupancy_Point_%03d", j-1, m_config[i]->getId(),occlast)); + if(mean==0 || chi2==0 || occ0==0 || occmax==0){ + std::cout<<"Did not find histo "<<mean<<" "<<chi2<<" "<<occ0<<" "<<occmax<<std::endl; + std::cout<<"occlast "<<occlast<<std::endl; + assert(0); + return; + } + } + for (int chip=0;chip<nchip;chip++){ + for (int col=0;col<ncol;col++){ + for (int row=0;row<nrow;row++){ + CORBA::Octet val=int(varValues[0]); //initial setting + if(varValues[0]==-1 || j!=0){ //val==-1 means retuning, use TDAC values from file + if(m_config[i]->getType()=="FEI4A") val=m_config[i]->getFEI4AConfig()->FETrims.dacThresholdTrim[col][row]; + else if(m_config[i]->getType()=="FEI4B") val=m_config[i]->getFEI4BConfig()->FETrims.dacThresholdTrim[col][row]; + else val=m_config[i]->getModuleConfig()->FEConfig[chip].FETrims.dacThresholdTrim[row][col]; + } + if(j!=0){ //modify TDAC values appropriately + int diffval=int(varValues[j]); + if(m_config[i]->getType()=="FEI3"){ + if(chi2->GetBinContent(chip*ncol+col+1, row+1)!=0){ + double m=mean->GetBinContent(chip*ncol+col+1, row+1); + if(m<target && val+diffval<128)val+=diffval; + else if(m>target && val>=diffval)val-=diffval; + }else if (occ0->GetBinContent(chip*ncol+col+1, row+1)!=0 && occmax->GetBinContent(chip*ncol+col+1, row+1)!=0 + && val+diffval<128){ + val+=diffval; + }else if (occ0->GetBinContent(chip*ncol+col+1, row+1)==0 && occmax->GetBinContent(chip*ncol+col+1, row+1)==0 && val!=0 + && val>=diffval){ + val-=diffval; + } + }else{ + if(chi2->GetBinContent(col+1, row+1)!=0){ + double m=mean->GetBinContent(col+1, row+1); + if(m>target && val+diffval<32)val+=diffval; + else if(m<target && val>=diffval)val-=diffval; + }else if (occ0->GetBinContent(col+1, row+1)==0 && occmax->GetBinContent(col+1, row+1)==0 + && val+diffval<32){ + val+=diffval; + }else if (occ0->GetBinContent(col+1, row+1)!=0 && occmax->GetBinContent(col+1, row+1)!=0 && val!=0 + && val>=diffval){ + val-=diffval; + } + } + } + if(m_config[i]->getType()=="FEI4A")m_config[i]->getFEI4AConfig()->FETrims.dacThresholdTrim[col][row]=val; + else if(m_config[i]->getType()=="FEI4B")m_config[i]->getFEI4BConfig()->FETrims.dacThresholdTrim[col][row]=val; + else m_config[i]->getModuleConfig()->FEConfig[chip].FETrims.dacThresholdTrim[row][col]=val; + threshhist->SetBinContent(chip*ncol+col+1, row+1, val); + } + } + } + if(saveChecked()){ + TGListTreeItem* branch=m_tree->FindChildByName(root,subdir); + TGListTreeItem* item=m_tree->AddItem(branch,CalibAnalysis::addPosition(name, m_config).c_str()); + item->SetPictures(m_thp,m_thp); + if(m_config[i]->getType()=="FEI4A") m_controller.downloadModuleConfig(m_config[i]->getRce(), m_config[i]->getId(), *m_config[i]->getFEI4AConfig()); + else if(m_config[i]->getType()=="FEI4B") m_controller.downloadModuleConfig(m_config[i]->getRce(), m_config[i]->getId(), *m_config[i]->getFEI4BConfig()); + else m_controller.downloadModuleConfig(m_config[i]->getRce(), m_config[i]->getId(), *m_config[i]->getModuleConfig()); + m_file->cd(subdir); + threshhist->Write(); + threshhist->SetDirectory(gDirectory); + } + } + m_controller.downloadScanConfig(*(currentScanConfig())); +} + +void CalibGui::setupTdacFastTuning(int j){ + TGListTreeItem* root=m_tree->FindChildByName(0,"Histos"); + char subdir[128]; + sprintf(subdir, "loop1_%d", j); + for (int i=0;i<ConfigGui::MAX_MODULES;i++){ + if (m_config[i]->isIncluded()==false)continue; + int ncol, nrow, nchip, maxval; + if(m_config[i]->getType().substr(0,4)=="FEI4"){ + ncol=80; + nrow=336; + nchip=1; + maxval=32; + }else{ + ncol=18; + nrow=160; + nchip=16; + maxval=128; + } + //ipc::PixelFEI4Config *cfg=m_config[i]->getFEI4Config(); + currentScanConfig()->scanLoop[0].dataPoints[0] = currentScan()->getThresholdTargetValue(); + std::vector<float> varValues=currentScan()->getLoopVarValues(1); + int repetitions = currentScan()->getRepetitions(); + double targetEff = 0.5; + TH2 *occ0=0; + char name[128]; + sprintf (name, "TDAC_settings_Mod_%d_it_%d", m_config[i]->getId(), j); + TH2F* threshhist=new TH2F(name, Form("TDAC settings module %d step %d", m_config[i]->getId(), j), + nchip*ncol, 0, nchip*ncol, nrow, 0, nrow); + threshhist->SetMinimum(0); + threshhist->GetXaxis()->SetTitle("Column"); + threshhist->GetYaxis()->SetTitle("Row"); + if(j!=0){ + occ0=(TH2*)m_file->Get(Form("loop1_%d/Mod_%d_Occupancy_Point_000", j-1, m_config[i]->getId())); + if(occ0==0){ + std::cout<<"Did not find occupancy histo "<<occ0<<std::endl; + assert(0); + return; + } + } + for (int chip=0;chip<nchip;chip++){ + for (int col=0;col<ncol;col++){ + for (int row=0;row<nrow;row++){ + CORBA::Octet val=int(varValues[0]); //initial setting + if(varValues[0]==-1 || j!=0){ //val==-1 means retuning, use TDAC values from file + if(m_config[i]->getType()=="FEI4A") val=m_config[i]->getFEI4AConfig()->FETrims.dacThresholdTrim[col][row]; + else if(m_config[i]->getType()=="FEI4B") val=m_config[i]->getFEI4BConfig()->FETrims.dacThresholdTrim[col][row]; + else val=m_config[i]->getModuleConfig()->FEConfig[chip].FETrims.dacThresholdTrim[row][col]; + } + if(j!=0){ //modify TDAC values appropriately + int diffval=int(varValues[j]); + if(m_config[i]->getType()=="FEI3"){ + double m= occ0->GetBinContent(chip*ncol+col+1, row+1) / repetitions; + if(m>targetEff && val+diffval<128)val+=diffval; + else if(m<targetEff && val>diffval)val-=diffval; + }else{ + double m=occ0->GetBinContent(col+1, row+1) / repetitions; + if(m<targetEff && val+diffval<32)val+=diffval; + else if(m>targetEff && val>diffval)val-=diffval; + } + } + if(m_config[i]->getType()=="FEI4A")m_config[i]->getFEI4AConfig()->FETrims.dacThresholdTrim[col][row]=val; + else if(m_config[i]->getType()=="FEI4B")m_config[i]->getFEI4BConfig()->FETrims.dacThresholdTrim[col][row]=val; + else m_config[i]->getModuleConfig()->FEConfig[chip].FETrims.dacThresholdTrim[row][col]=val; + threshhist->SetBinContent(chip*ncol+col+1, row+1, val); + } + } + } + if(saveChecked()){ + TGListTreeItem* branch=m_tree->FindChildByName(root,subdir); + TGListTreeItem* item=m_tree->AddItem(branch,CalibAnalysis::addPosition(name, m_config).c_str()); + item->SetPictures(m_thp,m_thp); + if(m_config[i]->getType()=="FEI4A") m_controller.downloadModuleConfig(m_config[i]->getRce(), m_config[i]->getId(), *m_config[i]->getFEI4AConfig()); + else if(m_config[i]->getType()=="FEI4B") m_controller.downloadModuleConfig(m_config[i]->getRce(), m_config[i]->getId(), *m_config[i]->getFEI4BConfig()); + else m_controller.downloadModuleConfig(m_config[i]->getRce(), m_config[i]->getId(), *m_config[i]->getModuleConfig()); + m_file->cd(subdir); + threshhist->Write(); + threshhist->SetDirectory(gDirectory); + } + } + m_controller.downloadScanConfig(*(currentScanConfig())); +} + +void CalibGui::setupOffsetScan(int j){ + ipc::ScanOptions* scanPar=currentScanConfig(); + if(j==0){ + scanPar->stagingMode = CORBA::string_dup("FEI4_ENA_SCAP"); + for(unsigned int k=0;k<scanPar->scanLoop[0].nPoints;k++) + scanPar->scanLoop[0].dataPoints[k]= k*3; + }else{ + scanPar->stagingMode = CORBA::string_dup("FEI4_ENA_BCAP"); + for(unsigned int k=0;k<scanPar->scanLoop[0].nPoints;k++) + scanPar->scanLoop[0].dataPoints[k]= k; + } + //m_controller.downloadScanConfig(*m_scan->getScanConfig()); + m_controller.downloadScanConfig(*(scanPar)); +} + +void CalibGui::setupMask(int loop_i, int j){ + //scanLoop loop_i loops through the different mask stages we want to cycle over + + std::vector<float> varValues; + if(loop_i==1){ + varValues=currentScan()->getLoopVarValues(1); + } + else if(loop_i==2){ + varValues=currentScan()->getLoopVarValues(2); + } + else{ + std::cout<<"CalibGui::setupMask error: invalid value loop_i = "<<loop_i<<std::endl; + return; + } + int stage = varValues[j]; + + for (int i=0;i<ConfigGui::MAX_MODULES;i++){ + if (m_config[i]->isIncluded()==false)continue; + int ncol, nrow, nchip, maxval; + if(m_config[i]->getType().substr(0,4)=="FEI4"){ + ncol=80; + nrow=336; + nchip=1; + maxval=32; + }else{ + //Not supporting FEI3, because the masking bits are different in that case + std::cout<<"CalibGui::setupMask ERROR:only FEI4 supported"<<std::endl; + return; + //ncol=18; + //nrow=160; + //nchip=16; + //maxval=128; + } + + // stage = row + 336*col + 1 (row from 0-335, col from 0-79. We add 1 because we reserve stage==0 for special meaning) + int rowInj = (stage-1)%336; + int colInj = (stage-1)/336; + + for (int col=0;col<ncol;col++){ + for (int row=0;row<nrow;row++){ + + //enable: bit 0, largeCap: bit 1, smallCap: bit 2 + + //set enable for all bits on FE + int val = (1<<ipc::enable); + //set smallCap and largeCap just for the pixel we are injecting + if(col==colInj && row==rowInj){ + val |= (1<<ipc::largeCap); + val |= (1<<ipc::smallCap); + } + // std::cout<<"row "<<row<<" col "<<col<<" ; val = "<<val<<std::endl; + + if(m_config[i]->getType()=="FEI4A")m_config[i]->getFEI4AConfig()->FEMasks[col][row] = val; + else if(m_config[i]->getType()=="FEI4B")m_config[i]->getFEI4BConfig()->FEMasks[col][row] = val; + + } + } + + if(m_config[i]->getType()=="FEI4A") m_controller.downloadModuleConfig(m_config[i]->getRce(), m_config[i]->getId(), *m_config[i]->getFEI4AConfig()); + else if(m_config[i]->getType()=="FEI4B") m_controller.downloadModuleConfig(m_config[i]->getRce(), m_config[i]->getId(), *m_config[i]->getFEI4BConfig()); + + } //end loop over i + + m_controller.downloadScanConfig(*(currentScanConfig())); + //This sets up mask stage, which sets Colpr_Mode to 3. This is necessary, since + //Colpr_Addr gets overwritten during configuration, so we need to be able to inject + //any arbitrary pixel + m_controller.setupMaskStage(stage); + +} + +PixScan* CalibGui::currentScan() +{ + if(m_primList->isLoaded()) + return m_primList->getCurrentScan(); + return m_scan->getPixScan(); +} +std::string CalibGui::getScanName(){ + if(m_primList->isLoaded())return m_primList->getCurrScanName(); + else return m_scan->getTypeString(); +} +ipc::ScanOptions* CalibGui::currentScanConfig() +{ + if(m_primList->isLoaded()) + return m_primList->getCurrentScanConfig(); + return m_scan->getScanConfig(); +} +void CalibGui::EndOfPrimListScan()//Called from the end of run loop, either move to next item +{ + if(!m_isrunning) + { + stopRun(); + return; + } + if(m_primList->getCurrentPause()!=0){ + m_cbinfo->addToMask(CallbackInfo::WAIT); + sleep(m_primList->getCurrentPause()); + } + if(m_primList->getCurrentUpdateConfig()) + { + m_globalconf->update(); + } + if(m_primList->currentScan+1 < m_primList->getNumScans() && m_isrunning){ + finishLogFile(); + m_primList->currentScan++; + setRun(true); + } + else{ + stopRun(); + } +} +void CalibGui::logScan(){ + LogData logdata; + m_scanLog->setAuthor("calibGui"); + m_scanLog->setScanName(getScanName().c_str()); + m_scanLog->setRunNumber(m_globalconf->getRunNumber()); + m_scanLog->setDebugging(debugChecked()); + logdata.comment=m_comment->GetText(); + logdata.exported=exportChecked(); + logdata.saved=saveChecked(); + if(saveChecked())logdata.datapath=m_globalconf->getDataDir(); + for (int i=0;i<ConfigGui::MAX_MODULES;i++){ + std::ostringstream ss; + if(m_config[i]->isIncluded()){ + ss<<"Module: "<<m_config[i]->getModuleId()<<" FE: "<< m_config[i]->getId()<<" Cfg: "<< m_config[i]->getFilename(); + logdata.configs.push_back(ss.str()); + } + } + m_scanLog->logScan(logdata); +} +void CalibGui::finishLogFile(){ + std::string runstatus; + if(isRunning()==false)runstatus="Aborted"; + else if(getStatus()==CalibGui::OK)runstatus="OK"; + else runstatus="Failed"; + std::string lstatus; + if(isRunning()==false)lstatus="Aborted"; + else if(getStatus()==CalibGui::OK)lstatus="Done"; + else lstatus="Failed"; + m_scanLog->finishLogFile(runstatus, lstatus); +} + +//==================================================================== +int main(int argc, char **argv){ + // + // Initialize command line parameters with default values + // + try { + IPCCore::init( argc, argv ); + } + catch( daq::ipc::Exception & ex ) { + ers::fatal( ex ); + return 1; + } + +// +// Declare command object and its argument-iterator +// + CmdArgStr partition_name ('p', "partition", "partition-name", "partition to work in."); + CmdLine cmd(*argv, &partition_name, NULL); + CmdArgvIter arg_iter(--argc, ++argv); +// +// Parse arguments +// + cmd.parse(arg_iter); + const char *p_name=getenv("TDAQ_PARTITION"); + if(p_name==NULL) p_name="rcetest"; + if(! partition_name.isNULL()) p_name= (const char*)partition_name; + IPCPartition* partition=new IPCPartition(p_name ); + //check if somebody else is using the partition + gROOT->SetStyle("Plain"); + gStyle->SetOptStat(0); + gStyle->SetPalette(1); + + TApplication theapp("app",&argc,argv); + new CalibGui(partition, gClient->GetRoot(),800,735); + theapp.Run(); + return 0; +} + + diff --git a/rce/rcecalib/server/CalibGui.hh b/rce/rcecalib/server/CalibGui.hh new file mode 100644 index 00000000..405a1b55 --- /dev/null +++ b/rce/rcecalib/server/CalibGui.hh @@ -0,0 +1,145 @@ +#ifndef CALIBGUI_HH +#define CALIBGUI_HH + +#include "TGMdiMainFrame.h" +#include <TTimer.h> +#include <TTimeStamp.h> +#include <TGLabel.h> +#include <TGTextEntry.h> +#include <TGNumberEntry.h> +#include "TFile.h" +#include <string> +#include "ConfigGui.hh" +#include "GlobalConfigGui.hh" + +namespace RCE { +class PixScan; } +namespace ipc{ + class ScanOptions; +} +class PrimListGui; +class ScanGui; +class IPCController; +class IPCHistoController; +class IPCPartition; +class TGListTree; +class TGListTreeItem; +class TH1; +class TRootEmbeddedCanvas; +class IPCGuiCallback; +class DataExporter; +class ScanLog; +class CallbackInfo; + +class CalibGui: public TGMainFrame { +public: + CalibGui(IPCPartition *partition, const TGWindow *p,UInt_t w,UInt_t h); + virtual ~CalibGui(); + int startRun(); + int setupScan(); + void enableControls(bool on); + void handleFileMenu(Int_t); + void handlePlotMenu(Int_t); + void timeouts(); + void toggle(); + void quit(); + void stopRun(); + void analyze(); + void saveHistos(); + int openFile(); + void clearTree(); + void loopAction(int i, int j); + void setupTdacTuning(int j); + void setupTdacFastTuning(int j); + void setupGdacTuningOuterLoop(); + void setupGdacTuning(int j); + void setupGdacFastTuning(int j); + void setupGdacCoarseFastTuning(int j); + void setupOffsetScan(int j); + void setupMask(int loop_i, int j); + void updateTree(); + void runloop(); + void runScan(int pr); + void verifyConfiguration(); + void displayHisto(TGListTreeItem* item, int b); + TGLabel* getEventLabel(){return m_nEvents;} + void synchSave1(); + void synchSave2(); + std::string getScanName(); + bool saveChecked(){return m_save->IsDisabledAndSelected();} + bool exportChecked(){return m_export->IsDisabledAndSelected();} + bool debugChecked(){return m_debug->IsDisabledAndSelected();} + ConfigGui* getConfig(int i){return m_config[i];} + TGTextEntry *getComment(){return m_comment;} + enum Status{OK, FAILED, ABORTED}; + Status getStatus(){return m_status;} + bool isRunning(){return m_isrunning;} + void allOffA(){switchOn(0,0);} + void allOffC(){switchOn(1,0);} + void allOffA2(){switchOn(2,0);} + void allOffC2(){switchOn(3,0);} + void allOnA(){switchOn(0,1);} + void allOnC(){switchOn(1,1);} + void allOnA2(){switchOn(2,1);} + void allOnC2(){switchOn(3,1);} + void switchOn(int panel, bool on); + void getFirm(); + void finishLogFile(); + void logScan(); + void writeGuiConfig(const char* filename); + void readGuiConfig(const char* filename); + void printFromGui(); + + static void *runloop( void *ptr ); + +private: + RCE::PixScan* currentScan(); + ipc::ScanOptions* currentScanConfig(); + void EndOfPrimListScan(); + void setRun(Bool_t on); + bool running(){return m_isrunning;} + void fillHistoTree(TGListTreeItem* branch); + enum Filemenu {LOAD, SAVE, QUIT}; + enum Plotmenu {GIF, PDF}; + PrimListGui * m_primList; + IPCPartition *m_partition; + IPCController& m_controller; + IPCHistoController& m_hcontroller; + ConfigGui* m_config[ConfigGui::MAX_MODULES]; + ScanGui * m_scan; + TGTextButton *m_start, *m_quit, *m_print; + TGCheckButton *m_save, *m_export, *m_debug; + TGLabel *m_nEvents, *m_time, *m_rate, *m_irate; + TGLabel *m_nLoop1, *m_nLoop2; + TGTextEntry *m_comment; + TGHorizontalFrame *m_datapaneldd; + TTimer *m_timers; + TTimeStamp m_starttime; + unsigned m_nevt; + unsigned m_nevtMin; + double m_oneminago; + bool m_isrunning; + Status m_status; + std::string m_oldRunName; + TGListTree *m_tree; + TH1 *m_histo; + TRootEmbeddedCanvas *m_canvas; + TFile *m_file, *m_anfile; + std::string m_exportdir; + std::string m_rcdir; + std::string m_dir; + IPCGuiCallback* m_cb; + CallbackInfo *m_cbinfo; + TString m_homedir; + TString m_logfile; + bool m_delhisto; + TGCanvas *m_tgc; + GlobalConfigGui* m_globalconf; + DataExporter *m_dataExporter; + ScanLog *m_scanLog; + const TGPicture *m_thp; + + +ClassDef (CalibGui,0) +}; +#endif diff --git a/rce/rcecalib/server/CallbackInfo.cc b/rce/rcecalib/server/CallbackInfo.cc new file mode 100644 index 00000000..582fc1c9 --- /dev/null +++ b/rce/rcecalib/server/CallbackInfo.cc @@ -0,0 +1,51 @@ +#include "CallbackInfo.hh" +#include "TGLabel.h" + +CallbackInfo::CallbackInfo(TGLabel* label): m_label(label), m_stage(0), m_mask(0){} + +void CallbackInfo::updateGui(){ + if(m_mask==0)return; + char a[128]; + for(int i=0;i<NBITS;i++){ + if((1<<i)&m_mask){ + m_mask=0; + switch(i){ + case FAILED: + m_label->SetText("Failed"); + break; + case DONE: + m_label->SetText("Done"); + break; + case VERIFY: + m_label->SetText("Verifying"); + break; + case WAIT: + m_label->SetText("Waiting"); + break; + case ANALYZE: + m_label->SetText("Analyzing"); + break; + case SAVE: + m_label->SetText("Saving Histos"); + break; + case STOP: + m_label->SetText("RCEs done"); + break; + case DOWNLOAD: + m_label->SetText("Downloading"); + break; + case FIT: + m_label->SetText("Fit"); + break; + case NEWSTAGE: + sprintf(a, "%d", m_stage); + m_label->SetText(a); + break; + case RUNNING: + m_label->SetText("Running"); + break; + } + break; + } + } +} diff --git a/rce/rcecalib/server/CallbackInfo.hh b/rce/rcecalib/server/CallbackInfo.hh new file mode 100644 index 00000000..e5cf0034 --- /dev/null +++ b/rce/rcecalib/server/CallbackInfo.hh @@ -0,0 +1,20 @@ +#ifndef CALLBACKINFO_HH +#define CALLBACKINFO_HH + +class TGLabel; + +class CallbackInfo{ +public: + enum guistate {FAILED, DONE, VERIFY, WAIT, ANALYZE, SAVE, STOP, DOWNLOAD, FIT, NEWSTAGE, RUNNING, NBITS}; + CallbackInfo(TGLabel* label); + void addToMask(int val){m_mask|=(1<<val);} + void setStage(int stage){m_stage=stage;} + void updateGui(); + void clear(){m_mask=0;} + bool failed(){return ((m_mask&(1<<FAILED))!=0);} +private: + TGLabel* m_label; + int m_stage; + unsigned m_mask; +}; +#endif diff --git a/rce/rcecalib/server/CmdDecoder.cc b/rce/rcecalib/server/CmdDecoder.cc new file mode 100644 index 00000000..bb5122db --- /dev/null +++ b/rce/rcecalib/server/CmdDecoder.cc @@ -0,0 +1,174 @@ +#ifdef RCE_V2 +#include "datCode.hh" +#include "rcecalib/server/CmdDecoder.hh" +#include DAT_PUBLIC( service, dynalink, RunnableModule.hh) +#include DAT_PUBLIC( service, dynalink, LinkingError.hh) +#include DAT_PUBLIC( service, dynalink, Linker.hh) +#include <stdio.h> +#include <arpa/inet.h> +extern "C"{ +#include <rtems/libio.h> +} +#else +#include "rcecalib/server/CmdDecoder.hh" +#include "rce/dynalink/RunnableModule.hh" +#include "rce/dynalink/LinkingError.hh" +#include "rce/dynalink/Linker.hh" +extern "C"{ + #include <librtemsNfs.h> +} +#endif +#include <stdlib.h> +#include <signal.h> +#include <iostream> +#include <sstream> +#include "namespace_aliases.hh" + +void CmdDecoder::run(){ + const char* command; + while(1){ + command=m_eth->receiveCommand(); + std::string reply=decode(command); + m_eth->reply(reply.c_str()); + } +} + +std::string CmdDecoder::decode(const char* msg){ + //split message by whitespace + std::vector<std::string> command; + std::istringstream iss(msg); + do { + std::string sub; + iss >> sub; + command.push_back(sub); + iss.peek(); + } while (iss); + if(command.size()==0)return "Bad Command"; + if(command[0]=="reboot")return cmdReboot(command); + else if(command[0]=="setenv")return cmdSetenv(command); + else if(command[0]=="mount")return cmdMount(command); + else if(command[0]=="runTask")return cmdLd(command); + else if(command[0]=="shutdown")return cmdShutdown(command); + else if(command[0]=="download")return cmdDownload(command); + else return "Unknown command"; + return "OK"; +} +std::string CmdDecoder::cmdReboot(std::vector<std::string>& command){ + if(command.size()>1 && command[1]=="-noshutdown"){ + // do nothing + }else if(m_running==true){ + cmdShutdown(command); + usleep(500000); + } + const char *cc_argv[] = + { + "reboot", /* always the name of the program */ + "-S", + "0" + }; + int cc_argc = sizeof( cc_argv ) / sizeof( cc_argv[ 0 ] ); + m_eth->reply("Rebooting..."); +#ifdef RCE_V2 + service::shell::Reboot_main(cc_argc, (char **)cc_argv); +#else + main_reboot(cc_argc, (char **)cc_argv); +#endif + return "OK"; +} +std::string CmdDecoder::cmdSetenv(std::vector<std::string>& cmd){ + if(cmd.size()!=3)return "Wrong number of parameters for setenv."; + setenv(cmd[1].c_str(),cmd[2].c_str(), 1); + return "OK"; +} +std::string CmdDecoder::cmdMount(std::vector<std::string>& cmd){ +#ifdef RCE_V2 + if(cmd.size()!=3)return "Wrong number of parameters for mount."; + //rpcUdpInit(); + //nfsInit( 0, 0 ); + printf("BOOTP server is %s. Use as NFS server.\n",inet_ntoa( rtems_bsdnet_bootp_server_address)); + mkdir(cmd[2].c_str(),S_IRWXU|S_IRWXG|S_IRWXO); + mount(cmd[1].c_str(), cmd[2].c_str(), "nfs", RTEMS_FILESYSTEM_READ_WRITE, ""); + // int stat=mount(inet_ntoa( rtems_bsdnet_bootp_server_address), (char*)cmd[1].c_str() ,(char*)cmd[2].c_str() ); + int stat=0; + if(stat==0){ + return "OK"; + }else{ + return "NFS mount failed."; + } +#else + if(cmd.size()!=3 && cmd.size()!=4)return "Wrong number of parameters for mount."; + rpcUdpInit(); + nfsInit( 0, 0 ); + int stat=0; + if(cmd.size()==3){ + printf("BOOTP server is %s. Use as NFS server.\n",inet_ntoa( rtems_bsdnet_bootp_server_address)); + stat=nfsMount(inet_ntoa( rtems_bsdnet_bootp_server_address), (char*)cmd[1].c_str() ,(char*)cmd[2].c_str() ); + }else{ + stat=nfsMount((char*)cmd[1].c_str(), (char*)cmd[2].c_str() ,(char*)cmd[3].c_str() ); + } + if(stat==0){ + return "OK"; + }else{ + return "NFS mount failed."; + } +#endif +} +std::string CmdDecoder::cmdLd(std::vector<std::string>& cmd){ + if(cmd.size()!=2)return "Wrong number of parameters for runTask."; + if(m_running==true)return "There is already a task running. Reboot first."; + const char *cc_argv[6]={"runTask", "-P", "100", "-N", "clb", ""}; + cc_argv[5]=cmd[1].c_str(); +#ifdef RCE_V2 + int stat=service::shell::RunTask_main(6,(char**)cc_argv); +#else + int stat=main_runTask(6,(char**)cc_argv); +#endif + if(stat==0){ + m_running=true; + pause(); + return "OK"; + }else{ + return "runTask failed."; + } +} +std::string CmdDecoder::cmdShutdown(std::vector<std::string>& cmd){ + if(m_running==false)return "Calibserver is not running."; + kill(getpid(),SIGUSR1); + return "OK"; +} + +std::string CmdDecoder::cmdDownload(std::vector<std::string>& cmd){ + if(cmd.size()!=3)return "Wrong number of parameters for download."; + if(m_running==true)return "There is already a module running."; + const char* ior=getenv("TDAQ_IPC_INIT_REF"); + if(ior==0 || std::string(ior).substr(0,4)!="IOR:")return "No IOR defined"; + int bufsize=atoi(cmd[1].c_str()); + unsigned char* aBuffer; + try{ + aBuffer = RCE::ELF::RunnableModule::getBuffer(bufsize); + }catch(...){ + return "Can't allocate an ELF image buffer."; + } + m_eth->reply("OK"); + std::string reply=m_eth->receiveModule(aBuffer, bufsize); + if(reply!="OK")return reply.c_str(); + RCE::ELF::RunnableModule* rmod=new(aBuffer) RCE::ELF::RunnableModule; + try{ + RCE::Dynalink::Linker &lnk(RCE::Dynalink::Linker::instance()); + lnk.clear(); + unsigned int name=0x43414c49; //CALI + unsigned int priority = 100; + unsigned int stack = RTEMS_MINIMUM_STACK_SIZE; + unsigned int mode = RTEMS_DEFAULT_MODES; + unsigned int attr = RTEMS_DEFAULT_ATTRIBUTES; + rmod->run(name, priority, stack, mode, attr); + }catch(RCE::Dynalink::LinkingError& e) { + char rs[256]; + sprintf(rs, "Linking error: %s", e.what()); + return rs; + } + std::cout<<"Loaded module at "<<std::hex<<rmod<<std::dec<<std::endl; + m_running=true; + pause(); + return "OK"; +} diff --git a/rce/rcecalib/server/CmdDecoder.hh b/rce/rcecalib/server/CmdDecoder.hh new file mode 100644 index 00000000..ab3c7883 --- /dev/null +++ b/rce/rcecalib/server/CmdDecoder.hh @@ -0,0 +1,41 @@ +#ifndef CMDDECODER_HH +#define CMDDECODER_HH + +#include <string> +#include <vector> +#include "rcecalib/server/EthPrimitive.hh" + +// shell commands need a declaration to be used in code. +#ifdef RCE_V2 +namespace service{ + namespace shell{ + int Reboot_main(int argc, char **argv); + int RunTask_main(int argc, char **argv); + } +} +#else +int main_reboot(int argc, char **argv); +int main_runTask(int argc, char **argv); +#endif +// use global IP address of bootp server in RTEMS +extern struct in_addr rtems_bsdnet_bootp_server_address; + +class CmdDecoder{ +public: + CmdDecoder(EthPrimitive* eth): m_eth(eth),m_running(false){}; + void run(); +private: + std::string decode(const char* msg); + std::string cmdReboot(std::vector<std::string>& cmd); + std::string cmdSetenv(std::vector<std::string>& cmd); + std::string cmdMount(std::vector<std::string>& cmd); + std::string cmdLd(std::vector<std::string>& cmd); + std::string cmdShutdown(std::vector<std::string>& cmd); + std::string cmdDownload(std::vector<std::string>& cmd); + + EthPrimitive* m_eth; + bool m_running; + +}; + +#endif diff --git a/rce/rcecalib/server/ConfigGui.cc b/rce/rcecalib/server/ConfigGui.cc new file mode 100644 index 00000000..34b6a0af --- /dev/null +++ b/rce/rcecalib/server/ConfigGui.cc @@ -0,0 +1,498 @@ +#include "rcecalib/server/ConfigGui.hh" +#include "rcecalib/server/TurboDaqFile.hh" +#include "rcecalib/server/FEI4AConfigFile.hh" +#include "rcecalib/server/FEI4BConfigFile.hh" +#include "rcecalib/server/HitbusConfigFile.hh" +#include "rcecalib/server/AFPHPTDCConfigFile.hh" +#include "rcecalib/util/exceptions.hh" +#include <TGFileDialog.h> +#include <sys/stat.h> +#include <boost/regex.hpp> +#include "PixelModuleConfig.hh" +#include <iostream> + +std::string ConfigGui::m_rootdir=""; + +ConfigGui::ConfigGui(const char* name, const TGWindow *p, UInt_t w, UInt_t h, UInt_t options, const char* prefix): + TGVerticalFrame(p,w,h,options), m_modName(name), m_valid(false), m_cfg(0), m_cfgfei4a(0), m_cfgfei4b(0), m_cfghitbus(0), + m_filename("None"), m_id(-1) { + std::string namelabel(prefix); + namelabel+=name; + m_name=new TGLabel(this,namelabel.c_str()); + AddFrame(m_name,new TGLayoutHints(kLHintsCenterX|kLHintsCenterY, 2, 2, 0, 0)); + FontStruct_t labelfont; + labelfont = gClient->GetFontByName("-adobe-helvetica-medium-r-*-*-18-*-*-*-*-*-iso8859-1"); + m_name->SetTextFont(labelfont); + + TGHorizontalFrame *confnl = new TGHorizontalFrame(this, 2,2 ); + AddFrame(confnl,new TGLayoutHints(kLHintsExpandX )); + TGLabel *cfg=new TGLabel(confnl,"File:"); + confnl->AddFrame(cfg,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 0, 0)); + m_configname=new TGLabel(confnl,"None"); + confnl->AddFrame(m_configname,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 0, 0)); + //TGLabel *cfgkey=new TGLabel(confnl,"-"); + //confnl->AddFrame(cfgkey,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 0, 0)); + m_key=new TGLabel(confnl,""); + confnl->AddFrame(m_key,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 0, 0)); + + TGHorizontalFrame *confdnl = new TGHorizontalFrame(this, 2,2 ); + AddFrame(confdnl,new TGLayoutHints(kLHintsExpandX )); + TGLabel *cfgd=new TGLabel(confdnl,"Dir:"); + confdnl->AddFrame(cfgd,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 0, 0)); + m_confdir=new TGLabel(confdnl,"None"); + confdnl->AddFrame(m_confdir,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 0, 0)); + + TGHorizontalFrame *confidl = new TGHorizontalFrame(this, 2,2 ); + AddFrame(confidl,new TGLayoutHints(kLHintsExpandX )); + TGLabel *cfgid=new TGLabel(confidl,"FEID:"); + confidl->AddFrame(cfgid,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 0, 0)); + m_idl=new TGLabel(confidl,"-1"); + confidl->AddFrame(m_idl,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 0, 0)); + m_modid=new TGLabel(confidl,""); + confidl->AddFrame(m_modid,new TGLayoutHints(kLHintsRight|kLHintsCenterY, 2, 2, 0, 0)); + TGLabel *modid=new TGLabel(confidl,"ModID:"); + confidl->AddFrame(modid,new TGLayoutHints(kLHintsRight|kLHintsCenterY, 2, 2, 0, 0)); + + TGHorizontalFrame *buttonl = new TGHorizontalFrame(this, 2,2 ); + AddFrame(buttonl,new TGLayoutHints(kLHintsExpandX )); + m_choosebutton=new TGTextButton(buttonl,"Choose Config"); + buttonl->AddFrame(m_choosebutton,new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX ,2,2,0,0)); + m_choosebutton->Connect("Clicked()", "ConfigGui", this, "openFileWindow()"); + TGTextButton *reload=new TGTextButton(buttonl,"Reload"); + buttonl->AddFrame(reload,new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX ,2,2,0,0)); + reload->Connect("Clicked()", "ConfigGui", this, "setConfig()"); + + TGHorizontalFrame *conf2 = new TGHorizontalFrame(this, 2,2 ); + AddFrame(conf2,new TGLayoutHints(kLHintsExpandX )); + + TGLabel *cfgtype=new TGLabel(conf2,"Type:"); + conf2->AddFrame(cfgtype,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 0, 0)); + m_configtype=new TGLabel(conf2,""); + conf2->AddFrame(m_configtype,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 0, 0)); + + m_inlink=new TGNumberEntry(conf2, 0, 2, -1, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMinMax, 0, 15); + conf2->AddFrame(m_inlink,new TGLayoutHints(kLHintsRight|kLHintsCenterY, 0, 2, 0, 0)); + TGLabel *linklabel2=new TGLabel(conf2,"Inlink:"); + conf2->AddFrame(linklabel2,new TGLayoutHints(kLHintsRight|kLHintsCenterY, 2, 2, 0, 0)); + + TGHorizontalFrame *conf1 = new TGHorizontalFrame(this, 2,2 ); + AddFrame(conf1,new TGLayoutHints(kLHintsExpandX )); + + m_configvalid=new TGCheckButton(conf1,"Valid"); + // m_configvalid->SetEnabled(false); + m_configvalid->SetOn(false); + conf1->AddFrame(m_configvalid,new TGLayoutHints(kLHintsCenterY | kLHintsLeft | kLHintsExpandX ,2,2,0,0)); + m_configvalid->Connect("Toggled(Bool_t)", "ConfigGui", this, "dummy(Bool_t)"); + + + m_outlink=new TGNumberEntry(conf1, 0, 2, -1, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMinMax, 0, 15); + conf1->AddFrame(m_outlink,new TGLayoutHints(kLHintsRight|kLHintsCenterY, 0, 2, 0, 0)); + TGLabel *linklabel=new TGLabel(conf1,"Outlink:"); + conf1->AddFrame(linklabel,new TGLayoutHints(kLHintsRight|kLHintsCenterY, 2, 2, 0, 0)); + + + TGHorizontalFrame *conf3 = new TGHorizontalFrame(this, 2,2 ); + AddFrame(conf3,new TGLayoutHints(kLHintsExpandX )); + + m_included=new TGCheckButton(conf3,"Included"); + m_included->SetOn(false); + conf3->AddFrame(m_included,new TGLayoutHints(kLHintsCenterY | kLHintsLeft | kLHintsExpandX ,2,2,0,0)); + m_included->Connect("Toggled(Bool_t)", "ConfigGui", this, "setIncluded(Bool_t)"); + + m_rce=new TGNumberEntry(conf3, 0, 2, -1, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMinMax, 0, 99); + conf3->AddFrame(m_rce,new TGLayoutHints(kLHintsRight|kLHintsCenterY, 0, 2, 0, 0)); + TGLabel *linklabel3=new TGLabel(conf3,"Rce:"); + conf3->AddFrame(linklabel3,new TGLayoutHints(kLHintsRight|kLHintsCenterY, 2, 2, 0, 0)); + + /* + TGHorizontalFrame *conf4 = new TGHorizontalFrame(this, 2,2 ); + AddFrame(conf4,new TGLayoutHints(kLHintsExpandX )); + m_phase=new TGNumberEntry(conf4, 0, 2, -1, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMinMax, 0, 3); + conf4->AddFrame(m_phase,new TGLayoutHints(kLHintsRight|kLHintsCenterY, 0, 2, 0, 0)); + TGLabel *linklabel4=new TGLabel(conf4,"Phase:"); + conf4->AddFrame(linklabel4,new TGLayoutHints(kLHintsRight|kLHintsCenterY, 2, 2, 0, 0)); + */ +} + +ConfigGui::~ConfigGui(){ + Cleanup(); +} + +void ConfigGui::openFileWindow(){ + const char *filetypes[] = { "Config files", "*.cfg", + "All files", "*", + 0, 0 }; + boost::cmatch matches; + boost::regex re("(^.*\\/)(.+\\.cfg)"); + std::string path(m_rootdir); + std::string filename; + if(boost::regex_search(m_filename.c_str(), matches, re)){ + if(matches.size()>2){ + path=std::string(matches[1].first, matches[1].second); + filename=std::string(matches[2].first, matches[2].second); + } + } + TGFileInfo fileinfo; + fileinfo.fIniDir=StrDup(path.c_str()); + fileinfo.fFilename=StrDup(filename.c_str()); + fileinfo.fFileTypes = filetypes; + new TGFileDialog(gClient->GetRoot(), 0, kFDOpen, &fileinfo); + if(!fileinfo.fFilename){ + printf("Scheisse\n"); + return; + } + m_filename=fileinfo.fFilename; + setConfig(); +} +void ConfigGui::setId(int id){ + m_id=id; + char a[128]; + sprintf(a, "%d", id); + updateText(m_idl, a); + setModuleName(); +} + +void ConfigGui::setModuleName(){ + char modname[128]; + sprintf(modname,"RCE%d_module_%d",getRce(), getId()); + m_modulename=modname; +} + +void ConfigGui::setConfig(){ + //printf("%s\n",filename); + struct stat stFileInfo; + int intStat; + // Attempt to get the file attributes + intStat = stat(m_filename.c_str(),&stFileInfo); + if(std::string(m_filename)=="None" || intStat != 0) { //File does not exist + resetConfig(); + }else{ + std::ifstream cfgFile(m_filename.c_str()); + std::string inpline; + getline(cfgFile, inpline); //read the first line to determine configuration format + cfgFile.close(); + boost::regex r1("TurboDAQ"); + boost::regex r2("FEI4A"); + boost::regex r3("FEI4B"); + boost::regex r4("Hitbus"); + boost::regex r5("Hptdc"); + if(boost::regex_search(inpline, r1)==true){ + TurboDaqFile turbo; + delete m_cfg; + delete m_cfgfei4a; + delete m_cfgfei4b; + delete m_cfghitbus; + delete m_cfghptdc; + m_cfgfei4a=0; + m_cfgfei4b=0; + m_cfghitbus=0; + m_cfghptdc=0; + m_cfg=new ipc::PixelModuleConfig; + try{ + turbo.readModuleConfig(m_cfg,m_filename); + }catch(rcecalib::Config_File_Error &err){ + ers::error(err); + resetConfig(); + return; + } + int id=strtol((const char*)m_cfg->idStr,0,10); + setId(id); + setType("FEI3"); + updateText(m_modid, (const char*)m_cfg->idStr); + }else if(boost::regex_search(inpline, r2)==true){ + FEI4AConfigFile fei4afile; + delete m_cfg; + delete m_cfgfei4b; + delete m_cfghitbus; + delete m_cfghptdc; + m_cfg=0; + m_cfgfei4b=0; + m_cfghitbus=0; + m_cfghptdc=0; + delete m_cfgfei4a; + m_cfgfei4a=new ipc::PixelFEI4AConfig; + try{ + fei4afile.readModuleConfig(m_cfgfei4a, m_filename); + }catch(rcecalib::Config_File_Error &err){ + ers::error(err); + resetConfig(); + return; + } + setType("FEI4A"); + updateText(m_modid, (const char*)m_cfgfei4a->idStr); + unsigned newmodid=parseModuleId((const char*)m_cfgfei4a->idStr,m_cfgfei4a->FEGlobal.Chip_SN); + setId(newmodid); + }else if(boost::regex_search(inpline, r3)==true){ + FEI4BConfigFile fei4bfile; + delete m_cfg; + delete m_cfgfei4a; + delete m_cfghitbus; + delete m_cfghptdc; + m_cfg=0; + m_cfgfei4a=0; + m_cfghitbus=0; + m_cfghptdc=0; + delete m_cfgfei4b; + m_cfgfei4b=new ipc::PixelFEI4BConfig; + try{ + fei4bfile.readModuleConfig(m_cfgfei4b, m_filename); + }catch(rcecalib::Config_File_Error &err){ + ers::error(err); + resetConfig(); + return; + } + setType("FEI4B"); + updateText(m_modid, (const char*)m_cfgfei4b->idStr); + unsigned newmodid=parseModuleId((const char*)m_cfgfei4b->idStr,m_cfgfei4b->FEGlobal.Chip_SN); + setId(newmodid); + } else if(boost::regex_search(inpline, r4)==true){ + HitbusConfigFile turbo; + delete m_cfg; + delete m_cfgfei4a; + delete m_cfgfei4b; + delete m_cfghitbus; + delete m_cfghptdc; + m_cfgfei4a=0; + m_cfgfei4b=0; + m_cfghptdc=0; + m_cfg=0; + m_cfghitbus=new ipc::HitbusModuleConfig; + try{ + turbo.readModuleConfig(m_cfghitbus,m_filename); + }catch(rcecalib::Config_File_Error &err){ + ers::error(err); + resetConfig(); + return; + } + int id=strtol((const char*)m_cfghitbus->idStr,0,10); + setId(id); + setType("Hitbus"); + updateText(m_modid, (const char*)m_cfghitbus->idStr); + } else if(boost::regex_search(inpline, r5)==true){ + AFPHPTDCConfigFile turbo; + delete m_cfg; + delete m_cfgfei4a; + delete m_cfgfei4b; + delete m_cfghitbus; + delete m_cfghptdc; + m_cfgfei4a=0; + m_cfgfei4b=0; + m_cfghitbus=0; + m_cfg=0; + m_cfghptdc=new ipc::AFPHPTDCModuleConfig; + try{ + turbo.readModuleConfig(m_cfghptdc,m_filename); + }catch(rcecalib::Config_File_Error &err){ + ers::error(err); + resetConfig(); + return; + } + int id=strtol((const char*)m_cfghptdc->idStr,0,10); + setId(id); + setType("HPTDC"); + updateText(m_modid, (const char*)m_cfghptdc->idStr); + }else{ + std::cout<<"Unknown configuration format."<<std::endl; + resetConfig(); + return; + } + + setValid(true); + setIncluded(true); + } + boost::cmatch matches; + std::string res="/([^/]*)\\.cfg$"; // parse what's hopefully the config file name + boost::regex re; + re=res; + if(boost::regex_search(m_filename.c_str(), matches, re)){ + if(matches.size()>1){ + std::string match(matches[1].first, matches[1].second); + res="(.*)__([0-9]+)$"; // parse what's hopefully the key + re=res; + if(boost::regex_search(match.c_str(), matches, re)){ + if(matches.size()>2){ + std::string match1(matches[1].first, matches[1].second); + std::string match2(matches[2].first, matches[2].second); + updateText(m_configname,match1.c_str()); + updateText(m_key,match2.c_str()); + }else{ + updateText(m_configname,match.c_str()); + updateText(m_key,""); + } + }else{ + updateText(m_configname,match.c_str()); + updateText(m_key,""); + } + }else{ + updateText(m_configname,"None"); + updateText(m_key,""); + } + }else{ + updateText(m_configname,"None"); + updateText(m_key,""); + } + res="/([^/]*)/[^/]*/*[^/]*$"; // parse what's hopefully the module name + re=res; + if(boost::regex_search(m_filename.c_str(), matches, re)){ + if(matches.size()>1){ + std::string match(matches[1].first, matches[1].second); + updateText(m_confdir, match.c_str()); + m_path=m_filename.substr(0,matches.position()+1); + }else{ + updateText(m_confdir, "None"); + } + }else{ + updateText(m_confdir, "None"); + } + Layout(); +} +unsigned ConfigGui::parseModuleId(const char* module, unsigned felong){ + boost::cmatch matches; + std::string res="([0-9]+)-([0-9]+)-([0-9]+)"; // parse what's hopefully the Module name + boost::regex re; + re=res; + unsigned fe=felong&0x3f; + if(boost::regex_search(module, matches, re)){ + if(matches.size()>3){ + std::string match1(matches[1].first, matches[1].second); + std::string match2(matches[2].first, matches[2].second); + std::string match3(matches[3].first, matches[3].second); + unsigned val1=strtoul(match1.c_str(),0,10); + unsigned val2=strtoul(match2.c_str(),0,10); + unsigned val3=strtoul(match3.c_str(),0,10); + return val1*1e6+val2*1e4+val3*1e2+fe; + }else{ + //std::cout<<"Module string not parsable or FE ID>99. Using SN"<<std::endl; + return felong; + } + } + //std::cout<<"Module string not parsable. Using SN"<<std::endl; + return felong; +} +void ConfigGui::resetConfig(){ + setIncluded(false); + setValid(false); + setType(""); + setInLink(0); + setOutLink(0); + setRce(0); + updateText(m_configname,"None"); + updateText(m_modid, "None"); + m_filename="None"; + setId(-1); +} +void ConfigGui::updateText(TGLabel* label, const char* newtext){ + unsigned len=strlen(label->GetText()->GetString()); + label->SetText(newtext); + if (strlen(newtext)>len)Layout(); +} + +void ConfigGui::setIncluded(bool on){ + if(m_configvalid->IsOn()) + m_included->SetOn(on); + else + m_included->SetOn(false); +} + +void ConfigGui::setValid(bool on){ + m_configvalid->SetOn(on); + m_valid=on; +} +void ConfigGui::setType(const char* type){ + updateText(m_configtype, type); +} +void ConfigGui::dummy(bool on){ + // disable clicking + m_configvalid->SetOn(m_valid); +} + +bool ConfigGui::isValid(){ + return m_valid; +} + +const std::string ConfigGui::getType(){ + return std::string(m_configtype->GetText()->Data()); +} + +bool ConfigGui::isIncluded(){ + return m_included->IsOn() || m_included->IsDisabledAndSelected(); +} +void ConfigGui::enableControls(bool on){ + m_choosebutton->SetEnabled(on); + if((m_included->GetState()==kButtonDisabled)==on) + m_included->SetEnabled(on); + m_inlink->SetState(on); + m_outlink->SetState(on); + m_rce->SetState(on); + m_configvalid->SetEnabled(on); + //m_phase->SetState(true); +} + +void ConfigGui::writeConfig(std::ofstream &ofile){ + copyConfig(ofile, m_filename.c_str()); +} + +void ConfigGui::copyConfig(std::ofstream &ofile, const char* filename){ + std::string fn(filename); + if(fn.substr(0,m_rootdir.size())==m_rootdir){ + ofile<<fn.substr(m_rootdir.size())<<std::endl; + }else{ + ofile<<filename<<std::endl; + } + ofile<<isIncluded()<<std::endl; + ofile<<getInLink()<<std::endl; + ofile<<getOutLink()<<std::endl; + ofile<<getRce()<<std::endl; + ofile<<getPhase()<<std::endl; +} +void ConfigGui::readConfig(std::ifstream &ifile){ + ifile>>m_filename; + if(m_filename[0]!='/')m_filename=m_rootdir+m_filename; //relative path + setConfig(); + bool incl; + ifile>>incl; + setIncluded(incl); + int link; + ifile >> link; + setInLink(link); + ifile >> link; + setOutLink(link); + ifile >> link; + setRce(link); + ifile >> link; + setPhase(link); +} +void ConfigGui::copyConfig(const char* dirname){ + if(getType()=="FEI3"){ + boost::cmatch matches; + std::string res="(.*)/[^/]*/[^/]*$"; // parse what's hopefully the module name + boost::regex re; + re=res; + if(boost::regex_search(m_filename.c_str(), matches, re)){ + if(matches.size()>1){ + std::string match(matches[1].first, matches[1].second); + char cmd[512]; + sprintf(cmd,"cp -r %s %s", match.c_str(), dirname); + system (cmd); + }else + std::cout<<"Bad config file name"<<std::endl; + }else + std::cout<<"Bad config file name"<<std::endl; + }else if(getType()=="FEI4A"){ + FEI4AConfigFile cf; + cf.writeModuleConfig(getFEI4AConfig(), dirname, getConfdir(), getConfigName(), getKey()); + }else if(getType()=="FEI4B"){ + FEI4BConfigFile cf; + cf.writeModuleConfig(getFEI4BConfig(), dirname, getConfdir(), getConfigName(), getKey()); + }else if(getType()=="Hitbus"){ + HitbusConfigFile cf; + cf.writeModuleConfig(getHitbusConfig(), dirname, getConfdir(), getConfigName(), getKey()); + }else if(getType()=="HPTDC"){ + AFPHPTDCConfigFile cf; + cf.writeModuleConfig(getHPTDCConfig(), dirname, getConfdir(), getConfigName(), getKey()); + }else{ + std::cout<<"Unknown config type"<<std::endl; + assert(0); + } +} + diff --git a/rce/rcecalib/server/ConfigGui.hh b/rce/rcecalib/server/ConfigGui.hh new file mode 100644 index 00000000..752f96db --- /dev/null +++ b/rce/rcecalib/server/ConfigGui.hh @@ -0,0 +1,93 @@ +#ifndef CONFIGGUI_HH +#define CONFIGGUI_HH + +#include <TGButton.h> +#include <TGTextEntry.h> +#include <TGNumberEntry.h> +#include <TGLabel.h> +#include <string> +#include <fstream> + +namespace ipc{ + class PixelModuleConfig; + class PixelFEI4AConfig; + class PixelFEI4BConfig; + class HitbusModuleConfig; + class AFPHPTDCModuleConfig; +} +class ConfigGui: public TGVerticalFrame{ +public: + enum constants{MAX_MODULES=64}; + ConfigGui(const char* name, const TGWindow *p, UInt_t w, UInt_t h, UInt_t options, const char* prefix="Frontend "); + virtual ~ConfigGui(); + void setConfig(); + void openFileWindow(); + void setIncluded(bool on); + void setValid(bool on); + void resetConfig(); + void setType(const char* type); + void dummy(bool on); + bool isValid(); + const std::string getType(); + void enableControls(bool on); + bool isIncluded(); + ipc::PixelModuleConfig* getModuleConfig(){return m_cfg;} + ipc::PixelFEI4AConfig* getFEI4AConfig(){return m_cfgfei4a;} + ipc::PixelFEI4BConfig* getFEI4BConfig(){return m_cfgfei4b;} + ipc::HitbusModuleConfig* getHitbusConfig(){return m_cfghitbus;} + ipc::AFPHPTDCModuleConfig* getHPTDCConfig(){return m_cfghptdc;} + void setInLink(int link){m_inlink->SetIntNumber(link);} + int getInLink(){return m_inlink->GetIntNumber();} + void setOutLink(int link){m_outlink->SetIntNumber(link);} + int getOutLink(){return m_outlink->GetIntNumber();} + void setRce(int link){m_rce->SetIntNumber(link);setModuleName();} + int getRce(){return m_rce->GetIntNumber();} + void setPhase(int phase){}//{m_phase->SetIntNumber(phase);} //obsolete function + int getPhase(){return 0;}//{return m_phase->GetIntNumber();} //obsolete function + void setId(int id); + int getId(){return m_id;} + const char* getModuleName(){return m_modulename.c_str();} + const char* getConfdir(){return m_confdir->GetText()->Data();} + const char* getKey(){return m_key->GetText()->Data();} + const char* getConfigName(){return m_configname->GetText()->Data();} + const char* getModuleId(){return m_modid->GetText()->Data();} + std::string getPath(){return m_path;} + void setModuleName(); + void updateText(TGLabel* label, const char* newtext); + void readConfig(std::ifstream &ifile); + void writeConfig(std::ofstream &ofile); + void copyConfig(std::ofstream &ofile, const char* filename); + void copyConfig(const char* dirname); + void setFilename(const char* filename){m_filename=filename;} + const char* getFilename(){return m_filename.c_str();} + const char* getName(){return m_modName.c_str();} + static void setRootDir(std::string s){ + m_rootdir=s; + } + static std::string getRootDir(){ + return m_rootdir; + } +private: + unsigned parseModuleId(const char* module, unsigned fe); + TGLabel *m_name, *m_configname, *m_idl, *m_key, *m_confdir, *m_modid, *m_configtype; + TGTextButton *m_choosebutton; + TGCheckButton *m_configvalid, *m_included; + TGNumberEntry *m_inlink, *m_outlink, *m_rce, *m_phase; + std::string m_modName; + bool m_valid; + ipc::PixelModuleConfig *m_cfg; + ipc::PixelFEI4AConfig *m_cfgfei4a; + ipc::PixelFEI4BConfig *m_cfgfei4b; + ipc::HitbusModuleConfig *m_cfghitbus; + ipc::AFPHPTDCModuleConfig *m_cfghptdc; + std::string m_filename; + std::string m_modulename; + std::string m_path; + int m_id; + + static std::string m_rootdir; + + ClassDef(ConfigGui,0); +}; + +#endif diff --git a/rce/rcecalib/server/CosmicDataReceiver.cc b/rce/rcecalib/server/CosmicDataReceiver.cc new file mode 100644 index 00000000..6e5f3112 --- /dev/null +++ b/rce/rcecalib/server/CosmicDataReceiver.cc @@ -0,0 +1,268 @@ +#include "CosmicDataReceiver.hh" + +#include "CosmicGui.hh" + +#include "eudaq/TransportFactory.hh" +#include "eudaq/Event.hh" +#include "eudaq/DetectorEvent.hh" +#include "eudaq/RawDataEvent.hh" + +#include "CosmicMonitoringGuiEmbedded.hh" + +void * CosmicDataReceiver_thread(void * arg) +{ + CosmicDataReceiver * cdr = static_cast<CosmicDataReceiver *>(arg); + cdr->DataThread(); + return 0; +} + +CosmicDataReceiver::CosmicDataReceiver(CosmicGui * gui, + IPCController* controller, + std::vector<ModuleInfo*> modinfo, + std::vector<int> rcesAll, + unsigned runnum, + const std::string & listenAddress, + const std::string& outputFile, + bool writeEudet, bool writeRaw) : +m_gui(gui), +m_dataserver(eudaq::TransportFactory::CreateServer(listenAddress)), +m_thread(), +m_done(false), +m_listening(true) +{ + m_dataproc=new CosmicOfflineDataProc(controller, modinfo, rcesAll, runnum, outputFile, writeEudet, writeRaw); + m_dataserver->SetCallback(eudaq::TransportCallback(this, &CosmicDataReceiver::DataHandler)); + pthread_attr_init(&m_threadattr); + pthread_create(&m_thread, &m_threadattr, CosmicDataReceiver_thread, this); +} + +CosmicDataReceiver::~CosmicDataReceiver() +{ + usleep(250000); //wait for buffer to flush + m_done = true; + pthread_join(m_thread, 0); + delete m_dataproc; + if (m_connection.size()>0){ + for(size_t i_connect =0; i_connect<m_connection.size(); i_connect++){ + delete m_connection[i_connect]; + } + m_connection.clear(); + } + delete m_dataserver; + +} + +void CosmicDataReceiver::OnReceive(counted_ptr<eudaq::Event> ev) +{ + // std::cout << "<CosmicDataReceiver::OnReceive> : Function called!" << std::endl; + // ev->Print(std::cout); + + // counted_ptr<eudaq::DetectorEvent> event((eudaq::DetectorEvent*)eudaq::EventFactory::Create(ser)); + eudaq::DetectorEvent* dev = (eudaq::DetectorEvent*)ev.get(); + m_gui->monitoringGui->addEvent(dev); + if(dev->GetEventNumber()!=0)m_gui->incrementNevents(); + + return; +} + +void CosmicDataReceiver::DataThread() +{ + try + { + while (!m_done) m_dataserver->Process(100000); + } + catch (const std::exception & e) + { + std::cout << "Error: Uncaught exception: " << e.what() << "\n" + << "DataThread is dying..." << std::endl; + } + catch (...) + { + std::cout << "Error: Uncaught unrecognised exception: \n" + << "DataThread is dying..." << std::endl; + } + + return; +} + +void CosmicDataReceiver::DataHandler(eudaq::TransportEvent & ev) +{ + static int cout_count; // keep track of how many RECEIVE cout printout has been printed + static const int cout_limit = 3; + + // std::vector<unsigned char> begdata(ev.packet.begin(), ev.packet.end()); + // std::cout<<"received data packet with size = "<<begdata.size()<<std::endl; + + + // Note: the type of ev.id is "eudaq::ConnectionInfo" + switch (ev.etype) + { + case (eudaq::TransportEvent::CONNECT): + std::cout << "<CosmicDataReceiver::DataHandler> : CONNECT" << std::endl; + if (m_listening) + { + m_dataserver->SendPacket("OK EUDAQ DATA DataCollector", ev.id, true); + } + else + { + m_dataserver->SendPacket("ERROR EUDAQ DATA CosmicDataReceiver not accepting connections", + ev.id, true); + m_dataserver->Close(ev.id); + } + break; + + case (eudaq::TransportEvent::DISCONNECT): + std::cout << "<CosmicDataReceiver::DataHandler> : DISCONNECT" << std::endl; + if (m_connection.size()==0) + { + std::cout << "<CosmicDataReceiver::DataHandler> : Warning: disconnect attempted when no " + << "m_connection is set." << std::endl; + } + else { + + int id_connect=-1; + int nConnections = m_connection.size(); + for(int i_connect = 0; i_connect<nConnections; i_connect++){ + if (ev.id.Matches(*m_connection[i_connect])){ + id_connect = i_connect; + break; + } + } + + if(id_connect>=0){ + delete m_connection[id_connect]; + m_connection.erase(m_connection.begin() + id_connect); //remove this element from vector + } + else{ + std::cout << "<CosmicDataReceiver::DataHandler> : Warning: attempted to disconnect " + << "from "<<ev.id<<", but this does not exist in m_connection list." << std::endl; + } + + } + break; + + case (eudaq::TransportEvent::RECEIVE): + if (cout_count < cout_limit) + { + cout_count++; + std::cout << "<CosmicDataReceiver::DataHandler> : RECEIVE" << std::endl; + } + else if (cout_count == cout_limit) + { + cout_count++; + std::cout << "<CosmicDataReceiver::DataHandler> : RECEIVE (output limit reached, no more cout for future events)." << std::endl; + } + + + if (ev.id.GetState() == 0) // Waiting for identification + { + + size_t i0 = 0, i1 = ev.packet.find(' '); + if (i1 == std::string::npos) break; + std::string part(ev.packet, i0, i1); + if (part != "OK") break; + i0 = i1+1; + i1 = ev.packet.find(' ', i0); + if (i1 == std::string::npos) break; + part = std::string(ev.packet, i0, i1-i0); + if (part != "EUDAQ") break; + i0 = i1+1; + i1 = ev.packet.find(' ', i0); + if (i1 == std::string::npos) break; + part = std::string(ev.packet, i0, i1-i0); + if (part != "DATA") break; + i0 = i1+1; + i1 = ev.packet.find(' ', i0); + part = std::string(ev.packet, i0, i1-i0); + ev.id.SetType(part); + i0 = i1+1; + i1 = ev.packet.find(' ', i0); + part = std::string(ev.packet, i0, i1-i0); + ev.id.SetName(part); + + m_dataserver->SendPacket("OK", ev.id, true); + ev.id.SetState(1); + std::string name = ev.id.GetName(); + if (name != std::string("CosmicGuiDataSender")) + { + // This is not the data sender for the cosmic gui; do nothing + std::cout << "name is: " << name << std::endl; + break; + } + else + { + //Check to see if this connection is already made; if it's not, add it. + int id_connect=-1; + int nConnections = m_connection.size(); + for(int i_connect = 0; i_connect<nConnections; i_connect++){ + if (ev.id.Matches(*m_connection[i_connect])){ + id_connect = i_connect; + break; + } + } + + if(id_connect<0){ + // eudaq::ConnectionInfo* newConnection = ev.id.Clone(); + m_connection.push_back(0); + size_t nConnections = m_connection.size(); + m_connection[nConnections-1] = ev.id.Clone(); + } + else{ + std::cout << "<CosmicDataReceiver::DataHandler> : Request to connect " + << "to "<<ev.id<<", but this connection already exists. Ignoring." << std::endl; + } + + } + } + else + { + + if (m_connection.size() == 0) + { + std::cout << "<CosmicDataReceiver::DataHandler> : Receiving but m_connection is not set." + << std::endl; + } + else + { + + int id_connect=-1; + int nConnections = m_connection.size(); + for(int i_connect = 0; i_connect<nConnections; i_connect++){ + if (ev.id.Matches(*m_connection[i_connect])){ + id_connect = i_connect; + break; + } + } + + if (id_connect < 0){ + std::cout << "<CosmicDataReceiver::DataHandler> : Received data, but do not recognize the " + << " ev.id : "<<ev.id<<" , so ignoring data."<<std::endl; + break; + } + + std::vector<unsigned char> data(ev.packet.begin(), ev.packet.end()); + size_t i=0; + while(i<data.size()){ + // int length=data[i]<<8|data[i+1]; + unsigned short length=*(unsigned short*)&data[i]; + if(length==0){ + std::cout<<"Length 0 event"<<std::endl; + break; + } + unsigned short link=*(unsigned short*)&data[i+2]; + //unsigned short link=data[i+2]<<8|data[i+3]; + int retval=m_dataproc->processData(link, &data[i+4], length); + if(retval==1)break;//resynch + i+=length+4; + } + + } + } + break; + + default: + std::cout << "<CosmicDataReceiver::DataHandler> : Unknown event type: " << ev.id << std::endl; + } + + return; +} diff --git a/rce/rcecalib/server/CosmicDataReceiver.hh b/rce/rcecalib/server/CosmicDataReceiver.hh new file mode 100644 index 00000000..0f029e6b --- /dev/null +++ b/rce/rcecalib/server/CosmicDataReceiver.hh @@ -0,0 +1,45 @@ +#ifndef COSMICDATARECEIVER_HH +#define COSMICDATARECEIVER_HH + +#include <pthread.h> +#include <string> + +class CosmicGui; +class ModuleInfo; +class IPCController; + +#include "rcecalib/eudaq/TransportServer.hh" +#include "rcecalib/eudaq/Event.hh" +#include "rcecalib/dataproc/CosmicEventReceiver.hh" +#include "rcecalib/server/CosmicOfflineDataProc.hh" + +class CosmicDataReceiver: public CosmicEventReceiver +{ + public: + CosmicDataReceiver(CosmicGui * gui, + IPCController* controller, + std::vector<ModuleInfo*> modinfo, + std::vector<int> rcesAll, + unsigned runnum, + const std::string & listenAddress, const std::string& outputFile, + bool writeEudet, bool writeRaw); + ~CosmicDataReceiver(); + + void OnReceive(counted_ptr<eudaq::Event> ev); + + void DataThread(); + + private: + void DataHandler(eudaq::TransportEvent & ev); + + CosmicGui * m_gui; // Pointer to the gui to pass information back + eudaq::TransportServer * m_dataserver; // Receives the data packets + pthread_t m_thread; + pthread_attr_t m_threadattr; + bool m_done; + bool m_listening; + std::vector<eudaq::ConnectionInfo*> m_connection; + CosmicOfflineDataProc* m_dataproc; +}; + +#endif diff --git a/rce/rcecalib/server/CosmicGui.cc b/rce/rcecalib/server/CosmicGui.cc new file mode 100644 index 00000000..0bf34721 --- /dev/null +++ b/rce/rcecalib/server/CosmicGui.cc @@ -0,0 +1,1373 @@ +#include <ipc/partition.h> +#include <ipc/core.h> +#include "rcecalib/server/CosmicDataReceiver.hh" +#include "rcecalib/server/CosmicGui.hh" +#include "rcecalib/server/GlobalConfigGui.hh" +#include "rcecalib/util/VerifyErrors.hh" +#include "rcecalib/server/CosmicMonitoringGuiEmbedded.hh" +#include "rcecalib/server/IPCController.hh" +#include "rcecalib/server/PixScan.hh" +#include "rcecalib/server/TurboDaqFile.hh" +#include "rcecalib/server/ScanLog.hh" +#include "rcecalib/server/atlasimage.hh" +#include "rcecalib/config/FEI3/JJFormatter.hh" +#include "rcecalib/config/FEI4/FEI4AFormatter.hh" +#include "rcecalib/config/FEI4/FEI4BFormatter.hh" +#include "rcecalib/config/afp-hptdc/AFPHPTDCFormatter.hh" +#include "rcecalib/config/ModuleInfo.hh" +#include "ScanOptions.hh" +#include "TApplication.h" +#include "TGMsgBox.h" +#include "TGIcon.h" +#include "TGMenu.h" +#include "TGTab.h" +#include <TGFileDialog.h> +#include <TROOT.h> +#include <TStyle.h> +#include <cmdl/cmdargs.h> +#include <iostream> +#include <time.h> +#include <sys/stat.h> +#include <fstream> +#include <list> +#include <netdb.h> + + +#include <boost/property_tree/ptree.hpp> + +#include <is/infoT.h> +#include <is/infodictionary.h> + +using namespace RCE; + +CosmicGui::~CosmicGui(){ + Cleanup(); + if (m_dataReceiver) delete m_dataReceiver; + m_dataReceiver = 0; +} + +CosmicGui::CosmicGui(IPCController& controller, bool autostart, const TGWindow *p,UInt_t w,UInt_t h) + : TGMainFrame(p,w,h), m_controller(controller), m_realTime(true), m_dataReceiver(0) +{ + + // connect x icon on window manager + Connect("CloseWindow()","CosmicGui",this,"quit()"); + + TGMenuBar *menubar=new TGMenuBar(this,1,1,kHorizontalFrame | kRaisedFrame); + TGLayoutHints *menubarlayout=new TGLayoutHints(kLHintsTop|kLHintsLeft,0,4,0,0); + // menu "File" + TGPopupMenu* filepopup=new TGPopupMenu(gClient->GetRoot()); + filepopup->AddEntry("&Load Config",LOAD); + filepopup->AddEntry("&Save Config",SAVE); + filepopup->AddSeparator(); + filepopup->AddEntry("Save &Histograms",HISTOS); + filepopup->AddEntry("Save &Screenshot",SCREENSHOT); + filepopup->AddSeparator(); + filepopup->AddEntry("&Quit",QUIT); + menubar->AddPopup("&File",filepopup,menubarlayout); + + AddFrame(menubar, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 0,0,0,2)); + + filepopup->Connect("Activated(Int_t)","CosmicGui",this,"handleFileMenu(Int_t)"); + + TGTab* fTab = new TGTab(this); + AddFrame(fTab,new TGLayoutHints(kLHintsExpandX|kLHintsExpandY )) ; + TGCompositeFrame *tab0 = fTab->AddTab("Main"); + TGCompositeFrame *tab1 = fTab->AddTab("Config DUT 1-16"); + TGCompositeFrame *tab2 = fTab->AddTab("Config Telescope 1-16"); + TGCompositeFrame *datapanelt2x = fTab->AddTab("Config DUT 17-32"); + TGCompositeFrame *datapanelt2bx = fTab->AddTab("Config Telescope 17-32"); + TGCompositeFrame *tab3 = fTab->AddTab("Monitoring"); + + TGVerticalFrame* mainframe=new TGVerticalFrame(tab0,2,2,kSunkenFrame); + TGHorizontalFrame *datapanel1 = new TGHorizontalFrame(mainframe, 2, 2, kSunkenFrame); + mainframe->AddFrame(datapanel1,new TGLayoutHints(kLHintsExpandX ,0,0,0,20)); + TGHorizontalFrame *datapanel44 = new TGHorizontalFrame(mainframe, 2, 2, kSunkenFrame); + mainframe->AddFrame(datapanel44,new TGLayoutHints(kLHintsExpandX ,0,0,0,20)); + TGHorizontalFrame *datapanel2 = new TGHorizontalFrame(mainframe, 2, 2, kSunkenFrame); + mainframe->AddFrame(datapanel2,new TGLayoutHints(kLHintsExpandX )); + TGHorizontalFrame *datapanel3 = new TGHorizontalFrame(mainframe, 2, 2, kSunkenFrame); + mainframe->AddFrame(datapanel3,new TGLayoutHints(kLHintsExpandX)); + TGHorizontalFrame *datapanel5 = new TGHorizontalFrame(mainframe, 2, 2, kSunkenFrame); + mainframe->AddFrame(datapanel5,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY)); + tab0->AddFrame(mainframe,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY)); + + TGVerticalFrame *datapanel4[4]; + datapanel4[0] = new TGVerticalFrame(tab1, 2, 2, kSunkenFrame); + tab1->AddFrame(datapanel4[0],new TGLayoutHints(kLHintsExpandX)); + datapanel4[1] = new TGVerticalFrame(tab2, 2, 2, kSunkenFrame); + tab2->AddFrame(datapanel4[1],new TGLayoutHints(kLHintsExpandX)); + datapanel4[2] = new TGVerticalFrame(datapanelt2x, 2, 2, kSunkenFrame); + datapanelt2x->AddFrame(datapanel4[2],new TGLayoutHints(kLHintsExpandX)); + datapanel4[3] = new TGVerticalFrame(datapanelt2bx, 2, 2, kSunkenFrame); + datapanelt2bx->AddFrame(datapanel4[3],new TGLayoutHints(kLHintsExpandX)); + + + + int modperpanel=ConfigGui::MAX_MODULES/4; + for(int j=0;j<4;j++){ + TGHorizontalFrame *datapanelb=new TGHorizontalFrame(datapanel4[j]); + datapanel4[j]->AddFrame(datapanelb,new TGLayoutHints(kLHintsExpandX )); + TGTextButton *alloff=new TGTextButton(datapanelb,"All Off"); + alloff->SetMargins(15,25,0,0); + datapanelb->AddFrame(alloff,new TGLayoutHints(kLHintsCenterY | kLHintsLeft ,2,2,2,2)); + TGTextButton *allon=new TGTextButton(datapanelb,"All On"); + allon->SetMargins(15,25,0,0); + datapanelb->AddFrame(allon,new TGLayoutHints(kLHintsCenterY | kLHintsLeft ,2,2,2,2)); + if(j==0){ + alloff->Connect("Clicked()", "CosmicGui", this,"allOffA()"); + allon->Connect("Clicked()", "CosmicGui", this,"allOnA()"); + }else if(j==1){ + alloff->Connect("Clicked()", "CosmicGui", this,"allOffC()"); + allon->Connect("Clicked()", "CosmicGui", this,"allOnC()"); + }else if(j==2){ + alloff->Connect("Clicked()", "CosmicGui", this,"allOffA2()"); + allon->Connect("Clicked()", "CosmicGui", this,"allOnA2()"); + }else if(j==3){ + alloff->Connect("Clicked()", "CosmicGui", this,"allOffC2()"); + allon->Connect("Clicked()", "CosmicGui", this,"allOnC2()"); + } + TGHorizontalFrame *datapanelc[4]; + for(int i=0;i<4;i++){ + datapanelc[i] = new TGHorizontalFrame(datapanel4[j]); + datapanel4[j]->AddFrame(datapanelc[i],new TGLayoutHints(kLHintsExpandX |kLHintsExpandY)); + } + char modname[128]; + for (int i=0;i<modperpanel;i++){ + if(j%2==0) sprintf(modname, "DUT FE %d", 1+i+(j/2)*16); + else sprintf(modname, "Telescope FE %d", 1+i+(j/2)*16); + m_config[i+modperpanel*j]=new ConfigGui(modname, datapanelc[i/(modperpanel/4)],1,1, kSunkenFrame, ""); + datapanelc[i/(modperpanel/4)]->AddFrame(m_config[i+modperpanel*j],new TGLayoutHints(kLHintsExpandX | kLHintsExpandY,2,2,1,1)); + } + } + + std::vector<ConfigGui*> vec_config(m_config,m_config+ConfigGui::MAX_MODULES); + monitoringGui = new CosmicMonitoringGuiEmbedded(tab3,1,1,kSunkenFrame,vec_config); + tab3->AddFrame(monitoringGui,new TGLayoutHints(kLHintsExpandX|kLHintsExpandY)); + + m_globalconf=new GlobalConfigGui(m_config, ".cosmicDaq.rc", datapanel1, 1, 1, kSunkenFrame); + datapanel1->AddFrame(m_globalconf,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY,2,2,2,2)); + + m_isrunning=false; + m_nevtMin=0; + m_nevt=0; + m_timers=new TTimer; + m_timers->Connect("Timeout()","CosmicGui",this,"timeouts()"); + m_timerm=new TTimer; + m_timerm->Connect("Timeout()","CosmicGui",this,"timeoutm()"); + m_timerl=new TTimer; + m_timerl->Connect("Timeout()","CosmicGui",this,"timeoutl()"); + + FontStruct_t maskfont= gClient->GetFontByName("-adobe-helvetica-bold-r-*-*-12-*-*-*-*-*-iso8859-1"); + TGVerticalFrame *startmenu = new TGVerticalFrame(datapanel2, 0, 0, kSunkenFrame); + datapanel2->AddFrame(startmenu, new TGLayoutHints(kLHintsTop|kLHintsLeft, 2,2,0,2)); + TGLabel *startmenulabel=new TGLabel(startmenu,"Run Options:"); + startmenulabel->SetTextFont(maskfont); + startmenu->AddFrame(startmenulabel,new TGLayoutHints(kLHintsCenterX|kLHintsTop, 2, 2, 0, 50)); + + m_start=new TGTextButton(startmenu,"Start Run"); + FontStruct_t labelfont; + labelfont = gClient->GetFontByName("-adobe-helvetica-medium-r-*-*-18-*-*-*-*-*-iso8859-1"); + m_start->SetFont(labelfont); + m_start->SetMargins(10,40,10,10); + startmenu->AddFrame(m_start,new TGLayoutHints(kLHintsCenterY | kLHintsCenterX ,2,2,5,5)); + m_start->Connect("Clicked()", "CosmicGui", this, "toggle()"); + + TGHorizontalFrame *maxevents = new TGHorizontalFrame(startmenu); + startmenu->AddFrame(maxevents, new TGLayoutHints(kLHintsCenterY|kLHintsLeft,0,0,5,5)); + + m_maxtrue = new TGCheckButton(maxevents); + maxevents->AddFrame(m_maxtrue, new TGLayoutHints(kLHintsLeft|kLHintsCenterY)); + TGLabel *maximum=new TGLabel(maxevents,"Max Evts"); + maxevents->AddFrame(maximum, new TGLayoutHints(kLHintsLeft|kLHintsCenterY,0,0,0,0)); + m_maxevents=new TGNumberEntry(maxevents, 0, 10, -1, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMin, 0); + maxevents->AddFrame(m_maxevents, new TGLayoutHints(kLHintsCenterY|kLHintsLeft,5,0,5,5)); + TGVerticalFrame *fileframe= new TGVerticalFrame(startmenu, 0, 0, kSunkenFrame); + startmenu->AddFrame(fileframe,new TGLayoutHints(kLHintsCenterY|kLHintsCenterX ,10,0,20,10)); + TGLabel *filelabel=new TGLabel(fileframe,"File Format:"); + fileframe->AddFrame(filelabel,new TGLayoutHints(kLHintsRight|kLHintsCenterY, 2, 2, 2, 0)); + m_eudetfile=new TGCheckButton(fileframe,"Eudet"); + fileframe->AddFrame(m_eudetfile,new TGLayoutHints(kLHintsCenterY | kLHintsLeft ,15,0,3,3)); + m_rawfile=new TGCheckButton(fileframe,"Raw"); + fileframe->AddFrame(m_rawfile,new TGLayoutHints(kLHintsCenterY | kLHintsLeft ,15,0,3,3)); + m_writeRootFile=new TGCheckButton(fileframe,"ROOT"); + fileframe->AddFrame(m_writeRootFile,new TGLayoutHints(kLHintsCenterY | kLHintsLeft ,15,0,3,3)); + + + TGVerticalFrame *trigmenu1 = new TGVerticalFrame(datapanel2, 0, 0, kSunkenFrame); + datapanel2->AddFrame(trigmenu1,new TGLayoutHints(kLHintsCenterY ,2,0,0,0)); + + TGLabel *tscl=new TGLabel(trigmenu1,"Trigger Sources:"); + tscl->SetTextFont(maskfont); + trigmenu1->AddFrame(tscl,new TGLayoutHints(kLHintsCenterX|kLHintsCenterY, 0, 0, 0, 0)); + m_scint=new TGCheckButton(trigmenu1,"Scintillators"); + trigmenu1->AddFrame(m_scint,new TGLayoutHints(kLHintsCenterY | kLHintsLeft ,0,0,0,0)); + m_eudet=new TGCheckButton(trigmenu1,"Eudet Trg"); + trigmenu1->AddFrame(m_eudet,new TGLayoutHints(kLHintsCenterY | kLHintsLeft ,0,0,0,0)); + TGVerticalFrame *trigmenu7 = new TGVerticalFrame(trigmenu1, 0, 0, kSunkenFrame); + trigmenu1->AddFrame(trigmenu7,new TGLayoutHints(kLHintsCenterX ,5,0,0,0)); + TGHorizontalFrame *trigmenu7a = new TGHorizontalFrame(trigmenu7); + trigmenu7->AddFrame(trigmenu7a,new TGLayoutHints(kLHintsCenterX ,0,0,0,0)); + TGVerticalFrame *trigmenu7b = new TGVerticalFrame(trigmenu7a); + trigmenu7a->AddFrame(trigmenu7b,new TGLayoutHints(kLHintsCenterX ,0,0,0,0)); + TGVerticalFrame *trigmenu7c = new TGVerticalFrame(trigmenu7a); + trigmenu7a->AddFrame(trigmenu7c,new TGLayoutHints(kLHintsCenterX ,0,0,0,0)); + m_HSIO1=new TGCheckButton(trigmenu7b,"HSIO Ext 1"); + trigmenu7b->AddFrame(m_HSIO1,new TGLayoutHints(kLHintsCenterY | kLHintsLeft ,0,0,15,0)); + m_HSIO2=new TGCheckButton(trigmenu7b,"HSIO Ext 2"); + trigmenu7b->AddFrame(m_HSIO2,new TGLayoutHints(kLHintsCenterY | kLHintsLeft ,0,0,0,0)); + m_hsiologic=new TGButtonGroup(trigmenu7c, 2, 1, 2, 0, "Logic"); + trigmenu7c->AddFrame(m_hsiologic, new TGLayoutHints(kLHintsTop | kLHintsLeft, 2, 0, 0, 0)); + new TGRadioButton(m_hsiologic, "OR", 0); + new TGRadioButton(m_hsiologic, "AND", 1); + m_hsiologic->SetButton(1); + m_hsiostate=1; + m_hsiologic->Connect("Pressed(Int_t)", "CosmicGui", this, "setHsioLogic(Int_t)"); + + TGVerticalFrame *trigmenu4 = new TGVerticalFrame(trigmenu1, 0, 0, kSunkenFrame); + trigmenu1->AddFrame(trigmenu4,new TGLayoutHints(kLHintsCenterX ,15,0,0,0)); + m_cyclic=new TGCheckButton(trigmenu4,"Cyclic Trg"); + trigmenu4->AddFrame(m_cyclic,new TGLayoutHints(kLHintsCenterY | kLHintsLeft ,0,0,0,0)); + TGLabel *cperiodl=new TGLabel(trigmenu4,"Cyclic Period (ticks)"); + trigmenu4->AddFrame(cperiodl,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 3, 3, 0, 0)); + m_cperiod=new TGNumberEntry(trigmenu4,0,10,-1,TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative); + trigmenu4->AddFrame(m_cperiod,new TGLayoutHints(kLHintsCenterY |kLHintsCenterX, 0, 0, 3, 3)); + TGVerticalFrame *trigmenuhb = new TGVerticalFrame(trigmenu1, 0, 0, kSunkenFrame); + trigmenu1->AddFrame(trigmenuhb,new TGLayoutHints(kLHintsCenterX ,15,0,0,0)); + m_hitbus=new TGCheckButton(trigmenuhb,"Hitbus"); + trigmenuhb->AddFrame(m_hitbus,new TGLayoutHints(kLHintsTop | kLHintsLeft ,0,0,0,0)); + m_hbinput=new TGButtonGroup(trigmenuhb, 4, 1, 4, 0, "Logic"); + trigmenuhb->AddFrame(m_hbinput, new TGLayoutHints(kLHintsTop | kLHintsLeft, 2, 0, 0, 0)); + new TGRadioButton(m_hbinput, "Chip 1", 1); + new TGRadioButton(m_hbinput, "Chip 2", 2); + new TGRadioButton(m_hbinput, "1 OR 2", 3); + new TGRadioButton(m_hbinput, "1 AND 2", 4); + m_hbstate=1; + m_hbinput->Connect("Pressed(Int_t)", "CosmicGui", this, "setHbLogic(Int_t)"); + + + TGVerticalFrame *hbframe= new TGVerticalFrame(datapanel2, 0, 0, kSunkenFrame); + datapanel2->AddFrame(hbframe,new TGLayoutHints(kLHintsTop ,5,0,0,0)); + TGLabel *hbchiplabel=new TGLabel(hbframe,"Hitbus Chips:"); + hbchiplabel->SetTextFont(maskfont); + hbframe->AddFrame(hbchiplabel,new TGLayoutHints(kLHintsCenterX|kLHintsTop, 2, 2, 0, 0)); + TGTab* hTab = new TGTab(hbframe); + hbframe->AddFrame(hTab,new TGLayoutHints(kLHintsExpandX|kLHintsExpandY )) ; + TGCompositeFrame *tabh[2]; + tabh[0] = hTab->AddTab("Hitbus Chip 1"); + tabh[1] = hTab->AddTab("Hitbus Chip 2"); + for (int k=0;k<2;k++){ + TGHorizontalFrame *trigmenu5 = new TGHorizontalFrame(tabh[k]); + tabh[k]->AddFrame(trigmenu5,new TGLayoutHints(kLHintsCenterY ,15,2,2,2)); + TGVerticalFrame *planeframe= new TGVerticalFrame(trigmenu5); + trigmenu5->AddFrame(planeframe, new TGLayoutHints(kLHintsCenterY)); + m_tp[k][0]=new TGCheckButton(planeframe,"TA1"); + m_tp[k][1]=new TGCheckButton(planeframe,"TA2"); + m_tp[k][2]=new TGCheckButton(planeframe,"TA3"); + m_tp[k][3]=new TGCheckButton(planeframe,"TB1"); + m_tp[k][4]=new TGCheckButton(planeframe,"TB2"); + m_tp[k][5]=new TGCheckButton(planeframe,"TB3"); + for (int i=0;i<3;i++) + planeframe->AddFrame(m_tp[k][i],new TGLayoutHints(kLHintsTop | kLHintsLeft ,2,0,0,0)); + TGLabel *hcl=new TGLabel(planeframe,"RCE"); + planeframe->AddFrame(hcl,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 0, 0, 10, 0)); + m_hbrce[k]=new TGNumberEntry(planeframe,0,2,-1,TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative); + planeframe->AddFrame(m_hbrce[k],new TGLayoutHints(kLHintsCenterY |kLHintsLeft, 0, 0, 3, 10)); + for (int i=3;i<6;i++) + planeframe->AddFrame(m_tp[k][i],new TGLayoutHints(kLHintsTop | kLHintsLeft ,2,0,0,0)); + TGVerticalFrame *logframe= new TGVerticalFrame(trigmenu5); + trigmenu5->AddFrame(logframe, new TGLayoutHints(kLHintsTop)); + m_talogic[k]=new TGButtonGroup(logframe, "TA Logic"); + logframe->AddFrame(m_talogic[k], new TGLayoutHints(kLHintsTop | kLHintsLeft, 2, 0, 0, 0)); + new TGRadioButton(m_talogic[k], "OR", 0); + new TGRadioButton(m_talogic[k], "AND", 1); + m_talogic[k]->SetButton(0); + m_tastate[k]=0; + m_tablogic[k]=new TGButtonGroup(logframe, 1, 2, 5, 0, "TA to TB"); + logframe->AddFrame(m_tablogic[k], new TGLayoutHints(kLHintsTop | kLHintsLeft, 2, 0, 0, 0)); + new TGRadioButton(m_tablogic[k], "OR", 0); + new TGRadioButton(m_tablogic[k], "AND", 1); + m_tablogic[k]->SetButton(0); + m_tabstate[k]=0; + m_tblogic[k]=new TGButtonGroup(logframe, "TB Logic"); + logframe->AddFrame(m_tblogic[k], new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 0, 0)); + new TGRadioButton(m_tblogic[k], "OR", 0); + new TGRadioButton(m_tblogic[k], "AND", 1); + m_tblogic[k]->SetButton(0); + } + m_talogic[0]->Connect("Pressed(Int_t)", "CosmicGui", this, "setTaLogic0(Int_t)"); + m_tablogic[0]->Connect("Pressed(Int_t)", "CosmicGui", this, "setTabLogic0(Int_t)"); + m_tblogic[0]->Connect("Pressed(Int_t)", "CosmicGui", this, "setTbLogic0(Int_t)"); + m_talogic[1]->Connect("Pressed(Int_t)", "CosmicGui", this, "setTaLogic1(Int_t)"); + m_tablogic[1]->Connect("Pressed(Int_t)", "CosmicGui", this, "setTabLogic1(Int_t)"); + m_tblogic[1]->Connect("Pressed(Int_t)", "CosmicGui", this, "setTbLogic1(Int_t)"); + TGHorizontalFrame *hbdel = new TGHorizontalFrame(hbframe); + hbframe->AddFrame(hbdel,new TGLayoutHints(kLHintsBottom ,15,2,2,2)); + TGLabel *hmdellabel=new TGLabel(hbdel,"D-:"); + hbdel->AddFrame(hmdellabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + m_hbdelaym=new TGNumberEntry(hbdel, 0, 5, -1, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMinMax, 0, 31); + hbdel->AddFrame(m_hbdelaym,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 0, 2, 2, 0)); + m_hbdelay=new TGNumberEntry(hbdel, 0, 5, -1, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMinMax, 0, 31); + hbdel->AddFrame(m_hbdelay,new TGLayoutHints(kLHintsRight|kLHintsCenterY, 0, 2, 2, 0)); + TGLabel *hdellabel=new TGLabel(hbdel,"D+:"); + hbdel->AddFrame(hdellabel,new TGLayoutHints(kLHintsRight|kLHintsCenterY, 2, 2, 2, 0)); + + + TGVerticalFrame *discframe= new TGVerticalFrame(datapanel2, 0, 0, kSunkenFrame); + datapanel2->AddFrame(discframe,new TGLayoutHints(kLHintsTop ,5,0,0,0)); + + TGLabel *scint=new TGLabel(discframe,"Scintillators"); + scint->SetTextFont(maskfont); + discframe->AddFrame(scint,new TGLayoutHints(kLHintsCenterX|kLHintsCenterY,0,0,0,0)); + TGHorizontalFrame *trigmenu6 = new TGHorizontalFrame(discframe); + discframe->AddFrame(trigmenu6,new TGLayoutHints(kLHintsCenterY ,15,2,2,2)); + TGVerticalFrame *aframe= new TGVerticalFrame(trigmenu6); + trigmenu6->AddFrame(aframe, new TGLayoutHints(kLHintsTop,0,0,0,0)); + TGLabel *ahcl=new TGLabel(aframe,"Scint:"); + aframe->AddFrame(ahcl,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 0, 0, 0, 0)); + m_NAND[0]=new TGCheckButton(aframe,"0"); + m_NAND[1]=new TGCheckButton(aframe,"1"); + m_NAND[2]=new TGCheckButton(aframe,"2"); + m_NAND[3]=new TGCheckButton(aframe,"3"); + for (int i=0;i<4;i++){ + aframe->AddFrame(m_NAND[i],new TGLayoutHints(kLHintsTop|kLHintsLeft ,2,0,0,0)); + } + TGVerticalFrame *alogframe= new TGVerticalFrame(trigmenu6); + trigmenu6->AddFrame(alogframe, new TGLayoutHints(kLHintsTop)); + TGLabel *bhcl = new TGLabel(alogframe,"Logic:"); + alogframe->AddFrame(bhcl, new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 0, 0, 0, 0)); + m_NANDlogic[0]=new TGCheckButton(alogframe,"Anti"); + m_NANDlogic[1]=new TGCheckButton(alogframe,"Anti"); + m_NANDlogic[2]=new TGCheckButton(alogframe,"Anti"); + m_NANDlogic[3]=new TGCheckButton(alogframe,"Anti"); + for (int i=0;i<4;i++){ + alogframe->AddFrame(m_NANDlogic[i], new TGLayoutHints(kLHintsTop | kLHintsLeft, 2, 0, 0,0)); + } + + TGHorizontalFrame *delayframe= new TGHorizontalFrame(discframe); + discframe->AddFrame(delayframe, new TGLayoutHints(kLHintsCenterY|kLHintsCenterX, 2, 2, 2, 2)); + TGVerticalFrame *delayframe1= new TGVerticalFrame(delayframe); + delayframe->AddFrame(delayframe1, new TGLayoutHints(kLHintsCenterY|kLHintsCenterX)); + TGVerticalFrame *delayframe2= new TGVerticalFrame(delayframe); + delayframe->AddFrame(delayframe2, new TGLayoutHints(kLHintsCenterY|kLHintsCenterX)); + + + TGLabel *delay0label=new TGLabel(delayframe1,"Sc0 Del:"); + delayframe1->AddFrame(delay0label,new TGLayoutHints(kLHintsLeft|kLHintsCenterY|kLHintsCenterX, 2, 2, 2, 0)); + m_delay0=new TGNumberEntry(delayframe1, 0, 2, -1, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMinMax, 0, 63); + delayframe1->AddFrame(m_delay0,new TGLayoutHints(kLHintsLeft|kLHintsCenterY|kLHintsCenterX, 0, 0, 0, 0)); + + TGLabel *delay1label=new TGLabel(delayframe1,"Sc1 Del:"); + delayframe1->AddFrame(delay1label,new TGLayoutHints(kLHintsLeft|kLHintsCenterY|kLHintsCenterX, 2, 2, 2, 0)); + m_delay1=new TGNumberEntry(delayframe1, 0, 2, -1, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMinMax, 0, 63); + delayframe1->AddFrame(m_delay1,new TGLayoutHints(kLHintsLeft|kLHintsCenterY|kLHintsCenterX, 0, 0, 0, 0)); + + + TGLabel *delay2label=new TGLabel(delayframe2,"Sc2 Del:"); + delayframe2->AddFrame(delay2label,new TGLayoutHints(kLHintsLeft|kLHintsCenterY|kLHintsCenterX, 2, 2, 2, 0)); + m_delay2=new TGNumberEntry(delayframe2, 0, 2, -1, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMinMax, 0, 63); + delayframe2->AddFrame(m_delay2,new TGLayoutHints(kLHintsLeft|kLHintsCenterY|kLHintsCenterX, 0, 0, 0, 0)); + + TGLabel *delay3label=new TGLabel(delayframe2,"Sc3 Del:"); + delayframe2->AddFrame(delay3label,new TGLayoutHints(kLHintsLeft|kLHintsCenterY|kLHintsCenterX, 2, 2, 2, 0)); + m_delay3=new TGNumberEntry(delayframe2, 0, 2, -1, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMinMax, 0, 63); + delayframe2->AddFrame(m_delay3,new TGLayoutHints(kLHintsLeft|kLHintsCenterY|kLHintsCenterX, 0, 0, 0, 0)); + + + TGVerticalFrame *quitmenu = new TGVerticalFrame(datapanel2, 0, 0); + datapanel2->AddFrame(quitmenu, new TGLayoutHints(kLHintsTop|kLHintsCenterX, 0, 0, 0, 0)); + + TGVerticalFrame *phasebusyframe=new TGVerticalFrame(quitmenu, 0, 0, kSunkenFrame); + quitmenu->AddFrame(phasebusyframe, new TGLayoutHints(kLHintsTop|kLHintsExpandX|kLHintsCenterX, 2, 2, 2, 2)); + TGLabel *phasebusylabel=new TGLabel(phasebusyframe,"Phase busy"); + phasebusylabel->SetTextFont(maskfont); + phasebusyframe->AddFrame(phasebusylabel, new TGLayoutHints(kLHintsCenterX|kLHintsCenterY, 0, 0, 0, 0)); + + m_phasebusyen=new TGCheckButton(phasebusyframe, "Enable"); + phasebusyframe->AddFrame(m_phasebusyen, new TGLayoutHints(kLHintsTop|kLHintsLeft, 2, 2, 2, 2)); + m_phasebusysel=new TGButtonGroup(phasebusyframe, 2, 2, 4, 0, "Active phase"); + phasebusyframe->AddFrame(m_phasebusysel, new TGLayoutHints(kLHintsTop|kLHintsLeft, 2, 0, 0, 0)); + new TGRadioButton(m_phasebusysel, "0->0", 0); + new TGRadioButton(m_phasebusysel, "0->1", 1); + new TGRadioButton(m_phasebusysel, "1->1", 3); + new TGRadioButton(m_phasebusysel, "1->0", 2); + m_phasebusysel->Connect("Pressed(Int_t)", "CosmicGui", this, "setTriggerActivePhase(Int_t)"); + m_phasebusysel->SetButton(0); + m_phasebusystate=0; + + TGHorizontalFrame *tempframe= new TGHorizontalFrame(quitmenu); + quitmenu->AddFrame(tempframe, new TGLayoutHints(kLHintsTop|kLHintsCenterX|kLHintsExpandX, 2, 2, 2, 2)); + TGVerticalFrame *tempframe1= new TGVerticalFrame(tempframe,0,0,kSunkenFrame); + tempframe->AddFrame(tempframe1, new TGLayoutHints(kLHintsTop|kLHintsCenterX|kLHintsExpandX)); + TGLabel *tempmenulabel=new TGLabel(tempframe1,"FE Temperatures:"); + tempmenulabel->SetTextFont(maskfont); + tempframe1->AddFrame(tempmenulabel,new TGLayoutHints(kLHintsCenterX|kLHintsTop, 2, 2, 0, 0)); + m_tempenable=new TGCheckButton(tempframe1,"Read Temps"); + m_tempenable->Connect("Clicked()", "CosmicGui", this, "synchSave2()"); + tempframe1->AddFrame(m_tempenable,new TGLayoutHints(kLHintsTop | kLHintsLeft ,2,2,2,2)); + m_templog=new TGCheckButton(tempframe1,"Log Temps"); + m_templog->Connect("Clicked()", "CosmicGui", this, "synchSave1()"); + tempframe1->AddFrame(m_templog,new TGLayoutHints(kLHintsTop | kLHintsLeft ,2,2,2,5)); + TGLabel *tempfreqlabel=new TGLabel(tempframe1,"Frequency:"); + tempframe1->AddFrame(tempfreqlabel,new TGLayoutHints(kLHintsCenterX|kLHintsTop, 2, 2, 0, 0)); + m_tempfreq=new TGComboBox(tempframe1,100); + tempframe1->AddFrame(m_tempfreq,new TGLayoutHints(kLHintsTop | kLHintsCenterX,2,2,2,2)); + m_tempfreq->AddEntry("0.1 Hz", 400000000); + m_tempfreq->AddEntry("0.2 Hz", 200000000); + m_tempfreq->AddEntry("0.5 Hz", 80000000); + m_tempfreq->AddEntry("1 Hz", 40000000); + m_tempfreq->Resize(100,20); + + m_quit=new TGTextButton(quitmenu,"Quit"); + m_quit->Connect("Clicked()", "CosmicGui", this,"quit()"); + m_quit->SetFont(labelfont); + m_quit->SetMargins(15,30,10,10); + quitmenu->AddFrame(m_quit,new TGLayoutHints(kLHintsCenterY | kLHintsCenterX ,2,2,15,5)); + + TGLabel *timelabel=new TGLabel(datapanel3,"Time:"); + datapanel3->AddFrame(timelabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 10, 0)); + m_time=new TGLabel(datapanel3,"0 s "); + datapanel3->AddFrame(m_time,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 30, 0, 0)); + m_time->SetTextFont(labelfont); + + TGLabel *nevlabel=new TGLabel(datapanel3,"Events:"); + datapanel3->AddFrame(nevlabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 10, 0)); + m_nEvents=new TGLabel(datapanel3,"0 "); + datapanel3->AddFrame(m_nEvents,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 0, 0)); + m_nEvents->SetTextFont(labelfont); + + TGLabel *ratelabel=new TGLabel(datapanel3,"Total Rate:"); + datapanel3->AddFrame(ratelabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 10, 0)); + m_rate=new TGLabel(datapanel3,"0.00 Hz "); + datapanel3->AddFrame(m_rate,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 10, 0)); + m_rate->SetTextFont(labelfont); + + TGLabel *iratelabel=new TGLabel(datapanel3,"Current Rate:"); + datapanel3->AddFrame(iratelabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 10, 0)); + m_irate=new TGLabel(datapanel3,"0.00 Hz "); + datapanel3->AddFrame(m_irate,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 10, 0)); + m_irate->SetTextFont(labelfont); + + TGLabel *ihitlabel=new TGLabel(datapanel3,"Hits per Event:"); + datapanel3->AddFrame(ihitlabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 10, 0)); + m_hpe=new TGLabel(datapanel3,"0.00 "); + datapanel3->AddFrame(m_hpe,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 10, 0)); + m_hpe->SetTextFont(labelfont); + + + + TGLabel *latencylabel=new TGLabel(datapanel44,"Latency:"); + datapanel44->AddFrame(latencylabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + latencylabel->SetTextFont(maskfont); + latencylabel=new TGLabel(datapanel44,"DUT"); + datapanel44->AddFrame(latencylabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + m_l1alatency=new TGNumberEntry(datapanel44, 0, 3, -1, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMinMax, 0, 255); + datapanel44->AddFrame(m_l1alatency,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 0, 2, 2, 0)); + latencylabel=new TGLabel(datapanel44,"Telescope"); + datapanel44->AddFrame(latencylabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + m_l1alatencytel=new TGNumberEntry(datapanel44, 0, 3, -1, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMinMax, 0, 255); + datapanel44->AddFrame(m_l1alatencytel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 0, 2, 2, 0)); + + TGLabel *ntrglabel=new TGLabel(datapanel44,"Consec. Trgs:"); + ntrglabel->SetTextFont(maskfont); + datapanel44->AddFrame(ntrglabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 20, 2, 2, 0)); + ntrglabel=new TGLabel(datapanel44,"DUT"); + datapanel44->AddFrame(ntrglabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + m_ntrg=new TGNumberEntry(datapanel44, 0, 3, -1, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMinMax, 1, 16); + datapanel44->AddFrame(m_ntrg,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 0, 2, 2, 0)); + ntrglabel=new TGLabel(datapanel44,"Telescope"); + datapanel44->AddFrame(ntrglabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + m_ntrgtel=new TGNumberEntry(datapanel44, 0, 3, -1, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMinMax, 1, 16); + datapanel44->AddFrame(m_ntrgtel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 0, 2, 2, 0)); + + + TGLabel *delaylabel=new TGLabel(datapanel44,"Trg Delay:"); + delaylabel->SetTextFont(maskfont); + datapanel44->AddFrame(delaylabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 20, 2, 2, 0)); + m_trgdelay=new TGNumberEntry(datapanel44, 0, 3, -1, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMinMax, 0, 255); + datapanel44->AddFrame(m_trgdelay,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 0, 2, 2, 0)); + + TGLabel *deadtimelabel=new TGLabel(datapanel44,"Deadtime:"); + deadtimelabel->SetTextFont(maskfont); + datapanel44->AddFrame(deadtimelabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + m_deadtime=new TGNumberEntry(datapanel44, 0, 5, -1, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMinMax, 0, 65535); + datapanel44->AddFrame(m_deadtime,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 0, 2, 2, 0)); + + + TGPicturePool tgpool(0,0); + const TGPicture* pic=tgpool.GetPicture("atlas",const_cast<char**>(atlas_detector_small)); + TGIcon* tgi=new TGIcon(datapanel5 ,pic,300,196); + datapanel5->AddFrame(tgi,new TGLayoutHints(kLHintsCenterX|kLHintsCenterY, 0, 2, 10, 0)); + // m_controller.writeHWregister(4,1); + // sleep(1); + // unsigned counter4=m_controller.readHWregister(9); + // unsigned counter10=m_controller.readHWregister(10); + // unsigned l1counter=m_controller.readHWregister(11); + // unsigned counter4m=m_controller.readHWregister(12); + // unsigned counter10m=m_controller.readHWregister(13); + // unsigned counter10e=m_controller.readHWregister(14); + // unsigned tdccounter=m_controller.readHWregister(15); + // std::cout<<"Counter 4: "<<counter4<<" Counter 10: "<<counter10<<std::endl; + // std::cout<<"Counter 4m: "<<counter4m<<" Counter 10m: "<<counter10m<<std::endl; + // std::cout<<"Counter 10e: "<<counter10e<<" TDC counter: "<<(tdccounter&0xffff)<<std::endl; + // std::cout<<"l1counter: "<<l1counter<<std::endl; + + std::string rcfile=getenv("HOME"); + rcfile+="/.cosmicDaq.rc"; + + readConfig(rcfile.c_str()); + + m_scanLog=new ScanLog; + + SetWindowName("Cosmic Telescope DAQ"); + Resize(w,h); + Layout(); + MapSubwindows(); + MapWindow(); + if(autostart==true)m_start->Clicked(); + } +void CosmicGui::toggle(){ + setRun(!running()); +} +void CosmicGui::synchSave1(){ + if(m_templog->IsOn()==true && m_tempenable->IsOn()==false){ + m_tempenable->SetOn(true); + } +} +void CosmicGui::synchSave2(){ + if(m_templog->IsOn()==true && m_tempenable->IsOn()==false){ + m_templog->SetOn(false); + } +} + +void CosmicGui::setRun(Bool_t on){ + if (on){ + //unsigned statusd=m_controller.readHWregister(4); + //std::cout<<"Statusd before run "<<std::hex<<statusd<<std::dec<<std::endl; + /* + if(m_oldRunName==m_name->GetText()){ + time_t t=time(0); + struct tm* thetime; + thetime=localtime(&t); + char runnr[128]; + sprintf(runnr,"cosmic%04d%02d%02d%02d%02d%02d",thetime->tm_year+1900,thetime->tm_mon+1,thetime->tm_mday, + thetime->tm_hour, thetime->tm_min, thetime->tm_sec); + m_name->SetText(runnr); + m_oldRunName=runnr; + } + */ + int status=startRun(); + if(status==0){ + m_timers->Start(1000,kFALSE); // update every second + m_timerm->Start(5000,kFALSE); // update every 5 second + m_timerl->Start(60000,kFALSE); // update every minut} + m_starttime.Set(); + m_oneminago=m_starttime.AsDouble(); + m_nevtMin=0; + m_nevt=0; + enableControls(false); + m_start->SetDown(true); + m_isrunning=true; + m_start->SetText("Running"); + m_rate->SetText("Starting..."); + m_irate->SetText("Starting..."); + } + }else{ + stopRun(); + enableControls(true); + m_timers->Stop(); + m_timerm->Stop(); + m_timerl->Stop(); + m_start->SetText("Start Run"); + m_isrunning=false; + m_start->SetDown(false); + m_irate->SetText("0.00 Hz"); + m_nEvents->SetText(Form("%u", m_nevt)); + /* + m_nevt = m_controller.getNEventsProcessed(); + char labelstring[128]; + sprintf(labelstring,"%u",m_nevt); + m_nEvents->SetText(labelstring); + */ + } +} +//int counter=0; +void CosmicGui::timeouts(){ + // 1 s timeout, update number of events + m_nEvents->SetText(Form("%u", m_nevt)); + //std::cout<<"nevents = "<<m_nevt<<std::endl; + //counter++; + //std::cout<<counter<<" "<<m_nevt<<std::endl; + // unsigned status=m_controller.readHWregister(3); + // std::cout<<"Status "<<std::hex<<status<<std::dec<<std::endl; + // unsigned statusd=m_controller.readHWregister(4); + // std::cout<<"Statusd "<<std::hex<<statusd<<std::dec<<std::endl; + TTimeStamp currenttime; + currenttime.Set(); + int timediff=(int)(currenttime.AsDouble()-m_starttime.AsDouble()+.5); + m_time->SetText(Form("%d s", timediff)); + m_hpe->SetText(Form("%.3f",monitoringGui->getHitsPerEvent()) ); + if(m_maxtrue->IsDisabledAndSelected()){ + unsigned maxevents; + maxevents = m_maxevents->GetIntNumber(); + if(m_nevt>=maxevents){ + setRun(false); + setRun(true); + } + } + +} +void CosmicGui::timeoutm(){ + // 5 s timeout, update monitoring display + monitoringGui->updateDisplay(); +} + +void CosmicGui::timeoutl(){ + // 60 s timeout, update rates + TTimeStamp currenttime; + currenttime.Set(); + double timediff=currenttime.AsDouble()-m_starttime.AsDouble(); + assert(timediff>0); + double nevtmin=float(m_nevt-m_nevtMin); + double rate=double(m_nevt)/timediff; + double tmin=currenttime.AsDouble()-m_oneminago; + double ratemin=nevtmin/tmin; + m_oneminago=currenttime.AsDouble(); + m_nevtMin=m_nevt; + char labelstring[128]; + sprintf(labelstring,"%.2f Hz",rate); + m_rate->SetText(labelstring); + sprintf(labelstring,"%.2f Hz",ratemin); + m_irate->SetText(labelstring); +} + +int CosmicGui::openFile(PixScan *scan){ + struct stat stFileInfo; + int intStat; + intStat = stat(m_globalconf->getDataDir(),&stFileInfo); + if(intStat != 0) { //File does not exist + std::cout<<"Data directory "<<m_globalconf->getDataDir()<<" does not exist"<<std::endl; + return 1; + } + char runnum[128]; + sprintf(runnum,"%06d",m_globalconf->getRunNumber()); + TString runname; + runname = (std::string("cosmic_")+runnum); + TString rcdir(TString("/")+runname); + rcdir=m_globalconf->getDataDir()+rcdir; + m_fullpath=std::string(rcdir.Data())+"/"+runname+".raw"; + m_rootfile=std::string(rcdir.Data())+"/"+runname+".root"; + m_tempfile=std::string(rcdir.Data())+"/"+"temperatures.txt"; + TString rcconfig(rcdir+"/globalconfig.txt"); + std::string topconfigname=m_globalconf->getConfigName()+".cfg"; + TString topconfig(rcdir+"/"+topconfigname); + TString scanconfig(rcdir+"/scanconfig_"+runname+".txt"); + // Attempt to get the file attributes + intStat = stat(rcdir.Data(),&stFileInfo); + if(intStat == 0) { //File exists + int retcode; + new TGMsgBox(gClient->GetRoot(), 0, "Attention", "Data file exists. Overwrite?", + kMBIconExclamation, kMBYes | kMBCancel,&retcode); + if(retcode==kMBYes){ + char command[512]; + sprintf(command, "rm -rf %s",rcdir.Data()); + system(command); + } else { + return 1; + } + } + if(not m_eudetfile->IsOn() && not m_rawfile->IsOn() && not m_writeRootFile->IsOn()){ + int retcode; + new TGMsgBox(gClient->GetRoot(), 0, "Attention", "No file format has been selected. Is this OK?", + kMBIconExclamation, kMBYes | kMBCancel,&retcode); + if(retcode==kMBYes){ + char command[512]; + sprintf(command, "rm -rf %s",rcdir.Data()); + system(command); + } + else { + return 1; + } + } + + // make new run directory + mkdir (rcdir.Data(),0777); + + // copy configuration + writeConfig(rcconfig.Data()); + + m_globalconf->copyConfig(topconfig.Data()); + std::ofstream sc(scanconfig.Data()); + ipc::ScanOptions options; + scan->convertScanConfig(options); + scan->setRunNumber(m_globalconf->getRunNumber()); + scan->dump(sc, options); + std::string oldcfg=std::string(rcdir.Data())+"/config"; + mkdir (oldcfg.c_str(),0777); + for (int i=0;i<ConfigGui::MAX_MODULES;i++){ + if(m_config[i]->isIncluded()){ + m_config[i]->copyConfig(oldcfg.c_str()); + } + } + return 0; +} + +int CosmicGui::startRun(){ + char name[512]; + int newrunno=m_globalconf->incrementRunNumber(); + writeStdConfig(); // remember in case we crash + const std::string port = "33000"; + if (m_realTime == true) + { + std::stringstream ss("tcp://"); + ss<<getenv("ORBHOST"); + ss << ":" << port; + std::string address = ss.str(); + std::cout << "<CosmicGui::startRun> : Server address is: " << address << std::endl; + sprintf(name,"CosmicGui|%05d|%s",newrunno,address.c_str()); + } + //configure all valid modules + std::map<int,unsigned int> linkmap; + std::map<int,int> rcemap; + std::map<int, unsigned long long> multiplexer; + //bool valid=false; + //set up RCEs first + m_controller.removeAllRces(); + for (int i=0;i<ConfigGui::MAX_MODULES;i++){ + if(m_config[i]->isIncluded()){ + m_controller.addRce(m_config[i]->getRce()); + rcemap[m_config[i]->getRce()]=1; + multiplexer[m_config[i]->getRce()]=0; + } + } + //now set up modules + + for(size_t i=0;i<m_moduleinfo.size();i++){ + delete m_moduleinfo[i]->getFormatter(); + delete m_moduleinfo[i]; + } + m_moduleinfo.clear(); + m_rce.clear(); + if(rcemap.size()==0){ + std::cout<<"No modules included. Adding RCE 0 in case you want to run without modules"<<std::endl; + m_controller.addRce(0); + m_rce.push_back(0); + rcemap[0]=1; + } + //Default Trigger IF + int retval=m_controller.setupTrigger(); + if(retval!=0){//Object not found, i.e. bad RCE specified. + new TGMsgBox(gClient->GetRoot(), 0, "Attention", + Form("RCE %d specified in config does not exist.", retval-1000), + kMBIconExclamation, kMBOk); + return 1; + } + int dutmult=m_ntrg->GetIntNumber(); + dutmult==0 ? dutmult=15 : dutmult=dutmult-1; + int telmult=m_ntrgtel->GetIntNumber(); + telmult==0 ? telmult=15 : telmult=telmult-1; + m_controller.removeAllModules(); + for (int i=0;i<ConfigGui::MAX_MODULES;i++){ + if(m_config[i]->isIncluded()){ + //valid=true; + unsigned rce=m_config[i]->getRce(); + unsigned outlink=m_config[i]->getOutLink(); + assert(linkmap.find(outlink+1000*rce)==linkmap.end()); + linkmap[outlink+1000*rce]=1; + unsigned inlink=m_config[i]->getInLink(); + int id=m_config[i]->getId(); + const char* modname=m_config[i]->getName(); + //Multiplexer optimization parameters + if(std::string(modname).substr(0,9)=="Telescope"){ + multiplexer[rce]|=telmult<<(outlink*4); + }else{ + multiplexer[rce]|=dutmult<<(outlink*4); + } + if(m_config[i]->getType()=="FEI4A"){ + printf("FEI4A: addModule (%s, %d, %d, %d, %d)\n",modname, 0, inlink, outlink, rce); + m_controller.addModule(modname, "FEI4A",id, inlink, outlink, rce, "FEI4A"); + m_moduleinfo.push_back(new ModuleInfo(modname, id, inlink, outlink, 1, 336, 80, new FEI4AFormatter(id))); + m_rce.push_back(rce); + ipc::PixelFEI4AConfig *cfg=m_config[i]->getFEI4AConfig(); + m_controller.downloadModuleConfig(rce, id,*cfg); + // assert(m_controller.writeHWregister(15,0x80)==0); //setup mux + } else if(m_config[i]->getType()=="FEI4B"){ + ipc::PixelFEI4BConfig *cfg=m_config[i]->getFEI4BConfig(); + AbsFormatter* formatter=new FEI4BFormatter(id); + boost::property_tree::ptree *pt=new boost::property_tree::ptree; + pt->put("HitDiscCnfg",cfg->FEGlobal.HitDiscCnfg); + formatter->configure(pt); + delete pt; + printf("FEI4B: addModule (%s, %d, %d, %d, %d)\n",modname, id, inlink, outlink, rce); + m_controller.addModule(modname, "FEI4B",id, inlink, outlink, rce, "FEI4B"); + m_moduleinfo.push_back(new ModuleInfo(modname, id, inlink, outlink, 1, 336, 80, formatter)); + m_rce.push_back(rce); + m_controller.downloadModuleConfig(rce, id,*cfg); + } else if(m_config[i]->getType()=="FEI3"){ + printf("FEI3: addModule (%s, %d, %d, %d, %d)\n",modname, id, inlink, outlink, rce); + m_controller.addModule(modname, "FEI3",id, inlink, outlink, rce, "JJ"); + m_moduleinfo.push_back(new ModuleInfo(modname, id, inlink, outlink, 16, 160, 18, new JJFormatter(id))); + m_rce.push_back(rce); + ipc::PixelModuleConfig *cfg=m_config[i]->getModuleConfig(); + m_controller.downloadModuleConfig(rce, id,*cfg); + } else if(m_config[i]->getType()=="Hitbus"){ + printf("Hitbus: addModule (%s, %d, %d, %d, %d)\n",modname, id, inlink, outlink, rce); + m_controller.addModule(modname, "Hitbus",id, inlink, outlink, rce, ""); + ipc::HitbusModuleConfig *cfg=m_config[i]->getHitbusConfig(); + m_controller.downloadModuleConfig(rce, id ,*cfg); + } else if(m_config[i]->getType()=="HPTDC"){ + ipc::AFPHPTDCModuleConfig *cfg=m_config[i]->getHPTDCConfig(); + printf("AFP-HPTDC: addModule (%s, %d, %d, %d, %d)\n",modname, id, inlink, outlink, rce); + AbsFormatter* formatter=new AFPHPTDCFormatter(id); + //this formatter needs to be configured. + boost::property_tree::ptree *pt=new boost::property_tree::ptree; + for(int l=0;l<2;l++){ + for(int j=0;j<12;j++){ + for(int k=0;k<1024;k++){ + char name[32]; + sprintf(name, "c_%d_%d_%d", l, j, k); + pt->put(name, cfg->calib[l][j][k]); + } + } + } + formatter->configure(pt); + delete pt; + m_controller.addModule(modname, "HPTDC",id, inlink, outlink, rce, ""); + m_moduleinfo.push_back(new ModuleInfo(modname, id, inlink, outlink, 1, 12, 1, formatter)); + m_rce.push_back(rce); + m_controller.downloadModuleConfig(rce, id ,*cfg); + } else { + std::cout<<"Unknown config type"<<std::endl; + assert(0); + } + } + } + + unsigned goodHSIOconnection; + for (std::map <int, int>::const_iterator it = rcemap.begin(); it != rcemap.end(); ++it){ + int rce=it->first; + goodHSIOconnection=m_controller.writeHWregister(rce, 3,0); //Mode 0=normal 1=tdccalib 2=eudaq + assert(goodHSIOconnection==0); + // Reset delays + goodHSIOconnection=m_controller.writeHWregister(rce, 7,0); + assert(goodHSIOconnection==0); + //Delay 0 + for(int i=0;i<m_delay0->GetIntNumber();i++){ + goodHSIOconnection=m_controller.writeHWregister(rce, 5,1); + assert(goodHSIOconnection==0); + } + //Delay 1 + for(int i=0;i<m_delay1->GetIntNumber();i++){ + goodHSIOconnection=m_controller.writeHWregister(rce, 5,2); + assert(goodHSIOconnection==0); + } + //Delay 2 + for(int i=0;i<m_delay2->GetIntNumber();i++){ + goodHSIOconnection=m_controller.writeHWregister(rce, 5,4); + assert(goodHSIOconnection==0); + } + //Delay 3 + for(int i=0;i<m_delay3->GetIntNumber();i++){ + goodHSIOconnection=m_controller.writeHWregister(rce, 5,8); + assert(goodHSIOconnection==0); + } + //Hitbus delay + goodHSIOconnection=m_controller.writeHWregister(rce, 28,m_hbdelay->GetIntNumber()); + assert(goodHSIOconnection==0); + goodHSIOconnection=m_controller.writeHWregister(rce, 29,m_hbdelaym->GetIntNumber()); + assert(goodHSIOconnection==0); + //Multiplexer optimization + //goodHSIOconnection=m_controller.writeHWregister(rce, 22,multiplexer[rce]&0xffffffff); + //assert(goodHSIOconnection==0); + //goodHSIOconnection=m_controller.writeHWregister(rce, 23,multiplexer[rce]>>32); + //assert(goodHSIOconnection==0); + goodHSIOconnection=m_controller.writeHWregister(rce, 23,0xf0000000); //TDC multiplicity 16 + assert(goodHSIOconnection==0); + + //Configure phase busy trigger + int phaseBusySel = 0; + phaseBusySel |= int(m_phasebusyen->IsOn()); + phaseBusySel |= m_phasebusystate<<1; + if (it == rcemap.begin()) { + std::cout << "PhaseBusy trigger " << ((phaseBusySel&1) ? "ON" : "OFF") << " (Mask: " << + bool(phaseBusySel&4) << bool(phaseBusySel&2) << ")" << std::endl; + } + goodHSIOconnection=m_controller.writeHWregister(rce, 34,phaseBusySel); // set busy 3 out of 4 phases + assert(goodHSIOconnection==0); + //goodHSIOconnection=m_controller.writeHWregister(rce, 33, 100); // buffer length records + //assert(goodHSIOconnection==0); + //Configure Temperature ADC readout + goodHSIOconnection=m_controller.writeHWregister(rce, 31,m_tempfreq->GetSelected()); + assert(goodHSIOconnection==0); + goodHSIOconnection=m_controller.writeHWregister(rce, 32,m_tempenable->IsOn()); + assert(goodHSIOconnection==0); + + //Disc Buttons + + unsigned N_ANDbtn=0; + for (int i=0;i<4;i++){ + if(m_NAND[i]->IsOn()){ + N_ANDbtn|=(1<<i); + } + if(m_NANDlogic[i]->IsOn()){ + N_ANDbtn|=(1<<(i+8)); + } + } + unsigned extlogic=0; + if(m_HSIO1->IsOn()&&!m_HSIO2->IsOn())extlogic=0; //for completeness + else if (!m_HSIO1->IsOn() && m_HSIO2->IsOn())extlogic=1; + else if (m_HSIO1->IsOn() && m_HSIO2->IsOn() && m_hsiostate==0)extlogic=2; + else if (m_HSIO1->IsOn() && m_HSIO2->IsOn() && m_hsiostate==1)extlogic=3; + N_ANDbtn|=extlogic<<14; + goodHSIOconnection=m_controller.writeHWregister(rce, 6, N_ANDbtn); + // Hitbus setup + goodHSIOconnection=m_controller.writeHWregister(rce, 30, m_hbstate); + m_controller.sendHWcommand(rce, 17); // Tell the HSIO that the RCE is present. + } + + for (int k=0;k<2;k++){ + if(rcemap.find(m_hbrce[k]->GetIntNumber())==rcemap.end())continue; + unsigned hitbusconfig=0; + for (int i=0;i<2;i++){ + for (int j=0;j<3;j++) + if(m_tp[k][i*3+j]->IsOn())hitbusconfig|=(1<<(i*4+j)); + } + if(m_tastate[k]==1)hitbusconfig|=(1<<3); + if(m_tbstate[k]==1)hitbusconfig|=(1<<7); + if(m_tabstate[k]==1)hitbusconfig|=(1<<8); + m_controller.writeHWregister(m_hbrce[k]->GetIntNumber(), 21,hitbusconfig); + } + + + PixScan scn(PixScan::COSMIC_DATA, PixLib::EnumFEflavour::PM_FE_I2); + ipc::ScanOptions options; + // Set calibration (i.e. output file) name + // Or the ip address of the linux host: tcp://xxx.xxx.xxx.xxx + + scn.setName(name); + // Override l1a latency + scn.setLVL1Latency(m_l1alatency->GetIntNumber()); + scn.setSecondaryLatency(m_l1alatencytel->GetIntNumber()); + // Set number of triggers per L1A + scn.setConsecutiveLvl1TrigA(0,m_ntrg->GetIntNumber()); + scn.setConsecutiveLvl1TrigA(1,m_ntrgtel->GetIntNumber()); + scn.setTriggerMask(m_scint->IsOn()|(m_cyclic->IsOn()<<1)|(m_eudet->IsOn()<<2)| + ((m_HSIO1->IsOn() || m_HSIO2->IsOn())<<3)|(m_hitbus->IsOn()<<4)); + //scn.setHitbusConfig(hitbusconfig); + scn.setEventInterval(m_cperiod->GetIntNumber()); + scn.setStrobeLVL1Delay(m_trgdelay->GetIntNumber()); + scn.setDeadtime(m_deadtime->GetIntNumber()); + scn.convertScanConfig(options); + + int of=openFile(&scn); + if(of!=0)return 1; + + monitoringGui->setup(true, m_writeRootFile->IsOn(), m_rootfile.c_str(), + m_templog->IsOn(), m_tempfile.c_str()); + + if (m_realTime == true) + { + // Set-up to receive the data properly + std::cout << "CosmicGui: starting CosmicDataReceiver at tcp://" << port << std::endl; + std::vector<ModuleInfo*> modinfo=getModuleInfo(); + std::vector<int> rcesAll=getRces(); + unsigned runNo=m_globalconf->getRunNumber(); + IPCController* controller=getController(); + m_dataReceiver = new CosmicDataReceiver(this, controller, modinfo, rcesAll, + runNo, "tcp://" + port, m_fullpath, m_eudetfile->IsOn(), m_rawfile->IsOn()); + } + + + m_controller.downloadScanConfig(options); + logScan(); + m_controller.startScan(); + + return 0; +} + +void CosmicGui::stopRun(){ + m_controller.stopWaitingForData(); + std::cout<<"called stopwaitingfordata"<<std::endl; + monitoringGui->saveHistos(m_globalconf->getRunNumber(), m_globalconf->getDataDir()); + finishLogFile(); + bool idle=false; + for(int i=0;i<50;i++){ + if(m_controller.getScanStatus()==0){ + std::cout<<"called getstatus"<<std::endl; + idle=true; + break; + } + usleep(100000); + } + assert(idle); + /* + std::cout<<"Verifying HW configuration"<<std::endl; + int retval=m_controller.verifyModuleConfigHW(); + if(retval&0x100)std::cout<<"No formatter defined. Skipping register readback."<<std::endl; + if(retval&0x1)std::cout<<"Global register readback failed for unknown reasons."<<std::endl; + if(retval&0x2)std::cout<<"Global register readback differs from original configuration."<<std::endl; + if(retval&0x4)std::cout<<"Pixel register read back wrong number of words."<<std::endl; + if(retval&0x8)std::cout<<"Pixel register readback differs from original configuration."<<std::endl; + if(retval==0)std::cout<<"Register verification successful."<<std::endl; + */ + m_controller.resetFE(); //also sweeps events stuck in the buffer + m_controller.removeAllModules(); + //unsigned goodHSIOconnection=m_controller.writeHWregister(3,0); //Normal operating mode + //assert(goodHSIOconnection==0); + //goodHSIOconnection=m_controller.writeHWregister(0,0); //Inhibit all channels + //assert(goodHSIOconnection==0); + // unsigned l1counter=m_controller.readHWregister(11); + // unsigned counter4=m_controller.readHWregister(9); + // unsigned counter4m=m_controller.readHWregister(12); + // unsigned counter10m=m_controller.readHWregister(13); + // unsigned counter10=m_controller.readHWregister(10); + // unsigned counter10e=m_controller.readHWregister(14); + // unsigned tdccounter=m_controller.readHWregister(15); + // std::cout<<"Counter 4: "<<counter4<<" Counter 10: "<<counter10<<std::endl; + // std::cout<<"Counter 4m: "<<counter4m<<" Counter 10m: "<<counter10m<<std::endl; + // std::cout<<"Counter 10e: "<<counter10e<<" TDC counter: "<<(tdccounter&0xffff)<<std::endl; + // std::cout<<"l1counter: "<<l1counter<<std::endl; + + if (m_dataReceiver) delete m_dataReceiver; + m_dataReceiver = 0; + if(m_writeRootFile->IsDisabledAndSelected())monitoringGui->closeRootFile(); + if(m_templog->IsDisabledAndSelected())monitoringGui->closeTempFile(); + + return; +} + +void CosmicGui::verifyConfiguration(){ + std::cout<<"Verifying HW configuration"<<std::endl; + for (int i=0;i<ConfigGui::MAX_MODULES;i++){ + if(m_config[i]->isIncluded()){ + unsigned rce=m_config[i]->getRce(); + unsigned id=m_config[i]->getId(); + std::cout<<"Frontend "<<id<<" on RCE "<<rce<<" Outlink "<<m_config[i]->getOutLink()<<":"<<std::endl; + int retval=m_controller.verifyModuleConfigHW(rce, id); + if(retval&ModuleVerify::NO_FORMATTER)std::cout<<"No formatter defined. Skipping register readback."<<std::endl; + if(retval&ModuleVerify::GLOBAL_READBACK_FAILED)std::cout<<"Global register readback failed for unknown reasons."<<std::endl; + if(retval&ModuleVerify::GLOBAL_READBACK_DIFFERENT)std::cout<<"Global register readback differs from original configuration."<<std::endl; + if(retval&ModuleVerify::PIXEL_WRONG_N_WORDS)std::cout<<"Pixel register read back wrong number of words."<<std::endl; + if(retval&ModuleVerify::PIXEL_READBACK_DIFFERENT)std::cout<<"Pixel register readback differs from original configuration."<<std::endl; + if(retval==ModuleVerify::OK)std::cout<<"Register verification successful."<<std::endl; + } + } +} +void CosmicGui::enableControls(bool on){ + m_tempenable->SetEnabled(on); + m_templog->SetEnabled(on); + m_tempfreq->SetEnabled(on); + m_quit->SetEnabled(on); + m_delay0->SetState(on); + m_delay1->SetState(on); + m_delay2->SetState(on); + m_delay3->SetState(on); + m_maxevents->SetState(on); + m_l1alatency->SetState(on); + m_l1alatencytel->SetState(on); + m_ntrg->SetState(on); + m_ntrgtel->SetState(on); + m_trgdelay->SetState(on); + m_deadtime->SetState(on); + m_hbdelay->SetState(on); + m_hbdelaym->SetState(on); + m_cperiod->SetState(on); + m_scint->SetEnabled(on); + m_eudet->SetEnabled(on); + m_cyclic->SetEnabled(on); + m_HSIO1->SetEnabled(on); + m_HSIO2->SetEnabled(on); + m_hsiologic->SetState(on); + m_hitbus->SetEnabled(on); + m_hbinput->SetState(on); + m_eudetfile->SetEnabled(on); + m_rawfile->SetEnabled(on); + m_writeRootFile->SetEnabled(on); + m_maxtrue->SetEnabled(on); + for (int k=0;k<2;k++){ + for (int i=0;i<6;i++) + m_tp[k][i]->SetEnabled(on); + m_talogic[k]->SetState(on); + m_tblogic[k]->SetState(on); + m_tablogic[k]->SetState(on); + m_hbrce[k]->SetState(on); + } + for (int i=0;i<4;i++){ + m_NAND[i]->SetEnabled(on); + m_NANDlogic[i]->SetEnabled(on); + } + for(int i=0;i<ConfigGui::MAX_MODULES;i++) + m_config[i]->enableControls(on); + m_globalconf->enableControls(on); + m_phasebusysel->SetState(on); + m_phasebusyen->SetEnabled(on); +} + +void CosmicGui::writeConfig(const char* filename){ + std::cout<<"Writing config to "<<filename<<std::endl; + std::ofstream ofile(filename); + + ofile<<m_trgdelay->GetIntNumber()<<std::endl; + ofile<<m_deadtime->GetIntNumber()<<std::endl; + ofile<<m_hbdelay->GetIntNumber()<<std::endl; + ofile<<m_hbdelaym->GetIntNumber()<<std::endl; + ofile<<m_l1alatency->GetIntNumber()<<std::endl; + ofile<<m_l1alatencytel->GetIntNumber()<<std::endl; + ofile<<m_ntrg->GetIntNumber()<<std::endl; + ofile<<m_ntrgtel->GetIntNumber()<<std::endl; + ofile<<m_delay0->GetIntNumber()<<std::endl; + ofile<<m_delay1->GetIntNumber()<<std::endl;; + ofile<<m_delay2->GetIntNumber()<<std::endl; + ofile<<m_delay3->GetIntNumber()<<std::endl; + ofile<<m_maxevents->GetIntNumber()<<std::endl; + ofile<<m_scint->IsOn()<<std::endl; + ofile<<m_cyclic->IsOn()<<std::endl; + ofile<<m_eudet->IsOn()<<std::endl; + ofile<<m_HSIO1->IsOn()<<std::endl; + ofile<<m_HSIO2->IsOn()<<std::endl; + ofile<<m_hsiostate<<std::endl; + ofile<<m_hitbus->IsOn()<<std::endl; + ofile<<m_hbstate<<std::endl; + ofile<<m_cperiod->GetIntNumber()<<std::endl; + ofile<<m_maxtrue->IsOn()<<std::endl; + for (int k=0;k<2;k++){ + for (int i=0;i<6;i++) + ofile<<m_tp[k][i]->IsOn()<<std::endl; + ofile<<m_tastate[k]<<std::endl; + ofile<<m_tbstate[k]<<std::endl; + ofile<<m_tabstate[k]<<std::endl; + ofile<<m_hbrce[k]->GetIntNumber()<<std::endl; + } + for (int i=0;i<4;i++){ + ofile<<m_NAND[i]->IsOn()<<std::endl; + } + for (int i=0;i<4;i++){ + ofile<<m_NANDlogic[i]->IsOn()<<std::endl; + } + ofile<<m_eudetfile->IsOn()<<std::endl; + ofile<<m_rawfile->IsOn()<<std::endl; + ofile<<m_writeRootFile->IsOn()<<std::endl; + ofile<<m_tempenable->IsOn()<<std::endl; + ofile<<m_templog->IsOn()<<std::endl; + ofile<<m_tempfreq->GetSelected()<<std::endl; + ofile<<m_phasebusyen->IsOn()<<std::endl; + ofile<<m_phasebusystate<<std::endl; + m_globalconf->writeGuiConfig(ofile); +} + +void CosmicGui::readConfig(const char* filename){ + struct stat stFileInfo; + int intStat; + // Attempt to get the file attributes + intStat = stat(filename,&stFileInfo); + if(intStat != 0) { //File does not exist + std::cout<<std::endl<<"No config file "<<filename<<" found."<<std::endl; + return; + } + std::ifstream ifile(filename); + int td, dt, hb, lat, nt, del0, del1, del2, del3, maxevnt, maxt, trg, trgper, fi, pbusy; + ifile>>td; + m_trgdelay->SetIntNumber(td); + ifile>>dt; + m_deadtime->SetIntNumber(dt); + ifile>>hb; + m_hbdelay->SetIntNumber(hb); + ifile>>hb; + m_hbdelaym->SetIntNumber(hb); + ifile>>lat; + m_l1alatency->SetIntNumber(lat); + ifile>>lat; + m_l1alatencytel->SetIntNumber(lat); + ifile>>nt; + m_ntrg->SetIntNumber(nt); + ifile>>nt; + m_ntrgtel->SetIntNumber(nt); + ifile>>del0; + m_delay0->SetIntNumber(del0); + ifile>>del1; + m_delay1->SetIntNumber(del1); + ifile>>del2; + m_delay2->SetIntNumber(del2); + ifile>>del3; + m_delay3->SetIntNumber(del3); + ifile>>maxevnt; + m_maxevents->SetIntNumber(maxevnt); + ifile>>trg; + m_scint->SetOn(trg); + ifile>>trg; + m_cyclic->SetOn(trg); + ifile>>trg; + m_eudet->SetOn(trg); + ifile>>trg; + m_HSIO1->SetOn(trg); + ifile>>trg; + m_HSIO2->SetOn(trg); + ifile>>trg; + m_hsiostate=trg; + m_hsiologic->SetButton(trg); + ifile>>trg; + m_hitbus->SetOn(trg); + ifile>>trg; + m_hbstate=trg; + m_hbinput->SetButton(trg); + ifile>>trg; + m_cperiod->SetIntNumber(trg); + ifile>>maxt; + m_maxtrue->SetOn(maxt); + for (int k=0;k<2;k++){ + for (int i=0;i<6;i++){ + ifile>>trgper; + m_tp[k][i]->SetOn(trgper); + } + ifile>>trgper; + m_tastate[k]=trgper; + m_talogic[k]->SetButton(trgper); + ifile>>trgper; + m_tbstate[k]=trgper; + m_tblogic[k]->SetButton(trgper); + ifile>>trgper; + m_tabstate[k]=trgper; + m_tablogic[k]->SetButton(trgper); + ifile>>trgper; + m_hbrce[k]->SetIntNumber(trgper); + } + for (int i=0;i<4;i++){ + ifile>>trgper; + m_NAND[i]->SetOn(trgper); + } + for (int i=0;i<4;i++){ + ifile>>trgper; + m_NANDlogic[i]->SetOn(trgper); + } + ifile>>fi; + m_eudetfile->SetOn(fi); + ifile>>fi; + m_rawfile->SetOn(fi); + ifile>>fi; + m_writeRootFile->SetOn(fi); + ifile>>fi; + m_tempenable->SetOn(fi); + ifile>>fi; + m_templog->SetOn(fi); + ifile>>fi; + m_tempfreq->Select(fi,0); + ifile>>pbusy; + m_phasebusyen->SetOn(pbusy); + ifile>>pbusy; + m_phasebusystate=pbusy; + m_phasebusysel->SetButton(pbusy); + m_globalconf->readGuiConfig(ifile); +} + +void CosmicGui::quit(){ + writeStdConfig(); + gApplication->Terminate(0); +} + +void CosmicGui::writeStdConfig(){ + std::string rcfile=getenv("HOME"); + rcfile+="/.cosmicDaq.rc"; + writeConfig(rcfile.c_str()); +} + +void CosmicGui::handleFileMenu(int item){ + TGFileInfo fileinfo; + const char* types[]={"Teststand config", "*.tcf", "All files", "*", 0,0}; + fileinfo.fFileTypes=types; + if(item==QUIT)quit(); + else if(item==LOAD){ + new TGFileDialog(gClient->GetRoot(), 0, kFDOpen, &fileinfo); + if(!fileinfo.fFilename){ + printf("Scheisse\n"); + return; + } + readConfig(fileinfo.fFilename); + } + else if(item==SAVE){ + new TGFileDialog(gClient->GetRoot(), 0, kFDSave, &fileinfo); + if(!fileinfo.fFilename){ + printf("Scheisse\n"); + return; + } + writeConfig(fileinfo.fFilename); + } +} + +void CosmicGui::logScan(){ + LogData logdata; + m_scanLog->setAuthor("cosmicGui"); + m_scanLog->setScanName("CosmicData"); + m_scanLog->setRunNumber(m_globalconf->getRunNumber()); + m_scanLog->setDebugging(false); + //logdata.comment=m_comment->GetText(); + logdata.exported=false; + logdata.saved=true; + logdata.datapath=m_globalconf->getDataDir(); + for (int i=0;i<ConfigGui::MAX_MODULES;i++){ + std::ostringstream ss; + if(m_config[i]->isIncluded()){ + ss<<"Module: "<<m_config[i]->getModuleId()<<" FE: "<< m_config[i]->getId()<<" Cfg: "<< m_config[i]->getFilename(); + logdata.configs.push_back(ss.str()); + } + } + m_scanLog->logScan(logdata); +} +void CosmicGui::finishLogFile(){ + std::string runstatus="OK"; + std::string lstatus="Done"; + m_scanLog->finishLogFile(runstatus, lstatus); +} + +void CosmicGui::switchOn(int panel, bool on){ + int modperpanel=ConfigGui::MAX_MODULES/4; + for (int i=panel*modperpanel;i<(panel+1)*modperpanel;i++){ + m_config[i]->setIncluded(on); + } +} + + + +//==================================================================== +int main(int argc, char **argv){ + // + // Initialize command line parameters with default values + // + try { + IPCCore::init( argc, argv ); + } + catch( daq::ipc::Exception & ex ) { + ers::fatal( ex ); + return 1; + } + +// +// Declare command object and its argument-iterator +// + CmdArgStr partition_name ('p', "partition", "partition-name", "partition to work in."); + CmdArgBool start('s', "start", "Start run when GUI comes up."); + CmdLine cmd(*argv, &partition_name, &start, NULL); + CmdArgvIter arg_iter(--argc, ++argv); +// +// Parse arguments +// + cmd.parse(arg_iter); + const char *p_name=getenv("TDAQ_PARTITION"); + if(p_name==NULL) p_name="rcetest"; + if(! partition_name.isNULL()) p_name= (const char*)partition_name; + try{ + IPCPartition p(p_name ); + IPCController controller(p); + new IPCHistoManager(p,"RceIsServer", "dummy"); + + gROOT->SetStyle("Plain"); + TApplication theapp("app",&argc,argv); + new CosmicGui(controller, start, gClient->GetRoot(),800, 735); + theapp.Run(); + return 0; + }catch(...){ + std::cout<<"Partition "<<p_name<<" does not exist."<<std::endl; + exit(0); + } +} + + diff --git a/rce/rcecalib/server/CosmicGui.hh b/rce/rcecalib/server/CosmicGui.hh new file mode 100644 index 00000000..d3287539 --- /dev/null +++ b/rce/rcecalib/server/CosmicGui.hh @@ -0,0 +1,108 @@ +#ifndef COSMICGUI_HH +#define COSMICGUI_HH + +#include "TGMdiMainFrame.h" +#include <TTimer.h> +#include <TTimeStamp.h> +#include <TGLabel.h> +#include <TGTextEntry.h> +#include <TGNumberEntry.h> +#include <TGButtonGroup.h> +#include <TGComboBox.h> +#include "ConfigGui.hh" +#include <string> + +class GlobalConfigGui; +class IPCController; +class CosmicDataReceiver; +class CosmicMonitoringGuiEmbedded; +class ModuleInfo; +class ScanLog; +namespace RCE{ + class PixScan; +} + +class CosmicGui: public TGMainFrame { + friend class CosmicDataReceiver; +public: + enum Filemenu {LOAD, SAVE, QUIT, HISTOS, SCREENSHOT}; + CosmicGui(IPCController &c, bool autostart, const TGWindow *p,UInt_t w,UInt_t h); + virtual ~CosmicGui(); + void toggle(); + void synchSave1(); + void synchSave2(); + void timeouts(); + void timeoutm(); + void timeoutl(); + int startRun(); + void stopRun(); + void verifyConfiguration(); + void enableControls(bool on); + void quit(); + void writeStdConfig(); + void handleFileMenu(Int_t); + void readConfig(const char* filename); + void writeConfig(const char* filename); + void incrementNevents(){m_nevt++;} + std::vector<ModuleInfo*>& getModuleInfo(){return m_moduleinfo;} + std::vector<int>& getRces(){return m_rce;} + int getL1AperTrig(){return m_ntrg->GetIntNumber();} + int getRunNumber(){return m_runno->GetIntNumber();} + IPCController* getController(){return &m_controller;} + void allOffA(){switchOn(0,0);} + void allOffC(){switchOn(1,0);} + void allOffA2(){switchOn(2,0);} + void allOffC2(){switchOn(3,0);} + void allOnA(){switchOn(0,1);} + void allOnC(){switchOn(1,1);} + void allOnA2(){switchOn(2,1);} + void allOnC2(){switchOn(3,1);} + void switchOn(int panel, bool on); + void setTaLogic0(Int_t i){m_tastate[0]=i;} + void setTaLogic1(Int_t i){m_tastate[1]=i;} + void setTbLogic0(Int_t i){m_tbstate[0]=i;} + void setTbLogic1(Int_t i){m_tbstate[1]=i;} + void setTabLogic0(Int_t i){m_tabstate[0]=i;} + void setTabLogic1(Int_t i){m_tabstate[1]=i;} + void setHbLogic(Int_t i){m_hbstate=i;} + void setHsioLogic(Int_t i){m_hsiostate=i;} + void setTriggerActivePhase(Int_t i){m_phasebusystate=i;} + +private: + void setRun(Bool_t on); + bool running(){return m_isrunning;} + int maxRunNum(); + void logScan(); + void finishLogFile(); + int openFile(RCE::PixScan*); + + IPCController& m_controller; + ConfigGui* m_config[ConfigGui::MAX_MODULES]; + TGTextButton* m_start, *m_quit; + TGLabel *m_nEvents, *m_time, *m_rate, *m_irate, *m_hpe; + TGNumberEntry *m_delay0, *m_delay1, *m_delay2, *m_delay3, *m_l1alatency, *m_l1alatencytel, *m_trgdelay, *m_ntrg, *m_ntrgtel, *m_runno, *m_deadtime, *m_cperiod, *m_hbdelay, *m_hbdelaym, *m_maxevents; + TGNumberEntry *m_hbrce[2]; + TGCheckButton *m_scint, *m_cyclic, *m_eudet, *m_HSIO1, *m_HSIO2, *m_hitbus, *m_NAND[4], *m_NANDlogic[4], *m_eudetfile, *m_rawfile, *m_writeRootFile, *m_maxtrue, *m_tempenable, *m_templog; + TGCheckButton *m_tp[2][6], *m_phasebusyen; + TGButtonGroup *m_talogic[2], *m_tblogic[2], *m_tablogic[2], *m_hbinput, *m_hsiologic, *m_phasebusysel; + TGComboBox *m_tempfreq; + int m_tastate[2], m_tbstate[2], m_tabstate[2], m_hbstate, m_hsiostate, m_phasebusystate; + bool m_isrunning; + bool m_realTime; + TTimer *m_timers, *m_timerm, *m_timerl; + TTimeStamp m_starttime; + unsigned m_nevt; + unsigned m_nevtMin; + double m_oneminago; + std::string m_oldRunName; + CosmicDataReceiver * m_dataReceiver; + CosmicMonitoringGuiEmbedded* monitoringGui; + std::vector<ModuleInfo*> m_moduleinfo; + std::vector<int> m_rce; + std::string m_fullpath, m_rootfile, m_tempfile; + ScanLog *m_scanLog; + GlobalConfigGui* m_globalconf; + +ClassDef (CosmicGui,0) +}; +#endif diff --git a/rce/rcecalib/server/CosmicMonitoringGui.cc b/rce/rcecalib/server/CosmicMonitoringGui.cc new file mode 100644 index 00000000..1ef0ccc5 --- /dev/null +++ b/rce/rcecalib/server/CosmicMonitoringGui.cc @@ -0,0 +1,97 @@ +#include "rcecalib/server/CosmicMonitoringGui.hh" +#include "rcecalib/server/CosmicMonitoringGuiEmbedded.hh" +#include "TApplication.h" +#include "TGMsgBox.h" +#include "TH1.h" +#include "TGIcon.h" +#include "TGMenu.h" +#include "TCanvas.h" +#include "TGCanvas.h" +#include "TGListTree.h" +#include "TRootEmbeddedCanvas.h" +#include <TGFileDialog.h> +#include <TROOT.h> +#include <TStyle.h> +#include <assert.h> +#include <iostream> +#include <time.h> +#include <sys/stat.h> +#include <fstream> +#include <list> +#include <pthread.h> +#include <vector> +#include "eudaq/Event.hh" +#include "config/FormattedRecord.hh" +#include "eudaq/DetectorEvent.hh" +#include "eudaq/RawDataEvent.hh" +#include "eudaq/FileSerializer.hh" +#include "eudaq/counted_ptr.hh" + + + + +CosmicMonitoringGui::~CosmicMonitoringGui(){ +} + +CosmicMonitoringGui::CosmicMonitoringGui(const char* filename, int nevt, const TGWindow *p,UInt_t w,UInt_t h) + : TGMainFrame(p,w,h) { + + // connect x icon on window manager + Connect("CloseWindow()","CosmicMonitoringGui",this,"quit()"); + + TGMenuBar *menubar=new TGMenuBar(this,1,1,kHorizontalFrame | kRaisedFrame); + TGLayoutHints *menubarlayout=new TGLayoutHints(kLHintsTop|kLHintsLeft,0,4,0,0); + // menu "File" + TGPopupMenu* filepopup=new TGPopupMenu(gClient->GetRoot()); + //filepopup->AddEntry("&Load Config",LOAD); + //filepopup->AddEntry("&Save Config",SAVE); + filepopup->AddSeparator(); + filepopup->AddEntry("&Quit",QUIT); + menubar->AddPopup("&File",filepopup,menubarlayout); + + AddFrame(menubar, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 0,0,0,2)); + + filepopup->Connect("Activated(Int_t)","CosmicMonitoringGui",this,"handleFileMenu(Int_t)"); + + embededGui = new CosmicMonitoringGuiEmbedded(filename, nevt, this,1,1,kChildFrame); + AddFrame(embededGui,new TGLayoutHints(kLHintsExpandX|kLHintsExpandY)); + + SetWindowName("Monitoring GUI"); + Resize(w,h); + Layout(); + MapSubwindows(); + MapWindow(); +} +void CosmicMonitoringGui::quit(){ + gApplication->Terminate(0); +} + + +void CosmicMonitoringGui::handleFileMenu(int item){ + if(item==QUIT)quit(); +} + +//==================================================================== +int main(int argc, char **argv){ + // + // Initialize command line parameters with default values +// +// Declare command object and its argument-iterator +// +// + + gROOT->SetStyle("Plain"); + gStyle->SetOptStat(0); + gStyle->SetPalette(1); + const char *filename=argv[1]; + std::cout<<"Filename "<<filename<<std::endl; + int nevt=10000000; + if(argc==3)nevt=atoi(argv[2]); + std::cout<<"Nevt "<<nevt<<std::endl; + TApplication theapp("app",&argc,argv); + new CosmicMonitoringGui(filename, nevt, gClient->GetRoot(),800,600); + theapp.Run(); + return 0; +} + + diff --git a/rce/rcecalib/server/CosmicMonitoringGui.hh b/rce/rcecalib/server/CosmicMonitoringGui.hh new file mode 100644 index 00000000..65f8fcc1 --- /dev/null +++ b/rce/rcecalib/server/CosmicMonitoringGui.hh @@ -0,0 +1,28 @@ +#ifndef COSMICMONITORINGGUI_HH +#define COSMICMONITORINGGUI_HH + +#include "TGMdiMainFrame.h" +#include <TGLabel.h> +#include <TGTextEntry.h> +#include <TGNumberEntry.h> +#include "TFile.h" +#include "TH2F.h" +#include <string> + + +class CosmicMonitoringGuiEmbedded; + +class CosmicMonitoringGui: public TGMainFrame { +public: + CosmicMonitoringGui(const char* filename, int nevt, const TGWindow *p,UInt_t w,UInt_t h); + virtual ~CosmicMonitoringGui(); + void handleFileMenu(Int_t); + void quit(); +private: + + CosmicMonitoringGuiEmbedded* embededGui; + enum Filemenu {LOAD, SAVE, QUIT}; + +ClassDef (CosmicMonitoringGui,0) +}; +#endif diff --git a/rce/rcecalib/server/CosmicMonitoringGuiEmbedded.cc b/rce/rcecalib/server/CosmicMonitoringGuiEmbedded.cc new file mode 100644 index 00000000..8baee90c --- /dev/null +++ b/rce/rcecalib/server/CosmicMonitoringGuiEmbedded.cc @@ -0,0 +1,1297 @@ +#include "rcecalib/server/CosmicMonitoringGuiEmbedded.hh" +#include "rcecalib/server/ConfigGui.hh" +#include "TApplication.h" +#include "TGMsgBox.h" +#include "TH1.h" +#include "TGIcon.h" +#include "TGMenu.h" +#include "TCanvas.h" +#include "TGCanvas.h" +#include "TGListTree.h" +#include "TRootEmbeddedCanvas.h" +#include <TGFileDialog.h> +#include <TROOT.h> +#include <TStyle.h> +#include <assert.h> +#include <math.h> +#include <iostream> +#include <time.h> +#include <sys/stat.h> +#include <time.h> +#include <fstream> +#include <list> +#include <pthread.h> +#include <vector> +#include "eudaq/Event.hh" +#include "config/FormattedRecord.hh" +#include "eudaq/DetectorEvent.hh" +#include "eudaq/RawDataEvent.hh" +#include "eudaq/FileSerializer.hh" +#include "eudaq/counted_ptr.hh" + +int hitbusEdge(unsigned word, int j){ + for (int i=9;i>=0;i--){ + if((word&(1<<((2-j)+3*i)))!=0){ + return 9-i; + } + } + return -1; +} + +CosmicMonitoringGuiEmbedded::~CosmicMonitoringGuiEmbedded(){ + Cleanup(); + for(int i=0;i<MAX_RCE_NUM;i++)delete [] m_linkToIndex[i]; + delete [] m_linkToIndex; +} + +void CosmicMonitoringGuiEmbedded::init(){ + TGVerticalFrame* datapanel=new TGVerticalFrame(this,1,1, kSunkenFrame); + // scan panel + TGHorizontalFrame *datapanel5 = new TGHorizontalFrame(datapanel, 2, 2, kSunkenFrame); + datapanel->AddFrame(datapanel5,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY)); + AddFrame(datapanel,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY)); + + TGVerticalFrame *treepanel = new TGVerticalFrame(datapanel5, 150, 2, kSunkenFrame); + datapanel5->AddFrame(treepanel,new TGLayoutHints(kLHintsExpandY)); + TGVerticalFrame *plotpanel = new TGVerticalFrame(datapanel5, 2, 2, kSunkenFrame); + datapanel5->AddFrame(plotpanel,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY)); + + m_tgc=new TGCanvas(treepanel, 300,100); + //TGViewPort* vp=tgc->GetViewPort(); + m_tree=new TGListTree(m_tgc, kHorizontalFrame); + m_tree->Connect("Clicked(TGListTreeItem*, Int_t)","CosmicMonitoringGuiEmbedded", this, "displayHisto(TGListTreeItem*, Int_t)"); + //tree->AddItem(0,"/"); + treepanel->AddFrame(m_tgc,new TGLayoutHints(kLHintsExpandY)); + m_canvas=new TRootEmbeddedCanvas("Canvas",plotpanel,100,100); + m_canvas->GetCanvas()->GetPad(0)->SetRightMargin(0.15); + m_www=0; m_hhh=0; + gStyle->SetPalette(1); + gStyle->SetOptStat(10); + plotpanel->AddFrame(m_canvas,new TGLayoutHints(kLHintsExpandY|kLHintsExpandX)); + m_linkToIndex=new int*[MAX_RCE_NUM]; + for(int i=0;i<MAX_RCE_NUM;i++)m_linkToIndex[i]=0; + +} + + +void CosmicMonitoringGuiEmbedded::setup(bool online, bool writeRootFile, const char* rootfile, + bool writeTemps, const char* tempfile){ + + std::cout<<"Setting up monitoring histograms"<<std::endl; + m_writeRootFile=writeRootFile; + m_logtemps=writeTemps; + if(m_nMods>0){ + delete [] m_nhits; + for (int i=0;i<m_nMods;i++){ + delete [] m_pixx[i]; + delete [] m_pixy[i]; + delete [] m_value[i]; + delete [] m_timing[i]; + delete [] m_hitincluster[i]; + delete [] m_posx[i]; + delete [] m_posy[i]; + delete [] m_posz[i]; + } + delete [] m_pixx; + delete [] m_pixy; + delete [] m_value; + delete [] m_timing; + delete [] m_hitincluster; + delete [] m_posx; + delete [] m_posy; + delete [] m_posz; + } + m_starttime_sec=(unsigned)time(0); + m_lasttime_sec= -1; + m_nMods = 0; + m_nRces = 0; + m_triggerPhase=-1; + m_linkmap.clear(); + for(int i=0;i<MAX_RCE_NUM;i++){ + delete [] m_linkToIndex[i]; + m_linkToIndex[i]=0; + } + m_outlinks.clear(); + m_rceNums.clear(); + m_rces.clear(); + m_fetype.clear(); + m_timeStampLimit=5.0; + m_nev=0; + m_hitsperevent=0; + m_nScreenshots=0; + m_histo=0; + m_graph=0; + for (int i=0;i<MAX_RCES;i++){ + m_tdc[i]=0; + for(int k=0;k<2;k++)for(int l=0;l<3;l++)m_hitbus[i][k][l]=0; + } + for(int i=0;i<ConfigGui::MAX_MODULES;i++){ + if(i!=ConfigGui::MAX_MODULES-1){ + m_corxx[i]=0; + m_corxy[i]=0; + m_coryy[i]=0; + m_coryx[i]=0; + } + m_tempsec[i]=0; + m_tempmin[i]=0; + m_occ[i]=0; + m_toth[i]=0; + m_bx[i]=0; + m_afptdc[i]=0; + m_timestamp[i]=0; + m_projx[i]=0; + m_projy[i]=0; + m_corrindex[i]=-1; + } + + if(online){ + + for (unsigned int i=0; i<m_config.size(); i++){ + if(m_config[i]->isIncluded()){ + //valid=true; + m_lastcount[i]=0; + unsigned outlink=m_config[i]->getOutLink(); + unsigned rceNum=m_config[i]->getRce(); + addRce(rceNum); + + std::cout<<"\tModule "<<i<<": outlink "<<outlink<<" , RCE "<<rceNum<<std::endl; + createLink(outlink,rceNum); //this increments m_nMods + + if(m_config[i]->getType()=="FEI4A" || m_config[i]->getType()=="FEI4B"){ + m_fetype.push_back(4); + }else if(m_config[i]->getType()=="FEI3"){ + m_fetype.push_back(3); + }else if(m_config[i]->getType()=="Hitbus"){ + m_fetype.push_back(9); + }else if(m_config[i]->getType()=="HPTDC"){ + m_fetype.push_back(11); + } + else { + std::cout<<"Unknown FE type"<<std::endl; + assert(0); + } + } + } + + } + else{ //offline/standalone executable + + std::string chanDefName = "cosmicChannelDefs.txt"; + std::ifstream cha(chanDefName.data()); + if (!cha.is_open()){ + + std::cout << "Cannot find "<<chanDefName<<std::endl; + bool success = setupChannelsFromFile(m_filename); + + if(!success){ + std::cout<<"Couldn't read "<<m_filename<<" ; instead setting default values for channels"<<std::endl; + + createLink(11,0); + createLink(12,0); + createLink(13,0); + createLink(14,0); + createLink(0,0); + + m_fetype.push_back(3); + m_fetype.push_back(3); + m_fetype.push_back(3); + m_fetype.push_back(3); + m_fetype.push_back(4); + + addRce(0); + } + + } + else{ + + //Read in channel definitions from text file (for standalone cosmicMonitoringGui only) + std::cout<<"Reading in channel definitions from "<<chanDefName<<std::endl; + int upl, rce, fet; + while(!cha.eof()){ + cha>>upl>>rce>>fet; + + createLink(upl,rce); + addRce(rce); + m_fetype.push_back(fet); + + std::cout<<"Module "<<(m_nMods-1)<<" : uplink "<<upl<<" ; RCE "<<rce<<" ; FEI"<<fet<<std::endl; + + } + + } + + } //end if(!online) + + // These are needed even when no root file is written. + m_nhits=new Int_t[m_nMods]; + m_pixx=new Int_t*[m_nMods]; + m_pixy=new Int_t*[m_nMods]; + m_value=new Int_t*[m_nMods]; + m_timing=new Int_t*[m_nMods]; + m_hitincluster=new Int_t*[m_nMods]; + m_posx=new Double_t*[m_nMods]; + m_posy=new Double_t*[m_nMods]; + m_posz=new Double_t*[m_nMods]; + for (int i=0;i<m_nMods;i++){ + m_pixx[i]=new Int_t[MAXHIT]; + m_pixy[i]=new Int_t[MAXHIT]; + m_value[i]=new Int_t[MAXHIT]; + m_timing[i]=new Int_t[MAXHIT]; + m_hitincluster[i]=new Int_t[MAXHIT]; + m_posx[i]=new Double_t[MAXHIT]; + m_posy[i]=new Double_t[MAXHIT]; + m_posz[i]=new Double_t[MAXHIT]; + } + for (int i=0;i<m_nMods;i++){ + for(int j=0;j<MAXHIT;j++){ + m_hitincluster[i][j]=0; + m_posx[i][j]=0; + m_posy[i][j]=0; + m_posz[i][j]=0; + } + } + fillHistoTree(); + if(writeRootFile==true)setupRootFile(rootfile); + if(writeTemps==true)m_tempfile=new std::ofstream(tempfile); + +} + +CosmicMonitoringGuiEmbedded::CosmicMonitoringGuiEmbedded(const TGWindow *p,UInt_t w,UInt_t h,UInt_t options, const std::vector<ConfigGui*> config) + : TGVerticalFrame(p,w,h,options), m_config(config), m_nMods(0), m_evfile(0) { + init(); +} + +CosmicMonitoringGuiEmbedded::CosmicMonitoringGuiEmbedded(const char* filename, int nevt, const TGWindow *p,UInt_t w,UInt_t h,UInt_t options) + : TGVerticalFrame(p,w,h,options), m_filename(filename),m_nMods(0), m_evfile(0) { + + init(); + setup(false, false, 0, false, 0); //online==false + + readFile(m_filename, nevt); +// TFile a("out.root","recreate"); +// tdc->Write(); + // a.Close(); +} + +void CosmicMonitoringGuiEmbedded::clearTree(){ + TGListTreeItem* root=m_tree->FindChildByName(0,"Histos"); + if(root) {m_tree->DeleteChildren(root); + root->SetOpen(false); + updateTree(); + } +} + +void CosmicMonitoringGuiEmbedded::updateTree(){ + int x=m_tgc->GetViewPort()->GetX(); + int y=m_tgc->GetViewPort()->GetY(); + int w=m_tgc->GetViewPort()->GetWidth(); + int h=m_tgc->GetViewPort()->GetHeight(); + m_tree->DrawRegion(x,y,w,h); +} + +void CosmicMonitoringGuiEmbedded::updateHisto(){ + m_histo->SetMinimum(0); + if(m_histo->GetDimension()==1){ + m_canvas->GetCanvas()->SetCanvasSize(m_ww, m_wh); + if(std::string(m_histo->GetName()).substr(0,4)=="proj")gStyle->SetOptStat(1110); + else gStyle->SetOptStat(10); + m_histo->Draw(); + }else{ + gStyle->SetOptStat(10); + int nx=m_histo->GetNbinsX(); + int wh=0; + if(nx==144){ //FEI3 + wh=int(m_ww*0.944/0.4/144*320*0.05); + }else{ //FEI4 + wh=int(m_ww*0.944/0.25/80*336*0.05); + } + m_canvas->GetCanvas()->SetCanvasSize(m_ww, wh); + m_histo->Draw("colz"); + } +} + +void CosmicMonitoringGuiEmbedded::updateGraph(){ + m_canvas->GetCanvas()->SetCanvasSize(m_ww, m_wh); + m_graph->Draw("AP"); +} + +void CosmicMonitoringGuiEmbedded::fillHistoTree(){ + + char name[128], title[128]; + + clearTree(); + for (size_t i=0;i<m_histlist.size();i++){ + delete m_histlist[i]; + } + m_histlist.clear(); + for (int i=0;i<m_nMods;i++){ + if(m_fetype[i]==4){ + sprintf(name,"tempmin%d",i); + sprintf(title,"Temperature by minute Mod%d-RCE%d",m_outlinks[i],m_rceNums[i]); + m_tempmin[i]=new TGraph; + m_tempmin[i]->SetMinimum(-40); + m_tempmin[i]->SetMarkerStyle(22); + m_tempmin[i]->SetName(name); + m_tempmin[i]->SetTitle(title); + m_tempmin[i]->Expand(1000); + m_histlist.push_back(m_tempmin[i]); + sprintf(name,"tempsec%d",i); + sprintf(title,"Temperature 60 sec Mod%d-RCE%d",m_outlinks[i],m_rceNums[i]); + m_tempsec[i]=new TH1F(name, title, 60,0,60); + m_tempsec[i]->SetOption("p"); + m_tempsec[i]->SetMarkerStyle(22); + m_histlist.push_back(m_tempsec[i]); + }else{ + m_tempmin[i]=0; + m_tempsec[i]=0; + } + sprintf(name,"occ%d",i); + sprintf(title,"Occupancy Mod%d-RCE%d",m_outlinks[i],m_rceNums[i]); + if(m_fetype[i]==4){ + m_occ[i]=new TH2F(name,title, 80,0,80,336,0, 336); //FEI4 + m_histlist.push_back(m_occ[i]); + m_occ[i]->SetMinimum(0); + } else if(m_fetype[i]==3) { + m_occ[i]=new TH2F(name,title, 8*18,0,8*18,2*160,0, 2*160); + m_histlist.push_back(m_occ[i]); + m_occ[i]->SetMinimum(0); + }else{ + m_occ[i]=0; + } + if(m_fetype[i]==4){ + m_projx[i]=new TH1F(Form("projx%d%d",m_outlinks[i],m_rceNums[i]), + Form("X projection Mod %d RCE %d", m_outlinks[i],m_rceNums[i]), + 80,0,20); + m_projx[i]->GetXaxis()->SetTitle("x (mm)"); + m_projy[i]=new TH1F(Form("projy%d%d",m_outlinks[i],m_rceNums[i]), + Form("Y projection Mod %d RCE %d", m_outlinks[i],m_rceNums[i]), + 336,0,16.8); + m_projy[i]->GetXaxis()->SetTitle("y (mm)"); + m_histlist.push_back(m_projx[i]); + m_histlist.push_back(m_projy[i]); + } else if(m_fetype[i]==3) { + m_projx[i]=new TH1F(Form("projx%d%d",m_outlinks[i],m_rceNums[i]), + Form("X projection Mod %d RCE %d", m_outlinks[i],m_rceNums[i]), + 144,0,57.6); + m_projx[i]->GetXaxis()->SetTitle("x (mm)"); + m_projy[i]=new TH1F(Form("projy%d%d",m_outlinks[i],m_rceNums[i]), + Form("Y projection Mod %d RCE %d", m_outlinks[i],m_rceNums[i]), + 320,0,16); + m_projy[i]->GetXaxis()->SetTitle("y (mm)"); + m_histlist.push_back(m_projx[i]); + m_histlist.push_back(m_projy[i]); + }else{ + m_projx[i]=0; + m_projy[i]=0; + } + sprintf(name,"tot%d",i); + sprintf(title,"ToT Mod%d-RCE%d",m_outlinks[i],m_rceNums[i]); + if(m_fetype[i]==4){ + m_toth[i]=new TH1F(name,title, 60,-.5,59.5); + m_histlist.push_back(m_toth[i]); + } else if(m_fetype[i]==3) { + m_toth[i]=new TH1F(name,title, 256,-.5,255.5); + m_histlist.push_back(m_toth[i]); + } else + m_toth[i]=0; + + if(m_fetype[i]==3 || m_fetype[i]==4){ + sprintf(title,"Timing Mod%d-RCE%d",m_outlinks[i],m_rceNums[i]); + sprintf(name,"bx%d",i); + m_bx[i]=new TH1F(name,title, 16,-.5,15.5); + m_histlist.push_back(m_bx[i]); + + // sprintf(title,"ToT Vs Timestamp Mod%d-RCE%d",m_outlinks[i],m_rceNums[i]); + //sprintf(name,"tstamp%d",i); + //m_timestamp[i]=new TH1F(name, title, 5000,0.0,m_timeStampLimit); + //m_histlist.push_back(m_timestamp[i]); + m_timestamp[i]=0; + }else{ + m_bx[i]=0; + m_timestamp[i]=0; + } + if(m_fetype[i]==11){ // AFP HPTDC board + m_afptdc[i]=new TH1F*[12]; + for(int j=0;j<12;j++){ + sprintf(title,"TDC RCE%d-Board%d-Channel%d",m_rceNums[i],m_outlinks[i],j); + sprintf(name,"bx%d_%d",i,j); + m_afptdc[i][j]=new TH1F(name,title, 1024,-.5,1023.5); + m_histlist.push_back(m_afptdc[i][j]); + } + }else{ + m_afptdc[i]=0; + } + + + if(m_fetype[i]==3 || m_fetype[i]==4){ + int j=i+1; + if(j==m_nMods) j=0; //wrap around + while(m_fetype[j]!=3 && m_fetype[j]!=4){ + if(i==j)break; + j=j+1; + if(j==m_nMods)j=0; //wrap around + } + if(i!=j && m_corrindex[j]!=i){ + + int nX[2] = {8*18, 80}; + int nY[2] = {2*160, 336}; + int idxI =0, idxJ = 0; + + if(m_fetype[i]==4){ + idxI = 1; + } + if(m_fetype[j]==4){ + idxJ = 1; + } + sprintf(title,"Col-Col Correlation Mod%d-RCE%d x Mod%d-RCE%d",m_outlinks[i],m_rceNums[i],m_outlinks[j],m_rceNums[j]); + sprintf(name,"corxx%d%d",i,j); + m_corxx[i]=new TH2F(name,title, nX[idxI],0,nX[idxI],nX[idxJ],0,nX[idxJ]); + + sprintf(title,"Col-Row Correlation Mod%d-RCE%d x Mod%d-RCE%d",m_outlinks[i],m_rceNums[i],m_outlinks[j],m_rceNums[j]); + sprintf(name,"corxy%d%d",i,j); + m_corxy[i]=new TH2F(name,title, nX[idxI],0,nX[idxI],nY[idxJ],0,nY[idxJ]); + + sprintf(title,"Row-Row Correlation Mod%d-RCE%d x Mod%d-RCE%d",m_outlinks[i],m_rceNums[i],m_outlinks[j],m_rceNums[j]); + sprintf(name,"coryy%d%d",i,j); + m_coryy[i]=new TH2F(name,title, nY[idxI],0,nY[idxI],nY[idxJ],0,nY[idxJ]); + + sprintf(title,"Row-Col Correlation Mod%d-RCE%d x Mod%d-RCE%d",m_outlinks[i],m_rceNums[i],m_outlinks[j],m_rceNums[j]); + sprintf(name,"coryx%d%d",i,j); + m_coryx[i]=new TH2F(name,title, nY[idxI],0,nY[idxI],nX[idxJ],0,nX[idxJ]); + + m_histlist.push_back(m_corxx[i]); + m_histlist.push_back(m_corxy[i]); + m_histlist.push_back(m_coryy[i]); + m_histlist.push_back(m_coryx[i]); + m_corrindex[i]=j; + }else{ + m_corxx[i]=0; + m_corxy[i]=0; + m_coryy[i]=0; + m_coryx[i]=0; + } + } + } + + for (int i=0;i<m_nRces;i++){ + sprintf(title,"TDC for RCE %d",m_rces[i]); + sprintf(name,"tdc%d",i); + m_tdc[i]=new TH1F(name, title, 64,-.5,63.5); + m_histlist.push_back(m_tdc[i]); + for (int j=0;j<m_nMods;j++){ + if(m_fetype[j]==9){ + for(int k=0;k<2;k++){ + char tel[8]; + if(k==0)sprintf(tel,"A"); + else sprintf(tel,"B"); + for (int l=0;l<3;l++){ + sprintf(title,"Timing hitbus data RCE %d telescope %s FE %d", i, tel, l+1); + sprintf(name, "hbtiming_%d_%s_%d", i, tel, l+1); + m_hitbus[i][k][l]=new TH1F(name, title, 10,0,10); + m_histlist.push_back(m_hitbus[i][k][l]); + } + } + break; + } + } + } + + TGListTreeItem* root=m_tree->FindChildByName(0,"Histos"); + if (!root) root = m_tree->AddItem(0,"Histos"); + TGListTreeItem* occr=m_tree->AddItem(root,"Occupancy"); + TGListTreeItem* prxr=m_tree->AddItem(root,"Projection X"); + TGListTreeItem* pryr=m_tree->AddItem(root,"Projection Y"); + TGListTreeItem* timingr=m_tree->AddItem(root,"Timing"); + TGListTreeItem* totr=m_tree->AddItem(root,"ToT"); + TGListTreeItem* corr=m_tree->AddItem(root,"Correlation"); + TGListTreeItem* corrmods[m_nMods]; + for (int i=0;i<m_nMods;i++){ + sprintf(name,"Mod%d-RCE%d",m_outlinks[i],m_rceNums[i]); + corrmods[i]=m_tree->AddItem(corr, name); + } + TGListTreeItem* tempr=m_tree->AddItem(root,"Temperatures"); + TGListTreeItem* tdcr=m_tree->AddItem(root,"TDC"); + // TGListTreeItem* tstampr=m_tree->AddItem(root,"Timestamp"); + TGListTreeItem* hitbusr=m_tree->AddItem(root,"Hitbus Timing"); + TGListTreeItem* afpr=m_tree->AddItem(root,"AFP TDC"); + const TGPicture *thp = gClient->GetPicture("h1_t.xpm"); + + for (int i=0;i<m_nRces;i++){ + char mtit[128]; + sprintf(mtit,"TDC for RCE %d",m_rces[i]); + m_tree->AddItem(tdcr,mtit, m_tdc[i], thp, thp); + } + + for (int i=0;i<m_nRces;i++){ + char mtit[128]; + if(m_hitbus[i][0][0]!=0){ + for(int k=0;k<2;k++){ + char tel[8]; + if(k==0)sprintf(tel,"A"); + else sprintf(tel,"B"); + for(int l=0;l<3;l++){ + sprintf(mtit, "RCE %d Telescope %s FE %d", i, tel, l+1); + m_tree->AddItem(hitbusr, mtit, m_hitbus[i][k][l], thp, thp); + } + } + } + } + + + for(int i=0;i<m_nMods;i++){ + char mtit[128]; + sprintf(mtit,"Mod%d-RCE%d",m_outlinks[i],m_rceNums[i]); + if(m_tempsec[i]!=0)m_tree->AddItem(tempr,Form("%s-sec", mtit),m_tempsec[i], thp, thp); + if(m_tempmin[i]!=0)m_tree->AddItem(tempr,Form("%s-min", mtit),m_tempmin[i], thp, thp); + if(m_occ[i]!=0)m_tree->AddItem(occr,mtit,m_occ[i], thp, thp); + if(m_projx[i]!=0)m_tree->AddItem(prxr,mtit,m_projx[i], thp, thp); + if(m_projy[i]!=0)m_tree->AddItem(pryr,mtit,m_projy[i], thp, thp); + if(m_toth[i]!=0)m_tree->AddItem(totr,mtit,m_toth[i], thp, thp); + if(m_bx[i]!=0)m_tree->AddItem(timingr,mtit, m_bx[i], thp, thp); + //if(m_timestamp[i]!=0)m_tree->AddItem(tstampr,mtit, m_timestamp[i], thp, thp); + if(m_afptdc[i]!=0){ + TGListTreeItem* mfpr=m_tree->AddItem(afpr,mtit); + for(int j=0;j<12;j++){ + sprintf(mtit, "Ch%d", j); + m_tree->AddItem(mfpr, mtit, m_afptdc[i][j], thp, thp); + } + } + if(m_corxx[i]!=0){ + int j=m_corrindex[i]; + sprintf(mtit,"Col-Col Mod%d-RCE%d x Mod%d-RCE%d",m_outlinks[i],m_rceNums[i],m_outlinks[j],m_rceNums[j]); + m_tree->AddItem(corrmods[i],mtit, m_corxx[i], thp, thp); + sprintf(mtit,"Col-Row Mod%d-RCE%d x Mod%d-RCE%d",m_outlinks[i],m_rceNums[i],m_outlinks[j],m_rceNums[j]); + m_tree->AddItem(corrmods[i],mtit, m_corxy[i], thp, thp); + sprintf(mtit,"Row-Row Mod%d-RCE%d x Mod%d-RCE%d",m_outlinks[i],m_rceNums[i],m_outlinks[j],m_rceNums[j]); + m_tree->AddItem(corrmods[i],mtit, m_coryy[i], thp, thp); + sprintf(mtit,"Row-Col Mod%d-RCE%d x Mod%d-RCE%d",m_outlinks[i],m_rceNums[i],m_outlinks[j],m_rceNums[j]); + m_tree->AddItem(corrmods[i],mtit, m_coryx[i], thp, thp); + } + } + + root->SetOpen(true); + timingr->SetOpen(true); + totr->SetOpen(true); + occr->SetOpen(true); + tempr->SetOpen(true); + prxr->SetOpen(true); + pryr->SetOpen(true); + corr->SetOpen(true); + afpr->SetOpen(true); + for (int i=0;i<m_nMods;i++){ + corrmods[i]->SetOpen(true); + } +} + +void CosmicMonitoringGuiEmbedded::displayHisto(TGListTreeItem* item, int b){ + TGListTreeItem *parent=item->GetParent(); + if(parent==0)return; + if(std::string(parent->GetText())=="Histos")return; + if(std::string(parent->GetText())=="Correlation")return; + if(std::string(parent->GetText())=="AFP TDC")return; + TObject *t=(TObject*)item->GetUserData(); + if(t->InheritsFrom("TH1")){ + m_histo=(TH1*)item->GetUserData(); + m_graph=0; + }else if(t->InheritsFrom("TGraph")){ + m_graph=(TGraph*)item->GetUserData(); + m_histo=0; + } + updateDisplay(); +} + +void CosmicMonitoringGuiEmbedded::updateDisplay(){ + if(m_www!=GetWidth()|| + m_hhh!=GetHeight()){ + m_www=GetWidth(); + m_hhh=GetHeight(); + m_ww=m_canvas->GetCanvas()->GetWw(); + m_wh=m_canvas->GetCanvas()->GetWh(); + } + m_canvas->GetCanvas()->Clear(""); + m_canvas->GetCanvas()->Update(); + if(m_histo!=0) updateHisto(); + else if(m_graph!=0){ + m_graphmutex.Lock(); //ROOT crashes if the graph is updated between Draw() and canvas Update() + updateGraph(); + } + m_canvas->GetCanvas()->Update(); + if(m_graph!=0)m_graphmutex.UnLock(); +} + +unsigned CosmicMonitoringGuiEmbedded::nextcurrent(unsigned char* p){ + unsigned current=*(unsigned*)&p[m_indx]; + //unsigned current=(p[m_indx]<<24) | (p[m_indx+1]<<16) | (p[m_indx+2]<<8) | p[m_indx+3]; + m_indx+=4; + return current; +} +unsigned CosmicMonitoringGuiEmbedded::getWord(unsigned char *p, int word){ + return *(unsigned*)&p[word*4]; + //return (p[word*4]<<24) | (p[word*4+1]<<16) | (p[word*4+2]<<8) | p[word*4+3]; +} + + +bool CosmicMonitoringGuiEmbedded::setupChannelsFromFile(const char* filename) +{ + std::cout<<"Setting up channels based on first event in file "<<filename<<std::endl; + eudaq::FileDeserializer fs(filename); + bool itWorked=false; + + if(fs.HasData()){ + + eudaq::DetectorEvent* dev=(eudaq::DetectorEvent*)eudaq::EventFactory::Create(fs); + dev=(eudaq::DetectorEvent*)eudaq::EventFactory::Create(fs); //get the second event in file (first event is just a file header) + + if(dev->IsEORE() || dev->IsBORE()) return false; + eudaq::RawDataEvent::data_t pixblock; + + int rce=-1; + int link=-1; + + for(unsigned k=0;k<dev->NumEvents();k++){ + + eudaq::RawDataEvent* rev=(eudaq::RawDataEvent*)dev->GetEvent(k); + + int totalBlocks = rev->NumBlocks(); + int currentBlock = 0; + + if(rev->GetSubType()=="APIX-CT"){ + eudaq::RawDataEvent::data_t block0=rev->GetBlock(0); + + size_t blockSize = block0.size(); + const unsigned tdcSize = 10; //number of 4-byte words of TDC data per RCE + + int nTDC = blockSize/(4*tdcSize); + + for(int iTDC=0; iTDC<nTDC; iTDC++){ + int firstWord = iTDC*tdcSize; + unsigned rceNum=getWord(&block0[0],firstWord+0); + rceNum = rceNum&0xff; + addRce(rceNum); + } + currentBlock = 1; + + }else if(rev->GetSubType()=="CTEL"){ + currentBlock = 0; + totalBlocks = 1; + }else{ + //std::cout<<"Unknown data block. Skipping."<<std::endl; + continue; + } + + + while(currentBlock<totalBlocks){ + + pixblock=rev->GetBlock(currentBlock); + m_indx=0; + + while (m_indx<pixblock.size()){ + unsigned currentu=nextcurrent(&pixblock[0]); + + FormattedRecord current(currentu); + if(current.isHeader()){ + link=current.getLink(); + bool newlink = createLink(link,rce); + if(newlink){ + m_fetype.push_back(4); //hard-code FEI4 for now + } + } + else if(current.isHeaderTwo()){ + rce = current.getRCE(); + } + else{ + continue; + } + + } + currentBlock++; + } //end loop over all the pixel blocks in event + + } //end loop over all the 'events' + + itWorked=true; + } + return itWorked; + +} + + +bool CosmicMonitoringGuiEmbedded::readFile(const char* filename,int nevt) +{ + //This reads in a file in the EUDET format + + std::cout<<"Reading file "<<filename<<std::endl; + + m_nev = ntrg = highesttot = 0; + eudaq::FileDeserializer fs(filename); + while(fs.HasData()){ + eudaq::DetectorEvent* dev=(eudaq::DetectorEvent*)eudaq::EventFactory::Create(fs); + if(m_nev>nevt)break; + //if(nev==10)break; + // dev->Print(std::cout); + addEvent(dev); + } + std::cout<<"\n----------Summary---------------------"<<std::endl; + std::cout<<"Highest ToT: "<<highesttot<<std::endl; + //need to subtract 2 from m_nev because of the end-of-file and begin-of-file + std::cout<<(m_nev-2)<<" events. "<<ntrg<<" triggers, summed over all frontends."<<std::endl; + + return true; +} +bool CosmicMonitoringGuiEmbedded::addEvent(const eudaq::DetectorEvent* dev, bool refresh){ + eudaq::RawDataEvent::data_t pixblock; + if(dev->IsEORE() || dev->IsBORE()) return false; + // std::cout<<std::endl<<"Adding a new event!!!"<<std::endl; + + int l1id=-1; + int link=-1; + int bxid=0; + int rce=-1; + int firstbxid=-1; + int oldrce=-1; + int oldbxid[MAX_LINKS]; + std::vector<int> modtot; + for(int i=0;i<m_nMods;i++){ + modtot.push_back(0); + m_nhits[i]=0; + oldbxid[m_outlinks[i]]=-1; + } + + //std::vector<double> timeStamps; + //for(int i=0; i<m_nRces; i++){ + //timeStamps.push_back(0); + //} + + + for(unsigned k=0;k<dev->NumEvents();k++){ + eudaq::RawDataEvent* rev=(eudaq::RawDataEvent*)dev->GetEvent(k); + + int totalBlocks = rev->NumBlocks(); + int currentBlock = 0; + m_triggerPhase = -1; + + if(rev->GetSubType()=="APIX-CT"){ + m_nev++; + if((m_nev-1)%10000==0){ + std::cout<<"Event "<<(m_nev-1)<<std::endl; + if(m_nev>1){ + for (int i=0;i<m_nMods;i++){ + if(m_occ[i]==0)continue; + float rate=0; + if(m_occ[i]->GetEntries()-m_lastcount[i]>0)rate=(m_occ[i]->GetEntries()-m_lastcount[i])/10000; + std::cout<<"Hits per event for "<<m_rceNums[i]<<" "<<m_outlinks[i]<<": "<<rate <<std::endl; + m_lastcount[i]=m_occ[i]->GetEntries(); + if((m_nMods>1 && i==1)||m_nMods==1)m_hitsperevent=rate; + } + } + } + // std::cout<<"event "<<m_nev<<" contains "<<dev->NumEvents()<<" 'events' "<<std::endl; + + eudaq::RawDataEvent::data_t block0=rev->GetBlock(0); + + size_t blockSize = block0.size(); + const unsigned tdcSize = 10; //number of 4-byte words of TDC data per RCE + + int nTDC = blockSize/(4*tdcSize); + + //for(unsigned int i=0;i<(blockSize/4);i++){ + // std::cout<<std::hex<<getWord(&block0[0],i)<<std::dec<<std::endl; + //} + + int oldBitpos=-1; + for(int iTDC=0; iTDC<nTDC; iTDC++){ + + int firstWord = iTDC*tdcSize; + + unsigned rceNum=getWord(&block0[0],firstWord+0); + rceNum = rceNum&0xff; + + unsigned counter1=getWord(&block0[0],firstWord+3); + unsigned counter2=getWord(&block0[0],firstWord+4); + unsigned long long counter=counter2; + counter=(counter<<32) | counter1; + //printf("%llx\n",counter); + int bitpos=-1; + for (int j=0;j<64;j++){ + if(((counter>>j)&1)==0){ + bitpos=j; + break; + } + } + // if(bitpos!=-1)std::cout<<"Phase is " <<bitpos*.4<<" ns"<<std::endl; + + for(int iRce=0; iRce<m_nRces; iRce++){ + if(m_rces[iRce]==rceNum){ + if(bitpos!=-1){ + m_tdc[iRce]->Fill(bitpos); + m_triggerPhase = bitpos; + if (oldBitpos!=-1 && oldBitpos!=bitpos){ + std::cout<<"TDC value mismatch between RCEs"<<std::endl; + } + oldBitpos=bitpos; + } + break; + } + } + + for(int iRce=0; iRce<m_nRces; iRce++){ + if(m_rces[iRce]==rceNum){ + if(m_hitbus[iRce][0][0]!=0){ + for(int k=0;k<2;k++){ + for (int l=0;l<3;l++){ + int edge=hitbusEdge(k==0?counter1 : counter2,l); + if(edge!=-1)m_hitbus[iRce][k][l]->Fill(edge); + } + } + } + break; + } + } + + + + unsigned trgtime1=getWord(&block0[0],firstWord+5); + unsigned trgtime2=getWord(&block0[0],firstWord+6); + unsigned deadtime1=getWord(&block0[0],firstWord+7); + unsigned deadtime2=getWord(&block0[0],firstWord+8); + unsigned long long trgtime=trgtime1; + trgtime=(trgtime<<32) | trgtime2; + unsigned long long deadtime=deadtime1; + deadtime=(deadtime<<32) | deadtime2; + //unsigned hitbusword=(getWord(&block0[0],firstWord+9)&0xf000000)>>24; + //std::cout<<"Trigtime "<<trgtime<<std::endl; + //std::cout<<"Deadtime "<<deadtime<<std::endl; + //double timeStampSeconds = trgtime * 25.6e-9; + //std::cout<<"event "<<m_nev<<" on RCE "<<rceNum<<"\t\t Time stamp: "<<timeStampSeconds<<" sec."<<std::endl; + //rebinTimestamps(timeStampSeconds); + // unsigned eudaqtrg=getWord(&block0[0],firstWord+9); + // std::cout<<"Eudaq trigger word: "<<eudaqtrg<<std::endl; + //for(int iRce=0; iRce<m_nRces; iRce++){ + //if(m_rces[iRce]==rceNum){ + //timeStamps[iRce] = timeStampSeconds; + //} + //} + + if(m_writeRootFile==true && iTDC==0){ + m_eventinfo.timestamp=time(NULL); + m_eventinfo.framenumber=m_nev; + m_eventinfo.triggerTime=trgtime; + m_evtree->Fill(); + } + } //end loop over the different RCE's in the TDC block + + currentBlock = 1; + + }else if(rev->GetSubType()=="CTEL"){ + currentBlock = 0; + totalBlocks = 1; + }else if(rev->GetSubType()=="TEMP"){ + // Temperature readout + pixblock=rev->GetBlock(0); + unsigned rce=getWord(&pixblock[0],0); + unsigned short *adc=(unsigned short*)&pixblock[4]; + unsigned timenow=(unsigned)time(0); + int timediffsec=timenow-m_starttime_sec; + for(int i=0;i<8;i++){ + float res=0; + int chan=i; // remapped to outlinks. + int mod = m_linkToIndex[rce][chan]; + if(mod==-1 || m_tempsec[mod]==0)continue; + float reading=float(adc[i]&0xfff); + if(reading==0)res=0; + else res=(4095./reading-1)*10000-100; + float temperature=-273; + float b=3435; + if(res!=0)temperature=b*298.15/(b+log(res/10000)*298.15)-273.15; + if(timediffsec%60<m_lasttime_sec){ + float newval=0; + if(m_tempsec[mod]->GetEntries()>0)newval=m_tempsec[mod]->GetSumOfWeights()/m_tempsec[mod]->GetEntries(); + m_graphmutex.Lock(); + m_tempmin[mod]->SetPoint(m_tempmin[mod]->GetN(), (float)timediffsec/60, newval); + m_graphmutex.UnLock(); + m_tempsec[mod]->Reset(); + } + if(m_tempsec[mod]->GetBinContent(timediffsec%60)==0){ //sometimes 2 readings in the same bin + m_tempsec[mod]->SetBinContent(timediffsec%60, temperature); + if(m_logtemps==true)*m_tempfile<<timenow<<" "<<rce<<" "<<chan<<" "<<temperature<<std::endl; + } + } + m_lasttime_sec=timediffsec%60; + if (refresh) updateDisplay(); + return true; + }else{ + //std::cout<<"Unknown data block. Skipping."<<std::endl; + continue; + } + + while(currentBlock<totalBlocks){ + + pixblock=rev->GetBlock(currentBlock); + m_indx=0; + + while (m_indx<pixblock.size()){ + unsigned currentu=nextcurrent(&pixblock[0]); + + FormattedRecord current(currentu); + if(current.isHeader()){ + ntrg++; //really, this is the total number of triggers summed over all the modules + link=current.getLink(); + int l1id_temp=current.getL1id()&0xf; + bxid=current.getBxid()&0xff; + if(l1id==-1){ + l1id = l1id_temp; + } else{ + if(l1id_temp != l1id){ + std::cout<<"Not all data in event has same l1id!! FATAL ERROR!"<<std::endl; + assert(0); + } + } + if(firstbxid==-1){ + firstbxid = bxid; + } + + if( oldbxid[link]!=-1 ){ + int bxid_expected = oldbxid[link] + 1; + if(bxid_expected==256){ + bxid_expected=0; + } + if(bxid!=bxid_expected){ + std::cout<<"WARNING: RCE "<<rce<<" link "<<link<<" has bxid = "<<bxid; + std::cout<<" ; expected bxid = "<<bxid_expected<<std::endl; + } + } else{ + //this is the first data from this rce/link in this event. + if(bxid!=firstbxid){ + std::cout<<"ERROR: not all the modules in RCE "<<rce<<" in this event have the "; + std::cout<<"same initial bxid. FATAL ERROR."<<std::endl; + assert(0); + } + + } + oldbxid[link] = bxid; + } + else if(current.isHeaderTwo()){ + rce = current.getRCE(); + if(rce != oldrce){ + oldrce=rce; + for(int i=0;i<m_nMods;i++)oldbxid[m_outlinks[i]]=-1; + firstbxid=-1; //Modules from different rce's can have different + //bxid's, even if they have the same l1id + } + + }else if(current.isData()){ + m_nhit++; + int mod = m_linkToIndex[rce][link]; + int chip=0; + int tot=0; + int col=0; + int row=0; + int x=0; + int y=0; + int diffbx=0; + if(m_fetype[mod]==3 || m_fetype[mod]==4){ + chip=current.getFE(); + tot=current.getToT(); + if(tot>highesttot)highesttot=tot; + col=current.getCol(); + row=current.getRow(); + diffbx=bxid-firstbxid; + if (diffbx<0)diffbx+=256; + if (chip<8){ + x=18*chip+col; + y=row; + } else { + x=(15-chip)*18+17-col; + y= 319-row; + } + if(m_occ[mod]!=0){ + m_occ[mod]->Fill(x,y); + modtot[mod]+=tot; + m_bx[mod]->Fill(diffbx); + } + if(m_projx[mod]!=0){ + int nx=m_projx[mod]->GetNbinsX(); + double scale=0.25; + if(nx==144)scale=0.4; + m_projx[mod]->Fill(x*scale+scale/2); + m_projy[mod]->Fill(0.05*y+0.025); + } + }else if (m_fetype[mod]==11){ //AFP HPTDC + unsigned word=current.getWord(); + unsigned tdcid=(word>>24)&0xf; + if (tdcid>0xc || tdcid<0xa){ //TDC ids are a, b, c + std::cout<<"Bad TDC id"<<std::endl; + }else{ + unsigned chan=(word>>22)&0x3; + x=(tdcid-0xa)*4+chan; + y=(word>>28)&0x1; + tot=word&0x1fffff; //10 bits + if(m_afptdc[mod]!=0){ + m_afptdc[mod][x]->Fill(tot&0x3ff); + } + } + } + if(m_nhits[mod]<MAXHIT){ + m_pixx[mod][m_nhits[mod]]=x; + m_pixy[mod][m_nhits[mod]]=y; + m_value[mod][m_nhits[mod]]=tot; + m_timing[mod][m_nhits[mod]]=diffbx; + m_nhits[mod]++; + }else{ + std::cout<<"MORE THAN "<<MAXHIT<<" hits in module RCE "<<m_rceNums[mod]<<" outlink "<<m_outlinks[mod]<<std::endl; + } + } + + }//end loop over data in the pixel block + + currentBlock++; + } //end loop over all the pixel blocks in event + + } //end loop over all the events + + + for(int i=0;i<m_nMods;i++){ + + if(m_toth[i]!=0 && modtot[i]!=0)m_toth[i]->Fill(modtot[i]); + + //double theTimeStamp=0; + //unsigned rceNum = m_rceNums[i]; + + //for(int iRce=0; iRce<m_nRces; iRce++){ + //if(m_rces[iRce]==rceNum){ + ////std::cout<<"getting timestamp for iRce = "<<iRce<<std::endl; + //theTimeStamp = timeStamps[iRce]; + //} + //} + + //if(modtot[i]>100){ + // std::cout<<"filling stamp for mod "<<i<<" with "<<theTimeStamp<<std::endl; + //std::cout<<m_timestamp[i]<<std::endl; + //if(m_timestamp[i]!=0)m_timestamp[i]->Fill(theTimeStamp,modtot[i]); + //} + + //if(modtot[i]>100){ + //std::cout<<"Noisy hit on event "<<m_nev<<", timestamp "<<theTimeStamp<<" s, with ToT on mod "<<i<<" = "<<modtot[i]<<std::endl; + //} + + if(m_corxx[i]!=0){ + int j=m_corrindex[i]; + for(int iHit=0; iHit<m_nhits[i]; iHit++){ + for(int jHit=0; jHit<m_nhits[j]; jHit++){ + + int x1 = m_pixx[i][iHit]; + int y1 = m_pixy[i][iHit]; + int x2 = m_pixx[j][jHit]; + int y2 = m_pixy[j][jHit]; + + m_corxx[i]->Fill(x1,x2); + m_corxy[i]->Fill(x1,y2); + m_coryy[i]->Fill(y1,y2); + m_coryx[i]->Fill(y1,x2); + + } + } + } + if(m_writeRootFile==true){ + m_pltree[i]->Fill(); + } + } + + if (refresh) updateDisplay(); + + return true; + +} + +void CosmicMonitoringGuiEmbedded::addRce(unsigned int rceNum){ + + int rceSize = m_rces.size(); + bool newRce=true; + for(int iRce=0; iRce<rceSize; iRce++){ + if(m_rces[iRce]==rceNum){ + newRce=false; + break; + } + } + if(newRce){ + std::cout<<"Adding rce "<<rceNum<<std::endl; + m_rces.push_back(rceNum); + } + m_nRces=m_rces.size(); + +} + +void CosmicMonitoringGuiEmbedded::printModules(){ + + for (unsigned int i=0; i<m_config.size(); i++){ + + if(m_config[i]->isIncluded()){ + //valid=true; + unsigned outlink=m_config[i]->getOutLink(); + unsigned rce=m_config[i]->getRce(); + std::cout<<"Module "<<i<<" : rce = "<<rce<<", outlink = "<<outlink<<std::endl; + } + } + +} + +bool CosmicMonitoringGuiEmbedded::createLink(unsigned outlink, unsigned rceNum){ + bool newLink=false; + + if(m_linkmap.find(outlink + 1000*rceNum) != m_linkmap.end()){ + //std::cout<<"Already have link "<<outlink<<" rce "<<rceNum<<std::endl; + } + else{ + std::cout<<"Making link "<<outlink<<" rce "<<rceNum<<std::endl; + + m_linkmap[outlink + 1000*rceNum] = m_nMods; + if(m_linkToIndex[rceNum]==0){ + m_linkToIndex[rceNum]=new int[MAX_LINKS]; + for(int i=0;i<MAX_LINKS;i++)m_linkToIndex[rceNum][i]=-1; + } + m_linkToIndex[rceNum][outlink]=m_nMods; + m_outlinks.push_back(outlink); + m_rceNums.push_back(rceNum); + m_nMods++; + newLink=true; + } + + return newLink; + +} + +void CosmicMonitoringGuiEmbedded::saveHistos(int runnum, const char* datadir){ + + char filename[512]; + sprintf(filename, "%s/cosmic_%06d/monitoringHistograms.root", datadir, runnum); + TFile histofile(filename, "recreate"); + for (int i=0;i<m_nMods;i++){ + if (m_tempmin[i] != 0) m_tempmin[i]->Write(); + if (m_tempsec[i] != 0) m_tempsec[i]->Write(); + if (m_occ[i] != 0) m_occ[i]->Write(); + if (m_toth[i] != 0) m_toth[i]->Write(); + if (m_bx[i] != 0) m_bx[i]->Write(); + //if (m_timestamp[i]!=0) m_timestamp[i]->Write(); + if (m_corxx[i] != 0) m_corxx[i]->Write(); + if (m_corxy[i] != 0) m_corxy[i]->Write(); + if (m_coryy[i] != 0) m_coryy[i]->Write(); + if (m_coryx[i] != 0) m_coryx[i]->Write(); + if (m_projx[i] != 0) m_projx[i]->Write(); + if (m_projy[i] != 0) m_projy[i]->Write(); + if (m_afptdc[i]!=0){ + for (int j=0;j<12;j++){ + m_afptdc[i][j]->Write(); + } + } + } + for(int i=0; i<m_nRces; i++){ + if (m_tdc[i]!=0) m_tdc[i]->Write(); + for (int k=0;k<2;k++){ + for (int l=0;l<3;l++){ + if(m_hitbus[i][k][l]!=0)m_hitbus[i][k][l]->Write(); + } + } + } +} + +void CosmicMonitoringGuiEmbedded::saveScreenshot(int runnum, const char* datadir){ + + char filename[512]; + sprintf(filename, "%s/cosmic_%06d/screenshot_%d.png", datadir, runnum, m_nScreenshots++); + std::cout<<filename<<std::endl; + m_canvas->SaveAs(filename); +} + +void CosmicMonitoringGuiEmbedded::rebinTimestamps(double timeStamp){ + + while( (timeStamp + 1) > m_timeStampLimit ){ + + m_timeStampLimit = m_timeStampLimit*2; + + //std::cout<<"Timestamp limit changed to "<<m_timeStampLimit<<std::endl; + + for(int imod=0; imod<m_nMods; imod++){ + if(m_timestamp[imod]!=0){ + const int nbins = m_timestamp[imod]->GetNbinsX(); + double xmin = m_timestamp[imod]->GetBinLowEdge(1); + double xmax = m_timestamp[imod]->GetBinLowEdge(nbins+1); + double newxmax = 2*(xmax-xmin) + xmin; + + double yvals[nbins]; + + //std::cout<<"Originally:"<<std::endl; + //for(int jbin=0; jbin < nbins; jbin++){ + // std::cout<<"jbin+1: "<<jbin+1<<" = "<<m_timestamp[imod]->GetBinContent(jbin+1)<<std::endl; + // } + + + for(int jbin=0; jbin < nbins; jbin++){ + yvals[jbin] = 0; + } + for(int jbin=0; jbin < (nbins/2); jbin++){ + int bin1 = jbin*2 + 1; + yvals[jbin] = m_timestamp[imod]->GetBinContent(bin1) + m_timestamp[imod]->GetBinContent(bin1+1); + } + + m_timestamp[imod]->SetBins(nbins,xmin,newxmax); + + for(int jbin=0; jbin < nbins; jbin++){ + m_timestamp[imod]->SetBinContent(jbin+1,yvals[jbin]); + } + + //std::cout<<"Now:"<<std::endl; + // for(int jbin=0; jbin < nbins; jbin++){ + // std::cout<<"jbin+1: "<<jbin+1<<" = "<<m_timestamp[imod]->GetBinContent(jbin+1)<<std::endl; + // } + + } + } + + + } + +} + +void CosmicMonitoringGuiEmbedded::setupRootFile(const char* rootfile){ + m_evfile=new TFile(rootfile, "recreate"); + m_pltree=new TTree*[m_nMods]; + for (int i=0;i<m_nMods;i++){ + char name[128]; + sprintf(name, "Plane%d", i); + m_evfile->cd(); + m_evfile->mkdir(name); + m_evfile->cd(name); + m_pltree[i]=new TTree("Hits", "Hits"); + m_pltree[i]->Branch("NHits", &m_nhits[i], "NHits/I"); + m_pltree[i]->Branch("PixX", m_pixx[i], "HitPixX[NHits]/I"); + m_pltree[i]->Branch("PixY", m_pixy[i], "HitPixY[NHits]/I"); + m_pltree[i]->Branch("Value", m_value[i], "HitValue[NHits]/I"); + m_pltree[i]->Branch("Timing", m_timing[i], "HitTiming[NHits]/I"); + m_pltree[i]->Branch("HitInCluster", m_hitincluster[i], "HitInCluster[NHits]/I"); + m_pltree[i]->Branch("PosX", m_posx[i], "HitPosX[NHits]/D"); + m_pltree[i]->Branch("PosY", m_posy[i], "HitPosY[NHits]/D"); + m_pltree[i]->Branch("PosZ", m_posz[i], "HitPosZ[NHits]/D"); + } + m_evfile->cd(); + m_evtree=new TTree("Event", "Event information"); + m_evtree->Branch("TimeStamp", &m_eventinfo.timestamp, "TimeStamp/l"); + m_evtree->Branch("FrameNumber", &m_eventinfo.framenumber, "FrameNumber/l"); + m_evtree->Branch("TriggerOffset", &m_eventinfo.triggeroffset, "TriggerOffset/I"); + m_evtree->Branch("TriggerInfo", &m_eventinfo.triggerinfo, "TriggerInfo/I"); + m_evtree->Branch("Invalid", &m_eventinfo.invalid, "Invalid/O"); + m_evtree->Branch("TriggerTime", &m_eventinfo.triggerTime, "TriggerTime/l"); + m_evtree->Branch("TriggerPhase", &m_triggerPhase, "TriggerPhase/I"); + m_evfile->Write(); + +} +void CosmicMonitoringGuiEmbedded::closeRootFile(){ + usleep(500000); + m_evfile->Write(); + m_evfile->Close(); + m_evfile->Delete(); + delete [] m_pltree; +} +void CosmicMonitoringGuiEmbedded::closeTempFile(){ + m_tempfile->close(); + delete m_evfile; +} diff --git a/rce/rcecalib/server/CosmicMonitoringGuiEmbedded.hh b/rce/rcecalib/server/CosmicMonitoringGuiEmbedded.hh new file mode 100644 index 00000000..c58cd518 --- /dev/null +++ b/rce/rcecalib/server/CosmicMonitoringGuiEmbedded.hh @@ -0,0 +1,140 @@ +#ifndef COSMICMONITORINGGUIEMBDED_HH +#define COSMICMONITORINGGUIEMBDED_HH + +#include "ConfigGui.hh" +#include "TGMdiMainFrame.h" +#include <TGLabel.h> +#include <TGTextEntry.h> +#include <TGNumberEntry.h> +#include "TFile.h" +#include "TH2F.h" +#include "TGraph.h" +#include <TTree.h> +#include <string> +#include <map> +#include "TMutex.h" + +#define MAX_RCES 8 +#define MAXHIT 1000 + + +class TGListTree; +class TGListTreeItem; +class TH1; +class TRootEmbeddedCanvas; +class IPCGuiCallback; +namespace eudaq { +class DetectorEvent; +} + +struct EventInfo{ + ULong64_t timestamp; + ULong64_t framenumber; + Int_t triggeroffset; + Int_t triggerinfo; + Bool_t invalid; + ULong64_t triggerTime; +}; + +class CosmicMonitoringGuiEmbedded: public TGVerticalFrame { +public: + CosmicMonitoringGuiEmbedded(const char* filename, int nevt, const TGWindow *p,UInt_t w,UInt_t h,UInt_t options); + CosmicMonitoringGuiEmbedded(const TGWindow *p,UInt_t w,UInt_t h,UInt_t options, const std::vector<ConfigGui*> config); + virtual ~CosmicMonitoringGuiEmbedded(); + void setup(bool online, bool writeRootFile, const char* rootfile, bool writeTemps, const char* tempfile); + void clearTree(); + void updateTree(); + void updateDisplay(); + void updateHisto(); + void updateGraph(); + void saveHistos(int runnum, const char* datadir); + void saveScreenshot(int runnum, const char* datadir); + void displayHisto(TGListTreeItem* item, int b); + unsigned nextcurrent(unsigned char* p); + unsigned getWord(unsigned char *p, int word); + bool setupChannelsFromFile(const char* filename); + bool addEvent(const eudaq::DetectorEvent* dev, bool refresh = false); + bool readFile(const char* filename, int nevt); + void addRce(unsigned int rceNum); + void printModules(); + bool createLink(unsigned outlink, unsigned rceNum); + void rebinTimestamps(double timestamp); + double getHitsPerEvent(){return m_hitsperevent;} + void closeRootFile(); + void closeTempFile(); + +private: + + void fillHistoTree(); + void init(); + void setupRootFile(const char* rootfile); + + enum Filemenu {LOAD, SAVE, QUIT}; + TGTextButton* *m_quit; + TGListTree* m_tree; + TH1 *m_histo; + TGraph* m_graph; + const std::vector<ConfigGui*> m_config; + const char* m_filename; + TRootEmbeddedCanvas *m_canvas; + std::string m_dir; + bool m_delhisto; + TGCanvas *m_tgc; + + //Currently setting the limit at 4 RCE's (with 8 modules each) + TH2F* m_occ[ConfigGui::MAX_MODULES]; + TH2F* m_corxx[ConfigGui::MAX_MODULES-1]; + TH2F* m_corxy[ConfigGui::MAX_MODULES-1]; + TH2F* m_coryy[ConfigGui::MAX_MODULES-1]; + TH2F* m_coryx[ConfigGui::MAX_MODULES-1]; + TH1F* m_toth[ConfigGui::MAX_MODULES]; + TH1F* m_bx[ConfigGui::MAX_MODULES]; + TH1F* m_tdc[MAX_RCES]; + TH1F* m_hitbus[MAX_RCES][2][3]; + TH1F* m_timestamp[ConfigGui::MAX_MODULES]; + TH1F* m_projx[ConfigGui::MAX_MODULES]; + TH1F* m_projy[ConfigGui::MAX_MODULES]; + TH1F **m_afptdc[ConfigGui::MAX_MODULES]; + int m_corrindex[ConfigGui::MAX_MODULES]; + TH1F* m_tempsec[ConfigGui::MAX_MODULES]; + TGraph* m_tempmin[ConfigGui::MAX_MODULES]; + std::vector<TObject*> m_histlist; + + unsigned int m_indx; + double m_noiserate; + int m_noiseUpdateTime; + + std::map<int,int> m_linkmap; + enum constants{MAX_RCE_NUM=100, MAX_LINKS=16}; + int **m_linkToIndex; + std::vector<unsigned> m_outlinks; + std::vector<unsigned> m_rceNums; + std::vector<int> m_fetype; + std::vector<unsigned int> m_rces; + int m_nMods; + int m_nRces; + int m_nev; + int m_nhit; + int ntrg; + int highesttot; + double m_timeStampLimit; + unsigned int m_ww, m_wh, m_www, m_hhh; + int m_lastcount[ConfigGui::MAX_MODULES]; + double m_hitsperevent; + int m_nScreenshots; + TFile *m_evfile; + std::ofstream *m_tempfile; + TTree **m_pltree, *m_evtree; + Int_t *m_nhits; + Int_t **m_pixx, **m_pixy, **m_value, **m_timing, **m_hitincluster; + Int_t m_triggerPhase; + Double_t **m_posx, **m_posy, **m_posz; + EventInfo m_eventinfo; + bool m_writeRootFile, m_logtemps; + unsigned m_starttime_sec; + int m_lasttime_sec; + TMutex m_graphmutex; + +ClassDef (CosmicMonitoringGuiEmbedded,0) +}; +#endif diff --git a/rce/rcecalib/server/CosmicOfflineDataProc.cc b/rce/rcecalib/server/CosmicOfflineDataProc.cc new file mode 100644 index 00000000..0aa3f6dc --- /dev/null +++ b/rce/rcecalib/server/CosmicOfflineDataProc.cc @@ -0,0 +1,378 @@ +#include <boost/property_tree/ptree.hpp> +#include <boost/regex.hpp> +#include <boost/algorithm/string.hpp> +#include "server/CosmicOfflineDataProc.hh" +#include "config/ConfigIF.hh" +#include "config/FormattedRecord.hh" +#include "dataproc/DataProcFactory.hh" +#include "dataproc/CosmicEventReceiver.hh" +#include "dataproc/CosmicEvent.hh" +#include "dataproc/CosmicEventIterator.hh" +#include "dataproc/Channeldefs.hh" +#include "server/IPCController.hh" +#include "config/AbsFormatter.hh" +#include "config/ModuleInfo.hh" +#include "eudaq/Event.hh" +#include "eudaq/DataSender.hh" +#include "eudaq/DataSenderIF.hh" +#include "eudaq/DetectorEvent.hh" +#include "eudaq/RawDataEvent.hh" +#include "eudaq/counted_ptr.hh" +#include <iomanip> +#include <iostream> +#include <stdlib.h> +#include <time.h> + +namespace{ + const unsigned timeout=5; +} + +void printhitbus(unsigned word){ + for (int i=0;i<3;i++){ + std::cout<<"FE "<<3-i<<": "; + for (int j=0;j<10;j++){ + std::cout<<((word&(1<<(j*3+i)))!=0); + } + std::cout<<std::endl; + } +} +int CosmicOfflineDataProc::processData(unsigned short rlink, unsigned char* data, int size){ + //std::cout<<"Event size = "<<size<<std::endl; + //std::cout<<std::hex<<"First word = "<<(unsigned)data[0]<<(unsigned)data[1]<<(unsigned)data[2]<<(unsigned)data[3]<<std::dec<<std::endl; + assert(size!=0); + m_nfrag++; + int link=rlink&LINKMASK; + int rceNum = (rlink>>RCEPOS)&RCEMASK; + //std::cout<<"Data from link "<<link<<std::endl; + if (link==ADCREADOUT){ + //std::cout<<"Data from link 8"<<std::endl; + eudaq::DetectorEvent *dev=new eudaq::DetectorEvent(m_runNo,0,0); + counted_ptr<eudaq::Event> ev(dev); + eudaq::RawDataEvent* cpcp=new eudaq::RawDataEvent("TEMP",m_runNo,0); + counted_ptr<eudaq::Event> cpc(cpcp); + cpcp->AddBlock(0); + cpcp->AppendBlock(0,(char*)&rceNum,sizeof(unsigned)); + cpcp->AppendBlock(0,(char*)data,12*sizeof(unsigned)); + dev->AddEvent(cpc); + CosmicEventReceiver::receiveEvent(ev); //this function adds event to monitoring GUI + //std::cout<<"Done Data from link 8"<<std::endl; + return 0; + } + bool marker=(rlink>>MARKERPOS)&0x1; + int rceIndex = m_rceToIndex[rceNum]; + + m_hits=0; + int module = m_linkToIndex[rceNum][link]; //map link/rce onto module index + // if synching throw away fragments until we find the marker + if(m_modsynch[module]==true) { + + if (marker==false){ + if(m_print>0){ + if(link==TDCREADOUT)std::cout<<"Ignoring TDC link: "<<std::endl; + else { + std::cout<<"Ignoring Link "<<link<<std::endl; + } + m_print--; + } + m_tossed[module]++; + return 0; + } + m_modsynch[module]=false; + //if(marker)std::cout<<"Markerevent"<<std::endl; + std::cout<<"Tossed "<<m_tossed[module]<<" fragments for link "<<link<<" , RCE "<<rceNum<<std::endl; + } + if (link==TDCREADOUT){ + //std::cout<<"Data from link TDCREADOUT"<<std::endl; + // unsigned trgtime1=data[3]; + // unsigned trgtime2=data[4]; + // unsigned long long trgtime=trgtime1; + // trgtime=(trgtime<<32) | trgtime2; + + // std::cout<<"Trigger time: "<<std::hex<<trgtime<<std::dec<<std::endl; + //std::cout<<"Link TDCREADOUT L1id "<<((data[0]>>24)&0xf)<<std::endl; + unsigned udata[32]; + if(size!=32)std::cout<<"Bad TDC fragment size "<<size<<std::endl; + for(int i=0;i<32;i+=4) + udata[i/4]=data[i]<<24|data[i+1]<<16|data[i+2]<<8|data[i+3]; + bool success=m_iterator->setTdcData(udata,rceIndex); + int tluid=(udata[7]&0xffff); + //std::cout<<"TLU trigger id:"<<(udata[7]&0xffff)<<std::endl; +// std::cout<<"Trigger word:"<<((udata[7]&0xff0000)>>16)<<std::endl; + //unsigned fifothresh=(udata[7]&0xf000000)>>24; + //if(fifothresh)std::cout<<std::hex<<fifothresh<<std::dec<<std::endl; + m_event++; + //std::cout<<"Hitbus word:"<<hitbusword<<std::endl; + //unsigned backpressure=(udata[7]&0x1000000); + //unsigned fifofull=(udata[7]&0x2000000); + //if(backpressure)std::cout<<"Backpressure"<<std::endl; + //if(fifofull)std::cout<<"Fifo full"<<std::endl; +// unsigned hitbus1=udata[1]; +// unsigned hitbus2=udata[2]; +// if(hitbus1!=0){ +// std::cout<<"Hitbus TA:"<<std::endl; +// printhitbus(hitbus1); +// } +// if(hitbus2!=0){ +// std::cout<<"Hitbus TB:"<<std::endl; +// printhitbus(hitbus2); +// } + unsigned trgtime1=udata[3]; + unsigned trgtime2=udata[4]; + unsigned long long trgtime=trgtime1; + trgtime=(trgtime<<32) | trgtime2; + //std::cout<<"Trigger time stamp: "<<trgtime<<std::endl; + unsigned deadtime1=udata[5]; + unsigned deadtime2=udata[6]; + unsigned long long deadtime=deadtime1; + deadtime=(deadtime<<32) | deadtime2; + //std::cout<<"Deadtime: "<<deadtime<<std::endl; + + if(success==false){ + resynch(); + return 1; + } + }else{ + if(module>=m_nModules){ + std::cout<<"Bad link "<<link<<std::endl; + return 0; + } + unsigned parsed[16384]; + int parsedsize=0; + int nl1a; + if(m_swap[module]==true){ + unsigned swapped[16384]; + for(int i=0;i<size;i+=4){ + swapped[i/4]=data[i]<<24|data[i+1]<<16|data[i+2]<<8|data[i+3]; + } + m_formatter[module]->decode(swapped,size/sizeof(unsigned),parsed, parsedsize, nl1a); + }else{ + m_formatter[module]->decode((unsigned*)&data[0],size/sizeof(unsigned),parsed, parsedsize, nl1a); + } + unsigned int l1id=99; + int ntrg=0; + int bxfirst=-666; + int bxlast=-777; + int start=0; + //std::cout<<"New event"<<std::endl; + do{ //possibly we must split the data because it belongs to 2 triggers. + //if(start!=0)std::cout<<"Newstart "<<start<<" "<<m_iterator->nEvents()+1<<std::endl; + + int newstart=processModuleData(&parsed[start],parsedsize-start,link, module, l1id, bxfirst, bxlast, ntrg); + //if(m_hits>0) std::cout<<"Link "<<link<<" had "<<m_hits<<" hits."<<std::endl; + //std::cout<<"Data from module "<<module<<" link="<<link<<" with l1id="<<l1id<<" bxfirst="<<bxfirst<<" ntrg="<<ntrg<<" bxlast="<<bxlast<<std::endl; + //bool isdut=((link<9) || (m_file==0)); //all data is DUT when running as a producer (m_file==0) + bool isdut=true; //not using CTEL for now. + if(ntrg==0){ + std::cout<<"Inserting duplicate header for data-only frame on module RCE="<<rceNum<<" outlink="<<link<<std::endl; + FormattedRecord fr(FormattedRecord::HEADER); + fr.setL1id(l1id); + fr.setBxid(bxfirst); + unsigned hd=fr.getWord(); + m_iterator->addPixelData(module,l1id, bxfirst, bxlast, ntrg, rceIndex, isdut, &hd,1); + } + bool success=m_iterator->addPixelData(module,l1id, bxfirst, bxlast, ntrg, rceIndex, isdut, &parsed[start],newstart); + if(success==false){ + resynch(); + return 1; + } + start+=newstart; + }while(start<parsedsize); + } + return 0; +} + +int CosmicOfflineDataProc::processModuleData(unsigned* udata,int size, int link, int module, + unsigned& l1id, int& bxfirst, int& bxlast, int &ntrg){ + FormattedRecord* data=(FormattedRecord*)udata; + if(!data[0].isHeader()){ + std::cout<<"Module data not starting with 0x2xxxxxxx. Using old header info."<<std::endl; + ntrg=0; + bxfirst=m_bxfirst[module]; + bxlast=bxfirst; + l1id=m_l1id[module]; + }else{ + ntrg=1; + data[0].setLink(link); + bxfirst=data[0].getBxid()&0xff; + bxlast=bxfirst; + l1id=data[0].getL1id()&0xf; + m_l1id[module]=l1id; + m_bxfirst[module]=bxfirst; + //int bx=data[0].getBxid(); + //std::cout<<"Link "<<link<<" l1a "<<l1id<<" bx "<<bx<<std::endl; + } + //std::cout<<"Link "<<link<<" l1a "<<l1id<<" bxfirst "<<m_bxfirst[module]<<std::endl; + unsigned l1a; + for (int i=1;i<size;i++){ + if (data[i].isHeader()){ + l1a=data[i].getL1id()&0xf; + if(l1id!=l1a)return i; + data[i].setLink(link); + bxlast=data[i].getBxid()&0xff; + //std::cout<<"Link "<<link<<" l1a "<<l1a<<" bx "<<bxlast<<std::endl; + ntrg++; + } + //}else if(data[i]&0x80000000){ + // //m_hits++; + // int chip=(data[i]>>24)&0xf; + // int tot=(data[i]>>16)&0xff; + // int col=(data[i]>>8)&0x1f; + // int row=data[i]&0xff; + // int tr=bx-bxfirst; + // if (tr<0)tr+=256; + //if(row<156 && tot > 6) + // std::cout<<"Link "<<link<<" Trigger "<<tr<<" Chip "<<chip<<" row "<<row<<" col "<<col<<" tot "<<tot<<std::endl; + // } + } + return size; +} + + +void CosmicOfflineDataProc::resynch(){ + std::cout<<"Resynchronizing"<<std::endl; + // set synch flags for everybody + for (int i=0;i<64;i++)m_modsynch[i]=true; + for (int i=0;i<64;i++)m_tossed[i]=0; + m_print=0; + m_iterator->resynch(); + m_controller->resynch();//pause run, reset counters, post markers +} + +CosmicOfflineDataProc::CosmicOfflineDataProc(IPCController* controller, + std::vector<ModuleInfo*> modinfo, + std::vector<int> rcesAll, + unsigned runnum, + const std::string& outputFile, + bool writeEudet, bool writeRaw) + : m_runNo(runnum), m_event(0), m_hitbus(0), m_controller(controller), m_sec(0xffffffff), m_chunk(0) +{ + + m_nModules=modinfo.size(); + m_l1id=new int[m_nModules]; + m_bxfirst=new int[m_nModules]; + m_swap=new int[m_nModules]; + m_rceToIndex=new int[MAX_RCES]; + m_linkToIndex=new int*[MAX_RCES]; + for(int i=0;i<MAX_RCES;i++)m_linkToIndex[i]=0; + for(int i=0;i<m_nModules;i++){ + m_l1id[i]=0; + m_bxfirst[i]=0; + } + + //make a vector only of the *unique* rce numbers + std::vector<int> rces; + for(unsigned imod=0; imod<rcesAll.size(); imod++){ + int rceNum=rcesAll[imod]; + bool newRCE=true; + + for(unsigned jrce=0; jrce<rces.size(); jrce++){ + if(rces[jrce] == rceNum){ + newRCE=false; + break; + } + } + if(newRCE){ + rces.push_back(rceNum); + } + + } + + unsigned nRces=rces.size(); + for(unsigned i=0; i<nRces; i++){ + m_rceToIndex[rces[i]] = i; + m_linkToIndex[rces[i]]=new int[MAX_LINKS]; + m_linkToIndex[rces[i]][TDCREADOUT]=m_nModules+i; + } + for (int i=0;i<m_nModules;i++){ + m_linkToIndex[rcesAll[i]][modinfo[i]->getOutLink()]=i; + } + + for (int i=0;i<m_nModules;i++){ + m_formatter[i]=modinfo[i]->getFormatter(); + if(std::string(m_formatter[i]->getName())=="JJ" || + std::string(m_formatter[i]->getName())=="AFPHPTDC"){ // need to byte-swap + m_swap[i]=true; + }else{ + m_swap[i]=false; + } + } + for(int i=0;i<64;i++){ + m_modsynch[i] = false; + m_tossed[i] = 0; + } + m_nfrag=0; + m_print=0; + bool monitor=false; + m_pfile=0; + m_file=0; + if(outputFile!=""){ + monitor=true; + if(writeEudet==true){ + m_file=new eudaq::FileSerializer(outputFile.c_str()); + eudaq::DetectorEvent dev(m_runNo,0,0); + dev.SetFlags(eudaq::Event::FLAG_BORE); + dev.SetTag("CONFIG", "Name = Test"); + eudaq::RawDataEvent *revc=new eudaq::RawDataEvent(eudaq::RawDataEvent::BORE("CTEL",m_runNo)); + counted_ptr<eudaq::Event> cpc(revc); + dev.AddEvent(cpc); + eudaq::RawDataEvent *revd=new eudaq::RawDataEvent(eudaq::RawDataEvent::BORE("APIX-CT",m_runNo)); + counted_ptr<eudaq::Event> cpd(revd); + dev.AddEvent(cpd); + dev.Serialize(*m_file); + } + if(writeRaw==true){ + std::cout<<"Run number "<<m_runNo<<std::endl; + std::string pfname=outputFile.substr(0,outputFile.size()-4)+"_000000.dat"; + m_filename=outputFile.substr(0,outputFile.size()-4); + m_pfile=new std::ofstream(pfname.c_str(), std::ios::binary); + unsigned utime=(unsigned)time(0); + m_pfile->write((char*)&utime, 4); + m_pfile->write((char*)&nRces, 4); + } + } + // create the event iterator class which does all the work + m_iterator=new CosmicEventIterator(monitor, m_file, m_pfile, m_runNo,m_nModules,rces); + + +} + +CosmicOfflineDataProc::~CosmicOfflineDataProc(){ + m_iterator->flushEvents(); + std::cout<<"Number of fragments processed: "<<m_nfrag<<std::endl; + //if(m_event>0)std::cout<<"Hitbus efficiency in the previous run: "<<(float)m_hitbus/(float)m_event<<std::endl; + if(m_pfile!=0){ + m_pfile->close(); + delete m_pfile; + } + if(m_file!=0){ + int eventnumber=m_iterator->nEvents()+1; + eudaq::DetectorEvent dev(m_runNo,eventnumber,0); + dev.SetFlags(eudaq::Event::FLAG_EORE); + eudaq::RawDataEvent *revc=new eudaq::RawDataEvent(eudaq::RawDataEvent::EORE("CTEL",m_runNo,eventnumber)); + counted_ptr<eudaq::Event> cpc(revc); + dev.AddEvent(cpc); + eudaq::RawDataEvent *revd=new eudaq::RawDataEvent(eudaq::RawDataEvent::EORE("APIX-CT",m_runNo,eventnumber)); + counted_ptr<eudaq::Event> cpd(revd); + dev.AddEvent(cpd); + dev.Serialize(*m_file); + delete m_file; + } + std::cout<<"close file called"<<std::endl; + delete m_iterator; + delete [] m_l1id; + delete [] m_bxfirst; + delete [] m_swap; + delete [] m_rceToIndex; + for(int i=0;i<MAX_RCES;i++)delete [] m_linkToIndex[i]; + delete [] m_linkToIndex; +} + +inline void CosmicOfflineDataProc::switchfile(){ + m_chunk++; + m_pfile->close(); + char chunknum[16]; + sprintf(chunknum, "_%06d.dat", m_chunk); + m_pfile->open((m_filename+chunknum).c_str(),std::ios::binary); + unsigned utime=(unsigned)time(0); + m_pfile->write((char*)&utime, 4); +} diff --git a/rce/rcecalib/server/CosmicOfflineDataProc.hh b/rce/rcecalib/server/CosmicOfflineDataProc.hh new file mode 100644 index 00000000..54d70e13 --- /dev/null +++ b/rce/rcecalib/server/CosmicOfflineDataProc.hh @@ -0,0 +1,57 @@ +#ifndef COSMICOFFLINEDATAPROC_HH +#define COSMICOFFLINEDATAPROC_HH + +#include <boost/property_tree/ptree_fwd.hpp> +#include "rcecalib/eudaq/FileSerializer.hh" +#include <list> +#include <string> +#include <vector> +#include <fstream> +#include <map> + +class CosmicEvent; +class CosmicEventIterator; +class AbsFormatter; +class IPCController; +class ModuleInfo; + +class CosmicOfflineDataProc{ +public: + CosmicOfflineDataProc(IPCController* controller, + std::vector<ModuleInfo*> modinfo, + std::vector<int> rceAll, + unsigned runnum, const std::string& outputFile, bool writeEudet, bool writeRaw); + virtual ~CosmicOfflineDataProc(); + int processData(unsigned short link, unsigned char* data, int size); +protected: + void resynch(); + inline int processModuleData(unsigned* data,int size, int link, int module, unsigned& l1id, int& bxfirst, int &bxlast, int &ntrg); + void switchfile(); + enum constants{MAX_RCES=100, MAX_LINKS=32}; + + int m_nModules; + bool m_modsynch[64]; + int* m_l1id; + int* m_bxfirst; + int* m_swap; + int **m_linkToIndex; + int *m_rceToIndex; + int m_tossed[64]; + unsigned m_runNo; + eudaq::FileSerializer *m_file; + std::ofstream* m_pfile; + //std::ofstream m_file; + int m_nfrag; + CosmicEventIterator* m_iterator; + int m_print; + int m_hits; + int m_event; + int m_hitbus; + AbsFormatter* m_formatter[64]; + IPCController* m_controller; + unsigned m_sec; + unsigned m_chunk; + std::string m_filename; +}; + +#endif diff --git a/rce/rcecalib/server/DataExporter.cc b/rce/rcecalib/server/DataExporter.cc new file mode 100644 index 00000000..cee067ef --- /dev/null +++ b/rce/rcecalib/server/DataExporter.cc @@ -0,0 +1,117 @@ +#include "rcecalib/server/DataExporter.hh" +#include "rcecalib/server/ConfigGui.hh" +#include "stdlib.h" +#include "TFile.h" +#include "TKey.h" +#include "TROOT.h" +#include "TClass.h" +#include <iostream> +#include <sys/stat.h> +#include <boost/regex.hpp> + +const std::string DataExporter::basedir=getExportBaseDir(); + +const std::string DataExporter::getExportBaseDir(){ + char * var = getenv( "EXPORT_DIR" ); + if(var) return var; + char *home=getenv("HOME"); + return std::string(home)+"/export"; +} + +void DataExporter::exportData(std::string &runname, std::string &topconfigname, std::string &rcdir, TFile* file, TFile* anfile){ + struct stat stFileInfo; + int intStat; + intStat = stat(basedir.c_str(),&stFileInfo); + if(intStat != 0) { //File does not exist + std::cout<<"Export directory "<<basedir<<" does not exist. Not exporting data."<<std::endl; + return; + } + std::map<std::string, std::map<int, int> > ids; + for (int i=0;i<ConfigGui::MAX_MODULES;i++){ + if(!m_cfg[i]->isIncluded())continue; + std::string modname="M"; + modname+=m_cfg[i]->getModuleId(); + std::string moddir=basedir+"/"+modname; + intStat = stat(moddir.c_str(),&stFileInfo); + if(intStat != 0) mkdir (moddir.c_str(),0777); + std::string configdir=moddir+"/configs"; + intStat = stat(configdir.c_str(),&stFileInfo); + if(intStat != 0) mkdir (configdir.c_str(),0777); + std::string datadir=moddir+"/data"; + intStat = stat(datadir.c_str(),&stFileInfo); + if(intStat != 0) mkdir (datadir.c_str(),0777); + // Copy config + char cmd[512]; + sprintf(cmd,"cp %s/globalconfig.txt %s/globalconfig_%s.txt", rcdir.c_str(), configdir.c_str(), runname.c_str()); + system (cmd); + sprintf(cmd,"cp %s/%s %s/%s", rcdir.c_str(), topconfigname.c_str(), configdir.c_str(), topconfigname.c_str()); + system (cmd); + sprintf(cmd,"cp %s/scanconfig_%s.txt %s/scanconfig_%s.txt", rcdir.c_str(), runname.c_str(), configdir.c_str(), runname.c_str()); + system (cmd); + m_cfg[i]->copyConfig(configdir.c_str()); + int feid=m_cfg[i]->getId(); + ids[modname][feid]=1; + } + for (std::map <std::string, std::map<int, int> >::const_iterator it = ids.begin(); it != ids.end(); ++it){ + std::string modname=it->first; + std::string datadir=basedir+"/"+modname+"/data/"; + std::string hfilename=modname+"_"+runname+".root"; + TFile hfile((datadir+"/"+hfilename).c_str(), "recreate", file->GetTitle()); + CopyFile(file->GetName(), it->second, "histos"); + if(anfile!=0)CopyFile(anfile->GetName(), it->second, "analysis"); + } +} + +void DataExporter::CopyDir(TDirectory *source, const std::map<int, int> &ids, const char* dirname) { + //copy all objects and subdirs of directory source as a subdir of the current directory + TDirectory *savdir = gDirectory; + TDirectory *adir = savdir->mkdir(dirname); + adir->cd(); + //loop on all entries of this directory + TKey *key; + TIter nextkey(source->GetListOfKeys()); + while ((key = (TKey*)nextkey())) { + const char *classname = key->GetClassName(); + TClass *cl = gROOT->GetClass(classname); + if (!cl) continue; + if (cl->InheritsFrom(TDirectory::Class())) { + source->cd(key->GetName()); + TDirectory *subdir = gDirectory; + adir->cd(); + CopyDir(subdir, ids, subdir->GetName()); + adir->cd(); + } else { + source->cd(); + boost::regex re("Mod_(\\d+)"); + std::string name(key->GetName()); + boost::cmatch matches; + if(boost::regex_search(name.c_str(), matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + int id=strtol(match.c_str(),0,10); + if( ids.find(id)!=ids.end()){ + TObject *obj = key->ReadObj(); + adir->cd(); + obj->Write(); + delete obj; + } + } + } + } + adir->SaveSelf(kTRUE); + savdir->cd(); +} +void DataExporter::CopyFile(const char *fname, const std::map<int, int> &ids, const char* topdir) { + //Copy all objects and subdirs of file fname as a subdir of the current directory + TDirectory *target = gDirectory; + TFile *f = TFile::Open(fname); + if (!f || f->IsZombie()) { + printf("Cannot copy file: %s\n",fname); + target->cd(); + return; + } + target->cd(); + CopyDir(f, ids, topdir); + delete f; + target->cd(); +} diff --git a/rce/rcecalib/server/DataExporter.hh b/rce/rcecalib/server/DataExporter.hh new file mode 100644 index 00000000..00514577 --- /dev/null +++ b/rce/rcecalib/server/DataExporter.hh @@ -0,0 +1,23 @@ +#ifndef DATAEXPORTER_HH +#define DATAEXPORTER_HH + +class TFile; +class ConfigGui; +class TDirectory; +#include <string> +#include <map> + +class DataExporter{ +public: + DataExporter(ConfigGui** cfg): m_cfg(cfg){} + ~DataExporter(){} + void exportData(std::string &runname, std::string &topconfigname, std::string &rcdir, TFile* file, TFile* anfile); +private: + void CopyDir(TDirectory *source, const std::map<int, int> &ids, const char* topdir); + void CopyFile(const char *fname, const std::map<int, int> &ids, const char* dirname); + static const std::string getExportBaseDir(); + ConfigGui** m_cfg; + static const std::string basedir; +}; + +#endif diff --git a/rce/rcecalib/server/EthPrimitive.cc b/rce/rcecalib/server/EthPrimitive.cc new file mode 100644 index 00000000..74a7f16c --- /dev/null +++ b/rce/rcecalib/server/EthPrimitive.cc @@ -0,0 +1,65 @@ +#include "rcecalib/server/EthPrimitive.hh" +#include <unistd.h> +#include <stdio.h> +#include <assert.h> +#include <sys/uio.h> +#include <iostream> +#include <string.h> +#include <new> + + +EthPrimitive::EthPrimitive(unsigned short port){ + RceNet::IpAddress src(port); +#ifdef RCE_V2 + m_socket.bind(src); + m_socket.listen(); +#else + m_socket.listen(src); +#endif + RceNet::IpAddress name; + m_socket.getname(name); + printf("TCP upload socket %d bound to port %d\n", m_socket.socket(), name.port()); +} + + +const char* EthPrimitive::receiveCommand() { + const unsigned buflen=1024; + static char buffer[buflen]; + int connfd = m_socket.accept(); + m_connection=new RceNet::Socket(connfd); + int bytes = m_connection->recv(buffer, buflen); + assert(bytes<(int)buflen); + buffer[bytes]=0; + while(buffer[bytes-1]==' ' && bytes>0)buffer[--bytes]=0; + std::cout<<"COMMAND: "<<buffer<<std::endl; + return buffer; +} +void EthPrimitive::reply(const char* msg){ + assert(m_connection!=0); + m_connection->send((void*)msg, strlen(msg) ); + delete m_connection; + m_connection=0; +} +void EthPrimitive::reply(char* buffer, int len){ + assert(m_connection!=0); + m_connection->send((void*)buffer, len ); + delete m_connection; + m_connection=0; +} + +const char* EthPrimitive::receiveModule(unsigned char *buffer, int size) { + assert(m_connection==0); + int connfd = m_socket.accept(); + m_connection=new RceNet::Socket(connfd); + int remaining = size; + int offset = 0; + while( remaining > 0 ) { + int bytes = m_connection->recv(buffer + offset, remaining); + if(bytes<0)break; + offset += bytes; + remaining -= bytes; + } + if(remaining!=0)return "Download failed."; + return "OK"; +} + diff --git a/rce/rcecalib/server/EthPrimitive.hh b/rce/rcecalib/server/EthPrimitive.hh new file mode 100644 index 00000000..1bd6617b --- /dev/null +++ b/rce/rcecalib/server/EthPrimitive.hh @@ -0,0 +1,33 @@ +#ifndef ETH_PRIMITIVE_H +#define ETH_PRIMITIVE_H + +#define PACKETSIZE 300 +#include <sys/types.h> +#include "sys/socket.h" +#include <netinet/in.h> +#ifdef RCE_V2 +#include "datCode.hh" +#include DAT_PUBLIC( oldPpi, net, SocketTcp.hh) +#include DAT_PUBLIC( oldPpi, net, IpAddress.hh) +#include DAT_PUBLIC( oldPpi, net, IpAddress.hh) +#else +#include "rce/net/SocketTcp.hh" +#include "rce/net/IpAddress.hh" +#include "rce/service/Procedure.hh" +#endif +#include "namespace_aliases.hh" +class CmdDecoder; + +class EthPrimitive { + public: + EthPrimitive(unsigned short port); + const char* receiveCommand(); + const char* receiveModule(unsigned char* buffer, int size); + void reply(const char* msg); + void reply(char* buffer, int len); + private: + RceNet::Socket *m_connection; + RceNet::SocketTcp m_socket; +}; + +#endif diff --git a/rce/rcecalib/server/FEI4AConfigFile.cc b/rce/rcecalib/server/FEI4AConfigFile.cc new file mode 100644 index 00000000..ff418460 --- /dev/null +++ b/rce/rcecalib/server/FEI4AConfigFile.cc @@ -0,0 +1,737 @@ +#include "rcecalib/server/FEI4AConfigFile.hh" +#include "rcecalib/util/exceptions.hh" +#include <boost/algorithm/string.hpp> +#include <iostream> +#include <fstream> +#include <vector> +#include <sys/stat.h> + +std::string FEI4AConfigFile::getFullPath(std::string relPath){ + std::string newPath = relPath, basePath=m_moduleCfgFilePath, testName; + unsigned int pos; + // skip config file-name part of base path + pos = basePath.find_last_of('/'); + if(pos!=std::string::npos) basePath.erase(pos,basePath.length()-pos); + // skip "config" part of base path + pos = basePath.find_last_of('/'); + if(pos!=std::string::npos) basePath.erase(pos,basePath.length()-pos); + // now skip module part of base path, but keep last "/" + pos = basePath.find_last_of('/'); + if(pos!=std::string::npos) basePath.erase(pos+1,basePath.length()-pos); + else basePath=""; + // then add relative path of DAC or mask file + newPath = basePath + newPath; + return newPath; +} + +FEI4AConfigFile::~FEI4AConfigFile(){} + +unsigned short FEI4AConfigFile::lookupToUShort(std::string par){ + if( m_params.find(par)==m_params.end()){ + std::cout<<"Parameter "<<par<<" does not exist."<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + std::string vals=m_params[par]; + unsigned short val; + int success=convertToUShort(vals, val); + if(success==false){ + std::cout<<"Bad value "<<vals<< " for parameter "<<par<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + return val; +} +float FEI4AConfigFile::lookupToFloat(std::string par){ + if( m_params.find(par)==m_params.end()){ + std::cout<<"Parameter "<<par<<" does not exist."<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + std::string vals=m_params[par]; + float val; + char* end; + val=strtof(vals.c_str(), &end); + if(end-vals.c_str()!=(int)vals.size()){ + std::cout<<"Bad value "<<vals<< " for parameter "<<par<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + return val; +} + +int FEI4AConfigFile::convertToUShort(std::string par, unsigned short& val){ + char* end; + val=strtoul(par.c_str(), &end, 0); + if(end-par.c_str()!=(int)par.size()){ + return 0; + } + if((val&0xffff0000)!=0){ + std::cout<<"Value "<<val<<" too large."<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + return 1; +} + + +void FEI4AConfigFile::setupMaskBit(const long int bit, ipc::PixelFEI4AConfig* cfg, std::string par){ + if( m_params.find(par)==m_params.end()){ + std::cout<<"Parameter "<<par<<" does not exist."<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + unsigned short val; + int success=convertToUShort(m_params[par], val); + //file + if(success==false){ + std::string fullpath=getFullPath(m_params[par]); + std::ifstream* maskfile=new std::ifstream(fullpath.c_str()); + if(!maskfile->good()){ + std::cout<<"Cannot open file with name "<<fullpath<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + std::string inpline; + unsigned short row=0; + while(true){ + getline(*maskfile, inpline); + if(maskfile->eof())break; + boost::trim(inpline); + if(inpline.size()!=0 && inpline[0]!='#'){ //remove comment lines and empty lines + std::vector<std::string> splitVec; + split( splitVec, inpline, boost::is_any_of(" -"), boost::token_compress_on ); + if(splitVec.size()!=17){ + std::cout<<"Bad input line "<<inpline<<std::endl; + continue; + } + int success=convertToUShort(splitVec[0], val); + if(success!=true || val!=++row){//check and increment row number + throw rcecalib::Config_File_Error(ERS_HERE); + } + std::string oneline; + for(int i=1;i<17;i++)oneline+=splitVec[i]; //concatenate everyting. + if(oneline.size()!=(unsigned)ipc::IPC_N_I4_PIXEL_COLUMNS) throw rcecalib::Config_File_Error(ERS_HERE); + for(int i=0;i<ipc::IPC_N_I4_PIXEL_COLUMNS;i++){ + if(oneline[i]=='1')cfg->FEMasks[i][row-1]|=1<<bit; + } + } + } + if(row!=ipc::IPC_N_I4_PIXEL_ROWS) throw rcecalib::Config_File_Error(ERS_HERE); + delete maskfile; + }else{ + // left are the cases all 0 and all 1 + if(val!=0 && val!=1) throw rcecalib::Config_File_Error(ERS_HERE); + for (int i=0;i<ipc::IPC_N_I4_PIXEL_COLUMNS;i++){ + for(int j=0;j<ipc::IPC_N_I4_PIXEL_ROWS;j++){ + cfg->FEMasks[i][j]|=val<<bit; + } + } + } +} + + +void FEI4AConfigFile::setupDAC(unsigned char trim[][ipc::IPC_N_I4_PIXEL_ROWS] , std::string par){ + if( m_params.find(par)==m_params.end()){ + std::cout<<"Parameter "<<par<<" does not exist."<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + unsigned short val; + int success=convertToUShort(m_params[par], val); + //file + if(success==false){ + std::string fullpath=getFullPath(m_params[par]); + std::ifstream* dacfile=new std::ifstream(fullpath.c_str()); + if(!dacfile->good()){ + std::cout<<"Cannot open file with name "<<fullpath<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + std::string inpline; + unsigned short hrow=1; + while(true){ + getline(*dacfile, inpline); + if(dacfile->eof())break; + boost::trim(inpline); + if(inpline.size()!=0 && inpline[0]!='#'){ //remove comment lines and empty lines + std::vector<std::string> splitVec; + split( splitVec, inpline, boost::is_any_of(" "), boost::token_compress_on ); + if(splitVec.size()!=41){ + std::cout<<"Bad input line "<<inpline<<std::endl; + continue; + } + success=convertToUShort(splitVec[0].substr(0,splitVec[0].size()-1),val); + if(success!=true || val!=++hrow/2){//check and increment row number + throw rcecalib::Config_File_Error(ERS_HERE); + } + for(int i=0;i<ipc::IPC_N_I4_PIXEL_COLUMNS/2;i++){ + success=convertToUShort(splitVec[i+1], val); + if(!success) throw rcecalib::Config_File_Error(ERS_HERE); + trim[i+(hrow%2)*ipc::IPC_N_I4_PIXEL_COLUMNS/2][hrow/2-1]=val; + } + } + } + if(hrow/2!=ipc::IPC_N_I4_PIXEL_ROWS) throw rcecalib::Config_File_Error(ERS_HERE); + delete dacfile; + }else{ + // left are the cases where all settings are identical. + for (int i=0;i<ipc::IPC_N_I4_PIXEL_COLUMNS;i++){ + for(int j=0;j<ipc::IPC_N_I4_PIXEL_ROWS;j++){ + trim[i][j]=val; + } + } + } +} + +void FEI4AConfigFile::writeModuleConfig(ipc::PixelFEI4AConfig* config, const std::string &base, const std::string &confdir, + const std::string &configname, const std::string &key){ + struct stat stFileInfo; + int intStat; + // Attempt to get the file attributes + intStat = stat(base.c_str(),&stFileInfo); + if(intStat != 0) { //File does not exist + std::cout<<"Directory "<<base<<" does not exist. Not writing config file"<<std::endl; + return; + } + intStat = stat((base+"/"+confdir).c_str(),&stFileInfo); + if(intStat != 0) { //File does not exist + //std::cout<<"Directory "<<base<<"/"<<confdir<<" does not exist. Creating."<<std::endl; + mkdir ((base+"/"+confdir).c_str(),0777); + mkdir ((base+"/"+confdir+"/configs").c_str(),0777); + mkdir ((base+"/"+confdir+"/masks").c_str(),0777); + mkdir ((base+"/"+confdir+"/tdacs").c_str(),0777); + mkdir ((base+"/"+confdir+"/fdacs").c_str(),0777); + } + std::string cfgname=configname; + if(key.size()!=0)cfgname+="__"+key; + std::string fullpath=base+"/"+confdir+"/configs/"+cfgname+".cfg"; + std::ofstream cfgfile(fullpath.c_str()); + cfgfile<<"# FEI4A Configuration"<<std::endl; + cfgfile<<std::endl; + cfgfile<<"# Module name"<<std::endl; + cfgfile<<std::endl; + cfgfile<<"ModuleID\t\t"<<config->idStr<<std::endl; + cfgfile<<std::endl; + cfgfile<<"# Geographical address"<<std::endl; + cfgfile<<std::endl; + cfgfile<<"Address\t\t\t"<<(unsigned)config->FECommand.address<<std::endl; + cfgfile<<std::endl; + cfgfile<<"# Global register"<<std::endl; + cfgfile<<std::endl; + //Global register + ipc::PixelFEI4AGlobal* cfg=&config->FEGlobal; + cfgfile<<"TrigCnt\t\t\t"<<cfg->TrigCnt<<std::endl; + cfgfile<<"Conf_AddrEnable\t\t"<<cfg->Conf_AddrEnable <<std::endl; + cfgfile<<"Reg2Spare\t\t"<<cfg->Reg2Spare <<std::endl; + cfgfile<<"ErrMask0\t\t"<<"0x"<<std::hex<<cfg->ErrMask0 <<std::dec<<std::endl; + cfgfile<<"ErrMask1\t\t"<<"0x"<<std::hex<<cfg->ErrMask1 <<std::dec<<std::endl; + cfgfile<<"PrmpVbpRight\t\t"<< cfg->PrmpVbpRight <<std::endl; + cfgfile<<"Vthin\t\t\t"<<cfg->Vthin <<std::endl; + cfgfile<<"DisVbn_CPPM\t\t"<<cfg->DisVbn_CPPM <<std::endl; + cfgfile<<"PrmpVbp\t\t\t"<<cfg->PrmpVbp <<std::endl; + cfgfile<<"TdacVbp\t\t\t"<< cfg->TdacVbp <<std::endl; + cfgfile<<"DisVbn\t\t\t"<<cfg->DisVbn <<std::endl; + cfgfile<<"Amp2Vbn\t\t\t"<<cfg->Amp2Vbn <<std::endl; + cfgfile<<"Amp2VbpFol\t\t"<<cfg->Amp2VbpFol <<std::endl; + cfgfile<<"PrmpVbpTop\t\t"<<cfg->PrmpVbpTop <<std::endl; + cfgfile<<"Amp2Vbp\t\t\t"<<cfg->Amp2Vbp <<std::endl; + cfgfile<<"FdacVbn\t\t\t"<<cfg->FdacVbn <<std::endl; + cfgfile<<"Amp2Vbpf\t\t"<<cfg->Amp2Vbpf <<std::endl; + cfgfile<<"PrmpVbnFol\t\t"<<cfg->PrmpVbnFol <<std::endl; + cfgfile<<"PrmpVbpLeft\t\t"<<cfg->PrmpVbpLeft <<std::endl; + cfgfile<<"PrmpVbpf\t\t"<<cfg->PrmpVbpf <<std::endl; + cfgfile<<"PrmpVbnLcc\t\t"<<cfg->PrmpVbnLcc <<std::endl; + cfgfile<<"Reg13Spare\t\t"<<cfg->Reg13Spare <<std::endl; + cfgfile<<"PxStrobes\t\t"<<cfg->PxStrobes <<std::endl; + cfgfile<<"S0\t\t\t"<<cfg->S0 <<std::endl; + cfgfile<<"S1\t\t\t"<<cfg->S1 <<std::endl; + cfgfile<<"LVDSDrvIref\t\t"<<cfg->LVDSDrvIref <<std::endl; + cfgfile<<"BonnDac\t\t\t"<<cfg->BonnDac <<std::endl; + cfgfile<<"PllIbias\t\t"<<cfg->PllIbias <<std::endl; + cfgfile<<"LVDSDrvVos\t\t"<<cfg->LVDSDrvVos <<std::endl; + cfgfile<<"TempSensBias\t\t"<<cfg->TempSensBias <<std::endl; + cfgfile<<"PllIcp\t\t\t"<<cfg->PllIcp <<std::endl; + cfgfile<<"Reg17Spare\t\t"<<cfg->Reg17Spare <<std::endl; + cfgfile<<"PlsrIdacRamp\t\t"<<cfg->PlsrIdacRamp <<std::endl; + cfgfile<<"Reg18Spare\t\t"<<cfg->Reg18Spare <<std::endl; + cfgfile<<"PlsrVgOPamp\t\t"<<cfg->PlsrVgOPamp <<std::endl; + cfgfile<<"PlsrDacBias\t\t"<<cfg->PlsrDacBias <<std::endl; + cfgfile<<"Reg19Spare\t\t"<<cfg->Reg19Spare <<std::endl; + cfgfile<<"Vthin_AltCoarse\t\t"<<cfg->Vthin_AltCoarse <<std::endl; + cfgfile<<"Vthin_AltFine\t\t"<<cfg->Vthin_AltFine <<std::endl; + cfgfile<<"PlsrDAC\t\t\t"<<cfg->PlsrDAC <<std::endl; + cfgfile<<"DIGHITIN_Sel\t\t"<<cfg->DIGHITIN_Sel <<std::endl; + cfgfile<<"DINJ_Override\t\t"<<cfg->DINJ_Override <<std::endl; + cfgfile<<"HITLD_In\t\t"<<cfg->HITLD_In <<std::endl; + cfgfile<<"Reg21Spare\t\t"<<cfg->Reg21Spare <<std::endl; + cfgfile<<"Reg22Spare2\t\t"<<cfg->Reg22Spare2 <<std::endl; + cfgfile<<"Colpr_Addr\t\t"<<cfg->Colpr_Addr <<std::endl; + cfgfile<<"Colpr_Mode\t\t"<<cfg->Colpr_Mode <<std::endl; + cfgfile<<"Reg22Spare1\t\t"<<cfg->Reg22Spare1 <<std::endl; + cfgfile<<"DisableColumnCnfg0\t"<<"0x"<<std::hex<<cfg->DisableColumnCnfg0 <<std::dec<<std::endl; + cfgfile<<"DisableColumnCnfg1\t"<<"0x"<<std::hex<<cfg->DisableColumnCnfg1 <<std::dec<<std::endl; + cfgfile<<"DisableColumnCnfg2\t"<<"0x"<<std::hex<<cfg->DisableColumnCnfg2 <<std::dec<<std::endl; + cfgfile<<"TrigLat\t\t\t"<< cfg->TrigLat <<std::endl; + cfgfile<<"CMDcnt\t\t\t"<<cfg->CMDcnt <<std::endl; + cfgfile<<"StopModeCnfg\t\t"<<cfg->StopModeCnfg <<std::endl; + cfgfile<<"HitDiscCnfg\t\t"<<cfg->HitDiscCnfg <<std::endl; + cfgfile<<"EN_PLL\t\t\t"<<cfg->EN_PLL <<std::endl; + cfgfile<<"Efuse_sense\t\t"<<cfg->Efuse_sense <<std::endl; + cfgfile<<"Stop_Clk\t\t"<<cfg->Stop_Clk <<std::endl; + cfgfile<<"ReadErrorReq\t\t"<<cfg->ReadErrorReq <<std::endl; + cfgfile<<"ReadSkipped\t\t"<<cfg->ReadSkipped <<std::endl; + cfgfile<<"Reg27Spare\t\t"<<cfg->Reg27Spare <<std::endl; + cfgfile<<"GateHitOr\t\t"<<cfg->GateHitOr <<std::endl; + cfgfile<<"CalEn\t\t\t"<<cfg->CalEn <<std::endl; + cfgfile<<"SR_clr\t\t\t"<<cfg->SR_clr <<std::endl; + cfgfile<<"Latch_en\t\t"<<cfg->Latch_en <<std::endl; + cfgfile<<"SR_Clock\t\t"<<cfg->SR_Clock <<std::endl; + cfgfile<<"LVDSDrvSet06\t\t"<<cfg->LVDSDrvSet06 <<std::endl; + cfgfile<<"Reg28Spare\t\t"<<cfg->Reg28Spare <<std::endl; + cfgfile<<"EN40M\t\t\t"<<cfg->EN40M <<std::endl; + cfgfile<<"EN80M\t\t\t"<<cfg->EN80M <<std::endl; + cfgfile<<"CLK0_S2\t\t\t"<<(cfg->CLK0 &0x1)<<std::endl; + cfgfile<<"CLK0_S1\t\t\t"<<((cfg->CLK0>>1)&0x1 )<<std::endl; + cfgfile<<"CLK0_S0\t\t\t"<<((cfg->CLK0>>2)&0x1 )<<std::endl; + cfgfile<<"CLK1_S2\t\t\t"<<(cfg->CLK1&0x1 )<<std::endl; + cfgfile<<"CLK1_S1\t\t\t"<<((cfg->CLK1>>1)&0x1 )<<std::endl; + cfgfile<<"CLK1_S0\t\t\t"<<((cfg->CLK1>>2)&0x1 )<<std::endl; + cfgfile<<"EN160M\t\t\t"<<cfg->EN160M <<std::endl; + cfgfile<<"EN320M\t\t\t"<<cfg->EN320M <<std::endl; + cfgfile<<"Reg29Spare1\t\t"<<cfg->Reg29Spare1 <<std::endl; + cfgfile<<"no8b10b\t\t\t"<<cfg->no8b10b <<std::endl; + cfgfile<<"Clk2OutCnfg\t\t"<<cfg->Clk2OutCnfg <<std::endl; + cfgfile<<"EmptyRecord\t\t"<<cfg->EmptyRecord <<std::endl; + cfgfile<<"Reg29Spare2\t\t"<<cfg->Reg29Spare2 <<std::endl; + cfgfile<<"LVDSDrvEn\t\t"<<cfg->LVDSDrvEn <<std::endl; + cfgfile<<"LVDSDrvSet30\t\t"<<cfg->LVDSDrvSet30 <<std::endl; + cfgfile<<"LVDSDrvSet12\t\t"<<cfg->LVDSDrvSet12 <<std::endl; + cfgfile<<"PlsrRiseUpTau\t\t"<<cfg->PlsrRiseUpTau <<std::endl; + cfgfile<<"PlsrPwr\t\t\t"<<cfg->PlsrPwr <<std::endl; + cfgfile<<"PlsrDelay\t\t"<<cfg->PlsrDelay <<std::endl; + cfgfile<<"ExtDigCalSW\t\t"<<cfg->ExtDigCalSW <<std::endl; + cfgfile<<"ExtAnaCalSW\t\t"<<cfg->ExtAnaCalSW <<std::endl; + cfgfile<<"Reg31Spare\t\t"<<cfg->Reg31Spare <<std::endl; + cfgfile<<"SELB0\t\t\t"<<cfg->SELB0 <<std::endl; + cfgfile<<"SELB1\t\t\t"<<cfg->SELB1 <<std::endl; + cfgfile<<"SELB2\t\t\t"<<cfg->SELB2 <<std::endl; + cfgfile<<"EfuseCref\t\t"<<cfg->EfuseCref <<std::endl; + cfgfile<<"EfuseVref\t\t"<<cfg->EfuseVref <<std::endl; + cfgfile<<"Chip_SN\t\t\t"<<cfg->Chip_SN <<std::endl; + cfgfile<<std::endl; + cfgfile<<"# Pixel register"<<std::endl; + cfgfile<<std::endl; + cfgfile<<"enable\t\t\t"<<confdir<<"/masks/enable_"<<cfgname<<".dat"<<std::endl; + cfgfile<<"largeCap\t\t"<<confdir<<"/masks/largeCap_"<<cfgname<<".dat"<<std::endl; + cfgfile<<"smallCap\t\t"<<confdir<<"/masks/smallCap_"<<cfgname<<".dat"<<std::endl; + cfgfile<<"hitbus\t\t\t"<<confdir<<"/masks/hitbus_"<<cfgname<<".dat"<<std::endl; + cfgfile<<std::endl; + cfgfile<<"tdac\t\t\t"<<confdir<<"/tdacs/tdac_"<<cfgname<<".dat"<<std::endl; + cfgfile<<"fdac\t\t\t"<<confdir<<"/fdacs/fdac_"<<cfgname<<".dat"<<std::endl; + cfgfile<<std::endl; + cfgfile<<std::endl; + cfgfile<<"# Charge injection parameters"<<std::endl; + cfgfile<<std::endl; + cfgfile<<"cinjLo\t\t\t"<<config->FECalib.cinjLo <<std::endl; + cfgfile<<"cinjHi\t\t\t"<<config->FECalib.cinjHi <<std::endl; + cfgfile<<"vcalCoeff[0]\t\t"<<config->FECalib.vcalCoeff[0] <<std::endl; + cfgfile<<"vcalCoeff[1]\t\t"<<config->FECalib.vcalCoeff[1] <<std::endl; + cfgfile<<"vcalCoeff[2]\t\t"<<config->FECalib.vcalCoeff[2] <<std::endl; + cfgfile<<"vcalCoeff[3]\t\t"<<config->FECalib.vcalCoeff[3] <<std::endl; + cfgfile<<"chargeCoeffClo\t\t"<<config->FECalib.chargeCoeffClo<<std::endl; + cfgfile<<"chargeCoeffChi\t\t"<<config->FECalib.chargeCoeffChi<<std::endl; + cfgfile<<"chargeOffsetClo\t\t"<<config->FECalib.chargeOffsetClo<<std::endl; + cfgfile<<"chargeOffsetChi\t\t"<<config->FECalib.chargeOffsetChi<<std::endl; + cfgfile<<"monleakCoeff\t\t"<<config->FECalib.monleakCoeff<<std::endl; + writeMaskFile(ipc::enable, config, base+"/"+confdir+"/masks/enable_"+cfgname+".dat"); + writeMaskFile(ipc::largeCap, config, base+"/"+confdir+"/masks/largeCap_"+cfgname+".dat"); + writeMaskFile(ipc::smallCap, config, base+"/"+confdir+"/masks/smallCap_"+cfgname+".dat"); + writeMaskFile(ipc::hitbus, config, base+"/"+confdir+"/masks/hitbus_"+cfgname+".dat"); + + writeDacFile(config->FETrims.dacThresholdTrim, base+"/"+confdir+"/tdacs/tdac_"+cfgname+".dat"); + writeDacFile(config->FETrims.dacFeedbackTrim, base+"/"+confdir+"/fdacs/fdac_"+cfgname+".dat"); + + + +} +void FEI4AConfigFile::writeMaskFile(const long int bit, ipc::PixelFEI4AConfig* config, const std::string &filename){ + std::ofstream maskfile(filename.c_str()); + maskfile<<"### 1 6 11 16 21 26 31 36 41 46 51 56 61 66 71 76"<<std::endl; + char linenr[128]; + for(int i=1;i<=336;i++){ + sprintf(linenr,"%3d ", i); + maskfile<<linenr; + for (int j=1;j<=80;j++){ + maskfile<<((config->FEMasks[j-1][i-1]>>bit)&0x1); + if(j%10==0)maskfile<<" "; + else if(j%5==0)maskfile<<"-"; + } + maskfile<<std::endl; + } +} + +void FEI4AConfigFile::writeDacFile(unsigned char trim[][ipc::IPC_N_I4_PIXEL_ROWS] , const std::string filename){ + std::ofstream maskfile(filename.c_str()); + char line[512]; + for (int i=0;i<674;i++){ + if(i>1){ + sprintf(line, "%3d",i/2); + maskfile<<line; + if(i%2==0)maskfile<<"a "; + else maskfile<<"b "; + }else{ + maskfile<<"### "; + } + for (int j=1;j<=40;j++){ + if(i==0)sprintf(line, "%2d ",j); + else if(i==1)sprintf(line, "%2d ",j+40); + else { + int val = trim[j-1+(i%2)*ipc::IPC_N_I4_PIXEL_COLUMNS/2][i/2-1]; + sprintf(line, "%2d ",val); + } + maskfile<<line; + if(j%10==0)maskfile<<" "; + } + maskfile<<std::endl; + } +} + +void FEI4AConfigFile::readModuleConfig(ipc::PixelFEI4AConfig* config, std::string filename){ + //clear structure + char* ccfg=(char*)config; + for (unsigned int i=0;i<sizeof(ipc::PixelFEI4AConfig);i++)ccfg[i]=0; + //open file + m_moduleCfgFile=new std::ifstream(filename.c_str()); + if(!m_moduleCfgFile->good()){ + std::cout<<"Cannot open file with name "<<filename<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + m_moduleCfgFilePath = filename; + // parse config file + std::string inpline; + m_params.clear(); + while(true){ + getline(*m_moduleCfgFile, inpline); + if(m_moduleCfgFile->eof())break; + boost::trim(inpline); + if(inpline.size()!=0 && inpline[0]!='#'){ //remove comment lines and empty lines + std::vector<std::string> splitVec; + split( splitVec, inpline, boost::is_any_of(" \t"), boost::token_compress_on ); + if(splitVec.size()<2){ + std::cout<<"Bad input line "<<inpline<<std::endl; + continue; + } + m_params[splitVec[0]]=splitVec[1]; + } + } + // Module name + std::string modname=""; + if( m_params.find("ModuleID")==m_params.end()){ + std::cout<<"No Module ID defined."<<std::endl; + }else{ + modname=m_params["ModuleID"]; + } + sprintf((char*)config->idStr, "%s", modname.c_str()); + //Geographical address + config->FECommand.address=lookupToUShort("Address"); + //Global register + ipc::PixelFEI4AGlobal* cfg=&config->FEGlobal; + cfg->TrigCnt = lookupToUShort("TrigCnt"); + cfg->Conf_AddrEnable = lookupToUShort("Conf_AddrEnable"); + cfg->Reg2Spare = lookupToUShort("Reg2Spare"); + cfg->ErrMask0 = lookupToUShort("ErrMask0"); + cfg->ErrMask1 = lookupToUShort("ErrMask1"); + cfg->PrmpVbpRight = lookupToUShort("PrmpVbpRight"); + cfg->Vthin = lookupToUShort("Vthin"); + cfg->DisVbn_CPPM = lookupToUShort("DisVbn_CPPM"); + cfg->PrmpVbp = lookupToUShort("PrmpVbp"); + cfg->TdacVbp = lookupToUShort("TdacVbp"); + cfg->DisVbn = lookupToUShort("DisVbn"); + cfg->Amp2Vbn = lookupToUShort("Amp2Vbn"); + cfg->Amp2VbpFol = lookupToUShort("Amp2VbpFol"); + cfg->PrmpVbpTop = lookupToUShort("PrmpVbpTop"); + cfg->Amp2Vbp = lookupToUShort("Amp2Vbp"); + cfg->FdacVbn = lookupToUShort("FdacVbn"); + cfg->Amp2Vbpf = lookupToUShort("Amp2Vbpf"); + cfg->PrmpVbnFol = lookupToUShort("PrmpVbnFol"); + cfg->PrmpVbpLeft = lookupToUShort("PrmpVbpLeft"); + cfg->PrmpVbpf = lookupToUShort("PrmpVbpf"); + cfg->PrmpVbnLcc = lookupToUShort("PrmpVbnLcc"); + cfg->Reg13Spare = lookupToUShort("Reg13Spare"); + cfg->PxStrobes = lookupToUShort("PxStrobes"); + cfg->S0 = lookupToUShort("S0"); + cfg->S1 = lookupToUShort("S1"); + cfg->LVDSDrvIref = lookupToUShort("LVDSDrvIref"); + cfg->BonnDac = lookupToUShort("BonnDac"); + cfg->PllIbias = lookupToUShort("PllIbias"); + cfg->LVDSDrvVos = lookupToUShort("LVDSDrvVos"); + cfg->TempSensBias = lookupToUShort("TempSensBias"); + cfg->PllIcp = lookupToUShort("PllIcp"); + cfg->Reg17Spare = lookupToUShort("Reg17Spare"); + cfg->PlsrIdacRamp = lookupToUShort("PlsrIdacRamp"); + cfg->Reg18Spare = lookupToUShort("Reg18Spare"); + cfg->PlsrVgOPamp = lookupToUShort("PlsrVgOPamp"); + cfg->PlsrDacBias = lookupToUShort("PlsrDacBias"); + cfg->Reg19Spare = lookupToUShort("Reg19Spare"); + cfg->Vthin_AltCoarse = lookupToUShort("Vthin_AltCoarse"); + cfg->Vthin_AltFine = lookupToUShort("Vthin_AltFine"); + cfg->PlsrDAC = lookupToUShort("PlsrDAC"); + cfg->DIGHITIN_Sel = lookupToUShort("DIGHITIN_Sel"); + cfg->DINJ_Override = lookupToUShort("DINJ_Override"); + cfg->HITLD_In = lookupToUShort("HITLD_In"); + cfg->Reg21Spare = lookupToUShort("Reg21Spare"); + cfg->Reg22Spare2 = lookupToUShort("Reg22Spare2"); + cfg->Colpr_Addr = lookupToUShort("Colpr_Addr"); + cfg->Colpr_Mode = lookupToUShort("Colpr_Mode"); + cfg->Reg22Spare1 = lookupToUShort("Reg22Spare1"); + cfg->DisableColumnCnfg0 = lookupToUShort("DisableColumnCnfg0"); + cfg->DisableColumnCnfg1 = lookupToUShort("DisableColumnCnfg1"); + cfg->DisableColumnCnfg2 = lookupToUShort("DisableColumnCnfg2"); + cfg->TrigLat = lookupToUShort("TrigLat"); + cfg->CMDcnt = lookupToUShort("CMDcnt"); + cfg->StopModeCnfg = lookupToUShort("StopModeCnfg"); + cfg->HitDiscCnfg = lookupToUShort("HitDiscCnfg"); + cfg->EN_PLL = lookupToUShort("EN_PLL"); + cfg->Efuse_sense = lookupToUShort("Efuse_sense"); + cfg->Stop_Clk = lookupToUShort("Stop_Clk"); + cfg->ReadErrorReq = lookupToUShort("ReadErrorReq"); + cfg->ReadSkipped = lookupToUShort("ReadSkipped"); + cfg->Reg27Spare = lookupToUShort("Reg27Spare"); + cfg->GateHitOr = lookupToUShort("GateHitOr"); + cfg->CalEn = lookupToUShort("CalEn"); + cfg->SR_clr = lookupToUShort("SR_clr"); + cfg->Latch_en = lookupToUShort("Latch_en"); + cfg->SR_Clock = lookupToUShort("SR_Clock"); + cfg->LVDSDrvSet06 = lookupToUShort("LVDSDrvSet06"); + cfg->Reg28Spare = lookupToUShort("Reg28Spare"); + cfg->EN40M = lookupToUShort("EN40M"); + cfg->EN80M = lookupToUShort("EN80M"); + //special case + cfg->CLK0 = lookupToUShort("CLK0_S2"); + cfg->CLK0 |= lookupToUShort("CLK0_S1")<<1; + cfg->CLK0 |= lookupToUShort("CLK0_S0")<<2; + cfg->CLK1 = lookupToUShort("CLK1_S2"); + cfg->CLK1 |= lookupToUShort("CLK1_S1")<<1; + cfg->CLK1 |= lookupToUShort("CLK1_S0")<<2; + + cfg->EN160M = lookupToUShort("EN160M"); + cfg->EN320M = lookupToUShort("EN320M"); + cfg->Reg29Spare1 = lookupToUShort("Reg29Spare1"); + cfg->no8b10b = lookupToUShort("no8b10b"); + cfg->Clk2OutCnfg = lookupToUShort("Clk2OutCnfg"); + cfg->EmptyRecord = lookupToUShort("EmptyRecord"); + cfg->Reg29Spare2 = lookupToUShort("Reg29Spare2"); + cfg->LVDSDrvEn = lookupToUShort("LVDSDrvEn"); + cfg->LVDSDrvSet30 = lookupToUShort("LVDSDrvSet30"); + cfg->LVDSDrvSet12 = lookupToUShort("LVDSDrvSet12"); + cfg->PlsrRiseUpTau = lookupToUShort("PlsrRiseUpTau"); + cfg->PlsrPwr = lookupToUShort("PlsrPwr"); + cfg->PlsrDelay = lookupToUShort("PlsrDelay"); + cfg->ExtDigCalSW = lookupToUShort("ExtDigCalSW"); + cfg->ExtAnaCalSW = lookupToUShort("ExtAnaCalSW"); + cfg->Reg31Spare = lookupToUShort("Reg31Spare"); + cfg->SELB0 = lookupToUShort("SELB0"); + cfg->SELB1 = lookupToUShort("SELB1"); + cfg->SELB2 = lookupToUShort("SELB2"); + cfg->EfuseCref = lookupToUShort("EfuseCref"); + cfg->EfuseVref = lookupToUShort("EfuseVref"); + cfg->Chip_SN = lookupToUShort("Chip_SN"); + + // charge injection + config->FECalib.cinjLo=lookupToFloat("cinjLo"); + config->FECalib.cinjHi=lookupToFloat("cinjHi"); + config->FECalib.vcalCoeff[0]=lookupToFloat("vcalCoeff[0]"); + config->FECalib.vcalCoeff[1]=lookupToFloat("vcalCoeff[1]"); + config->FECalib.vcalCoeff[2]=lookupToFloat("vcalCoeff[2]"); + config->FECalib.vcalCoeff[3]=lookupToFloat("vcalCoeff[3]"); + config->FECalib.chargeCoeffClo=lookupToFloat("chargeCoeffClo"); + config->FECalib.chargeCoeffChi=lookupToFloat("chargeCoeffChi"); + config->FECalib.chargeOffsetClo=lookupToFloat("chargeOffsetClo"); + config->FECalib.chargeOffsetChi=lookupToFloat("chargeOffsetChi"); + config->FECalib.monleakCoeff=lookupToFloat("monleakCoeff"); + + //Pixel register + //Masks + setupMaskBit(ipc::enable, config, "enable"); + setupMaskBit(ipc::largeCap, config, "largeCap"); + setupMaskBit(ipc::smallCap, config, "smallCap"); + setupMaskBit(ipc::hitbus, config, "hitbus"); + + setupDAC(config->FETrims.dacThresholdTrim, "tdac"); + setupDAC(config->FETrims.dacFeedbackTrim, "fdac"); + delete m_moduleCfgFile; +} + +void FEI4AConfigFile::dump(const ipc::PixelFEI4AConfig &config){ + const ipc::PixelFEI4AGlobal* cfg=&config.FEGlobal; + std::cout<<"Global Register Fields:"<<std::endl; + std::cout<<"======================="<<std::endl; + std::cout<<"TrigCnt = "<<cfg->TrigCnt<<std::endl; + std::cout<<"Conf_AddrEnable = "<<cfg->Conf_AddrEnable<<std::endl; + std::cout<<"Reg2Spare = "<<cfg->Reg2Spare<<std::endl; + std::cout<<"ErrMask0 = "<<cfg->ErrMask0<<std::endl; + std::cout<<"ErrMask1 = "<<cfg->ErrMask1<<std::endl; + std::cout<<"PrmpVbpRight = "<<cfg->PrmpVbpRight<<std::endl; + std::cout<<"Vthin = "<<cfg->Vthin<<std::endl; + std::cout<<"DisVbn_CPPM = "<<cfg->DisVbn_CPPM<<std::endl; + std::cout<<"PrmpVbp = "<<cfg->PrmpVbp<<std::endl; + std::cout<<"TdacVbp = "<<cfg->TdacVbp<<std::endl; + std::cout<<"DisVbn = "<<cfg->DisVbn<<std::endl; + std::cout<<"Amp2Vbn = "<<cfg->Amp2Vbn<<std::endl; + std::cout<<"Amp2VbpFol = "<<cfg->Amp2VbpFol<<std::endl; + std::cout<<"PrmpVbpTop = "<<cfg->PrmpVbpTop<<std::endl; + std::cout<<"Amp2Vbp = "<<cfg->Amp2Vbp<<std::endl; + std::cout<<"FdacVbn = "<<cfg->FdacVbn<<std::endl; + std::cout<<"Amp2Vbpf = "<<cfg->Amp2Vbpf<<std::endl; + std::cout<<"PrmpVbnFol = "<<cfg->PrmpVbnFol<<std::endl; + std::cout<<"PrmpVbpLeft = "<<cfg->PrmpVbpLeft<<std::endl; + std::cout<<"PrmpVbpf = "<<cfg->PrmpVbpf<<std::endl; + std::cout<<"PrmpVbnLcc = "<<cfg->PrmpVbnLcc<<std::endl; + std::cout<<"Reg13Spare = "<<cfg->Reg13Spare<<std::endl; + std::cout<<"PxStrobes = "<<cfg->PxStrobes<<std::endl; + std::cout<<"S0 = "<<cfg->S0<<std::endl; + std::cout<<"S1 = "<<cfg->S1<<std::endl; + std::cout<<"LVDSDrvIref = "<<cfg->LVDSDrvIref<<std::endl; + std::cout<<"BonnDac = "<<cfg->BonnDac<<std::endl; + std::cout<<"PllIbias = "<<cfg->PllIbias<<std::endl; + std::cout<<"LVDSDrvVos = "<<cfg->LVDSDrvVos<<std::endl; + std::cout<<"TempSensBias = "<<cfg->TempSensBias<<std::endl; + std::cout<<"PllIcp = "<<cfg->PllIcp<<std::endl; + std::cout<<"Reg17Spare = "<<cfg->Reg17Spare<<std::endl; + std::cout<<"PlsrIdacRamp = "<<cfg->PlsrIdacRamp<<std::endl; + std::cout<<"Reg18Spare = "<<cfg->Reg18Spare<<std::endl; + std::cout<<"PlsrVgOPamp = "<<cfg->PlsrVgOPamp<<std::endl; + std::cout<<"PlsrDacBias = "<<cfg->PlsrDacBias<<std::endl; + std::cout<<"Reg19Spare = "<<cfg->Reg19Spare<<std::endl; + std::cout<<"Vthin_AltCoarse = "<<cfg->Vthin_AltCoarse<<std::endl; + std::cout<<"Vthin_AltFine = "<<cfg->Vthin_AltFine<<std::endl; + std::cout<<"PlsrDAC = "<<cfg->PlsrDAC<<std::endl; + std::cout<<"DIGHITIN_Sel = "<<cfg->DIGHITIN_Sel<<std::endl; + std::cout<<"DINJ_Override = "<<cfg->DINJ_Override<<std::endl; + std::cout<<"HITLD_In = "<<cfg->HITLD_In<<std::endl; + std::cout<<"Reg21Spare = "<<cfg->Reg21Spare<<std::endl; + std::cout<<"Reg22Spare2 = "<<cfg->Reg22Spare2<<std::endl; + std::cout<<"Colpr_Addr = "<<cfg->Colpr_Addr<<std::endl; + std::cout<<"Colpr_Mode = "<<cfg->Colpr_Mode<<std::endl; + std::cout<<"Reg22Spare1 = "<<cfg->Reg22Spare2<<std::endl; + std::cout<<"DisableColumnCnfg0 = "<<cfg->DisableColumnCnfg0<<std::endl; + std::cout<<"DisableColumnCnfg1 = "<<cfg->DisableColumnCnfg1<<std::endl; + std::cout<<"DisableColumnCnfg2 = "<<cfg->DisableColumnCnfg2<<std::endl; + std::cout<<"TrigLat = "<<cfg->TrigLat<<std::endl; + std::cout<<"CMDcnt = "<<cfg->CMDcnt<<std::endl; + std::cout<<"StopModeCnfg = "<<cfg->StopModeCnfg<<std::endl; + std::cout<<"HitDiscCnfg = "<<cfg->HitDiscCnfg<<std::endl; + std::cout<<"EN_PLL = "<<cfg->EN_PLL<<std::endl; + std::cout<<"Efuse_sense = "<<cfg->Efuse_sense<<std::endl; + std::cout<<"Stop_Clk = "<<cfg->Stop_Clk<<std::endl; + std::cout<<"ReadErrorReq = "<<cfg->ReadErrorReq<<std::endl; + std::cout<<"ReadSkipped = "<<cfg->ReadSkipped<<std::endl; + std::cout<<"Reg27Spare = "<<cfg->Reg27Spare<<std::endl; + std::cout<<"GateHitOr = "<<cfg->GateHitOr<<std::endl; + std::cout<<"CalEn = "<<cfg->CalEn<<std::endl; + std::cout<<"SR_clr = "<<cfg->SR_clr<<std::endl; + std::cout<<"Latch_en = "<<cfg->Latch_en<<std::endl; + std::cout<<"SR_Clock = "<<cfg->SR_Clock<<std::endl; + std::cout<<"LVDSDrvSet06 = "<<cfg->LVDSDrvSet06<<std::endl; + std::cout<<"Reg28Spare = "<<cfg->Reg28Spare<<std::endl; + std::cout<<"EN40M = "<<cfg->EN40M<<std::endl; + std::cout<<"EN80M = "<<cfg->EN80M<<std::endl; + std::cout<<"CLK1 = "<<cfg->CLK1<<std::endl; + std::cout<<"CLK0 = "<<cfg->CLK0<<std::endl; + std::cout<<"EN160M = "<<cfg->EN160M<<std::endl; + std::cout<<"EN320M = "<<cfg->EN320M<<std::endl; + std::cout<<"Reg29Spare1 = "<<cfg->Reg29Spare1<<std::endl; + std::cout<<"no8b10b = "<<cfg->no8b10b<<std::endl; + std::cout<<"Clk2OutCnfg = "<<cfg->Clk2OutCnfg<<std::endl; + std::cout<<"EmptyRecord = "<<cfg->EmptyRecord<<std::endl; + std::cout<<"Reg29Spare2 = "<<cfg->Reg29Spare2<<std::endl; + std::cout<<"LVDSDrvEn = "<<cfg->LVDSDrvEn<<std::endl; + std::cout<<"LVDSDrvSet30 = "<<cfg->LVDSDrvSet30<<std::endl; + std::cout<<"LVDSDrvSet12 = "<<cfg->LVDSDrvSet12<<std::endl; + std::cout<<"PlsrRiseUpTau = "<<cfg->PlsrRiseUpTau<<std::endl; + std::cout<<"PlsrPwr = "<<cfg->PlsrPwr<<std::endl; + std::cout<<"PlsrDelay = "<<cfg->PlsrDelay<<std::endl; + std::cout<<"ExtDigCalSW = "<<cfg->ExtDigCalSW<<std::endl; + std::cout<<"ExtAnaCalSW = "<<cfg->ExtAnaCalSW<<std::endl; + std::cout<<"Reg31Spare = "<<cfg->Reg31Spare<<std::endl; + std::cout<<"SELB0 = "<<cfg->SELB0<<std::endl; + std::cout<<"SELB1 = "<<cfg->SELB1<<std::endl; + std::cout<<"SELB2 = "<<cfg->SELB2<<std::endl; + std::cout<<"EfuseCref = "<<cfg->EfuseCref<<std::endl; + std::cout<<"EfuseVref = "<<cfg->EfuseVref<<std::endl; + std::cout<<"Chip_SN = "<<cfg->Chip_SN<<std::endl; + // charge injection + std::cout<<std::endl; + std::cout<<"Charge injection parameters:"<<std::endl; + std::cout<<"============================"<<std::endl; + std::cout<<"cinjLo = "<<config.FECalib.cinjLo<<std::endl; + std::cout<<"cinjHi = "<<config.FECalib.cinjHi<<std::endl; + std::cout<<"vcalCoeff[0] = "<<config.FECalib.vcalCoeff[0]<<std::endl; + std::cout<<"vcalCoeff[1] = "<<config.FECalib.vcalCoeff[1]<<std::endl; + std::cout<<"vcalCoeff[2] = "<<config.FECalib.vcalCoeff[2]<<std::endl; + std::cout<<"vcalCoeff[3] = "<<config.FECalib.vcalCoeff[3]<<std::endl; + std::cout<<"chargeCoeffClo = "<<config.FECalib.chargeCoeffClo<<std::endl; + std::cout<<"chargeCoeffChi = "<<config.FECalib.chargeCoeffChi<<std::endl; + std::cout<<"chargeOffsetClo = "<<config.FECalib.chargeOffsetClo<<std::endl; + std::cout<<"chargeOffsetChi = "<<config.FECalib.chargeOffsetChi<<std::endl; + std::cout<<"monleakCoeff = "<<config.FECalib.monleakCoeff<<std::endl; + + //DACs + std::cout<<"Threshold DAC:"<<std::endl; + std::cout<<"--------------"<<std::endl; + dumpDac(config.FETrims.dacThresholdTrim); + std::cout<<"Feedback DAC:"<<std::endl; + std::cout<<"-------------"<<std::endl; + dumpDac(config.FETrims.dacFeedbackTrim); + + //Masks + std::cout<<"Enable Mask:"<<std::endl; + std::cout<<"------------"<<std::endl; + dumpMask(ipc::enable, config); + std::cout<<"Large Cap Mask:"<<std::endl; + std::cout<<"---------------"<<std::endl; + dumpMask(ipc::largeCap, config); + std::cout<<"Small Cap Mask:"<<std::endl; + std::cout<<"---------------"<<std::endl; + dumpMask(ipc::smallCap, config); + std::cout<<"Hitbus Mask:"<<std::endl; + std::cout<<"------------"<<std::endl; + dumpMask(ipc::hitbus, config); + +} + +void FEI4AConfigFile::dumpDac(const unsigned char trim[][ipc::IPC_N_I4_PIXEL_ROWS]){ + std::cout<<(unsigned)trim[0][0]<<" "<<(unsigned)trim[79][335]<<std::endl; + for (int i=0;i<674;i++){ + if(i>1){ + printf("%3d",i/2); + if(i%2==0)std::cout<<"a "; + else std::cout<<"b "; + }else{ + std::cout<<"### "; + } + for (int j=1;j<=40;j++){ + if(i<2){ + if(i==0)printf("%2d ",j); + else printf("%2d ",j+40); + }else{ + if(i%2==0)printf("%2d ",trim[j-1][i/2-1]); + else printf("%2d ",trim[j+39][i/2-1]); + } + if(j%10==0)std::cout<<" "; + } + std::cout<<std::endl; + } + std::cout<<std::endl; + } + + void FEI4AConfigFile::dumpMask(const long int bit, const ipc::PixelFEI4AConfig& cfg){ + + for (int i=0;i<=336;i++){ + if(i==0){ + std::cout<<"### 1 6 11 16 21 26 31 36 41 46 51 56 61 66 71 76"<<std::endl; + } + else{ + printf("%3d ",i); + for (int j=1;j<=80;j++){ + printf("%1d",(cfg.FEMasks[j-1][i-1]>>bit)&0x1); + if(j%10==0)std::cout<<" "; + else if(j%5==0)std::cout<<"-"; + } + std::cout<<std::endl; + } + } + std::cout<<std::endl; + } diff --git a/rce/rcecalib/server/FEI4AConfigFile.hh b/rce/rcecalib/server/FEI4AConfigFile.hh new file mode 100644 index 00000000..9fef2674 --- /dev/null +++ b/rce/rcecalib/server/FEI4AConfigFile.hh @@ -0,0 +1,32 @@ +#ifndef FEI4ACONFIGFILE_HH +#define FEI4ACONFIGFILE_HH + +#include "PixelFEI4AConfig.hh" +#include <string> +#include <map> + +class FEI4AConfigFile { +public: + FEI4AConfigFile(){} + ~FEI4AConfigFile(); + void readModuleConfig(ipc::PixelFEI4AConfig* cfg, std::string filename); + void writeModuleConfig(ipc::PixelFEI4AConfig* cfg, const std::string &base, const std::string &confdir, const std::string &configname, const std::string &key); + void writeMaskFile(const long int bit, ipc::PixelFEI4AConfig* config, const std::string &filename); + void writeDacFile(unsigned char trim[][ipc::IPC_N_I4_PIXEL_ROWS] , const std::string filename); + void dump(const ipc::PixelFEI4AConfig& cfg); +private: + std::string getFullPath(std::string relPath); + void setupDAC(unsigned char trim[][ipc::IPC_N_I4_PIXEL_ROWS] , std::string par); + void setupMaskBit(const long int bit, ipc::PixelFEI4AConfig *cfg, std::string par); + void dumpMask(const long int bit, const ipc::PixelFEI4AConfig& cfg); + unsigned short lookupToUShort(std::string par); + int convertToUShort(std::string par, unsigned short& val); + float lookupToFloat(std::string par); + void dumpDac(const unsigned char trim[][ipc::IPC_N_I4_PIXEL_ROWS]); + + std::string m_moduleCfgFilePath; + std::ifstream *m_moduleCfgFile; + std::map<std::string, std::string> m_params; +}; + +#endif diff --git a/rce/rcecalib/server/FEI4BConfigFile.cc b/rce/rcecalib/server/FEI4BConfigFile.cc new file mode 100644 index 00000000..e0b65078 --- /dev/null +++ b/rce/rcecalib/server/FEI4BConfigFile.cc @@ -0,0 +1,772 @@ +#include "rcecalib/server/FEI4BConfigFile.hh" +#include "rcecalib/util/exceptions.hh" +#include <boost/algorithm/string.hpp> +#include <iostream> +#include <fstream> +#include <vector> +#include <sys/stat.h> + +std::string FEI4BConfigFile::getFullPath(std::string relPath){ + std::string newPath = relPath, basePath=m_moduleCfgFilePath, testName; + unsigned int pos; + // skip config file-name part of base path + pos = basePath.find_last_of('/'); + if(pos!=std::string::npos) basePath.erase(pos,basePath.length()-pos); + // skip "config" part of base path + pos = basePath.find_last_of('/'); + if(pos!=std::string::npos) basePath.erase(pos,basePath.length()-pos); + // now skip module part of base path, but keep last "/" + pos = basePath.find_last_of('/'); + if(pos!=std::string::npos) basePath.erase(pos+1,basePath.length()-pos); + else basePath=""; + // then add relative path of DAC or mask file + newPath = basePath + newPath; + return newPath; +} + +FEI4BConfigFile::~FEI4BConfigFile(){} + +unsigned short FEI4BConfigFile::lookupToUShort(std::string par){ + if( m_params.find(par)==m_params.end()){ + std::cout<<"Parameter "<<par<<" does not exist."<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + std::string vals=m_params[par]; + unsigned short val; + int success=convertToUShort(vals, val); + if(success==false){ + std::cout<<"Bad value "<<vals<< " for parameter "<<par<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + return val; +} +float FEI4BConfigFile::lookupToFloat(std::string par){ + if( m_params.find(par)==m_params.end()){ + std::cout<<"Parameter "<<par<<" does not exist."<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + std::string vals=m_params[par]; + float val; + char* end; + val=strtof(vals.c_str(), &end); + if(end-vals.c_str()!=(int)vals.size()){ + std::cout<<"Bad value "<<vals<< " for parameter "<<par<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + return val; +} + +int FEI4BConfigFile::convertToUShort(std::string par, unsigned short& val){ + char* end; + val=strtoul(par.c_str(), &end, 0); + if(end-par.c_str()!=(int)par.size()){ + return 0; + } + if((val&0xffff0000)!=0){ + std::cout<<"Value "<<val<<" too large."<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + return 1; +} + + +void FEI4BConfigFile::setupMaskBit(const long int bit, ipc::PixelFEI4BConfig* cfg, std::string par){ + if( m_params.find(par)==m_params.end()){ + std::cout<<"Parameter "<<par<<" does not exist."<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + unsigned short val; + int success=convertToUShort(m_params[par], val); + //file + if(success==false){ + std::string fullpath=getFullPath(m_params[par]); + std::ifstream* maskfile=new std::ifstream(fullpath.c_str()); + if(!maskfile->good()){ + std::cout<<"Cannot open file with name "<<fullpath<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + std::string inpline; + unsigned short row=0; + while(true){ + getline(*maskfile, inpline); + if(maskfile->eof())break; + boost::trim(inpline); + if(inpline.size()!=0 && inpline[0]!='#'){ //remove comment lines and empty lines + std::vector<std::string> splitVec; + split( splitVec, inpline, boost::is_any_of(" -"), boost::token_compress_on ); + if(splitVec.size()!=17){ + std::cout<<"Bad input line "<<inpline<<std::endl; + continue; + } + int success=convertToUShort(splitVec[0], val); + if(success!=true || val!=++row){//check and increment row number + throw rcecalib::Config_File_Error(ERS_HERE); + } + std::string oneline; + for(int i=1;i<17;i++)oneline+=splitVec[i]; //concatenate everyting. + if(oneline.size()!=(unsigned)ipc::IPC_N_I4_PIXEL_COLUMNS) throw rcecalib::Config_File_Error(ERS_HERE); + for(int i=0;i<ipc::IPC_N_I4_PIXEL_COLUMNS;i++){ + if(oneline[i]=='1')cfg->FEMasks[i][row-1]|=1<<bit; + } + } + } + if(row!=ipc::IPC_N_I4_PIXEL_ROWS) throw rcecalib::Config_File_Error(ERS_HERE); + delete maskfile; + }else{ + // left are the cases all 0 and all 1 + if(val!=0 && val!=1) throw rcecalib::Config_File_Error(ERS_HERE); + for (int i=0;i<ipc::IPC_N_I4_PIXEL_COLUMNS;i++){ + for(int j=0;j<ipc::IPC_N_I4_PIXEL_ROWS;j++){ + cfg->FEMasks[i][j]|=val<<bit; + } + } + } +} + + +void FEI4BConfigFile::setupDAC(unsigned char trim[][ipc::IPC_N_I4_PIXEL_ROWS] , std::string par){ + if( m_params.find(par)==m_params.end()){ + std::cout<<"Parameter "<<par<<" does not exist."<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + unsigned short val; + int success=convertToUShort(m_params[par], val); + //file + if(success==false){ + std::string fullpath=getFullPath(m_params[par]); + std::ifstream* dacfile=new std::ifstream(fullpath.c_str()); + if(!dacfile->good()){ + std::cout<<"Cannot open file with name "<<fullpath<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + std::string inpline; + unsigned short hrow=1; + while(true){ + getline(*dacfile, inpline); + if(dacfile->eof())break; + boost::trim(inpline); + if(inpline.size()!=0 && inpline[0]!='#'){ //remove comment lines and empty lines + std::vector<std::string> splitVec; + split( splitVec, inpline, boost::is_any_of(" "), boost::token_compress_on ); + if(splitVec.size()!=41){ + std::cout<<"Bad input line "<<inpline<<std::endl; + continue; + } + success=convertToUShort(splitVec[0].substr(0,splitVec[0].size()-1),val); + if(success!=true || val!=++hrow/2){//check and increment row number + throw rcecalib::Config_File_Error(ERS_HERE); + } + for(int i=0;i<ipc::IPC_N_I4_PIXEL_COLUMNS/2;i++){ + success=convertToUShort(splitVec[i+1], val); + if(!success) throw rcecalib::Config_File_Error(ERS_HERE); + trim[i+(hrow%2)*ipc::IPC_N_I4_PIXEL_COLUMNS/2][hrow/2-1]=val; + } + } + } + if(hrow/2!=ipc::IPC_N_I4_PIXEL_ROWS) throw rcecalib::Config_File_Error(ERS_HERE); + delete dacfile; + }else{ + // left are the cases where all settings are identical. + for (int i=0;i<ipc::IPC_N_I4_PIXEL_COLUMNS;i++){ + for(int j=0;j<ipc::IPC_N_I4_PIXEL_ROWS;j++){ + trim[i][j]=val; + } + } + } +} + +void FEI4BConfigFile::writeModuleConfig(ipc::PixelFEI4BConfig* config, const std::string &base, const std::string &confdir, + const std::string &configname, const std::string &key){ + struct stat stFileInfo; + int intStat; + // Attempt to get the file attributes + intStat = stat(base.c_str(),&stFileInfo); + if(intStat != 0) { //File does not exist + std::cout<<"Directory "<<base<<" does not exist. Not writing config file"<<std::endl; + return; + } + intStat = stat((base+"/"+confdir).c_str(),&stFileInfo); + if(intStat != 0) { //File does not exist + //std::cout<<"Directory "<<base<<"/"<<confdir<<" does not exist. Creating."<<std::endl; + mkdir ((base+"/"+confdir).c_str(),0777); + mkdir ((base+"/"+confdir+"/configs").c_str(),0777); + mkdir ((base+"/"+confdir+"/masks").c_str(),0777); + mkdir ((base+"/"+confdir+"/tdacs").c_str(),0777); + mkdir ((base+"/"+confdir+"/fdacs").c_str(),0777); + } + std::string cfgname=configname; + if(key.size()!=0)cfgname+="__"+key; + std::string fullpath=base+"/"+confdir+"/configs/"+cfgname+".cfg"; + std::ofstream cfgfile(fullpath.c_str()); + cfgfile<<"# FEI4B Configuration"<<std::endl; + cfgfile<<std::endl; + cfgfile<<"# Module name"<<std::endl; + cfgfile<<std::endl; + cfgfile<<"ModuleID\t\t"<<config->idStr<<std::endl; + cfgfile<<std::endl; + cfgfile<<"# Geographical address"<<std::endl; + cfgfile<<std::endl; + cfgfile<<"Address\t\t\t"<<(unsigned)config->FECommand.address<<std::endl; + cfgfile<<std::endl; + cfgfile<<"# Global register"<<std::endl; + cfgfile<<std::endl; + //Global register + ipc::PixelFEI4BGlobal* cfg=&config->FEGlobal; + cfgfile<<"TrigCnt\t\t\t"<<cfg->TrigCnt<<std::endl; + cfgfile<<"Conf_AddrEnable\t\t"<<cfg->Conf_AddrEnable <<std::endl; + cfgfile<<"Reg2Spare\t\t"<<cfg->Reg2Spare <<std::endl; + cfgfile<<"ErrMask0\t\t"<<"0x"<<std::hex<<cfg->ErrMask0 <<std::dec<<std::endl; + cfgfile<<"ErrMask1\t\t"<<"0x"<<std::hex<<cfg->ErrMask1 <<std::dec<<std::endl; + cfgfile<<"PrmpVbpRight\t\t"<< cfg->PrmpVbpRight <<std::endl; + cfgfile<<"BufVgOpAmp\t\t"<<cfg->BufVgOpAmp <<std::endl; + cfgfile<<"Reg6Spare\t\t"<<cfg->Reg6Spare <<std::endl; + cfgfile<<"PrmpVbp\t\t\t"<<cfg->PrmpVbp <<std::endl; + cfgfile<<"TdacVbp\t\t\t"<< cfg->TdacVbp <<std::endl; + cfgfile<<"DisVbn\t\t\t"<<cfg->DisVbn <<std::endl; + cfgfile<<"Amp2Vbn\t\t\t"<<cfg->Amp2Vbn <<std::endl; + cfgfile<<"Amp2VbpFol\t\t"<<cfg->Amp2VbpFol <<std::endl; + cfgfile<<"Reg9Spare\t\t"<<cfg->Reg9Spare <<std::endl; + cfgfile<<"Amp2Vbp\t\t\t"<<cfg->Amp2Vbp <<std::endl; + cfgfile<<"FdacVbn\t\t\t"<<cfg->FdacVbn <<std::endl; + cfgfile<<"Amp2Vbpf\t\t"<<cfg->Amp2Vbpf <<std::endl; + cfgfile<<"PrmpVbnFol\t\t"<<cfg->PrmpVbnFol <<std::endl; + cfgfile<<"PrmpVbpLeft\t\t"<<cfg->PrmpVbpLeft <<std::endl; + cfgfile<<"PrmpVbpf\t\t"<<cfg->PrmpVbpf <<std::endl; + cfgfile<<"PrmpVbnLcc\t\t"<<cfg->PrmpVbnLcc <<std::endl; + cfgfile<<"Reg13Spare\t\t"<<cfg->Reg13Spare <<std::endl; + cfgfile<<"PxStrobes\t\t"<<cfg->PxStrobes <<std::endl; + cfgfile<<"S0\t\t\t"<<cfg->S0 <<std::endl; + cfgfile<<"S1\t\t\t"<<cfg->S1 <<std::endl; + cfgfile<<"LVDSDrvIref\t\t"<<cfg->LVDSDrvIref <<std::endl; + cfgfile<<"GADCOpAmp\t\t"<<cfg->GADCOpAmp <<std::endl; + cfgfile<<"PllIbias\t\t"<<cfg->PllIbias <<std::endl; + cfgfile<<"LVDSDrvVos\t\t"<<cfg->LVDSDrvVos <<std::endl; + cfgfile<<"TempSensBias\t\t"<<cfg->TempSensBias <<std::endl; + cfgfile<<"PllIcp\t\t\t"<<cfg->PllIcp <<std::endl; + cfgfile<<"Reg17Spare\t\t"<<cfg->Reg17Spare <<std::endl; + cfgfile<<"PlsrIdacRamp\t\t"<<cfg->PlsrIdacRamp <<std::endl; + cfgfile<<"VrefDigTune\t\t"<<cfg->VrefDigTune <<std::endl; + cfgfile<<"PlsrVgOPamp\t\t"<<cfg->PlsrVgOPamp <<std::endl; + cfgfile<<"PlsrDacBias\t\t"<<cfg->PlsrDacBias <<std::endl; + cfgfile<<"VrefAnTune\t\t"<<cfg->VrefAnTune <<std::endl; + cfgfile<<"Vthin_AltCoarse\t\t"<<cfg->Vthin_AltCoarse <<std::endl; + cfgfile<<"Vthin_AltFine\t\t"<<cfg->Vthin_AltFine <<std::endl; + cfgfile<<"PlsrDAC\t\t\t"<<cfg->PlsrDAC <<std::endl; + cfgfile<<"DIGHITIN_Sel\t\t"<<cfg->DIGHITIN_Sel <<std::endl; + cfgfile<<"DINJ_Override\t\t"<<cfg->DINJ_Override <<std::endl; + cfgfile<<"HITLD_In\t\t"<<cfg->HITLD_In <<std::endl; + cfgfile<<"Reg21Spare\t\t"<<cfg->Reg21Spare <<std::endl; + cfgfile<<"Reg22Spare2\t\t"<<cfg->Reg22Spare2 <<std::endl; + cfgfile<<"Colpr_Addr\t\t"<<cfg->Colpr_Addr <<std::endl; + cfgfile<<"Colpr_Mode\t\t"<<cfg->Colpr_Mode <<std::endl; + cfgfile<<"Reg22Spare1\t\t"<<cfg->Reg22Spare1 <<std::endl; + cfgfile<<"DisableColumnCnfg0\t"<<"0x"<<std::hex<<cfg->DisableColumnCnfg0 <<std::dec<<std::endl; + cfgfile<<"DisableColumnCnfg1\t"<<"0x"<<std::hex<<cfg->DisableColumnCnfg1 <<std::dec<<std::endl; + cfgfile<<"DisableColumnCnfg2\t"<<"0x"<<std::hex<<cfg->DisableColumnCnfg2 <<std::dec<<std::endl; + cfgfile<<"TrigLat\t\t\t"<< cfg->TrigLat <<std::endl; + cfgfile<<"CMDcnt\t\t\t"<<cfg->CMDcnt <<std::endl; + cfgfile<<"StopModeCnfg\t\t"<<cfg->StopModeCnfg <<std::endl; + cfgfile<<"HitDiscCnfg\t\t"<<cfg->HitDiscCnfg <<std::endl; + cfgfile<<"EN_PLL\t\t\t"<<cfg->EN_PLL <<std::endl; + cfgfile<<"Efuse_sense\t\t"<<cfg->Efuse_sense <<std::endl; + cfgfile<<"Stop_Clk\t\t"<<cfg->Stop_Clk <<std::endl; + cfgfile<<"ReadErrorReq\t\t"<<cfg->ReadErrorReq <<std::endl; + cfgfile<<"Reg27Spare1\t\t"<<cfg->Reg27Spare1 <<std::endl; + cfgfile<<"GADC_Enable\t\t"<<cfg->GADC_Enable <<std::endl; + cfgfile<<"ShiftReadBack\t\t"<<cfg->ShiftReadBack <<std::endl; + cfgfile<<"Reg27Spare2\t\t"<<cfg->Reg27Spare2 <<std::endl; + cfgfile<<"GateHitOr\t\t"<<cfg->GateHitOr <<std::endl; + cfgfile<<"CalEn\t\t\t"<<cfg->CalEn <<std::endl; + cfgfile<<"SR_clr\t\t\t"<<cfg->SR_clr <<std::endl; + cfgfile<<"Latch_en\t\t"<<cfg->Latch_en <<std::endl; + cfgfile<<"SR_Clock\t\t"<<cfg->SR_Clock <<std::endl; + cfgfile<<"LVDSDrvSet06\t\t"<<cfg->LVDSDrvSet06 <<std::endl; + cfgfile<<"Reg28Spare\t\t"<<cfg->Reg28Spare <<std::endl; + cfgfile<<"EN40M\t\t\t"<<cfg->EN40M <<std::endl; + cfgfile<<"EN80M\t\t\t"<<cfg->EN80M <<std::endl; + cfgfile<<"CLK0_S2\t\t\t"<<(cfg->CLK0 &0x1)<<std::endl; + cfgfile<<"CLK0_S1\t\t\t"<<((cfg->CLK0>>1)&0x1 )<<std::endl; + cfgfile<<"CLK0_S0\t\t\t"<<((cfg->CLK0>>2)&0x1 )<<std::endl; + cfgfile<<"CLK1_S2\t\t\t"<<(cfg->CLK1&0x1 )<<std::endl; + cfgfile<<"CLK1_S1\t\t\t"<<((cfg->CLK1>>1)&0x1 )<<std::endl; + cfgfile<<"CLK1_S0\t\t\t"<<((cfg->CLK1>>2)&0x1 )<<std::endl; + cfgfile<<"EN160M\t\t\t"<<cfg->EN160M <<std::endl; + cfgfile<<"EN320M\t\t\t"<<cfg->EN320M <<std::endl; + cfgfile<<"Reg29Spare1\t\t"<<cfg->Reg29Spare1 <<std::endl; + cfgfile<<"no8b10b\t\t\t"<<cfg->no8b10b <<std::endl; + cfgfile<<"Clk2OutCnfg\t\t"<<cfg->Clk2OutCnfg <<std::endl; + cfgfile<<"EmptyRecord\t\t"<<cfg->EmptyRecord <<std::endl; + cfgfile<<"Reg29Spare2\t\t"<<cfg->Reg29Spare2 <<std::endl; + cfgfile<<"LVDSDrvEn\t\t"<<cfg->LVDSDrvEn <<std::endl; + cfgfile<<"LVDSDrvSet30\t\t"<<cfg->LVDSDrvSet30 <<std::endl; + cfgfile<<"LVDSDrvSet12\t\t"<<cfg->LVDSDrvSet12 <<std::endl; + cfgfile<<"TempSensDiodeSel\t"<<cfg->TempSensDiodeSel <<std::endl; + cfgfile<<"TempSensDisable\t\t"<<cfg->TempSensDisable <<std::endl; + cfgfile<<"IleakRange\t\t"<<cfg->IleakRange <<std::endl; + cfgfile<<"Reg30Spare\t\t"<<cfg->Reg30Spare <<std::endl; + cfgfile<<"PlsrRiseUpTau\t\t"<<cfg->PlsrRiseUpTau <<std::endl; + cfgfile<<"PlsrPwr\t\t\t"<<cfg->PlsrPwr <<std::endl; + cfgfile<<"PlsrDelay\t\t"<<cfg->PlsrDelay <<std::endl; + cfgfile<<"ExtDigCalSW\t\t"<<cfg->ExtDigCalSW <<std::endl; + cfgfile<<"ExtAnaCalSW\t\t"<<cfg->ExtAnaCalSW <<std::endl; + cfgfile<<"Reg31Spare\t\t"<<cfg->Reg31Spare <<std::endl; + cfgfile<<"GADCSel\t\t\t"<<cfg->GADCSel <<std::endl; + cfgfile<<"SELB0\t\t\t"<<cfg->SELB0 <<std::endl; + cfgfile<<"SELB1\t\t\t"<<cfg->SELB1 <<std::endl; + cfgfile<<"SELB2\t\t\t"<<cfg->SELB2 <<std::endl; + cfgfile<<"Reg34Spare1\t\t"<<cfg->Reg34Spare1 <<std::endl; + cfgfile<<"PrmpVbpMsnEn\t\t"<<cfg->PrmpVbpMsnEn <<std::endl; + cfgfile<<"Reg34Spare2\t\t"<<cfg->Reg34Spare2 <<std::endl; + cfgfile<<"Chip_SN\t\t\t"<<cfg->Chip_SN <<std::endl; + cfgfile<<"Reg1Spare\t\t"<<cfg->Reg1Spare <<std::endl; + cfgfile<<"SmallHitErase\t\t"<<cfg->SmallHitErase <<std::endl; + cfgfile<<"Eventlimit\t\t"<<cfg->Eventlimit <<std::endl; + cfgfile<<std::endl; + cfgfile<<"# Pixel register"<<std::endl; + cfgfile<<std::endl; + cfgfile<<"enable\t\t\t"<<confdir<<"/masks/enable_"<<cfgname<<".dat"<<std::endl; + cfgfile<<"largeCap\t\t"<<confdir<<"/masks/largeCap_"<<cfgname<<".dat"<<std::endl; + cfgfile<<"smallCap\t\t"<<confdir<<"/masks/smallCap_"<<cfgname<<".dat"<<std::endl; + cfgfile<<"hitbus\t\t\t"<<confdir<<"/masks/hitbus_"<<cfgname<<".dat"<<std::endl; + cfgfile<<std::endl; + cfgfile<<"tdac\t\t\t"<<confdir<<"/tdacs/tdac_"<<cfgname<<".dat"<<std::endl; + cfgfile<<"fdac\t\t\t"<<confdir<<"/fdacs/fdac_"<<cfgname<<".dat"<<std::endl; + cfgfile<<std::endl; + cfgfile<<std::endl; + cfgfile<<"# Charge injection parameters"<<std::endl; + cfgfile<<std::endl; + cfgfile<<"cinjLo\t\t\t"<<config->FECalib.cinjLo <<std::endl; + cfgfile<<"cinjHi\t\t\t"<<config->FECalib.cinjHi <<std::endl; + cfgfile<<"vcalCoeff[0]\t\t"<<config->FECalib.vcalCoeff[0] <<std::endl; + cfgfile<<"vcalCoeff[1]\t\t"<<config->FECalib.vcalCoeff[1] <<std::endl; + cfgfile<<"vcalCoeff[2]\t\t"<<config->FECalib.vcalCoeff[2] <<std::endl; + cfgfile<<"vcalCoeff[3]\t\t"<<config->FECalib.vcalCoeff[3] <<std::endl; + cfgfile<<"chargeCoeffClo\t\t"<<config->FECalib.chargeCoeffClo<<std::endl; + cfgfile<<"chargeCoeffChi\t\t"<<config->FECalib.chargeCoeffChi<<std::endl; + cfgfile<<"chargeOffsetClo\t\t"<<config->FECalib.chargeOffsetClo<<std::endl; + cfgfile<<"chargeOffsetChi\t\t"<<config->FECalib.chargeOffsetChi<<std::endl; + cfgfile<<"monleakCoeff\t\t"<<config->FECalib.monleakCoeff<<std::endl; + writeMaskFile(ipc::enable, config, base+"/"+confdir+"/masks/enable_"+cfgname+".dat"); + writeMaskFile(ipc::largeCap, config, base+"/"+confdir+"/masks/largeCap_"+cfgname+".dat"); + writeMaskFile(ipc::smallCap, config, base+"/"+confdir+"/masks/smallCap_"+cfgname+".dat"); + writeMaskFile(ipc::hitbus, config, base+"/"+confdir+"/masks/hitbus_"+cfgname+".dat"); + + writeDacFile(config->FETrims.dacThresholdTrim, base+"/"+confdir+"/tdacs/tdac_"+cfgname+".dat"); + writeDacFile(config->FETrims.dacFeedbackTrim, base+"/"+confdir+"/fdacs/fdac_"+cfgname+".dat"); + + + +} +void FEI4BConfigFile::writeMaskFile(const long int bit, ipc::PixelFEI4BConfig* config, const std::string &filename){ + std::ofstream maskfile(filename.c_str()); + maskfile<<"### 1 6 11 16 21 26 31 36 41 46 51 56 61 66 71 76"<<std::endl; + char linenr[128]; + for(int i=1;i<=336;i++){ + sprintf(linenr,"%3d ", i); + maskfile<<linenr; + for (int j=1;j<=80;j++){ + maskfile<<((config->FEMasks[j-1][i-1]>>bit)&0x1); + if(j%10==0)maskfile<<" "; + else if(j%5==0)maskfile<<"-"; + } + maskfile<<std::endl; + } +} + +void FEI4BConfigFile::writeDacFile(unsigned char trim[][ipc::IPC_N_I4_PIXEL_ROWS] , const std::string filename){ + std::ofstream maskfile(filename.c_str()); + char line[512]; + for (int i=0;i<674;i++){ + if(i>1){ + sprintf(line, "%3d",i/2); + maskfile<<line; + if(i%2==0)maskfile<<"a "; + else maskfile<<"b "; + }else{ + maskfile<<"### "; + } + for (int j=1;j<=40;j++){ + if(i==0)sprintf(line, "%2d ",j); + else if(i==1)sprintf(line, "%2d ",j+40); + else { + int val = trim[j-1+(i%2)*ipc::IPC_N_I4_PIXEL_COLUMNS/2][i/2-1]; + sprintf(line, "%2d ",val); + } + maskfile<<line; + if(j%10==0)maskfile<<" "; + } + maskfile<<std::endl; + } +} + +void FEI4BConfigFile::readModuleConfig(ipc::PixelFEI4BConfig* config, std::string filename){ + //clear structure + char* ccfg=(char*)config; + for (unsigned int i=0;i<sizeof(ipc::PixelFEI4BConfig);i++)ccfg[i]=0; + //open file + m_moduleCfgFile=new std::ifstream(filename.c_str()); + if(!m_moduleCfgFile->good()){ + std::cout<<"Cannot open file with name "<<filename<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + m_moduleCfgFilePath = filename; + // parse config file + std::string inpline; + m_params.clear(); + while(true){ + getline(*m_moduleCfgFile, inpline); + if(m_moduleCfgFile->eof())break; + boost::trim(inpline); + if(inpline.size()!=0 && inpline[0]!='#'){ //remove comment lines and empty lines + std::vector<std::string> splitVec; + split( splitVec, inpline, boost::is_any_of(" \t"), boost::token_compress_on ); + if(splitVec.size()<2){ + std::cout<<"Bad input line "<<inpline<<std::endl; + continue; + } + m_params[splitVec[0]]=splitVec[1]; + } + } + // Module name + std::string modname=""; + if( m_params.find("ModuleID")==m_params.end()){ + std::cout<<"No Module ID defined."<<std::endl; + }else{ + modname=m_params["ModuleID"]; + } + sprintf((char*)config->idStr, "%s", modname.c_str()); + //Geographical address + config->FECommand.address=lookupToUShort("Address"); + //Global register + ipc::PixelFEI4BGlobal* cfg=&config->FEGlobal; + cfg->TrigCnt = lookupToUShort("TrigCnt"); + cfg->Conf_AddrEnable = lookupToUShort("Conf_AddrEnable"); + cfg->Reg2Spare = lookupToUShort("Reg2Spare"); + cfg->ErrMask0 = lookupToUShort("ErrMask0"); + cfg->ErrMask1 = lookupToUShort("ErrMask1"); + cfg->PrmpVbpRight = lookupToUShort("PrmpVbpRight"); + cfg->BufVgOpAmp = lookupToUShort("BufVgOpAmp"); + cfg->Reg6Spare = lookupToUShort("Reg6Spare"); + cfg->PrmpVbp = lookupToUShort("PrmpVbp"); + cfg->TdacVbp = lookupToUShort("TdacVbp"); + cfg->DisVbn = lookupToUShort("DisVbn"); + cfg->Amp2Vbn = lookupToUShort("Amp2Vbn"); + cfg->Amp2VbpFol = lookupToUShort("Amp2VbpFol"); + cfg->Reg9Spare = lookupToUShort("Reg9Spare"); + cfg->Amp2Vbp = lookupToUShort("Amp2Vbp"); + cfg->FdacVbn = lookupToUShort("FdacVbn"); + cfg->Amp2Vbpf = lookupToUShort("Amp2Vbpf"); + cfg->PrmpVbnFol = lookupToUShort("PrmpVbnFol"); + cfg->PrmpVbpLeft = lookupToUShort("PrmpVbpLeft"); + cfg->PrmpVbpf = lookupToUShort("PrmpVbpf"); + cfg->PrmpVbnLcc = lookupToUShort("PrmpVbnLcc"); + cfg->Reg13Spare = lookupToUShort("Reg13Spare"); + cfg->PxStrobes = lookupToUShort("PxStrobes"); + cfg->S0 = lookupToUShort("S0"); + cfg->S1 = lookupToUShort("S1"); + cfg->LVDSDrvIref = lookupToUShort("LVDSDrvIref"); + cfg->GADCOpAmp = lookupToUShort("GADCOpAmp"); + cfg->PllIbias = lookupToUShort("PllIbias"); + cfg->LVDSDrvVos = lookupToUShort("LVDSDrvVos"); + cfg->TempSensBias = lookupToUShort("TempSensBias"); + cfg->PllIcp = lookupToUShort("PllIcp"); + cfg->Reg17Spare = lookupToUShort("Reg17Spare"); + cfg->PlsrIdacRamp = lookupToUShort("PlsrIdacRamp"); + cfg->VrefDigTune = lookupToUShort("VrefDigTune"); + cfg->PlsrVgOPamp = lookupToUShort("PlsrVgOPamp"); + cfg->PlsrDacBias = lookupToUShort("PlsrDacBias"); + cfg->VrefAnTune = lookupToUShort("VrefAnTune"); + cfg->Vthin_AltCoarse = lookupToUShort("Vthin_AltCoarse"); + cfg->Vthin_AltFine = lookupToUShort("Vthin_AltFine"); + cfg->PlsrDAC = lookupToUShort("PlsrDAC"); + cfg->DIGHITIN_Sel = lookupToUShort("DIGHITIN_Sel"); + cfg->DINJ_Override = lookupToUShort("DINJ_Override"); + cfg->HITLD_In = lookupToUShort("HITLD_In"); + cfg->Reg21Spare = lookupToUShort("Reg21Spare"); + cfg->Reg22Spare2 = lookupToUShort("Reg22Spare2"); + cfg->Colpr_Addr = lookupToUShort("Colpr_Addr"); + cfg->Colpr_Mode = lookupToUShort("Colpr_Mode"); + cfg->Reg22Spare1 = lookupToUShort("Reg22Spare1"); + cfg->DisableColumnCnfg0 = lookupToUShort("DisableColumnCnfg0"); + cfg->DisableColumnCnfg1 = lookupToUShort("DisableColumnCnfg1"); + cfg->DisableColumnCnfg2 = lookupToUShort("DisableColumnCnfg2"); + cfg->TrigLat = lookupToUShort("TrigLat"); + cfg->CMDcnt = lookupToUShort("CMDcnt"); + cfg->StopModeCnfg = lookupToUShort("StopModeCnfg"); + cfg->HitDiscCnfg = lookupToUShort("HitDiscCnfg"); + cfg->EN_PLL = lookupToUShort("EN_PLL"); + cfg->Efuse_sense = lookupToUShort("Efuse_sense"); + cfg->Stop_Clk = lookupToUShort("Stop_Clk"); + cfg->ReadErrorReq = lookupToUShort("ReadErrorReq"); + cfg->Reg27Spare1 = lookupToUShort("Reg27Spare1"); + cfg->GADC_Enable = lookupToUShort("GADC_Enable"); + cfg->ShiftReadBack = lookupToUShort("ShiftReadBack"); + cfg->Reg27Spare2 = lookupToUShort("Reg27Spare2"); + cfg->GateHitOr = lookupToUShort("GateHitOr"); + cfg->CalEn = lookupToUShort("CalEn"); + cfg->SR_clr = lookupToUShort("SR_clr"); + cfg->Latch_en = lookupToUShort("Latch_en"); + cfg->SR_Clock = lookupToUShort("SR_Clock"); + cfg->LVDSDrvSet06 = lookupToUShort("LVDSDrvSet06"); + cfg->Reg28Spare = lookupToUShort("Reg28Spare"); + cfg->EN40M = lookupToUShort("EN40M"); + cfg->EN80M = lookupToUShort("EN80M"); + //special case + cfg->CLK0 = lookupToUShort("CLK0_S2"); + cfg->CLK0 |= lookupToUShort("CLK0_S1")<<1; + cfg->CLK0 |= lookupToUShort("CLK0_S0")<<2; + cfg->CLK1 = lookupToUShort("CLK1_S2"); + cfg->CLK1 |= lookupToUShort("CLK1_S1")<<1; + cfg->CLK1 |= lookupToUShort("CLK1_S0")<<2; + + cfg->EN160M = lookupToUShort("EN160M"); + cfg->EN320M = lookupToUShort("EN320M"); + cfg->Reg29Spare1 = lookupToUShort("Reg29Spare1"); + cfg->no8b10b = lookupToUShort("no8b10b"); + cfg->Clk2OutCnfg = lookupToUShort("Clk2OutCnfg"); + cfg->EmptyRecord = lookupToUShort("EmptyRecord"); + cfg->Reg29Spare2 = lookupToUShort("Reg29Spare2"); + cfg->LVDSDrvEn = lookupToUShort("LVDSDrvEn"); + cfg->LVDSDrvSet30 = lookupToUShort("LVDSDrvSet30"); + cfg->LVDSDrvSet12 = lookupToUShort("LVDSDrvSet12"); + cfg->TempSensDiodeSel = lookupToUShort("TempSensDiodeSel"); + cfg->TempSensDisable = lookupToUShort("TempSensDisable"); + cfg->IleakRange = lookupToUShort("IleakRange"); + cfg->Reg30Spare = lookupToUShort("Reg30Spare"); + cfg->PlsrRiseUpTau = lookupToUShort("PlsrRiseUpTau"); + cfg->PlsrPwr = lookupToUShort("PlsrPwr"); + cfg->PlsrDelay = lookupToUShort("PlsrDelay"); + cfg->ExtDigCalSW = lookupToUShort("ExtDigCalSW"); + cfg->ExtAnaCalSW = lookupToUShort("ExtAnaCalSW"); + cfg->Reg31Spare = lookupToUShort("Reg31Spare"); + cfg->GADCSel = lookupToUShort("GADCSel"); + cfg->SELB0 = lookupToUShort("SELB0"); + cfg->SELB1 = lookupToUShort("SELB1"); + cfg->SELB2 = lookupToUShort("SELB2"); + cfg->Reg34Spare1 = lookupToUShort("Reg34Spare1"); + cfg->PrmpVbpMsnEn = lookupToUShort("PrmpVbpMsnEn"); + cfg->Reg34Spare2 = lookupToUShort("Reg34Spare2"); + cfg->Chip_SN = lookupToUShort("Chip_SN"); + cfg->Reg1Spare = lookupToUShort("Reg1Spare"); + cfg->SmallHitErase = lookupToUShort("SmallHitErase"); + cfg->Eventlimit = lookupToUShort("Eventlimit"); + + if((cfg->HitDiscCnfg==0 && cfg->SmallHitErase==0) + ||(cfg->HitDiscCnfg!=0 && cfg->SmallHitErase!=0)){ + std::cout<<"***WARNING: HitDiscCnfig="<<cfg->HitDiscCnfg<<" and SmallHitErase="<<cfg->SmallHitErase<<" on Chip with SN="<<cfg->Chip_SN<<"."<<std::endl; + } + // charge injection + config->FECalib.cinjLo=lookupToFloat("cinjLo"); + config->FECalib.cinjHi=lookupToFloat("cinjHi"); + config->FECalib.vcalCoeff[0]=lookupToFloat("vcalCoeff[0]"); + config->FECalib.vcalCoeff[1]=lookupToFloat("vcalCoeff[1]"); + config->FECalib.vcalCoeff[2]=lookupToFloat("vcalCoeff[2]"); + config->FECalib.vcalCoeff[3]=lookupToFloat("vcalCoeff[3]"); + config->FECalib.chargeCoeffClo=lookupToFloat("chargeCoeffClo"); + config->FECalib.chargeCoeffChi=lookupToFloat("chargeCoeffChi"); + config->FECalib.chargeOffsetClo=lookupToFloat("chargeOffsetClo"); + config->FECalib.chargeOffsetChi=lookupToFloat("chargeOffsetChi"); + config->FECalib.monleakCoeff=lookupToFloat("monleakCoeff"); + + //Pixel register + //Masks + setupMaskBit(ipc::enable, config, "enable"); + setupMaskBit(ipc::largeCap, config, "largeCap"); + setupMaskBit(ipc::smallCap, config, "smallCap"); + setupMaskBit(ipc::hitbus, config, "hitbus"); + + setupDAC(config->FETrims.dacThresholdTrim, "tdac"); + setupDAC(config->FETrims.dacFeedbackTrim, "fdac"); + delete m_moduleCfgFile; +} + +void FEI4BConfigFile::dump(const ipc::PixelFEI4BConfig &config){ + const ipc::PixelFEI4BGlobal* cfg=&config.FEGlobal; + std::cout<<"Global Register Fields:"<<std::endl; + std::cout<<"======================="<<std::endl; + std::cout<<"TrigCnt = "<<cfg->TrigCnt<<std::endl; + std::cout<<"Conf_AddrEnable = "<<cfg->Conf_AddrEnable<<std::endl; + std::cout<<"Reg2Spare = "<<cfg->Reg2Spare<<std::endl; + std::cout<<"ErrMask0 = "<<cfg->ErrMask0<<std::endl; + std::cout<<"ErrMask1 = "<<cfg->ErrMask1<<std::endl; + std::cout<<"PrmpVbpRight = "<<cfg->PrmpVbpRight<<std::endl; + std::cout<<"BufVgOpAmp = "<<cfg->BufVgOpAmp<<std::endl; + std::cout<<"Reg6Spare = "<<cfg->Reg6Spare<<std::endl; + std::cout<<"PrmpVbp = "<<cfg->PrmpVbp<<std::endl; + std::cout<<"TdacVbp = "<<cfg->TdacVbp<<std::endl; + std::cout<<"DisVbn = "<<cfg->DisVbn<<std::endl; + std::cout<<"Amp2Vbn = "<<cfg->Amp2Vbn<<std::endl; + std::cout<<"Amp2VbpFol = "<<cfg->Amp2VbpFol<<std::endl; + std::cout<<"Reg9Spare = "<<cfg->Reg9Spare<<std::endl; + std::cout<<"Amp2Vbp = "<<cfg->Amp2Vbp<<std::endl; + std::cout<<"FdacVbn = "<<cfg->FdacVbn<<std::endl; + std::cout<<"Amp2Vbpf = "<<cfg->Amp2Vbpf<<std::endl; + std::cout<<"PrmpVbnFol = "<<cfg->PrmpVbnFol<<std::endl; + std::cout<<"PrmpVbpLeft = "<<cfg->PrmpVbpLeft<<std::endl; + std::cout<<"PrmpVbpf = "<<cfg->PrmpVbpf<<std::endl; + std::cout<<"PrmpVbnLcc = "<<cfg->PrmpVbnLcc<<std::endl; + std::cout<<"Reg13Spare = "<<cfg->Reg13Spare<<std::endl; + std::cout<<"PxStrobes = "<<cfg->PxStrobes<<std::endl; + std::cout<<"S0 = "<<cfg->S0<<std::endl; + std::cout<<"S1 = "<<cfg->S1<<std::endl; + std::cout<<"LVDSDrvIref = "<<cfg->LVDSDrvIref<<std::endl; + std::cout<<"GADCOpAmp = "<<cfg->GADCOpAmp<<std::endl; + std::cout<<"PllIbias = "<<cfg->PllIbias<<std::endl; + std::cout<<"LVDSDrvVos = "<<cfg->LVDSDrvVos<<std::endl; + std::cout<<"TempSensBias = "<<cfg->TempSensBias<<std::endl; + std::cout<<"PllIcp = "<<cfg->PllIcp<<std::endl; + std::cout<<"Reg17Spare = "<<cfg->Reg17Spare<<std::endl; + std::cout<<"PlsrIdacRamp = "<<cfg->PlsrIdacRamp<<std::endl; + std::cout<<"VrefDigTune = "<<cfg->VrefDigTune<<std::endl; + std::cout<<"PlsrVgOPamp = "<<cfg->PlsrVgOPamp<<std::endl; + std::cout<<"PlsrDacBias = "<<cfg->PlsrDacBias<<std::endl; + std::cout<<"VrefAnTune = "<<cfg->VrefAnTune<<std::endl; + std::cout<<"Vthin_AltCoarse = "<<cfg->Vthin_AltCoarse<<std::endl; + std::cout<<"Vthin_AltFine = "<<cfg->Vthin_AltFine<<std::endl; + std::cout<<"PlsrDAC = "<<cfg->PlsrDAC<<std::endl; + std::cout<<"DIGHITIN_Sel = "<<cfg->DIGHITIN_Sel<<std::endl; + std::cout<<"DINJ_Override = "<<cfg->DINJ_Override<<std::endl; + std::cout<<"HITLD_In = "<<cfg->HITLD_In<<std::endl; + std::cout<<"Reg21Spare = "<<cfg->Reg21Spare<<std::endl; + std::cout<<"Reg22Spare2 = "<<cfg->Reg22Spare2<<std::endl; + std::cout<<"Colpr_Addr = "<<cfg->Colpr_Addr<<std::endl; + std::cout<<"Colpr_Mode = "<<cfg->Colpr_Mode<<std::endl; + std::cout<<"Reg22Spare1 = "<<cfg->Reg22Spare2<<std::endl; + std::cout<<"DisableColumnCnfg0 = "<<cfg->DisableColumnCnfg0<<std::endl; + std::cout<<"DisableColumnCnfg1 = "<<cfg->DisableColumnCnfg1<<std::endl; + std::cout<<"DisableColumnCnfg2 = "<<cfg->DisableColumnCnfg2<<std::endl; + std::cout<<"TrigLat = "<<cfg->TrigLat<<std::endl; + std::cout<<"CMDcnt = "<<cfg->CMDcnt<<std::endl; + std::cout<<"StopModeCnfg = "<<cfg->StopModeCnfg<<std::endl; + std::cout<<"HitDiscCnfg = "<<cfg->HitDiscCnfg<<std::endl; + std::cout<<"EN_PLL = "<<cfg->EN_PLL<<std::endl; + std::cout<<"Efuse_sense = "<<cfg->Efuse_sense<<std::endl; + std::cout<<"Stop_Clk = "<<cfg->Stop_Clk<<std::endl; + std::cout<<"ReadErrorReq = "<<cfg->ReadErrorReq<<std::endl; + std::cout<<"Reg27Spare1 = "<<cfg->Reg27Spare1<<std::endl; + std::cout<<"GADC_Enable = "<<cfg->GADC_Enable<<std::endl; + std::cout<<"ShiftReadBack = "<<cfg->ShiftReadBack<<std::endl; + std::cout<<"Reg27Spare2 = "<<cfg->Reg27Spare2<<std::endl; + std::cout<<"GateHitOr = "<<cfg->GateHitOr<<std::endl; + std::cout<<"CalEn = "<<cfg->CalEn<<std::endl; + std::cout<<"SR_clr = "<<cfg->SR_clr<<std::endl; + std::cout<<"Latch_en = "<<cfg->Latch_en<<std::endl; + std::cout<<"SR_Clock = "<<cfg->SR_Clock<<std::endl; + std::cout<<"LVDSDrvSet06 = "<<cfg->LVDSDrvSet06<<std::endl; + std::cout<<"Reg28Spare = "<<cfg->Reg28Spare<<std::endl; + std::cout<<"EN40M = "<<cfg->EN40M<<std::endl; + std::cout<<"EN80M = "<<cfg->EN80M<<std::endl; + std::cout<<"CLK1 = "<<cfg->CLK1<<std::endl; + std::cout<<"CLK0 = "<<cfg->CLK0<<std::endl; + std::cout<<"EN160M = "<<cfg->EN160M<<std::endl; + std::cout<<"EN320M = "<<cfg->EN320M<<std::endl; + std::cout<<"Reg29Spare1 = "<<cfg->Reg29Spare1<<std::endl; + std::cout<<"no8b10b = "<<cfg->no8b10b<<std::endl; + std::cout<<"Clk2OutCnfg = "<<cfg->Clk2OutCnfg<<std::endl; + std::cout<<"EmptyRecord = "<<cfg->EmptyRecord<<std::endl; + std::cout<<"Reg29Spare2 = "<<cfg->Reg29Spare2<<std::endl; + std::cout<<"LVDSDrvEn = "<<cfg->LVDSDrvEn<<std::endl; + std::cout<<"LVDSDrvSet30 = "<<cfg->LVDSDrvSet30<<std::endl; + std::cout<<"LVDSDrvSet12 = "<<cfg->LVDSDrvSet12<<std::endl; + std::cout<<"TempSensDiodeSel = "<<cfg->TempSensDiodeSel<<std::endl; + std::cout<<"TempSensDisable = "<<cfg->TempSensDisable<<std::endl; + std::cout<<"IleakRange = "<<cfg->IleakRange<<std::endl; + std::cout<<"PlsrRiseUpTau = "<<cfg->PlsrRiseUpTau<<std::endl; + std::cout<<"PlsrPwr = "<<cfg->PlsrPwr<<std::endl; + std::cout<<"PlsrDelay = "<<cfg->PlsrDelay<<std::endl; + std::cout<<"ExtDigCalSW = "<<cfg->ExtDigCalSW<<std::endl; + std::cout<<"ExtAnaCalSW = "<<cfg->ExtAnaCalSW<<std::endl; + std::cout<<"Reg31Spare = "<<cfg->Reg31Spare<<std::endl; + std::cout<<"SELB0 = "<<cfg->SELB0<<std::endl; + std::cout<<"SELB1 = "<<cfg->SELB1<<std::endl; + std::cout<<"SELB2 = "<<cfg->SELB2<<std::endl; + std::cout<<"Reg34Spare1 = "<<cfg->Reg34Spare1<<std::endl; + std::cout<<"PrmpVbpMsnEn = "<<cfg->PrmpVbpMsnEn<<std::endl; + std::cout<<"Reg34Spare2 = "<<cfg->Reg34Spare2<<std::endl; + std::cout<<"Chip_SN = "<<cfg->Chip_SN<<std::endl; + std::cout<<"Reg1Spare = "<<cfg->Reg1Spare<<std::endl; + std::cout<<"SmallHitErase = "<<cfg->SmallHitErase<<std::endl; + std::cout<<"Eventlimit = "<<cfg->Eventlimit<<std::endl; + // charge injection + std::cout<<std::endl; + std::cout<<"Charge injection parameters:"<<std::endl; + std::cout<<"============================"<<std::endl; + std::cout<<"cinjLo = "<<config.FECalib.cinjLo<<std::endl; + std::cout<<"cinjHi = "<<config.FECalib.cinjHi<<std::endl; + std::cout<<"vcalCoeff[0] = "<<config.FECalib.vcalCoeff[0]<<std::endl; + std::cout<<"vcalCoeff[1] = "<<config.FECalib.vcalCoeff[1]<<std::endl; + std::cout<<"vcalCoeff[2] = "<<config.FECalib.vcalCoeff[2]<<std::endl; + std::cout<<"vcalCoeff[3] = "<<config.FECalib.vcalCoeff[3]<<std::endl; + std::cout<<"chargeCoeffClo = "<<config.FECalib.chargeCoeffClo<<std::endl; + std::cout<<"chargeCoeffChi = "<<config.FECalib.chargeCoeffChi<<std::endl; + std::cout<<"chargeOffsetClo = "<<config.FECalib.chargeOffsetClo<<std::endl; + std::cout<<"chargeOffsetChi = "<<config.FECalib.chargeOffsetChi<<std::endl; + std::cout<<"monleakCoeff = "<<config.FECalib.monleakCoeff<<std::endl; + + //DACs + std::cout<<"Threshold DAC:"<<std::endl; + std::cout<<"--------------"<<std::endl; + dumpDac(config.FETrims.dacThresholdTrim); + std::cout<<"Feedback DAC:"<<std::endl; + std::cout<<"-------------"<<std::endl; + dumpDac(config.FETrims.dacFeedbackTrim); + + //Masks + std::cout<<"Enable Mask:"<<std::endl; + std::cout<<"------------"<<std::endl; + dumpMask(ipc::enable, config); + std::cout<<"Large Cap Mask:"<<std::endl; + std::cout<<"---------------"<<std::endl; + dumpMask(ipc::largeCap, config); + std::cout<<"Small Cap Mask:"<<std::endl; + std::cout<<"---------------"<<std::endl; + dumpMask(ipc::smallCap, config); + std::cout<<"Hitbus Mask:"<<std::endl; + std::cout<<"------------"<<std::endl; + dumpMask(ipc::hitbus, config); + +} + +void FEI4BConfigFile::dumpDac(const unsigned char trim[][ipc::IPC_N_I4_PIXEL_ROWS]){ + std::cout<<(unsigned)trim[0][0]<<" "<<(unsigned)trim[79][335]<<std::endl; + for (int i=0;i<674;i++){ + if(i>1){ + printf("%3d",i/2); + if(i%2==0)std::cout<<"a "; + else std::cout<<"b "; + }else{ + std::cout<<"### "; + } + for (int j=1;j<=40;j++){ + if(i<2){ + if(i==0)printf("%2d ",j); + else printf("%2d ",j+40); + }else{ + if(i%2==0)printf("%2d ",trim[j-1][i/2-1]); + else printf("%2d ",trim[j+39][i/2-1]); + } + if(j%10==0)std::cout<<" "; + } + std::cout<<std::endl; + } + std::cout<<std::endl; + } + + void FEI4BConfigFile::dumpMask(const long int bit, const ipc::PixelFEI4BConfig& cfg){ + + for (int i=0;i<=336;i++){ + if(i==0){ + std::cout<<"### 1 6 11 16 21 26 31 36 41 46 51 56 61 66 71 76"<<std::endl; + } + else{ + printf("%3d ",i); + for (int j=1;j<=80;j++){ + printf("%1d",(cfg.FEMasks[j-1][i-1]>>bit)&0x1); + if(j%10==0)std::cout<<" "; + else if(j%5==0)std::cout<<"-"; + } + std::cout<<std::endl; + } + } + std::cout<<std::endl; + } diff --git a/rce/rcecalib/server/FEI4BConfigFile.hh b/rce/rcecalib/server/FEI4BConfigFile.hh new file mode 100644 index 00000000..ad1b4c6c --- /dev/null +++ b/rce/rcecalib/server/FEI4BConfigFile.hh @@ -0,0 +1,32 @@ +#ifndef FEI4BCONFIGFILE_HH +#define FEI4BCONFIGFILE_HH + +#include "PixelFEI4BConfig.hh" +#include <string> +#include <map> + +class FEI4BConfigFile { +public: + FEI4BConfigFile(){} + ~FEI4BConfigFile(); + void readModuleConfig(ipc::PixelFEI4BConfig* cfg, std::string filename); + void writeModuleConfig(ipc::PixelFEI4BConfig* cfg, const std::string &base, const std::string &confdir, const std::string &configname, const std::string &key); + void writeMaskFile(const long int bit, ipc::PixelFEI4BConfig* config, const std::string &filename); + void writeDacFile(unsigned char trim[][ipc::IPC_N_I4_PIXEL_ROWS] , const std::string filename); + void dump(const ipc::PixelFEI4BConfig& cfg); +private: + std::string getFullPath(std::string relPath); + void setupDAC(unsigned char trim[][ipc::IPC_N_I4_PIXEL_ROWS] , std::string par); + void setupMaskBit(const long int bit, ipc::PixelFEI4BConfig *cfg, std::string par); + void dumpMask(const long int bit, const ipc::PixelFEI4BConfig& cfg); + unsigned short lookupToUShort(std::string par); + int convertToUShort(std::string par, unsigned short& val); + float lookupToFloat(std::string par); + void dumpDac(const unsigned char trim[][ipc::IPC_N_I4_PIXEL_ROWS]); + + std::string m_moduleCfgFilePath; + std::ifstream *m_moduleCfgFile; + std::map<std::string, std::string> m_params; +}; + +#endif diff --git a/rce/rcecalib/server/GlobalConfigGui.cc b/rce/rcecalib/server/GlobalConfigGui.cc new file mode 100644 index 00000000..e37c100c --- /dev/null +++ b/rce/rcecalib/server/GlobalConfigGui.cc @@ -0,0 +1,560 @@ +#include "rcecalib/server/GlobalConfigGui.hh" +#include "rcecalib/server/FEI4AConfigFile.hh" +#include "rcecalib/server/FEI4BConfigFile.hh" +#include "rcecalib/server/TurboDaqFile.hh" +#include "rcecalib/server/HitbusConfigFile.hh" +#include "PixelFEI4AConfig.hh" +#include "PixelFEI4BConfig.hh" +#include "PixelModuleConfig.hh" +#include "rcecalib/server/ConfigGui.hh" +#include <TGFileDialog.h> +#include <iostream> +#include <boost/regex.hpp> +#include <sys/stat.h> +#include <sstream> +#ifdef SQLDB +#include <mysql.h> +#endif + +GlobalConfigGui::GlobalConfigGui(ConfigGui* cg[], const char* dffile, const TGWindow *p, UInt_t w, UInt_t h, UInt_t options): + TGVerticalFrame(p,w,h,options), m_config(cg), m_defaultfile(dffile){ + + m_name=new TGLabel(this,"Global Module Configuration"); + AddFrame(m_name,new TGLayoutHints(kLHintsCenterX|kLHintsTop, 2, 2, 10, 0)); + FontStruct_t labelfont; + labelfont = gClient->GetFontByName("-adobe-helvetica-medium-r-*-*-18-*-*-*-*-*-iso8859-1"); + m_name->SetTextFont(labelfont); + + TGHorizontalFrame *conf0 = new TGHorizontalFrame(this, 2,2 ); + AddFrame(conf0,new TGLayoutHints(kLHintsExpandX )); + labelfont = gClient->GetFontByName("-adobe-helvetica-medium-r-*-*-14-*-*-*-*-*-iso8859-1"); + m_update=new TGTextButton(conf0,"Update"); + m_update->SetFont(labelfont); + m_update->SetMargins(5,10,5,5); + m_update->Connect("Clicked()", "GlobalConfigGui", this,"update()"); + conf0->AddFrame(m_update,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + TGTextButton *sd=new TGTextButton(conf0,"Save"); + sd->Connect("Clicked()", "GlobalConfigGui", this,"saveDefault()"); + sd->SetFont(labelfont); + sd->SetMargins(5,10,5,5); + conf0->AddFrame(sd,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + m_save=new TGTextButton(conf0,"Save As"); + m_save->Connect("Clicked()", "GlobalConfigGui", this,"save()"); + m_save->SetFont(labelfont); + m_save->SetMargins(5,10,5,5); + conf0->AddFrame(m_save,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + m_load=new TGTextButton(conf0,"Load"); + m_load->Connect("Clicked()", "GlobalConfigGui", this,"load()"); + m_load->SetFont(labelfont); + m_load->SetMargins(5,10,5,5); + conf0->AddFrame(m_load,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + TGLabel *masklabel=new TGLabel(conf0,"Config Name:"); + FontStruct_t maskfont= gClient->GetFontByName("-adobe-helvetica-bold-r-*-*-12-*-*-*-*-*-iso8859-1"); + masklabel->SetTextFont(maskfont); + conf0->AddFrame(masklabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + m_name=new TGLabel(conf0," "); + conf0->AddFrame(m_name,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + masklabel=new TGLabel(conf0,"Key:"); + masklabel->SetTextFont(maskfont); + conf0->AddFrame(masklabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 10, 2, 2, 0)); + m_key=new TGLabel(conf0," "); + conf0->AddFrame(m_key,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + + // Config directory + + FontStruct_t clabelfont = gClient->GetFontByName("-adobe-helvetica-medium-r-*-*-18-*-*-*-*-*-iso8859-1"); + FontStruct_t cmaskfont= gClient->GetFontByName("-adobe-helvetica-bold-r-*-*-12-*-*-*-*-*-iso8859-1"); + m_conf1 = new TGHorizontalFrame(this, 2,2 ); + AddFrame(m_conf1,new TGLayoutHints(kLHintsExpandX )); + TGLabel *ddlabel=new TGLabel(m_conf1,"Config Root Dir:"); + m_conf1->AddFrame(ddlabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 10, 2, 10, 0)); + ddlabel->SetTextFont(clabelfont); + m_rootdirl=new TGLabel(m_conf1, " "); + m_rootdirl->SetTextFont(cmaskfont); + m_conf1->AddFrame(m_rootdirl,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 10, 2, 10, 0)); + TGTextButton *lddd=new TGTextButton(m_conf1,"Browse"); + lddd->Connect("Clicked()", "GlobalConfigGui", this,"guiSetRootDir()"); + lddd->SetFont(clabelfont); + lddd->SetMargins(10,15,3,3); + m_conf1->AddFrame(lddd,new TGLayoutHints(kLHintsCenterY | kLHintsRight ,2,2,5,5)); + TGTextButton *absp=new TGTextButton(m_conf1,"Abs Path"); + absp->Connect("Clicked()", "GlobalConfigGui", this,"setAbsPath()"); + absp->SetFont(clabelfont); + absp->SetMargins(10,15,3,3); + m_conf1->AddFrame(absp,new TGLayoutHints(kLHintsCenterY | kLHintsRight ,2,2,5,5)); + + // Data directory + + m_conf2 = new TGHorizontalFrame(this, 2,2 ); + AddFrame(m_conf2,new TGLayoutHints(kLHintsExpandX )); + ddlabel=new TGLabel(m_conf2,"Data Dir:"); + m_conf2->AddFrame(ddlabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 10, 2, 10, 0)); + ddlabel->SetTextFont(clabelfont); + m_datadir=new TGLabel(m_conf2, " "); + m_datadir->SetTextFont(cmaskfont); + m_conf2->AddFrame(m_datadir,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 10, 2, 10, 0)); + lddd=new TGTextButton(m_conf2,"Browse"); + lddd->Connect("Clicked()", "GlobalConfigGui", this,"guiSetDataDir()"); + lddd->SetFont(clabelfont); + lddd->SetMargins(10,15,3, 3); + m_conf2->AddFrame(lddd,new TGLayoutHints(kLHintsCenterY | kLHintsRight ,2,2,5,5)); + + // Run Number + TGHorizontalFrame *datapanel2 = new TGHorizontalFrame(this, 2, 2, kSunkenFrame); + AddFrame(datapanel2,new TGLayoutHints(kLHintsExpandX )); + TGLabel *runlabel=new TGLabel(datapanel2,"Run Number:"); + runlabel->SetTextFont(clabelfont); + datapanel2->AddFrame(runlabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 10, 2, 10, 0)); + FontStruct_t labelfont2; + labelfont2 = gClient->GetFontByName("-adobe-helvetica-medium-r-*-*-24-*-*-*-*-*-iso8859-1"); + m_runno=new TGNumberEntry(datapanel2,0,5,-1,TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative); + m_runno->GetNumberEntry()->SetFont(labelfont2); + m_runno->SetHeight(30); + m_runno->SetWidth(140); + //reset RunNum if SQLDB +#ifdef SQLDB + m_runno->SetIntNumber(maxRunNum()); + m_runno->SetState(false); +#endif + // m_name->Connect("TextChanged(const char*)", "CalibGui", this,"setName(const char*)"); + datapanel2->AddFrame(m_runno,new TGLayoutHints(kLHintsCenterY |kLHintsCenterX, 5, 5, 5, 5)); + + gClient->GetColorByName("red", m_red); + m_homedir=std::string(getenv("HOME")); + +} + + +GlobalConfigGui::~GlobalConfigGui(){ + Cleanup(); +} + +void GlobalConfigGui::guiSetDataDir(){ + std::string dirs=setDir(); + if(dirs!="")setDataDir(dirs.c_str()); +} + +void GlobalConfigGui::setDataDir(const char* dd){ + m_datadir->SetText(dd); + m_conf2->Layout(); + m_ddir=dd; +} + +void GlobalConfigGui::updateText(TGLabel* label, const char* newtext){ + //unsigned len=strlen(label->GetText()->GetString()); + label->SetText(newtext); + //if (strlen(newtext)>len)Layout(); + Layout(); +} + +void GlobalConfigGui::enableControls(bool on){ + #ifndef SQLDB + m_runno->SetState(on); + #endif + m_save->SetEnabled(on); + m_load->SetEnabled(on); + m_update->SetEnabled(on); +} + +void GlobalConfigGui::print(std::ostream &os){ +} + +void GlobalConfigGui::updateAvailable(bool on){ + if(on)m_update->SetTextColor(m_red); + else m_update->SetTextColor(0); + m_upd=on; + Layout(); +} + +void GlobalConfigGui::save(){ + const char *filetypes[] = { "Config files", "*.cfg", + "All files", "*", + 0, 0 }; + bool sth=false; + for(int i=0;i<ConfigGui::MAX_MODULES;i++)if(m_config[i]->isIncluded())sth=true; + if(sth==false){ + std::cout<<"Nothing to save."<<std::endl; + return; + } + TGFileInfo fileinfo; + if(m_path!="") + fileinfo.fIniDir=StrDup(m_path.c_str()); + else + fileinfo.fIniDir=StrDup(m_rootdir.c_str()); + fileinfo.fFileTypes = filetypes; + fileinfo.fFilename=0; + char newconfigname[512]; + std::string oldname=m_name->GetText()->Data(); + if(oldname!=" " && oldname!="Unknown"){ + sprintf(newconfigname, "%s__%d.cfg", oldname.c_str(),getRunNumber()); + fileinfo.fFilename=StrDup(newconfigname); + } + new TGFileDialog(gClient->GetRoot(), 0, kFDSave, &fileinfo); + if(!fileinfo.fFilename){ + printf("Scheisse\n"); + return; + } + m_filename=fileinfo.fFilename; + if(m_filename.size()<4 || m_filename.substr(m_filename.size()-4,4)!=".cfg")m_filename+=".cfg"; + setupDisplay(); + saveConfig(); +} +void GlobalConfigGui::saveConfig(){ + copyConfig(m_filename.c_str()); +} +void GlobalConfigGui::copyConfig(const char *filename){ + std::ofstream of(filename); + for(int i=0;i<ConfigGui::MAX_MODULES;i++){ + m_config[i]->writeConfig(of); + } +} + + + +void GlobalConfigGui::load(){ + const char *filetypes[] = { "Config files", "*.cfg", + "All files", "*", + 0, 0 }; + TGFileInfo fileinfo; + if(std::string(m_name->GetText()->Data())!="Default" && m_path!="") + fileinfo.fIniDir=StrDup(m_path.c_str()); + else + fileinfo.fIniDir=StrDup(m_rootdir.c_str()); + fileinfo.fFileTypes = filetypes; + fileinfo.fFilename=StrDup(m_cfgpluskey.c_str()); + new TGFileDialog(gClient->GetRoot(), 0, kFDOpen, &fileinfo); + if(!fileinfo.fFilename){ + printf("Scheisse\n"); + return; + } + m_filename=fileinfo.fFilename; + setupDisplay(); + loadConfig(); +} + +void GlobalConfigGui::load(const char* filename){ + m_filename=filename; + setupDisplay(); + loadConfig(); +} + +void GlobalConfigGui::loadConfig(){ + // Attempt to get the file attributes + struct stat stFileInfo; + int intStat; + intStat = stat(m_filename.c_str(),&stFileInfo); + if(intStat != 0) { //File does not exist} + m_filename="None"; + setupDisplay(); + return; + } + std::ifstream cfgFile(m_filename.c_str()); + std::string filename; + for(int i=0;i<ConfigGui::MAX_MODULES;i++){ + m_config[i]->readConfig(cfgFile); + } +} + +void GlobalConfigGui::update(){ + if(m_upd==false)return; + // Attempt to get the file attributes + struct stat stFileInfo; + int intStat; + char fname[512]; + sprintf(fname, "%stop/config__%d.cfg", m_configdir.c_str(), getRunNumber()); + intStat = stat(fname,&stFileInfo); + if(intStat != 0) { //File does not exist} + std::cout<<"There is no top level config file for this run."<<std::endl; + return; + } + const char *filetypes[] = { "Config files", "*.cfg", + "All files", "*", + 0, 0 }; + std::string oldname=m_name->GetText()->Data(); + if(oldname!=" " && oldname!="Unknown") + { + m_filename=m_path+oldname+Form("__%d.cfg",getRunNumber()); + } + else{ + TGFileInfo fileinfo; + fileinfo.fIniDir=StrDup(m_rootdir.c_str()); + fileinfo.fFileTypes = filetypes; + fileinfo.fFilename=0; + new TGFileDialog(gClient->GetRoot(), 0, kFDSave, &fileinfo); + if(!fileinfo.fFilename){ + printf("Scheisse\n"); + return; + } + m_filename=fileinfo.fFilename; + if(m_filename.size()<4 || m_filename.substr(m_filename.size()-4,4)!=".cfg")m_filename+=".cfg"; + } + updateAvailable(false); + setupDisplay(); + std::ifstream oldfile(fname); + std::ofstream newfile(m_filename.c_str()); + int chan; + std::string filename, oldfilename, oldfilenamenopath; + int ind=0; + while (oldfile.good()){ + oldfile>>oldfilenamenopath; + if(oldfilenamenopath[0]!='/')oldfilename=m_rootdir+oldfilenamenopath; //relative path + else oldfilename=oldfilenamenopath; + filename=oldfilename; + if(oldfile.eof())break; + boost::regex re("configUpdate"); + bool docopy=false; + std::string path=m_config[ind]->getPath(); + if(path.substr(0,m_rootdir.size())==m_rootdir)path=path.substr(m_rootdir.size()); + if(boost::regex_search(filename.c_str(), re)){ + filename.replace(0,m_configdir.size(), path); + docopy=true; + newfile<<filename<<std::endl; + }else{ + newfile<<oldfilenamenopath<<std::endl; + } + for(int i=0;i<5;i++){ + oldfile>>chan; + newfile<<chan<<std::endl; + } + if(docopy==true){ + if(m_config[ind]->getType()=="FEI3"){ + ipc::PixelModuleConfig* cf=new ipc::PixelModuleConfig; + TurboDaqFile turbodaqfile; + turbodaqfile.readModuleConfig(cf, oldfilename); + char key[32]; + sprintf(key, "%d", getRunNumber()); + turbodaqfile.writeModuleConfig(cf, m_config[ind]->getPath(), + m_config[ind]->getConfdir(), + m_config[ind]->getConfigName(), + key); + delete cf; + }else if(m_config[ind]->getType()=="FEI4A"){ + ipc::PixelFEI4AConfig* cf=new ipc::PixelFEI4AConfig; + FEI4AConfigFile fei4afile; + fei4afile.readModuleConfig(cf, oldfilename); + char key[32]; + sprintf(key, "%d", getRunNumber()); + fei4afile.writeModuleConfig(cf, m_config[ind]->getPath(), + m_config[ind]->getConfdir(), + m_config[ind]->getConfigName(), + key); + delete cf; + }else if(m_config[ind]->getType()=="FEI4B"){ + ipc::PixelFEI4BConfig* cf=new ipc::PixelFEI4BConfig; + FEI4BConfigFile fei4bfile; + fei4bfile.readModuleConfig(cf, oldfilename); + char key[32]; + sprintf(key, "%d", getRunNumber()); + fei4bfile.writeModuleConfig(cf, m_config[ind]->getPath(), + m_config[ind]->getConfdir(), + m_config[ind]->getConfigName(), + key); + delete cf; + }else if(m_config[ind]->getType()=="Hitbus"){ + ipc::HitbusModuleConfig* cf=new ipc::HitbusModuleConfig; + HitbusConfigFile hitbusfile; + hitbusfile.readModuleConfig(cf, oldfilename); + char key[32]; + sprintf(key, "%d", getRunNumber()); + hitbusfile.writeModuleConfig(cf, m_config[ind]->getPath(), + m_config[ind]->getConfdir(), + m_config[ind]->getConfigName(), + key); + delete cf; + } + + + } + ind++; + } + newfile.close(); + loadConfig(); +} + +void GlobalConfigGui::setConfigDir(const char* name){ + m_configdir=name; + mkdir((m_configdir+"top").c_str(), 0777); +} + +void GlobalConfigGui::saveDefault(){ + std::ofstream of((m_homedir+m_defaultfile).c_str()); + writeGuiConfig(of); + of.close(); +} + +void GlobalConfigGui::writeGuiConfig(std::ofstream &ofile){ + if(m_filename=="None") + m_filename=std::string(getenv("HOME"))+"/"+"Default.cfg"; + ofile<<getRunNumber()<<std::endl; + ofile<<m_filename<<std::endl; + ofile<<m_ddir<<std::endl; + ofile<<m_rootdir<<std::endl; + saveConfig(); +} + +void GlobalConfigGui::readGuiConfig(std::ifstream &ifile){ + int runno; + ifile>>runno; + setRunNumber(runno); + std::string filename; + ifile>>m_filename; + std::string datadir; + ifile>>datadir; + if(datadir=="")datadir=m_homedir+"/calibData"; + setDataDir(datadir.c_str()); + std::string configdir; + ifile>>configdir; + setRootDir(configdir.c_str()); + setupDisplay(); + loadConfig(); +} + +void GlobalConfigGui::setupDisplay(){ + boost::cmatch matches; + //std::string res="/([^/]*)\\.cfg$"; // parse what's hopefully the config file name + boost::regex re; + std::string res("(^.*\\/)(.+)\\.cfg$"); + re=res; + if(boost::regex_search(m_filename.c_str(), matches, re)){ + if(matches.size()>2){ + m_path=std::string(matches[1].first, matches[1].second); + m_cfgpluskey=std::string(matches[2].first, matches[2].second); + res="(.*)__([0-9]+)$"; // parse what's hopefully the key + re=res; + if(boost::regex_search(m_cfgpluskey.c_str(), matches, re)){ + if(matches.size()>2){ + std::string match1(matches[1].first, matches[1].second); + std::string match2(matches[2].first, matches[2].second); + updateText(m_name,match1.c_str()); + updateText(m_key,match2.c_str()); + }else{ + updateText(m_name,m_cfgpluskey.c_str()); + updateText(m_key,""); + } + }else{ + updateText(m_name,m_cfgpluskey.c_str()); + updateText(m_key,""); + } + }else{ + updateText(m_name,"Unknown"); + updateText(m_key,"Unknown"); + m_path=""; + } + }else{ + updateText(m_name,"Unknown"); + updateText(m_key,"Unknown"); + m_path=""; + } +} +void GlobalConfigGui::filePrompt()//Prompt for name of config file +{ + const char *filetypes[] = { "Config files", "*.cfg", + "All files", "*", + 0, 0 }; + TGFileInfo fileinfo; + fileinfo.fIniDir=0; + fileinfo.fFileTypes = filetypes; + fileinfo.fFilename=0; + new TGFileDialog(gClient->GetRoot(), 0, kFDSave, &fileinfo); + m_filename=fileinfo.fFilename; + if(m_filename.size()<4 || m_filename.substr(m_filename.size()-4,4)!=".cfg")m_filename+=".cfg"; + setupDisplay(); + std::cout << "File name " << m_filename << std::endl; +} +bool GlobalConfigGui::oldFileLoaded() +{ + std::string oldname=m_name->GetText()->Data(); + + return oldname!=" " && oldname!="Unknown"; +} + +std::string GlobalConfigGui::setDir(){ + const char *filetypes[] = { "Directory", "*/", 0, 0 }; + TGFileInfo fileinfo; + fileinfo.fIniDir=0; + //fileinfo.fIniDir=StrDup(m_path.c_str()); + fileinfo.fFileTypes = filetypes; + //fileinfo.fFilename=StrDup(m_cfgpluskey.c_str()); + fileinfo.fFilename=0; + new TGFileDialog(gClient->GetRoot(), 0, kFDOpen, &fileinfo); + if(!fileinfo.fFilename){ + printf("Scheisse\n"); + return ""; + } + std::string datadir; + struct stat stFileInfo; + int intStat; + // Root TGFileinfo is a mess, have to try multiple options + intStat = stat(fileinfo.fFilename,&stFileInfo); + if(intStat != 0) { //File does not exist + intStat = stat(fileinfo.fIniDir,&stFileInfo); + if(intStat !=0) { // File does not exist + std::cout<<"Directory does not exist"<<std::endl; + }else{ + datadir=fileinfo.fIniDir; + } + }else{ + datadir=fileinfo.fFilename; + } + return datadir; +} + +void GlobalConfigGui::guiSetRootDir(){ + std::string dirs=setDir(); + if(dirs!="") setRootDir(dirs.c_str()); +} + + +void GlobalConfigGui::setRootDir(const char* dd){ + m_rootdirl->SetText(dd); + m_conf1->Layout(); + m_rootdir=dd; + if(m_rootdir.size()>0 && m_rootdir[m_rootdir.size()-1]!='/')m_rootdir+="/"; + m_config[0]->setRootDir(m_rootdir); //static function +} +void GlobalConfigGui::setAbsPath(){ + m_rootdirl->SetText(""); + m_conf1->Layout(); + m_rootdir=""; + m_config[0]->setRootDir(m_rootdir); //static function +} + +// Does not increment anymore, increment is happening in maxRunNum +// just being lazy +int GlobalConfigGui::incrementRunNumber(){ + int newrunno=maxRunNum(); + m_runno->SetIntNumber(newrunno); + return newrunno; +} + +int GlobalConfigGui::maxRunNum() +{ + #ifdef SQLDB + MYSQL *conn; + MYSQL_RES *result; + MYSQL_ROW row; + conn = mysql_init(NULL); + std::string dbName="RCECalibRuns"; + #ifdef SQLDEBUG + dbName="RCECalibRunsDev"; + #endif + if(mysql_real_connect(conn, "pixiblsr1daq1", "DBWriter", "W#1ter", dbName.c_str(), 0, NULL, 0)==NULL) + { + + std::cout << "SQL connection to " << dbName << " failed!! Nothing will be inserted!" <<std::endl; + //m_primList->updateStatus("Failed to connect to SQL database!"); + return m_runno->GetIntNumber(); + } + //mysql_query(conn, "SELECT max(RunNum) FROM CalibRunLog"); + mysql_query(conn, "INSERT INTO CalibRunLog (RunNum) VALUES(NULL);"); + mysql_query(conn, "SELECT LAST_INSERT_ID();"); + result = mysql_store_result(conn); + row= mysql_fetch_row(result); + int maxNum; + std::stringstream(row[0]) >> maxNum; + mysql_free_result(result); + mysql_close(conn); + return maxNum; + #endif + return m_runno->GetIntNumber()+1; +} diff --git a/rce/rcecalib/server/GlobalConfigGui.hh b/rce/rcecalib/server/GlobalConfigGui.hh new file mode 100644 index 00000000..03e85d79 --- /dev/null +++ b/rce/rcecalib/server/GlobalConfigGui.hh @@ -0,0 +1,71 @@ +#ifndef GLOBALCONFIGGUI_HH +#define GLOBALCONFIGGUI_HH + +#include <TGButton.h> +#include <TGTextEntry.h> +#include <TGLabel.h> +#include <TGComboBox.h> +#include <fstream> +#include <string> +#include <map> +#include "TGNumberEntry.h" + +class ConfigGui; + +class GlobalConfigGui: public TGVerticalFrame{ +public: + GlobalConfigGui(ConfigGui* cfg[], const char* filename, const TGWindow *p, UInt_t w, UInt_t h, UInt_t options); + virtual ~GlobalConfigGui(); + void print(std::ostream &os); + void enableControls(bool on); + void updateAvailable(bool on); + void save(); + void saveConfig(); + void copyConfig(const char* filename); + void saveDefault(); + void load(); + void load(const char* filename); + void loadConfig(); + void update(); + void setupDisplay(); + void readGuiConfig(std::ifstream &in); + void writeGuiConfig(std::ofstream &out); + void setConfigDir(const char* name); + void filePrompt(); + bool oldFileLoaded(); + std::string setDir(); + void setRootDir(const char* dd); + void guiSetRootDir(); + void setAbsPath(); + std::string getConfigName(){ return m_cfgpluskey; } + const char* getDataDir(){return m_ddir.c_str();} + void setDataDir(const char* dd); + void guiSetDataDir(); + int getRunNumber(){return m_runno->GetIntNumber();} + void setRunNumber(int runno){m_runno->SetIntNumber(runno);} + int incrementRunNumber(); +private: + int maxRunNum(); + TGLabel *m_name; + TGLabel *m_key; + TGLabel *m_rootdirl; + TGLabel *m_datadir; + TGNumberEntry *m_runno; + TGTextButton *m_update, *m_save, *m_load; + TGHorizontalFrame *m_conf1, *m_conf2; + ConfigGui **m_config; + bool m_upd; + std::string m_filename; + std::string m_configdir; + std::string m_path; + std::string m_cfgpluskey; + std::string m_homedir; + std::string m_rootdir; + std::string m_ddir; + std::string m_defaultfile; + Pixel_t m_red; + void updateText(TGLabel* label, const char* newtext); + ClassDef(GlobalConfigGui,0); +}; + +#endif diff --git a/rce/rcecalib/server/HitbusConfigFile.cc b/rce/rcecalib/server/HitbusConfigFile.cc new file mode 100644 index 00000000..b5f6df0a --- /dev/null +++ b/rce/rcecalib/server/HitbusConfigFile.cc @@ -0,0 +1,146 @@ +#include "rcecalib/server/HitbusConfigFile.hh" +#include "rcecalib/util/exceptions.hh" +#include <boost/algorithm/string.hpp> +#include <iostream> +#include <fstream> +#include <vector> +#include <sys/stat.h> + +HitbusConfigFile::~HitbusConfigFile(){} + +unsigned short HitbusConfigFile::lookupToUShort(std::string par){ + if( m_params.find(par)==m_params.end()){ + std::cout<<"Parameter "<<par<<" does not exist."<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + std::string vals=m_params[par]; + unsigned short val; + int success=convertToUShort(vals, val); + if(success==false){ + std::cout<<"Bad value "<<vals<< " for parameter "<<par<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + return val; +} + +int HitbusConfigFile::convertToUShort(std::string par, unsigned short& val){ + char* end; + val=strtoul(par.c_str(), &end, 0); + if(end-par.c_str()!=(int)par.size()){ + return 0; + } + if((val&0xffff0000)!=0){ + std::cout<<"Value "<<val<<" too large."<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + return 1; +} + +void HitbusConfigFile::writeModuleConfig(ipc::HitbusModuleConfig* config, const std::string &base, const std::string &confdir, + const std::string &configname, const std::string &key){ + struct stat stFileInfo; + int intStat; + // Attempt to get the file attributes + intStat = stat(base.c_str(),&stFileInfo); + if(intStat != 0) { //File does not exist + std::cout<<"Directory "<<base<<" does not exist. Not writing config file"<<std::endl; + return; + } + intStat = stat((base+"/"+confdir).c_str(),&stFileInfo); + if(intStat != 0) { //File does not exist + //std::cout<<"Directory "<<base<<"/"<<confdir<<" does not exist. Creating."<<std::endl; + mkdir ((base+"/"+confdir).c_str(),0777); + } + std::string cfgname=configname; + if(key.size()!=0)cfgname+="__"+key; + std::string fullpath=base+"/"+confdir+"/"+cfgname+".cfg"; + std::ofstream cfgfile(fullpath.c_str()); + cfgfile<<"# Hitbus Chip Configuration"<<std::endl; + cfgfile<<std::endl; + cfgfile<<"# Module name"<<std::endl; + cfgfile<<std::endl; + cfgfile<<"ModuleID\t\t"<<config->idStr<<std::endl; + cfgfile<<std::endl; + cfgfile<<"# Registers"<<std::endl; + cfgfile<<std::endl; + //Register + cfgfile<<"bpm\t\t\t"<<(unsigned)config->bpm<<std::endl; + cfgfile<<"delay_tam1\t\t"<<(unsigned)config->delay_tam1<<std::endl; + cfgfile<<"delay_tam2\t\t"<<(unsigned)config->delay_tam2<<std::endl; + cfgfile<<"delay_tam3\t\t"<<(unsigned)config->delay_tam3<<std::endl; + cfgfile<<"delay_tbm1\t\t"<<(unsigned)config->delay_tbm1<<std::endl; + cfgfile<<"delay_tbm2\t\t"<<(unsigned)config->delay_tbm2<<std::endl; + cfgfile<<"delay_tbm3\t\t"<<(unsigned)config->delay_tbm3<<std::endl; + cfgfile<<"bypass_delay\t\t"<<(unsigned)config->bypass_delay<<std::endl; + cfgfile<<"clock\t\t\t"<<"0x"<<std::hex<<(unsigned)config->clock<<std::dec<<std::endl; + cfgfile<<"function_A\t\t"<<"0x"<<std::hex<<(unsigned)config->function_A<<std::dec<<std::endl; + cfgfile<<"function_B\t\t"<<"0x"<<std::hex<<(unsigned)config->function_B<<std::dec<<std::endl; +} + +void HitbusConfigFile::readModuleConfig(ipc::HitbusModuleConfig* config, std::string filename){ + //clear structure + char* ccfg=(char*)config; + for (unsigned int i=0;i<sizeof(ipc::HitbusModuleConfig);i++)ccfg[i]=0; + //open file + m_moduleCfgFile=new std::ifstream(filename.c_str()); + if(!m_moduleCfgFile->good()){ + std::cout<<"Cannot open file with name "<<filename<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + m_moduleCfgFilePath = filename; + // parse config file + std::string inpline; + m_params.clear(); + while(true){ + getline(*m_moduleCfgFile, inpline); + if(m_moduleCfgFile->eof())break; + boost::trim(inpline); + if(inpline.size()!=0 && inpline[0]!='#'){ //remove comment lines and empty lines + std::vector<std::string> splitVec; + split( splitVec, inpline, boost::is_any_of(" \t"), boost::token_compress_on ); + if(splitVec.size()<2){ + std::cout<<"Bad input line "<<inpline<<std::endl; + continue; + } + m_params[splitVec[0]]=splitVec[1]; + } + } + // Module name + std::string modname=""; + if( m_params.find("ModuleID")==m_params.end()){ + std::cout<<"No Module ID defined."<<std::endl; + }else{ + modname=m_params["ModuleID"]; + } + sprintf((char*)config->idStr, "%s", modname.c_str()); + //Registers + config->bpm = lookupToUShort("bpm"); + config->delay_tam1 = lookupToUShort("delay_tam1"); + config->delay_tam2 = lookupToUShort("delay_tam2"); + config->delay_tam3 = lookupToUShort("delay_tam3"); + config->delay_tbm1 = lookupToUShort("delay_tbm1"); + config->delay_tbm2 = lookupToUShort("delay_tbm2"); + config->delay_tbm3 = lookupToUShort("delay_tbm3"); + config->bypass_delay = lookupToUShort("bypass_delay"); + config->clock = lookupToUShort("clock"); + config->function_A = lookupToUShort("function_A"); + config->function_B = lookupToUShort("function_B"); + + delete m_moduleCfgFile; +} + +void HitbusConfigFile::dump(const ipc::HitbusModuleConfig &config){ + std::cout<<"Registers:"<<std::endl; + std::cout<<"=========="<<std::endl; + std::cout<<"bpm = "<<config.bpm<<std::endl; + std::cout<<"delay_tam1 = "<<config.delay_tam1<<std::endl; + std::cout<<"delay_tam2 = "<<config.delay_tam2<<std::endl; + std::cout<<"delay_tam3 = "<<config.delay_tam3<<std::endl; + std::cout<<"delay_tbm1 = "<<config.delay_tbm1<<std::endl; + std::cout<<"delay_tbm2 = "<<config.delay_tbm2<<std::endl; + std::cout<<"delay_tbm3 = "<<config.delay_tbm3<<std::endl; + std::cout<<"bypass_delay = "<<config.bypass_delay<<std::endl; + std::cout<<"clock = "<<config.clock<<std::endl; + std::cout<<"function_A = "<<config.function_A<<std::endl; + std::cout<<"function_B = "<<config.function_B<<std::endl; +} diff --git a/rce/rcecalib/server/HitbusConfigFile.hh b/rce/rcecalib/server/HitbusConfigFile.hh new file mode 100644 index 00000000..dbde1be6 --- /dev/null +++ b/rce/rcecalib/server/HitbusConfigFile.hh @@ -0,0 +1,25 @@ +#ifndef HITBUSCONFIGFILE_HH +#define HITBUSCONFIGFILE_HH + +#include "HitbusModuleConfig.hh" +#include <string> +#include <map> + +class HitbusConfigFile { +public: + HitbusConfigFile(){} + ~HitbusConfigFile(); + void readModuleConfig(ipc::HitbusModuleConfig* cfg, std::string filename); + void writeModuleConfig(ipc::HitbusModuleConfig* config, const std::string &base, const std::string &confdir, + const std::string &configname, const std::string &key); + void dump(const ipc::HitbusModuleConfig& cfg); +private: + unsigned short lookupToUShort(std::string par); + int convertToUShort(std::string par, unsigned short& val); + + std::string m_moduleCfgFilePath; + std::ifstream *m_moduleCfgFile; + std::map<std::string, std::string> m_params; +}; + +#endif diff --git a/rce/rcecalib/server/IPCCallback.hh b/rce/rcecalib/server/IPCCallback.hh new file mode 100644 index 00000000..7ee36d3a --- /dev/null +++ b/rce/rcecalib/server/IPCCallback.hh @@ -0,0 +1,20 @@ +#ifndef IPCCALLBACK_HH +#define IPCCALLBACK_HH + +#include "ipc/object.h" +#include "Callback.hh" +#include <ipc/server.h> + +class IPCCallback : public IPCServer, + public IPCObject<POA_ipc::Callback> +{ +public: + IPCCallback(): m_rce(0){} + void notify( const ipc::CallbackParams &msg )=0; + void stopServer()=0; + void addRce(){m_rce++;} +protected: + int m_rce; +}; + +#endif diff --git a/rce/rcecalib/server/IPCController.cc b/rce/rcecalib/server/IPCController.cc new file mode 100644 index 00000000..ac3999bd --- /dev/null +++ b/rce/rcecalib/server/IPCController.cc @@ -0,0 +1,975 @@ + +#include "rcecalib/server/IPCController.hh" +#include "rcecalib/server/IPCRegularCallback.hh" +#include "rcecalib/server/PixScan.hh" +#include "IPCFEI3Adapter.hh" +#include "IPCFEI4AAdapter.hh" +#include "IPCFEI4BAdapter.hh" +#include "IPCHitbusAdapter.hh" +#include "IPCAFPHPTDCAdapter.hh" +#include "IPCScanAdapter.hh" +#include "IPCConfigIFAdapter.hh" +#include "IPCScanRootAdapter.hh" +#include "ScanOptions.hh" +#include "ers/ers.h" +#include <stdio.h> +#include <boost/lexical_cast.hpp> +#include <string> + +IPCController::IPCController(IPCPartition &p):m_partition(p){} + +void IPCController::addRce(int rce){ + for(size_t i=0;i<m_rces.size();i++)if(m_rces[i]==rce)return; //RCE has already been added. + m_rces.push_back(rce); +} +void IPCController::removeAllRces(){ + m_rces.clear(); +} +void IPCController::downloadModuleConfig(int rce, int id, PixelModuleConfig& config){ + ipc::IPCFEI3Adapter_var modhandle; + std::string names=boost::lexical_cast<std::string>(id)+"_RCE"+boost::lexical_cast<std::string>(rce); + const char* name=names.c_str(); + try { + bool v=m_partition.isObjectValid<ipc::IPCFEI3Adapter>(name); + if(!v) { + std::cout<<"Not valid"<<std::endl; + assert(0); + } + modhandle = m_partition.lookup<ipc::IPCFEI3Adapter>( name ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + modhandle -> IPCdownloadConfig( config ); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } +} + +void IPCController::downloadModuleConfig(int rce, int id, PixelFEI4AConfig& config){ + ipc::IPCFEI4AAdapter_var modhandle; + std::string names=boost::lexical_cast<std::string>(id)+"_RCE"+boost::lexical_cast<std::string>(rce); + const char* name=names.c_str(); + try { + bool v=m_partition.isObjectValid<ipc::IPCFEI4AAdapter>(name); + if(!v) { + std::cout<<name<<" not valid"<<std::endl; + assert(0); + } + modhandle = m_partition.lookup<ipc::IPCFEI4AAdapter>( name ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + modhandle -> IPCdownloadConfig( config ); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } +} + +void IPCController::downloadModuleConfig(int rce, int id, PixelFEI4BConfig& config){ + ipc::IPCFEI4BAdapter_var modhandle; + std::string names=boost::lexical_cast<std::string>(id)+"_RCE"+boost::lexical_cast<std::string>(rce); + const char* name=names.c_str(); + try { + bool v=m_partition.isObjectValid<ipc::IPCFEI4BAdapter>(name); + if(!v) { + std::cout<<"Not valid"<<std::endl; + assert(0); + } + modhandle = m_partition.lookup<ipc::IPCFEI4BAdapter>( name ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + modhandle -> IPCdownloadConfig( config ); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } +} + +void IPCController::downloadModuleConfig(int rce, int id, HitbusModuleConfig& config){ + ipc::IPCHitbusAdapter_var modhandle; + std::string names=boost::lexical_cast<std::string>(id)+"_RCE"+boost::lexical_cast<std::string>(rce); + const char* name=names.c_str(); + try { + bool v=m_partition.isObjectValid<ipc::IPCHitbusAdapter>(name); + if(!v) { + std::cout<<"Not valid"<<std::endl; + assert(0); + } + modhandle = m_partition.lookup<ipc::IPCHitbusAdapter>( name ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + modhandle -> IPCdownloadConfig( config ); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } +} +void IPCController::downloadModuleConfig(int rce, int id, AFPHPTDCModuleConfig& config){ + ipc::IPCAFPHPTDCAdapter_var modhandle; + std::string names=boost::lexical_cast<std::string>(id)+"_RCE"+boost::lexical_cast<std::string>(rce); + const char* name=names.c_str(); + try { + bool v=m_partition.isObjectValid<ipc::IPCAFPHPTDCAdapter>(name); + if(!v) { + std::cout<<"Not valid"<<std::endl; + assert(0); + } + modhandle = m_partition.lookup<ipc::IPCAFPHPTDCAdapter>( name ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + modhandle -> IPCdownloadConfig( config ); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } +} + +void IPCController::addModule(const char* name, const char* type, int id, int inLink, int outLink, int rce, const char* formatter){ + ipc::IPCConfigIFAdapter_var handle; + char cfa[128]; + sprintf(cfa, "configIF_RCE%d",rce); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + ipc::ModSetup s; + s.id=id; + s.inLink=inLink; + s.outLink=outLink; + std::string typestring; + if(std::string(type)=="FEI3")typestring="IPC_FEI3_multiThread"; + else if(std::string(type)=="FEI4A")typestring="IPC_FEI4A_multiThread"; + else if(std::string(type)=="FEI4B")typestring="IPC_FEI4B_multiThread"; + else if(std::string(type)=="Hitbus")typestring="IPC_Hitbus_multiThread"; + else if(std::string(type)=="HPTDC")typestring="IPC_AFPHPTDC_multiThread"; + else(assert(0)); + handle -> IPCsetupModule( name,typestring.c_str(),s , formatter); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } +} + +int IPCController::setupTrigger(const char* type){ + ipc::IPCConfigIFAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "configIF_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + return m_rces[i]+1000; + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + handle->IPCsetupTriggerIF(type); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } + return 0; +} + +void IPCController::removeAllModules(){ + ipc::IPCConfigIFAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "configIF_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + handle->IPCdeleteModules(); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } +} +void IPCController::startScan(){ + ipc::IPCScanAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "scanCtrl_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCScanAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + handle -> IPCstartScan( ); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } +} + +void IPCController::abortScan(){ + ipc::IPCScanAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "scanCtrl_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCScanAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + handle -> IPCabort( ); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } +} + +void IPCController::stopWaitingForData(){ + ipc::IPCScanAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "scanCtrl_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCScanAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + handle -> IPCstopWaiting( ); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } +} + +void IPCController::getEventInfo(unsigned* nevent) { + ipc::IPCConfigIFAdapter_var handle; + char cfa[128]; + assert(m_rces.size()>0); + sprintf(cfa, "configIF_RCE%d", m_rces[0]); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + *nevent= handle -> IPCnTrigger(); + + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } +} +int IPCController::verifyModuleConfigHW(int rce, int id) { + ipc::IPCConfigIFAdapter_var handle; + char cfa[128]; + int retval=0; + sprintf(cfa, "configIF_RCE%d",rce); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + retval|=handle -> IPCverifyModuleConfigHW(id); + + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + return retval; +} + +void IPCController::setupParameter(const char* par, int val) { + ipc::IPCConfigIFAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "configIF_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + handle -> IPCsetupParameter(par, val); + + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } +} + +void IPCController::setupMaskStage(int stage) { + ipc::IPCConfigIFAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "configIF_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + handle -> IPCsetupMaskStage(stage); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } +} + + +void IPCController::downloadScanConfig(ipc::ScanOptions& options){ + ipc::IPCScanRootAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "scanRoot_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCScanRootAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + handle -> IPCconfigureScan(options); + + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } +} + +void IPCController::waitForScanCompletion(ipc::Priority pr, IPCCallback* callb){ + IPCCallback *cb; + if(callb==0) cb=new IPCRegularCallback; + else cb=callb; + ipc::IPCScanRootAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "scanRoot_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCScanRootAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + handle -> IPCconfigureCallback(cb->_this(), pr ); + cb->addRce(); + + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } + cb->run(); + cb->_destroy(); +} +void IPCController::runScan(ipc::Priority pr, IPCCallback* callb){ + IPCCallback *cb; + if(callb==0) cb=new IPCRegularCallback; + else cb=callb; + ipc::IPCScanRootAdapter_var rhandle; + ipc::IPCScanAdapter_var shandle; + char cfa[128]; + char cfb[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "scanRoot_RCE%d", m_rces[i]); + sprintf(cfb, "scanCtrl_RCE%d", m_rces[i]); + try { + shandle = m_partition.lookup<ipc::IPCScanAdapter>( cfb ); + rhandle = m_partition.lookup<ipc::IPCScanRootAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + rhandle -> IPCconfigureCallback(cb->_this(), pr ); + cb->addRce(); + shandle->IPCstartScan(); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } + cb->run(); + cb->_destroy(); +} + +unsigned IPCController::getNEventsProcessed(){ + ipc::IPCScanRootAdapter_var handle; + char cfa[128]; + assert(m_rces.size()>0); + //maybe have to change if have multiple RCE's? + sprintf(cfa, "scanRoot_RCE%d", m_rces[0]); + try { + handle = m_partition.lookup<ipc::IPCScanRootAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + return handle -> IPCnEvents( ); + + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + return 0; +} + +void IPCController::resynch(){ + ipc::IPCScanRootAdapter_var handle; + char cfa[128]; + assert(m_rces.size()>0); + + for(size_t i=0;i<m_rces.size();i++){ + std::cout<<"IPCController sending resynch command to RCE "<<m_rces[i]<<std::endl; + + sprintf(cfa, "scanRoot_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCScanRootAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + handle -> IPCresynch( ); + + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + + } + +} + +void IPCController::resetFE(){ + ipc::IPCConfigIFAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "configIF_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + handle->IPCresetFE(); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } +} + +void IPCController::configureModulesHW(){ + ipc::IPCConfigIFAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "configIF_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + handle->IPCconfigureModulesHW(); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } +} + +unsigned IPCController::writeHWglobalRegister(const char* name, int reg, unsigned short val){ + ipc::IPCFEI4AAdapter_var modhandle; + try { + bool v=m_partition.isObjectValid<ipc::IPCFEI4AAdapter>(name); + if(!v) { + std::cout<<"Not valid"<<std::endl; + assert(0); + } + modhandle = m_partition.lookup<ipc::IPCFEI4AAdapter>( name ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + return modhandle->IPCwriteHWglobalRegister(reg,val); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + return 1000; +} + +unsigned IPCController::readHWglobalRegister(const char* name, int reg, unsigned short &val){ + ipc::IPCFEI4AAdapter_var modhandle; + try { + bool v=m_partition.isObjectValid<ipc::IPCFEI4AAdapter>(name); + if(!v) { + std::cout<<"Not valid"<<std::endl; + assert(0); + } + modhandle = m_partition.lookup<ipc::IPCFEI4AAdapter>( name ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + return modhandle->IPCreadHWglobalRegister(reg,val); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + return 1000; +} +unsigned IPCController::writeHWdoubleColumn(const char* name, unsigned bit, unsigned dcol, std::vector<unsigned> data, std::vector<unsigned> &retvec){ + ipc::IPCFEI4AAdapter_var modhandle; + try { + bool v=m_partition.isObjectValid<ipc::IPCFEI4AAdapter>(name); + if(!v) { + std::cout<<"Not valid"<<std::endl; + assert(0); + } + modhandle = m_partition.lookup<ipc::IPCFEI4AAdapter>( name ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + ipc::uvec ipcdata; + ipc::uvec_var retv; + ipcdata.length(data.size()); + for(size_t i=0;i<data.size();i++)ipcdata[i]=data[i]; + unsigned stat= modhandle->IPCwriteDoubleColumnHW(bit, dcol, ipcdata, retv); + for(unsigned i=0;i<retv->length();i++)retvec.push_back(retv[i]); + return stat; + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + return 1000; +} +unsigned IPCController::readHWdoubleColumn(const char* name, unsigned bit, unsigned dcol, std::vector<unsigned> &retvec){ + ipc::IPCFEI4AAdapter_var modhandle; + try { + bool v=m_partition.isObjectValid<ipc::IPCFEI4AAdapter>(name); + if(!v) { + std::cout<<"Not valid"<<std::endl; + assert(0); + } + modhandle = m_partition.lookup<ipc::IPCFEI4AAdapter>( name ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + ipc::uvec_var retv; + unsigned stat= modhandle->IPCreadDoubleColumnHW(bit, dcol, retv); + for(unsigned i=0;i<retv->length();i++)retvec.push_back(retv[i]); + return stat; + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + return 1000; +} + +unsigned IPCController::sendHWcommand(int rce, unsigned char opcode){ + ipc::IPCConfigIFAdapter_var handle; + bool foundRce=false; + for(size_t i=0;i<m_rces.size();i++)if(m_rces[i]==rce)foundRce=true; + assert(foundRce); + char cfa[128]; + sprintf(cfa, "configIF_RCE%d", rce); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + return handle->IPCsendHWcommand(opcode); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + return 1000; +} + +unsigned IPCController::writeHWregister(int rce, unsigned addr, unsigned val){ + ipc::IPCConfigIFAdapter_var handle; + bool foundRce=false; + for(size_t i=0;i<m_rces.size();i++)if(m_rces[i]==rce)foundRce=true; + assert(foundRce); + char cfa[128]; + sprintf(cfa, "configIF_RCE%d", rce); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + return handle->IPCwriteHWregister(addr,val); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + return 1000; +} + +unsigned IPCController::readHWregister(int rce, unsigned addr, unsigned &val){ + ipc::IPCConfigIFAdapter_var handle; + bool foundRce=false; + for(size_t i=0;i<m_rces.size();i++)if(m_rces[i]==rce)foundRce=true; + assert(foundRce); + char cfa[128]; + sprintf(cfa, "configIF_RCE%d", rce); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + return handle->IPCreadHWregister((CORBA::ULong)addr,(CORBA::ULong&) val); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + return 1000; +} +unsigned IPCController::writeHWblockData(int rce, std::vector<unsigned>& data){ + ipc::IPCConfigIFAdapter_var handle; + bool foundRce=false; + for(size_t i=0;i<m_rces.size();i++)if(m_rces[i]==rce)foundRce=true; + assert(foundRce); + char cfa[128]; + sprintf(cfa, "configIF_RCE%d", rce); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + ipc::blockdata ipcdata; + ipcdata.length(data.size()); + for(size_t i=0;i<data.size();i++)ipcdata[i]=data[i]; + return handle->IPCwriteHWblockData(ipcdata); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + return 1000; +} +unsigned IPCController::readHWblockData(int rce, std::vector<unsigned>& data,std::vector<unsigned>& retvec ){ + ipc::IPCConfigIFAdapter_var handle; + bool foundRce=false; + for(size_t i=0;i<m_rces.size();i++)if(m_rces[i]==rce)foundRce=true; + assert(foundRce); + char cfa[128]; + sprintf(cfa, "configIF_RCE%d", rce); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + ipc::blockdata ipcdata; + ipc::blockdata_var retv; + ipcdata.length(data.size()); + for(size_t i=0;i<data.size();i++)ipcdata[i]=data[i]; + unsigned stat= handle->IPCreadHWblockData(ipcdata, retv); + for(unsigned i=0;i<retv->length();i++)retvec.push_back(retv[i]); + return stat; + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + return 1000; +} + +unsigned IPCController::readHWbuffers(int rce, std::vector<unsigned char>& retvec ){ + ipc::IPCConfigIFAdapter_var handle; + bool foundRce=false; + for(size_t i=0;i<m_rces.size();i++)if(m_rces[i]==rce)foundRce=true; + assert(foundRce); + char cfa[128]; + sprintf(cfa, "configIF_RCE%d", rce); + try { + handle = m_partition.lookup<ipc::IPCConfigIFAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + ipc::chardata_var retv; + unsigned nbuf= handle->IPCreadHWbuffers(retv); + for(unsigned i=0;i<retv->length();i++)retvec.push_back(retv[i]); + return nbuf; + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + return (unsigned)-1; +} + +int IPCController::getScanStatus(){ + ipc::IPCScanAdapter_var handle; + int status=0; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "scanCtrl_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCScanAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + status|= handle->IPCgetStatus(); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + } + return status; +} diff --git a/rce/rcecalib/server/IPCController.hh b/rce/rcecalib/server/IPCController.hh new file mode 100644 index 00000000..9c930df2 --- /dev/null +++ b/rce/rcecalib/server/IPCController.hh @@ -0,0 +1,70 @@ +#ifndef IPCCONTROLLER_HH +#define IPCCONTROLLER_HH + +#include "ipc/partition.h" +#include "PixelModuleConfig.hh" +#include "PixelFEI4AConfig.hh" +#include "PixelFEI4BConfig.hh" +#include "HitbusModuleConfig.hh" +#include "AFPHPTDCModuleConfig.hh" +#include "IPCScanRootAdapter.hh" +#include "IPCScanAdapter.hh" +#include <vector> +#include <map> + +class IPCCallback; +namespace ipc{ + class ScanOptions; +} + +class IPCController{ +public: + IPCController() {}; + IPCController(IPCPartition &p); + void addRce(int rce); + void removeAllRces(); + + void downloadModuleConfig(int rce, int id, ipc::PixelModuleConfig& config); + void downloadModuleConfig(int rce, int id, ipc::PixelFEI4AConfig& config); + void downloadModuleConfig(int rce, int id, ipc::PixelFEI4BConfig& config); + void downloadModuleConfig(int rce, int id, ipc::HitbusModuleConfig& config); + void downloadModuleConfig(int rce, int id, ipc::AFPHPTDCModuleConfig& config); + void addModule(const char* name, const char* type, int id, int inLink, int outLink, int rce, const char* formatter); + int setupTrigger(const char* type="default"); + void removeAllModules(); + void resetFE(); + void configureModulesHW(); + + unsigned writeHWglobalRegister(const char* name, int reg, unsigned short val); + unsigned readHWglobalRegister(const char* name, int reg, unsigned short& val); + unsigned writeHWdoubleColumn(const char* name, unsigned bit, unsigned dcol, std::vector<unsigned> data, std::vector<unsigned> &retvec); + unsigned readHWdoubleColumn(const char* name, unsigned bit, unsigned dcol, std::vector<unsigned> &retvec); + + unsigned writeHWregister(int rce, unsigned addr, unsigned val); + unsigned readHWregister(int rce, unsigned addr, unsigned& val); + unsigned sendHWcommand(int rce, unsigned char opcode); + unsigned writeHWblockData(int rce, std::vector<unsigned> &data); + unsigned readHWblockData(int rce, std::vector<unsigned> &data, std::vector<unsigned>& retvec); + unsigned readHWbuffers(int rce, std::vector<unsigned char>& retvec); + + void downloadScanConfig(ipc::ScanOptions &scn); + int verifyModuleConfigHW(int rce, int id); + + void waitForScanCompletion(ipc::Priority pr, IPCCallback* callb=0); + void runScan(ipc::Priority pr, IPCCallback* callb=0); + void startScan(); + void abortScan(); + void stopWaitingForData(); + void getEventInfo(unsigned* nevent); + int getScanStatus(); + unsigned getNEventsProcessed(); + void resynch(); + void setupParameter(const char* par, int val); + void setupMaskStage(int stage); +private: + + IPCPartition m_partition; + std::vector<int> m_rces; +}; + +#endif diff --git a/rce/rcecalib/server/IPCGuiCallback.cc b/rce/rcecalib/server/IPCGuiCallback.cc new file mode 100644 index 00000000..2c53a8b0 --- /dev/null +++ b/rce/rcecalib/server/IPCGuiCallback.cc @@ -0,0 +1,29 @@ + +#include "rcecalib/server/IPCGuiCallback.hh" +#include "rcecalib/server/CallbackInfo.hh" + +void IPCGuiCallback::notify(const ipc::CallbackParams& msg){ + if(msg.status==ipc::SCANNING){ + m_cbinfo->setStage(msg.maskStage); + m_cbinfo->addToMask(CallbackInfo::NEWSTAGE); + std::cout<<"RCE "<<msg.rce<<": Mask Stage "<<msg.maskStage<<std::endl; + }else if(msg.status==ipc::FITTING){ + std::cout<<"RCE "<<msg.rce<<": Fitting"<<std::endl; + m_cbinfo->addToMask(CallbackInfo::FIT); + }else if(msg.status==ipc::DOWNLOADING){ + std::cout<<"RCE "<<msg.rce<<": Downloading"<<std::endl; + m_cbinfo->addToMask(CallbackInfo::DOWNLOAD); + }else if(msg.status==ipc::FAILED){ + m_cbinfo->addToMask(CallbackInfo::FAILED); + std::cout<<"RCE "<<msg.rce<<": Failed"<<std::endl; + } +} + +void IPCGuiCallback::stopServer(){ + m_rce--; + if(m_rce<=0){ + m_cbinfo->addToMask(CallbackInfo::STOP); + stop(); + } +} + diff --git a/rce/rcecalib/server/IPCGuiCallback.hh b/rce/rcecalib/server/IPCGuiCallback.hh new file mode 100644 index 00000000..48f5fb65 --- /dev/null +++ b/rce/rcecalib/server/IPCGuiCallback.hh @@ -0,0 +1,18 @@ +#ifndef IPCGUICALLBACK_HH +#define IPCGUICALLBACK_HH + +#include "rcecalib/server/IPCCallback.hh" + +class CallbackInfo; + +class IPCGuiCallback : public IPCCallback { +public: + IPCGuiCallback(CallbackInfo* info): IPCCallback(),m_cbinfo(info){ + } + void notify( const ipc::CallbackParams & msg ); + void stopServer(); +private: + CallbackInfo* m_cbinfo; +}; + +#endif diff --git a/rce/rcecalib/server/IPCHistoController.cc b/rce/rcecalib/server/IPCHistoController.cc new file mode 100644 index 00000000..44a9e684 --- /dev/null +++ b/rce/rcecalib/server/IPCHistoController.cc @@ -0,0 +1,207 @@ + +#include "rcecalib/server/IPCHistoController.hh" +#include "IPCScanRootAdapter.hh" +#include "ers/ers.h" +#include <oh/OHIterator.h> +#include <oh/OHServerIterator.h> +#include <oh/OHProviderIterator.h> +#include <oh/OHRootReceiver.h> +#include "TH1D.h" +#include "TH2D.h" +#include "TH2C.h" +#include "TH2S.h" + +class HistoReceiver : public OHRootReceiver { +public: + void clearList(){ + m_list.clear(); + } + void receive( OHRootHistogram & h ) + { + m_list.push_back(h.histogram.get()); + h.histogram.release(); // we ask the histogram auto_ptr to drop ownership + // for the histogram since it will be kept by ROOT + } + std::vector<TH1*>& getHistos(){return m_list;} +private: + std::vector<TH1*> m_list; +}; + +IPCHistoController::IPCHistoController(IPCPartition &p):m_partition(p){} + +void IPCHistoController::addRce(int rce){ + for(size_t i=0;i<m_rces.size();i++)if(m_rces[i]==rce)return; //RCE has already been added. + m_rces.push_back(rce); +} + +void IPCHistoController::removeAllRces(){ + m_rces.clear(); +} + +// std::vector<TH1*> IPCHistoController::getHistosFromIS(const char* reg){ +// HistoReceiver hr; +// try{ +// OHProviderIterator pii( m_partition, "RceIsServer"); +// while(pii++){ +// OHIterator it( m_partition, "RceIsServer", pii.name(), reg); +// while ( it++ ){ +// it.retrieve( hr ); +// } +// } +// }catch(daq::is::InvalidCriteria){ +// std::cout<<"Invalid object"<<std::endl; +// }catch(daq::is::RepositoryNotFound){ +// std::cout<<"Object not found"<<std::endl; +// }catch ( daq::ipc::InvalidPartition & ex ){ +// std::cout<<"partition does not exist"<<std::endl; +// }catch ( daq::is::Exception & ex ){ +// std::cout<<"IS exception"<<std::endl; +// }catch(...){ +// std::cout<<"Something else went wrong"<<std::endl; +// } +// return hr.getHistos(); +// } + +std::vector<TH1*> IPCHistoController::getHistosFromIS(const char* reg){ + HistoReceiver hr; + try{ + OHHistogramIterator it( m_partition, "RceIsServer", ".*", reg); + while ( it++ ){ + it.retrieve( hr ); + if(hr.getHistos().back()!=0) + hr.getHistos().back()->SetName(it.name().c_str()); + } + }catch(daq::is::InvalidCriteria){ + std::cout<<"Invalid object"<<std::endl; + }catch(daq::is::RepositoryNotFound){ + std::cout<<"Object not found"<<std::endl; + }catch ( daq::ipc::InvalidPartition & ex ){ + std::cout<<"partition does not exist"<<std::endl; + }catch ( daq::is::Exception & ex ){ + std::cout<<"IS exception"<<std::endl; + }catch(...){ + std::cout<<"Something else went wrong"<<std::endl; + } + return hr.getHistos(); +} + +std::vector<std::string> IPCHistoController::getHistoNames(const char* reg){ + std::vector<std::string> retvect; + ipc::StringVect_var stringvect; + ipc::IPCScanRootAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "scanRoot_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCScanRootAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + stringvect=handle -> IPCgetHistoNames(reg); + + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + + + for(unsigned int i=0;i<stringvect->length();i++){ + retvect.push_back(std::string(stringvect[i])); + } + } + return retvect; +} + +std::vector<std::string> IPCHistoController::getPublishedHistoNames(){ + std::vector<std::string> retvect; + ipc::StringVect_var stringvect; + ipc::IPCScanRootAdapter_var handle; + char cfa[128]; + for(size_t i=0;i<m_rces.size();i++){ + sprintf(cfa, "scanRoot_RCE%d", m_rces[i]); + try { + handle = m_partition.lookup<ipc::IPCScanRootAdapter>( cfa ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + stringvect=handle -> IPCgetPublishedHistoNames(); + + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + + + for(unsigned int i=0;i<stringvect->length();i++){ + retvect.push_back(std::string(stringvect[i])); + } + } + return retvect; + } + + + +bool IPCHistoController::clearISServer(std::string regex, bool verbose) +{ + try + { + OHServerIterator sit( m_partition, "RceIsServer" ); + if ( verbose ) + { + std::cout << "Partition \"" << m_partition.name() + << "\" contains " << sit.entries() + << " IS server(s):" << std::endl; + } + + while ( sit++ ) + { + try { + OHHistogramIterator hit(m_partition, sit.name(), ".*", regex); + + if ( hit.entries() ) + { + if ( verbose ){ + std::cout << "removing " << hit.entries() + << " histogram(s) from the '" << sit.name() << "' server ... "; + } + + hit.removeAll(); + + if ( verbose ){ + std::cout << "done" << std::endl; + } + } + } + catch( ers::Issue & ex ) + { + ers::error( ex ); + return false; + } + } + } + catch ( ers::Issue & ex ) + { + ers::error( ex ); + return false; + } + + return true; + +} + diff --git a/rce/rcecalib/server/IPCHistoController.hh b/rce/rcecalib/server/IPCHistoController.hh new file mode 100644 index 00000000..12e1fe7a --- /dev/null +++ b/rce/rcecalib/server/IPCHistoController.hh @@ -0,0 +1,30 @@ +#ifndef IPCHISTOCONTROLLER_HH +#define IPCHISTOCONTROLLER_HH + +#include "ipc/partition.h" +#include "IPCScanRootAdapter.hh" +#include <vector> + +#include <TH1.h> + + +class IPCHistoController{ +public: + IPCHistoController() {}; + IPCHistoController(IPCPartition &p); + void addRce(int rce); + void removeAllRces(); + + std::vector<TH1*> getHistosFromIS(const char* reg); + std::vector<std::string> getHistoNames(const char* reg); + std::vector<std::string> getPublishedHistoNames(); + + std::string getIPCPartitionName() { return m_partition.name(); } + + bool clearISServer(std::string regex="RCE.*", bool verbose=false); + + IPCPartition m_partition; + std::vector<int> m_rces; +}; + +#endif diff --git a/rce/rcecalib/server/IPCRegularCallback.cc b/rce/rcecalib/server/IPCRegularCallback.cc new file mode 100644 index 00000000..625b0f91 --- /dev/null +++ b/rce/rcecalib/server/IPCRegularCallback.cc @@ -0,0 +1,19 @@ + +#include "rcecalib/server/IPCRegularCallback.hh" + +void IPCRegularCallback::notify(const ipc::CallbackParams& msg){ + if(msg.status==ipc::SCANNING){ + std::cout<<"RCE "<<msg.rce<<": Mask Stage "<<msg.maskStage<<std::endl; + }else if(msg.status==ipc::FITTING){ + std::cout<<"RCE "<<msg.rce<<": Fitting"<<std::endl; + } +} + +void IPCRegularCallback::stopServer(){ + m_rce--; + if(m_rce<=0){ + std::cout<<"Done"<<std::endl; + stop(); + } +} + diff --git a/rce/rcecalib/server/IPCRegularCallback.hh b/rce/rcecalib/server/IPCRegularCallback.hh new file mode 100644 index 00000000..105d3dad --- /dev/null +++ b/rce/rcecalib/server/IPCRegularCallback.hh @@ -0,0 +1,13 @@ +#ifndef IPCREGULARCALLBACK_HH +#define IPCREGULARCALLBACK_HH + +#include "rcecalib/server/IPCCallback.hh" + +class IPCRegularCallback : public IPCCallback { +public: + IPCRegularCallback(): IPCCallback(){} + void notify( const ipc::CallbackParams & msg ); + void stopServer(); +}; + +#endif diff --git a/rce/rcecalib/server/Makefile b/rce/rcecalib/server/Makefile new file mode 100644 index 00000000..c98722e2 --- /dev/null +++ b/rce/rcecalib/server/Makefile @@ -0,0 +1,29 @@ +# Package level makefile +# ---------------------- +%.mk:; + +# Checks +# ------ +# Check release location variables + +ifeq ($(RELEASE_DIR),) +export RELEASE_DIR := $(RELEASE) +endif +include $(RELEASE_DIR)/Makefile.inc + +default: .server + +clean: + +$(MAKE) -j$(JOBS) -C. $(HOST_ARCH).clean $(RCE_ARCH).clean + +include $(RELEASE_DIR)/make/share/setup.mk +include ../flags.mk + +ifndef PREMAKE_DONE +include $(RELEASE_DIR)/make/share/premake.mk +else +include constituents.mk +include $(RELEASE_DIR)/make/sw/package.mk +include $(RELEASE_DIR)/make/sw/rootcint.mk +endif + diff --git a/rce/rcecalib/server/Mean.hh b/rce/rcecalib/server/Mean.hh new file mode 100644 index 00000000..51b6acd2 --- /dev/null +++ b/rce/rcecalib/server/Mean.hh @@ -0,0 +1,28 @@ +#ifndef MEAN_HH +#define MEAN_HH +#include <math.h> + +class Mean{ +public: + Mean():sum(0),sum2(0),n(0){} + void clear(){sum=0;sum2=0;n=0;} + void accumulate(float val){ + sum+=val; + sum2+=val*val; + n++; + } + float mean(){ + if(n>0)return sum/n; + else return 0; + } + float sigma(){ + if(n>0)return sqrt(1/(float)n*sum2-mean()*mean()); + else return 0; + } + int nEntries(){return n;} +private: + float sum; + float sum2; + int n; +}; +#endif diff --git a/rce/rcecalib/server/PixScan.cc b/rce/rcecalib/server/PixScan.cc new file mode 100644 index 00000000..0404a286 --- /dev/null +++ b/rce/rcecalib/server/PixScan.cc @@ -0,0 +1,851 @@ +///////////////////////////////////////////////////////////////////// +// PixScan.cxx +///////////////////////////////////////////////////////////////////// +// +// 17/06/05 Version 1.0 (PM) +// +// +// Still missing: +// setting up of the rod scan structure before sending reference +// presets +// histogram downloads +// histogram staging + +#include "rcecalib/server/PixScan.hh" + +#include <sstream> +#include <iostream> +namespace RCE { + PixScan::PixScan(ScanType presetName, FEflavour feFlavour) { + // initConfig(); + presetRCE(presetName, feFlavour); + setupRCE(presetName, feFlavour); + resetScan(); + } + + + PixScan::~PixScan() { + } + + + bool PixScan::setupRCE(ScanType presetName, FEflavour feFlavour) { + m_name="Scan"; + m_receiver="Pgp"; + m_dataHandler="RegularScan"; + m_dataProc="OCCUPANCY"; + m_scanType="RegularCfg"; + m_triggerType="default"; + m_formatterType="JJ"; + m_analysisType="NONE"; + m_hitbusConfig=0; + m_callbackPriority=ipc::LOW; + m_timeout_seconds=0; + m_timeout_nanoseconds=100000000; + m_firstStage = 0; + m_stepStage = 1; + m_oneByOne=false; + m_LVL1Latency_Secondary=0; + m_moduleTrgMask=0; + m_deadtime=0; + m_mixedTrigger=false; + m_setupThreshold=false; + m_triggerMask=0; + m_triggerDataOn=false; + m_threshold=100; + m_fitfun="SCURVE"; + m_verifyConfig=false; + m_eventInterval=0; + m_hitbusConfig=0; + m_clearMasks=false; + m_protectFifo=false; + m_runnumber=0; + m_injectForTrigger=0; + m_overrideLatency=false; + m_allowedTimeouts=5; + m_nTriggers=0; + m_noiseThreshold=1e-6; + m_useAbsoluteNoiseThreshold=false; + m_useVcal=false; + + bool fei3=(feFlavour == PM_FE_I2); + bool fei4=(feFlavour == PM_FE_I4A || feFlavour == PM_FE_I4B || feFlavour == PM_FE_I4); + if (presetName == DIGITAL_TEST && fei3) { + m_scanType="Regular"; + m_analysisType = "Fei3DigitalTest"; + addHistoName(".*FEI4_Errors"); + addHistoName("Mod_[0-9]+_Occupancy_Point_000"); + } else if (presetName == DIGITAL_TEST && fei4) { + m_firstStage = 0; + m_dataHandler="RegularScanRaw"; + m_dataProc="RawFei4Occupancy"; + m_formatterType=""; + m_analysisType = "Fei4DigitalTest"; + // addHistoName("RCE[0-9]+_Mod_0_Occupancy_Point_000"); + addHistoName(".*"); + } else if (presetName == DIGITALTEST_SELFTRIGGER && fei4) { + m_firstStage = 0; + m_dataHandler="RegularScanRaw"; + m_dataProc="RawFei4Occupancy"; + m_formatterType=""; + m_analysisType = "Fei4DigitalTest"; + m_allowedTimeouts=1000; + m_callbackPriority=ipc::HIGH; + // addHistoName("RCE[0-9]+_Mod_0_Occupancy_Point_000"); + addHistoName(".*"); + } else if (presetName == MULTISHOT && fei4) { + m_formatterType="FEI4B"; + addHistoName("Mod_0_Occupancy_Point_000"); + m_triggerType="MultiShot"; + m_eventInterval=5; + } else if (presetName == ANALOG_TEST && fei3) { + m_scanType="Regular"; + addHistoName(".*"); + } else if (presetName == TOT_TEST && fei3) { + m_scanType="Regular"; + m_dataProc="TOT"; + m_analysisType="TOT"; + addHistoName(".*"); + } else if (presetName == ANALOG_TEST && fei4) { + m_dataHandler="RegularScanRaw"; + m_dataProc="RawFei4Occupancy"; + m_analysisType = "Fei4DigitalTest"; + m_formatterType=""; + addHistoName(".*"); + } else if (presetName == TOT_TEST && fei4) { + m_formatterType="FEI4"; + m_dataProc="TOT"; + m_analysisType="TOT"; + addHistoName(".*"); + } else if (presetName == TOT_CALIB && fei4) { + m_formatterType="FEI4"; + m_dataProc="TOTCALIB"; + m_analysisType="TOTCALIB"; + addHistoName(".*"); + } else if (presetName == THRESHOLD_SCAN && fei3) { + m_scanType="Regular"; + m_analysisType="Threshold"; + addHistoName(".*"); + } else if (presetName == THRESHOLD_SCAN && fei4) { + m_dataHandler="RegularScanRaw"; + m_dataProc="RawFei4Occupancy"; + m_formatterType=""; + m_analysisType="Threshold"; + addHistoName(".*"); + } else if (presetName == TEMPERATURE_SCAN && fei4) { + m_dataHandler="RegularScanRaw"; + m_dataProc="Temperature"; + m_triggerType="Temperature"; + m_formatterType=""; + m_analysisType="Temperature"; + addHistoName(".*"); + } else if (presetName == MONLEAK_SCAN && fei4) { + m_dataHandler="RegularScanRaw"; + m_dataProc="Monleak"; + m_triggerType="Monleak"; + m_formatterType=""; + m_analysisType="Temperature"; + addHistoName(".*"); + } else if (presetName == SERIAL_NUMBER_SCAN && fei4) { + m_dataHandler="RegularScanRaw"; + m_dataProc="SerialNumber"; + m_triggerType="SerialNumber"; + m_formatterType=""; + m_analysisType="SerialNumber"; + addHistoName(".*"); + } else if (presetName == MODULE_CROSSTALK && fei4) { + m_dataHandler="ModuleCrosstalkRaw"; + m_dataProc="RawFei4Occupancy"; + m_formatterType=""; + m_analysisType="Threshold"; + m_LVL1Latency_Secondary=238; + m_moduleTrgMask=1; + // have to use m_oneByOne for this scan + m_oneByOne=true; + m_mixedTrigger=true; + m_analysisType="ModuleCrosstalk"; + addHistoName(".*"); + } else if (presetName == OFFSET_SCAN && fei4) { + m_stepStage = 5; + //m_setupThreshold=true; + //m_threshold=120; + m_fitfun="SCURVE_NOCONV"; + m_dataHandler="RegularScanRaw"; + m_dataProc="RawFei4Occupancy"; + m_formatterType=""; + m_analysisType="Offset"; + addHistoName(".*"); + } else if (presetName == CROSSTALK_SCAN && fei4) { + m_dataHandler="RegularScanRaw"; + m_dataProc="RawFei4Occupancy"; + m_fitfun="SCURVE_XTALK"; + m_formatterType=""; + m_analysisType="Crosstalk"; + m_callbackPriority=ipc::MEDIUM; + addHistoName(".*"); + } else if (presetName == DIFFUSION && fei4) { + m_dataHandler="RegularScanRaw"; + m_dataProc="RawFei4Occupancy"; + m_formatterType=""; + m_fitfun="SCAN_SCURVE_XTALK"; + m_analysisType="Crosstalk"; + m_callbackPriority=ipc::MEDIUM; + addHistoName(".*"); + std::vector<float> pixels; // = row + 336*col + 1 (row from 0-335, col from 0-79. We add 1 because maskStage==0 has special + + pixels.push_back(20 + 336*11 + 1); + pixels.push_back(40 + 336*31 + 1); + pixels.push_back(176 + 336*55 + 1); + pixels.push_back(177 + 336*55 + 1); + pixels.push_back(178 + 336*55 + 1); + pixels.push_back(175 + 336*56 + 1); + pixels.push_back(176 + 336*56 + 1); + + setLoopVarValues(1, pixels); + + } else if (presetName == TWOTRIGGER_THRESHOLD && fei4) { + m_eventInterval=245; + m_dataHandler="RegularScan"; + m_injectForTrigger=3; //bit mask. 3: inject on both triggers, 2: inject on 2nd trigger, 1: inject on 1st trigger, 0: no inject + m_dataProc="MultiTrigOccupancy"; + m_formatterType="FEI4"; + m_triggerType="MultiTrigger"; + m_analysisType="MultiTrig"; + addHistoName(".*"); + } else if (presetName == TWOTRIGGER_NOISE && fei4) { + m_eventInterval=245; // Overwritten by MULTITRIG_INTERVAL loop + m_dataHandler="RegularScan"; + m_dataProc="MultiTrigNoise"; + m_formatterType="FEI4"; + m_triggerType="MultiTrigger"; + m_analysisType="MultiTrigNoise"; + addHistoName(".*"); + + } else if (presetName == GDAC_SCAN && fei4) { + if(feFlavour == PM_FE_I4A){ //FEI4A + m_maskStageTotalSteps= FEI4_COL_ANL_40; + m_maskStageSteps = 24; + }else{ //FEI4B + m_maskStageTotalSteps= FEI4_COLPR1x6; + m_maskStageSteps = 5; + } + m_stepStage = 5; + m_dataHandler="RegularScanRaw"; + m_dataProc="RawFei4Occupancy"; + m_formatterType=""; + m_analysisType="Gdac"; + addHistoName(".*"); + } else if ((presetName == GDAC_TUNE || presetName == GDAC_RETUNE) && fei4) { + m_stepStage = 5; + m_dataHandler="RegularScanRaw"; + m_dataProc="RawFei4Occupancy"; + m_formatterType=""; + m_analysisType="Gdac"; + addHistoName(".*"); + } else if ((presetName == GDAC_FAST_TUNE || presetName == GDAC_FAST_RETUNE) && fei4) { + m_stepStage = 2; + m_dataHandler="RegularScanRaw"; + m_dataProc="RawFei4Occupancy"; + m_formatterType=""; + m_analysisType="GdacFast"; + addHistoName(".*"); + } else if (presetName == GDAC_COARSE_FAST_TUNE && fei4) { + m_stepStage = 2; + m_dataHandler="RegularScanRaw"; + m_dataProc="RawFei4Occupancy"; + m_formatterType=""; + m_analysisType="GdacCoarseFast"; + addHistoName(".*"); + } else if (presetName == IF_TUNE && fei4) { + m_formatterType="FEI4"; + m_scanType="IfScan"; + m_dataProc="TOT"; + m_analysisType = "Iffanalysis"; + m_callbackPriority=ipc::MEDIUM; + addHistoName("^([^T]|T[^o]|To[^T]|ToT[^2])*.{0,3}$"); //anything except ToT2 histos + } else if (presetName == FDAC_TUNE && fei4) { + m_formatterType="FEI4"; + m_dataProc="TOT"; + m_analysisType = "Fei4Fdacanalysis"; + addHistoName(".*"); + } else if (presetName == VTHIN_SCAN && fei4) { + m_formatterType="FEI4"; + addHistoName(".*"); + } else if (presetName == DELAY_SCAN && fei4) { + m_formatterType="FEI4"; + } else if (presetName == MEASUREMENT_SCAN) { + m_firstStage = 5; + m_timeout_nanoseconds=1; + m_allowedTimeouts=-1; + m_name="172.21.6.43:1444"; //address of the computer that does the measurement + m_receiver="Measurement"; + m_dataProc="Measurement"; + m_triggerType="Measurement"; + m_dataHandler="Simple"; + addHistoName(".*"); + } else if (presetName == SELFTRIGGER && fei4) { + //m_name="data_RUNNUM.hit"; + m_formatterType="FEI4"; + m_scanType="Selftrigger"; + m_dataProc="Selftrigger"; + m_dataHandler="CosmicData"; + m_timeout_seconds=1000000000; + m_timeout_nanoseconds=0; + m_allowedTimeouts=-1; + m_protectFifo=true; + addHistoName(".*"); + } else if (presetName == REGISTER_TEST && fei4) { + m_dataHandler="RegularScanRaw"; + m_dataProc="Fei4RegisterTest"; + m_triggerType="Fei4RegisterTest"; + m_formatterType=""; + m_analysisType="RegisterTest"; + m_allowedTimeouts=0; + m_useVcal=true; + addHistoName(".*"); + } else if (presetName == EXT_REGISTER_VERIFICATION && fei4) { + m_formatterType="FEI4"; + m_scanType="CosmicData"; + m_dataProc="Selftrigger"; + m_dataHandler="CosmicData"; + m_timeout_seconds=0; + m_timeout_nanoseconds=100000000; + m_verifyConfig=true; + } else if (presetName == NOISESCAN && fei4) { + m_formatterType="FEI4"; + m_scanType="Noisescan"; + m_dataProc="Noisescan"; + m_dataHandler="CosmicData"; + m_receiver="PgpCosmic"; + m_analysisType="Fei4Noise"; + m_timeout_seconds=60; + m_timeout_nanoseconds=0; + m_allowedTimeouts=-1; + m_triggerMask=0x2; //Trigger mask 1=scint 2=cyclic 4=Eudet 8=HSIO + m_eventInterval=20; + m_protectFifo=true; + m_noiseThreshold=1e-6; + m_useAbsoluteNoiseThreshold=false; + addHistoName(".*"); + } else if (presetName == NOISESCAN_SELFTRIGGER && fei4) { + m_formatterType="FEI4"; + m_scanType="Selftrigger"; + m_dataProc="Noisescan"; + m_dataHandler="CosmicData"; + m_receiver="PgpCosmic"; + m_analysisType="Fei4Noise"; + m_timeout_seconds=60; + m_timeout_nanoseconds=0; + m_allowedTimeouts=-1; + m_protectFifo=true; + m_noiseThreshold=10; + m_useAbsoluteNoiseThreshold=true; + addHistoName(".*"); + } else if (presetName == STUCKPIXELS && fei4) { + m_dataProc="Hitor"; + m_formatterType="FEI4Hitor"; + m_analysisType="Fei4StuckPixel"; + m_callbackPriority=ipc::HIGH; + m_triggerType="Hitor"; + addHistoName(".*"); + } else if (presetName == LV1LATENCY_SCAN && fei3) { + m_dataHandler="CosmicData"; + m_receiver="PgpCosmic"; + m_timeout_seconds=60; + m_timeout_nanoseconds=0; + } else if (presetName == SCINTDELAY_SCAN) { + m_scanType="Delay"; + m_dataProc="Delay"; + m_dataHandler="DelayScan"; + m_receiver="PgpCosmic"; + m_timeout_seconds=5; + m_timeout_nanoseconds=0; + m_allowedTimeouts=-1; + addHistoName(".*"); + } else if (presetName == COSMIC_DATA) { + m_hitbusConfig=1; + m_scanType="CosmicData"; + m_dataHandler="CosmicData"; + //m_dataProc="CosmicData"; + m_receiver="PgpCosmicNw"; + m_triggerDataOn=true; + m_timeout_seconds=1000000000; + m_timeout_nanoseconds=0; + m_allowedTimeouts=-1; + m_overrideLatency=true; + } else if (presetName == COSMIC_RCE) { + m_digitalInjection = false; + m_scanType="CosmicData"; + m_dataHandler="CosmicData"; + m_dataProc="CosmicData"; + m_receiver="PgpCosmic"; + m_triggerDataOn=true; + m_timeout_seconds=1000000000; + m_timeout_nanoseconds=0; + m_allowedTimeouts=-1; + } else if (presetName == EXTTRIGGER && fei4) { + m_triggerDataOn=true; + m_overrideLatency=true; + m_LVL1Latency = 210; + m_hitbusConfig=1; + //m_eventInterval=750; + m_triggerMask=0x8; //Trigger mask 1=scint 2=cyclic 4=Eudet 8=HSIO + m_formatterType="FEI4"; + m_scanType="CosmicData"; + m_dataProc="Selftrigger"; + m_dataHandler="CosmicData"; + m_receiver="PgpCosmic"; + //Setup below for multiple hardware triggers: + //Trigger stream with m_strobeLVL1Delay leading 0s, + //then m_consecutiveLvl1TrigA[1] triggers m_LVL1Latency_Secondary ticks apart + //m_triggerType="MultiShot"; + //m_consecutiveLvl1TrigA[1]= 2; //n L1A + //m_consecutiveLvl1TrigA[0]= 1; + //m_LVL1Latency_Secondary=10; + //m_strobeLVL1Delay=32; + //------- + m_timeout_seconds=1000000000; + m_timeout_nanoseconds=0; + m_allowedTimeouts=-1; + addHistoName(".*"); + } else if ((presetName == TDAC_TUNE || presetName == GDAC_TUNE) && fei3) { + + if (presetName == TDAC_TUNE) { + m_analysisType="Fei3Tdac_tune"; + } else { + m_analysisType="Gdac"; + } + addHistoName(".*"); + } else if ((presetName == TDAC_TUNE || presetName==TDAC_TUNE_ITERATED) && fei4) { + m_thresholdTargetValue = 1600; + m_dataHandler="RegularScanRaw"; + m_dataProc="RawFei4Occupancy"; + m_analysisType="Fei4Tdac_tune"; + m_formatterType=""; + addHistoName(".*"); + } else if ((presetName == TDAC_FAST_TUNE || presetName==TDAC_FAST_RETUNE) && fei4) { + m_dataHandler="RegularScanRaw"; + m_dataProc="RawFei4Occupancy"; + m_analysisType="Fei4TdacFast_tune"; + m_formatterType=""; + addHistoName(".*"); + } else if (presetName == T0_SCAN && fei4) { + m_dataHandler="RegularScanRaw"; + m_dataProc="RawFei4Occupancy"; + m_fitfun="SCURVE_NOCONV"; + m_formatterType=""; + m_analysisType="T0"; + addHistoName(".*"); + } else if (presetName == TIMEWALK_MEASURE && fei4) { + m_dataHandler="RegularScanRaw"; + m_dataProc="RawFei4Occupancy"; + m_fitfun="SCURVE_NOCONV"; + m_formatterType=""; + m_analysisType="TimeWalk"; + addHistoName(".*"); + } else if (presetName == INTIME_THRESH_SCAN && fei4) { + m_dataHandler="RegularScanRaw"; + m_dataProc="RawFei4Occupancy"; + m_formatterType=""; + m_analysisType="Threshold"; + addHistoName(".*"); + } else if ((presetName == FDAC_TUNE || presetName == IF_TUNE) && fei3) { + addHistoName(".*"); + m_dataProc="TOT"; + + if (presetName == FDAC_TUNE) { + m_analysisType = "Fei3Fdacanalysis"; + } else { + m_analysisType = "Iffanalysis"; + } + } else if (presetName == TOT_CALIB && fei3) { + m_scanType="Regular"; + m_dataProc="TOT"; + } else if (presetName == T0_SCAN && fei3) { + m_scanType="Regular"; + addHistoName(".*"); + } else if (presetName == TIMEWALK_MEASURE && fei3) { + m_scanType="Regular"; + addHistoName(".*"); + } else if (presetName == INTIME_THRESH_SCAN && fei3) { + m_scanType="Regular"; + } else if (presetName == CROSSTALK_SCAN && fei3) { + m_scanType="Regular"; + addHistoName(".*"); + } else if (presetName == INCREMENTAL_TDAC_SCAN && feFlavour == PM_FE_I2) { + m_scanType="Regular"; + /* no RCE BOC scans at this point */ + } else if (presetName == BOC_RX_DELAY_SCAN) { return false; + } else if (presetName == BOC_V0_RX_DELAY_SCAN) { return false; + } else if (presetName == BOC_THR_RX_DELAY_SCAN) { return false; + } else { + + std::cout<<"Scan not implemented (index= "<< presetName<< ")"<<std::endl; + return false; + } + return true; + } + + bool PixScan::presetRCE(ScanType presetName, FEflavour feFlavour) { + #include "PixScanBase_presetRCE.h" + } + /* void PixScan::preset(ScanType presetName) now in PixScanBase - + to sync with PixLib */ + + + + + + bool PixScan::loop(int index) { + if (index < MAX_LOOPS) { + if (m_loopTerminating[index]) { + m_loopTerminating[index] = false; + m_loopEnded[index] = true; + if (index == 0) { + m_FECounter = 0; + m_maskStageIndex = 0; + m_newMaskStage = true; + m_newScanStep = true; + m_newFE = m_FEbyFE; + if (m_dspProcessing[0]) m_newScanStep = false; + if (m_dspMaskStaging || m_maskStageMode == STATIC || m_runType != NORMAL_SCAN) m_newMaskStage = false; + } + m_loopIndex[index] = 0; + return false; + } else { + m_loopEnded[index] = false; + return true; + } + } + assert(0); + return false; + } + + int PixScan::scanIndex(int index) { + if (index < MAX_LOOPS) { + return m_loopIndex[index]; + } + assert(0); + return 0; + } + + void PixScan::next(int index) { + if (index == 0) { + if ((m_dspProcessing[0] || !m_loopActive[0]) && + (m_dspMaskStaging || m_maskStageMode == STATIC || m_runType != NORMAL_SCAN)) { + m_loopIndex[index] = m_loopVarNSteps[index] - 1; + m_maskStageIndex = m_maskStageSteps - 1; + m_loopTerminating[0] = true; + m_newScanStep = false; + m_newMaskStage = false; + } else if (m_dspProcessing[0] || !m_loopActive[0]) { + if (m_maskStageIndex < m_maskStageSteps - 1) { + m_maskStageIndex++; + m_newScanStep = false; + m_newMaskStage = true; + } else { + m_loopTerminating[0] = true; + } + } else if (m_dspMaskStaging || m_maskStageMode == STATIC || m_runType != NORMAL_SCAN) { + if (m_loopIndex[0] < m_loopVarNSteps[0] - 1) { + m_loopIndex[0]++; + m_newScanStep = true; + m_newMaskStage = false; + } else { + m_loopTerminating[0] = true; + } + } else { + if ((m_loopIndex[0] == m_loopVarNSteps[0] - 1) && (m_maskStageIndex == m_maskStageSteps - 1)) { + m_loopTerminating[0] = true; + m_newScanStep = false; + m_newMaskStage = false; + } else { + if (m_innerLoopSwap) { + if (m_loopIndex[0] < m_loopVarNSteps[0] - 1) { + m_loopIndex[0]++; + m_newScanStep = true; + m_newMaskStage = false; + } else { + m_loopIndex[0] = 0; + m_maskStageIndex++; + m_newScanStep = false; + m_newMaskStage = true; + } + } else { + + if (m_maskStageIndex < m_maskStageSteps - 1) { + m_maskStageIndex++; + m_newScanStep = false; + m_newMaskStage = true; + } else { + m_maskStageIndex = 0; + m_loopIndex[0]++; + m_newScanStep = true; + m_newMaskStage = false; + } + } + } + } + } else if (index < MAX_LOOPS) { + if (m_dspProcessing[index] || !m_loopActive[index]) { + m_loopIndex[index] = m_loopVarNSteps[index] - 1; + m_loopTerminating[index] = true; + } else { + if ((m_loopIndex[index] < m_loopVarNSteps[index] - 1) || m_loopVarValuesFree[index]) { + m_loopIndex[index]++; + } else { + m_loopTerminating[index] = true; + } + } + } else { + assert(0); + } + } + + void PixScan::terminate(int index) { + if (index > 0 && index < MAX_LOOPS) { + if (m_loopVarValuesFree[index]) { + m_loopTerminating[index] = true; + m_loopVarNSteps[index] = m_loopIndex[index]+1; + } + } else { + assert(0); + } + } + + bool PixScan::newMaskStep() { + return m_newMaskStage; + } + + bool PixScan::newScanStep() { + return m_newScanStep; + } + + void PixScan::resetScan() { + m_FECounter=0; + m_actualFE = -1; + // Reset indexes + for (int i=0; i<MAX_LOOPS; i++) { + m_loopIndex[i] = 0; + m_loopTerminating[i] = false; + m_loopEnded[i] = false; + } + m_maskStageIndex = 0; + m_newMaskStage = true; + m_newScanStep = true; + if (m_dspProcessing[0]) m_newScanStep = false; + if (m_dspMaskStaging || m_maskStageMode == STATIC || m_runType != NORMAL_SCAN) m_newMaskStage = false; + // Reset histograms + } + + + + void PixScan::convertScanConfig(ipc::ScanOptions& scanPar){ + // Initialize ScanPar structure + int nLoopTot = 0; + int i; + int m_nBinTot = 0; + for (i=0; i<MAX_LOOPS; i++) { + if (getLoopActive(i) && getDspProcessing(i)) { + nLoopTot++; + m_nBinTot += getLoopVarNSteps(i); + } else { + break; + } + } + // zero everything + char* pointer=(char*)&scanPar; + for (unsigned i=0;i<sizeof(ipc::ScanOptions);i++){ + *pointer++=0; + } + + PixLib::EnumMaskSteps mss; + PixLib::EnumMaskStageMode msm; + PixLib::EnumScanParam sp; + PixLib::EnumFitFunc ff; + PixLib::EnumScanAct sa; + PixLib::EnumTriggMode tm; + PixLib::EnumTriggOptions to; + + // Load scan config + scanPar.runNumber=m_runnumber; + scanPar.name=CORBA::string_dup(m_name.c_str()); + scanPar.scanType=CORBA::string_dup(m_scanType.c_str()); + scanPar.receiver=CORBA::string_dup(m_receiver.c_str()); + scanPar.dataHandler=CORBA::string_dup(m_dataHandler.c_str()); + scanPar.dataProc=CORBA::string_dup(m_dataProc.c_str()); + scanPar.timeout.seconds=m_timeout_seconds; + scanPar.timeout.nanoseconds=m_timeout_nanoseconds; + scanPar.timeout.allowedTimeouts=m_allowedTimeouts; + if (getMaskStageMode() == PixScan::STATIC) { + scanPar.stagingMode = CORBA::string_dup(msm.lookup(STATIC).c_str()); + //scanPar.general.stageAdvanceFirst = 0; //? + scanPar.maskStages = CORBA::string_dup(mss.lookup(STEPS_32).c_str()); + scanPar.nMaskStages = 32; + } else { + scanPar.stagingMode = CORBA::string_dup(msm.lookup(getMaskStageMode()).c_str()); + if (getInnerLoopSwap()) { + //scanPar.general.stageAdvanceFirst = 0; //? + } else { + //scanPar.general.stageAdvanceFirst = 1; //? + } + scanPar.maskStages = CORBA::string_dup(mss.lookup(getMaskStageTotalSteps()).c_str()); + scanPar.nMaskStages = getMaskStageSteps(); + } + scanPar.firstStage=m_firstStage; + scanPar.stepStage=m_stepStage; + scanPar.nLoops = 0; + scanPar.scanLoop.length(nLoopTot); + for (int i=0; i<nLoopTot; i++) { + if (getLoopActive(i) && getDspProcessing(i)) { + scanPar.nLoops++; + scanPar.scanLoop[i].scanParameter = CORBA::string_dup(sp.lookup(getLoopParam(i)).c_str()); + scanPar.scanLoop[i].nPoints = getLoopVarNSteps(i); + //scanPar.scanLoop[i].dataPointsPtr = 0x0; + scanPar.scanLoop[i].endofLoopAction.Action = CORBA::string_dup(sa.lookup(PixLib::EnumScanAct::NO_ACTION).c_str()); + if (getDspLoopAction(i)) { + if (getLoopAction(i) == PixScan::SCURVE_FIT) { + // scanPar.scanLoop[i].endofLoopAction.Action = SCAN_CALC_THRESH; + scanPar.scanLoop[i].endofLoopAction.Action = CORBA::string_dup(sa.lookup(PixLib::EnumScanAct::FIT).c_str()); + scanPar.scanLoop[i].endofLoopAction.fitFunction = CORBA::string_dup(m_fitfun.c_str()); + } else if (getLoopAction(i) == PixScan::TDAC_TUNING) { + scanPar.scanLoop[i].endofLoopAction.Action = CORBA::string_dup(sa.lookup(PixLib::EnumScanAct::TUNE_THRESH).c_str()); + scanPar.scanLoop[i].endofLoopAction.fitFunction = CORBA::string_dup(ff.lookup(PixLib::EnumFitFunc::SCURVE).c_str()); + scanPar.scanLoop[i].endofLoopAction.targetThreshold = getThresholdTargetValue(); + } else if (getLoopAction(i) == PixScan::NORMALIZE) { + scanPar.scanLoop[i].endofLoopAction.Action = CORBA::string_dup(sa.lookup(PixLib::EnumScanAct::FIT).c_str()); + scanPar.scanLoop[i].endofLoopAction.fitFunction = CORBA::string_dup("NORMALIZE"); + } + } + if (scanPar.scanLoop[i].nPoints > 0) { + //Add loop values at the very end + std::vector<float> loopvalues = getLoopVarValues(i); + scanPar.scanLoop[i].dataPoints.length(scanPar.scanLoop[i].nPoints); + for(unsigned int k=0;k<scanPar.scanLoop[i].nPoints;k++){ + scanPar.scanLoop[i].dataPoints[k]= (int)loopvalues[k]; + } + } + + } else { + scanPar.scanLoop[i].scanParameter = CORBA::string_dup(sp.lookup(NO_PAR).c_str()); + scanPar.scanLoop[i].endofLoopAction.Action = CORBA::string_dup(sa.lookup(PixLib::EnumScanAct::NO_ACTION).c_str()); + scanPar.scanLoop[i].endofLoopAction.fitFunction = CORBA::string_dup(""); + } + } + //scanPar.general.configSet = getModConfig(); //? + scanPar.trigOpt.nEvents = getRepetitions(); + scanPar.trigOpt.moduleTrgMask = m_moduleTrgMask; + scanPar.trigOpt.triggerMask = m_triggerMask; + scanPar.trigOpt.deadtime = m_deadtime; + scanPar.trigOpt.triggerDataOn = m_triggerDataOn; + scanPar.trigOpt.nL1AperEvent = getConsecutiveLvl1TrigA(0); + scanPar.trigOpt.nTriggersPerGroup = getConsecutiveLvl1TrigA(1); + scanPar.trigOpt.nTriggers = m_nTriggers; + scanPar.trigOpt.Lvl1_Latency = getLVL1Latency(); + scanPar.trigOpt.Lvl1_Latency_Secondary = m_LVL1Latency_Secondary; + scanPar.trigOpt.strobeDuration = getStrobeDuration(); + scanPar.trigOpt.strobeMCCDelay = getStrobeMCCDelay(); + scanPar.trigOpt.strobeMCCDelayRange = getStrobeMCCDelayRange(); + scanPar.trigOpt.injectForTrigger = m_injectForTrigger; + scanPar.trigOpt.hitbusConfig = m_hitbusConfig; + //override + scanPar.trigOpt.CalL1ADelay = getStrobeLVL1Delay(); + scanPar.trigOpt.eventInterval = m_eventInterval; + scanPar.trigOpt.threshold=m_threshold; + std::vector<std::string> optMask; + if(m_totTargetCharge!=0 && m_useVcal==false){ + scanPar.trigOpt.vcal_charge = getTotTargetCharge(); + optMask.push_back(to.lookup(PixLib::EnumTriggOptions::SPECIFY_CHARGE_NOT_VCAL).c_str()); + } else { + scanPar.trigOpt.vcal_charge = getFeVCal(); + } + //getModScanConcurrent() //? + //getFeHitbus() //? + if (getDigitalInjection()) optMask.push_back(to.lookup(PixLib::EnumTriggOptions::DIGITAL_INJECT).c_str()); + else if (getChargeInjCapHigh()) { + optMask.push_back(to.lookup(PixLib::EnumTriggOptions::USE_CHIGH).c_str()); + } else { + optMask.push_back(to.lookup(PixLib::EnumTriggOptions::USE_CLOW).c_str()); + } + if(m_oneByOne==true)optMask.push_back("ONE_BY_ONE"); + if(m_setupThreshold==true)optMask.push_back("SETUP_THRESHOLD"); + if(m_clearMasks==true)optMask.push_back("CLEAR_MASKS"); + if(m_protectFifo==true)optMask.push_back("PROTECT_FIFO"); + if(m_overrideLatency==true)optMask.push_back("OVERRIDE_LATENCY"); + scanPar.trigOpt.optionsMask.length(optMask.size()); + for(size_t i=0;i<optMask.size();i++){ + scanPar.trigOpt.optionsMask[i]=CORBA::string_dup(optMask[i].c_str()); + } + + if (getSelfTrigger()) { + scanPar.trigOpt.triggerMode = CORBA::string_dup(tm.lookup(PixLib::EnumTriggMode::INTERNAL_SELF).c_str()); + } else if (m_mixedTrigger==true){ + scanPar.trigOpt.triggerMode = CORBA::string_dup(tm.lookup(PixLib::EnumTriggMode::MIXED).c_str()); + } else { + // More options needed here in PixScan + scanPar.trigOpt.triggerMode = CORBA::string_dup(tm.lookup(PixLib::EnumTriggMode::DSP).c_str()); + } + + scanPar.histos.length(m_histoNames.size()); + for(size_t i=0;i<m_histoNames.size();i++){ + scanPar.histos[i]=CORBA::string_dup(m_histoNames[i].c_str()); + } + } + void PixScan::dump(std::ostream &os, const ipc::ScanOptions& scanPar) + { + /* force decimal output */ + os <<std::dec<<"Run number = " << m_runnumber << std::endl; + os <<"Formatter = " << m_formatterType << std::endl; + os << "Analysis = " << m_analysisType << std::endl; + os << "ToT target value = " << m_totTargetValue << std::endl; + os << "ToT target charge = " << m_totTargetCharge << std::endl; + os << "Threshold target value = " << m_thresholdTargetValue << std::endl; + os << "scanPar.name = " << scanPar.name << std::endl; + os << "scanPar.receiver = " << scanPar.receiver << std::endl; + os << "scanPar.dataHandler = " << scanPar.dataHandler << std::endl; + os << "scanPar.dataProc = " << scanPar.dataProc << std::endl; + os << "scanPar.scanType = " << scanPar.scanType << std::endl; + os << "scanPar.timeout.seconds = " << scanPar.timeout.seconds << std::endl; + os << "scanPar.timeout.nanaseconds = " << scanPar.timeout.nanoseconds << std::endl; + os << "scanPar.stagingMode = " << scanPar.stagingMode << std::endl; + os << "scanPar.nMaskStages = " << scanPar.nMaskStages << std::endl; + os << "scanPar.maskStages = " << scanPar.maskStages << std::endl; + os << "scanPar.firstStage = " << scanPar.firstStage << std::endl; + os << "scanPar.stepStage = " << scanPar.firstStage << std::endl; + os << "scanPar.trigOpt.nEvents = " << scanPar.trigOpt.nEvents << std::endl; + os << "scanPar.trigOpt.moduleTrgMask = " << scanPar.trigOpt.moduleTrgMask << std::endl; + os << "scanPar.trigOpt.nL1AperEvent = " << (int) scanPar.trigOpt.nL1AperEvent << std::endl; + os << "scanPar.trigOpt.nTriggersPerGroup = " << (int) scanPar.trigOpt.nTriggersPerGroup << std::endl; + os << "scanPar.trigOpt.nTriggers = " << (int) scanPar.trigOpt.nTriggers << std::endl; + os << "scanPar.trigOpt.Lvl1_Latency = " << (int) scanPar.trigOpt.Lvl1_Latency << std::endl; + os << "scanPar.trigOpt.Lvl1_Latency_Secondary = " << (int) scanPar.trigOpt.Lvl1_Latency_Secondary << std::endl; + os << "scanPar.trigOpt.strobeDuration = " << scanPar.trigOpt.strobeDuration << std::endl; + os << "scanPar.trigOpt.strobeMCCDelay = " << scanPar.trigOpt.strobeMCCDelay << std::endl; + os << "scanPar.trigOpt.strobeMCCDelayRange = " << scanPar.trigOpt.strobeMCCDelayRange << std::endl; + os << "scanPar.trigOpt.CalL1ADelay = " << scanPar.trigOpt.CalL1ADelay << std::endl; + os << "scanPar.trigOpt.eventInterval = " << scanPar.trigOpt.eventInterval << std::endl; + os << "scanPar.trigOpt.threshold = " << scanPar.trigOpt.threshold << std::endl; + os << "scanPar.trigOpt.triggerMode = " << scanPar.trigOpt.triggerMode << std::endl; + os << "scanPar.trigOpt.triggerMask = " << scanPar.trigOpt.triggerMask << std::endl; + os << "scanPar.trigOpt.triggerDataOn = " << (int)scanPar.trigOpt.triggerDataOn << std::endl; + os << "scanPar.trigOpt.injectForTrigger = " << (int)scanPar.trigOpt.injectForTrigger << std::endl; + os << "scanPar.trigOpt.hitbusConfig = " << (int)scanPar.trigOpt.hitbusConfig << std::endl; + os << "scanPar.trigOpt.deadtime = " << scanPar.trigOpt.deadtime << std::endl; + os << "scanPar.trigOpt.vcal_charge = " << scanPar.trigOpt.vcal_charge << std::endl; + for(unsigned i=0;i<scanPar.trigOpt.optionsMask.length();i++) + os << "scanPar.trigOpt.optionsMask["<<i<<"] = " << scanPar.trigOpt.optionsMask[i] << std::endl; + + os << "scanPar.nLoops = " << (int)scanPar.nLoops << std::endl; + for(int i=0;i<scanPar.nLoops;i++) { + os << "scanPar.scanLoop["<<i<<"].scanParameter = " << scanPar.scanLoop[i].scanParameter << std::endl; + os << "scanPar.scanLoop["<<i<<"].endofLoopAction.Action = " << scanPar.scanLoop[i].endofLoopAction.Action << std::endl; + os << "scanPar.scanLoop["<<i<<"].endofLoopAction.fitFunction = " << scanPar.scanLoop[i].endofLoopAction.fitFunction << std::endl; + os << "scanPar.scanLoop["<<i<<"].endofLoopAction.targetThreshold = " << scanPar.scanLoop[i].endofLoopAction.targetThreshold << std::endl; + os << "scanPar.scanLoop["<<i<<"].nPoints = " << scanPar.scanLoop[i].nPoints << std::endl; + for(unsigned int j=0;j<scanPar.scanLoop[i].nPoints;j++) { + os << "scanPar.scanLoop["<<i<<"].dataPoints["<<j<<"] = " << scanPar.scanLoop[i].dataPoints[j] <<std::endl; + } + } + for(unsigned i=0;i<scanPar.histos.length();i++) + os << "scanPar.histos["<<i<<"] = " << scanPar.histos[i] << std::endl; + } +} diff --git a/rce/rcecalib/server/PixScan.hh b/rce/rcecalib/server/PixScan.hh new file mode 100644 index 00000000..2b9d46e9 --- /dev/null +++ b/rce/rcecalib/server/PixScan.hh @@ -0,0 +1,216 @@ +#ifndef PIXSCAN_HH +#define PIXSCAN_HH + +#include "ScanOptions.hh" +#include "Callback.hh" +#include "PixScanBase.h" +using namespace ipc; + + +#include <vector> +#include <list> +#include <map> +#include <string> +#include <assert.h> +#include <sys/time.h> + +namespace RCE { + + class PixScan : public PixLib::PixScanBase{ + + +private: + // Global scan config + // RCE specific + std::string m_name; + std::string m_scanType; + std::string m_triggerType; + std::string m_formatterType; + std::string m_receiver; + std::string m_dataHandler; + std::string m_dataProc; + std::string m_analysisType; + ipc::Priority m_callbackPriority; + unsigned m_timeout_seconds; + unsigned m_timeout_nanoseconds; + std::vector<std::string>m_histoNames; + int m_eventInterval; + bool m_oneByOne; + int m_firstStage; + int m_stepStage; + int m_LVL1Latency_Secondary; + unsigned short m_moduleTrgMask; + bool m_mixedTrigger; + bool m_setupThreshold; + unsigned short m_threshold; + std::string m_fitfun; + bool m_verifyConfig; + unsigned short m_triggerMask; + bool m_triggerDataOn; + int m_injectForTrigger; + unsigned short m_deadtime; + unsigned short m_hitbusConfig; + bool m_clearMasks; + bool m_protectFifo; + int m_runnumber; + bool m_overrideLatency; + int m_allowedTimeouts; + unsigned m_nTriggers; + double m_noiseThreshold; + bool m_useAbsoluteNoiseThreshold; + bool m_useVcal; + + + std::map<std::string, int> m_histogramTypes; + std::map<std::string, int> m_scanTypes; + void prepareIndexes(HistogramType type, unsigned int mod, int ix2, int ix1, int ix0); + +public: + //! Constructors + PixScan() {}; + PixScan(ScanType presetName, FEflavour feFlavour); + PixScan(PixLib::PixScanBase &base):PixLib::PixScanBase(base){}; + + //! Destructor + ~PixScan(); + + + //! Load predefined configurations + + // setup RCE specific fields + bool setupRCE(ScanType presetName, FEflavour feFlavour); + bool presetRCE(ScanType presetName, FEflavour feFlavour); + + void resetScan(); + + void convertScanConfig(ipc::ScanOptions& scanPar); + void dump(std::ostream &os, const ipc::ScanOptions& scanPar); + //! Scan attributes + void setFirstStage(int firstStage){ + m_firstStage=firstStage; + } + int getFirstStage(){ + return m_firstStage; + } + void setStepStage(int stepStage){ + m_stepStage=stepStage; + } + int getStepStage(){ + return m_stepStage; + } + void setSetupThreshold(bool setupThreshold) { + m_setupThreshold=setupThreshold; + } + bool getSetupThreshold() { + return m_setupThreshold; + } + void setThreshold(unsigned short threshold){ + m_threshold=threshold; + } + unsigned short getThreshold(){ + return m_threshold; + } + void setTimeoutSeconds(unsigned timeoutSeconds){ + m_timeout_seconds=timeoutSeconds; + } + unsigned getTimeoutSeconds(){ + return m_timeout_seconds; + } + + void setName(const char* name){ + m_name=name; + } + std::string getName(){ + return m_name; + } + void addHistoName(const char* name){ + m_histoNames.push_back(name); + } + std::vector<std::string>& getHistoNames(){ + return m_histoNames; + } + unsigned short getModuleTrgMask(){ + return m_moduleTrgMask; + } + void setModuleTrgMask (unsigned short modTrgMask){ + m_moduleTrgMask=modTrgMask; + } + const char* getAnalysisType(){ + return m_analysisType.c_str(); + } + ipc::Priority getCallbackPriority(){ + return m_callbackPriority; + } + const char* getScanTypeName(){ + return m_scanType.c_str(); + } + + const char* getTriggerType(){ + return m_triggerType.c_str(); + } + const char* getFormatterType(){ + return m_formatterType.c_str(); + } + const bool verifyConfig(){ + return m_verifyConfig; + } + void setTriggerMask(unsigned short mask){ + m_triggerMask=mask; + } + void setEventInterval(unsigned val){ + m_eventInterval=val; + } + void setDeadtime(unsigned val){ + m_deadtime=val; + } + void setHitbusConfig(unsigned short val){ + m_hitbusConfig=val; + } + unsigned short getHitbusConfig(){ + return m_hitbusConfig; + } + bool clearMasks(){ + return m_clearMasks; + } + void setClearMasks(bool on){ + m_clearMasks=on; + } + bool protectFifo(){ + return m_protectFifo; + } + void setRunNumber(int runnum){ + m_runnumber=runnum; + } + int getRunNumber(){ + return m_runnumber; + } + double getNoiseThreshold(){ + return m_noiseThreshold; + } + bool useAbsoluteNoiseThreshold(){ + return m_useAbsoluteNoiseThreshold; + } + void setSecondaryLatency(int lat){ + m_LVL1Latency_Secondary=lat; + } + int getSecondaryLatency(){ + return m_LVL1Latency_Secondary; + } + //! Scan coontrol + + void initConfig(); + bool loop(int index); + int scanIndex(int index); + void next(int index); + void terminate(int index); + bool newMaskStep(); + bool newScanStep(); + + + }; + +} +#endif + + + diff --git a/rce/rcecalib/server/PrimList.cc b/rce/rcecalib/server/PrimList.cc new file mode 100644 index 00000000..4d8856b3 --- /dev/null +++ b/rce/rcecalib/server/PrimList.cc @@ -0,0 +1,119 @@ +///////////////////////////////////////////////////////////////////// +// PixScan.cxx +///////////////////////////////////////////////////////////////////// +// +// 14/06/12 Version 1.0 (Author:Jackie Brosamer) +// +// + + + +#include "rcecalib/server/PrimList.hh" + +#include <sstream> +#include <iostream> + +namespace RCE { + + //! Constructors + //Load saved primlist from file + /*PrimList::PrimList() { + m_scans = new std::vector <PixScan*> (); + }*/ + + + + //! Destructor + PrimList::~PrimList(){ + for(size_t i=0;i<m_scans.size();i++){ + delete m_scans[i]; + delete m_options[i]; + } + } + + PixScan* PrimList::getScan(int index) { + if((unsigned)index<m_scans.size())return m_scans.at(index); + else return 0; + } + std::string PrimList::getScanName(int index){ + if((unsigned)index<m_scannames.size())return m_scannames.at(index); + else return ""; + } + std::string PrimList::getPreScript(int index){ + if((unsigned)index<m_preScripts.size())return m_preScripts.at(index); + else return ""; + } + std::string PrimList::getPostScript(int index){ + if((unsigned)index<m_postScripts.size())return m_postScripts.at(index); + else return ""; + } + std::string PrimList::getTopConfig(int index){ + if((unsigned)index<m_topConfigs.size())return m_topConfigs.at(index); + else return ""; + } + ipc::ScanOptions* PrimList::getScanOptions(int index) { + if((unsigned)index<m_options.size())return m_options.at(index); + else return 0; + } + std::vector<std::string>& PrimList::getDisabledList(int index) { + assert((unsigned)index<m_disabled.size()); + return m_disabled.at(index); + } + std::vector<std::string>& PrimList::getEnabledList(int index) { + assert((unsigned)index<m_enabled.size()); + return m_enabled.at(index); + } + int PrimList::getPause(int index){ + if((unsigned)index<m_scannames.size())return m_pause.at(index); + else return 0; + } + bool PrimList::getUpdateConfig(int index) + { + assert((unsigned)index<m_enabled.size()); + return m_updateConfigs.at(index); + } + void PrimList::addScan(std::string scanname, PixScan* scan, std::string preScript, std::string postScript, std::vector<std::string> enables, std::vector<std::string> disables, bool updateConfig, std::string topConfig, int pause) { + m_scannames.push_back(scanname); + m_preScripts.push_back(preScript); + m_postScripts.push_back(postScript); + m_enabled.push_back(enables); + m_disabled.push_back(disables); + m_scans.push_back(scan); + m_updateConfigs.push_back(updateConfig); + ipc::ScanOptions *scanopt=new ipc::ScanOptions; + scan->convertScanConfig(*scanopt); + m_options.push_back(scanopt); + m_topConfigs.push_back(topConfig); + m_pause.push_back(pause); + } + + void PrimList::clearScans() + { + for(size_t i=0;i<m_scans.size();i++){ + delete m_scans[i]; + delete m_options[i]; + } + m_scans.clear(); + m_options.clear(); + m_scannames.clear(); + m_preScripts.clear(); + m_postScripts.clear(); + m_enabled.clear(); + m_disabled.clear(); + m_updateConfigs.clear(); + m_topConfigs.clear(); + m_pause.clear(); + } + + + + + + +} + + + + + + diff --git a/rce/rcecalib/server/PrimList.hh b/rce/rcecalib/server/PrimList.hh new file mode 100644 index 00000000..a1ccdd70 --- /dev/null +++ b/rce/rcecalib/server/PrimList.hh @@ -0,0 +1,69 @@ +#ifndef PRIMLIST_HH +#define PRIMLIST_HH + +#include "PixScan.hh" +#include "ScanOptions.hh" +#include "Callback.hh" +#include "PixScanBase.h" + +using namespace ipc; + + +#include <vector> +#include <list> +#include <map> +#include <string> +#include <assert.h> +#include <sys/time.h> +#include "ScanOptions.hh" + + +namespace RCE { + + class PixScan; + + + class PrimList //: public PixLib::PixScanBase +{ + + + +private: + std::vector <PixScan*> m_scans; + std::vector <ipc::ScanOptions*> m_options; + std::vector <std::string> m_scannames; + std::vector <std::string> m_preScripts; //filepath of shell scripts to be executed before scan + std::vector <std::string> m_postScripts; //filepath of scripts to be executed after scan + std::vector <std::vector<std::string> > m_enabled; //enabled frontends + std::vector <std::vector<std::string> > m_disabled; //disabled frontends + std::vector <bool> m_updateConfigs; + std::vector<std::string> m_topConfigs; + std::vector<int> m_pause; +public: + //! Constructors + PrimList() {}; + + //! Destructor + ~PrimList(); + + //! Get Functions + PixScan* getScan(int index); + ipc::ScanOptions* getScanOptions(int index); + unsigned nScans(){return m_scans.size();} + std::string getScanName(int index); + std::string getPreScript(int index); + std::string getPostScript(int index); + std::vector<std::string>& getDisabledList(int index); + std::vector<std::string>& getEnabledList(int index); + bool getUpdateConfig(int index); + void addScan(std::string scanname, PixScan* scan, std::string preScript, std::string postScript, std::vector<std::string> enables, std::vector<std::string> disables, bool updateConfig, std::string topConfig, int pause); + void clearScans(); + std::string getTopConfig(int index); + int getPause(int index); + }; + +} +#endif + + + diff --git a/rce/rcecalib/server/PrimListGui.cc b/rce/rcecalib/server/PrimListGui.cc new file mode 100644 index 00000000..00ecb10a --- /dev/null +++ b/rce/rcecalib/server/PrimListGui.cc @@ -0,0 +1,572 @@ +#include "rcecalib/server/PrimListGui.hh" +#include "rcecalib/server/PrimList.hh" +#include "rcecalib/server/PixScan.hh" +#include "rcecalib/server/ConfigGui.hh" +#include "ScanOptions.hh" +#include <iostream> +#include <fstream> +#include <string> +#include <sstream> +#include <algorithm> +using namespace RCE; + +PrimListGui::PrimListGui(const char* name, const TGWindow *p, UInt_t w, UInt_t h, UInt_t options): + + TGVerticalFrame(p,w,h,options), m_pList(new PrimList) +{ + + m_name=new TGLabel(this,name); + AddFrame(m_name,new TGLayoutHints(kLHintsCenterX|kLHintsTop, 2, 2, 10, 0)); + FontStruct_t labelfont; + labelfont = gClient->GetFontByName("-adobe-helvetica-medium-r-*-*-18-*-*-*-*-*-iso8859-1"); + m_name->SetTextFont(labelfont); + + TGHorizontalFrame *btnFrame = new TGHorizontalFrame(this, 2,2 ); + AddFrame(btnFrame,new TGLayoutHints(kLHintsExpandX )); + TGTextButton* loadBtn =new TGTextButton(btnFrame,"Load Primlist"); + loadBtn->SetFont(labelfont); + loadBtn->SetMargins(5,10,5,5); + loadBtn->Connect("Clicked()", "PrimListGui", this,"load()"); + btnFrame->AddFrame(loadBtn,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + + TGTextButton* clearBtn =new TGTextButton(btnFrame,"Clear Primlist"); + clearBtn->SetFont(labelfont); + clearBtn->SetMargins(5,10,5,5); + clearBtn->Connect("Clicked()", "PrimListGui", this,"clear()"); + btnFrame->AddFrame(clearBtn,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + plStatusLabel = new TGLabel(btnFrame, " "); + FontStruct_t statusfont= gClient->GetFontByName("-adobe-helvetica-bold-r-*-*-12-*-*-*-*-*-iso8859-1"); + plStatusLabel->SetTextFont(statusfont); + btnFrame->AddFrame(plStatusLabel, new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 20, 2, 2, 0)); + +} + + + + +PrimListGui::~PrimListGui(){ + Cleanup(); +} + +void PrimListGui::updateText(TGLabel* label, const char* newtext){ + //unsigned len=strlen(label->GetText()->GetString()); + label->SetText(newtext); + //if (strlen(newtext)>len)Layout(); + Layout(); +} + +void PrimListGui::disableControls(){ + +} +void PrimListGui::enableControls(){ + +} + +void PrimListGui::printFromGui(){ + // print(std::cout); +} + +void PrimListGui::print(std::ostream &os){ + +} + +RCE::PrimList* PrimListGui::getPrimList(){ + return m_pList; +} +int PrimListGui::loadPrimList(const char* fPath)//Name,Flavor,Threshold,Charge,ToT +{std::cout << "LOADING" << std::endl; + int loaded=0; + std::ifstream file; + file.open(fPath); + if (file.is_open()) + { + std::string line; + int i = 1; + while (file.good() ) + { + std::getline(file,line); + if(line.compare("")== 0) + break; + int err = parseScan(line); + if (err == 0) + { + loaded++; + } + else + { + //m_pList=new PrimList(); + std::string failSt = "Failed to load PrimList on item " + i; + updateStatus(failSt); + std::cout << "NULL SCAN" << line << " error "<<err<<std::endl; + clear(); + return 0; + } + + } + + file.close(); + } + //check to make sure scannames are good (DEBUG LATER) +/* + std::vector<std::string>::iterator itr; + for ( itr = m_scannames.begin(); itr != m_scannames.end(); ++itr ) + { + int str = m_scantypes.find(*itr)->second; + std::cout << "NAME " << *itr << str << std::endl; + //std::map <std::string, int>::const_iterator itr2; + if (m_scantypes.find(*itr) == m_scantypes.end()) + { + std::string failSt = "Bad scan name: ";// + str + "!"; + updateStatus(failSt); + m_pList = new PrimList(); + return -1; + } + }*/ + return loaded; + +} + +void PrimListGui::setScanTypes (std::map<int, std::string> pscantypes) +{ + std::map<std::string,int> revMap; + std::map<int,std::string>::iterator it; + for ( it=pscantypes.begin() ; it != pscantypes.end(); it++ ) + { + std::transform((*it).second.begin(), (*it).second.end(), (*it).second.begin(), ::toupper); + revMap.insert(std::pair<std::string, int>((*it).second, (*it).first)); + } + m_scantypes = revMap; + +} + +void PrimListGui::setFlavor(std::string pFlavor) +{ + flavor = pFlavor; +} +int PrimListGui::parseScan(std::string line)//Name,Flavor,Options +{ + PixScan* scan; + std::string scnName, scnFlavour, tmp; + std::istringstream buf(line); + getline(buf, scnName, ','); + getline(buf, scnFlavour, ','); + //to uppercase for user error + std::transform(scnName.begin(), scnName.end(), scnName.begin(), ::toupper); + std::transform(scnFlavour.begin(), scnFlavour.end(), scnFlavour.begin(), ::toupper); + //remove accidental spaces + std::string::iterator end_pos = std::remove(line.begin(), line.end(), ' '); + line.erase(end_pos, line.end()); + if (scnName == NULL || scnName == "" || scnFlavour == NULL || scnFlavour == "" ) + { + return 1; //error + } + PixLib::EnumFEflavour::FEflavour fl=PixLib::EnumFEflavour::PM_FE_I4A; + if(scnFlavour=="FEI3")fl=PixLib::EnumFEflavour::PM_FE_I2; + else if (scnFlavour=="FEI4A")fl=PixLib::EnumFEflavour::PM_FE_I4A; + else if (scnFlavour=="FEI4B")fl=PixLib::EnumFEflavour::PM_FE_I4B; + if(m_scantypes.find(scnName)==m_scantypes.end())return 2; //error + scan = new PixScan((PixScan::ScanType) m_scantypes[scnName],fl); + std::string preScript=""; + std::string postScript=""; + std::string topConfig=""; + bool updateConfig=true; + std::vector<std::string> enables; + std::vector<std::string> disables; + int pause=0; + //Look for optional scan parameters + std::string optPar; + while (getline(buf, optPar, ',')) + { + std::string paramName, paramVal; + std::istringstream buf2 (optPar); + getline(buf2, paramName, '='); + getline(buf2, paramVal); + int err=setScanParam(paramName, paramVal, scan, preScript, postScript, enables, disables, + updateConfig, topConfig, pause); + if(err!=0){ + delete scan; + return 3; + } + } + m_pList->addScan(scnName, scan, preScript, postScript, enables, disables, updateConfig, topConfig, pause); + + + return 0; + +} +int PrimListGui::toInt(std::string str) +{ + int result; + std::stringstream(str) >> result; + return result; +} + +void PrimListGui::load() +{ + + TGFileInfo fileinfo; + new TGFileDialog(gClient->GetRoot(), 0, kFDOpen, &fileinfo); + if(!fileinfo.fFilename){ + printf("Scheisse\n"); + return; + } + int load = loadPrimList(fileinfo.fFilename); + std::stringstream buf; + if(load != 0 && isLoaded()) { + buf << "Loaded "<< load << " items from " << fileinfo.fFilename<<". "<<getNumScans()<<" items total."; + updateStatus(buf.str()); + } + currentScan=0; +} +void PrimListGui::clear() +{ + currentScan=0; + m_pList->clearScans(); + std::stringstream buf; + buf << "No primlist loaded."; + updateStatus(buf.str()); +} +int PrimListGui::setScanParam(std::string name, std::string value, PixScan* pScan, std::string &preScript, + std::string &postScript, std::vector<std::string> &enabled, std::vector<std::string> &disabled, + bool &updateConfig, std::string &topConfig, int &pause) +{ + //convert name to uppercase to avoid any case issue + + std::transform(name.begin(), name.end(), name.begin(), ::toupper); + if(name.compare("TOPCONFIG")==0 ) + { + topConfig=value; + return 0; + } + if(name.compare("SCRIPT")==0 || name.compare("PRESCRIPT")==0 )//Don't want to change case! + { + preScript=value; + return 0; + } + if(name.compare("POSTSCRIPT")==0) + { + postScript=value; + return 0; + } + std::transform(value.begin(), value.end(), value.begin(), ::toupper); + if(name.compare("UPDATECONFIG")==0) + { + updateConfig=toBool(value); + } + else if(name.compare("PAUSE")==0) + { + pause=toInt(value); + } + else if(name.compare("MODSCANCONCURRENT")==0) + { + pScan->setModScanConcurrent(toBool(value)); + } + else if(name.compare("MASKSTAGESTEPS")==0) + { + pScan->setMaskStageSteps(toInt(value)); + } + else if (name.compare("TUNINGSTARTFROMCONFIGVALUE")==0) + { + pScan->tuningStartsFromCfgValues(toBool(value)); + } + else if (name.compare("REPETITIONS")==0) + { + pScan->setRepetitions(toInt(value)); + } + else if (name.compare("SELFTRIGGER")==0) + { + pScan->setSelfTrigger(toBool(value)) ; + } + else if (name.compare("STROBELVL1DELAYOVERRIDE")==0) + { + pScan->setStrobeLVL1DelayOveride(toBool(value)) ; + } + else if (name.compare("STROBELVL1DELAY")==0) + { + pScan->setStrobeLVL1Delay(toInt(value)) ; + } + else if (name.compare("LVL1LATENCY")==0) + { + pScan->setLVL1Latency(toInt(value)) ; + } + else if (name.compare("STROBEMCCDELAY")==0) + { + pScan->setStrobeMCCDelay(toInt(value)) ; + } + else if (name.compare("STROBEMCCDELAYRANGE")==0) + { + pScan->setStrobeMCCDelayRange(toInt(value)) ; + } + else if (name.compare("STROBEDURATION")==0) + { + pScan->setStrobeDuration(toInt(value)) ; + } + else if (name.compare("CLEARMASKS")==0) + { + pScan->setClearMasks(toInt(value)) ; + } + else if (name.compare("MODULEMASK")==0)//format MODULEMASK=Group;Mask + { + std::vector <std::string> values = toVector(value); + int group = toInt(values[0]); + int mask = toInt(values[1]); + pScan->setModuleMask(group,mask); + } + else if (name.compare("CONFIGENABLED")==0)//format Group;Enabled + { + std::vector <std::string> values = toVector(value); + int group = toInt(values[0]); + bool ena = toBool(values[1]); + pScan->setConfigEnabled(group,ena); + } + else if (name.compare("TRIGGERENABLED")==0)//format Group;Enabled + { + std::vector <std::string> values = toVector(value); + int group = toInt(values[0]); + bool ena = toBool(values[1]); + pScan->setTriggerEnabled(group,ena); + } + else if (name.compare("STROBEENABLED")==0)//format Group;Enabled + { + std::vector <std::string> values = toVector(value); + int group = toInt(values[0]); + bool ena = toBool(values[1]); + pScan->setStrobeEnabled(group,ena); + } + else if (name.compare("MODULEMASK")==0) + { + pScan->setStrobeMCCDelayRange(toInt(value)) ; + } + else if (name.compare("FEVCAL")==0) + { + pScan->setFeVCal(toInt(value)) ; + } + else if (name.compare("THRESHOLDTARGETVALUE")==0) + { + if(toInt(value)>0)//If value is 0, should just use default + pScan->setThresholdTargetValue(toInt(value)); + } + else if (name.compare("TOTTARGETCHARGE")==0) + { + if(toInt(value)>0)//If value is 0, should just use default + pScan->setTotTargetCharge(toInt(value)); + } + else if (name.compare("TOTTARGETVALUE")==0) + { + if(toInt(value)>0)//If value is 0, should just use default + pScan->setTotTargetValue(toInt(value)); + } + else if (name.compare("STEPSTAGE")==0) + { + pScan->setStepStage(toInt(value)); + } + else if (name.compare("SETUPTHRESHOLD")==0) + { + pScan->setSetupThreshold(toBool(value)); + } + else if (name.compare("THRESHOLD")==0) + { + pScan->setThreshold(toInt(value)); + } + else if (name.compare("TIMEOUTSECONDS")==0) + { + pScan->setTimeoutSeconds(toInt(value)); + } + else if (name.compare("LVL1LATENCY")==0) + { + pScan->setLVL1Latency(toInt(value)); + } + else if (name.compare("STROBEDURATION")==0) + { + pScan->setStrobeDuration(toInt(value)); + } + + else if (name.compare("MODCONFIGTYPE")==0) + { + PixLib::EnumModConfigType enumObj; + std::map<std::string, int> enummap = enumObj.EnumModConfigTypeMap(); + pScan->setModConfig((PixLib::EnumModConfigType::ModConfigType)enummap[value]); + } + else if (name.compare("MASKSTAGEMODE")==0) + { + PixLib::EnumMaskStageMode enumObj; + std::map<std::string, int> enummap = enumObj.EnumMaskStageModeMap(); + pScan->setMaskStageMode((PixLib::EnumMaskStageMode::MaskStageMode)enummap[value]); + + } + else if (name.compare("MASKSTAGETOTALSTEPS")==0) + { + PixLib::EnumMaskSteps enumObj; + std::map<std::string, int> enummap = enumObj.EnumMaskStageStepsMap(); + pScan->setMaskStageTotalSteps((PixLib::EnumMaskSteps::MaskStageSteps)enummap[value]); + } + else if (name.compare("MODULETRGMASK")==0) + { + pScan->setModuleTrgMask(toInt(value)); + } + //Loop Variable Values + else if (name.compare("LOOPVARVALUES")==0) + { + int index; + std::string tmp; + std::istringstream buf (value); + getline(buf, tmp, ';'); + index = toInt(tmp); + size_t begOfVector = value.find('['); + if(begOfVector == std::string::npos)//then format index;startVal;endVal;nSteps + { + int nSteps; + double startVal, endVal; + getline(buf, tmp, ';'); + startVal=toDouble(tmp); + getline(buf, tmp, ';'); + endVal=toDouble(tmp); + getline(buf, tmp, ';'); + nSteps=toInt(tmp); + pScan->setLoopVarValues(index, startVal, endVal, nSteps); + } + else //then format [val1;val2;val3;...] + { + std::vector <float> values; + size_t endOfVector = value.find(']'); + value = value.substr(begOfVector+1, endOfVector-begOfVector-1); //trim off index[, ] + new (&buf) std::istringstream (value); + while (getline(buf, tmp, ';')) + { + values.push_back(toDouble(tmp)); + } + pScan->setLoopVarValues(index, values); + + } + + } + else if (name.compare("ENABLEFES")==0 || name.compare("DISABLEFES")==0 ) + { + value.erase (std::remove (value.begin(), value.end(), ' '), value.end()); + std::string tmp; + std::istringstream buf (value); + std::vector <float> values; + while (getline(buf, tmp, ';')) + { + if(name.compare("ENABLEFES")==0)enabled.push_back(tmp); + else disabled.push_back(tmp); + } + } + else + { + std::string st = "Unrecognized scan parameter name: " + name; + updateStatus(st); + return 1; + } + return 0; + +} +std::vector <std::string> PrimListGui::toVector(std::string value) +{ + std::vector <std::string> values; + std::istringstream buf (value); + std::string tmp; + while (getline(buf, tmp, ';')) + { + values.push_back(tmp); + } + return values; +} +double PrimListGui::toDouble(std::string val) +{ + double result; + std::stringstream(val) >> result; + return result; +} +bool PrimListGui::toBool(std::string val) +{ + bool result; + std::stringstream(val) >> result; + return result; +} + +bool PrimListGui::isLoaded() +{ + return m_pList->nScans() > 0; +} +void PrimListGui::updateStatus(std::string str) +{ + updateText(plStatusLabel, str.c_str()); +} +int PrimListGui::getNumScans() +{ + return m_pList->nScans(); +} +std::string PrimListGui::getCurrScanName() +{ + return m_pList->getScanName(currentScan); + +} +RCE::PixScan* PrimListGui::getCurrentScan() +{ + return getPrimList()->getScan(currentScan); +} +std::string PrimListGui::getCurrentPreScript() +{ + return m_pList->getPreScript(currentScan); +} +std::string PrimListGui::getCurrentPostScript() +{ + return m_pList->getPostScript(currentScan); +} +int PrimListGui::getCurrentPause() +{ + return m_pList->getPause(currentScan); +} +std::string PrimListGui::getCurrentTopConfig() +{ + return m_pList->getTopConfig(currentScan); +} +ipc::ScanOptions* PrimListGui::getCurrentScanConfig() +{ + return getPrimList()->getScanOptions(currentScan); +} +std::vector<std::string>& PrimListGui::getCurrentDisabledList(){ + return m_pList->getDisabledList(currentScan); +} +std::vector<std::string>& PrimListGui::getCurrentEnabledList(){ + return m_pList->getEnabledList(currentScan); +} +void PrimListGui::setRunNumber(int runnum){ + getCurrentScan()->setRunNumber(runnum); + getCurrentScanConfig()->runNumber=runnum; +} + +bool PrimListGui::getCurrentUpdateConfig() +{ + return m_pList->getUpdateConfig(currentScan); +} + +void PrimListGui::changeIncludes(ConfigGui* cfg[]){ + for (int i=0;i<ConfigGui::MAX_MODULES;i++){ + if(cfg[i]->isIncluded()){ + std::vector<std::string> dis=getCurrentDisabledList(); + for(size_t j=0;j<dis.size();j++){ + if (cfg[i]->getName()==dis[j]){ + cfg[i]->setIncluded(false); + std::cout<<"Disabled FE "<<dis[j]<<std::endl; + break; + } + } + }else if (cfg[i]->isValid()){ + std::vector<std::string> en=getCurrentEnabledList(); + for(size_t j=0;j<en.size();j++){ + if (cfg[i]->getName()==en[j]){ + cfg[i]->setIncluded(true); + std::cout<<"Enabled FE "<<en[j]<<std::endl; + break; + } + } + } + } +} + + + + + diff --git a/rce/rcecalib/server/PrimListGui.hh b/rce/rcecalib/server/PrimListGui.hh new file mode 100644 index 00000000..a306e605 --- /dev/null +++ b/rce/rcecalib/server/PrimListGui.hh @@ -0,0 +1,83 @@ +#ifndef PRIMLISTGUI_HH +#define PRIMLISTGUI_HH + +#include <TGButton.h> +#include <TGTextEntry.h> +#include <TGNumberEntry.h> +#include <TGLabel.h> +#include <TGComboBox.h> +#include <TGListBox.h> +#include <TGFileDialog.h> +#include <TGListView.h> +#include <fstream> +#include <string> +#include <map> +#include <utility> + + +//push update after scan +namespace ipc{ + class ScanOptions; +} +namespace RCE { + class PixScan; + class PrimList; +} +class ConfigGui; + +class PrimListGui: public TGVerticalFrame{ +public: + PrimListGui(const char* name, const TGWindow *p, UInt_t w, UInt_t h, UInt_t options); + virtual ~PrimListGui(); + void print(std::ostream &os); + void printFromGui(); + void disableControls(); + void enableControls(); + RCE::PrimList* getPrimList(); + void load(); + int loadPrimList(const char* fPath); + void clear(); + void setFlavor(std::string pFlavor); + void setScanTypes (std::map<int, std::string> pscantypes); + bool isLoaded(); + void updateStatus(std::string str); + int currentScan; + std::string getCurrScanName(); + int getNumScans(); + RCE::PixScan* getCurrentScan(); + ipc::ScanOptions* getCurrentScanConfig(); + std::string getCurrentPreScript(); + std::string getCurrentPostScript(); + std::string getCurrentTopConfig(); + std::vector<std::string>& getCurrentDisabledList(); + std::vector<std::string>& getCurrentEnabledList(); + bool getCurrentUpdateConfig(); + int getCurrentPause(); + void changeIncludes(ConfigGui* cfg[]); + void setFailed(bool on){m_failed=on;} + bool failed(){return m_failed;} + void setRunNumber(int runnum); +private: + RCE::PrimList* m_pList; + TGLabel *m_name; + TGLabel *plStatusLabel; + void updateText(TGLabel* label, const char* newtext); + //both flavor passed from CalibGui + std::string flavor; + //scan types copied from ScanGui + std::map<std::string, int> m_scantypes; + bool m_failed; + //helper functions + int toInt(std::string); + int parseScan(std::string line); + int setScanParam(std::string name, std::string value, RCE::PixScan* pScan, std::string &preScript, + std::string &postScript, std::vector<std::string> &enabled, + std::vector<std::string> &disabled, bool &updateConfig, std::string &topConfig, int &pause); + bool toBool(std::string val); + double toDouble(std::string val); + std::vector <std::string> toVector(std::string value); + + ClassDef(PrimListGui,0); +}; + +#endif diff --git a/rce/rcecalib/server/RceControl.cc b/rce/rcecalib/server/RceControl.cc new file mode 100644 index 00000000..6a2aef12 --- /dev/null +++ b/rce/rcecalib/server/RceControl.cc @@ -0,0 +1,123 @@ +#include <stdio.h> +#include <iostream> +#include <fstream> +#include <string.h> +#include "rcecalib/server/BootLoaderPort.hh" +#include <boost/algorithm/string.hpp> +#include <termios.h> +#include "RceControl.hh" + +#include <arpa/inet.h> // for htonl +namespace RCE { + RceControl::RceControl(const char *rce,int timeout):m_rce(rce),m_timeout(timeout) { + m_dst=RceNet::IpAddress(RceNet::getaddr(rce),BootloaderPort);} + + int RceControl::setEnvVar(const char *var,const char *val) { + std::string inpline; + inpline="setenv "+std::string(var)+std::string(" ")+std::string(val); + sendCommand(inpline); + return 0; + } + + + + int RceControl::setIorFromFile(const char *iorfile) { + std::string inpline; + //std::istream *inp; + if(!iorfile) iorfile=getenv("TDAQ_IPC_INIT_REF"); + if(strstr(iorfile,"file:/") )iorfile+=6; + if(iorfile){ + std::ifstream g(iorfile); + if (!g.good()) { + std::cout<<"Error: Could not find file "<<iorfile<<std::endl; + return -1; + } + inpline=""; + getline (g,inpline); + g.close(); + if(inpline.substr(0,4)!="IOR:"){ + std::cout<<"Error: "<<iorfile<<" does not contain an IOR string"<<std::endl; + return -1; + } + inpline="setenv TDAQ_IPC_INIT_REF "+inpline; + sendCommand(inpline); + } + return 0; + } + +int RceControl::loadModule(const char *filename) { + if(!filename) return -1; + // Read module into buffer + std::ifstream f(filename); + if (!f.good()) { + std::cout<<"Error: Could not find file "<<filename<<std::endl; + return -1; + } + f.seekg(0, std::ios::end); + unsigned length = f.tellg(); + f.seekg(0, std::ios::beg); + char *buffer=new char[length]; + f.read(buffer,length); + char msg[128]; + // send download command + sprintf(msg,"download %d bytes",length); + std::string rep=sendCommand(msg); + if(rep!="OK") return -1; + std::cout<<"HOST"<<" => "<<m_rce<<": Uploading module."<<std::endl; + // download module + RceNet::SocketTcp socket2; + socket2.connect(m_dst); + socket2.send(buffer, length); + delete [] buffer; + // receive confirmation + socket2.setrcvtmo(m_timeout); + int bytes=socket2.recv(msg,128); + socket2.close(); + if(bytes<0){ + std::cout<<"Receive error."<<std::endl; + } + msg[bytes]=0; + std::cout<<"HOST"<<" <= "<<m_rce<<": "<<msg<<std::endl; + return 0; +} + +const char* RceControl::sendCommand(std::string inpline){ + std::cout<<"HOST"<<" => "<<m_rce<<": "<<inpline<<std::endl; + RceNet::SocketTcp *socket=0; + int nretries=10; + while(nretries>0){ + try{ + socket=new RceNet::SocketTcp; + socket->connect(m_dst); + socket->send(inpline.c_str(), inpline.size()); + break; + } catch (...){ + //std::cout<<"Connect failed. Trying again"<<std::endl; + nretries--; + delete socket; + sleep(1); + } + } + if(nretries==0){ + std::cout<<"Network error. Exiting."<<std::endl; + exit(0); + } + static char line[128]; + try{ + socket->setrcvtmo(m_timeout); + int bytes=socket->recv(line,128); + line[bytes]=0; + std::cout<<"HOST"<<" <= "<<m_rce<<": "<<line<<std::endl; + //if(std::string(line)=="Rebooting...")sleep(1); // wait for reboot to finish + } + catch (...){ + std::cout<<"Network error. Exiting."<<std::endl; + delete socket; + return 0; + } + socket->close(); + delete socket; + return line; +} + +} diff --git a/rce/rcecalib/server/RceControl.hh b/rce/rcecalib/server/RceControl.hh new file mode 100644 index 00000000..4e89e2a8 --- /dev/null +++ b/rce/rcecalib/server/RceControl.hh @@ -0,0 +1,34 @@ +#ifndef __RCE_CONTROL_HH__ +#define __RCE_CONTROL_HH__ +#ifdef RCE_V2 +#include "datCode.hh" +#include DAT_PUBLIC( oldPpi, net, IpAddress.hh) +#include DAT_PUBLIC( oldPpi, net, Error.hh) +#include DAT_PUBLIC( oldPpi, net, Getaddr.hh) +#include DAT_PUBLIC( oldPpi, net, SocketTcp.hh) + +#else +#include "rce/net/IpAddress.hh" +#include "rce/net/Getaddr.hh" +#include "rce/net/IpAddress.hh" +#include "rce/net/SocketTcp.hh" +#include "rce/net/Error.hh" +#endif +#include "namespace_aliases.hh" +namespace RCE { + class RceControl { + public: + RceControl(){}; + RceControl(const char *rce,int timeout=10000); + int setIorFromFile(const char* iorfile=NULL); + int setEnvVar(const char* var,const char *val); + int loadModule(const char *name); + int runScript(const char *name); + const char* sendCommand(std::string inpline); + private: + std::string m_rce; + int m_timeout; + RceNet::IpAddress m_dst; + }; +} +#endif diff --git a/rce/rcecalib/server/RceOfflineProducer.cc b/rce/rcecalib/server/RceOfflineProducer.cc new file mode 100644 index 00000000..ba429f85 --- /dev/null +++ b/rce/rcecalib/server/RceOfflineProducer.cc @@ -0,0 +1,380 @@ +#include "rcecalib/server/RceOfflineProducer.hh" +#include "rcecalib/server/CosmicDataReceiver.hh" +#include "rcecalib/server/CosmicDataReceiver.hh" +#include "rcecalib/config/ModuleInfo.hh" +#include "rcecalib/eudaq/ProducerIF.hh" +#include "rcecalib/eudaq/RawDataEvent.hh" +#include "rcecalib/eudaq/Utils.hh" +#include "rcecalib/eudaq/Exception.hh" +#include "rcecalib/server/PixScan.hh" +#include "rcecalib/server/TurboDaqFile.hh" +#include "rcecalib/server/FEI4AConfigFile.hh" +#include "rcecalib/server/FEI4BConfigFile.hh" +#include "rcecalib/server/HitbusConfigFile.hh" +#include "rcecalib/config/FEI3/JJFormatter.hh" +#include "rcecalib/config/FEI4/FEI4AFormatter.hh" +#include "rcecalib/config/FEI4/FEI4BFormatter.hh" +#include <cmdl/cmdargs.h> +#include "rcecalib/util/RceName.hh" +#include <iostream> +#include <ostream> +#include <vector> +#include <stdio.h> +#include <sys/stat.h> +#include <ipc/core.h> + +#include <netdb.h> + +namespace{ + static const std::string EVENT_TYPE = "APIX-CT"; + + void startScan(void* arg){ + IPCController* controller=(IPCController*)arg; + controller->startScan(); + } +} +using namespace RCE; + +RceOfflineProducer::RceOfflineProducer(const std::string & name, const std::string & runcontrol, IPCPartition& p, int rce) + : eudaq::Producer(name, runcontrol), m_run(0), m_PlaneMask(0), m_conseq(1), m_rce(rce), m_controller(new IPCController(p)), + m_options(0), m_datareceiver(0){ + std::cout<<"Rce producer on RCE "<<m_rce<<std::endl; +} + +RceOfflineProducer::~RceOfflineProducer(){ + delete m_controller; + if (m_datareceiver) delete m_datareceiver; + m_datareceiver = 0; +} +// This gets called whenever the DAQ is configured +void RceOfflineProducer::OnConfigure(const eudaq::Configuration & config) { + std::cout << "Configuring: " << config.Name() << std::endl; + std::cout<<config<<std::endl; + char msg[64]; + try{ + //Default Trigger IF + for(size_t i=0;i<m_moduleinfo.size();i++){ + delete m_moduleinfo[i]->getFormatter(); + delete m_moduleinfo[i]; + } + m_moduleinfo.clear(); + m_controller->removeAllRces(); + m_controller->addRce(m_rce); + m_controller->setupTrigger(); + m_controller->removeAllModules(); + m_numboards = config.Get("nFrontends", -1); + if(m_numboards==-1)throw eudaq::Exception("nFrontends not defined"); + m_link.clear(); + m_sensor.clear(); + m_pos.clear(); + m_stype.clear(); + for(int i=0;i<m_numboards;i++){ + int outlink = config.Get("Module" + eudaq::to_string(i) + ".OutLink", "OutLink", -1); + if(outlink==-1){ + sprintf(msg,"Module %d: Outlink is not defined.",i); + throw eudaq::Exception(msg); + } + m_link.push_back(outlink); + int inlink = config.Get("Module" + eudaq::to_string(i) + ".InLink", "InLink", -1); + if(inlink==-1){ + sprintf(msg,"Module %d: Inlink is not defined.",i); + throw eudaq::Exception(msg); + } + int id = config.Get("Module" + eudaq::to_string(i) + ".FEID", "FEID", -1); + if(id==-1){ + sprintf(msg,"Frontend %d: FEID is not defined.",i); + throw eudaq::Exception(msg); + } + int sid = config.Get("Module" + eudaq::to_string(i) + ".SensorId", "SensorId", -1); + if(sid==-1){ + sprintf(msg,"Frontend %d: sensor id is not defined.",i); + throw eudaq::Exception(msg); + } + m_sensor.push_back(sid); + int lr = config.Get("Module" + eudaq::to_string(i) + ".Position", "Position", -1); + if(lr==-1){ + sprintf(msg,"Frontend %d: Position is not defined.",i); + throw eudaq::Exception(msg); + } + m_pos.push_back(lr); + int stype = config.Get("Module" + eudaq::to_string(i) + ".ModuleType", "ModuleType", -1); + if(stype==-1){ + sprintf(msg,"Frontend %d: Module sensor type is not defined.",i); + throw eudaq::Exception(msg); + } + if(stype<1 || stype>4){ //only 1, 2, and 4-chip modules and FEI3 chips are defined at this point + sprintf(msg,"Frontend %d: Module sensor type %d does not exist.", i, stype); + throw eudaq::Exception(msg); + } + if(stype!=3 && lr>=stype){ + sprintf(msg,"Frontend %d: Position %d does not exist in %d-chip sensors.", i, lr, stype); + throw eudaq::Exception(msg); + } + if(m_stype.find(sid)==m_stype.end())m_stype[sid]=stype; + else if(m_stype[sid]!=stype){ + sprintf(msg, "Module %d: Definition of module type clashes with the definition for a different FE of the same sensor", i); + throw eudaq::Exception(msg); + } + std::string modtype = config.Get("Module" + eudaq::to_string(i) + ".Type", "Type", ""); + if(modtype==""){ + sprintf(msg,"Module %d: Module frontend type is not defined.",i); + throw eudaq::Exception(msg); + } + std::string filename = config.Get("Module" + eudaq::to_string(i) + ".File", "File", ""); + if(filename==""){ + sprintf(msg,"Module %d: Configuration filename is not defined.",i); + throw eudaq::Exception(msg); + } + + struct stat stFileInfo; + int intStat; + // Attempt to get the file attributes + intStat = stat(filename.c_str(),&stFileInfo); + if(intStat!=0) { //file does not exist + sprintf(msg, "Configuration: File %s does not exist.",filename.c_str()); + throw eudaq::Exception(msg); + } + // create module via IPC + char modname[32]; + sprintf(modname,"RCE%d_module_%d",m_rce, outlink); + if(modtype=="FEI4A"){ + printf("FEI4A: addModule (%s, %d, %d, %d, %d)\n",modname, 0, inlink, outlink, m_rce); + m_controller->addModule(modname, "FEI4A",id, inlink, outlink, m_rce, "FEI4A"); + m_moduleinfo.push_back(new ModuleInfo(modname, id, inlink, outlink, 1, 336, 80, new FEI4AFormatter(id))); + FEI4AConfigFile fei4af; + ipc::PixelFEI4AConfig *cfg=new ipc::PixelFEI4AConfig; + fei4af.readModuleConfig(cfg, filename); + m_controller->downloadModuleConfig(m_rce, id,*cfg); + delete cfg; + // assert(m_controller.writeHWregister(15,0x80)==0); //setup mux + } else if(modtype=="FEI4B"){ + printf("FEI4B: addModule (%s, %d, %d, %d, %d)\n",modname, id, inlink, outlink, m_rce); + m_controller->addModule(modname, "FEI4B",id, inlink, outlink, m_rce, "FEI4B"); + m_moduleinfo.push_back(new ModuleInfo(modname, id, inlink, outlink, 1, 336, 80, new FEI4BFormatter(id))); + FEI4BConfigFile fei4bf; + ipc::PixelFEI4BConfig *cfg=new ipc::PixelFEI4BConfig; + fei4bf.readModuleConfig(cfg, filename); + m_controller->downloadModuleConfig(m_rce, id,*cfg); + delete cfg; + }else if(modtype=="FEI3"){ + printf("FEI3: addModule (%s, %d, %d, %d, %d)\n",modname, id, inlink, outlink, m_rce); + m_controller->addModule(modname, "FEI3",id, inlink, outlink, m_rce, "JJ"); + m_moduleinfo.push_back(new ModuleInfo(modname, id, inlink, outlink, 16, 160, 18, new JJFormatter(id))); + TurboDaqFile turbo; + ipc::PixelModuleConfig *cfg=new ipc::PixelModuleConfig; + turbo.readModuleConfig(cfg, filename); + m_controller->downloadModuleConfig(m_rce, id,*cfg); + delete cfg; + } else if(modtype=="Hitbus"){ + printf("Hitbus: addModule (%s, %d, %d, %d, %d)\n",modname, id, inlink, outlink, m_rce); + m_controller->addModule(modname, "Hitbus",id, inlink, outlink, m_rce, ""); + //m_moduleinfo.push_back(new ModuleInfo(modname, id, inlink, outlink, 0, 0, 0, 0)); + HitbusConfigFile hitbusf; + ipc::HitbusModuleConfig *cfg=new ipc::HitbusModuleConfig; + hitbusf.readModuleConfig(cfg, filename); + m_controller->downloadModuleConfig(m_rce, id,*cfg); + }else{ + std::cout<<"Unknown config"<<std::endl; + } + } + // set up hardware trigger + unsigned goodHSIOconnection=0; + goodHSIOconnection=m_controller->writeHWregister(m_rce, 3,2); //runmode 0=normal 1=tdccalib 2=eudaq assert(serstat==0); + assert(goodHSIOconnection==0); + m_controller->sendHWcommand(m_rce, 17); // Tell the HSIO that the RCE is present. + //serstat=m_controller->writeHWregister(0, 22,1); // coincidence l1 + //serstat=m_controller->writeHWregister(0, 23,1); // coincidence hitbus + //serstat=m_controller->writeHWregister(0, 24,3); // coincidence hitbus + //m_controller.writeHWregister(3,0); //Normal mode + + // Scan configuration + std::cout<<"Deleting scan options "<<m_options<<std::endl; + delete m_options; + PixScan scn(PixScan::COSMIC_DATA, PixLib::EnumFEflavour::PM_FE_I2); + m_options=new ipc::ScanOptions; + scn.setName("TCP"); // send data over the network rather than to file + // Override l1a latency + int latency = config.Get("Latency", -1); + if(latency==-1){ + throw eudaq::Exception("Latency is not defined."); + } + scn.setLVL1Latency(latency); + m_conseq = config.Get("ConseqTriggers", -1); + if(m_conseq==(unsigned)-1){ + throw eudaq::Exception("Number of consecutive triggers is not defined."); + } + scn.setConsecutiveLvl1TrigA(0,m_conseq); + int trgdelay = config.Get("Trgdelay", -1); + if(trgdelay==-1){ + throw eudaq::Exception("Trigger delay is not defined."); + } + scn.setStrobeLVL1Delay(trgdelay); + int deadtime = config.Get("Deadtime", 0); + scn.setDeadtime(deadtime); + int cyclic = config.Get("Cyclic_Period", 40000000); + scn.setEventInterval(cyclic); + scn.setTriggerMask(4); // eudet=4 + + scn.convertScanConfig(*m_options); + //m_controller->downloadScanConfig(*m_options); + // At the end, set the status that will be displayed in the Run Control. + SetStatus(eudaq::Status::LVL_OK, "Configured (" + config.Name() + ")"); + } catch (const std::exception & e) { + printf("Caught exception: %s\n", e.what()); + SetStatus(eudaq::Status::LVL_ERROR, "Configuration Error"); + } catch (...) { + printf("Unknown exception\n"); + SetStatus(eudaq::Status::LVL_ERROR, "Configuration Error"); + } +} + + // This gets called whenever a new run is started + // It receives the new run number as a parameter +void RceOfflineProducer::OnStartRun(unsigned param) { + m_run = param; + std::string port="33000"; + std::cout << "Start Run: " << m_run << std::endl; + std::stringstream ss("tcp://"); + ss<<getenv("ORBHOST"); + ss << ":" << port; + std::string address = ss.str(); + std::cout << "<CosmicGui::startRun> : Server address is: " << address << std::endl; + char name[128]; + sprintf(name,"CosmicGui|%05d|%s",m_run,address.c_str()); + m_options->name=CORBA::string_dup(name); + + std::cout << "CosmicGui: starting CosmicDataReceiver at tcp://" << port << std::endl; + std::vector<int> rcesAll; + if(m_numboards>0) for(int i=0;i<m_numboards;i++)rcesAll.push_back(m_rce); //only one RCE + else rcesAll.push_back(m_rce); // no FEs + m_datareceiver = new CosmicDataReceiver(0, m_controller, m_moduleinfo, rcesAll, + m_run, "tcp://" + port, "", false, false); + + m_controller->downloadScanConfig(*m_options); + // It must send a BORE to the Data Collector + eudaq::RawDataEvent bore(eudaq::RawDataEvent::BORE(EVENT_TYPE, m_run)); + // You can set tags on the BORE that will be saved in the data file + // and can be used later to help decoding + bore.SetTag("nFrontends", eudaq::to_string(m_numboards)); + bore.SetTag("consecutive_lvl1", eudaq::to_string(m_conseq)); + char tagname[128]; + for(int i=0;i<m_numboards;i++){ + sprintf(tagname, "OutLink_%d", i); + bore.SetTag(tagname, eudaq::to_string(m_link[i])); + sprintf(tagname, "SensorId_%d", i); + bore.SetTag(tagname, eudaq::to_string(m_sensor[i])); + sprintf(tagname, "Position_%d", i); + bore.SetTag(tagname, eudaq::to_string(m_pos[i])); + sprintf(tagname, "ModuleType_%d", i); + bore.SetTag(tagname, eudaq::to_string(m_stype[m_sensor[i]])); + } + // Send the event to the Data Collector + SendEvent(bore); + // Enable writing events via tcp/ip + ProducerIF::setProducer(this); + //start run + omni_thread::create(startScan,(void*)m_controller); + //m_controller->startScan(); + + std::cout<<"Started scan"<<std::endl; + // At the end, set the status that will be displayed in the Run Control. + SetStatus(eudaq::Status::LVL_OK, "Running"); + } + + // This gets called whenever a run is stopped +void RceOfflineProducer::OnStopRun() { + std::cout << "Stopping Run" << std::endl; + + m_controller->stopWaitingForData(); + //wait for late events to trickle in + sleep(1); + //wait for scan to be complete + bool idle=false; + for(int i=0;i<50;i++){ + if(m_controller->getScanStatus()==0){ + std::cout<<"called getstatus"<<std::endl; + idle=true; + break; + } + usleep(100000); + } + if(idle==false)std::cout<<"Scan did not go into idle state"<<std::endl; + //disable sending events via TCP/IP + if (m_datareceiver) delete m_datareceiver; + m_datareceiver = 0; + + ProducerIF::setProducer(0); + // Send an EORE after all the real events have been sent + // You can also set tags on it (as with the BORE) if necessary + unsigned evnum=m_controller->getNEventsProcessed(); + SendEvent(eudaq::RawDataEvent::EORE(EVENT_TYPE, m_run, evnum)); + SetStatus(eudaq::Status::LVL_OK, "Stopped"); + } + + // This gets called when the Run Control is terminating, + // we should also exit. +void RceOfflineProducer::OnTerminate() { + std::cout << "Terminating..." << std::endl; + if (m_datareceiver) delete m_datareceiver; + m_datareceiver = 0; + exit(0); + } + +int main ( int argc, char ** argv ) +{ + CmdArgStr partition_name ('p', "partition", "partition-name", "partition to work in."); + CmdArgInt rce_number ('r', "rce", "rce-number", "RCE to connect to", CmdArg::isREQ | CmdArg::isVALREQ); + CmdArgStr hostname ('d', "runcontrol", "runcontrol-host", "Run control hostname.", CmdArg::isREQ | CmdArg::isVALREQ); + + try { + IPCCore::init( argc, argv ); + } + catch( daq::ipc::Exception & ex ) { + ers::fatal( ex ); + return 1; + } + + // Declare command object and its argument-iterator + CmdLine cmd(*argv, &partition_name, &rce_number, &hostname, NULL); + CmdArgvIter arg_iter(--argc, ++argv); + + // Parse arguments + + cmd.parse(arg_iter); + + std::string rchost; + hostent * ipAddrContainer = gethostbyname((const char*)hostname); + if (ipAddrContainer != 0) { + int nBytes; + if (ipAddrContainer->h_addrtype == AF_INET) nBytes = 4; + else if (ipAddrContainer->h_addrtype == AF_INET6) nBytes = 6; + else { + std::cout << "Unrecognized IP address type. Run not started." + << std::endl; + exit(0); + } + std::stringstream ss("tcp://"); + ss << "tcp://"; + for (int i = 0, curVal; i < nBytes; i++) + { + curVal = static_cast<int>(ipAddrContainer->h_addr[i]); + if (curVal < 0) curVal += 256; + ss << curVal; + if (i != nBytes - 1) ss << "."; + } + ss<<":44000"; + rchost=ss.str(); + }else{ + std::cout<<"Bad IP address. Exiting."<<std::endl; + exit(0); + } + const char *p_name=getenv("TDAQ_PARTITION"); + if(p_name==NULL) p_name="rcetest"; + if(! partition_name.isNULL()) p_name= (const char*)partition_name; + int rce=(int)rce_number; + IPCPartition p(p_name ); + IPCController controller(p); + new IPCHistoManager(p,"RceIsServer", "dummy"); + RceOfflineProducer producer("RceOfflineProducer", rchost.c_str(), p, rce); + sleep(100000000); +} diff --git a/rce/rcecalib/server/RceOfflineProducer.hh b/rce/rcecalib/server/RceOfflineProducer.hh new file mode 100644 index 00000000..6cef3ac3 --- /dev/null +++ b/rce/rcecalib/server/RceOfflineProducer.hh @@ -0,0 +1,38 @@ +#ifndef RCEPRODUCER_HH +#define RCEPRODUCER_HH + +#include "eudaq/Producer.hh" + +#include "rcecalib/server/IPCController.hh" +#include <vector> + +class ModuleInfo; +class CosmicDataReceiver; + +class RceOfflineProducer : public eudaq::Producer { +public: + RceOfflineProducer(const std::string & name, const std::string & runcontrol, IPCPartition& p, int rce); + virtual ~RceOfflineProducer(); + virtual void OnConfigure(const eudaq::Configuration & config) ; + virtual void OnStartRun(unsigned param) ; + virtual void OnStopRun() ; + virtual void OnTerminate() ; + +private: + unsigned m_run; + unsigned m_PlaneMask; + unsigned m_conseq; + int m_numboards; + int m_rce; + std::vector<int> m_sensor; + std::vector<int> m_pos; + std::vector<int> m_link; + std::vector<int> m_id; + std::map<int, int> m_stype; + IPCController* m_controller; + ipc::ScanOptions* m_options; + std::vector<ModuleInfo*> m_moduleinfo; + CosmicDataReceiver *m_datareceiver; +}; + +#endif diff --git a/rce/rcecalib/server/RceProducer.cc b/rce/rcecalib/server/RceProducer.cc new file mode 100644 index 00000000..8d9ca1ea --- /dev/null +++ b/rce/rcecalib/server/RceProducer.cc @@ -0,0 +1,217 @@ +#include "rcecalib/server/RceProducer.hh" +#include "rcecalib/eudaq/ProducerIF.hh" +#include "rcecalib/eudaq/RawDataEvent.hh" +#include "rcecalib/eudaq/Utils.hh" +#include "rcecalib/eudaq/Exception.hh" +#include "rcecalib/server/PixScan.hh" +#include "rcecalib/server/TurboDaqFile.hh" +#include "rcecalib/server/FEI4AConfigFile.hh" +#include "rcecalib/server/FEI4BConfigFile.hh" +#include "rcecalib/util/RceName.hh" +#include <iostream> +#include <ostream> +#include <vector> +#include <stdio.h> +#include <sys/stat.h> + + +namespace{ + static const std::string EVENT_TYPE = "APIX-CT"; + + void startScan(void* arg){ + IPCController* controller=(IPCController*)arg; + controller->startScan(); + } +} +using namespace RCE; + +// This gets called whenever the DAQ is configured +void RceProducer::OnConfigure(const eudaq::Configuration & config) { + std::cout << "Configuring: " << config.Name() << std::endl; + std::cout<<"Deleting scan options "<<m_options<<std::endl; + char msg[64]; + unsigned rce=RceName::getRceNumber(); + try{ + //Default Trigger IF + m_controller.removeAllRces(); + m_controller->addRce(rce); + m_controller->setupTrigger(); + m_controller->removeAllModules(); + int numboards = config.Get("NumModules", -1); + if(numboards==-1)throw eudaq::Exception("NumModules not defined"); + for(int i=0;i<numboards;i++){ + int outlink = config.Get("Module" + eudaq::to_string(i) + ".OutLink", "OutLink", -1); + if(outlink==-1){ + sprintf(msg,"Module %d: Outlink is not defined.",i); + throw eudaq::Exception(msg); + } + m_PlaneMask|=1<<outlink; + int inlink = config.Get("Module" + eudaq::to_string(i) + ".InLink", "InLink", -1); + if(inlink==-1){ + sprintf(msg,"Module %d: Inlink is not defined.",i); + throw eudaq::Exception(msg); + } + int id = config.Get("Module" + eudaq::to_string(i) + ".Id", "Id", -1); + if(id==-1){ + sprintf(msg,"Module %d: id is not defined.",i); + throw eudaq::Exception(msg); + } + std::string modtype = config.Get("Module" + eudaq::to_string(i) + ".Type", "Type", ""); + if(modtype==""){ + sprintf(msg,"Module %d: Module type is not defined.",i); + throw eudaq::Exception(msg); + } + std::string filename = config.Get("Module" + eudaq::to_string(i) + ".File", "File", ""); + if(filename==""){ + sprintf(msg,"Module %d: Configuration filename is not defined.",i); + throw eudaq::Exception(msg); + } + + filename="/nfs/moduleconfigs/"+filename; + struct stat stFileInfo; + int intStat; + // Attempt to get the file attributes + intStat = stat(filename.c_str(),&stFileInfo); + if(intStat!=0) { //file does not exist + sprintf(msg, "Configuration: File %s does not exist.",filename.c_str()); + throw eudaq::Exception(msg); + } + // create module via IPC + char modname[32]; + sprintf(modname,"RCE%d_module_%d",rce, outlink); + if(modtype=="FEI4A"){ + printf("FEI4A: addModule (%s, %d, %d, %d, %d)\n",modname, 0, inlink, outlink, rce); + m_controller->addModule(modname, "FEI4A",id, inlink, outlink, rce, "FEI4A"); + FEI4AConfigFile fei4af; + ipc::PixelFEI4AConfig *cfg=new ipc::PixelFEI4AConfig; + fei4af.readModuleConfig(cfg, filename); + m_controller->downloadModuleConfig(modname,*cfg); + delete cfg; + // assert(m_controller.writeHWregister(15,0x80)==0); //setup mux + } else if(modtype=="FEI4B"){ + printf("FEI4B: addModule (%s, %d, %d, %d, %d)\n",modname, id, inlink, outlink, rce); + m_controller->addModule(modname, "FEI4B",id, inlink, outlink, rce, "FEI4B"); + FEI4BConfigFile fei4bf; + ipc::PixelFEI4BConfig *cfg=new ipc::PixelFEI4BConfig; + fei4bf.readModuleConfig(cfg, filename); + m_controller->downloadModuleConfig(modname,*cfg); + delete cfg; + }else{ + printf("FEI3: addModule (%s, %d, %d, %d, %d)\n",modname, inlink, inlink, rce, outlink); + m_controller->addModule(modname, "FEI3",id, inlink, outlink, rce, "JJ"); + TurboDaqFile turbo; + ipc::PixelModuleConfig *cfg=new ipc::PixelModuleConfig; + turbo.readModuleConfig(cfg, filename); + m_controller->downloadModuleConfig(modname,*cfg); + delete cfg; + } + } + // set up hardware trigger + unsigned serstat=0; + serstat=m_controller->writeHWregister(RceName::getRceNumber(), 3,1); //runmode 0=normal 1=tdccalib 2=eudaq + assert(serstat==0); + //m_controller.writeHWregister(3,0); //Normal mode + + // Scan configuration + std::cout<<"Deleting scan options "<<m_options<<std::endl; + delete m_options; + PixScan scn(PixScan::COSMIC_RCE, PixLib::EnumFEflavour::PM_FE_I2); + m_options=new ipc::ScanOptions; + scn.setName("TCP"); // send data over the network rather than to file + // Override l1a latency + int latency = config.Get("Latency", -1); + if(latency==-1){ + throw eudaq::Exception("Latency is not defined."); + } + scn.setLVL1Latency(latency); + m_conseq = config.Get("ConseqTriggers", -1); + if(m_conseq==(unsigned)-1){ + throw eudaq::Exception("Number of consecutive triggers is not defined."); + } + scn.setConsecutiveLvl1TrigA(0,m_conseq); + int trgdelay = config.Get("Trgdelay", -1); + if(trgdelay==-1){ + throw eudaq::Exception("Trigger delay is not defined."); + } + scn.setStrobeLVL1Delay(trgdelay); + int deadtime = config.Get("Deadtime", 0); + scn.setDeadtime(deadtime); + int cyclic = config.Get("Cyclic_Period", 40000000); + scn.setEventInterval(cyclic); + scn.setTriggerMask(4); // eudet=4 + + scn.convertScanConfig(*m_options); + //m_controller->downloadScanConfig(*m_options); + // At the end, set the status that will be displayed in the Run Control. + SetStatus(eudaq::Status::LVL_OK, "Configured (" + config.Name() + ")"); + } catch (const std::exception & e) { + printf("Caught exception: %s\n", e.what()); + SetStatus(eudaq::Status::LVL_ERROR, "Configuration Error"); + } catch (...) { + printf("Unknown exception\n"); + SetStatus(eudaq::Status::LVL_ERROR, "Configuration Error"); + } +} + + // This gets called whenever a new run is started + // It receives the new run number as a parameter +void RceProducer::OnStartRun(unsigned param) { + m_run = param; + std::cout << "Start Run: " << m_run << std::endl; + char name[20]; + sprintf(name,"TCP_%d",m_run); + m_options->name=CORBA::string_dup(name); + + m_controller->downloadScanConfig(*m_options); + // It must send a BORE to the Data Collector + eudaq::RawDataEvent bore(eudaq::RawDataEvent::BORE(EVENT_TYPE, m_run)); + // You can set tags on the BORE that will be saved in the data file + // and can be used later to help decoding + bore.SetTag("PlaneMask", eudaq::to_string(m_PlaneMask)); + bore.SetTag("nFrames", eudaq::to_string(m_conseq)); + // Send the event to the Data Collector + SendEvent(bore); + // Enable writing events via tcp/ip + ProducerIF::setProducer(this); + //start run + omni_thread::create(startScan,(void*)m_controller); + //m_controller->startScan(); + + std::cout<<"Started scan"<<std::endl; + // At the end, set the status that will be displayed in the Run Control. + SetStatus(eudaq::Status::LVL_OK, "Running"); + } + + // This gets called whenever a run is stopped +void RceProducer::OnStopRun() { + std::cout << "Stopping Run" << std::endl; + + m_controller->stopWaitingForData(); + //wait for late events to trickle in + sleep(1); + //wait for scan to be complete + bool idle=false; + for(int i=0;i<50;i++){ + if(m_controller->getScanStatus()==0){ + std::cout<<"called getstatus"<<std::endl; + idle=true; + break; + } + usleep(100000); + } + if(idle==false)std::cout<<"Scan did not go into idle state"<<std::endl; + //disable sending events via TCP/IP + ProducerIF::setProducer(0); + // Send an EORE after all the real events have been sent + // You can also set tags on it (as with the BORE) if necessary + unsigned evnum=m_controller->getNEventsProcessed(); + SendEvent(eudaq::RawDataEvent::EORE(EVENT_TYPE, m_run, evnum)); + SetStatus(eudaq::Status::LVL_OK, "Stopped"); + } + + // This gets called when the Run Control is terminating, + // we should also exit. +void RceProducer::OnTerminate() { + std::cout << "Terminating..." << std::endl; + } + diff --git a/rce/rcecalib/server/RceProducer.hh b/rce/rcecalib/server/RceProducer.hh new file mode 100644 index 00000000..69ad544e --- /dev/null +++ b/rce/rcecalib/server/RceProducer.hh @@ -0,0 +1,29 @@ +#ifndef RCEPRODUCER_HH +#define RCEPRODUCER_HH + +#include "eudaq/Producer.hh" + +#include "rcecalib/server/IPCController.hh" + +class RceProducer : public eudaq::Producer { +public: + RceProducer(const std::string & name, const std::string & runcontrol, IPCPartition& p) + : eudaq::Producer(name, runcontrol), m_run(0), m_PlaneMask(0), m_conseq(1), m_controller(new IPCController(p)), + m_options(0){std::cout<<"Rce producer constructor "<< m_options<<std::endl;} + virtual ~RceProducer(){ + delete m_controller; + } + virtual void OnConfigure(const eudaq::Configuration & config) ; + virtual void OnStartRun(unsigned param) ; + virtual void OnStopRun() ; + virtual void OnTerminate() ; + +private: + unsigned m_run; + unsigned m_PlaneMask; + unsigned m_conseq; + IPCController* m_controller; + ipc::ScanOptions* m_options; +}; + +#endif diff --git a/rce/rcecalib/server/ScanGui.cc b/rce/rcecalib/server/ScanGui.cc new file mode 100644 index 00000000..44ba489c --- /dev/null +++ b/rce/rcecalib/server/ScanGui.cc @@ -0,0 +1,276 @@ +#include "rcecalib/server/ScanGui.hh" +#include "rcecalib/server/PixScan.hh" +#include "ScanOptions.hh" +#include <iostream> +using namespace RCE; + +ScanGui::ScanGui(const char* name, const TGWindow *p, UInt_t w, UInt_t h, UInt_t options): + TGVerticalFrame(p,w,h,options), m_scan(0), m_scanopt(0), m_scn(0), + m_thresholdTargetC(-1), m_targetChargeC(-1), m_targetValueC(-1){ + + m_name=new TGLabel(this,name); + AddFrame(m_name,new TGLayoutHints(kLHintsCenterX|kLHintsTop, 2, 2, 10, 0)); + FontStruct_t labelfont; + labelfont = gClient->GetFontByName("-adobe-helvetica-medium-r-*-*-18-*-*-*-*-*-iso8859-1"); + m_name->SetTextFont(labelfont); + + TGLabel *cfg=new TGLabel(this,"Scan Type:"); + AddFrame(cfg,new TGLayoutHints(kLHintsCenterX|kLHintsTop, 2, 2, 10, 0)); + + m_scan=new TGComboBox(this,100); + AddFrame(m_scan,new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX ,2,2,5,0)); + if(!m_initialized)initScanTypes(); + m_scan->Resize(150,20); + //m_scan->Connect("Selected(Int_t)", "ScanGui", this, "selected(Int_t)"); + + m_typestring=""; + //Injection + TGHorizontalFrame *conf0 = new TGHorizontalFrame(this, 2,2 ); + AddFrame(conf0,new TGLayoutHints(kLHintsExpandX )); + TGLabel *masklabel=new TGLabel(conf0,"Injection:"); + FontStruct_t maskfont= gClient->GetFontByName("-adobe-helvetica-bold-r-*-*-12-*-*-*-*-*-iso8859-1"); + masklabel->SetTextFont(maskfont); + conf0->AddFrame(masklabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + m_dig=new TGLabel(conf0,""); + conf0->AddFrame(m_dig,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + masklabel=new TGLabel(conf0,"Repetitions:"); + conf0->AddFrame(masklabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 10, 2, 2, 0)); + m_rep=new TGLabel(conf0,""); + conf0->AddFrame(m_rep,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + + // mask + TGHorizontalFrame *conf1 = new TGHorizontalFrame(this, 2,2 ); + AddFrame(conf1,new TGLayoutHints(kLHintsExpandX )); + masklabel=new TGLabel(conf1,"Mask:"); + masklabel->SetTextFont(maskfont); + conf1->AddFrame(masklabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + m_maskmode=new TGLabel(conf1,""); + conf1->AddFrame(m_maskmode,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + TGLabel *mslabel=new TGLabel(conf1,"Number of Steps:"); + conf1->AddFrame(mslabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 10, 2, 2, 0)); + m_maskstages=new TGLabel(conf1,""); + conf1->AddFrame(m_maskstages,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + //Loops + TGHorizontalFrame *loopframe[3]; + char loopstr[128]; + for(int i=0;i<3;i++){ + loopframe[i] = new TGHorizontalFrame(this, 2,2 ); + AddFrame(loopframe[i],new TGLayoutHints(kLHintsExpandX )); + sprintf(loopstr, "Loop %d:",i); + m_active[i]=new TGCheckButton(loopframe[i],loopstr); + m_active[i]->SetFont(maskfont); + m_active[i]->SetOn(0); + m_active[i]->Connect("Toggled(Bool_t)", "ScanGui", this, "dummyAct(Bool_t)"); + loopframe[i]->AddFrame(m_active[i],new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + m_par[i]=new TGLabel(loopframe[i],""); + loopframe[i]->AddFrame(m_par[i],new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + TGLabel *looplabel=new TGLabel(loopframe[i],"N:"); + loopframe[i]->AddFrame(looplabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 10, 2, 2, 0)); + m_steps[i]=new TGLabel(loopframe[i],""); + loopframe[i]->AddFrame(m_steps[i],new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + looplabel=new TGLabel(loopframe[i],"Lo:"); + loopframe[i]->AddFrame(looplabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 10, 2, 2, 0)); + m_low[i]=new TGLabel(loopframe[i],""); + loopframe[i]->AddFrame(m_low[i],new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + looplabel=new TGLabel(loopframe[i],"Hi:"); + loopframe[i]->AddFrame(looplabel,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 10, 2, 2, 0)); + m_high[i]=new TGLabel(loopframe[i],""); + loopframe[i]->AddFrame(m_high[i],new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 2, 0)); + m_rce[i]=new TGCheckButton(loopframe[i],"RCE"); + m_rce[i]->SetOn(false); + m_rceb[i]=false; + loopframe[i]->AddFrame(m_rce[i],new TGLayoutHints(kLHintsRight|kLHintsCenterY, 10, 2, 2, 0)); + m_rce[i]->Connect("Toggled(Bool_t)", "ScanGui", this, "dummy(Bool_t)"); + } + TGHorizontalFrame *conf2 = new TGHorizontalFrame(this, 2,2 ); + AddFrame(conf2,new TGLayoutHints(kLHintsExpandX )); + TGLabel *linklabeltune=new TGLabel(conf2,"Tuning Parameters:"); + linklabeltune->SetTextFont(maskfont); + conf2->AddFrame(linklabeltune,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 0, 0)); + TGLabel *linklabel2=new TGLabel(conf2,"Target threshold:"); + conf2->AddFrame(linklabel2,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 0, 0)); + m_thresholdTarget=new TGNumberEntry(conf2, 0, 5, -1, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMinMax, 0, 20000); + conf2->AddFrame(m_thresholdTarget,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 0, 2, 0, 5)); + TGLabel *linklabel3=new TGLabel(conf2," Target charge:"); + conf2->AddFrame(linklabel3,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 0, 0)); + m_targetCharge=new TGNumberEntry(conf2, 0, 5, -1, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMinMax, 0, 50000); + conf2->AddFrame(m_targetCharge,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 0, 2, 0, 5)); + TGLabel *linklabel4=new TGLabel(conf2," ToT target value:"); + conf2->AddFrame(linklabel4,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 2, 2, 0, 0)); + m_targetValue=new TGNumberEntry(conf2, 0, 3, -1, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMinMax, 0, 127); + conf2->AddFrame(m_targetValue,new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 0, 2, 0, 5)); + +} + +void ScanGui::dummy(bool on){ + // disable clicking + for(int i=0;i<3;i++)m_rce[i]->SetOn(m_rceb[i]); +} + +void ScanGui::dummyAct(bool on){ + // disable clicking + if(m_scn) + for(int i=0;i<3;i++)m_active[i]->SetOn(m_scn->getLoopActive(i)); + else + for(int i=0;i<3;i++)m_active[i]->SetOn(false); +} + +ScanGui::~ScanGui(){ + Cleanup(); +} + +void ScanGui::updateText(TGLabel* label, const char* newtext){ + //unsigned len=strlen(label->GetText()->GetString()); + label->SetText(newtext); + //if (strlen(newtext)>len)Layout(); + Layout(); +} + +void ScanGui::enableControls(bool on){ + m_scan->SetEnabled(on); + m_targetCharge->SetState(on); + m_targetValue->SetState(on); + m_thresholdTarget->SetState(on); +} + + +void ScanGui::print(std::ostream &os){ + getScanConfig(); + if(m_scanopt!=0){ + m_scn->dump(os, *m_scanopt); + } +} + +RCE::PixScan* ScanGui::getPixScan(){ + return m_scn; +} + + +ipc::ScanOptions *ScanGui::getScanConfig(){ + return m_scanopt; +} + +void ScanGui::initScanTypes(){ + PixLib::EnumScanType scantypes; + m_scantypes[PixScan::DIGITAL_TEST]=scantypes.lookup(PixScan::DIGITAL_TEST); + m_scantypes[PixScan::ANALOG_TEST]=scantypes.lookup(PixScan::ANALOG_TEST); + m_scantypes[PixScan::THRESHOLD_SCAN]=scantypes.lookup(PixScan::THRESHOLD_SCAN); + m_scantypes[PixScan::CROSSTALK_SCAN]=scantypes.lookup(PixScan::CROSSTALK_SCAN); + m_scantypes[PixScan::T0_SCAN]=scantypes.lookup(PixScan::T0_SCAN); + m_scantypes[PixScan::TIMEWALK_MEASURE]=scantypes.lookup(PixScan::TIMEWALK_MEASURE); + m_scantypes[PixScan::INTIME_THRESH_SCAN]=scantypes.lookup(PixScan::INTIME_THRESH_SCAN); + m_scantypes[PixScan::DELAY_SCAN]=scantypes.lookup(PixScan::DELAY_SCAN); + m_scantypes[PixScan::MEASUREMENT_SCAN]=scantypes.lookup(PixScan::MEASUREMENT_SCAN); + m_scantypes[PixScan::VTHIN_SCAN]=scantypes.lookup(PixScan::VTHIN_SCAN); + m_scantypes[PixScan::SELFTRIGGER]=scantypes.lookup(PixScan::SELFTRIGGER); + m_scantypes[PixScan::EXTTRIGGER]=scantypes.lookup(PixScan::EXTTRIGGER); + m_scantypes[PixScan::MULTISHOT]=scantypes.lookup(PixScan::MULTISHOT); + m_scantypes[PixScan::STUCKPIXELS]=scantypes.lookup(PixScan::STUCKPIXELS); + m_scantypes[PixScan::IF_TUNE]=scantypes.lookup(PixScan::IF_TUNE); + m_scantypes[PixScan::FDAC_TUNE]=scantypes.lookup(PixScan::FDAC_TUNE); + m_scantypes[PixScan::NOISESCAN]=scantypes.lookup(PixScan::NOISESCAN); + m_scantypes[PixScan::GDAC_TUNE]=scantypes.lookup(PixScan::GDAC_TUNE); + m_scantypes[PixScan::TDAC_TUNE]=scantypes.lookup(PixScan::TDAC_TUNE); + m_scantypes[PixScan::TOT_TEST]=scantypes.lookup(PixScan::TOT_TEST); + m_scantypes[PixScan::TOT_CALIB]=scantypes.lookup(PixScan::TOT_CALIB); + m_scantypes[PixScan::CROSSTALK_SCAN]=scantypes.lookup(PixScan::CROSSTALK_SCAN); + m_scantypes[PixScan::TWOTRIGGER_THRESHOLD]=scantypes.lookup(PixScan::TWOTRIGGER_THRESHOLD); + m_scantypes[PixScan::TWOTRIGGER_NOISE]=scantypes.lookup(PixScan::TWOTRIGGER_NOISE); + m_scantypes[PixScan::DIFFUSION]=scantypes.lookup(PixScan::DIFFUSION); + m_scantypes[PixScan::OFFSET_SCAN]=scantypes.lookup(PixScan::OFFSET_SCAN); + m_scantypes[PixScan::TDAC_TUNE_ITERATED]=scantypes.lookup(PixScan::TDAC_TUNE_ITERATED); + m_scantypes[PixScan::MODULE_CROSSTALK]=scantypes.lookup(PixScan::MODULE_CROSSTALK); + m_scantypes[PixScan::REGISTER_TEST]=scantypes.lookup(PixScan::REGISTER_TEST); + m_scantypes[PixScan::GDAC_SCAN]=scantypes.lookup(PixScan::GDAC_SCAN); + m_scantypes[PixScan::GDAC_RETUNE]=scantypes.lookup(PixScan::GDAC_RETUNE); + m_scantypes[PixScan::TEMPERATURE_SCAN]=scantypes.lookup(PixScan::TEMPERATURE_SCAN); + m_scantypes[PixScan::MONLEAK_SCAN]=scantypes.lookup(PixScan::MONLEAK_SCAN); + m_scantypes[PixScan::SERIAL_NUMBER_SCAN]=scantypes.lookup(PixScan::SERIAL_NUMBER_SCAN); + m_scantypes[PixScan::TDAC_FAST_TUNE]=scantypes.lookup(PixScan::TDAC_FAST_TUNE); + m_scantypes[PixScan::TDAC_FAST_RETUNE]=scantypes.lookup(PixScan::TDAC_FAST_RETUNE); + m_scantypes[PixScan::GDAC_FAST_TUNE]=scantypes.lookup(PixScan::GDAC_FAST_TUNE); + m_scantypes[PixScan::GDAC_FAST_RETUNE]=scantypes.lookup(PixScan::GDAC_FAST_RETUNE); + m_scantypes[PixScan::EXT_REGISTER_VERIFICATION]=scantypes.lookup(PixScan::EXT_REGISTER_VERIFICATION); + m_scantypes[PixScan::GDAC_COARSE_FAST_TUNE]=scantypes.lookup(PixScan::GDAC_COARSE_FAST_TUNE); + m_scantypes[PixScan::NOISESCAN_SELFTRIGGER]=scantypes.lookup(PixScan::NOISESCAN_SELFTRIGGER); + m_scantypes[PixScan::DIGITALTEST_SELFTRIGGER]=scantypes.lookup(PixScan::DIGITALTEST_SELFTRIGGER); + + for(std::map<int, std::string>::iterator it=m_scantypes.begin();it!=m_scantypes.end();it++){ + m_scan->AddEntry((*it).second.c_str(), (*it).first); + } + m_initialized=true; +} + + +void ScanGui::setupScan(std::string flavor, int runnum){ + PixLib::EnumFEflavour::FEflavour fl; + if(flavor=="FEI3")fl=PixLib::EnumFEflavour::PM_FE_I2; + else if (flavor=="FEI4A")fl=PixLib::EnumFEflavour::PM_FE_I4A; + else if (flavor=="FEI4B")fl=PixLib::EnumFEflavour::PM_FE_I4B; + else return; + + delete m_scn; + + m_scn=new PixScan((PixScan::ScanType)m_scan->GetSelected(), fl); + // Set targets from GUI unless they are 0 in the GUI + if(m_targetCharge->GetIntNumber()!=0) + m_scn->setTotTargetCharge(m_targetCharge->GetIntNumber()); + else + m_targetCharge->SetIntNumber(m_scn->getTotTargetCharge()); + + if(m_thresholdTarget->GetIntNumber()!=0) + m_scn->setThresholdTargetValue(m_thresholdTarget->GetIntNumber()); + else + m_thresholdTarget->SetIntNumber(m_scn->getThresholdTargetValue()); + + if(m_targetValue->GetIntNumber()!=0) + m_scn->setTotTargetValue(m_targetValue->GetIntNumber()); + else + m_targetValue->SetIntNumber(m_scn->getTotTargetValue()); + + m_typestring=m_scantypes[m_scan->GetSelected()]; + m_scn->setRunNumber(runnum); + delete m_scanopt; + m_scanopt=new ipc::ScanOptions; + m_scn->convertScanConfig(*m_scanopt); + + char nms[128]; + if(m_scn->getDigitalInjection())updateText(m_dig, "Digital"); + else updateText(m_dig, "Analog"); + sprintf(nms, "%d", m_scn->getRepetitions()); + updateText(m_rep, nms); + updateText(m_maskmode, m_scanopt->maskStages); + sprintf(nms,"%d",m_scanopt->nMaskStages); + updateText(m_maskstages, nms); + m_thresholdTargetC=m_scn->getThresholdTargetValue(); + m_thresholdTarget->SetIntNumber(m_thresholdTargetC); + m_targetChargeC=m_scn->getTotTargetCharge(); + m_targetCharge->SetIntNumber(m_targetChargeC); + m_targetValueC=m_scn->getTotTargetValue(); + m_targetValue->SetIntNumber(m_targetValueC); + PixLib::EnumScanParam paramTypes; + for (int j=0;j<3;j++){ + updateText(m_par[j], paramTypes.lookup(m_scn->getLoopParam(j)).c_str()); + std::vector<float> vals=m_scn->getLoopVarValues(j); + sprintf(nms,"%d", vals.size()); + updateText(m_steps[j], nms); + float low=0; + float high=0; + if(vals.size()>0){ + low=vals.front(); + high=vals.back(); + } + sprintf(nms,"%d", (int)low); + updateText(m_low[j], nms); + sprintf(nms,"%d", (int)high); + updateText(m_high[j], nms); + if(m_scn->getDspProcessing(j))m_rceb[j]=true; + else m_rceb[j]=false; + m_rce[j]->SetOn(m_rceb[j]); + m_active[j]->SetOn(m_scn->getLoopActive(j)); + } + +} + +bool ScanGui::m_initialized=false; +std::map<int, std::string> ScanGui::m_scantypes; diff --git a/rce/rcecalib/server/ScanGui.hh b/rce/rcecalib/server/ScanGui.hh new file mode 100644 index 00000000..9abef311 --- /dev/null +++ b/rce/rcecalib/server/ScanGui.hh @@ -0,0 +1,57 @@ +#ifndef SCANGUI_HH +#define SCANGUI_HH + +#include <TGButton.h> +#include <TGTextEntry.h> +#include <TGNumberEntry.h> +#include <TGLabel.h> +#include <TGComboBox.h> +#include <fstream> +#include <string> +#include <map> + + +namespace ipc{ + class ScanOptions; +} +namespace RCE { +class PixScan; +} + +class ScanGui: public TGVerticalFrame{ +public: + ScanGui(const char* name, const TGWindow *p, UInt_t w, UInt_t h, UInt_t options); + virtual ~ScanGui(); + void print(std::ostream &os); + void enableControls(bool on); + std::string getTypeString(){return m_typestring;} + ipc::ScanOptions* getScanConfig(); + RCE::PixScan* getPixScan(); + //void selected(int i); + void dummy(bool); + void dummyAct(bool); + void setupScan(std::string flavor, int runnum); + static std::map<int, std::string> getScanTypes() {return m_scantypes;} +private: + void initScanTypes(); + TGLabel *m_name; + TGLabel *m_maskmode, *m_maskstages; + TGLabel *m_dig, *m_rep; + TGComboBox *m_scan; + TGCheckButton *m_active[3]; + TGCheckButton *m_rce[3]; + TGLabel *m_par[3], *m_steps[3], *m_low[3], *m_high[3]; + TGNumberEntry *m_thresholdTarget, *m_targetCharge, *m_targetValue; + bool m_rceb[3]; + ipc::ScanOptions *m_scanopt; + RCE::PixScan *m_scn; + void updateText(TGLabel* label, const char* newtext); + static std::map<int, std::string> m_scantypes; + static bool m_initialized; + std::string m_typestring; + int m_thresholdTargetC, m_targetChargeC, m_targetValueC; + ClassDef(ScanGui,0); +}; + +#endif + diff --git a/rce/rcecalib/server/ScanLog.cc b/rce/rcecalib/server/ScanLog.cc new file mode 100644 index 00000000..9219b7a6 --- /dev/null +++ b/rce/rcecalib/server/ScanLog.cc @@ -0,0 +1,316 @@ +#include "rcecalib/server/ScanLog.hh" +#include <stdlib.h> +#include <sys/stat.h> +#include <iostream> +#include <fstream> +#include <sstream> +#include <boost/algorithm/string.hpp> +#include <ctime> +#include <TROOT.h> +#ifdef SQLDB +#include <mysql.h> +#warning Including SQL database interface +#else +#warning Not including SQL database interface +#endif +//#define SQLDEBUG 1 +namespace{ + const char* hostname="atlpix01.cern.ch"; + const int port=443; +} + +ScanLog::ScanLog(){ + const char *ou_name=getenv("OLDUSER"); + const char *u_name=getenv("USER"); + m_user="Unknown"; + if(ou_name!=NULL) m_user=ou_name; + else if(u_name!=NULL)m_user=u_name; +} + + +void ScanLog::logScan(LogData& logdata){ + std::string logdir=std::string(getenv("HOME"))+"/scanlog"; + struct stat stFileInfo; + int intStat; + intStat = stat(logdir.c_str(),&stFileInfo); + if(intStat != 0) { //File does not exist + std::cout<<"Creating directory for scan logs"<<std::endl; + mkdir(logdir.c_str(), 0777); + } + std::string runnrfilename=logdir+"/currentRunNumber.txt"; + ofstream runnrfile(runnrfilename.c_str()); + runnrfile<<m_runnumber<<std::endl; + runnrfile.close(); + m_infofilename=logdir+Form("/calibSetup_%06d.txt",m_runnumber); + char command[512]; + sprintf(command, "cd ~/daq; svn info | grep URL>%s;cd -", m_infofilename.c_str()); + system(command); + fstream infofile; + infofile.open(m_infofilename.c_str(),fstream::out | fstream::app); + infofile<<"Comment: "<<logdata.comment<<std::endl; + infofile<<"Run number: "<<m_runnumber<<std::endl; + infofile<<"User: "<<m_user<<std::endl; + infofile<<"Host: "; + const char *host_name=getenv("HOST"); + if(host_name!=0)infofile<<host_name<<std::endl; + else infofile<<"Unknown"<<std::endl; + infofile<<"Scan Type: "<<m_scanname<<std::endl; + infofile<<"Debugging Run: "<<m_debugging<<std::endl; + infofile<<"Data exported: "<<logdata.exported<<std::endl; + infofile<<"Data saved and analyzed: "<<logdata.saved<<std::endl; + infofile<<"Data Path: "; + if(logdata.saved==true)infofile<<logdata.datapath<<std::endl; + else infofile<<std::endl; + for (unsigned int i=0;i<logdata.configs.size();i++) + infofile<<logdata.configs[i]<<std::endl; + infofile<<"Started: " << formattedCurrentTime() << std::endl; + infofile.close(); + #ifdef SQLDB + startLogToDB(); + #endif + #ifdef ELOG + #warning ELOG included + if(m_debugging==false)writeToElog(); + #else + #warning ELOG not included + #endif +} +const char* ScanLog::formattedCurrentTime() +{ + time_t now = time(0); + tm *ltm = localtime(&now); + char formattedTime [128]; + sprintf(formattedTime, "%04d-%02d-%02d %02d:%02d:%02d", (1900+ltm->tm_year), (1+ltm->tm_mon), (ltm->tm_mday), (ltm->tm_hour), (ltm->tm_min), (ltm->tm_sec)); + std::string toReturn(formattedTime); + return toReturn.c_str(); +} +void ScanLog::finishLogFile(std::string runstatus, std::string lstatus){ + fstream infofile; + infofile.open(m_infofilename.c_str(),fstream::out | fstream::app); + infofile<<"Finished: " << formattedCurrentTime() << std::endl; + infofile<<"Status: "<<runstatus<<std::endl; + #ifdef ELOG + if(m_debugging==false)updateElog(lstatus); + #endif + #ifdef SQLDB + finishLogToDB(); + #endif +} + +void ScanLog::writeToElog(){ + char elogcmd[1024]; + char elogfile[512]; + sprintf(elogfile,"/tmp/elog_%d.txt", m_runnumber); + sprintf(elogcmd,"elog -h %s -s -x -p %d -d elog -l \"IBL Stave Test\" -u calibGUI rce -a Author=%s -a Title=\"Scan %d %s\" -a Category=\"Datataking\" -a \"Type of Entry\"=\"Scan Log\" -a Status=\"In progress\" -a \"People present\"=\"%s\" -a Automated=1 -m %s | tee %s &", + hostname, port, m_author.c_str(), m_runnumber, m_scanname.c_str(), + m_user, m_infofilename.c_str(), elogfile); + system(elogcmd); +} + +void ScanLog::updateElog(std::string lstatus){ + struct stat stFileInfo; + int intStat; + char elogfile[512]; + sprintf(elogfile,"/tmp/elog_%d.txt", m_runnumber); + intStat = stat(elogfile,&stFileInfo); + if(intStat!=0){ + std::cout<<"Logbook update failed"<<std::endl; + return; + } + int n=30; + ifstream reply(elogfile); + char rep[512]; + do{ + reply.getline(rep,512); + if(!reply.eof())break; + std::cout<<"Waiting for logbook"<<std::endl; + sleep(1); + reply.close(); + reply.open(elogfile); + }while(n-->0); + if(n==0){ + std::cout<<"ELOG entry failed"<<std::endl; + }else{ + int id; + int stat=sscanf (rep,"Message successfully transmitted, ID=%d",&id); + if(stat==EOF)std::cout<<"Bad logbook entry"<<std::endl; + else{ + char elogcmd[1024]; + sprintf(elogcmd,"elog -h %s -s -x -p %d -d elog -l \"IBL Stave Test\" -u calibGUI rce -a Author=%s -a Title=\"Scan %d %s\" -a Category=\"Datataking\" -a \"Type of Entry\"=\"Scan Log\" -a Status=\"%s\" -a \"People present\"=\"%s\" -a Automated=1 -m %s -e %d &", + hostname, port, m_author.c_str(), m_runnumber, m_scanname.c_str(), + lstatus.c_str(), m_user, m_infofilename.c_str(),id); + system(elogcmd); + remove(elogfile); + } + } +} +void ScanLog::startLogToDB() +{ + #ifdef SQLDB + ifstream log; + log.open(m_infofilename.c_str()); + std::string tmp, url, user, host, scanType, dataPath, startTime, endTime, comment, status; + int runNum; + bool debuggingRun, dataExported, dataSaved; + //std::vector <int> FEIds; + std::vector <std::string> modIds, cfgs, FEIds; + std::getline(log,tmp, ':'); + std::getline(log, url); + boost::algorithm::trim(url); + std::getline(log,tmp, ':'); + std::getline(log, comment); + boost::algorithm::trim(comment); + std::getline(log,tmp, ':'); + log >> runNum; + std::getline(log,tmp, ':'); + std::getline(log, user); + boost::algorithm::trim(user); + std::getline(log,tmp, ':'); + std::getline(log, host); + boost::algorithm::trim(host); + std::getline(log,tmp, ':'); + std::getline(log, scanType); + boost::algorithm::trim(scanType); + std::getline(log,tmp, ':'); + log >> debuggingRun; + std::getline(log,tmp, ':'); + log >> dataExported; + std::getline(log,tmp, ':'); + log >> dataSaved; + std::getline(log,tmp, ':'); + std::getline(log, dataPath); + boost::algorithm::trim(dataPath); + std::getline(log, tmp, ':'); + boost::algorithm::trim(tmp); + while (tmp.compare("Module") == 0) + { + std::string modId, cfgPath, FEId; + log >> modId; + boost::algorithm::trim(modId); + std::getline(log,tmp, ':'); + log >> FEId; + boost::algorithm::trim(FEId); + std::getline(log,tmp, ':'); + std::getline(log,cfgPath); + boost::algorithm::trim(cfgPath); + std::getline(log,tmp, ':'); + modIds.push_back(modId); + FEIds.push_back(FEId); + cfgs.push_back(cfgPath); + } + std::getline(log,startTime); + boost::algorithm::trim(startTime); + std::getline(log,tmp, ':');//times require special parsing bc whitespace + log.close(); + //Now insert into SQL DB + + MYSQL *conn; + conn = mysql_init(NULL); + char queryStr [1056]; + sprintf(queryStr, "UPDATE CalibRunLog SET URL='%s', User='%s', Host='%s', ScanType='%s', Debugging='%d', DataExported=%d, DataSaved=%d, DataPath='%s', StartTime='%s' WHERE RunNum=%d;", url.c_str(), user.c_str(), host.c_str(), scanType.c_str(), debuggingRun, dataExported, dataSaved, dataPath.c_str(), startTime.c_str(), runNum); + std::string dbName="RCECalibRuns"; + #ifdef SQLDEBUG + dbName="RCECalibRunsDev"; + #endif + if(mysql_real_connect(conn, "pixiblsr1daq1", "DBWriter", "W#1ter", dbName.c_str(), 0, NULL, 0)==NULL) + + { + std::cout << "SQL connection to " << dbName << " failed!! Nothing will be inserted!" <<std::endl; + return; + } + mysql_query(conn, queryStr); + //Now insert Module info + + for (unsigned int i=0; i < modIds.size(); i++) + { + sprintf(queryStr, "INSERT INTO ModuleLog (RunNum, ModuleId, FEId, CfgName) VALUES (%d, '%s', '%s', '%s');", runNum, modIds.at(i).c_str(), FEIds.at(i).c_str(), cfgs.at(i).c_str()); + mysql_query(conn, queryStr); + } + mysql_close(conn); +#endif +} +void ScanLog::finishLogToDB() +{ +#ifdef SQLDB + ifstream log; + log.open(m_infofilename.c_str()); + std::string tmp, url, user, host, scanType, dataPath, startTime, endTime, comment, status; + int runNum; + bool debuggingRun, dataExported, dataSaved; + //std::vector <int> FEIds;//Read in everything even though it's junk + std::vector <std::string> modIds, cfgs, FEIds; + std::getline(log,tmp, ':'); + std::getline(log, url); + boost::algorithm::trim(url); + std::getline(log,tmp, ':'); + std::getline(log, comment); + boost::algorithm::trim(comment); + std::getline(log,tmp, ':'); + log >> runNum; + std::getline(log,tmp, ':'); + std::getline(log, user); + boost::algorithm::trim(user); + std::getline(log,tmp, ':'); + std::getline(log, host); + boost::algorithm::trim(host); + std::getline(log,tmp, ':'); + std::getline(log, scanType); + boost::algorithm::trim(scanType); + std::getline(log,tmp, ':'); + log >> debuggingRun; + std::getline(log,tmp, ':'); + log >> dataExported; + std::getline(log,tmp, ':'); + log >> dataSaved; + std::getline(log,tmp, ':'); + std::getline(log, dataPath); + boost::algorithm::trim(dataPath); + std::getline(log, tmp, ':'); + boost::algorithm::trim(tmp); + while (tmp.compare("Module") == 0) + { + std::string modId, cfgPath, FEId; + log >> modId; + boost::algorithm::trim(modId); + std::getline(log,tmp, ':'); + log >> FEId; + boost::algorithm::trim(FEId); + std::getline(log,tmp, ':'); + std::getline(log,cfgPath); + boost::algorithm::trim(cfgPath); + std::getline(log,tmp, ':'); + modIds.push_back(modId); + FEIds.push_back(FEId); + cfgs.push_back(cfgPath); + } + std::getline(log,startTime); + boost::algorithm::trim(startTime); + std::getline(log,tmp, ':');//times require special parsing bc whitespace + std::getline(log,endTime); + boost::algorithm::trim(endTime); + std::getline(log,tmp, ':'); + std::getline(log, status); + boost::algorithm::trim(status); + + //Now insert into SQL DB + + MYSQL *conn; + conn = mysql_init(NULL); + char queryStr [1056]; + sprintf(queryStr, "UPDATE CalibRunLog SET EndTime='%s', Comment='%s', Status='%s' WHERE RunNum=%d", endTime.c_str(), comment.c_str(), status.c_str(), runNum); + std::string dbName="RCECalibRuns"; + #ifdef SQLDEBUG + dbName="RCECalibRunsDev"; + #endif + if(mysql_real_connect(conn, "pixiblsr1daq1", "DBWriter", "W#1ter", dbName.c_str(), 0, NULL, 0)==NULL) + + { + std::cout << "SQL connection to " << dbName << " failed!! Nothing will be inserted!" <<std::endl; + return; + } + mysql_query(conn, queryStr); + mysql_close(conn); +#endif + } + + diff --git a/rce/rcecalib/server/ScanLog.hh b/rce/rcecalib/server/ScanLog.hh new file mode 100644 index 00000000..7f45871e --- /dev/null +++ b/rce/rcecalib/server/ScanLog.hh @@ -0,0 +1,51 @@ +#ifndef SCANLOG_HH +#define SCANLOG_HH + +#include <string> +#include <vector> + + +class LogData{ +public: + std::string comment; + bool exported; + bool saved; + std::string datapath; + std::vector<std::string> configs; +}; + +class ScanLog{ +public: + ScanLog(); + ~ScanLog(){} + void logScan(LogData&); + void finishLogFile(std::string runstatus, std::string lstatus); + void writeToElog(); + void updateElog(std::string lstatus); + void finishLogToDB(); + void startLogToDB(); + void setFile(std::string f){m_infofilename=f;} + void logOldFile(); + void setAuthor(const char* name){ + m_author=name; + } + void setScanName(const char* name){ + m_scanname=name; + } + void setRunNumber(int runnumber){ + m_runnumber=runnumber; + } + void setDebugging(bool db){ + m_debugging=db; + } +private: + std::string m_infofilename; + const char* m_user; + std::string m_author; + std::string m_scanname; + int m_runnumber; + bool m_debugging; + const char* formattedCurrentTime(); +}; + +#endif diff --git a/rce/rcecalib/server/StandardStream.o b/rce/rcecalib/server/StandardStream.o new file mode 100644 index 0000000000000000000000000000000000000000..d91a7f65ea6eb27d9c739428f9b331b36f0ab949 GIT binary patch literal 1165544 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%0AA1W)`oh$nH<Zusp(u<WW6<`ls= zp(*h)CZ}Cg{YjkICg_LKmP)+xOqhd^c8Ir@*Y-7DetuWR@_0T>T!X|BmU^L%j|KMS z@a0RG8{~>#lCM={@bRT>BrYd0&Zj|I2R0ky-!pFEmA$e#&qey8Igz^e6^jk*{YhL_ z=<avuNwW>_OgvP!q2M0>K-pH^@t1uw&IVZg+hgc9O_DD8B$JQ0>3K3LKQApo?(Bu+ z-d4YB=k~2T?r*5)*i8Y)Wda59H=u)MNmh1C<DQy5+b^Sh3FU~%@9FHF_O#xHckOA| zx^36qot&CbDYrHt=hpe9@Je!9Vo8#f#pm&k0FPHziugj!mPyVAz3c8>AFZk1dl@>4 z&tE7<*A}JV_<S2~dr!^I#t$}Z-??Z4UNI8ryi?E4?b^QQ?p=-VZQ8M?aZ$oRE0Ipc z_TBgI*t3U&nx)%!?$};?g>>G2*Urz@)bFUZ$7&W!WR5(yZ{D+K`))Zlx>yqN<+<&) zyY}qayZt>ijoa$B@7`R`xx?CrKD>R=+DX*UyFRde&z_q57H4X;RJ=SJ-f<VTW%tgS z`XC|2v1eBb;*THM(}#Z9EuPoT-L`Yr&TYFI9+DH79G(pP^3gp{d1XO@{I_xLt)~7x zyC_9dOpCMfzbhf-mGQn*?pfJ9ofOn_DsSs{IXdYpVGhna8|%aiwl1RGkL5*>gmydU za@y_NRidpscHX;-KXNp7*KTbogYwGBIj_JA@Qp0Mcad!7(JKAd`FWC(MknI)dnzg7 z{E@M8di~068$8?W-o9to-rd`_2TU2mh1_dli}`r_W?6v$mDpr{cJrw#QQ!07`SFSP z^V=uf?48k{tvwL&;*wfKc+hKZ+~{?ivER}Q`DwwP&5uj$rTqBBUdNA*>qR`Cu`a>; zoxFv&@_DT+<m~T+)>q;gRP5Nc)t;i?xN+-;8PRaIe)ryOjnTV5QeGb2xvMd%T^YFR zYik}@zo&lNJJ#=caDDx@`_|J4YHPm!KgdTL>o=?`EL>Nxwc(-0x?MYOTldcO4Gr6F z-QBqT{yn$i&4mT;xOG=U<N6&tx7F{h-M(HmeCvj-g@qPeZ*{%C!3*^hk9Bno4Q8zu zwN<0Gdf$Y+`F^GeiD|Xl5q{T0d7AiHZE7gh2WWSsBi&lFx9PPnN33aGZwHE~De&=! zmWZ!%wtsf}?j4N}A&zO>alg2YY1p-AhjjJ=V+QGCOv8>^(re9L<k$EIYt6lTcW(3X z>UZqayowCMp2nJO9BVV%YREy@P_vuQDKOI>zWCY8nB?9a3P(x%1h0Icusn?~nqqiS znYx%;c<+#qA0LY4vuSl0TOg51!f2i`VvB~|yS6bvi1HPW(y)e%{fwnQ=%wFGo(F68 zL{(P4{CQ|2%y{B`a?jp-u&Kmr=Nr}DggiQ?iPn+-p6%OrMr-WoCc0<4oKG}p_a0HF zDELjad@V)Q+$vv|@SCcse!Yu<XY?jxZi-5())BLA-TFPdx2=aG-)QVvA3q*hx2;M1 z$6|}FYj^F18zDmRRgsra?<Ghm3HN&O_j>UXN_@SSQ12%|TVbWf4?fbN-MZ*-b;jm& zIbLbf<&XDd69#_^ywGpXh{mPM?<`*bDJ;*3lwP&DMSchAxcnAg{xevXky-Y*<6*|* zCgTyLl_;b1E5Y={->)_PrT8WCPyGE#^C!}i-$9#{m1RWAlh`C#K8f?6#iZx>$b@y+ zwDfT&jguAg+BGOw5ppH-712k~SNh5_vMYLAXqFw9bJ~eCDm`wmcf2oqKnG5Kc}8}* z`gO&L(D87O_<bPV3{jTK$DQNhfR=*k-IqvT%D<$)%k`gNU8=&rwj2+~>gRlQW+_j6 z8}$D-y*1(oRnk6rp5WWNk@jl7wCM%XNHV`}Itu!Bb)XOQ;+-wFJW2aT>4W@sS>Oru zRpGVU$@<bn{4?~0;GYQ5&inYDjve{lWQcUzPw;~$*zYFNnl4pZfgWR4Hpx4ZBz+-z zmy3VO$~rIq=_Kh3@xNUBUj=`^K41$cN9u~$-m5E#Weeh_i=QYaquV5Q4dT8Mx=}H_ z_n^-_<dgA6oQ<MB0^xi(o{#JI`L);)spDvPbw$46H)Vl3<mJ=v_7}(}-}WcXH%a^g z`Q)4bWcl1fm&kW6c|N(%!Suw+S9v1j+0rYA-1%UdW9hTwS1(=edsryH+zGKzez^}~ zq5N`Z#6tNatqbQ*6FHN~pH960NW0?y7Fb@dd`9M6GqHBWZ?R_aNml%Y@}GKz`DtUN zO^owDpWkBm&%DC?uLb{H5!^mbV|hljw8xe5od{9UXeS;^@%%8)$D+NNq&}B-N7P5l zA6d3Vnw}o_v6M$sEm8nC94X5vsOXM7nhG6ot8FtN*vD9qF(!Z;$}P(%D?gT|vlHl7 zJevB*GHQY)9*^q`mS^OZKAI}B_P9*Dw0(Ij<&kBtpS;c}dMMR4O?y%}S6VeZvP>1> z`L28m>x|LvZc&ZZKJHZNG|~6%71gBI#nLHBd0e{Ox8krKF(-e4a?wBG(b9~DieqW$ z0}riIb=QkJx+B$JU*6;DWKS>y`VKdhWmJ?~dn3D8{CN08Xx5HVC9U_WI9p1wxt6u+ zM99u{wg2#N<bD=s3K?ztOi5$CQLGMMH4F|u?3H6qIpq$QP#)>k*0a>8B7(<5?tyVm zFU&*kf(d2KPviPt(o17BC=n$`Il{*0BlpFG3g*G_^e1<{q_mc1)RjM$g3i^gRV&P0 z#BIAH(DQI_rd)1+X-1XRU-^kp{o{`BDBTh3upVw+F}Qt#t0S|<*{UTpEvm^^Y4tvt zln#+W?Sdq@A1FA$iBM%s3S$Cw++d>uMG(Xu7f+nEH@y8PTvD1*U3Mfx>er*GAy!TN zdMI)nOZ)orudV1xKf3bps?N->UggP!PGV0<pf8Tv*xPE+nOm08pv4#dCqmW2Uy?nX zchy}Qr?~#oIGY<Tjq^K=3*eN9P@Gz7V&!<WETh#aRb|jTAvi6Q)Rv%1;uZ3ht0i-` z{PFHBk~xcABf?rlmPiU|Cto>zy$5O@`Zd$9oW9;8H4pv!qpyHIdF7FNndWU@N)*LB zM0mw^@amS_cXi1+>+yTI;}!7p>ZjbFwW#{()w@Sd@!dadS6$U3%hb(+KK5v8cf|Lx zBN?{ZSuf){DXXL2$t%nswfXfg{Yai|d+Y$ftJ*$~XJ+6LwK8gZ6ffg!!!VDG-=&SX zqB7>p%ILs9&tDtRo|m-W^mMPS&{Fo7Wke~LuX;Tu>=i$ys4Sy5L?_eZij&YhSAh1o zQ*Zn2cps5G9^L;$9dOE_OV1pm?4^B=c5uG5p^^F1{y05Jn&<m+FI=dwG^2#RMua?; z*66pEwqx=O=i$q}YnOxnr^t0V_;N4Y<>1RbZkK~E_qr_#zXY3jPbz(Ef2iW<N>R{} z3^YRT^0gIZjC`eUY48Wtk1YH8@~-qimG|nqkV!dLia(G~I%*xXSIfu(T21~yB)-*< zOrFliI+6K8X~t=naf4D|+^ChBs;?tB89;*X)vX_4BS+Q`bgT^vyW0_Ke@=B%w}-Ew zZSdq7ujG!EZu;63I?C<{C92Y9@I**w7&1<=18Yy7AD>-Vo}Zk*LV0pUNyfZ1$md!8 z<r&jXVAdis_`aKE@#KuFp<YH3_IdQ&YcO8xoAbGfa@p$i=1O+Q)7I0drDqE1sMrXO zZ9YkPi@mf#O|uIDz8peVWRR!KOZOKIqr^2y0#BWvH(?VjN?MN~@bq~&aT{91=kkv5 z@;Ld5lVl@_#3=7HuRKFOt%MDMsMt+0_;gut*5Fi0aQyj=(vbmq5*&O+AEoob<T!r$ zl}>eX9KZZZrzJVgh{sFmbSB4{@^F;Sca!3TB0)MM$#J|oVfFLV<Tw>UI_Hw(GzR2x zRwc*j4$zU#HHn@>!$CTCCdZi!(y2&_6IPc1PxRyLN{&O@tB>f}X-$q(?%^n%$CKkU z1nHbij?)#S^MB06$>Hj)ArGffg$KtUd=M|`6NIAY`O?pmCUqiNdN%VtUVW-P`hMM& zv_e#{#mg%TFMe7UX}<k+an7R=CB6<=d~8DWcNTf+PwW)YwiuH4kcXd`x6jLahP)v| zJEMIOZLzoHMtR*a$espI>_dwaw^1OprL6KK(AIgL$Tcmrvtx^KvBk_N{aLPL<QWm1 zg1I=*Pbsq~bLdwSFZ4BUS@OIc^W^RE@}3gD)pHl>qVOH@@~Zqzb8$qrDGw*H>=%fS zm7TUDaUqessnO(lQ;WR3DjS2t#JuE76(5mDWgD4`BlKGpV~$-?yNQp<HjzB<aFV<^ z&>XjUogC4dv_T9G{G}h^Ig=z`lzv&-e|S3S<O`>Wj|Mg+NF(pEf+Tt2xvb2~D?G#5 zb9m}nwq#AP!Ln8_pYptQF3((O_en+`(PNl)F4@L~;GME)7Vo3U@uJ{Se!F)8J*_Kt zfh^|p)bR+f-M{c~{5nqlNFieIn%V{OSAiooEK8EVk+jK6<R`D)&q$Jg&}%Ce;y(e- zxq0}{P$!B=>xq{?w!snQF6nG=#=&Wh$BF4kaEkFIY3~-IQw`49OVH`SCUuvf)9<;? zLh@k$Nb4o&pcA|AF;BU&SYzPTC+MpZpHD3HBhiPKmlBuBI|I#dL#&O9ZHP!-DW5!v zG+QMuAwCK|_E(zHzJw1Zr<tt&3$O8cXo?*~PU(Zfy-C}Y6_PGbf}AVzBrYL7%3a$f z#Kp=!l$>TQIPxUYY?io$_$V~Hh>OX2IyucDaO6p(d0OHU;-k=<CN3uD^jw;GY+I#+ z!{f-9z-6pI-^L4mAlF1F?j*R<hAg!CBKUQRZo*dHg*RXdz!&@TgmOg|7T_1$gaJ`_ zoYE}pOGuv5g*Rga|AL3V$TF-Xk35Si1Gp=<SbS&H*U<tSGg0sl**ol=F_FK4z93<9 zMsQAI%W7;?Cpce;;lwsB1PA}O`!j;`ObjQs$x{f<d81EQWOK(Bw^2ixGO&$2;U@B> zF!5e!vj(5asJ3_DJ6i<*z4L6?Krk0P%5V2<1ovL#w*6Av#!VEwL1XN`jo^JDR=%JP zGA8W(`=LC+c@~_64IJTz{q6pZ;QaNx{8oW$_izO7Uy{;VRc7z=50!$GniHcHx0wT- zRSov;|4@P8{m0~Z=y(<WZ})QqukjL_I_OXGoHEAl>qwq6m)P7P5BAI?u=_jYS(dx- zCJ#I^dF6iwq;v>={iQd0O2|_S6P|F1<oT=1-^9s=M!%(Dghqrpqdy+WC2iCgyN@Gj zHzeQ85xld;*u5O^(l*SCcU2Zk8}*dY1#dYvO13!!y{n43-K)XFTk*;H@oJ5+`#R7| z-;*4#6ncmJy&dpYK73^xJW=RS|MmY;#O8LvO&;_pyr}<npGSE8mn-IVb&2;sKNjG1 zbuBp4s8ZUR493-0vT;SZt{&i&KJV<Db#A$?K5fkX;96eqxiVg~Ti4)ob`MBoZkxZ| zDg~F<?ga_%lUK%*dUXx<mui*LDs(0<UFYF@&4@8}Ux+-b-h0Kovm!?Sw~E&5Rg2ib zEnzx@|J(f`;r+AA-y{+mt;X0rB4}jZb@?=Mp)qRgBmR~7Z1T+_;dRy+yH_N5-@E)p zVQ5^7o$P)QG_JbpisZev(TeLtg~kI(HjYTog;!4yuYG>J(IDQ}=EtM_@>sr%3+8NC zkqF;6(EiC|@&5Dtc-UVai}$1X@oE*#!~2Kic+h$S{x45Tk&9mb-^<%n$|3(LW9*(1 z`LAaF8{Alubjok{l_Z^ZI3fMIbe4}sC{MYhvmTO|o^OoZUy}51$EV{L*OeP%_n0J| zgI$-}Xp%gw_W%2Y3MJ3f;_?jI|M_F{uvxMgKD57fzX?9qWGyOBHafF=PLd~oad|52 z{}WQ#t|`5Ao-(!>I>hP>S)^~j=3`g50R@2)Xq^^H_|Q3_^>>%Q5mm@I4*$3NP|(O? z%zDYqC>Tb`hyCq-l;qpT*e+pHssx+{W9*)k;5>5qZ4f?lJ@&WzQbOYbZT=-Tr$jdF zZ}+Cib1iL764~B}|J(g3!TIv#%a&)%8?nFLqY@hbJpV=&{p%Z>Su)sy?xeoU9Ma#c zlC*Bpx{{;`W|nb2EMeer7ZsImoDY$Sa+*RDdLR-YAfQJV^Rq?md`tsr5tUmmKMQRv zQ0$3Vl0s?_l9{mt3v7v(tBBY-<H+}){!;=_X`?y-d*f3D3l>*a+}A&25;G(bVsTMP zXuZZ!$R+L}wk%8H9{JV|V#Bg4HOUp1ARt>^5<kOV#Yd<)w1Unq0vaPWU=;+4JpnpJ zNy?bHsDcHE^g%?p2A@1jgyz5;GERLk2{@2BnFL<uV5Z-a97%LP+h95QNfhmQWIoEG zX%ed!@|Iflmjd?N*pq-$7CZ}h!6IB>r~?DC5f~?`u>=NQbNq&=N~22#{0~ltR^ANr zj#zL6@T^6Ez7Pe$Cn~tXhwLBWH`xUd&_|S5|0xFOw!S064=d=<GK*~WJ{DmWZ?$pm z*T9$tTeJp#_S#r4JGH~13771G8+-!pHIzijo<oW^4=tFvd*RHUlp=iNf^?RI@LS;} zO)P0bYwA)J^&6~TH%(L}Y4i$gBV2&Y<qNiSMP!!IR`Btf+hA0n%uDQoig|^DsU>AD zDKn;lU#oi8xNxgdKett3{43*A8UNPCj}RM)YPK`GX29tL(vsX~8>~LS$#~L|+HXns z15U(~o+j#?C4G*u<(34}Bs+FuMj%AuhMtm|qofH~bc`nr<={+dsj7-XW}iTpaQU4` zb&_reO9U2K<anclA2IwQkduXR9hD|G#pTddgG}oSnaDYr;0qDr0{tRBCDV{WUgkEz z8HpeU=uAOJ==o0q9cFcUYne@!6Oax*Dq>G?c;aAu<`C1oP;uM>Qz(llsy-`HA*NCx zW+uVKDdCoG3q@XheXcN6JW*UB?;$&F>;|MzG94Y`rGf|;d|XS?C2k~vq@d+nlKFrQ zHnUXR0QHf0k_l3dC6JWlfRxxx<muq;vS2UZ*j$nUD~vBpGC*fMo(`0Q)mR#zpfx2q zP}+cKgO<(+2-EQ-r8oi6E@6{aoB0r#=C?@#$=|BdvMLb2f+fl*upU?dNOcOjZ@j9U ztc5dsb$bjtrx&W`zak+JE73diBrfm-ytC7mpqEsy`I-cz1qwD_#JtKRX~j$k-ZW|i zaw;{h4r%g$+AB0b@?@O7<P2+Q#%7-32udND#f07?$>D6x9M09`U@sttT*I`Na3+xR ztZ|$*xyojy?F@Sjlt)@lzlM8l=3c<bc+Q$UYBSSnlN`r+k|^rEaGo}D5;mSQ$u5m3 z4KIOli{i>G=Vsk<%}ik2L-Cw7xxr?pT_rilnV-g`J%clWaTA&sO+INepClRU2Wkh{ z#yxK{pO=l?1kNO<<Y?v;{EXxvXE~CaQlgm&OiDs4q{-Dbb2Z5$$~k3BF@r*o(WIQQ zbk4A=SP`!~O-4p^mx7F`rEw*Y^Sr55nwh|)CODfWH)-b7CXy#Kb1LQlGbjW<O{(=f z0y*9rXFy3_mZ@|I%(5+UnZY*8un;yNkRzUPnKil7X6^*#oMv7|VZaOu!A}!OS2_eH z(i%@klk=2L1am|h<1@Dsb<k!$sE3B*gn*cd&<vnP0+SZe%xM&c<HbQC<g{^GuF@ee zTs#p+N0YHSbka(A@y38d(b4I)9GYNv&NvC0(Bv}B%$AHU`AX&i-qV&24nU>_NSZV8 z@+6Y<<mrYar4{Ofytr4Ql-XKD-GNE$<)skCR?6adI@1f$Nm|+f9crlv(aXDVX@5;c zLvCZelYmpl7$Pchfv3o7t%#@*TiP+eaSKw<#SnN7f#i>~39+*JR7oItsHp-5ABfAA zgAhMyCtn`%dSZk)))9nhOI%`uPoZ%>%I`wnVLJ+!>{Lb>ke?$Deg^`9$`%-=D@(kI z>w+0TXsX;C>^~I%L)xn*n>J2qCdnInqy!bV8=eH5vEU4dh#(s*B0_e2KP`DmRC!Ls zrivbePsBR3q)OkF7fb`TndQudgHP@t*usn40#5KwDj1im#2P{Jp!_-l$unp{FAuS? zCkLq0Dzp=@SNE0F;rncCAF(4gb_5WE`O44KSfyWY!6sNi0R&&Xph-mOm3Di-8Ss<^ z#f(tmD1c8%K%vwee-uEn!$<0)_(_xX91vx*jabcdI^IJs5DiO76*VNJk~J`p3P&(O zfy4!#GVA<hL?JJFXA>^Y1XI=;;xecP0~44~p~i+P0TE8J1)r$3QIxnc6Ka$sVSsd> z)<BrpXkj+2(FCGYjTYsGurAmH1~wWk>?nj15t{x(8KjO0i(2&qf;jz+*;ru~@a9>c z2^A=UPruG5ObAP9E2OGO_7Md`5ritXpr`;H1?y53$P>0TkUXObYMv4cdU@)>^Pg&f zN$Yx&r`$SO2Ows_$uv6!6_9+wGU$3kvFv0`mPc6PT#|h(d3Gp@8=*zdjg%#V5UYl+ zvLK}kRjbB*N+85Nm`FNXQBtl6KLEe@XN&bYaoBX@+(&?sMNI-qbvbVx?Yt6@*tiER zh*d<;EVY|vM@@A$J4^+PJvl)5t4LYM3wQBXxXa3b*r0*8%OZ3E_G?`ykWqkU8vq=# zv7+b^8#@9xX^Bn386Oh;Nl~UP=oLj8Gp{H?O^E>12qr#G74M`41(9FD>CkC@=h;*t zK0o5P6-fL7futLeY9UhOtL0U;a*b7%)$u+AZm=&MT(H5GN+CkhE(jw5VPvf32((EK zmV!iS9K~{yXU2jO>pvw{-V%P}3(`_}#08X6xK?!65|`NELw%IKw3rvQie1Sr4hBeI zoT%+fqkw}J0UUiw_&cnY#EP04Y|*feIE^%Y_>bfbno;uBTSXoOoUob(0y(aV3L<1A z?*&pbt&d~^Ms2yGHcujP++A4b+SH{UwsNV5m7}6slW-Z@LG2u+JzVNxLnT_XwZEE* zujJL}XVO;5v(zQpK^jV@gZGqzp$JVcl})-xnvCC&9@ZI6(o7fG4wl|RW+l>~3{lK3 z+v4;9(!K_p84#q0l(v}`j>BKpqe_7Xti}cahrDQ^RbsVQ0@!1t36-w&KEbEdw(3Hw z!}b%B|B&s^ygb2vVid$Pw#oBSgH7HHc_9-RZPAdbI5Ma%;q9~n`yyapf2Gljl4~o| zdhKFDuYL&`w|1+^wi`=3&qqKbs;cE<iW$_}ifW?jln#M>Eg45glhGd1uRwe0#Y!g~ zJ%AacBcEBO(_=AYB9L1t<LF58$~>h*U{<0VOt*4MF@topc&;6KxeSy?8G4=b$}E8@ zs=zoO55x%=u~{NyX(9_E#6M-$nf%CMC}pd!IL&~A7L-^d!-EKP00+oGMn-@V8_MS` zRnR9yK}|-hGAEF)HsdCUnhbUHCm(CBvie(v{#KQ%3Rcwvj>f4{^9(DO3?y2WuPuP) zp<f2ye=<g(I;kT%O|7?sJ1<#2AYDZ&79o)DMB^+X$>MZKMqsYWQ5mkvRm`A8<O9>I zkPtcqhI>Hc=t%O_XdgNR=4uLyWv?a{%pe_pnrnKL4uO1c8b?QyXOzx0Gsa|5ROn<O zIha8@@}cUrRvrTR9yN}RCQm7yYp3*67s>nvNP-!pBOkI}hlrGmz+B%OPe+r_DxK@j z8k22>$c7`BK|1_2*Y_(O0&~MuJRMC&T=a82nQuVl$a4d#0y9X5pXLS_A`gLl^BPw! zNzSo)CNMWr2cUCfkzxkv$j7p)@onf3$ak>e2d1&G|7d!J3beX{+nqp#(3&XSaf5=< zQ-J3bTua8AtY_R*0@$gsH}wLZv>=k+T&Up9TL3MEn;Vty9I5KmsaMy*E?qrYxUOkd zP+1i#2pe-#w}LlI2@s&30Nk7NEGVq16*S(n`Vhq(&<b!93b+YM6wZI5=@iLwm(s0u zRgksBuFbb#K46&z$+x!Ag3W-qNTp8)wq3l)hIR?$i{bDC6SK)SeMGhE$G)kE|NmsE zyy?6#Z!S=RZzlH5RTiuQv>e|I$2a3&aC~z=FO&kz;b!tmlsSQXejLwS(<vst=09&a zW6WENl*(Is0LLvTu@@|O!I-yYEBLl3V5tSm0c#cXDZ$O;<Fb^TK)y4M_bW-i75l)P zz}z~mUUBO={%IQ`<6`UKzn%gC77X#?>wp_Fd8;kh0N855VK`tV5N^XXw^<6el`3C} z^&jPG%Xcdpz4eTGg>YS0uAs2mkggzX%m&m`Pk>`@KmY;3-Edw(WrcZ&^`Bd}K(tw% zsen=or3ya{9%m?$<*uc(+FdWPR=WhIz-qT33TU-kP!1TcU8NaO?b4UYtZ(ir7mUQR z6q5_#RLCAcDx$=m<i$Dx(dG6lf2rO}4JeK@wx}#amtM03b53ex;LjFIdkfuOg<Z&^ z@Qf>kqYN*}HD?`*JmRvF2UXsqfeBGsm=kDr5d7>Q#GVeINktSTvlb|Mw1Ylq!C`)m zS@5h<Q=$!k{Tdq@035R51Rx55LO7ilBLqtiE1|Sa1LNQd!b*r1YOIJCYOs``F9iiR z_K-b<Ic#y1kAPDkqEcb$@<tSaKqQC>0wr)`PY3ymjkBFVSR%ZDIBjUca;F?Zlvtmr z&=;amA~yC2C8F*nfRYp#kidkIRPq$@!b)O`dBG(%_K@8<XjiWe0$PO<=sN0s8t5t~ zd1RGS#zDmTW(15qLJ8Z|X(09!K4QjDnZ{}!WCFpLNyPJHA~yC2C7g(nHG$MTr6j(A zcoHk(%}N@AE3v*zfU&0+XwnX<CjqU!33S~@M*HWWWUWLX3l%!C$^}FKkzWMBB>uz- z-w+T1M3IT}g~)78E}<qzU=VzwwqAKra%ID9^_qh~Zf1xd^J@CAX1NW`zq3pEy|Y(Q zgRJFFhj$?uO*DaA-4IVm(?^uhyGD%J)UAXz^(ktQkX-su+^B>I<Zg#}LYh9Rgo;Pm z0qIdfB`5>bAR&I5%}q*(KrVlXC#30PN@(+#G4Jiw-0vMw)F2^pn%}{bC>nv>{2fn7 z(@!a(-#KN>`}&m7`%WrqkPtb|`&*R|fm{y}exTJcu}9L&^OX>R`9PVrVISyFRB6uq zM+u$P#_s)RL9ElJ&`12VkEQ|`Fk~515phy#i;oznILfbD>xG|+LH$Qk%PAIKT`v4E z51=4^U|hkwON_buf`T8cU>~er!HO<GY!2>+XaGJ`Ye8Z^<i(x_wAp?)-I(9aQiR{d zDL#Bq!AcO2T_}8HfcLZokpbmNtpBKl1KJ0vgt$Vzu@X{o0PjY^58Bud9%3Q&yvBY6 zRzehnkDTSTu^)|E`o#JV?94|?)pP`MYe(D&S(Bko-}KQ2-u^h@G?l_vl2Xgts|;hL zPZBj`Ne}5o9`RlwH-!8ixuH#9s#?`6s;G@M*dgE*ikPcxelHh9*x(92V!$hWL^P|2 zUFsD+V!$huU$=UNpBnHAN&USuTGA@vhx)OIAbu=e!H?n3A1_q!;|KYNt9=T7;uIi? z26qd(+R|e|Vz=1XPe%C1tTx*xO99Ij;ge^K`P7Jl)gV+CS#Sz9L=>z+2GK~sD^$WM z)wW8AS+J=}n5m#jXk$M<3ef_Mt%j8l1y_mM*qSO!pIHBaovCS7(-Fx1Dsf(+$xz2~ zHT}Gkal&aTg~uyudUz+4VT|-NQRgh_b4IRQiT4V4nS00$Z344xNL^vujG_j;LJ_wp zn|ro^2pe3%M+|s{kBC<&;wkkCA2Hw+%I~y#g`ZmIi|t91r6t`a{7^p@5yaY31#9u= z?ez+7AK~B0o>A~V*O>cIG`RPntNX?ktRuG0#@3Yp+H7^rfE|jkBg>c_=N0@62%l+C zus#PhlvofMP+rh0RQ?>*wn~Uuu&GK|rl3k_W4B*`Xr0E^!%B#PTQ5Yt*iK77;1zN` zPW_;oj=<a>jrR&ohB}t3pCmauPB=}a@Rg*FlbWdvjrTyy+@GhU3FLB|c(2fOazp!m za_>B+Ua>1*QG;Hgh+WF&{w`y7!3J0G5d&V~BjOc`=&D!vhykw<e!C*-6@F^KD^!|t zE$L3-hx)O!Ant0m;IuIfeF`?5H)eO1g1d_WQ8c)_(bb-G1@{oU$HwlViP>Yb?HL3d zR)ofKWA+v(_*oD>+ppk*m8hY~g2;gKf?lB#R;spDLd;U{N!V&ZB;+e=iG83DqP+?} z2rD5<?1MtoiygD{iS-}YnFpuUbOdr&QQT^sBsZZIEJt9PC=(;UrUBkT3yza1U%?>B zrd%~5foZ~?FqAw{7tnv2@`x_e>7!B{SI|!d**rul;~N6G{V3k4G<`-zduYa(&*Llf zI-f6B)Sy!-BGOhuXb=o6fG7Eg0jKg2aVkZm40w`{7;q}(m#0qUr`GvmlNV_|SFcw5 zobW4FP!K=gqhNEynC4Lh_hlQizfi&b)ZYCE6_o$>+=5c^uNGokyx49)o2_LW@Qfm~ zqR_Sq1rLC5U`)aGMq}E$Er<*#FX&V%VWZkYB`i`<CA5wr67I9H`zj$iq6qD<5~317 zwB3uHw)BbhAK00Wh?<T-E}@EF7}0cm0k7&PG3E=P;#FVBH0JlK75x2Sz)1!FV8WP# zR4@<@7Vx%OkoN6huLaM*0aJnSa5=A~@Nlj2m015#u2t#>9aV6?pd}HmU%*<3udGlz zAZ*M*)DHNtlmGz)1oz==3zh?-c4GafqZy)DxPq)G;2@L${pSl8D3ax_rNeX4?C%r% z2RRB7m_I18U<qKY1!3?99SZuCP^WqLkZPAeuI7rb7?S=)2%%j9^QB6y7+>mC)L_L> zLg$tC!{<T7Bd85NVxVI9h*S(ktka6&BL*sl@~hX1;iuO5Vq0mxcv3y_i^306;^Bh$ zrAY-3l^gSAoPpRcZ!zX8O$vUc7x0vVUoAD}s|^+;_N!j(8IFS4Y@OMFQAOxHY0Tj+ z1&@GmG+n`?Lx8sC97P6{7pxc}{}+eUsw!c#f-2#Zf-0en{c<;yT#Y>nD<O)ll&FpE z%D421^&i-ou5vXUf!vT5UokYjQ%%=}TE2#Z;lN+3GUn_33Le9;j^!!X9W|yK+k(*D z#5-oe3BYLuAIXJ7y#>1fErmx0ly9(NDA!)~gRWlKm1;?Z>(>SqR91KgC4r6UKCR#* z6;MI|Vjltbk!lMHt8N8jr5>f!=nwpEO5F`5K>ztVHvPKguB9thL5>l7tk#0HfUOoh z2smItTA*X66!a;fPV>mPYL`Inj*Hi>rsMBaj7QEJb39#-h8%~`2~^6_kjJZe4_R;$ z0yzry<^#eMgx(P)8$1|yJQGTTT63Uc9!Gi99H^MbCl!Q>>BVJ;?IpIi%Yp-dBMSQB z`;_igdCcR5Mi!=gN`O8k0X<3rdXxbDr{^RxHLB&04?``Y;0X{<ASn)W;v6rU0Ms&f zSP<Ka(8MaMs0D=;J}I%-winw1`cF>@ORpz2st2M0uE)=6>}$gH(QacN?a>7d0`n-Y zP4NlLqr*0qVn2$TentcH=!}h>G3GIpQK5l(3<qGDioiUUZDX?mDYnE$DOj#HWdw$D zN~{*QQq9&=$<HPm+XRT;K$pPupe@1e<n6PueW<2RV+qW0+yTi5%<*0u+Y5+oprHPU zkWj#I>Y8K`-#U?RWAg#a6qmp}jyT||9Vaa~sRoqQM75(8y%$S~A4+ToFY*c~)*aDo z1X5=t)_+u3#KPbz0IUQY;I*+n;t7=D`_^ed>s#uY);WAc>|-9I9FTde75$Ve7<8RM zRB$$t&-@PC8&zB_(m@MKkuU))0uHOC8?&)zY(YWrpT`Q21#1VCE;^kAF~=$grHl56 zRaRYbDkIi^DBLAV6+u6lDhPo&0e$+_fKFfQvSMS?JFU$mfn0kT-%LvS6Y1Ja5|};| zOw-plX3W#Y3Vx%}m~Zr2a0UVe3O-W;IAXzZB^zue`=~>ZkX8^X<{MQCLdASzMnR~U zXRsOw&k*}ezXeAC#}zc*<5Qx-E2T26`#vRNeM$m)lmzrB0s7BVqsVknEzyV5K8+=C ziKjt)8c6}a;qsyh0j12{7Q}r-XkwLBp#^*SNo|+de%=8EW2`ETft{rGK{UwKXzXjk z^@#y2c~U)<z&tUmsv<B?oVKwP`-v%Sj0nt=5sf7<Poj(p4a}1`01i%Ip3Jwg`1q3) zTVe|-Sdlgw1m>wqjU_No)v4JC%u|PK>>)t>2D$|1DYOLz0`t_6jU7TY%^FK!`fvxD zNdnV1Xk!Nfu?-Xm)M8M;aO#?H5|4PgL~#ks(_0jmz<dL7z*RfWSa3!S=#WkAXhnYp z(ZvrXwwo7u1w`Iw#x)y()ESBO9~Bm{u&xRKD*;D%ZLE*@G?~1pr_s0PTk4wDIebLy zW1gfOka@BT{ZuO$be%CMnM6L{z_*e+>@$Umt3~RuU@zss1h9CfpVvC9mhOy=J!cCF zg8w{OiY!<=pmfoxr$|6;1kj#<qP_k&l@aSdPnKM&RASUz6@<V%U7*cmK&P*DSyfV3 zn@NLOO|k=dR0jr=hU#GOG*MKoVk!tE558iaxuA3i<c8q*=2p`Cqe_Utd@E0z&~KgL zj9!I;-^TyHJ*?n&aOCeyT99ne3bwJ|q5_gnnozQuZ#ODPR`VT<ODtK<cW_-m|MBzO z=jFk50sTCHejY&o=^sI2{1tN&nEun6hrskt+1M$-^ICZc%(FQfOJJVGjEF{Hp2Z`f zKwzFNv9Tq9Wj40Vm~WP9b46gjS*@`I=9{)u1m>IFHWo+wCIy5pf%)c18+#HEAte?e zDW`DL;x-!xLf>lU?X<C-fPE@2f%(>$jiri-I-#J}Ky)Y!6j;O1kBE{7Ds5~fV1wck zm;tK?0yA(y=@OW4=PE9N`F4}W`lf}hsQlYjX9VUunJOfK`A)gw5}5B)*jO0j3eq^L zN5B{g-+}RW5FN<~)X)-(pL_=yBo-OI8&O;W^WAifHQs|Rw77V&7OYtvdSINNXRL2~ zhyy6ji}FiF9`zH79cV4Sc^Zm68ucyFL_s3OZ|7L0kViE!s0e=Xg{W6%0i{T%6hX^j z6!e8x&p547-^z^Vnx(OUa=dz6ad-194uE*i;(5<n`F)w5t-|$6t$P%xQq@XZv@8l@ z8ZiP^@*k*~XAdP(RG-6v;WJRg3sHuQ{v&see>X=P7y`NGI=+F?bZQta)ptvb`9lQW zL2$vC=Wrar!G7Lx1^+0|m_MquU?bp+g8vC`fo!m?`9lf^32928Vg`{J5Gn=|0z$?7 z(WnI_79Wz>87Sd`fd1oC!a<c%vwEdZiCCYKfF30QJxYN7^S@DV{%}~;^qdQ|3JZex z9Fn5EL6kR$CIpl+TX*^+97cpDR$0|qP*_b^@C@Ljf-zPHje(uy`9p{XxfW{dbFT&0 z?@nUEDO-VYz5kEB_W_Euyz_mZ2F8#`60#CQ5)wOm(8Yu(GeIR&R8D)tc$tzI%3%|d zLlzilg|!D*=uylPi&Kk+WZ5eAE*jR51QW6$N;YWNgcDIaib@hxjHo1{qM6<0ZpbdX zOVy?7%)RG+e$Vs%y5DZPWzf<5IsUBgJkR_4|L1w%ZkitFyPLLEEM_{#a#_rDp?xs0 znCVK#tz=6xYVBgCIRG3v7Bk)CxJ_&+Texi$7P0ScSj?S+mdj%99J6C%F?YrsH^!E8 zgI^YNC*8sWi@9^daW`nqwB@pxyEqO!vRKSr>yEq5mf7He#ZC+l49*@+Qjrt!y{Oe? zG2a`ux-4dfbkLPK%JA6g*~QGx(WU+mgIp3=xQl>%WlO$t4l&ci4Oht~OIl3VCO|0J zZUM(t#qZG!JzMnKJ6m!z|G^y&RkVYl4%|#H(4P^z^&K5setBw~mpHI(R@aua<hGQw z^T68b@~y)6i``vJ4ocI#<ifOlP4_iYwoyR$WGmfUO==ljrD+sjx+)oJy(_SuZL58T z`Fi?l*J?9m<orI#<Qfx@-+z`^X5x?1#QQlW#K+KP0<0%}Mr^fT_w&2jA2Z3^gLa6C zKZ@Plxj_t1M7cqD_MvIF2{r#;s@PY-%j|fTU&y}9IVv+Ii<^!El+9xyyV7mBMY8+c zc7<=6cG+!CKig5a<-xeG&~DW&ue#>@IOWi?$Ujk$lswnw2e?GcBL6}~l9+2VyI{pE z@()xbiMcjEEU;o0`S&T3#PaV|+}&WsEasje3dUiatbE88eD@H4(UQjmKP1d;T2<L9 zS;eURsQzvezI)B~b*>!cYPaoYJ7Bl>kjOoZgBje@>OA?LS94V;Voqai9Fk{?z9`%K z)r*N^Ggs%F*RgH0Pa769N4xMimk4P+<tDwQx_gE+XYI3&#oQgUFB&Z7?iI&nfOqpE z$1!0sa}1k@A&Z$K`C7Y}xe~`^h7@bLQgfx_R<b2SNl7y7cU(zp(Qy~qo^V|0DSio| zwPL13N;Vg&l3eaSX-i>A(_Xb<nC6~gJ6jfWUo2&|R!-HtXS^q7%)Q%ow)fF!RQ<EH zij#J>_e`S5M9AY_(!19+`d(UjFRg@oUp1(A+fnBUuF}1|urOz!HcqwM)^j<UG+P{- zdk0;dLAGPIUKVrjwB!0hO2#zY_jdW7b!uXC(oEWQ&z9{ri@7(?a#_s1K|5O(b8nU7 za`f&cd1lLE?rm_~2DWXED>ZjHZWmiJ6pmy#<G7@CpRrsPb6=t5+FJ2TI`qcYikXt; zB0UX)GFNLE+a2vy8zyA#o42!Nk$>7H`M$Mss%EzLQT2~X?LdD-a8&)XwTi2Dw)d^_ z*W;N8dBkXR%r!c;&X!if{ZStna@$4c$v4~B6fDe{t&KzOvK<18NwdYViOsn<b8MGv zy(}iitsv2TAthrP?wf6_2n|L@Gg(Zm#CDs-#6pf6Vq0ft%VJ`^j@!$Y<ZJC>V#AI* z%;lKlO3f3FJHeI=84`=+W22GQkIF5V#r&woa&4{nB^|95GbK{8xky!#ORKB3mF<r9 zstpq|KiamlWs!e^CwaCazn`j^EsJ@e$qw`Z8jY%dwpKCU&i4L%l$i*5+)tzLca464 zRz5&0;XW`8Vs^`UvYy~7-M@wua|SALP`2Bcd}5X~TO6DFH(i`f6mx97Eam}j1&QMe zDV}J!Z?^Z>V$SGjCX2bh!FHR)+#hw^DBD3hTNZQwl;cjZC3&$Xr~Bs}cb@H%<1VpX zaoiQQWXO<MBp-=p(`vKa2ar6_@3@j7enr8n6`>L-*<7TjlFO(qg(XdU)rJX~`BFPu z7V}U;%51His+sLPRX;dl2l`;ls`_VZ6|3xQ=c`a=BINO44seZrkY+qcD}{RkY}xHY z<<1jar3VX;V$N(O4$5}Bg<^TqY;kNJEOs7?*;d$kS<Hjn3KGW`QasUc-)!dxNR!dg zOcpagY`e{3<|iF@lI@(GEsL37bKEtyB#&<vGr#S)+xXA1Tw8OV<vy4PmkitNBKb%( zo7R})j&V8TxRN1$MZv2TGbK{8xlonOWzm*0zlidV_NooTG!He|*|Nw#A(edJS~*oS z+lQ$7;RQR}hY60Vf3{Y!*Ut8#UX+;#c|1&`A9js?m{vYaE8#8_f)ckSfAIuY>EUV= zF=w_m4!N^M-z>Bx%@)Vz;d&RRo^8a|%VHkpR*>k4kk%6o_s#a9S<+;5G?T?VG;h1j zVjfy`+*P)lcD5|$;R4HLF%OeGvt=<4mpX1K+X}~(nnR8oVoQb;$s+kkG@I6v<1TTz z?zqxZ{Gy<>Vx~k&HW#Y0xfoX~;+^eP8@uM%*_s^w*M1>pJDK`}L6x1Ysp3a~5t~vr zZ9!FXPNF_LThoW4o4hLe-cVZu6s5~32BvK}S$X`_QEaz4v?-^~ZP(e-UFzKjci))Z zYRCYGEkHs{p2Y-^@_`_Wbt>FxFmH#$VgfW#xHt`*v}0f~6f0b*nIvRnHWvmdTn3p{ zZvC>@zn3Q5NeUdbTo#i(X?3O6>=SN#g1m7?IxL2Y#F;IOz6h7pr7+=c+Tw(}uNCxL z?!G~`Q*JxOcEy^pn0>2`yUGZ1ESJTc!KuI*iyaKkl%xq+NI4ZY0S=(=Mxy5?i&E&Y z&41bTU6QVI+Xc2uNqxtgZ3=E|Q>yGRv#PixW4P86&6bejDQFdZ(R0Kpp-|X22V!=6 zMx{$0ZW2+YeC|P&`!+eAJAQ8MbH}rfz^(Q}x@@+n%I9@SgkoJ1!<ZU(5NpVNz#bGk z+cvuuH`&u}D~&I-+kKpaee@>6Qt#rhRpL2i7DjBsEb`Ch@qaHMb0sUMa-Nk7%f|d9 z-&X#ULbeQ^%6~Eg7%|(QVuS<PDp~UlTgJkMF+bk2_n?@IVw<YjOY>8g2aEjEd`W+e z0&VltS(^rnSuC~#UMy$J`QR`tHUZioTS{8Q6<a0TnZ<EiC5!x{eaWBNTlu_ozc_Eq zW83zeE=?HoI8Eem{;US{y6vJdPvqL|6J7XXBEHkRL`dx9Gj~kQ&&uo;Q}eS$yT#Nz zK|@i%R8sMOKCk9Hf2=umvQ=}oYR*>8*(yCoolC8D0!veDse@rWPD39bbK4cRYj$f( z>T+92Z`f|1XmIIawp<9RELTJMCi@sS72(AHV>tCkb*JG~iTX&ym`6yO*|L~NxI-wP z#XLg(!W{<mpIeE=JhI@p+`o^IR;^vkBXmG?*8qo8xEp|O33r={@~mGLL!H94<yP8R zJyywOljAnAjam;Z<}pr)=+e%|h8%Z@*3?@ri&=`;%vj8l%a_HT7jlr}CKJO0i_BkY zlVk9Bk>#?O$IGl=7W1=^<=Qzey6vJnnwZ&hQe(MK)No19Xo(!yCq~^l9A(Qn<X1W@ z=7~)k?Fj-icL{9AAG98pgIrd)Gh4xyK9D4fJ^i9fh~-+xr4l*RbVkWm&P?PeN;R0v zHgPId5lQ@@&a!1pC_Yi;GG(hIQ+_nZN*`@t+iJHeeUw{FCg^J<Tkb!5-?Fs@uUZ9L zuyL6ekU6zWX}&6nzFcj&asN4lbVc~0+nM1>N<;H;67an-qa|j!!9Ial<evcLd*u7n zBQlZGBc8J?=E)5k@yTsto?<ej^z%GW?zVLM7gP`T7ZEUGx9ZD!>a~yD<z757<2DvN z5!C<4eY(t;r-!WK)0@VuaL`F&1?~!?lx;1DxNVf}sN0USowZvHiDUDNEn6Im{M)5T z4{s4aLu09p#XK`$^L=K7EiS3znHX?)>N8~W46fiR;m)kmSYA_E<X<&Set27Xv30*% zY|QiZ_JO>{kk)$b_Jt{9URbf)7fX$KvCVCl@HJ((8tM5aY-lXcW=zcs!*+|Q!A`iC znqQXNEvAx+|KY9X+z{5BI@zi@TQz5^=4_Roqt55&?EzZL!v%G4mey$K+DW^8p#pCq zx0RBX+?MoS;EbUA;+#v5?Js-5gym`|xJu6r8bdg-c^;?!sP0_9Dp6M#nIK6sTNbmr zYWu@tR>@zu4F6gB&y$M9Jj;oM%VM4-ty;U7XX$`&L!icSYuM5);nq_aN0zp-80r+R zEqBb$>bWs4V~!hRyKFtMnCCblqPqe%9Cw4(%vvssd4ADm#$uj#`LfvaLT2{3xf~dr zJ$d9H$6&3`dSEeY!`3g0d12gg<!H*;BCsA!%;cQBIOVvaK+k9ii+OR|ox^Q6Xdd1i zNAt^CTk$Um%-p4TJN|y_;g|hfj=D2D%9cJ5jm4gR(Ivz$ryX~iEr+_v#7QcbdxE24 ztHE5hiBqYXYk1UyS{Og5FHYc*JH~hT?37zA>)AO*HlHMYmfB^4<fx7GHAga+f-7CR zQgD;oM%hxkDEO+B=#!SKX+GOZNLPd}x($UVDXj^RfbZc=OUy50_6fuy|5h?jpn!Tr zhWrFY@__rdaWG-GD!0-a`@po)*`#MD&de6w;OWL9|JHKS|F3~-vqichromf_$>Ix_ z?GJ*y@4xz16L|brk?>VCBJi`zk9KzUL=PT}bhcd681C-w>^^w#y0&I3i+ZwXTX(p* zwXr+g(|NqRC7i1E6;CbP+Y;`Iws&?kwuYn4?U92ATOyqu;l`uQJ>i1~Z%AB7+#h;I zs@l`l*wT5tBN}d1{S=NEJ-wSzYq%%c-Fdy}{=e9VJDQJ1!i_y`&E5FDs=M=8W3;Wk z2k{g8Jy)KrE81Pz(%I1y4W2?VAEBCrop}3kxVz`z!H;&5e=p6v!P|-GpRA~+v!ywb zkozxDT7Fj=rIzcMa$xzRX+&4GQ&mUvv9KsyolfC+M~j_=D*a^|r8Wj1_wwB|3XyiE z*Kz#V(Qvl}dLoTVS98lX%~vOq`G3;sba%FddwLq%rJg6>okqhuU{2w`rcvmL5~s1} z`eR2sBQm}xTQV!Pe^%P^<mc099PbHtduiN}N$hp($;Z+tG<S7H+FP3aoqh5@t={3D zp5q*H@6LJZ9hP}T=O>yY!oE5jZET4&(*w`@Qz5Hx8FNf0ZMV{oHg`ln-WBf1r1gKr zeN=UZd#>n=9_nqETX|=+yRBwzxcgXpPY*X}Rk)))+?q!7=`*e7$B#$5jz^C~x$Tc} zn*Eow_Gxz{4|iPK9BFU8th4)AbGoQcN35?)duY0JEM2&pt%_~lN1LN9ZQ<@qBl4`d z{zy2j%X_W<$2d(Kx^xcz**WAs?CxleWL8``knuk64qs)TM2+%H$f#u>m5uEkS9S8- z>fmwL5$=}fg5R26t$fk*kmfnpeyl6f*p)eidti!IW}TxvmzyIzyc<6fw2!64W7N5q z9PWKhb7*bv>FVr}dvN7{zNUfY+_#1!VP;S8pO@OB;D6G3FGwQ1CgWfeFH=l2aUn)S zuW30q_+9|xv;281a}M6?tj|n1lK2a@6^WOh#LLq!veI<v27lAA|3!UIl&8hD;g)D; zccnGB%De09I<E<Llm@Nbp2Oz!D(-YT4|sg$VrxNu?JbSGWVd%*UD?8`wC72-jnVGr z_Gph~e`H4l(Xc)nkI4Opi{mX(tNZ?s;D7Ztn`Qg~j4RuTRo96)-_95PXWwV_-IG?8 zpKbCn<C<Ty%;aZt+`_&5B@5N^xsS))B|op#`nhjqP>6f@Ushq~b6h<<|H%vr>fw3! zGN1D3j+_6hHBXVM?b-*e)b~7ByR{up`nZjIna%Wok30Am7g%0I)4UF-w-?U0YVoJK zn!mv725-OO{J6er=;72?gSef0Z?;3O_AmaQ)^Gf@+~DmvFfY20X+>YKR_-j_AdBeV zo{srz%S=8lH~25H{G~gZey+U1^u0F_rR(DElh2lo?`Mg!8;WG+m*6#(h4P7j^}O@U z-H^%><%{;B{Fhca<+R<9bS*xoPEGCKteWq1-Vop8<sb83T71L>$#4K~NPmFEFE2J6 zz4UTAnqDA=Kd^@JGkb%#6VXaW(LcF&&pS>mT}yh$gO`7D59$<wq_jizpWouWsPH}_ z{zKpmi3_~_^Z&8C%C(+Kh94JiNXr-Bx4&G&=aLQMKY&uD7c9<_IR9%;>g)g2Q$Kc` zpXv@CJl-K4!O!}?d4jm}lplCc`7K-G4axugH>b~McbMWkuOri6otM#T;*BHCN?eH1 ze}6eft1rW7<5L-pd~dJYJO0$Y@$i%r=ThGArctDZjrCW{^RGK!Ezkd2_;Ng_y{R%c z=3l?{8U*>b3to#LKhGG%zJ52p^j(<d+~`kP>02s4UM23V&CCbvRg11~Oa9~RSF3X0 zt(9Evf1djqh143iE=;_xUKzfc&o#OeKUw(S{4kXkJ~4>Oo2;$aOBkiTxA7bPf6u?7 z@)D0vx$zS7C#C;&)vM$=%e?g!d47rWpK=P43d%A+`Hh4PeC^c=oB3`}E<Eegzv&Ee z&agi;H(q&^pN+%e%G2{BwD+TRS98050)D#u+M6-yg980IzVQej)3ikQ_e5P0uTAiv zhL7<1;c4n#+-Ks$58J-isv>zzH-3!IA>~8XM!xHH#`x=p<P<+VDh;MNq49zK-X4<U z9qoU1oR`b2H@bV^_2<d%pELe%eN^PJ@@DrD@3H2t)AZm>*HQ1K==bc->+A~K_pbl# zGxRb4w%@JC^XYjn5Pzt?1~2@lE8}?1znjPL^tEBfTa2?l@cJ2kb>F<6zTy2&KT=O$ z8<Nj({2kESAAbELzkZSrzWP7Ay}Bn^-k`nfeKy7`{vCbdhsoySz4-mZZ^+jw;-7F; zmLK5v>sjZ0(f*2|G5#A6{p{5D*%4|VYw;&_dYZ7~s{p6RZ7}&83Rxe2+WLL{hojej zI67#*<ih#zUPX92FJC6fs{fz%h`jzYQR>%!yf5dZ`w`FU;te#74*uwKwu7(2hh?Yh zp}^<)k{!9O`o1Et<2MrC_dtBVQ^<Purd@s+;a7gneH*}jTVRLt)Gu224cFY)GtwI- zeU-v*^}>Od$SwZ03BSdQ?hCi+<9J_P@az9_<Rv1cd;`I6cVcVD<c=P{>Sca6jNfY~ zzF&qLrntWSQhBBQ`iC#Q?A-sBFh6*(hgU|v1A9E|eRW*Uy?p&FJKsg||DK9(hbMhy zC+obPFt<SVmCt1SwL<*GRlbRu{1SZdAP*o*IsCKIvdM9m_D{b1?})!$VJR<V&G)W# zE%&a~$xMn|_0&(UC)aha{8T%&*L63!>gihT<)hcTt!*jwRixB2;aw~L6xTqhXE*Du zqraus^(poJu3tA%kDQqmZ(a4)bylGm5V@|4?1e-wd|fl}14T|RAm<AGq-$8#URSwS zwt%eSPgcpx&-Y&=3h=jWgaT`JG1-z6B>xKop@4Tkrpo1i{UDUBYp=UDC)}DH@~(CD z^a4T0-|K27ogM#^JxgbVyz5Q3+CQbv5U2y=KuLNS0;&80c;c_dld)JT<<Ckm1cpHf z3;-qRQ630_VjywFm(p(XJ`@Lm`d2&Q_XCL~a;17U4a|aAa-Ro?7x2fcMJ}~XgE^-w z{}+%r?Iw?*xd4{HGEgFx?SuH19BP303V~{%q<UVSR;GGYs>G^#zbStqa!8lYspg%@ z{#5J9WdFZQ{8O#-RQvh5zvT0r%lR$@C7=uxfgn&)x$s3tN%_C0c7ax&mk}@wmOvNi z*W%glA~)seR)8@u0Y<<ms08?olj^B_z?1i~_5tFWC=feh#_8qSiJuUV=d$>#0@XlC zuWMnXi#G#*7EFO@FaajP7#IisItICxc>O?0^Uh?~hhjg_y4%<@hm7^VQa>-VAAuFl zz$))~N<ftT3DyGg^k`T4rqfq@wX?I4+SdR&JNgUDQiwmRKx+MU@Wj3v$c&XjZ1$pG zfxh&98pMFiWdJCNTzaQ`i6#0WAaRsVRWF2r<UI=(fW#UCN+CAlSNXfuxtpHMst}BW zWl#p{K?x`YO2RJ(<6s_0J))<yn>-K2e6Rx6!7vyBgFxz&c(ou1ih+{mk*Z&Yg6J!q zs-D<%0f{{YB=#_nK1nW0r>a+gK_OTJn_v`-0r4p@%7FAq^J8mC_~jr~zXG1<E1jyI z*z^L4Jp&~6DA4-YS~^v|0<;UkI9LX|)ggMXp9`Ack@jzm>rEiD_<cAR<<wCDmUz}n zjSFBA#DL6y7R-TZFasum+-F*UCHoPel<F^&{V)b%r}t?e`+gw)dV!K$hrnL_G+-ls zYC#>S0yRKM{Wif6y=vf>>vgLqXR)O9iBE|kHWDKQB!-e-uU?s~%9lQG0O_mLrhS#X zCV*0^zUqylAbLYUdN}|Ff!IquN?PY`c2bMj{kHaN>GkvZ`uY4VJfEfHR0hU@+{bbc z$~`IfQa`8$Q6Tqm6;MjG+f7g8H6R4UkNA^&TS@($s@^z;zXSPZ@odW)0py!Cuf?+8 z0w?**6;^g}f}c%K<nz{SdX?Sf<BxMa38nzg5~b{Qt~bCozq=_?E_>{A>Oei{^YO_g zXB13;1s@;#eO&I#0VN6kz6P$FKr8V1$;d}%Uq7JkeZ<%|2!?$AsC%EpI?4aawqSR@ z=$ugq$mxtq5Cp{uyECF(_X6UcF>(rgbj}zBlVA>v1M*aQL!L2j$OpuIL#cAvXX2yt zhB6QWb)W)}r_vjSxTY6xAnqHcl*>L7ADuT$gBVx_vw%F6a;ZI+UgVa7D&?}z#78H$ z8q|Xbs0HMylsmySy~rhQ?!0o@XX2xiy8u?e23P{*sq{u_e`5$#fd=KW&%{UPjZL5n z41hL3o^dK<R|LvI1t<n3KuKglu*K_Z4(lwK1N6|o-xC}B+Gm{jP^x1i{7iO!y?QQE z{gS7(Cx6ofl*I2|^b65HmHHOZTLq(F98`dpsw-6=bxWF``q{0H-Si6aD*2a!avQ<@ zA-o`%0qa0yLqJKcD}l<Z*+)PKQ~@QaQ}tHZbAGL!=+^+HQ`Oro-!1PPjpKL$WXfCh zrqGeIHUTEVZgr&U?^e&L>PLt@1SA*9TXGTGaUi)VovPk$ebTvQ>W|8I>xbyQKG)3W z`c&t2s(LanxmT7s=Q3lZm&p(0rTD?Go#!g+nmSM6o$&D`m#Fg*V2zX97rmel492;x zPkZ6lVOtLxfY>RCf4@xm>U#*rurgUU$*~CFC*b$9SN;~hwmm;Gvy<%eljGRm`=cYW zILUn^Ic=a{80Wg@&0hGe*!BbRklERv;i(}`HSB7E@FZ91k=Q6n9;zcUk0hr6bIO93 z6;Up{3Q(Eg2SQw*PC2;*nmqrkN;XavGV%>bz8+~l0Z$g^7o+FpDz-{eQ((f?lyyS6 zT=#+@Fbqa~d>=1sa(8}U4FBUUMqoCfFZV*A&nF{>)$L~`rc$7uYte-l5FN2WCr*Xz zir_KNz&86TAaTk-IVc7tKxwb~p8XF0>aT%K6KDl(K&gq1^7@s@8Uyp>S^?_WFMyLk zDaPiN$d|E~UWk9+xv+5-ku3qyQHrr4o>7_dE7^pA=S$i4y~@kr2bh866es+qeGY8F z-v;y~5Lads0)t*%Gd@8bd-@pY0-R0z97HcpP3*)@<thlV@ocTlZv0vldO;uX``;_y zA5;7(i66gA`5IGd8&)RkCN&j-2H^LzSN;~hwmm-)_R{zK<Tz>PRE>`0w1Ix1Pk*m` zxkvf|dA$C-PV_NQOg}0>B?$TWa+W7}CNry7<9RL5PJ6G6vCjMA7I7T}l2_I59zXs* zK+l<$!1>kp0`~m<w(^%rY(0^yrfHw$>G;giz6Va3qrU#w*Mp_F7x$VO<636E;N#b` zZv_K@vu8gm?PqNRT|ntKr1!>gK2Mo8=1t^$W(j-d`zG>w<2u*`D_|8Y0($tyIe@Ox zE46=91@S6DgNys78rE9CJ@Te%jl#YRh_1*)7n#)+TXdD)I6;1s@W}B^)MD$w_Kh20 z6QtG?gEtSRz_faCwr@H~Pl`Y>C;){Z599+>&&>7dcVQC+17H;Nf&PU2%r^9U`6_7@ zAh$CoSxZ>Qz&OC}Ozh6Y?o7WOIiE=#dBhj}yd01V?<8x&y*YCo9=am4y2wOVY(-b; z%m~-yYV%-~Jgn^ytHhT)1_8B5zDjvwBl)9~Hx7ou2tYRv+dT5l!&WJ8iR(3E-h9HC zw^XqfgK<y@f*=><p+jzO&SBjE+iK1J723bK4ZjgE1SBr`y}2Jy*PE$B>CH`Ci*7#< zU1U~QY|&N9TPCL!cv4S3tJKp3ia-#g*0YKJ7FY#q>c!c<rI57(gg_Z62PL2s;O{N? zR<gNI;C}`zfGIGoQeI2y!7!iiBhQ}q@gpz6??pyGl73DQ{dD|%_!46gtoZy3KbYX# z*ERH%0%ge3*$JO|)nEL5yk}_bUP5labH0x9Ha^I~zAkNPRMsj`4MxEjr~|&dc9l!- zOF;;TFY-<L+;TU09{Q5kIG6#gfZoP`Caz!~0!ngS3C6(`XajzIE-lsYXDt{96F{ku z4QIy2im{G>Q4j^aKzwz9AduXZgeN-Eqj8{=fiFM5WtD(B&;-aQs}_)Z7X8jD2h@^P z3d+<OGZMQX5W9L%1w>!$Lf}=f3vA&x2hbP!nKp3J#7VESa-CcSSs|_^H_5R<x$LE8 zYRaZwxyNknQ>;?E)Fibav$ac2)GjqC>2=(G9Qgzo0i$3L41-qC4^sTa{X~#;fmFMw zvy1EXa@_|!zsfhc?D7F|>=`3x`*T|bYY3EpQcwhnK>;WPO0U#j{YyOh6sJu5JTxR< z%~NbbKuP6wFzS`b8Ugev8(wxVeUSdF!jsjfcB*<=bJ)eeJXrKONQq-V%Unmk0wkX3 zE`u1rR^r>wRah+b@n=660AoN&`9m;9mC5SG+cl2(ng#tpd`n#MsU+9*#oqINJ(c&f z5xWT>awXZ%(F5$IC-QTy?dKNzZ6LL8fCV76dlXo8de*LAx!jYP_<hLGv-bi$u%Bt6 z8z3k7tWC+je);vrk*Cv}gC7I)PX3biqMH)O_5i;9EN>clA?U-)Nmg-|T5r9RTm4au z1}_s|{1t(q(@_f>NBI@XMTfoqOe;R)r2W@<cmkP`JlC?ZlY1ho4agbr$jWne%I)*9 zRJE{SYoDo}eHQnoJQuBA-rn`zLZ9C<Xv|yZ!3rS9w?^R6<F~+j%NQ63LtrG~Kcn3& zdSWN`GvN2tevR5rx?a6?)Yq3i^52RNMriVxU49VcfZT+?-Q=pT_G)Q;EgJK-Vlbdw zFGe~(v(2ZDeCC&rJbw~QfpIY5vmfGGbVVk*$gHl|qN|io-24(Rel7bNAhwmD8kB-^ z)kY7Ux7CAQ&=0ym6tsZ|XaKDVeVgMFKGwh%SOKdE`P=5vUpD3};+!>N%pc@{0eIVh zp1%#dw_*1-?B3?H`-2+v$mI`+FZzGb1X@8oAP1#CsN!05MJBq)tghIitMs-7{4bJ2 zugk;c6GA5k;NxxUK=N1vC%_UQZ>6(B*wL@E=)+mWIjac}^DJVVMa;9v;jB8<#^(SS z2XpWf>^<|(8pD3dn73B|d=;#*=E2)wKgi1US>$`x3Rne;fV|I=xbt8J%q9|u`y*HJ zXZ=K2_vojfocQEaP!F&#pf?3IAOxxs@d`@07G05vE;6etw&*IIHBJr_<isj@y<PH? zUT>m@kC)6ZhI|rCsW)f)cINc<VK55l)!T<aKNtW}(3jA+HK3#YRmq<D;)6H^V_+JL z0OBjXeT}#$0Ck<6!@3SORLXugxu>u8YAL?XCf?aw#=N6Wxh_UpelIfWKbt(QoSe_5 zS7+0kv#CMp>@KcFS7f4#>}=5$TXdDq&gD7}Nc<pc84z39mx6pysM=2F9VM*QpcaHc z6{rA}0GoG|C-iNOGx(SXD_{=967qM9pg&>EJBz?LZ`IK&+=O?6wVxH6cdUXXundsD zV-eu<9dlp`OsDZjKH|^%X=UA`pF-*=ECaOw`@#^Y0{AVgOvEcJ=2~<`Cc4P1uGpfh z^o~(-7$c_vm)ARyy|V`1I(qnc$^2%KkAn&I=4{_t#~KBFAOgBTD`*4tpednmYv?D| zJlK2%eDN^=M!+N(0>cS^?~D<b81GyL)b`Fru(Sucr?2*EDZbt{ZOpryzzL8G%2n!O zy^EaQO)o^Q^sWZ%nm|85{;n<%1#N(yDZQ(XYta>%=pwVaO|0lDy>o+Do5WafacsO{ zbP9m@$N~B2Y=M(%g)Tbp9tF(u-7zo?X22wv0%Kqzp>J~)om^1<3i$YV7jfP-4_3e& zAih!&`4$nQs1THbd{CfL_PfbFeYICh>ubxH_Y52JUi`hM0<@~si$y-~p>~lg6^$dC z0P_HO(F~Xc=oL|mQqd^aqAN1dMP_xy7G0&HGOo*sv+d=9>^(7f^+0@7gE~+FLTcr7 z-m}2E4mQCWI006`Dp&-|34NRE7CihU)ro%5Uij!1ZR3NPyr&2d;ypQuIPZn`-k>r6 zr5ubH^M|vnT>s%P7zYKQ-<WgYy^q}A+XRrkw+7ULN)Q5N03Yuy2BjuW?~QUTz69f* zKlGJeb$O=x$RVk&R`QfwPqD6ZsP!Ct?C6{LtwYx3`gKkfd#;tv!M|MZW*66wqTdUc z%Q<sk5YWqW`ar*GC9bV}$j2v-bMTQGPkhNdtuOJ7FKa8Y@U3*tJl6|8`$g*8z!tu> z=lXrMs*Ua*_5V=(ErDgQn(!0M<)hg=FE06OykL!s7o@MjYES_xK_Mve*(=}EQ%RCv z@kLCjBiIJWMf?Y;XNNzLM*#f{PO3Nde*U13&ptQ=hEw#hl{gw#EyQP9KDt5r^F9H& z1~*tsS?O1BMXlMV>TRaidtV;>d{E%z>LIN?x~Xv_w#?hkgPfEy@#E)#8Ork|SO#P^ zB>-PCvtThGryx0<v&fpOUb!a5Im>|B&)LYpU-$97^S5gpd`X<RZ{kWUCCS6a-t_e7 zwdA05j(2^|R!Y8I=taRCh=Ca}3#Py{7zYzz7>t2_FbH}<pL%D1y8NjB)cB*sAik2F z=?M2Axyn8HK318rl9ku(l)tYYJzw6cr}pn_a&oKJpx)rs0{rc!_g?aT?*e+vSYC^i z_R5!My}Sm=Ynwa^?Q0P=D(xmOF5~0>N@M<Lj$aAL%Jm-&!5d>OVhsUmQYx-?*O~O= zde|3_r}*uKN4?hX9QzZ1J`~RY&Q9^9TC?8-Tj(;gcwXdj9(-%R&A#vD>)Sf%*B@1Y zP{Pl-@Xi&U#LY>>JD1!g-nm^M3R*!Mr~>pvDbDxw;(VXqKRSW`Tu_AV2%r}6f3EmX z^(XRCFb0;@8+$*0#>Z!W?kt!~(Z^QeXk4`rpK1B%o_ms-f!Lf^2<icb=jEuivrW<~ zO0Rcb1^h}7a&q-xYxl<yd(lmaV`KNhXa16tQYOBhADN+?pK}{PE2sn1Au~I-7Kkjw zS=(kUSFc<X<6JJ!rS@|RGw=(1eDad>x?3FaWzU%BTjEMACA~hk$kQW#$wBE{@A}-J zlPh2DSGnKh{wm%8Yv2S}0jq%XT)YJ4zyg>8GhhNtsu%XB%a8g`jXzHe;w#BLbzY1! zMqYByokz|xV<ju^-zh(D06kycs;Bnn4LP~h8&q%bBp&{D)3d#l-jI*&sq~5*rB~8B zCB3%2oK-GoZW*lcE7m5!`T?#>%Zxcc#6E@$za?8HP9+=eI+MOCiv9UjDSnIKQLp$t zzX?$9`L&=PRD&9|W<LT(vF}Rc^#Stu0DNmd#u|M2`cmfynE3}*0W~U}5AS?<HZDEX zc<(27iTC~jPzZ8C9=hv*o+v3_^^~9FcMxAwAcl_$KrQ0`{lPT;L|zF(pjW-I_w(z0 zeD?2e08J_S*h(CYs}|xjEg#+YkE1Uj*Z0qXlVAc&sx|vmy;uglRrqUwUW*^4wDzK# z8V4Kczn#apT039q`0?{Yu5zy5kBQ9Y{B3|Qnc4ZAr}L4WPfq8Lft7^c^T)X+hx4iZ z{J9MLSs$NsDd%<9IQX(>L48YHVky}?xIRDT>5;$Wpme@>eg3?Y$N3?ytH2N#1_NLa z^nrfBeRO^lG=T`nbl;sWKk7d<ew&MLJhHQEWk%#B_uL1_S!S$c<;6SYA1FbuMzz=n z0eWixfifqzdZl~Uv%Rb)SMsqvt!Hfl#FXAC>9u`^H7J*S*TIG{2XX-Q?Z?mlP0$3W zv+M*bem)4VjC1tCGJx!Z)bPO)kPGtgagr4urRbGzC;We~3cmRA`^$gr<QeNDhorj7 z$y0JY#kww_)(h~lqi^CD9~XpNzb+_X&$ZG8MecexySRQ8`qhBBTrdQf?*&bu2Gpun z;@Zl6^OZa<z(;C4@g?)LzQi}atgXbtx6%ci@e4+M_G8pHhb??-&vjW)wb9+9{(kW{ z4ko~q&(8|JR=v37ukkJ{a`7%KFy_KSkPGtAT?ZQpd*!R1N-psG6<@@ZIxegL<Rbnr z45slX@=6c_z3Pp<pI`6ev%jzbG^OZcD{(ZgT8PiId~`1yM_)j$7tVo`fPP&#sn+aM z^<o+HR^hLK6Hcxk(%Oq|Y8+zAyzM;3)!O+=$B&-}W+=~>3o((|T(AxBB{REV3#<Wh zx?l{fB>Y}5&NVq)K<yXIW#G^H_}=;3H4eV)Sy0~+msm<R53VnWd3y9(a!|U!yS`xF z$>aPG*HvH$41)nM2>L)j=mJsD1R@~QeRsP2sQ=XXZ7#m?$j+{ndyrh^o-AXP87o<N z@lJVJ33@fE#XbnoQ~R<qC%1Z~d)NCQd4F&eAIw-@i<I`tmuJ0w4cc_i6nSlvT9tN_ z8)`DtYNmnYQ4W}2oOY8}q8S2eU&X!wDD72VhoRVuA7B3sb=mKfv1W(Z=Yf25l;F$v z8M8!hDj^SSvCrkZaT{P0oqjL?lv3=hKC<5${cZA>T>F79Z_Q8g4WOeWy0%X#{mI0) z-vRB%hMq}Z&5)~|og;cGvE%X)<g1>HB`^o(!NN=M7c=Pl_&f68-Von$^76>e^X5NA zPSh^nSM}><t-xOcCp@|5Ac?>3F<CP4HJ_w-_%;*C@zUzi3;E7|QeKkp444HX_sE`A z<@@T*#7~VU_nkjZlDvc<#7iePGB;m5wF^voe3|K}X33uZ>vv!?@`p0$`}jNJ&<pV$ zC)xMI(>#{gN8(ZwsO7pIG`s}ADTBU`zax)j{NX!Jsd=m-55=YK?`xLA^YRRoor1i4 z7ki&v^D}GsEl$|Q`J3>IcJc#xjvqi2$W6%g+RF2H=WCn*x@qI2@a=t4z`a=rN)rB) z_`ZBI@r~px`IUhXz^4fUj}CAa4s?MTz}Y@91*QS_<pE}KU<eF@elVz3?0?gCsrd~g z=XVJ;T@nS<bjci`rc0>t5^B1H8ZV)yOGW^8mr$e9Z`>|5KYH%ZuacT7djU07#sD={ zQe!1GRZ?RmHC2uR>?)~I={Ihdnjby)=XWVJUD^kz>C$;XO_x&RrPOpOHC{?hmyQAK zE~Q4L-?&|Be)Qa*-(}QvSwEnr%N77NT^0k>bQv{XMopKE1MDuNMy21lU21;x+@Ig& zTwhM^ALIV{L?!!m_Jyp>`Eq)4`2?8MYIy5O-8J-}h91-``S`_Lmtu?E6`=(G3iwx) zfpSoh;Me4!kL-`PUEC|k;p4Lj`Nx~wwUq}Ge6_m*UC~jhDZpPLyb=&%Uj%|G_4wrR zaq{?h#qRu?T<r7F%>($o;v{Rr%-B585t+mkUCBX7^1EUlSv9ByAyB1KWXoU$9xRD* z#TM8;b-A6}DE-FdWAsw#N@87E2O2<=a+7&iPWbrjubc!+fSj(J2Mb^ZP{Wl|VA`j@ z$u+qifpsL;$M^A$5L@YwtC%r8_~SZIuiRwb9}{2c6N{XOW&VoVoH5N&V?G&VPfedV z0oK7PSW|7}#Qo$+_gC8LeffNn96s3!AG=TWCiFiA|5I%s0=g3XPgbIjthvm^{S-NT znp%}UO|RwJ%6)aH-KUU=j?yP<@K+132@wC2b--t5`Q-6w^7wR@T6y|u_@4}6UyYo8 zep>vNgNlTm%>x}PYjV1hgOcR;sgub2!5|=~Pxq;meICdM__Q%fS<6mcZs)c{zp<~U zmr9=@)@O#m2pCmvGVe31K0f=;tQqqsxqzHLbCMPDXEp#ee1>^`W<8<*Cnd<q^-qZV zCm|o-$NLjvD>e1;zfbB1Ltt3B$-Jhu1pjD`F-P-^Y1!h(|0(wM?5XK!5eR|;P?*qf zA#O`KAfJ{{f`618j*juyNwI64PVigdw~m7eFqz;VjiQe%(&plZ$>Az$RSMH<xwdj& z9cmXwCOS$-2k<utZxj&!=n(MPS^hXO@(53=m8YMEf3z3-e&qBsEPf-PD`98zK*!36 zDY}w_lFhFi`7DS5athC=lzkPb2KclwT3OppU2f-=%M7q@p_fW+G5$L5JXi!v%1!3A z7bN(yZ!ZKPKu+!DpaK+w62Ls$gFgKxuF18Xxb3|@zK_>VY^7^vjJbv$Tr&?Al$*?p z5MSw7r7_2<jOi>j=DHK?hmGlovDSflPy=dJ8yRssB7l54eEA$Bhhxk5!LD;Xq2CF= za|Nt|wFLjz6#B@n8+UQL$l=eL67oOGb=OwDkl?Fb7rLUObZicPG5+fD5?E(H4}5l( zPaa+5(Y2;lo_-qsv1#mQk<-sE@jC$~6LvNabgYb+qANKlNq$`sunD#SIdyHQlzkuQ z2l%ux##qNsU2f+VVg}fE&`YHrV)dNluN~)rT;(S7qBRM=?4z}y7m!ml0=hs0XadYL zTJO^z<(gch#Enk-_&(loVk=#{Va&Dk;M$YSS(&VU-gU%Rx(@y8(7(PEg!rq{Q(zes z0(ian?xn8lwg5hrGTH?_JFzeN{k89{rnXi<uddgou<n(AeFOIR`STh+2Bp{6Gvm*$ zu|`2Jh=8s{fX@yf9|FUGv!QhT271is&#~+Cox?we|L5C)+4ZS1>-CEO*<Zw5+&*&n zTz^90b0zLt<bScA;HzC9x}u|W{VM*}h{0L<9PzI|0ep7C?<0>s^7xz@v1a05zl8k? za{AjRe&@kL!qDb{j+NnCbR`ER$**sSSoxsP<@C8cl_DDh;{cyF#vE(x)a7<=P0RrM z&(ce!eq!|(fnrdi++<#V#K&jf-vveiIrR^LVbBNq0rTwd_36)YO|JdK?O*coeZ2op zY^A@*V}A7DFN#1=xyii0AimN7`UB{H0Uuu&;D6yY$;$O$KNto%0R0=`eSQVqT7Ybz z5`;i0C<8%&kAVU}Y^8x#uKQE`p|A9+%QMwS4oP*@k*DN(ign#ctvBLhN8iM66|yGR zuN%wRbFFkE{^fc%ySRQU`fY%@+&Bd|8#nfY2<TF+#I=?8`S?x9@R1r%e91hmFY%2p zYb&wvt#soI*POw){T%hJVhi8ebN%^{YNNYH{Xy{;1M^_f=Vu#VC%w4jukmiGbn$MY zuQyeI5>N_qL0-Z>&iC|Ga--j`_#&p%aZ^1Y7x8~n2&DQGc>`zyqw0;lpWo}_v%jei z^rz@!D{(ZgT8PiId~|P$p)VlUn^swiSn1bI3u?_iRc|eW-bwhFeLly@)k8Y_o6t>- zBe7-Pb{;XccD~Z_<L9B3Sq|VY2xMl30ADh*n+gD~ZX%}}=fHNt?~O68=K;0fxSD~# z;^TYgZ`U~ZvS&ekOI%_p**v(uam~}C*OG(Mjo$T*C!9RaZ{oTYOo3@I0Vcs17ze{( z1oVR;km<fVU4GPmYWzVL-*{waH^4neu5wR)o>gY7WaU*m<)5!cFQQuPLjXOs|9q{J zTfLgS>kW|iz$`wP@nBBEey@Ca)(`e`2J_uB#lE&tqtb5jFN|Y{{$CFBzaXRLFKn?d zW+k^T(628{17E+sxM0i|m%uVu)hO)CKn1qg4f*;p1b?U!gaG|h`eMGb8KHKGJ46nD zHLp_k5qE9nr3t>;4WTPKN?#1(uNYoAApRFifX~kI$>Xm=ph~Sg{WSb97GPh5yby@r zT#%Qrvw5InWyBO+$w5i-8=_BtRR<aXIsH|wN|CLB6Y%h9V<7sgoKu&7VVt>4&~NPj zl3pqe6Kl8$w1J3nlX=6_K0f>58L$f0z!F#nF+dH&%yW3or+?Czzvl9<iTl?D3BI5A z*Th!(n_6T3h93M)6KGX#GVgDQuQY=G2>O3Z?ti<;|4M6<wVrhWtbiIoPB#lLi0&vr zHZlZ;K^KSuVvXQq1ig_a_0E0@h%djt-q%o`sXlT@s%y;4^%U#6nObkg$Bw><Uwqs= z>H2kZAA7EqZXR&gyV=F{r_i4Un_vsX0KL4K8QwgrT8V2b=Nu_X9yjA7HJ<pAd0JoM z8(-E|V&PlqX3pO&T&Vru=CCg|=1cI!{uZvkG^pCx?or?R%f)9NC`kCZC4}!PFE07V z;|;iYx6s#H`au_nf?81Lvsb>Sr;;SU_!=$n>KMl_wcG;l7V6pI5BV(<fPUVxrry~5 z`7s}#{VnrgAw_@9#nHHGAwDI3DqnbCqCcYoa{W><Xa)4^OZjTeK2@(IgI*Q<YEa|k z>LIPY=%&Vz*n>dkPfkiUr!@Tdd0>X}e7U6!$ZVPbzGP;%G=OSAPI8`PMoPC3;}&wb zh1zc^RxW!#KbYWayj|nqOX9?ROI&;^**qjhiKj=eB?qNjyz5&^om}~Pzu9|roBLq{ zY=RSD9jt&=umF}pru%LZ*%a6Uuf&h~PmRBXU*ap-nJzL@a+Q1XORO?uB`Y7=DgV+i zdNZoUeh{Fi_Fo!xa;rD8cfAqG8#8&<jMgOV_sW-Ny}Sm=YnwdF>}wk}D(xn}wZfQN zLwvn%6s#HZwI<d&W4<!So_^h0#opJ4FK-z0W&B(H7;6xeqB{gU`>zcc^VJe(FMht7 ziw|_f&sT~8vM+D3=9@Sr`JKkL3E)TVt$t2i-HZi|8Cyn9KH^^~BYy(@r8N3`<xk>g z%K7=qN%rJAHm}jyi$70CWJ+Tp_*I}9)F?NZH`bcqe`V3d_!>OvgOcS_#}0lD`uWU) znBy_zLtu^G%!6%E0+>bW9MtbunT^P;-GXxAW#acCqYqyt7xAy8^Zgn=B)*MTt5U9u z0l6f}D|~XPBM+aFFEPG?t^fReWiN94ex)wOzK!b$=mJq+Tp#Z%Lka#@tI4AVkjGc? zrR3**6<eh*FLSn6+&v;^_RA;0I#>m3s>S|v>&@Xa2Ij${FHR=@6ne;HMsg2}&6k&e z=R-Ywc^cmADd>qmPgndZ-C6@5nVd=cd>O#k5WUO=C91`92Huw&kiA^_IQE4Jd-Z%P zx!g+ZTj|TK3(8IA-MW_Ge>sSs`kndhnO}w<YPWS3`TQ5dr|vJ80(6wDf1gbGx3-aM z6!Zdmq;wm;Z>uxrTT_5@_IK!f3*Ct&_VnR4YMAiV`wa}gk>lwvvzCJpy5qpJ|GQCR zzFFz)#m_g%djcKtGf@GMeIu8ZJe89C&SOg+;z#YRexYh(Puy>;;~SRvSIWqrMgK$^ z{k`(%@Dua=<g+K&Z>(r^_Ttae5t-6A>fqOd2GFG3WZpM=6a0xa7vt~XNgtGiKS3Qk z_=T>Y-y-I>mXVKxEqtu7=CM`+W|2Av_4`d`BXVoEs$6)P_`}FzKytyqlFs+<@FDSS zyjGQRT>;1?NzNHmnvgnz_?3K#F@dfB{Ow7O--)&q`#!Gw!2lT4sL8yE@dW>y4dl@T z$m5&%Qu6b@*{@t<zP=7Nm}?HmWxowhf=xg_luo-Iv->)8|2p&j`kF>zpNSuHGMSOw z!(#LG6TtJK9=<*gZ_&;2CH2Igrz<g)Zfk-cb7#^%Uq<mYPA`i<rE2k<f%o+;WG`1f zgMDejUOnGNF1JzBZS>`~Rplo0Zre)mzg~`?$j<!s%&)>vljo<*=f46zb$>ks&{4Af zeKO_W)<>?K)7yr?xN=#=XEkUA6F`aljr3LdA@-uDBzCG3QYQb5YZGWQ=I^JB`EG$R z-x+2<V9XsS*rPv5Pww#b@AiCSZb$F$7d`zs_6^SNJ2U)smRe^g_EW^Xqt4miQNxPt z_Ci+bRr*e`)Bk(?{ylP~@06zJ-w|~7e~*8guf)f8Y7>2YN&KmGbW-A~->C`Y%iyHb zSH9-=oo(mO+V`pye_sAc@+O}=h)#(YpBQ&w>+hS*`&8xly`wM1ewgbKFbc+eaecfy zW)l3VE^>(i@|ePxlAkw)t&-$^M;Set1KZfF0{W<Qs`9Bd?3j&`|Gdb|<b26F(erV8 zA^V_eb3Q^~3m*l5e3UZs=h5FxqrX@F0)9BtHf}NdB|yGPw~IedM`TL3H^FZOZ6KoD zWZvxq3H}{kZQmJjeNc(;@1XCg{BOhi_DTHF59!tIxgZZ<czcdoqjS3TnE$uezy_ed z-#!7>eeqtQd@_nZe8_W0o+WZ7<m}1J<sMd=g#T^&_p;^8?AxJ)ecUhgOj6Gz^-WTr zlArf&dad;BYW(!?%x};9di+qkt+PtK!>a+*{p~t{j*|87lPQ04n7qfpIG{&L-|gqQ zIB3j2tQqtD68>4AN%rV{FNZyTzB^>hT_;uBm^;fsg{Pm(+6KsPW|`HqpIOAd%h`*c z?~&(S=!l=YA^_Q)m8`zJ{eJ&p+vQ>Xc=lGGe3b4a?p;OrCLi&yl##!IeqkE@z4AB7 zearL1JnkgdyYe(T*Z8~B(-E1{orCa)z%Uq5ZZhxAsRaLf1un)6Jn4gy<x@v0|E?O> zPwCzFbCEB5^T=Z#!dDk7y-b}$+%K~cxwXqzE_Rvt^T_DKjO2oUC7tg-;6u)XjW?=N zt|Ne4lH~n9xzthT^8Fq$?!wl8{%oD6D#!0#V=4C2T+e`6Fz1Ww<K4BK;D2wJTt)zS zd=Fnre%|-6Rl2i?nFc`xs05{;3={+Up>*2ynBASs{Z8h6XMsjxzeoP`ma~!B$-OPU z?kohJZ}mLA4Udam_3)><l8e%JN8lrqvud9^i|*{ny)0){>ATD5O(1)@@^$Q+687qM znp~!dJx#x+^Oc*-n=bM3+mMZuTS|V@d*%1yhuW>5R-gX}eCnQ#0(6wDf1gbG-<{^! z%=!Ip4A7%Em9Z-a^vp0LGYE!&`0NJ_fEcC%)B`2SMfhU329$`MmalPYkk^7LPz}Uy z2q<OJOO;F9ZSeb=ul7Ofe0>hDpPSe3OZWMNJg;8qb0ilZc_0ENf%ueXQ3)soMW7hu zg94zmn_a5D=Qk&6%s%{Q<2NUSvqA6wztPHmK%KK{9=+`QKo`K)e(oZ<Dy8Zvf0)fU zaaM>^s7%(;419UMP=C(4%TMymnRm81^g;3!UuMS3cZ&TqQ1aUoPhyIl=m$hEgMJ{0 z9K8Vg0b&I5K>?t@fjsQC!AY<Iw!jit1`A*j;NOtv4*$YK$NDZ~72iQ1z9kmEC6@S> zSk|}165kR_d`m2k0_Esc0O|}(fiW-+B47m6fhJH1YSoIp+KJvE$fQTStSWjo3dr5| zn;1%gUF6vzY>1nU|Lj(^^8EN@DhX^5uK*N-66GfIvZz-ns{t7`WRsIU2c95{SZVp_ zX3_tBh3-7X{Y=201anTFHO)G!Qug@I5*>I}M|9Cq%Ie}en(&*|%QZGi-=_!PuLsok zgAnU7SOE=SQMK3)fDs^i)c<{AexF$19|eAYgIo`T-Sott>f%?)#_)Vf45du`9}xQo z=*?DuArJ(`@W^epP_4OM0&DO@kAD1M6KsJKVBM#;%=PLi=!rj1SNtl;UVTaorA+); zV$Y)YKL)@Gh=4A5<n}*W)tY?~C<USy1C<~I%0RhKFUWNX*iBFTsV;t%Yz)t*#8BER z|A*xCL+pRJWX#>gtg~Pagut|VW#0yRf#~J24uT=j2l{<_5w4?PH$CyEy7*PHF+86V zLus%4Ir=&`V$40%bPxWNGV$-GRx8_dHmaYAKUax9b<T-?fogNTSAI1%^uqedP4N?g zUj@)nx|{jTmAjZyo6^1T?_DtFzIs3{N}2fgoIoF&`|u$)N}2fgcA-D%>HG58GoM-9 zJLdVJS4!3o{k*pqprdrp2G?!q6Vsn(41VmSF+Umt)S{G;Ux+?7KcZH#QHo{aPoTf* z>HG4D?Um0gVoRPMdZ=Xm(9hTuKu0MS<a!K!V*2xZ0R97IAjaDQa#qU3zrP0EAfQ&U zQOd|)K`-Ca_vLf{Uir-8fgH~dy;2fC_tVe&*8n<7_t$Z~gg!C-c|HjL!B((k%tO?o zl!-szkFMCnoQ>*d;y;*&UX`cs%V*DgX7ON!=Z6}VtRMRMU;#i!X?~FF96(H|P3d9y z50CQJt_1We7hVSbLo=QXA7Z1FiT`j2{azsYzI^t~XBH1fJU{eM$@-z64_5<plpdPn zy28cu=b5#^`>iHp&LH<QLMBex<?zwZ#z%G&2myR5WtVa-I`FKH=%S;PwaNP?YE-}3 zxyZ!^g>3qswGB?HHha#b<dTEkKJ=8bm`_@M1N=pF7r;7ptU0XNv#fb)jn1j+jiEaQ zIR9BOpM5XaKAB1+PWB3rm>bGX=4GEu@B>5mAs5M2da`dE5KnTJnk8qcK`CdL>k*&c zDAzM8W#0un9eGc$lv4^n<i(-SIaN+q<u(tA<;C5VPYzk>^r!h*gM0$?Auy+2l6isU z1V5_)KZV2<U*woo1Zq#CoSxdBZ^VDl=U3uzo%ZJt@=;mbB9~o0{UgVHt?YZLDaslG z^wR#UPAo$`2H$a_pJoHy2<QS$pbb=jdQc3?0cwFDe{6%3KuPUIKLmEsw>s76X}lWt zzJA)D>HBfM22Ow_unZQ!BA5g7U<%BFQ7{Pxzz|T%WkWx#?Ha4tiZ8JhUt%l1#8!NX zt@!E(;;R?*fe@$y#h?VF_HP5;COyY~AO7~`fC#h1f6fZ`RX=MbIw#qevTlKGpp<G~ z;p{~}AbJ_}?Tn)6G=Wx74;nx%r~@HD-gb7xPyHOh`p?_xKLF2u)*!xnf%t9%;#*>g zZ;2(oC6@S>SVf>56o5kfdKBp6x*t$yU<;f8>tF_~f-%4h0s~-Ft=Oxb=rOlUdRb-M z3)t@?=DrHA-w8KnH+l91HpH;c#f5~S%*`)TiQN14XX`=MA>}6X{6BYR#gLJI4yyJX zcqZ~0Kw3V!a!%|y^7S!07e2Ge4mx>u0c(-xj3rwjI`FKH=%S;PwM@K~gkO2x5}P<l zg4o+LyvZ5?L*%^fY$SI%)AqiAXR1LBpy&2`PbIA7AP9<q<SzN;179At5xMY6K^X{w zm(o|c>Z5MS%QvI{)VO_ENj<$@9iAI~ZtUQ%pg^6rZfxST#x4ziVU)+pm@z-44?iW& zPiDX>Jam7IuZ1PR3>Id=9GC=CU>r=uy&LuO;~MO0K^3S56(9ug|Km~+1oZ94^!CSv zAQ$8TT>Y5dENp|5U=wVCb+7?a^B9Nck1smd*w}Tf)u0AQY{{h*NG=k)1W0VjB@ak0 z#Fktnw&Y@ClZ(=iN8qm{`lI}x(379cg9X>OIDdfaK`;rX0QNr_RVn*j<UhslPw~6h z1h88y1V!+OvzVXo^GJ>{k5I!C%e-XN8S}Fm_QYEPkJFDw&|R8H=s!vgkFKJNKhb|8 z7j$9Q3l^RI&$xaZx!8-JrENfL@v~F_kUhG_ns94U{YoC<N9{%bG5je#M%>4!afw{S zzfwm25c;!e^!Lgi#?Of7XM_DHn9}I%#h<4mGNs2#;Fp3jP_Eo$-eWZh{*qVQ&uU#C zRATutcqx48%@RsaRDlNMy<m|UOo26T9@76J;G2W`eS8cZ_&*zVcDwRh(WeiO(^K)U zr1Q1$@nz$MRLZqC|0FrRQIa|y+s0=hAjVS2<@>Va_+6?>wqL5}n*J;`0sJfZc}soD zC5JM=ydJLrl|H_Y_jsL;zlI()*!zOmN{_Fn=RX?bUYK|Hl$`NLm%uVu0L)M6wChda zf6mQXa#ebC68?08|LBa<i_68%(-E1{Bh2fOBI+jhC$_Qg0=@K@z0C5Fa_oj!gP=^U z*f+sPma4BByUL^Z*htvN?S|oxfKf1}++^M(Gd@0fK1yDiuSy=-BmYr)`Dn4{Cr`Z) z_auBSAI$;2ev5y<Of4R%gkKG6K$CKL=1zfGV}8DF%rEfs^Hwkfi1qUdWDCYTiF|nu z%qQ%gq))<EJ(c{t0A3LYI(y|WFJixh4Ly0X9F%}kfZmhT_ayP2ECkf^BzY`vvtqow z0k*&iuntzi8dwG^>Ye=*n8rqYN(}KSF~q0Dz^9FYiNvrziD7+84Dl&3@M&X^tBtY1 zx(K}bmuJ||`r<Zl-AeC90Dh#0zlgZnrI$~^mmZ0Y^)b#m1^Pfgh=Sgi;qSHbGeLgj zyIXx)!BeBuJO)<58o>4`diE6gK7}tOy|!}ZrX>9mAF1)gm-Ny465sf;wi0Vxt=X@G zjTHM5V^-i>`%U)rTxqZRcE05Ci+oV1UW|FV6qLb>0pe@Cr@LIdr`wQ6Km%w3l_2D^ zSH7pGlDOX`=lACbq>iVDz$U=|)6}!WpU8&+{d{^+y|MT6r+j?&PfvrH6n$(Zj>c6B z@tKy7?$cY;48&$7AJoFz1}D|p*(T`~q}N+1gI^9RoLoKF+Wm3F9^KS95?kgi^N^gB zGVznnLkxd)KxR_|q>d1%2IYX9p4wzBRj*tV<0+{X*3<bJ_<24)dC7U*Espq-IO<#C zN-QP4e!9TZqt}vy(o^2`(}hkR=a1lL6s&<0U<Is#C9n+U!2*~8F_7uLJ6(R%e`@?W z7hm(XGo9t0XaEsrOU^Q5B`fdUDPQSBZ(Oz5M*(_jzcS$DR<D2WdQY{IXB!v<LjeCz z;a_Pt`7=evJW~u}U>jij3^_kj0=m?TF{{K`rS4yrgBfF9m}1T2<38|0Ei!c1auWK_ zRT%SJB|7*M{TIpcMSA?g3Tvsee}U^Y<YF&=*6NLUp4j5&dFpr`*>fS*rp$gN59`OX zxBB=~dXBiy7vZzg`QMelfqr2c{k`%x$$iW7Q^S56zvQU&9R8m3bVR1~9CLhb2n>S} z<tFo<n@aH4yxLxvc70HZ<p<%V@Sm@B{d{qPIm{tn@#aBpFNDaqmsR@T$KE%GxZjgb z{=%lS+m%0$ANue@q4Tf$I$wz|z9ioB<0@tE%|A&_Z<K5u^)BBvVu-E({Ow7O-{&V% z>}TQ8pXXx$|4M$|^Q+3mb{H_PwNWtU<NJ7PGYP)*TF$+_FNm%5LUnrnb3x8PF{lI~ zPzK6D2`E)-_NQAf2cJc5){?8zbGh*I6a422oL*cmcAk#NlvaCrR`l^qAopJ~Ke=~h z#&Yk=*;^ek=GhI_elV<7>|^kerRuB3uJUE<YZCTxyG?v=fo*V7xyig|3ljWi$@5wA z(tK62XFk1rcEIx!Q7`ZsKoe*MzJ6Q(KABpqj*;smm;y27@++7qSmW0al>j@Xe=IfT zAL;W}k&`L^Uq+1imo;PlQ}mH33GY|f{Aa$CDPMU1R>7}OW}Qs=zYZGn>te^>+-8s7 zuhCQbb(y;sJCQ4?oz+K2X=9XMbB!7E@A&xlUiK4UTBYo%U9MHG61B7X=qPREqt875 zeHLu9r`C-Um9h`IYn7`+?W{gJO26u-KSRd+2l@R6`Tc4XjDul7PnCYftkdbm<^9M- zC)JMr{i+<)fhJH5YSoJUE0vewL;Tl+bp99NFS%YxjlWs}Cw%c&-L>>m<VwHt?5sXI zN*mO%QIEe~H-n8Pt|KaC-|DVat`fDg`sgTa;Co}uoh3N~8|z?8rR+D{wVXAPE2*8; zN5@ZF<Zh|ZTk}%ZeD7LU`e!M}TW7pg<+`e$Tu-j+UiqnZYOm{Va@Etd+RI0;cU#+1 z>eIez+zC&v{8L;5rJmiaw~qdnUe~A8_uF<IB|pKsgZvKI(q8jy;`g`M29`W~nXh0i z<@$uv$r?=IZ+h3U6#hcW^|E)pp2Amqi77Zmy+CoYANk$3CC^VrxyEOeTCz4Avdj6M ztAO)pvBnB=syqy_3dmO=zt6TH-+kbWS`YX;1H7TlAvcGz1pN+gEHcJ|IF@qxQ;_cv zK-W?V-|!4f%U@5=&**0t{Xo?D3#_?Ses3)#-*pj^?*`a)&8;dA%u^RNo!R7&w_uFm zEq$IIa-r;A$9wCFF@m?vIh-|OjNt8D3*JGm1@9bpc=rio1n(_y_%G-RN-7;n*Z8$H zIM7NEA#{b}-yaJ(*(GiK+lrtv;&5pf|8^g^Eb4GM`3XLOUyEs0(2U$-ofSl;9F7I~ zw_(6_#1qKBYa$rParnXj{|{g=Qtj}!i|+qvIlkuppIzVDGLGi?|G}{TZh?dRJyD@R zkUyY6kUyY6kUyY6kUyY6kUyY6kUyY6kUxYb-6CgHeEop@1+y`SALj8LZE$zJ!#zWM z?-<;NT<{}u5zJ#Nc&Nc)Vc7XSBjnb7oBSRb-cPX=ERH(J?_CA<^Xm;hXV`X-&j|$b ze$`@xRj}y%8PoW&#*XG=;U3c+zBb(56K-sehP#`io!ym<jaPRZZ*1x9J$SIOv7@v5 zSaT#HZ0YRii3Tw^c<?F_MGqdV>%1o1@&3|aPqg*m!E3`U;$x?RCvT2KI$La*ohly* z+W$;r*F`<1@zYlviB>dTd9*Rw9S$Ep(sLwQ-qqaRefaVtJy(1P<BMJVi){EqhmJ(| zmo**<M~J__CwlnEMUAk^BjKJNY!4l2wwyy1jYk@<ZH^odAF90^i@1O4Yz;RaZSD!X zz!$qZ4!2|2e(2D}%{@KsS9cux(<?7;7lq3&I@;OU6TLXv)*Wtc4gcApD=$A%*65S$ zzc}3667Gt&cXl+khNI2xk^N;Yk<Jd<e5@;S_zJZ5e>mLT-PzsP-f>kYfBdO!9FoTU zWwhv;Mk_r8UD6#UPUm%pu64QLDSCaE%l6{l*7mF0qlc{I=;4+tTw?n#j>=HlKO64W z@E1qBo7<y3jp5#CxTA->4paaBmbT_@8Z45-EySW+mhztKn!65NdF0|o(`jqq1h^{9 zb>Ze~8e2M#cSKz>744lpwr?K_ceJ`RqWeEgZ)nW1qsOm`pPa)jY2sbXDeO8PWf(2C zuU=cdj(w=*S}!;0+TmL1O}QS^#_r~htHXz{_;CEV?!RQmaXnny!tjME+IvWwvwO(M znP`l*HFv-`*45nId^8f?Uug$=@Zi<m;j25l+nYNM9&BxnhD(DUKm2FMn<MSf>wPx6 znPhV1sylcve5?z9a^^C4`ba#wnq1W!;ZBWmn@IPQyLCxVmm5sD)gH3OE_;}EJBSB3 zZ%3P38|{tRD6QJR|LSm*c}K!L5#(e?KWxvN98~WFrktDdmd>v057o9X#y>UOVVx~{ zI!^cf%RT-vZkC>KceF9%EqvrqBUxW$@5dvj@1|(HGTgQQL&Wc)JrVAMaI3o|y{ExN zz0vk#;g)OdE!@@F)85-CjElH~j)e~;seV|_mX(&vP6qYi_;InULsuMOG8J)VV@q>{ zJFL0e2|i>Uv>xY)&8^JLF5-N5gs+yTNqYz9RKgu=?!B(nK1tn4Iq=a>?7zg`1l;f) z925H_v=5^LAL@|@Q<%qtKDN3#Bke8MACA^U%MR5<FD9-p$Nl@|%v=`^U(?!ry&M{S zLPkx`^*m&{yE%)kVZ(DE+Sw|n#%ofd^8Fu@zBFnL?#Y*ETZ)+QWsL_8Sd;E>PiN$~ zeYSd!E)jm{lJvsH=GNw}Xt?#_a(i1Gs<98>i&K<)4qbGprgwjtC0lPqZiR}gx|>@h z5>LRMFuiN-k<L<F*Y%CZI<E~kHXo?8cV%h%7sZ{ga_|3$>&i85iFnV^^mmH9bfvto z9oX^02Imk5(|f6OuP{8jYmSy#zT7bF(RLnRpAFmOc|DP!<qW*ByuBmZc(|s0|NcXV zE^@Doc3Ql4Ud1pDbHg1w+7q?M^-#;Tz3vz%J$Vis&}VC7xAo9?ReOX-$Kgx&U(|Sc zON!h0OK$Q@dh`_Qtl&^L_IQ<~J5~FoAUE>v!^aMB-sKq|mgm?3|0}frAST^R-u<BG zQeT0*Q*`K1$JO+}-bIba+B=NAfE<%2rM=NEmv<(Ye6+J8%Ioa@{Sj`n#*X91j`ASo z*yx0k-fUcc`W{gicOMO3-QMA5^eVi2+P|NtUnG20^cXMjE()&>DesjkTAI6>Tihe4 zhBq?u@>&(Xw!I}>S$Vue-gCBo<lw=NMtDml;>!JLU(G(u7{gcd_QiYKA}^DNBQ=qZ z1N+M_DX;j@#pM-;Y9jHAOAa0Sus4(D-b37399VZ_?LW}?3H#Q{zS15}^VU(`8`@jw z|7Y*bpW8^UEK&R^>K|T*?JnC)EZjn_h_VXx9-~xcy<)W|-b_qnfLKUK*o*`yvSUJj z`#a~}Z_WG?NRlb3YGOLVZdoFM%x}5Nx#ymHfw!aU`*ow<kYOs`a<j#==!Yfl#6Z4l zXu`kfVr0peczpW^gZh}A_xq=3{r<^W@9gAaFvw1`0j_I?yCko^9W5lBIuhUfIInEL zaCwE;Ez`pu{CaOS{pepTwGzY9?TX)~TOe43*O2IMbj=&ZFUfB;3eMN7F?<^G3GQ(x zbVg!P^uvN{SGuW_`{BGJfrc8OVz7lPoA7H2L>2C?S3~RWNf1fn6d>GQO}7Y};iL;O zdCVp3F+FesB!)Fnw*7IF0f^%_fyZe7FgzA_&apN_JiDd~{@cyR9bD){-0P!*b2{F~ zDFOjKEcfdLVt~aIhXsds1z-F96kd1z_*(KY+?)A0$6w4>x33xPn>;KC{N=9^Ys%02 z{ER=L`51j*E_sI9xZq5sLhc_Kb1&!e^1Mz<1_IC6ztLopZ>KZdz!~zVn>p@azFX(= zjyCwsGC477Bu-&t^7Z!W?M*hM^Gp3F^hVL~?lOYH;XyLIo5N($TwvuSUHb*GPxlN7 z$7H?CN8_<15Ze*+X2b=%(Jh0cZia;P<7hjf$qN2yc$P2o*>=4gcIdlY<cGIOC)Zqf zn@+c}eOUTqcP~4^%fsC>d>k(MWK6R(H%UY=-@KBL=i83C`4R~2Y!<U$&HuHZ=1gMk zUoH3WhqUu}`;izXeWEN2ewY#9Kz<V8<bK89$KEGW$<7$brP_BBRU-Vw^U_}Dv(XqC zxkQtFNrHU_iqFqZ*RvVp_hL%NO#^@ICd+XiGK~cAP`}MIQ}f}5Zt=gE=Z|h~fUNM` zmlwa=t48(4ISDMl%Z*F3+TG!>XoASs@g_k2q&DE^>mKqqexCjY4q`8ttbxCa2zEKl z7@olrZuB><`+4V+tTLaC;Yv2Rg0I~o#Qg~edvrTJ<E`D#O?Gp=>n%qcL~AL-86zwn zp%I5VR3~u}Z1|~3?ORJ$^(z2WxP`V~k#xS}w`16aad!Y;8wL#cZP;iWIb>Ob{0fn= zez1Z%Pcak#c6!mZ;NBUa2>Zdb?h1Q=KYF`>Z}&E}+sF0WFQ;2r9~1nTSm<g2{K^>O zVdrr^U1(<Ie>Vw%$N`=|SZ9QMq8nat;3`!(O>&1`p5F{{p2T?9hLcSr_b50m--!#x zcajjx%{}pXph=$<F_X{(A&4YzNHllTC4L@Dej5GDc1rA{oA-Ll`C>6g;zr|U^6^}M zkG6g`zr{Y_{}?g-C>eL0lny&`cMA1;#%7(EIB2um%HEnIZT6T3ek9i!Cv1<Gk|%>z zz$PPDPDGHK#qfb}EP|aW{$LG;J;(G*BcxzVMCpzI(Ah-o(^XOIr*B5P@!fR$-GW%; z<294Je4Obg3Q)3Gf1GX`eDL+Idt!Z<v#0cK_WSq>M-E%!EcxIEXNkdfkEdTO<z&0w z<cfodtu8vBis@>%eFW~P_WYINP_laELsNnX$|tAv&tD5c*sXU666`^=2!h?^todnD zi{!3j;v|_|M9<ohjS{PXqh~_Y;HOJ@0z6-KGMSpd5WqRZah!^rk=J}8RRn*y>f-wa z{LtM<0t|;w{gmU}0_iT0FSw6sFB|R)U`N1kq7gCPm8hUSTCZQfdR9a%XAxHP%;od; zvH((dH3|j{S{N`p7OZe8YG%;frxk>$*sqGa`E1t_GiQMa8%udhc6k~7fJci3tpT`Z zexQPv*^hFuXx$H%u(NMoE$8Fy`kPk<C;R5r>HeEnC~Mrlf{T(oezqEIZ*h$^a0L)F zMG=52=B+@=M3@x3JK7E3cRmpppyf3Ysr-6@d=A#^eu^KEk26t;6o$ewPrL<TEraGO z8So5%huTE3ic^;I)WweHNU@}&ry%jJFnt?jy7CU^qdhVjaU^^&3mgp@Inhtse`X$Z z#f*}_X53IZ^GRnt;?6@W{$g*A7~-dVJHNdPu%KtJhINi5tj49@j7ME!iu+-2FpD$5 zPyg??|M>fNZ}a>rzuqB7Lke~+<)^=(hRFr1Y-wAdyMi?ia34+XN5nt`gyR?cD}OMk z8{|Y1Wp7;&%3@|dCP+3P4?E)Le*w0~FaSx5KL##J2&zA{A~-vmK1&{E!jG~8ZD}3E zi<o+gT(E&WZ~x;Rt~2&F-(W>LOcMFras#`#;-keI#Yry^o^996s$~r-+XYZ8z;qw9 z*kNpgb0+z2Jj+j#+g%C-ew%Ru!@SZv!4073Je|<E%8R*F?3mFTNKA#bS2Mhx;oP7e zn_iu0b(h0iYu{3JQtLU6JD~#w)8oH<{3mQhv|2>1{oVR<s`s2ys!x?>pYW->Ezpl$ zP@z2(6XA0Sy0~L}fc4Nc(P~yB{X1)<rXq4(2(mw!7w`A0v6SOGtg!&i_0f}1BzS_< ziWtMwJ%!-`;!DKL<VD1~P+y-H!~g0?>XF}oFCeL^`Blx2;p3PZoAjxaG$W}S2Hwto z+h8#s6+mycV?Y`!AkX=1u?GIRy1kl&X-chsLzD$K6){C>3Tosg7{FJ~GRtmVUu8r3 zhzIeJA3nt`D83yT{Dy0ZY^@6<C3*9{a?+cT6R}#uwR%ue9YwTFS#N~}Mx_&si3xCK zan{ZfB?24-!8P$1t1LjR_ZuX4dMK1+vax^(VL}`_aqD|Tl8^a}i-`KGqS+(>y_S_% zv|7y@jN5b3?NrqkcB0L%AXfvR4a!7_4J6?}1sK<;_J}sU=L2NOh+1o+F08eDOCf2{ z84mL;m@Yh{r1;3qNB)H}cIP<+uy$$-7Uediv35SRQpjlMW0jkR&0M0IGGf*W0~we@ zJ;HrPIk+O`hdSGdln0}TwE$<%(=41L^JFl_Z-27HBM&xN-+T0TQC|HM&fILiEi`U0 zai4>ovzR`zlIpk?3?ouNH{t}iJHM;F;XB;#zE<rlZm8e=IjJY(dx<iy^P2_srSnNq z+=EvvVYMo5Ax$8()VRM3Dq4GopZ^6BOnM{~UJjQ8aI70IZ?mfdTmX3SECiaKkV7~S zdmK31XOip`pE9&7S8g>)9Pnr4?KzScKnQ>pCd}^<_;iBOttCO)gKoS6;fwtid6oRA z*v=4zEWuT&l|RGx;Zq8D8-Ou4^Mq$<!IQLOXCxL~eB1c}(8>1|+QdKhJN?TbytENi zvfyFqTZ2I_K`;0z|1h<bMlohBqi<aXQA(GSU=0z3M2QR+Eso<ckRN65G<g&VM79gA z^5`{?`em`1j=^%$043n1AXx&u1UN3ZT8o>R*zY?)<}j2%-h-T)GywSpgr`|wc&0wk z`!yf-iG1QLA$tCSMVJC4AjBoI{}oK|vjr~g95=c(<1v4akFG>mlwPwQcTs&_zMc(1 zM1`#hNyTbS<g$$K>>+859h#j5-_M|0pMl5~K~N8Gmkr|}plo@(C|$^7+HZL&?o<z# zOY=4YA^yDnC;9CT(p=_XV|_qXS05p$xBK9wwhVucQcMUS1rJy<yKpH!HzL0+#KIXC zcpL1fx$a#o&^Lg!kf0WRf;^AmJ8Yn2VJM+2SlU<SV$~kR0SyoykVShIIk#n0N8tnR z^(Z_}0|@tNYzM;6=ThdoWj-$uxp9SpS5Cq9IC?dEf=6$ciKA(QBG?grmi0_T`nbGV zFZg2MU<LX16KYHYg6x*sXW|K0C1?pQ6l#zO5A`d0sJHjPs>&`<&_(GT-00DkWP4%X zC{eY$8V%ph<A@ZCZ%ATfo<}6Ha-RTxU^tLGo&l37$&_EP3^blHK^_@CW%-ADHDu)c zW^Sm)LD==sv4vFtxSkvYmRvx|`yIH7PJWMS#a~KbGkHMkk80?6XA<`_s#N_p5m?}$ zB!3~XL#L0R9J=MT*6|>K#n_>{-yrEmV-Zr44^qE@Aw+ICK~d}$0M`9<!7v!*jFl`K zj<fX!dtkn#i-`?#nHP;s9k_x32Pa%00UI}&=kMV=gz+OKTkWH%BVPH8FYssUSqIHB zz^Av<@f5{Wn8-ABt(}<U_Xi7fMg>qRuwD=0I;qU0j76rCPDasmhxeUNLI2ge>2^6s zeQ3S<9<5%}Nk_`2EE^G;-0ndaflW1VnUD%W*n>Yu#gXT+^9l4G;W#ot!Il=ch#T}A zTFTeqO#j>_54<hcS`Fmy>#_4`NzAKMo6g9(ZF=5C?jhi7Ln{Fl2#+MUX14nU`MT{_ zlNT-9^j19_GGV2^lF0`O9qYWow?<wW<Rg%n%E*rG86+SyMEAu{AdbC*^TK+IJr!z^ z0ujZjV%10KjM5PIe%#65{^QM$`7gsa|M|=H)jx;%ubp^1Y!Y7POMdgpHQd$rhqg>% zH3`a#b98}X)0XSV6PqqTSt8(mwyP4niBeak`fz@li8_^C?UF24#<qXYXTl}cVhdd7 zb>Ui8-lN_0TBv6SD-WLVkg_n!HaLK?&=v&Hin$UNcR#thANEP<7|PLQilGVmU_1i5 z4JUEK)7jC+AJc483Twy>k>5TROOM-wACzAv#UZ#`?m1xFN7%Wa_sd^g|CsXn+WS`D zKv1?UacH?5f|<x5!v{_sBpr9axwugJ%SWPOUpniK79Ww&prW!~bmJhoK!+Y~Fh8{Q zxBNl+ztLHD9kDLLE}tPm?J9~zM|G?%s4Kk(Ccl@=*07UZW((h^{;C#*ZCXiTb!59< zo4iK}3U5ZM-9HeRF*OVb(b5Ycgi;!T(W9)aWe)dnyKzs@0J{%?_k>~Zg3zPZTUn$? zSCdUF!(k6T1P29I@b#Zh9<)Ev|96(a0V{-2_?E-n3*K!Km<?%qa%~d{Zl4(@9!uh# zhD<CEzex~d+H+iK<lo$%{xA2Ze|LZSll#+uxIg{b{pqjfIn9$C30r~|!kHLG_c^cK zpZ@0lBrAMfusIAtG;-77dy{I)seEI4{Z4#UNY}+1y94B(hat&7Y+1ufR@0`4nz1l^ zLR++V@QH(h1}MF+cv^5H5#TvXVnVS4jhdxCO~2y_mty<n%7i>ap9c<f4P-y;IEC>k z!0iemQ#9tIpW-C{H3zHB)Fi_t@TIDtxgqPLjzPAe>1P^_*=!8Rpo9LJ=@dk7+&VTj zSKeIOqb;3ANYrz8<_qdy0Bqnd`S*5f>Q8O3L(Lw~6V?8gJ58SmONu>KBmdmO7&@GG zz0-16_JGY{Y#Le5Oph202#*&G$PQGwPX-<AyaOGcWp!EenhLUyD}di=jS#pA7->wB zJE48-+^*LXHfW&_#ZuI=-g)OE)^%zMJ;HFoMoF$=V7`uxG8{ar=+<dDwQ)8-_8gx2 z_k9iZuRW)SUS>FnDbOiYqKeUsW<c}~o>o3jc2h~(+=_Bac!UkAYA}IgK&Cb<f-q*K zAn3>Lv>^e-l$y5fgn4LMNF~02A_~jSD{_Qik5=o|<8r+(!0ll6s)l!$^=&uIV!otK z$z+)I5j{bwV1q`h6>6DcJsa8EIp`-jz+C}(px*#{aWe%pHw}!BO<YTiBzRHR#xr5y zTQRT4ItXhT1dqGts8dMoMx{nefHTW11(n_z0CYZ@p|eZgO`@90#mf3jQH5tJcTiu8 zKP#Ac5ctqKDwjm~WgxVGx+cT{@<}R-Ar^PDM(B??Nm71P-~tA+x3q~PWIYVi@ev;h zOcfE&VPPThRZ0pYIyDz%8+0u6afZNnl*CH>t6`+$ufY`p1~>jV=?K_n6J1N?Qel}R zDoE|NXtD^`X%J4M`U|z3YCP?$!Wu8bprgghgFDzDRyQPF`veo}n74i{n|Dz5CAoF| zlSy5lqbS7FnkqNpZL4EbKG>X!ewy)y0GMD<OD&F>v=j*R`e>i2G8T+*6KtHN+iP!p z*46dCmXqWnab5%$dKnw5AEXSLdSls`duS;%_&`P)nr9%WS}Rt}hHBdejc<$DjNWUr z<UJ1gAuT$?M72|#;gf74P>s{LsoLE^^cRU)oUhR9yM&P!f@xGcDK$`r+ZPiFOik-u zi6-O9T5)QQMx_&knVwA0kjN}5KaNNo(uL!HaeS|e`cvh1>Iuudx8C1@p&6EuaNFaC zEs8Sn(55{piVP)BYVwdo+KO1hNtO}z$p)oHux1xE>niOu;v}_Jia$jS6L=c=B|jk$ zmS8)egB<WTS)VZ;b;YzZ4IhD+gd|BGKd6dqA7)#&$1g_((ks_k7LavxrK3*bjPSjU z9HoX$<*JkX9YJ3q2NSr-Uz0cfZN~$IF`tC4@3R#Mt5K<-FMLG=?2BCG@1l2uc3zm~ ziTa1`{sD3p&R{)Dfc7e&3A8TYB^jvp3t%_!tO$LkD~aQXy5e2u0jSY>z{@XCoiy6) z@-m?C^X~e4#q!&`2_rDA5eWkB2fFy^;3`)H>7&>`W5C|aui#vMSng(v(QSdlse4_s z2#p;X6p+|^?6}@=Xz~TnPZCuoev1aC<qjt)5qHBR6Z|dJeLw*p7svI=$&<FWWWtv2 zviZuL6rc_3EeJFc<koxlreNbh8^Sg7Nt)&N!&6mT!8iVt2W)x1s>UxaM=41p7NOAL zK_`(ogK_9EJU6BYmh|0^G1PY$V6z-qsxnZ34oN^h-a`_u5P}Nd!n&Box*cCW>P+T% zXeATLPt|_g@szrxkU=1sB{qsw5mbW@)+MtK!Cqro4mtIJL51>N`6LWVoDAOpC`JeS z2k7#FB02}Z29?r7DyyM=#`bD&yAj3<_qC2*aIyZlB8Df@E?^Nrrl9;H3H75&vKt0J zDOQ$M{X}S2<bgsGb6CMAxhC-Oqiq4%%445qk`)N2#L_JO*((ny*?7-p<4WofGNSP7 zdqDG{xd%e7&4{Dy)OAc(0ygwM_6c4n(-lDu5sbJ^sq;~bkFpyrM*OEfo$~ZXf0M02 zDj&nL1V&`Oj%h9>DFSU<f;RzcpnMihyO~E8fFH4ID%b#27YToeYgemq1MHnTP*xX` zah<7P*JnFo9}KrI^m-2YtlX0mPX)0C*Cn6{Z3wXL9==X+S=_C+yH^%{H%bAfuoq@+ z8VQt=?$`>~=l)3d*>-5tHW7vCoByRcr>J175K35jv*1sed4UccpXq>4qmpvgh&R?Z zhD#7rZQWfc_R)m$0nk|xG|G=651rqWya+qwsM<pHapd$bn;+1^v}a(ffGl3{G&cpd z#=N(_Bzz`D$xa}ig|-GsP?@DnrnAw0u>%o$N1ZE)<BT0rZ!Vn^+wER7X+)_--p!VE zr8#!IhBQ<$7Q~Z9E3xMKDJ7mCVgf5;hW%%RP}Abdc1ZoAilLuD(3N#q>^bn+pGQ9r znXRPUKCDrs4&)14&SE$sK|iL~UU_D%b40Z0?QN<QO;qGX+jX^Qf@(GkZg?XlU`PrO zQJODUCkhbhmxtXM3+a)Hgj=6Ft3oIUWI1b7q^w9F0pSbIf{MG~F2*;sqj`gpsZ>K* zU9siVrSOMZQm5&djkBmw?JN>N><ZI!3c11k3St5Q_#T~#+G<YYye<GJd0?vhSCPJz zMCY(#PGVu8%(Yal6m!!;(UUXEJ))xsdXH2+q2^=tKjFb{?_4vNmrhTsd0q+}y45~) zZU)G}i>qb$NV0Sn-$_js<=D{MBSCxKdfl_)T8dC!dITLW8QWcZd{P^Tw}_hU(*)Om zfb$tzyb}S4tVi|OUYP98Y9F$WPz`(q=@!o$>ZsdL;>|xVFKfiqUss<5T1t>m>hZq} z$Ix*LE-!;>zUV=+OvL+UE<?)%+N{SU9auXU!WbT5z&!n~Iui+b$+IPW>tud!&m7t; zRrWSWX6uqPD}|)rVjShcwBV&h1DkOPRR$XQH(Pinwsc2=qQU$2e*3KpXDEk5Izd{R ztj4%4rF^!SuzHs5@odk|s)QS*rfAZTuG^6d@p(BlsvuIR<IoXQ^dZZ;g~z{&s?O1` z;k;Moi+GXM?6iFQq9G!ieQ}2fGr_W|a*Y<D#jmxVjh!zIDmi2G<$ej!xOR$7{IbdJ z;E!)V!gYR3$*5D1s@PL^QcO;8mrK>AgFs@+C14%#^r47<rJfqQ8(U40+Q|i8eyow9 zfuBNYMdRmelcXunT3YUPj`$yUg$yyg7|dMG`fx{5$M^dM#=Z!9O6yXr_w3et6ZRDv z^CYXB5PDDaI2^WAs78jz!rJsOLv-oSVYt;uX~KY67ZkV<Ryk9y#r=pIERy;usgc?? z%5OU}D>)k<Eg~W|y*Ifwh9+ImD4}2t=2+*~yZyFs<%javp)&$XQ#8yvx%6`No~y3y zeJ^6d$Bm5!xIJZFpblTmj81mZgVb7CLFEtH%$LP9%4HBSY$R65oY8Uu>SrK<*MN*& zC6CzKleoN=nIo0bpft$IShl{dVO0cTxz^ekdrn0K$$<tClP6IO=S&O7JeQpS@Fu}1 z-`L|{1#^@=#Gk7F8P9y9AM>&+JPEZ%JF!F!`EQ5Sdk`icGrL8A#UoBV_?S&=Q|Ius z+CoUbQm#=NNg-pZf)FX9DL)vlC}_$OwCaO3<cMdPYHdjoUdt(;XZi7RA*oDfNtIui zyCAdH$eyKciKC;)<`^reIRgs$iU>Fmwx)R6bT80$8tG)|=VDvRe8`6(-H%EI2G~{* z%EaCAlYcU$<{%f0azjj|BI312yy^1>IUI8o7FwbfQbL!YV7UU2oQu{BEXe3W%{|II z8v|Yh_58d18padS^oA|XQC7jG)*o)c(eZ-1`ORr_pLy_r6M=|bbG2Mq+s!;2TC80R z_-U#l-|foZRusn%)#g)?4M5Qb?4seY3!K%=CXmTIHACs>!Lk3`zv%V59BZ*(x!B}x zx`6T=ViTJL;unIzHsy|3NkozgMX&Xw8X@8q@w>x;L2|5pn`!?Foe%(!(H?6$ekz7N z^|dHDwstj!R^^-g69uu8C%vWS*OC?wv*$_v9$=)bOkrd3(pFXZ!pC+-tFqx%wzp(p z%W}dF`mKFbAbnks@asG=m@o&zmTcm&XU~rxq$t6|M`D=4YTz82PrFLt;Z@iEJ3v1M zyZQKok#m6;v-Ark@j9B&(9uBQNbS$?Qkn*Np}>iCGgUrElInp)HB^Zw0sTIw^dt`% zH1#o;mxEZ^3F?%be14eH_56c)ibsYJKz#(|tg?5i$F)<$idexO+{2LijwThwU94-V zW1C1X9Pxr!5P{@<yUA@|OGeOE!vjYu|ABQZwC0QYX9vtwfTd!61HbbWK!s9DCHSO0 zvuDfIkrNfdgL9$M=Uu>s_R$5uhA%@L$+n!&WaV6zbU=BRQTitX++%?Qtw34m_LisG zQh-XezPL@9UE5%dn>z??BPyyJB1W_*(FJ5H%Smvr(X>RTJO9FLr8HQ(oJlctEKoC* z7_A|$#bFRu$woX|+|hFWP@oxRm3Luz#&ax?RODHoHM6@DCe6VYgp^%fn*2s7t^40~ z`-qVo%2k8BC<yO02v~(Dgbt)MPv`)a&@|C<cOqFI#7ZN%(NmeBAJmNh(`nqvW*w4% zH=x0hyZA|FU+KNE1?$7;qoZD2=fxNV>fL-cA4AoXq7a61c+!bmhUDYb#(0+ycVRpX zF%Hs0N{5W4<0~Rkk4z&>0z|1~1gp_m@W7DiVig)P#{JDX+FRc`R21uca=)PqYLAvX z9v%m4D8GW=<Y34^*~5OO!K$0;xM;s7J|`fe)URfB_>PUgYx6-XW&C0d2QFQs4TNt? zagJ*&Q{#FGO_NM2(GbOboJ7uYt3lrbKOQtzs)JlBxl&XV3mlxejl!&QP)`|ub^&W~ zmOiu=W5n72sFUV3;>FPl)g*)%s>v~B*zaJV?Q7)66~$}(ovX#|27+L*DTt8QN5E7o z1SI-oMz$(9jMI9SP2<H*pjLPqJCOOc%nEV?gLpFHSR?7kQbYTU-vXqhbs5{^<aW2M zJj+?z!x4z--Kbx|rq(@D)@c20Bx{7*)T}WD@=7!nHa=E2DJ?K^GoQ@Sfoq1Pms<4# zz@?gFmf+(+Hu1jmul<^$4(yE+y@G!gAd_|ujV5uGt;@@(_;sL<ukKgs{=UA4uk;)B z9el3Z_JYqMvDge6arZz$R@|$~GJoZ169PgdM=auDYr*G44A-!}^1LcJgEo>A?=aFm znErcYsAmL1CF}8}r$Kxsihk7TFx^Es<Ont}V*|~Hl*#7!rUI?%l;*QKveh;{qY2wy zjuTFA7vc+^&=zi6LnNEVIEvL%tj_w0LlF*a1RNV`4v6Ix5W}&uPFrwT>FX*U0pd;I z2%*Y{7Rx!4Sf0R2U8RUxbI=$w!#7-ECzoJFpa7ZghMTt>-I=&-<!Dym&2S_-9#Dy* z%qnbAGVB13SVurBuBW??oll{BGf<83bOQ>lrTQRH`3aI85FFihv?m7@dmJUx1K$Cy zA&2b`haRrManRJjlgJsYn~*|VNkrl<)T?88r+r0`P)^d>QAbaZK+P_c@DjK}mzQx% zPV`gmLoP4*M^VIacDMYGQmd@}S6l(uatT~46e5ibHAm+`+VG|i7}+YPt3^unX9ItP zqVOx3f5{WwQgr~ONV%NSv?QwD;}H_^;43S=RAKUv3XQed%L6VBUPw5Pdih-B&8T9T zEDqKn#l1a~8Bb@DT?ZLW>Y=1M0rMd7y5-~v4(TqMo*heWlEhnD#RV-y)3q!Nau&cs z18p0Zj`q30i)gB>RYvFl)<z<3KHs1rE@ici7A^(V2>i)%qzWsu8Rd{UXd3oPA|2A) z(ITH@AY8x6g$sgjjb_!H`ewRxjgrsF%I2BTz!Gg60@u<u5~U#rQ93Y?l2ejP5S=Iw zcovD$Frfmge{i_W^9NT|`Ip9MGdOPPTN1LRqDt^(NZLAbNsn>+na~sGyCE+^Y^~F6 z!ZzL1<xd(Oi}L_xBMd1+u%&Wmq?Br|tI0o)89{?9*#|76YhO9|FV%$OHpnPdL>PR# z+UIt1tFz^YK}gqAufqO;ZGK8^g#cnnItA+~2!CuIy2ujLmTy(}7ECxWORuD*uRM9+ z*v{Er<se0lzwMc_VlbcQ^A&S_8y|uaeVeKxL_I`7S538>#&+0*36DN(g3i%g<5XP< z_6~7%icwuAYQJcmnc~Uj*|@(fm30Bj`f)j0J&xfT?5N?t{Y?X4C|7XqBM8jAulnxK z)^O~ffPIYy8T=pn1Os@Gv;#)AIFOtLz3Y5(Jwjq9I1O9*P7otSel#i8W<DeTIYGX1 z3|g~YzhU78+wx_ryCEeSt7L0lhQ5pJbT^W)zcF11E9AQPR1E;x-0gZhM+Zf0g$*Vj zU~<2U<qIPk!%jRQ(GOkeP&Pu^D1AQTbm&u=uu2A&bgu2fYcC|R-qi{Qa6VD(x;Ub$ zH^TEY%x_cmbKXCu#n=qg?uFhgr<z|`$3Sz_dqU_kn3$dQFdI6=%_WX$BMjS3E-y=> zO)vgf5d{3iC@VgXE{K<8t@c&V)d;koq9@RODsj4WT%Wd<f&-%kUX{oY${nl;>KYdt ztnR^Q<F=?{(pir$wDmOf-Pp<_C<E08;sSTh%tL1YbFSPxy7q8Ao7o<ZMo5nh5Vs~h zd9cd0#D!gUu@>3NI1CA*ozH?LRXU8Gz>K5RcbV3yS)z4G&x`Rmz+;gA_yZIi?uYn5 zHO(Dro1$1w(LpL@urrAgrIoT7t9nHE6r%vIb^b5t-$UF00$Wtnv9p3o*RL#N$un(Q zH4>mFY_n=l8C6|Ri7>v9tPBZ>>+O3Y{V9jlJ%-g57Wu5wcJ0`CF~|rUgSKk3eLns$ z#?QW1TLs93hMI(Uj_2Z>0*-iv)l%mp`f!Ifezg%*viSP`?Rx~N@B7`0{>AB8_o6yQ zR3hTA6IvId9@w%Ph%_5$yb2L6{wnQ(C1{pOoMsvVe~Qt7jv~oU{<TLG0&WiEoFw+K z_q1`8`<dDKlSnUG)j>+L6@ywu58)_cpPVzmdR<)WPaa3=*x1d9siF1y7P8pcNk?!m zzpYv2rNZfcCXfw->n4gc?jwYBn}beI-o#qR4OVK7ErG_`Si{^thq~2`e?^l6*f_u` z`8v+SK==;o&uU8+&Et(=>P2hCFwH=ophtFnmfIc{zY;-VEbjI>HVacQYEr)tYYUhG ze{{bSLP(_`iS=JEg29qbSSCHU(dTOA2{i#&%d1@PO6Eb6+q@$sd_CqtXs<eZE<YA# zubyrjyHFOzs=(!hY^Z8l3)mo4Mm%N%6piKa^O)HOuK2;)m>Ho(RvCz>7`jKHW)2JH zJ~=20_PSQ@g$R^uKCsqY(jXM^K;`Sm)Fpmg<*t=Wj&6*U(&#WLLkA5?vopJ%Oqa91 zAPa$rI<y>k@HH!JBd&>~8x;d7Yr+gqH|z1;S5h2fPS#2i=4Hy-ck6MdqiY*%G{dHx zh$-&*IU;E=hVt!A&KW5)0~ko^pX?9wN;b6}VHQw({rZ)y<~oukl)9JzU0y!1#m1Fw zmGa5Unt$_3;*wW9onT3b;G<LKL!fYZ36Y59Xm@!jHBZc(O#G$T60EAj?(HaXJDGrK zf}fti=-jc2Z+CaRxM&_>J<js}KX(>sroDWQ0!>SoDllFN(D+2R9+%e-WZode*yJ~l zh`up=g}-0#FcL+>BZ{U8Fe>sM5O*K|hCs*6`s1@*-B{77;f0(tH^iyI?>@eLL`eOZ zo%j2vXZ`-kS?}!RVlc=~GX&T6<1E2ZKQD0a5nB!tWh@Vrs4vS8<VJK<{h8|(KUAVA zG@ew8z}za>3H<yE%St8&74>59yNf)+{(O%MzAh@vB9U~?RCu<;wb8<Zly^2-6w|!K z4nOF8V2@|85EyofuL<*nSn?k^E)GK1W)W=jx?+9SuSMO0LSdCnqh>+D?s0BJX)^qT zBd&KjT%d75dD%yQbh~6(5xw%i?x(7dK_TvIbR&aJnf$V^UCPV;3z8nt9K6BcqoKs& z4on{?iJ=d($0j!X97K2?(L*o8TPVL^wk_>U8^_^}lbd8|n0-bAI)!qK(m3=nDE1U+ zJ(2SL(NNpuz@C|=0IKs2JI*Ny{W}a%Qx#vOdl<I2Uk{;P%c-*m!O@Pgu5gmrcaDdM zIIkA>J@%z-_6VcTMR3{GXg9ydbP=kb`rBdy=>xKMUS|m$`kx4D%EHB#r_v|011sIB z>tb?xD9-upvf2|yqu~ofz#y;+zlX+G&I={t5n1BjqS1h80<4?{sWi-CCFaTii$YEJ zlJoxXHP={ZTN=7J0BqxZia80ONK4@iL%Ey47n=DQ<fP64QT-R97f|mJcP<<p&JK>! z#B=;jCCkF!A<5EwB)(L=Vl!U}0KCB*5$K9{;c)p!^>+!7cUJ;=<ImH8f<cd&+!fXR zym3=wPa6wk&wxV>9kT-&9+sXh7KCm|L(1&95^lTBmoW4@I#yGx2_kS+_KRNfAj9jx zu46G%qzVfbd<w_Kpak(+2Rlm|Q42pcrN|ktXW4J5w8WDjaXK9UpmU^EKr2}O5;X>j zU5eyl^xp8@+ypSSPn`n!u{sUJJ}cGqgZT5q+lSRfx7+KTbx(Sy=Y#&)+2H)-eE9aE z`nPAG?@;ldXO|W0p=U{Ya}wD2D3pejWfKi?7fsizK9BElg6vC`f^9~jto<az$WsZf zK~5L)Hy9o=1?9xk!h0ASy}+E)=~y~q9`pxw2r3Kvv-vINl<n4LG_MUhTzxjih!z^C zGWujRT_9@KHdxOt2{WzKbrtdwJ|N`iyEiY%D<ZV6jAPJC8EnbZz)NX}qhHaiq`}_w z?d%D@@Tr-PLt8F8f&-l5{T|666`odA<|9kK1jQI4W+M}J)ZVV9Ho@K{cXNY-W%r>Q zW^SiiHpB@8bU|#SBPvs4rel8jek*koQQq-=yk?JTXag^>NM1fZ@)D9;TfV=H4aU4? z0m+A*eF68l8X?WLKOj&OAt0EZ8yyL@o)$l2toQ>b6NkxYYBWq-FS9w65dsm{TDdHd z{aVP;LIcduW?7a{bH+wgpx5{i2!|pTfp937GVld;ciVEYS|lP6$G%-L9>k5=0Ce6h z&~YHF&j~R0+vZP3Q6^0>Z7p^_AwLgRaL<XZNd6qLOOH-_MVrI`M0uksTQoZpJVE2B zlmeBDsFZDzcaT^khJtJeA}|QgZI#SzbLP@t|Avu18?O3*E^$SzB*Xb;4UA947RIQX zpa><bKJ?%xCUNkZNf}w}HbYJiJ(q{pTI!3AYo@1brfgt;5Buu692$Z1RvjOHiK&6B zOa*zt&Ef-X4o{`t>M92pN|&N+?<|fyxoc>nShrY(mnfpj_1-NvM9eL~x7lqiFmK^_ zC8~I)gNbJ=VY-{V2zNS~tT!)Ky742g46*&i4$}nD@1Vj!^*>!xd$nT9Mq@Y%L9b)w z)M^Y||DAL0HPnioOseO!uF1q721B0FH#pFnek67&=>`UoSmay`ENVw#galJPBo#4j ztX?VH^RTM4Xu{^d`(^m+um4~E!+-w#=GUu#{G7{vAg>|B$?jXUTaFQuWsFk{`VJj~ zVV~pXHHLoic|g49_Rcg{0y;jho`~PwJ~~5^vTL<9UdaH;tR9UX-3K165vxjTO}yHN z1`Iiopl29j#=%$eM+BQT^kfSl-7jBXj#LeWOdIrdS&L})gAqFuAzPA&S){c6N&~up zj*U_nuB3#2k9{hBg{I99v~F_KfjrTv;B3+2;VhloviNY0wbUt?|G=uTau3?g21(T( z$>c;vnCGHiWS@?8eRC-5=dSp8k>3wlYpjOTUF8ujAHI$Z;zSL=4kQ4|^Z>$LSmEKj z@U^pK4K}L`d9SU-$}=eeMDrhgw>l%R7%qcx(pWEo##qbsOlbq@%Zh^U3RaO9xwO6o z`+xvmBFup#`%fC`M*g0lbZ3T41+O0~aB>awY4uoyd0idvxoJ{`=d{#Bom_vKv)ZQu zDjv$i_E~Pnlg<P#nN1?N0oBIyNp<*>{Gj!>DQkm{GTN1}xznWeFJ6s-Kcqrg@b*t% z+vJ(YAhqN$zY0a|sD7`?e$r6Ef5!{idR{06B$F`JI(FXS!U*V?1<`n^Ptj8x5^9qh z+MXG$!ozET0-L0lU?P~idVI+%_1X{7FYI<D$>1C_%o0M;6a3%;#!Kx?P&X}ft_H&v zR7TlA!yjSO-RNe1FEcso?aP_DsE4eId9M2UzT7Jr(s$w&Rx$l~JC$tTTrC95v$enJ zZmmkd5*Ew1PGuQC(3I66D21p)z!8a+TkOM6s9RGF(B^E+P9Vf!BWana<1;ri>PO-l za2rON=J9{l3om^0%C$ybURJ9J@{-DSF`uEvS$SOti|UnH10O_+4Zpola#SC%cQ|B| z9+=rO3M%Msw4|SQNZ<edjnjBA2ELXi!PMOZ_x9|E%vu-M9d2VCdUP)B88F`2vVG+| zdjzLDz>(N5!O|LAp2}>oMlpAFdo{(>SkA0}a8zNv4Ej>u+ka(dLH9(N1;W0VV?c~B z5^0&}C0jS{V9_EJo1xYL7wkSg6oup0TA%Ak_S*k|BX>hdsz-dp{S<&3y41i)3Bv|O zZCY-|7siZ9zY}^iz{6FK2J2<fzky6#$1)<Ec4f#3jN;}|VaVn@xMDEouHdtXYcQ<- zK0r7Fc!QZkYgijIH0z`A!Sqa4)j1=AznBB&qr)Q_tH;IPi>y@T3g%lghWH$MgXI|( zWOnAO=|}c;%?pqM<v82zIW0cSHy^d}G>WIvytC!oCAeeDupPrP#zqgUcj08Bg$M|1 z5M=l(j``&%)aG`iPr1HS`e(GOo#frFsYVs+#a`A~d2m83@13Rp(Fp!cPWzHM4d05d zKP~+*0%6qgr2knup-+bk6vqU=L-9+uGG$H~9i2LYj$w^vfObGyk(j~s15bDykOH@+ zhM{}caF)qomJ)Jwep<Zcgo+W7P0?q7*_IL{F^P@B-1hF3Z6QBi2rwfvki{|D73=|J z_1vHfwZ^$=!c`Ivt}(_nC&5OAiGFaI=UZ81nV^mduE3Nuy^Gd2+K?`PmPx2cvO!l1 z+$hBYu7Fax6Bq@c=e~E}rg;WG<;2i@=R(3e`V7l3?$c2Ke;ke_#V#03IK42r%J5QA zaowXfiF^<(oboxUSEBFqB0g0Xx2~q9<Dv45TuE<j;D0zr?*?+Czgv4G%7uo!6rYYd z9gz6O#%x$mhIOfe3_CJbOjfCp`+{1ohsQ0s%G{B_;J3pmNU@A@vFz75R-@!$qFmvG zZKEa21_7qVi<Na{jD6G?UXMDaPI~!XK&YqGUxUAa><Mz+HEOX{==vaV0pRpBmaB2w zhJ1sVi<f10371lZ59VA-<VwVs2t_NTF(VfZTLkQIBg<<|!eP1sLmY8}pDGl=M%zLW zO86t=i33Uzy;6sxbqb|o2i=(G1<RMJ!6*T}6v>?xes<4T=5NlYfKbf9%F8bxHY_!E zm|z)WYEdhG-0W9l)D<83Ojl#d*$n%vKo2`Alh#tCP|2v<Nl0Bm)c`mgD+KTqR+n5S zL_Uh7hNF_$MlM_^49&!W?aT<r^6=>XAK48tUES4a_;wz&>?xSxy4=>Yng2jECP`nq zbfkx<z4mCrQ(AvrLc9dNWX)dPh5tnR^T{@hMy(VKjFJ78I6?<MH!&Es#4N)S;y&2a z<lR^ZALdpzsuDAil<@|?P9L;T>QI7&nJbwz@BC%mhOX<*r=Sse;5W?@U`%OZQ7!6M zH~&PugzTWOBqW`Ph)qKhn&3niQ@l7oz|ks9R|02c3S}T*g$z-q77J%K&PASaB{;Dk z4ONIeA@h(=4+;*{LO^Wkh8m>48s2OIV0XL5&>hzK3Wz;!A2Fe5J6d)CEiOij&E2ST z2So{py@PG6^tgamsIS{vCQ&yd9lM}7@;e$S@P5{-@29KzbP`ZBCQ#E7ghHN4t<saV zC?nh~_H69^)eb!g_TMpgtg}(x!#D$JtwgFwkB{n}HIh9qK8}Lgq5aI{)L?#SmIOC> z<PMRK%g=l)u1Tv{BHoE#DU5f5V5jiIK5(%p*~A*1NDx$dv(ti{;+f;ks`Q7<0bSyx zBcKu{HLSSi5w$62>b^9K5S@l#xf3_>kw>g?83AH(A84#dwCpf`VTZ<z0<}+eh|-PV z{<BeO^N8-z5jr~FjgO?{*Eu6Q=7^};@b@IOyh-4BnqMZam2);nAZf3-p&#<1Eb{cU zltyAe%>>}yBZbf-y*sHi5?|H+tr0r6Y~t+c(3h7Hn&oN($A7{yo1UV<?LOZAvbHZm zl;>0a-2&U2-(k2$qHF5Vc=})#C3=TN>r5c%!ww0%Up~~xL`tWU^<ZhLA<Dg67n1wX z)5>9SFcTyN7UTUwx+DT}gk&!kov<jl)x)zxk!%?0EgGZEQmgFl?T#{sr-MN+=x^ms z=H^T69@u^Z<3Jcjx+ppJxnkJr^&H~N+l2u5G^|8v1}9yUXANd2j32N8#oG3SVTl_J zP#R1(Ak863`n2DG`wPtn-t~^0O&4@ZD9tOh$U*B1l9@dJ;p(kewOXUre7niEiBy#F z4xY`R!39qW$Y`>%!G_xtXL-s{Gvx{?x5lKA=<Ab?$!iP!9cxiUnwZFOH7DhIyUY#M z3ABplGv;Rq6EqL|4M(l*RvL*0{2ekr5bd_jTxL5;y>hM$l{FA4i_6PNb`AmO4;Uh# zjUVA|mg^?rxN+wG`IZfyw+l#+;eG<LF-gzUy``ngHf*3+O+i4B0oJ~p#Ybqb;ADxv zb}XEL8(A-cP@LXmtKSU%gH?3}!U8_Q`wr$(LAeE`jm}^G^4DTJ{;LUx{(6m(k`q+G zuO&SC3l)<q^9hIv0J4XkpkxF8+Rt(4ejfcSTc-XzfC_&HwISC?8lVg|E?Dk&(}!<6 zXzQLA$SUL=rC4YPE9rhjTUDskle#BCJqhdzD3h$F+i2hGI$7)QX03^DS}GaX;i6@y zC<yHclS#H1I>EvQvdE*-izY5?`0hOrEOGakL51W7$;GS1H~C2n&N&gHB$+&kidVPK zEOj|u-XLf|AOd9vpo+ryJe;WsA<x!Vrnm6F-0#Yfj!4W9%b>P{DXXAO2KE*ON;4>- zCiidbd&8Y!a3;O~Qal<UDA?Q$JO8g!sS|tEKBb{LL?Pk+iH{G}{bQXm4?K{N^lNA% zx=Kcdj(z6Bfe@l;+h?QgddcR?4ssk#ZFE2EXC)E5gHuXNnA;oE+au+E%(i(j;Ir9w zSA`JSxhxCwihFd`e54)prxEXcKUX~&xUW)(>j5<)Ne6ht@6b9`FoKh%25~oc{NdaO zxA?~ri@hu1?O1X+dvMJ{fyZY^Ya&*LAzxrC1J$~U3Y96ZbkM{F9Jxq)0=gFn=k`li zxw9Bz41zVj2tlcZG(4*_Mo0PlAi)A@K(tJc*nwaLBBo?J`K~?*zNzbh?)bh(dF%vP zaTUjG2b5Z5)F!sFZ<$sy`k2#@PnDK6#3_T3)azY3QC2bv>wx1HWEP-kfj*iF&(Ir% zc84Bpy4{<~SEDx{83!oh`khBQCs3Q&3A3E1wOgi|msj8`^TDLK7tSU)w{dr{LP6!H zE^%0XlN1+m)~>wo=9S@G9N9pfXkM}xX{J!|wpjJLXQybDFZln@ytb4<(RAewTIT~F zBI*i)UXdVf@%v&ln?h>`OpzlZ!N)M}GBXQ}5?1snZJ(M(P+7odmsGiq0EjWl2*SgT ztsqt|2NvDxZtC)CdjbGz1~v8?*Tfo$+=&-8qJ5;x+txhVlhHQW9<JMrn{uyU32Xz5 zp<IoP{joML@g}y>Q`%WvtcIIl3RQ+NE%&t_^QHCg8l<yN=^i*P?g9fO7T>ZQYGo9_ z5HUU1rir^x><1Iih1%z4i2U2%8pKyXyaPp~c+{|s4-UvMJvy$K5W+)QW}7Fy`RC<j z!D0wxo*p<skle}58Z^qs*P=lF%5}6OK>p^{$^M&Hr}&Q{t-C0T5}S@`pH!xKMuFp) zSiB1%j&;bn@~ZmVnj6<RsEMQdnonzNg0iq9&I-E3=D0lb22UFFGRUADBLQ7>uJ;Pd zF~V}ZUm0VwK?{mfuM%Mk`i#0vzueGFi6L663WmjTci#_soB7-Ms+;xC`scmVKK$0) z{g1$T8NUNx`QlxOl}(c@y%5p07f68yVs@7AJzg(VE)7rBsQ90;tm4s6HL6N&Hsk5i zq5R=95(i6hBTT6o7aIclf`yxol$+jJnHO>EVw=&tz6~gA`dr>Wc6-iDFs%ns6l_cK zy<p0L30x$mcGAfEP|p*|P%-KOMd0U|VHx}jH$WYPVJi0^*W*E!#viOETR{mq*e&yh z&K7Sxg{b~#Tzw)p=B?EtekiwuGCpDr)bcmf((-Piwp86vW5^xHltVt&p&Sbo1D=H> zfld7Rh)4Y5!_Y#t_)*~jbl(ziKo$?64q=TkVmL}X|37K#g%(Tz;(^s9_NaasK+tq^ zy*oorM&gs?QE)thiXyLaO;@P|3nQa2fWT{fa_$CS?9e_Rre=hc%tnCrL!cI_x2SnY z^rG&`2Jw%{c=fT)5m3myVYF268~}tVFmhoc_ja`4{49*k&U!z{^crk3e;EJR^^C9C zd`q^6{J;-v(&oR?t7%{9@L2dp<$Kh<@qZTiqZunhH>X>RkyeCM4tLO@_HKpv9F-F% z!tgjv_*1ris6oqoWW-W{y-0D<+Lc7B`cGO)P0Z5d&q$x0vO!zyndy@i03LygzO`2x zd4k6<Jp)q5=*-A<*X!IMML=J<&6O-X9|F!z=2Ubu*neaeU`B>?NcJx8E*u6JSh333 zVI0rl0Al$z<vwH-5SxX76Pu*;Ws$oP{}R_H6=;i*O1@O~n()ypL<N)4hG?JB+^}%9 zG<Jy@?cs8X#*yHlz&QztX(JjEmQN;*aW0QfqTgimhi7y(5U(mRHG(@>AB;5)u*2!! z+%ZYESoWel=4;nZe#7;%BgO1#dER^`WTx}ZuT;)1ub4pIBQbDO3_j7m5yUIWG`nRL z($LnSoKAYUz>cD5O!L=P;S~Y3tNly3V7u&wL)%DmUD#18g;CUBuVK-nqsFt~umOx; z!E`feE(djewcof#c(8^Uq;+&a(f0zyzka=6k(oXD_VN;cuYV~Vl<53siK0X|0~H+s z>1?!L>~be5{5ysSS*nWkb{w0<5L!uSL9}Qzrr(UP0BUq<@}fit*brTUG1ZA^KZBhb zWi6BW{d_`lR@X++4kWp}lt0>5!_>d;(f3a9!FW(Le3Ngb?b_iDHejz(wOaTpo$Cdo zJ44yjv`2U1%6jQgVxaD!!>XSAuwh5OLXBNUQ6p0w8I}b34rtrrw=t4~hXYNX5O?67 zC)@&<qKK~%glTRGu}d@CUgo}+#b6J7A1VyeJU(<d*1rpm1wf%x((02~hM+^i-=FgJ zhmKZQ7~F##N=xp{)iL}Ana_sPrEVa=Gf|>Ee!sm)#wn#pOC#8DjF{vRk8a-Ck~RiM z-`>xHVTF-fX$?LhiNI(jB90SbR;*r7H_|SnWLh)WFxTeJ>$tET8EGu_!eodn00MU% z<m8MB+u<3r<2-S+V5w6)A0@b@>6t01K`LUyYXO_aF~Z@FTJqYy6Sg4SRQ}6!gW!vW z3E5e53to;Hh3q;(?w0u-eV}wXRXX{aANLc{6&1RxK5OLi4syAVp*Kb{2LZVa+0X<8 z)4SgO;g7+Ix6oYFR*_`{s!Ur&IeJczbTez`Lk=z==H;}3L9hHy5>>9H;>Ue@a4KFH zB*+-;l(QgoI%bQk>BRL*_1mG98}}a?k%CdlcoUks07OX3tF~q;TzpnGU0=C^E7D>S zte2H5xCrcXgLoogQ;!v#$z)b0ar$&ULsv0>wE0D;Q&l|N<QX(Q&;zM$>7K&2Fn|TN ziAhh=A5NWR#zM#DqaG`LM!?`Hfx#LiNq8<XZYqBT$h4bh0+9lh8Lb=ytN&2igX9Py z@EDBTgY3r3ZFig?W7UFP_PB8+16DbADrf9u`k02i>xJ;ui4v~yL8;)BAKzZIKxYit zpMyEyGj@Vo`EnDzf~I;~afqoo&yVa`Tc$D)C7}-}oVB@>FbW6|#a7DU1ggA3V3JSJ z$&3GIrW><o;qb|8UTmwlY=#B%+dFBBh^NBC9F_WqE3LfMA2D940*AMBJ+%+Q3{P1v z3YZt`zyBnWc;$;rRu&clGA=!viIvi=K=ISpSaj)Ib5Mx}L9uGQNto!`u@JCa+L${z zT9BG1V%}@`hb^X4<eSls&>nwUjem)c>JaCICWr+vu%6OhAf4IvTDfAu=j%V<i0`Pt zj?-h#*jIiEq^{cug$(WK`j7wcD{O;9249vQppjGopt6r@;2N9sQ;zhw`b*_nb{rB^ zk;S0U?Vjat9Tbl~(7jgE?>8Kd%71>{HFpt_T1dbZnRz@PqB3(}e#5jA32*SIK7Krq zorCHK(<u|6(ag*)G_M$+C}PNIuaqV#HqI3$s(YCv@m8lH`YQbqM%zHn98w;KXmsRt z(D*<^Z(fLG1MI{C{U#zgR)GrZ55_-k-cQFn{yWb_EEOT|$U-rK&cuYED#!>to(D5z zK3jUuk8yVwv|`8iH=4#FXSWp(+dUUdkuLw6Fu1|?UD(tgXpL}?%8`8>C@mqq15#gA z+eCn-s4E~+Bu;n^=~}a{g0W>5%%3T7D-lk91%0r|y(8j=cYKT{c&cDHpV0V<f95i( z%m}0DsSToE5WiI#{)iEkJO0QS{K0hm+2yeYy@I7fx4le2vqt#Oe|Em%&wulO6m;iU zy89ypwo4abXon6Wj&Ghd7ei?R3U7t&8a%nW9}ZZi!OTf4I2x-@5#FM1ZQ_Q}{^9B! z7}Yqnzvk$FL<~ZPHC7C|;HI0`OzS@OI%LF5h_EpS6zJx)e2<+s{K<~EBhijSN$?14 zAexvTHr3>(a`7_o@E{EAuoTC#Q8FH~q1~Ohz@KuIUeIdJ#Ho{iuW}JBsoNYVl0VtM z?AEN)njz_$QQI^cTS!{RS`>ld0A|bGY+-%e)E&Q9FDdFj^?6_Y!EBsktqSD#`injT zs$+lp;~)MghsxVKd!dsK`XIATs9~&@>&!IXoI0GeF;rV$GLnzCmcaG1UTpTo9m?dW z`{Pz>t)T4lzA~ES1|!@Qm|%>og<aolH?&h^^?BVs1f6Y=XHh|<Cp5KTomkd6Gw4_# znR17U2!*oU75FRCKma2Svlk%0^I?jq*;+Ld(uyvsk17vHqej|tl)n2E*Ti`0>fKr6 zLsA}s5%&6*Q@TcipP~(9r1}z+vkQmRYpB#7KBQj^nC{aLGF2X`>*W;_30TCM+g()i zW)q^Nd~`n90(_@EO#po~PzzP~!5fS(Kwdz<r8|^n$?Gi3^J5^YhYFli*T~^t+1*XC zb|syPCr+9SWp`InjO9#5g*AgqmWKX|p{PoRL5!<rmqUAW(5`LPp><-$c&S3f5!on- zSJr!wF2n{mA}WWx_t?HA#+pTgV)gzFt_%z7Kod3;Wzm>P7%<oQXwI;`e*MbUlN`sy zu#PV;pUB{KF_Xj-;LzaftiXGyz9Twfdo&yA&$;il4`S$51jzSWsPsygc$K7buwqwN zh(Nm4J#(!#1Uq7Vd+Jy&!Btoj5i3RV-2+`Afy&JB!c>iB2Ve=4i@Ks_;?9;dX#9yp zMFPA{i@ss>*3awRchD2D8c6IGFr-E04=@TTsb8eN&kR06&I6V3sX;)%LcsR{U9<#! ziNf9gq7KTJMffVaB~U^YNV@>*d0)VPn_<dF3`uH1T$Tkt$eybn*WIT~?fJZ?b3sv_ zw-x$bJnoY9m9j7q9EMFiZSRrg0+~AqlQ|M<<)7>im{F%qX4oN!=B~h&+NLd*@YPEN z%U;$&sb<&yj3aD<#6WZk2RwzPn+g;~w4YVAiyY}gl63UnX8N6=Ow=odgwPyXO17Mj z#WQ6SrR+<=!@OJ#8LVmb#EP>ZG;5Vj{p7?;EbM`ODWdV!*M-d@U_?qZr5;Mhy3O?= zY}4go6&TJ7AGfFY3W9w6mz@fQuP%3rYZKS>0U8}4932!ue+MEgV!M>R=7JVo(Dsar zq53FKP3dis{!Wk%l}A8$t1lVy7pUp%CWK!&3JoZa?-+Q-87FN^hI-p*qe6*sVT@aP zL_%gronW^*4cz{I-A|$O%l=6C6-UR516)#y;|qcSMiPe7P)_kn0P}AWf6g$*V*CM9 zYLGu*5<4W(c>P!4NeM~s_xMW7w}8}3wT&Cwe`T?nRIp*9FB{f@17)=>Q7D;;=4ri= zO?+TOLbA(B7!Ux7VLsDZv0Au;q}fY?K{$#|9P&>K+q$H#)sPH1(veFC@{f*MQ#lxU zre}3n@;47SIv;MN)-RL>j#)zvDlV}D6xM=&w*=VWyX%ryk>-%(wY_CWtRG<Y!}nuZ zcrHeicP7#tH|T2SBcj$1gpf%mC`YbAtaXnj2%Sl71DC|}*gnt^DpzR7oIZ!xcw4fw zRy{EM_Mb|`kHe(g)Zs!v(?E+Ne9XfF8{e}6gApb0nvz9VH=9imm@<IAI&$3&JaDy$ z_SweorY(Y6x@e0q5<MDa1(OSmHi^qD#7Xl3MoS}PkDasqD*z##%&~luzZ(Z?^1HAm zFGrz)2{i#vc=J=Y4{0r!rYK<n(EHB<YO_WOT+NLos#@j3_~xV+(~C-Bt><#C<ilFC zr<~En7#VvliiXu2jW329<>ab4ArB3un6h8}BJJYUe8~`dkZ+OdcqK~`9*WQ5bkb<G zz+84Frc(!$;v1K-#hy;)8VK7EY<vykQj+%e#feMFr$9jZgVBxc<oC$^|KdP9KQ~!7 zqs}NdE?F3%olh1^;>Sj}tTG6_G6&uL#<NNs15p^$bSwJeX9136J|B>Kw*Z53aOz4M z*Q4EjE4siq@A^!MYR!qqYZ2B{7}Cot0Lsu{OQsZJY^_)zA3YhP9T9khG{{6+e%7O2 z1wk)#i36U3eY`hpZ2MecAF)eej!2-}4&Z3HA-WY?EwNX1z;45J#?fdmpwb=~s$G$z zV5{nSa_n+6=E$_%)OvkfeE>5qWZW7a7?RLv%JnY0!lC35@U9uP5j59rmuUUAWqQy) za3-W50UgrnV9>S0WL<rK^&X!E_1mXQlH!4mQAkpZn27-(Yoo`;hN?7EuS^L78qZg5 z(LD{e6m}rD8=%b!iE)W<CxO=IQ1q^x219_6nxLw%``xV-Q~}Hi9M%>HOA&_@FJ!&c z1_XFr)Uv-I&@NJ7v8_nd%6!<R9njYjf(D~AvhJxV6es@atp1<Q`JC4U^{)hau5$dM zM_vw>3nc$)oC!ZQc+H35Ero!wD)L=bm~#dgoYzOk&&WyB1vxTr%5Ok-wD?F#AJA<U zT_{0?Xt(n+_1kcPFGmIdRbiM91Pyt51PNhtX_D=b4azY&@FsptK(G{%uWlkhAuaRo z_Y1b)7~dG52`9pU(HHO?PZ}u69j>nWLuop+gr=(Bf40PU$<ZyX%YPef(cXDmdw_af zzIObqPxE!KEjDndJKMc}{r3;*|LL@2nKbo3bCG&{lAB89{sWVAt+ZwHZrlBGV@Rp3 zrA_L-+2rq}MZk%kY}d%9pu{nS2!t?t!e&=H77BNh#6~2CgssqP1N~{esxK@D0i+3f zXG|>NiJb}1fYBIBzW{yTW7^hwBfZEU4n9p|Cnw`g&~hNsQ9}Qy@pJ7(Rl?9l8nzgr z_76fS`@zN?Qq|q44<w(BxE1Auk}W>ypa7{10UMe8Y}n>axA1`>keeJNkp+ICf=4n7 zE9Zh=^I2?(qUN+WK3@iuc?YiWH7E<%43HzVB&u;v#Zo@C)kV0M_ZZo>!!-54Q8rZD zI<-03_DxD~OZNcN#FnGo4^m7iE92lb0HPrD>E~H5*5?Am^i+K=1f3Oqu11buD%(0} zvghmC;5})tiXml79q_a~V~p=*S(3xysSZ&>c*4KNs!(fg*wHp!?qL0gWT)kk_O&0! zrg+sOu7+1}d#&WU2b%9>BtfL}q6=0VsDciLY-l2UQhm#?Lt`Ml_HvLAAv79a)Q7dX zg=`1;BHCqGeWxg7TnwRwuHm1}$zH#v>0+J<nV%1_EWbmdV`AH4c&4+x1WrdN=?WCC zU74RLfvMiS7lSvxTF;wo);UB3$i%1&!$=I4zi{@R+39FA8l&d`;UoHi?srBnjwkn< zSNRenInZB}V@w#9XU6}!?ffgA1kqZ|&=5o(1Be|$o_M;`3Y}hw^5IV?km5H!c0_7Z z98+O>dF?6q+uu6%da3dobz9h!Z^5#hRrh09G=12BE44yhf^g7kr1VRi{I2c4U`lgk z9B19oBrm-o582vwI5@rnef!Mi3oE5|DQU;H`H9a>Y^Ed{L{Z?MD7Fc6b~{=GMVPWd zR;d`nTmQE69vZ}?GU_ERPK!OK)QEhUg0<W2dW%d917bA)M1+Y+-Au%=)eiRgwyK`p zO-|NRUM4X>n}vXuG0|$azMWtFvPlwaj1nIoM-%yqE&R$|2p4Xq_VA{IgNss^(Jv*Q zg({ZbvlP8fV^%bXP9fF_b;uuq!oK_Q9UY~}pzhW?KxWJNc#9e*LWhZ!Y&t?V2JOxD zM!>KpGE?9IeJ~q?>k8{5Pix0|ny1z&+*CJE5Erm8dM!+z5g>dOR-RL3WdPzuSgk{= z#nTcQOG6HVBm$vE71py#4h&lFW-&vg>S($>SGQmmfZJfkBXVj<7t}%oi2M-Qmgt^V ziVokQ2#d(B8eQTUZ8qT+*~x8|QB%{>hAVGdzRZ+#{7t227=P!;LH5!(mo8EWSr*KL z!JfJzis&hJUXMTle_UcTD*EFg3s>b-rw3i6=Swn&uP_z`gS4d^Z47h}@#iB1w?+@s zw8me9gEi=?O59OEdfZ-`95RmUoPOgpOs-lm9Mxlw@hzzIvd)JGbs^h(-GNa5s&*<> ziAb27;8F&pZQCBpV71nOHC{w7i;T~U*R7niBFPPh4dCbfnJagVjRVFJ_;28Gtkx2@ zgO@ceI?PICzIW#bkhKLGx5mNe1*Z{#5#WlXszKj*uXmJ~2=mD9{3I>)u-8Xlf9>=Z zTMtM8_~DwQwpmrzTnvJ@g7OF5+~KwVE=wEk!@nhnbUL>$`v9=j*lvRd@ux0zBn@sC zdf?hanE3stc+t|;1|w)H5u^6jNN8wjO@PHdxRx7?p<Qk;BN}Uq5O2K&z}?ww*JEJa z$EF1}zBbfFq!>}XI?`ydxf|(vHiG>~=(mzykma-*kI+OC%ui~avOA4F&7^z?JyIQE zpbC*G<W5~(<jWBX(I^m+lCUXqH_YmIH+85HRW5!4xckHX{g9?F-^^B+UppPo5k^W* zWdQ0^l;WxKPZi62EXV~P2}Z5!@mj^IT){RFNyA=guYIG}FwwhJ3=;!{yEnee$9P5n z3U^Z+AuB*8sc$rwz%dapj08E0`S}^(-kpXB)bj@BY|?xQDNN`cjvEO7SwSq3iMLwt zN~6xVH#ule^O-1*dLw(lu`it*EAyi!S<O<!$;HHCm!yAPPphN3^^j-%R-&aOwv51s zwjC2dke8vy7Fg-`W_aTYWq#ZnQ@|t%!<q^oOxw00AsK3>IbTs3X1%pPobKw=fa|d7 z#Z*y>)I}I>)x|{s+EVkSxfZ9{Nx0Zk2ssGsqk3b*dP3M;CkCX_ej<5T1e+*Q2rJ|` zdWH5}L@(W~ow)9k?AabHpegLIQPUAfmkq$GE0B+`-oJg{_u#I(%*Mw)i@(Iw^>D+a z!vL(kLD(-aUG8LY1R@%b!EJS5-S7;Y)4Ms${x3|DiH-ikT=K7z(ZBv$EXISs?(nBS z1HgpjM)>DHpJac|&i{PU|0@piU&qUx(=jT55*iHT#R2g^Z?ovn0wBe(d90>4A4vjC zif*zoRZFQ9_j#=_O>*wk^pAXEo9TjYhd%P9HLoH5DuFyK{b<g3iRuvqiXYfQ>N^7< z_=h@RnsFD5QZ^=y%3V$at07VR8l-G+7sVawm8)~n4@%UKi|s7;1^E#YfXGEg;O;<m zRCf5O`k}v_nKEXko_VZP$g1&?RwB%g)dnC3SvxQeaTNt+JQlk|EMtuj5pJ8%ybFhc z8XNNQ3|9dK^wWm|c*_dK5wON$_92$GV&z*BeC$&UNpnd=+?I=ecDr6rAbG16o3p(Y zK?{S9q!_rp<h9Xz<5<`fo@J<mKU+3ODrb>L4U$Y1t9Z|Aa2w1N2QTw@plH{N`T}b! zc5-i?v}hUv`y|QZWqz=5?V3J6BMNKIZ-UU>E;ECT&3d9UNU(K*gM<AG716w1sJU&& zcF1f{Z#22*Bmq--k-i_q?)@1;?W@RZN}D-uS<;-fbUU&WaJziLR5Cz_s2CoXpyT)f zJlY%+poQVdr*R<^cCmKu8Ee-mQiit>FC`SD_%q(Ol(Cfrp6t87*lZs7DJ0F#+S{X2 zzL6Mx<bvYLy-Nc3ke9@9GyTfH5jZu)_tZe$=Bugku`dw$%g+7KFDo^t=2`DmoyTTU zT^$R2=pox>S)(ej-$HB>@@nf3(-j~28rhFd#j2c^XT{&-wa2piHi6G~qubCnRh(tA z^ycq%;9pBsgf9Gb4$`EE-QlIK!QjMrNeC{n{H2UT|8`L##fYFuec$%8DkDpBf7l#A z7@bctPhyWXB~Qx~EL*{62V%+aKBjMhuOM-Gm6qazbbTnG8t6=X&mI{0t;(_d9f%5O z1(8@4=39Y7!WTg_YyOvBH}8v0LEjeGk2$irM1GN!s?9pPux|=IZIuRq(2vvCykt%= zFlB~h3k>PiI+o?(y+X-qNAcuOA(I-#RD714lJxu(5uJqYGS$f4hFjKB)`L?6R#iMM zZ>ali?k~7Zz&Cey)b(F4H#&2`&E0UQ`b*|78Ii+7^F7-9p3y{RNPU)f0NVh{o8uiB z2%qH({&yIGMKn?nNz3Gc?w0bG1m3LRmzCl#e}Zinw~O_SR(aG0*+?WwAU}3%>*v<w zH`vk-sDxwE+xp?rfp~OtzMyMPu{=G*2yjsd_#JvLO0gf7@}!WfYP^~?0C@CL-H-M@ zsR>>QALz#{XQ#nfM|G%)z%bs+N|hA_w0_LyK#n?7H1mktf3QfX>7nmf0YubvW@<9S z76MQLK#+#e!fFR@JAMTJL1H4l!tojssh1_8$10<3PwcWFDyhMIq<GoVR{;2B27c~G z#4oW=VK-9uEbh&$8)@|4e@=p}kRcC}Lw%Yk9CAs~kp@UbWJrLfZ|1xk>6bBj0$S3L zJ!p+NCwUUXfE<Q}`YM*^T$0snGMw)%@X=#)12Ss>%iGqKve<IURwD9J7lwIz^#mnX zl0_Y+u|;`|Q-Z4p<V;FcYC&_USP9evOpoelb4z<vr7u15C7Po{DC&rgHrA<rc~Uia z^meq$y63~UqpW*2Gy+>}N5O+J!}cHZtYhU`nH3sWOA5H_h>7O69x*GZ$;gC7Eg0ES zAR|g=B}@bvcL~QgHc|BV>iL{rYL+0ysq*c2wGdHL&TGAtvYUJ1H=_IIpBW(FlH9l< zp%*NV0q=a^Xl@SP+^iS#@#7U3RM`;!>C)(U=K!YT#AI2(8f>AuCdDWfxWEu^Ss&&} z+-4&)*kXID@A{DQS5t3~;F*bU=CvU1KnLQ^Im~3Vc%$73<^yZ6rKZP3dZEZvSOOT< ze5rCvzA|@JiagN~D`^p7#wc;d&;~ZT?Y<oqnJ{=po5jB90Q3kjF=E$3D=L>9jzysg zg5m<;!Lz<jc(fqL)vx)mPq{yo36*By4a|Ws#8a_?R&-K#RlZTaqrrPGhmZ-?J`9>; zL3Su7EmO~3B-IheVMAp5<hknBi={9#3sS*jBGz*u1!DmW=`sTSc@w)}!adVCTsfXG zB($VPa==Mf(XZqlx-O>b4*eKx(OKS^0my#j8JUtb#6@n81ZXWJD{sZ!`r~r6dIYKG zP`0ixH7P%rm;CSCYBf2TzeEmh_wx8JAO8tQjSwOgE8#~!9XXQ8tn4qF(HTqt>6<Zk z1Fd8L>9n5=YMVA9HalL$;JPOPHv@+fZL6#4w%eV|N4G23GtOK`g8=*3;J5gB{3dnR z0sQ*3)~h}-8)GROQjrpudT4GT)Yk0fQl1c+$=RA}|B`^{H?Qv3^GWr;fdH}WF2^xV z<cb`NRP;o^T6^4yKNXL#oD)p_z%WX-JAj1Q=Gk_Nd)#1?N~B=+mJ#eM$nvmLRe4_@ z%h<yh93&p+Zz%yZ-_7qqO@W9QSEat-GLA%Kp+FZLvu8(E{gV?0S10(tIKDb(d?mGB zco&fUIKXK#pUo@-uwoy-vip|mo{Sca@nmKLXzm!_ZEux^#YGN+;>4w~33(s+JJY+0 zV2k7cw(Fn;j76{3xrG<5<e9Q=2rdkV$a4|bb?pxkgSaAcY<}4Wai=<ab|{>*V2JzS zvsEHA2BkZtIv{cYlLtNDv5wtXXPwG3n0r^thB&wC2wYJS3zIH&+wr5XQJXVX6x53V z#fXU%2!$*Kl-K|xqxhi&Z<p^YJb@Si!}=rPaE^5E_$n@wNfuMALHD2`xnm{ShP$_S zxK4N70Te-mcxMS_mGO69PHV>CFWjC5q`7Yb;Kgj8EJbVRNSw4DO-0C`wIq;=O({j- zCR4Owh=F*_fRf2@=!cO)tW$@cW8a!S0(yRyBaOP)q8XG&fTxh-ajHIk@T(LoWhHyy z<P1r}GQ|*9;VMTZ5vNwBm?>903~^ehVI+d)Ze2-95(pO#NC18nI-^t<fz3W_)GcG? z8=F@)d#2UPDhoD`#=e1AEEWe=ycrAKqEmb{ZltYYIX1Q1vLIZGFoOkLAikBpU<?VG z9AG_K5pnV$b^_Ve(T+O5KT(2rUK|!PNt~pH-3V+io^BB}B(+4)%g2+KxI$6rE*VPD zyi(G%Mhx&3h9;83Q10%;TGwNv!RSnRX%5qqpdPbUskgF237*L(oCN9y(?>0ZGn!Gz zh@wZnJg%P08upWqM0SP48g<eq7dJX2%OR#enw0k%Bm3qH83JE!T*UFY#fj|Lse-Ui zCkQb>+~@U&<++yQg+Uv8<<sf&`J?%TyRrug_uhBV!M^55v1KF~m1V>jj4c)}HUQ}y zR1}-_D;dm>-vQ1W5>KGJGhr};CErM=LHTv##2e^oSNo`(gcf$j#V4l<&u|+AUorQ= zZf;3B4Mxw2wTdQ|GX(Y*5-@8(Yg?_64#Ft#0bYubQUAdV%0TJ|nMr$;Y~<k&KzT(> zc+L~r9$?_2UkR6A_;#T*LhNMp{<ar=SlN#E7*6XXeZ8kR#<26~7jCJYgtCWBi-C|B zf=B8NzO2!s?uwgoOkZ)}STv@!mZTEhKESF>M2#2$$Mtl9evzy&JwTr!woEp@$kyp? z&7KEbh9SUp(HKNW$jI-mPnA<nHj&eK`Z5tQq~bQLuwCeh&#}qjxm8xdMl12AN&c_= zo5PJjuCqQTW|h{jh-k%!wbGkI^Z~#N$QVRfa@)jJg3u<;lc*$0OQaHoU3VpxTUht> z-B97*HuCJk`M@?u?zuL8^|I^Bo89`OU?Wm^?xEiS8U;OHZ-y=fuolUOUK@^+YN*=z ztsr6`aWl(W=~KFkx;7eO>ZZp~z~yaUWH9CF?7*Z8|9E1?T`BO;5p>#nVr$BNv)h%( z&v$ScA1zr_?=1a~Hkmr@i`yQ)6*XiG6#@L~KMBO{;oAp6jRZeB9l|YFCyxXM!aJ|8 zj1&1Bu~l!G0+m(av|*Bxop_-im=r~o04~QWz>Q8@LpzGIDAM%mr;;7IWnh>24+B7U zc9K-+=4Y}L3lMXZCK6V?hXv1^yG;C|LF`+MXjaz5>s3*d2)uUS_IP-37AKIoyVu4? zsTf73CmR$S%?ki!GgMdR2^$K&W0z-shoRO1Qj`r4Kde9ciniun_({_w4q)~E7nFcH zfE^T-*In05KS(sF<G6kEs=C(ZXIbiL>08J|6YibgKKY+tD)4|?ENz8Ynifxrs6}f4 z85pr=5lJ9+W6Pd7JnURjM9`H)JP7pwe!el?mcO4};arH}SAkrNrexEeL?`i)Y^>88 z(j_ch<G<LE*h_$$Xp%D$5T8_JXF=sG%Cg-@RjX&2#KkVCF>*mtunyJjAQC~@eNRy4 z?cn#;M|p^$gP<-T{FvnJyx7cFyl#E|7d{QB)&%-uqp^xGpcYNiC2L<WX9c4g4oez8 zh+qP82IS=~w1xz-lW|J;WXKIH5Hx9{i_1nYkjtBdl&=!TBdaX(_-0!*<FG1<6emL# zNN6sAYyuU<D%ukP5)afugnV|Habv5fZ~l3CSwp*djfi-=gVvD_w|Rvl{LQNj)uKKA zAFD<9|EAFD4iD$dY0bzNTMgA{d9!6uW*V^XruaD?rRnwu0yO#UcD=`5VH?6Zse0;M zBxFcY?9>|R(TMK?NmYhuppb)aKWlFV@Y=o8)7qCOu4IB`zXm}jtxx;~hFgO&2jP+> zxTxV$`6w)FN!I3c2C_3J&B??$ygt7Uvx<-<gjJqmG((>1;K}3yyr2o{bhI;*E^&Ya z?Zt(jqrJUF$0{DK1qUsk^ZRth?JR*|^E;Pep|)pnkYkfx&p~bx7*mJlLLVG>He|bU zQ)HA5_N~FL*YT?nn}_sh?*k8X_=D-5;ncGijPuBXXd&U0yFgq8<7RbJ>uO1si;SuP z*V)Q0=-UN$<Y}yy$v@$bP%)9Y23kf}T2AG2OO6a|s|WQ5twDuZ*Ov?o4JfQBS6lI( zux19+4sGv|=@JqfsK|7zLsE+@r=pN@%tD37xT6?<gE{TTWTS97Kg0K);(I?#Mci|j zC6P>gZE3KQ2?CCgBLuuJWy|@83|`<v*N)WDE)Yg}W_*W7?@b)l&5}wx{f~E;S0cfv z2a*%3Us`D&FY-2nL}S<_T-ru;%T%|w%@vH%tk=G2qn=BLU3&}~BiLD10T$gL`Ob8c zWLK1%!xtsVzxu~Y>`TM?s_Su`ZKr586E+s^Q)xi=srHyymY+E}QD(@hk`lgviRmzP z#;k%FfRNY1QSwy^2z1?$LiQ**8XmVi)O%VMPwP+_L8}?=93HERBnftL9p{QP*XZZG z)2d1b98RUq17K4coAdlX-(q+<Z9(K-v!Gb(&=^1itVoiQ$zQ+$w%n+`Xyu7TG5*Ho zE~Ug*Q9>rZ`9rBN>9#fyZ(FiLBo4P3Kv&CrNOrnBynR?*bi2LYS@)!OdOql%oej=U z(E0LE{o6C&31e6i!8W8g9Etnl-vP`P);oGMUyh_Bawmf;L*+KTaUqqW#cw3%Fh#QE z9v=Cclor!c8b1WWOg1@5Wq?T&lQ>psBr-a8xXi%*DTf<De_xcsKks?&JMf4&V#`hE zdP=!HX!XmfwKXV{_MUIn8(0v*F`}105D`LLF9$#6cD_^W$ZxF8rTquC7$7^9Co>rl zkK5v>n^A7s#R!Urjv_LHuGy6*gRX6_@c;Oqa@`wSy0p)=IEyzIC;X$5NzOnPoPvyC zA_QZg)bK;PT-!ekhNe<MQWRTHi=WrK;RAwUcX{knTWF<tEOsDMu==8}k>a_KzmC8) zUv)8i6;o;>AzN#$x~4iQF~9S4z_Zz<JOw!$a=3ErOk|QY3$UL>LG5}Pg>rb~eG)z= zT7;~Ncz+9_5AlUzOl;gEI#*D^Mvmbz_>Tab;H2DwkedGL4+e1xYmXMo5)=IG<>jCL z_=i7A@^8RB%P%!@;cT$})3==^8tzd7l=f(N2Yq!Hky7G4cs;yt2?|6!R|@tR;ZYBQ zBo<X;_2Qwd)XSWyckKMCK&S`5ylM58GyxH65OSD%lYk`vUBNl0P6|XOr^)z0M>K2; z6H0V9x_vY|X!-CaJd)zk&TeJ>_5%2C&};kRnzIZw3#NBqZT-;hj%W2pp{s9AEX5Ks zkKTajEkx5~LMuwnb5(oRa0j$Z$J34HN6a@{?q-Y8Ev=PEEC&v&UT_e%J?c9^Fo3!U z7_Tz0;cmSEh+A~-K$_l8C+NM#<yRy3Zn|C03w9HKKV8kIlXKEzFxo@<4u8s7K`hNd zP1FEwozO`8*A}-N8k6`80I?*(qBo!a1z3_DR&oKnKXfb}nFQwyn8!I<(g)Lm3aSJG zQfgf#vX$p{APLQ+9a_Yu_8hefHz(Ki&l#&G>mp1MqA4&<F!MW%F!-m)$V%dY*WNJm zMJYs-CaOyr0x?N|w&nJj8sRE!lH~rFg)ymAEj)O32m?eeR)?`UfX!cM{i@DvH(ewK zrB-Okn4V1qGNTIx?l<bfjJm6}6FF|deM?2+P!wqm+u}q+qbPLbTa%97#-369|JHt@ z?n`acg{@vm(M_sXg9k=1!_IQQ*dZRhw<}h3*yP5wq13pF{2uMbvo%5&o@W<9SCy4c zX05#j&Ot82`P*<k>yH|YfIdvttyYQl;~fSv4~Hm6{+h#V!`g9NC3^5q!2cI5443&z z<xoKq+m~|{7j9Yn3?rV;+^A){JZa^2NGTZGiK2s5<2I434GXJ$*xGGH256BB;n15A zN-lPFVFbiaXxJH77SuwK>i2fP*>z?!v_6ZAh_5y;(FmE(-Eu0;luW#ui?;;{e$P^- zYyE7~c&a);2QgqGq`Uq*w3khAZ|+5^^Y8_=t*q2$*vv529amn9hMLrQLHx8pyMrSp zE08C~40k5M1~9pZ#v8?S`e8EPYPcaPa6q1>or+T9K~bZ2YEGp%qMZ*-lVDz4BGmdA zLKX{Kbv7nUhJk_*4<Hd{^kOz!a~M(fX474FrDMW5q$8>G3V<yTFR?)Az!^s<6ONGh z;KU`Pi5Fan;dODquft#$b2>n1e1LwT!o-~wiqrs59^rdL>fD`au48PD8k1@`!V(QY zzUCj{K@M|By4ZucG>mGfvTTP!Ju@#QjfKg;d<l?327#sWLtOP)r`m>wD+{e!`tQq2 z8Q=M>(QIhv4lyz(Mr$Ju157ofFsgK-VcpnMn*?d1nd|sQ6|anDYh(;TAUPvl{8G*} z(SfbjJbfQ6^8<<w4;ttkiJh#rC)K~;z}3>e;QOr@G(=WK^}!_nlHjTt!EnmSdd~@n zR_<e_g)$C&`Ox`P!g={bKB7E;J!0Ow#~xEM6E@qg956>L5^uxOhF6k2{!8^AXEBE+ zXWTu5{Uxg+QTc~weHvu-W#}poqB#*E7mg;gT7Jfzh-OiuqNu^;Xn~Q5jGn5dj8Kdl zC4q=p!s3ShA5Pryd)cJ**+eS;j|!%-uQiR$0$|u~2t>9usRnWyN7UG_pzDUVI)Db4 z@v+fq(6vEv^HOdfv0yY-@<>#?IPIhEiIRKmU{^K&?6=myiCh|_TTrwTF1EiR9*ZeQ zBanWOqhI@eO@n^pbq>m{0O*aa@?m+xa`79$*(U|F^u?Vgey(pH_~={&4C?S-K+gz_ zjH)DLT%<2{Lse!3MQq%@8cRnz8&VblcgSRlwS6}Twj7Xx%|boKs%B_joQ_=*uCxNO zr@1R(Cn0S;C3nmjO3fJaFg_&dwfx72#9a~m5`%sjE~0+&Y+M;C9pB5iCqwwejfgu0 z6Ypx9$V3*+U~-s1_JsEkHcIV*Z+@YJ<0J0YH=VXvvU7Ta>g)VXZV6RYgdM2r0^kyb zPY5~OVh%JHlwd{o<T|0lezrk#&29mT_4QhDDuGZ{8!$=<x+nNh*i^%Y&hMs+4P>~z z;3CbGpdxQnHE$q#5H@~n<&vAJKT^?2Dge+j5o32$``7)hMAy-)q{r0W@b1680Vmz0 zcDjCs(op8W(5P{Zg=axj(Abq0j|^*R90iFb#07&?mEN&tO@vN*^0i8*@))E7{u4is zQMbxRwiU_>hK~A+`tC=Fg_Ntfoh7QHobo6r*TME3oAuNjjD*E#XdN5DRy3?b4_o=< z%T+<-V-P&tPIbZ{Oq0}C5eBX|JDHKF3?iFz)gT3+q@GnkUxAUULn}I;tjscZt86Js zIu(K{1U(U@fBs4`7DPoLZ6NJr_U=bRZ^Yl~rE;@1>3_uVI|!VUD8-ZJzf3pucT(=7 zWhM{}FR^DtB{CI;XKE_h+Bk-PJb3sju$9$E_v`-Lc5WxMLNJ}`|5JIBW2$kiF<Re@ z)rc7$m6H%LgBQb7F8WBcSqLN?>0>lsrDRSiR7My86+gB??q4~FEqN@sK&G`A)xmRu z(j>I_Sk6V(5AGWmO<()j<pPMhp-&~2bW6Zhp>i%f8uCkGW+I)5fE*$vJcyn^C%wC~ z`E;S|^2p_7T>xtzVE=;Us|`?IVByI05vGHck~Kw6)`QTMj<+xxUgOnnyPyJSK4Qfe z2{&mpK8c15JOW552nV7j626sk5y}_pea7jm(*JpHYTvYZD8}3>&>*X=>|eiewmbIh zWzww9N0O@65Za=19dPZ<ePR=AU>d{02i#({DB>gT#OJg02AhS-P(gd9vb5@&dkCFo z^V>ao@(|Lq>T$Eb#ZkPUF6`R3hjtqh@4Zeno??vxi*Q<|F1Q*OZ7~y5*0dHKgUYil ze!qn>u(?0zzo3#euCi}*@RJ!3k^Pjznc_h5a^c|cQc*$_^UB6JeI>r}FgtPeX--)& z-A!^W)45gCY}a=I;9FfJ5-^6sk|>{*=JMQ<6vy{Ksm=>SS(IK)Y93(_F_h>LJpz$Z zN?FB(eq{jw5nt!UkLwo>trzZB4bcsLiaLxqxe!$4?!DYfAJ#P=-<z6idW&LYABsmH z<Div&(!t1aGy#F@RjfMfUXX`9bd4P$n+`I(q5v%LqAxdZht<oNyL>8NJ9+5F`*Lo1 zv}!GCpZMw519voiKSC(Hk}w>yj9lcfciFTJ7kyPIDAPWVg+R-N=B#{Bl%&ke7ie}P z6inKb!Soi~wId6aGT-=us3*D(qj6-!18e6Uk<U9wZZjfSqy57$C^aO<2IChwHPwdD zkvpt!jq%g7aI*DxN(!McZB|0GPi`Vs3M^c0<sg>&Q_e(N12(bYhBbT4b|hkl9BOGi z=;b~B%2rZ{YDqa=ktq?I(3(4jNd<8LOB~8ZGpsMgZnU`VaimK9e<YM+QW^uuF{sE8 zKe9dP&dwXUvI^Uus0Z+;*px1P=w$E!liigmMrfD8=w48agiy)M&L0Cy&q;FLplA!F zger5#DcK?F@8(yc?Gi$>QM6u3bZYJ8^UVO>xD=|}V{Sp^(*>4#$4RJata31{Ajh!9 z?Fzs(6EJob5~lIy!PHk5E6pMTLvK}9IuBO`7Oh-+I3sZdJ?z5=`Nu273fD?ykz?;_ z)y`}+o%B~SSNQaDw-&JU?Pvn-f_{^W%AQ#rh#D>v>?KG;Y#tMoS<q#w{7}&5ot?4= zv{GO6GLMy?EvF|ivYs;?$c=L!P13>(Up9;-sOL9{1Zn#ivYP-Wtt{Sid&9AAM`mxG z<q+W9u9tF(;DKw7(F<;NMeC4(i+{rlSCa0Y+)+zgCLFqH1JXlMQK7L$p@;py$Kd!K zyXraj5>g>D^-_dTo+mUI5p%F24gGc4vTGSC?$&$pLg;M3WMOs(xNTt{i(cYX?5KhJ z=)qEQ#Fs?ji!h5_!9kpEaa9a2T<h$S&25f5l&$oCn@(2K0sxiYPrEgS0bOjzX4IOi zv;^iF5a`FsuS(WcVItH_mkaGP5Em+=qF!gh)z+d8gg9dn;Vo$bTaJn25nWzNvlkT* z9sQ&Hk20RH_Fu7>f$=<|1mL@eyQWc{Qia{&+j$@i;EBEH>oJT#P<e25K45%Sb@`Kx zr8Oheq;d2oD`h&xIK3(6S%T<>!@YAOSR5*WzsE$B#pUJG#VzxDq#=LtnooRgZur&# z$pYz?z2pR-2+fKTjg7Bt)KU-6`U{&^KD`CG$<N*6_f`VAXddId!|?^XwX1y~MnEFK zNI@UEsYziiR31TI)x{DCTWqm7D|qAz&GNLS?~(OeXzjSp5L}YmrR^82wfv2Z!|}E< zS-Bbq)A(y-ik!*&lw+)11|)XMSU3b-RA|{Afke%}T(-mW`VZ?4M0gvZ$=D7Pkb%mO zqPjxk{HdVv5b)bTM0|zRSC3k27RbhpDpid9=kL>7N-LJaWQ<C`w~t2-*SlR=4WSw% z3E*w{M2L}~>fW>e(|*=yGTQ9WEjv78Osy7HB>aThX~9M3wN*UuOKJRxEnSG!#4)y1 z=-zq^O>}A9@VbiDV3V+@AZ%c4pIt#|IvEGn64<fPY=4?92z3s4k6JrexDu?uZBS!E zziWX!6Z!QuXQU<q>aUD6B)H@OKPR}XNd!nnP{2s={rY+5hwWSf7obQi2jO+4#&=p) zQD)ZAX8|7tFzBQKum*^Pzq6AeG`P}hRgVo_tUs;_@dz55v<Xg>hLo9h_sT_&ilHFp zpZLi&c&74eYpPeqS#etsVEJl4m+cu_KqEsH5Q3YQlHJ~swq6j=7RAX<<ndHBoOLI> ziBF!Il(%)RIBa?|f)R*(b}9;Kjzq}Tb=kyWCg5;<{}Zm@I~2WIf5!XH`~6}*T1hX0 z8M}r~st-j?UQuqg!pU#FN5cj21-vOTxy`6Rv2{Cw#zldgPFm+cF`ndOs<k97Q%v-H zF!OyhB0v(?^@xVx1<q52;slAU9_n0gQ^O&oEsr2=ve5WN4NI<nbj;GUsrPT+gEsZP z-@WKxoSt<rF!t#}AB6+c<ehw2=@Q3KIv&T_pVcGb2&RNs&c6NZn!qdd(tOWQ&NL0( zmj|`hwLFShEtPBsUW`b~wmM|D4t{7_h$$7hYHKkK@1YI4upTMGXg_B;0j>l)Q^lUz zQOy(*N$W1d&}LwP-*+D5pme4y<~SM?vEI41p;EGREm4zwXP4m0!)7NWtdu6MD36)Y zB;-I~^dpIyUv6;OryzrX)$(N{M-<*!JJ>Ib*2Q!iXn)`xF^=-XeDhJ@Dwd~Gr@*HW zd@%+5kv5uTLvU>+f-9&{DW?0;-|nO*N~sh{l4?blTZ;+3HkZ!EC4ELbeck<hfe~R= zdX%pU0|Yiskzd71Qmp@pJftz7jq-Yr7?75#iOu%)0-9lwgt4CR+O)W-MKZ8pfK%#1 zHgZTjP@<*fv>4<?X;3e|D~c%;eAX++I9cY}U?hA=tt2(`d**BIIm*yP1lSZ7Gdqg9 zyz%qBTa403S(HkbKDLMLz?&-PB-i*0v&l7n3@=f3TVM(#q<8wZ(alDOo@4%ds26lI zY!M*)(U_Z$=t%v%x`;RqsfbWS)odJX*BvDHw>(8OY!a%j)fb*DmSrD-pINs8w~HCr zoDYmHemxhh89xbYK*xH|h8HO|m-C2pfLB6DtK@jy9Dmxr@CtUj(pXiA{?QO6#?Q2N zKCR_mB3LTEm%8ThHx=$M{?4?g$&QtmBaYw~8o@)69#pyD=RY$><49ES_7#8a+@g*k z<cvG0nWNF(#s`i3k5g1b>;ch!?eztcT?+M0aMhr>Gt=@|F2ys>fC+7ZEg)P_CzH9{ zBc>`K5lQ^VWnqDF3EnS&*1AS768vkOGD%T6f#WNww?FRj{(|l=+F!xgVW>6>DG;F( z+@;1({MeFF!@re_L&=1+T?wM7DyUEN+@pxq-<9ds89Q-k;Sf6mh_)j{F*tN9%A`lv zAVu>4vjf?>=X&6CgGwrkCyv{SWp2;2yN<aaUrk1|W8~EUfW8w*?oHl7HPDulFjq^U z<u8RHoAX-=$&W4jv4~x#-Uf>vePBK9%ugue#>A+D_<JPvx1;59B-~B>iI0z;D_6hJ z@?gRPf062MB-<m9`5E<eebj{g2?noVrv+eFi&GmcH;&E9weI=^zBPC64y#ch{eO<- zI!z=0ql6l>wZ6MHZmUK0{xw6@T&K&~WZShTl<g^)ovsFEe%M@nD2oEU#y=uaj0RXS z!DYdCwAkE@pa?oQm+s5ebJ|h{;g~7D39>dEVRZUJo)=5E>0sE%cFh?++Le~G>^<48 zLEW2R#t-OIa`DYs520FNkW`fwg2O)?PRRB&S3qyzOOq4hPgN%hgUO|XApbbVNSx)3 z8Hs~)qlhNTHmK;|BZ<8MEe;8Rz>-(vF|N@Pe<h797>6Bc*xRd`uoa{b+JO+sBm*5X zE1XAt)l<~aMvLhnze4#0^-r(>bUN=8UERP%IqPBz#-603*p{+_qlS(N?wAQ26*5XN z&MJXr^)n>S<YNW~x};l)IpHUhsq52xH#aTSHtI`28n(&~mJa8412pnSZOFnb;AWOb z4fI10El^SXT<)yBE7Z;rmZMNJowy<HYPnP<w?(ykFZ1H>&^%*+jqF71rkr>(4>)Dr zDp&gw@STxb*ZXZ_VT6l-9KagG6heuJ86_z*C5w49QM_b~M443v5Ovu1;@Aye(aSbn z=hO8}rhmIoR}awOQM%{u!vS_IRZ^U^&2UYHMzu>t-_b5cg|hisi$Azjc2F)~&?Z2? z6_qf|kCTQOHK4jsK`hlHlP0&k2?pNbAhr^+^mUq!b)$hzV|6RfA617rIbF~KqgN`= zoAu5A%9Ua$g{4H$2{ufRlq(D{gfaYi^fUT(u1ucm?ePIUC=i21k$C7dz5mzW4%()K zt*(H9=^9pPWVWvovKDcL(zLu}d@GXtxZ-WG>UGafF>0aU|37Ock6=YOe;NORu7*6n z-|bNS+)6zE<O|Sp#@j$S4{|zSyREHA>%mQG8aIoefD$dFB4nc4@d8ERxwN~-__sF7 z5QY(f7rmZ#?ZSwzp=H*njt0m>K&D^AiIez$NgO>JCfMp>7=)z6d=WNC1BQtp*nli0 zBmX5<>CQ?0!BValY{0e`*|BaB!eJ>;UER%D&NKa@@ETX>1*z3H=0Ba?%%Q*u6=;Q( zqw>244nFy&Xhc8nMKqd^VHP|vh><}7-Gt7h+)F7%eNRC|HNbRe<GFGDY_%|<eN(ny zUm8qB_%W$MsRoy}0lF=0N~qhMav*7iUsLOit8F~>bfZ9l_qs6Q6hwXzMagEpJX04M zCWGCdVJJOlW3!8zJgBh^$Pf%rTEI5$%Zk=~XmfO-B1y)YZrSFuYE;)YpEUi;w@W~J z%aGYo1^-h9sY!|{st>|B5upyLN*Z^hQKB?g*BlYBtbqA}a=4nWZwd^n2F>T7jc&e_ z)eWLm?skPn_GYvL5q$gI0(7~_<MnhWtkM0P5<Q}tfyT%;zNTo`rW{!xGn@upb7EB5 z8e6suF;0T%U_ip1oW`MZ)%38svH-5^^$rtlBq=Ya;Q(O}2RXSR7ux*W-wfrTojk5o zhiT_SD;ak?AFJxcdLRv&a0c9g6l)2)>du8^T(*kKeh(c_$q&-acZuFboamW3O~L#` zu&@Gj)<>r`aCK{_<4|<Sg!BX(RAbl@u|>nM_K0<^U_Y2nKqcc~Isy0=|JnmYizHPu z%L#HI<mILO(WX7Ae>W-}B__Gzb;a)T5~$JtkqaF`rQ2{(CRiFNpO)s|RMlf!*aa&f zt}0{3u^1?1z$6YW=QohaAz%LL9h2G&a~S>wNm}_E{Dp0Pha}vIzf8}mBFnrbV``i- z0m_+1p~@_WR|B)XM2J+mdeev96ry`;pys;?I*h<(H)l>gCm~|_7e}VCe{c0tTjXRL zf*s<)(_Cw#y0+!vkBRb1Rl8S*DX6@f>ZX`iR8M2phcEoiD-ZlqW6}~l6h&2ayld&8 zmO!GtlAj&PAurq^OV_M@2jji9@2PaSBpbjv$KfKVb>+D!)}C|RF!b!Vllg3BB;?wA zV2H*-F^~jE*&c8C58x6@hfCz&Pl33v8}~!YYWweak^l%BlawjE#k>*7IS#1Ks<BRs zCzhD@V!oX3pmQopSQB#o*v7WP&7!C?9j#n@)=+r;+0|xU?sJRb8P&(KlK9wZpp`G( zl2`(Y=_u7FeUoemY-(PTMGHFYw6EQ>)~8LrF+fsnzTT0<c3~Kwfc_r}<U>Ya)-XX5 z9=yaz3)rJbJcdK<`6C#cxbM7I)@VuC)LJ}}VBA6Ti5x4p0%g;6V8OAB^bwj2#`iw0 zywE+3!3Q@O0@VL7Kx4jkoP%qJ&p5#6>Dyqj8<)`625C*Rgrj|nx=wWf3N-SAyv0Px z;qKIyD#f~r4oKbbqwIvYS*hQ=X^v4EY<@X6V+`(@Ox6mRGtsR!e+RviLBM@o7(JH_ z><e5yPJJ-}4CPo+O<QFHCF#mK{tl4&?1aj2i#@S7+!`64As4(*c~w=Q&Z%?s{yjB6 zL7f%j7My^(lLIV2DXePRWpS`=$0X!W;Eus5Rb;=AuJ;5dClQ>bL$3OOi_iUg+$fcg z))GqK&r`5&n<Lt!a${O#8j%bWTJi|y$@8Rwj@&e7*n@-fd$=k+WnUU*V(4Q&e+**F zH4=#E`9<Q4OT#&d+824%47JL#(d2#vo&-l;sU({}PX}U9Wa^nTtyrQ4LNvspkRT$m z2J9a?u?!xV%|q5tL$pZFDeJk()GVrF0UapyT1CKBWHS=GO)0jT_wRxf!v0}tAIh@e zf5EoHe}Z%*L=drObx=oBFWPKwuB|q{*lGJJJ#LHNpCmfe>P*Io37!P1!Vxnf^<V@c zA_^U-b&yXFaohxpWJGnQmCxE0OnhHMY|5>vC(n3qV1r8ZR_a;ioJ`b$&OpdV@yM(S z!oX(-*Z?rR@Gs;w61<1n0Tz*nf8aQIncwe=T_AT{ac-q@STtlR;ZQ#x+QID2$T<WG z#}>I0I;YUi@^4;A-RhO#GLpgibw_D#S2vanO-nFRs?8y-;woZd=Q_WB{mLK~>7YTO zsK{hp+<}y7wW5W5Kof^ax2!MZ?1Z@|*N@>UcEy4orSY1Q72w^e6gWrABIrM1V?p2r zqpeyDC-;_EnWF|B=AZ|EXWsdqvc&RK$4m#8(-O~I)l-LP&cF_8#dOBKvCO0#>@0P5 z7f(XBIvR00d=GL0irS4;2M^EVlv?wAg$n-?LMh@kYHH0_Akb}>qVbIO)JeXcsr*t0 zBzZEGg)lE`Q_wGn`liTNyys82RyI~;22w)9D@Yjz2POUb<u#K0SFf_QOz8wRyFeq- zA?-kabrP1d{w@h7P?D>)h=gmq%})47T^ns+(L3TALOR0H<Vqbmh{<Pj2NPX+=-%xS zrU=Rx!AF)TmWkr3hdUBqh0pbJ!W8^A5@`pIf8&znaSdymk~}w#Y|_|aQ7o)YC?%j8 zMxFd4_=r>R9jVMk5v}=Bdy8zWDd@Ln5)hDo!Ej8=v&40Pkk(X6YKPEjdj}F28x<>h zP^`d#MZFn3rW^1ScR=8cV1ooQJ;-&U{iy5f1TGCsw(z{*)v^;GUhs)#D?W)V=JESX z6Lm~)4%P15Od)|OGHuA##~IIQoOqr583UU?k+#k<SONGR!4B5U)Po!R^0$|le-iqY zq;y7HjkhIw#TSW3axC0>2_H)iJu!W+$r0_M>@VZg92<Nd{gZhZLuxG+Q|R-Ff=)<~ z90=xtx!<FW7B><xQ953z0~zr5ckAsgYU(yWOUd?@z9msrlE?fEeM{BXaWwZ<_8TTC z>BYQ6D4+v~?=siK8LPUXuDBu7#g+}|ez*e$ao{avN{YL<7~O_u%}cvxy{MdgYr9tP zbuQ#T9(u+BKEN71OSooy{A0nVnV>9Ar!{;%=rTeqg`9))M4S{@Zn~J8Z)4reZra}< zJ=70O6dAi=kqu;JXuh2U%svGE&}m#vx46hM#|dR8R5-4q$!Ot#E$U-^FQe_kzeT}O z|B|)HW&U;z<Z`@Tf0$3<>BfaLwcwEGfQ#kLZvAm={})5~_Ez6a7-Af+`5wZtBeOKl zwkUv6><h=%^7t&$BWI(qHG*S7mC%%gxavctBl0~Zh{qcA`odK>4A@^yM-YfPP!CLL z4ELny6T5-xn{DBJer8?jo%9j!u^T&3I+m5XjBY{J1G)r|Y_lHU<>UL17v!@q(VZdX z-dhsY%@I}la~CM1zW^PtlhIaW&r8MzNo$|Ftr|yD9t&G9o$(cIkW{0pJ0xFT#YQt` z^6x~aP6^TM9J47i`ePuT#fBLOri)f@Lq#kE*TJ-{I`FP>2+kUFAlGU=h&!fj?PJFD z57{DJ5$~_y0*!F<ppNvkC6aG}2Q7Et?h?!@ly<4N$b2;)y_Rv&NfGtrUm75$$WF;% z5JW;CjrDBUNchhbthJcXo`uEE8bd-(g&4@{VxTjmkG9rWCG{Fo!Q)+4>@*_#9Dx)0 zKrfCbg(c)ec_ugU_)KX4@^w5*c)OXO_MOD!XTVbd-?~94hMNT>_JF<+np)ro-5eR# z61$LlGwMN*;eiicZ!w)sjjeZDN!UA)#|Kze02yr9pRC8uxlXBNTJOeeRQjgM6&2Q+ z@qbKq`>H)@9r4wVzvja}Gdp06%2tTIM@0fBF?7Hy&}Z2l0YzRcgg$e}(S3Elo=;x= z!DM6s0nVbPGVzkx*dPD!N1lBXchzy_`mDFBVX8e4O)DZ{yQN~Thj$+VB6eSe5u>#_ znkJqd$_4*__TC0guByBrpS%zP!~rxaV1NZy2oU1V>`Pt@7|1TL5<+AnDn=)>yOZp| z?#{9^n`{t~mxySiqDG907Hx{?FIB72QcE>zRMb?hMN5@hYEw(w)IZwPT1)l!ea?BF zd!Kvmxp!uFCs_ZV-${1v`QG!~=e)l^=Q)i`nS+Fpbp%iD;E<UarJIxQRx_e%E$Nu$ zw&FO}eDl+4H&t1VtyKlrT6sz|#s-nY!d9x!2-OFX!T}fA2!tAwB94!l0^8gbo1O*^ zWvPRT(^^z8N91{(JD7E)D=ZBcl45=OZ&_uq9S7Pm0F97x?Y*N|9W4*qOT2M~N?GkH z(fY4+M_Mx|je`czeo?)lRU5O>!=0RS2_NMD&26S6TL^N~6-Me=Ohq?NqSI}#a*u^+ zb)#Rz>PdKydT`D^Y<8q}EmM1F_S~>3k@W<H@;JB}bZoTNi`&P7%{Pj?y&N+r_u^fA z%g)M3+IB9ic`2LQ5LJoIe7HbObDLd@C}Bbp?08J`k{s%4$14@SXs?MgR4a}u11DK= z_q0UQJzQwpd?QR*rJ*s+bTYTvK@sGC%!Y}Xh9xM1rU|~48LmYYKhT)o-1<<cLYg3$ zaRdqysyK>hv?AEO9QXQR5;YwfuWX|`vT;{z^|v>*N?KmSs6@K?pn*4|5Tz>g0$Sie zjR;G*cdXP@5dotZl9gm&-8Hrhigz5UKuuS@@L7G_c5LtrM+Gf(g(e1NXfqkNtAlmg zKs1}Q7pKmw6#7XonZ2N(SgjaQTy8!>O*mFTt5unr*dR1K_@YY)?VThv?MIvM+4I7P z3mb5iYT=r((kPCNmZ+piv!)Ly(|94?I>*lgME6?2%XVxyQKv4&jcHgWO*LD}7+sO9 zQZC;Wh0CIFc_yW-n~pEIf*k!EEo2T%U^g8zQEb>kFA9%@nzYFNJ9wxKt;sgN=PDRO z`I_@YDGHPtEWTRxdLpF~8(c-#^{D$qjey=6+WVsAtMI7H(b|;2kZR>h+qAD-xuJ4n zX;d1W*!9G@JPs4sV>xER#*@K>Wdf)xbT3n>4C8u=%dbVP6^T_k;Hqm=hiA0iT&)Pu z^djR$HO-ZS>T3C@PU|(<lh2XB-e75Sabg%sA8_)%OsAJ3@kyFM@}aA(8Jd{VK6zNN z+uNcr7lrvK?1;k7D5N%m_WMd<g@)M8=tN;)a&qO$cx_kmLfjqM0R|eK@Eq6FcJa)r zOC)|POolgabHKBZMoU=Heeh5~zJu;aM%9{H%AhlL8nNUqJ2;MJi%{g;MI%SX>B2o( zT;Q?Va#{OD>B1gdfh0gpE8esP!1w`@dV>uNhK%;dHH8d%{8c#~UB*^WA#|tjxr~fH z&7lgcSPkPM26dM>^}}t2GRBfyAU%XtR<rMD2Y5*LNFncNBiW*a5ng&}$Bw;ZYE#O& z9YY4)Mf#LG=o+xU84iP#EH4ri8*atn^;Z8KMh7)I$mOmYQ!%L1Rzc>tJ!qfoAd5yY zO{{|XFjQE_rs`+PgcV1g@hB~#i7}W0MupxY@`eyhu!)9k6VxP@GsHGU(VR(C!?%Xl ze45(}HL?sOr=TJ+TfuQL@iOy0$ei%P^_Wxwj9bc+=IzRrBT#dP6%wdX3|<!a&T+K% z7;l<t%LT|XFGB1a)h{zvp))E2=F&S)U#Zn5*zdy)Jx5)ZS+{5lL*O_Y?Ns@^fBhZb zwiVi!`5i?NmRIO|)|zutT@Eo;TYA<`=Gu%g%6o?~HtWDTaIg?i4W_|8H_(9CoU|}M zMgYolh~}BuFEpKP(;6p?$S{5z-GXf^Y(3GDP+A!xWgoUrPFi2_4160D7ALimXr5^( z3k83;dJnoatl+3=AlgmoYd|u;N-Fw-fm_phy$*ASK^v_Kl{QoRVEbK}+_@VW^}0l> z&_t98+7(LNx|b|=(K9|?8LuOE5w!2q6>Dt#h%UBRCv6I-)dOdteZX_eVzmFES-pFk z?Ql=W&86`Qv{InpHG2TK%=A81TPaD0a~Bj}x=r08!Jb=JbcaM{!E|N=OTmF)4h?rY zY{~syZ1`~JIhy{#DstLhzG_C2f&99svdf}n*yPih@+OJ3lTs%mJ_}XG6LhBEzXa2F zS;1=6HL~CCHa)Zt@E{X&mCe-t+epPmqu9cZ+$U><rifORc;9J2jCQN`E*H>3+Ln~r zZ5gGlxN0DIBg?+5?oBQ#!Pp%tWh)a^G`d*tDw%^04SI*Oq`wWV&N0DDED8h)nuEnJ z)!#cuF8n7}&E|2mt%&W6K;A-)Rnc3R`Sgs3ki5Y~HMf%|D#1W9x|iT7{tfnZVeJS~ zXv%ZH6~Q4u?unW=NbjmnkeX>y4-t%Aq=h?bq8t9@rICVjeH^zyn59F&YZ<GGL<;yX zwPdkvn~zN%3*@jAip5VzxyUi<8cx&D*%}O9NG6NUplqfAP0%mP2AX?yubJylZwP_? z>e!ZIeDSb3H`GDWK3Ijf(ZXQg=EU+52wFpsgcUP4EvZHFlEp``=<YO~xEAe(3=1Mx z(FEcGZwy+E4r!{wU6(|*p^QZE1(&GPa1qs(w#7+Qd}O9O9(fA?EkP;QK+@&~i3P7x zI((><po=i^F&#%BNL;VOk-Z$8zojF%#7FfR@j)4eZdfL{*~q)PD*|rGtmn7s>~P5+ z3Wiw{v}>9(ZiL-Kg@_if{kYNd^}wbBb{EF5fYisE7Ia_000e%wRK~Yk>DZtgV^4pW z)P<XPL^_~6sZFDqg_#kthG?tM2olDDv>0}FLebP*^s*Nvu6^{XsF~4PF<UDOk(e3N z@4v!}^=zRHBq7Yr8YYXlDow9ZlkpI^hb1{hngG*wRwHfN-;$XzF1sXCE!DR6PngkX zBrjuv8JFe?kUWc);>Z{IuHgZk2&DrKI9LFl1?+@iv_Fm&*j^=R2KhWRk>-F8B}1&a zO1e<MO3MX}TW~VeC<Q@hGK@Q)%rKHv2UqF(z7jOUgko!0c1TNhEL8M}<W65<%W$Q? zXzszr0NQHTAEPVK=vI;(mOHR;Y88Xn?Z$|DfMu-JliGi}O&sT;NLiIMtXiut1&H=5 z^KH>-tyNCeIfk8r8rF|0=7dnE>A*=6Z!`3WLCISNyv;IZTpL~><!yBmUgGXxKC^4N zHlLe5MoiHn<kx=s4C_VCMMSSrDj}44>zYv2Yglo;0uoKtnKCA49GW)na2EL@4bd|Z zAJ3qX?rcGw2o!#^wkQ7`-OXNvUK6fqAT3P05Z+6g>mW%CGZqh|f@m-!2Tban3b7(l zawsHa@Z#&S!gIt|;aF<sR<%%Ox`7qxlemWEKS&KS9s9P@AO4jGw997y2}u;`Jv{wQ zXRO1)(Qvr|v58Z;B2-{l^@rFG8ZO}sDK_p=jz+M}gJYg7I)mt>D_irWywzF|i>vgM z;{(v^Jqpzgy)+(^v5!7DsCuk$f#A0+MT&b4On;;XanX~Cc7$uQH<4%yIyR#Z2dUG% z%v>=xQ5`ZHEj?yWmqd{GY#W_;#KyZFo*=<vA{j=jLr*&h?9454inl#H#S0N9D2RjV zi#{xL58@~vl^Q#rqKe<V$Y^=Zu&+oN<YD0sgFGxdQ?W^}UV1?8jOt<o?<So@>NEnE zHf>{mM1^;7A!eGIHZEGlVN6fTwV{z*4hJ-c!=nmjiyM+xJg|*q<S2%3Qq#;FFN0Q# zZ)k!_Idcp()L-L~;xZawk|jF$T!d*vFpC=JgXk+)Le^}int9EBbv$pqiui}t4nYOO zP`(pdy{*R7pky?!ga#9EJF7|4k{xbXA}RFkKxQeF4*iP?<M?Pc@mmtF8m$C+71Y{? zr!|&^cOK>2h5#A7t!$+bZK<*gkM_8NtmsWinHhFN%~=QMaE>~g17#jY%-2Yskd{NV zAw8o;e{47+@I@e9KF%I>45Zw+q9x948$PJ0<hWD<2lKC>m7>L@<rqqs<t~%Orv9NP zmGgb!iIu4zSh=R3?pIlhrq}d|O)SH5Mj@P;hjUV2E<o)I$s-2wM*Cq^%mfD^Y)P8# z7GootQ)F`y8nB1y5CSO{87z^&DcUkrB)jMe?I}k2-RJ~n$78r(8Sl+B^peb$O2rho zhDV?>H%1R<qZe6@M~Rn}TaP{z2m`CpI$CQ4mrn$mYhR&Po$7)F(JmQ<1EN@G=AN#| z<!E#b4KWmP8dlU+7%$AFgSe7%VjR4SxCID(0%@%>D}Z4p2Su4yFU^<)+xXzb>Wc#b z%UqjL+!`u2ORQTB51HwxAv)~x$i#@1mkuV$QHh*HpBk>k=Gq`iCNnxmc0fiMcT-|g z!pnR|t6Gr+$gOLNqcxKFzMKZwL4M{MnS*s=6fQD+zM>bD;B*l&h?t^kP_Cj7q!gDR za8jP#!iGL?xMamAtgt)HGDTV_SmX@4eX}PDpEp<VW3Px3Vl$33?$nP_i-{x5)WFT~ zwog&<vDtQU^>lpr_l0zhHF<MLjT%UOZ@r-^v^_`G&TaD}+2a$CfPjk?kO1$Q*PK8% zWXdsOI@X}n9-6uo4QJc7Qt?Lgg-}Tv_8e~1eLJ`mL4B@6wsE;GOt+UYf-GI`)$5%~ z**u+!!eFMyYEeT{O6@!Pg5}cL;5><Kr6@sz9f%IPdDqNw8m#+44tl5X9V9j{T20Jy zZ7AV=v`z|m&sT+2A)M<!(@U0JBvT~11&!VhT*t@f<0Az+Rs6>cfRFm|1G<{5CsfFU zA`;G$-CHF*1G$*&70w-$X+mj~f^cC^T)!CI(zF3Ko%0;;r)~W5W;&?ChXYNKpOT^u z*7RYHGvaHTUtw8_&arVohHfDw8LuL%hwL#s9x4%iTZc_Ox5ugzqq`rrvIirfs7OiU z10FNB!r>n?w!(5xz%V+rij-=ctmQ3C)B$wtIQN{iap}32L)I0-`6@*vOwW|1n`+PU z0^jh=En7_53TOOc_flc_NQbLv(>3*uDrY~afjPJH1s`O>&^k!QXukL=7!o~lhTMPc zteRhfyPRfPwi!!0xCz>%Mnr6TIVG>T9H8tI=z6AF@TTce;kBe^ybEet1n8&+PD0Uv zilEi0bL(6<U5wr_zP79uTB!kS+IE!)8JhDH;H>vhyv<xWoFK9cqFv1oN9}afgqlxO z70jW=okbl?GR-CeBx$OJ^)w;J&PQdmyEIzHI6u&miAz4L%C`oBM7u;H+!IV%d(3(~ zZXO=TMP!r#GECE_X&W3U^~6Qy>Zyinua#+bZ>Jh0Geaw=B0pmmgKo^+8tA?Y3y6&0 z+mVQNU(D>*>Gn2Ur<J};KB6%(-Bv#|Qo=o+cD=xyR)}2-n=jB(9<NEzXjZNM>ZaKp zFJP;QghhKHN`O139EB(C&}89`lPG4aEZQz$LK?@85JCZ0%ytlPOo6Lb<74wm_X=9X zR@%fOom!#_cdt+#2|`2?Nk&3}X0qrwVzOs^gqBUL)K`NAEfkL#A$^auYdDBOy-CEN zh<myeS;Ms}H61ALSDT|3IB`(IYQ})!klaZ%x-O$<Xmz8XYa`{JV>q%3DMz!;rP~%q zxGY+(;#vY(SkNBKx79hU^C=0U<z?M*-!najXbTmNQ^ByRsGxU2$|vo_v51hYu-99o zu$2o6wCrj!?ZM#q^8m^!$@5`d2MeLq8cr^mE+`yvc?A)gI)V*vqp`_er{gnwQTfqg z&)Txyi1NwZ*%l?NDM*9JPF6>>mXaLNGL|k;B1qfDi({D3vBZ$-9^%Rs+QRiLb5Jao zbVpV`$0z4V!P~?*sidT{H>PnlJZv>^%VD(L80qPv#&C3V&xl$3f{3atkQ73xE#6L( zy&?A3XbY^#I$EL*G7L=U-fT)p=@fly7c<bTtqxMf+X-}yPy!>@!I~|l|83{?>?}4| zgAUd~nxw0OhqnKV)fmd)JJ57>)TH;DclwaS{5z_+yQ$NTX%CuN0i*OB?RndCkhqAa zd-92k^bFFt*Dlp())&X2@ClOurBq)n9jQAha_0JXBMO0G@)(_=rq&X}7)LNFY29W7 zqfs=RIL^<FC-seujG3U7KubFGsD%k{H;EA)*8Y0Jv0c1{i=0#%=_%dB#J4JKYi4Z% zVkxZaCo(cMD^Nu`NrQW9c)g{e>o2QNYYuJdm`Iu3ILN|MDl~1f7&*#nRJkIH(Akl4 zk{c5a()9A?l0HxqjjVsxQphiB=mHq(#85n^A%tcJlhE~TM)1-fQHnj21ErA>7D0^- z3w{Us$&ulv%g?G40T?7BcWw<tH!{JR-ZP&^TOm*rUSUUt#3<D2a(4;MaHi8K^gTUY zIFU|=LyUx=3`flxUZgJMyVQN^IHxvDnis~mo9)l3T&<4aC9X&|I@uH1+GeRi>qIj< zXw^O1&Gv*txH!d6$N5dIj8?{!b>d+y;@7+eFW8c;*Ceo>noA4oa3@hO&A*J^nr^-F zB&#%e*0^dmJv}Q+ythHCT4~p(1@lH^HkM;@9{nifLdDb`k$}dMpgZOX`BeJ#E?Rjm znNx{4dLQ1LGic_Xt7x6gY=}n|rB?((pzI?TcROLpb&|vZPhLnCz!F8P1g(UL-qXT3 zM2bkT6hn$$b<<uS-c9m7mh~I&svV<*t8u0a;biwMCM4#ARlsJ?Oj!kNkk}cosN*$e z+1*}`7bu68*}avYi>QdS>Y>d?(X#I@#Cd`ly#c<RZh(haJCy;Opi_`c%5`E8#X=#F zUM!p2?T8sRy&;;NAzAg(pox|fOz)bpe}Oh!B1l~r!uU*fp-D!^Rk^FK0}B+E$JNEv zjIcy$662|!O!7VACbb$GHHrd`vHppXu?%V0#l<9Mlp8Gd)vLfbuqh`OX53f@Tlwk2 z7=4%85n<A9RpYye&JCGO>Lkq3C2AAaA*TyL$8VbjG**rt<-8eLlL}?ZxW3vloNS|` z7G_@3@Ps9}?=L=({~Z{D<(ApIjz^25xcd|>hf%tLzLvGk;8>hpSJW-R^bS`-yERT5 za%KEqzZ8Og&(%8l%&ls8JP&RG``uii@Wu!$iP6RsGgeXtiB1~&Y#QkreA|g@(JtBs z#dcgtQ+^zWXoI>?*<-*V1$RR%b|_t+vBm)ybKy;G$fpY7w>gM3o3VCrnsm8f)CP6D zril~vrj<Uc)HJc<@Qn}9fHoj^Kr{vDrbrbKp)!ntThSf}Lje1SOF3D14&^*nt~6Kn z1#%UhlMwYkN@gd^-|0sqOc1PU8GW9DMZ{TxBkc5fSGyDAIGi%J8&`?R-0)<I)h1w+ zY_)1e#<+ep5CdxmAoD(8j;dgffHno7d0?D$hE%sV%%!}xJetpSEbCa_-qo=j`zrxh z7C!+~wJSWN@IXe#W|Ar+ND*QW<au-0voYE;?M{cJR>~+O+(5=)!-@_BH)5K#;Qx2K zV~a_LVDw{;CYbKSr!%SL65sux|1T-A7m7+h#iVR8*QG}1%~+8_#hawIz})hNYG~Tx z*l;wEr5Vuj+p72a9T-jyUWYNB5mDvE;~7sCraCo=sY2?StYS<*N-AH=nHz9i$ELnW z{BV06>btO~7VEC#modiZ>48>^vbhd`M$Sfjj<`#Em!B9zgNvyMNjK5b9xK)EF+Ibr z`ta2V7Qv$d3q+Ab6;ZuKBz(X@f}#!zMW4B|Jk%M94m_{*Wb{hhX$xbp#4QG{7$_^f zgeypqGsy+!dbeWvF<cMAJ~;^sZ8t4^BdaE|RIO-ZVjT5m>-NkgDgJ;GzD`=BusSIe zPwx@}odk#fTjNTZxQ<(;@#Zk8Z7`GSzD?O$4l@0uZz~YG@NQ;xjPXVkrkC6~Qd;BW z4UVW6Z#2tcJ)we4;_deA9^DI21K9>?W^+qbuoy%NAXC*tYPl~dpzcHtb%ZV<Drc;! zls+R-VvA+0UUi_~HMI)Gsy%Y~gwZKO;zGp<jIWUby{6a%>(+Mt3~@~y7d5<);9U0z zp)jt#R$Wbyo_zk4#tcS^KKU3aF9tMs(~B<kK}*n28+o0Dz7=M{!JVBv(*i}yZkQM@ zV+bCTD+<b#y<|*=*wK>*^46VaENMyCf<uaX?1CoOu%I4IUw{AqK2E`uMe1o}X1jzh zZ#Sch8OQ(JB`p|JH2E}HP>;-H()1>c?1n1^T0t9Qn$}<*>TM^@-uvKq1v*0pp<+Tt z^cP<oQB-Hvl*cD9A%nWoaZCoW9mK2l!K$fe;+nh<V%FdDxNE^KzF%tfKX0py(;;4I ziaqz`(DesUhXMW6!|2&@8+}I}Qd-ooXz5_cfwtj|75}3BdeCg`$y?>Bw(>WAp<g3s zI_r*Eu&;y$(EcH``JA_OQX^F@<4QK1oY`u3Y$AKwQ|Yul*@0AW1b>(7E9@FP$6RkP zWTP7NdFZCmypU*!?Z2DbyrXY~3`jNX(;KcYRQPTP)QFLg_l>3P5U;CNo3ubmrwF7Z zhf|4Xx~rkpkP+R{jHr8qsC}?oe{PTXTUN<qPjXp_Ai3@ci5af-cuKd3Qcrn4A#y=9 zaG^0sp*B*0MrONimo$rNbp2>K3f6de%MeD*B<&I$Hd1G{A~K+1nc-dMX`M@)fdps| z#z@gah<cOHJH+?z5{fA473*H!vgX1ITRN7uFU{ka0j)U7F<82Dpk#U#8Po(X8aZ&z zDHoO6<#oY`XmJj`gdAp*3%XZ%7RDhI1wGsy%S}_o9YxYLO>|LPzHs^0t>{~t+_dG| zmC|~-Glg0<x0*&JkcX|nnpG^>w071kD~CEoGDc^F?{J=Ep>xtM7?35sPhJdmzDQmQ zru0vo(s<g629<W}>zA!iww*?>chN~!F0ZF<C~sEJ!+PEkNxii@TwC=8mQ>4|B4)E+ z#8K$9YjBkUo$ZWh7zx|TU^#>IUhyRs5l+jiW93m=C|NEdOV+z!Xh#)1O`=6kJo@J; z(NSoflM%n$lNgeF#W|_Wt?E!6ie{ZPl4dH#l%<};+R*R>KfIj<OD!0Yn*Oj}U(n2` z43a!@TE(71RLtluxeI>A^T<Z58d2{D5nvp;L{Mb@*6{sPGwSZEb>|~EkZBi|OrJ_k z$8e$7=nWp&+K)Uk%8txRC2I}57F8g2g`Symix9%m*GS>%-Ob&5xYVdt#KF3V^p?HC z_41M0=HVjUPitzixp&T}&<nF9cE~8-W;W1BbRG9!V!xqS9xaWVTlz?3l%}D9>L%>` zYV8C_B744+`Yu;O29q&Tumd4Gd!6RMZ}VulZ}*B<eu4}|+@Xj{7O;-qsS{sV>{P2> z+tk!!ax%I#?UU?i1U)Up@Nl)&I947CRwx#0<}72z2O{(3L3`#Ccd1d8Z=TeGECgv` zRT-MaN7vyIxn!DPy`^Br)`*h1t&6S*t72|X8nDb^`KFHT!yYu)=#OcT*xZxLliW2b zpPePzq^#yVmp<XvL6)+j>OEk@Tdi!j)f?Be@v;nt!iGGY{r|S7)j4y552`@0@+_UJ z6kgtv>awj;&keknQ0b~dtJ?T>+tgE})M&<8kQz`jolufyr)T=+4O)w%Jc<lIjmkW) zpfEc4VAke-#HyvLfzIJT%A)s%@GE<~mX247hDH*1=C&*OLNEWKNUk||s-QS*N4TIk zi?g7Lc?KN>X2tpi^f@Gn-h%_d8wwBw#=1liH_Mn!M6Dokl5#VHqe)!xxW=0mpW0B_ zZbjOp4vS!ul;7q^y4&_<bPC7Dga<A&QsI@O)m(Md%%he@tMF2V(YH3?nNF#R5zb#j z`DHs@#!WK4*iarU^-pZUYU0+CQ5_U5r-3dVx*)N!>p--qT2fKY#k8bVQ}2&%!qDDc z?S@P%kCLha>9vjQA8DGSI-2N>CruliPwSH@*o(zo8qUtUhjp;5=jl>Kd^lKDYnBQh z+y_L1alUj;gc{?^FU@HX%n8asy+-{*aZuo4?tjJV?I5<Iv6_YxPDZcX!1mwzxZA4< zjt6LoMXKSMTwEt`<V^ZeDz_{NBjq4i7x5L>#Dx-j<Rs7;f#OBNp)HLl1h5^c-Div+ zktp_b4VJe+7q^iIi8NU`pEk+io)wT1ouHclpmop)L6~%_+5u^mdK9$mL*tcgRu~wE zB*x7t2~q8{4)@Twy?DG8gOsnjt*@VMz@p(p*#3$T4DI0z43(gS9!FH{6}uo*ExR+! zP&!9YaNIpDqs)dRJItI+MzuCNB2iP2ePCLf!sTEHK%liKv5+>p<ZtD0MG0=gqQ7lm zMLF0C)7;>?A!Nvy&22fqJ^j;7X8u7fv+s!QvO-VaWkzpz3A?E@do`IuLPq(#IUBi# zuKq2JUpkBfkb~R%N+@`=`5L+NgBBEn??lR^ePA13frs5pnT?oTmF*b$WQ^pF`G|)m z!76VqdhNn6ow|(3lgr9y(!D52+p1Wn4~B%SRT_u1F|6eR*|5~BJ$a1tRDD=O7)0}H z<#bl9ni!?~=LR8!XcvLIOIyoWV^HtcVttjiKH@HGpu)LI&Z}~m>X=1}!nOg-vHHV8 zN#_Kq0}QGOF4@3kjTj~V?wsrJ^bE3y@C<0H@U0uL_f6gOWuBoBuvzyy8X7}<F|r+P z^A;0=*`U#DoY*vaI>H8rgi7qt>PuTuSli!*M%^lRfM92F*j`-dTW6#C8}0CDQzWK< zA$g(~Gz&3Ck;A?n)osNwKHQ>aYSA@BER#ULW6&Jt@>=Dzr|}HD3@2yN{XA&K$m<0| znq=9DW2R!IA5}BT68>0M+7fFwlRTL0LGQwsdduK8Y>l;&k4{nvMg<N{63KG}x6w?y zdy-`m_Z+_6mL<LF-IY>xU8UADi4|Kj_E94O-&_xEWH`16mg2&DndNS(biL~C(4P*^ zhReaMT)tf5)x3n6N25apwZ{?}@JuawW-}p{e`cbeYYRmUBXe{$!%od-XhNLmH|k6x zCxvLvU!bA4y^k+Y3MIoW?LL8lF3F973tbpf94wAOcuZ~PmbYRt6kTK9_ceJWDn5Mf ziQKVx9&9})Z!znDPSY#tvm-f}JY>b}Eh0-DKkpspjm^V$=$eUTV_4K>7)^JjTj^Re zN`Q3JNC9_&1vfdxzEG`NurS;}iyB#!lVTU7qceyzir4b(l7mhm;PZRX{bLRzQ3<`; zNXAewLOqir35l_+y}Q!f%9^M1ZsDpK-*M41Fu;A4ENli%fr>A#5y2^Wnt%oOMVO6g z%mt{kFy2dhLCs3q?zaeRVz3GYj$t<?rPWS7hOsY%X@`*)g%^D5OZ@)mW$3_+e7D^q z3`9SJSny<2&yRe~1?cHa0!eg^rVLlj^e;XpZDh2X4@RqLCEtiMqSL5s$LR)}uCaCe zS~!D^iV#@(ghqDygO1>2i+5^7TAiW)LrZg9TiSw7$ds2{dyYcI<vt>IN@A$74Z<8e zlgX$lw$LfVvLstGkTk=lL}p#(y5jHz?yw!E8(uLvhg{ScX6K_Q@7go(p#g{?wHL0s z9CI8iiDV`Xq(pX<2T!*3wQH7$1Ws^JYit-t$4*{-PW3unBiO2kQDHOV$sk$HlioiV z1Ig5m#&3MHk5z-Kl!c_MNjAKI)H#6TAABJmPU&FPjkb9)l|t<`eY)A>ZpYnE5H404 zEk!W8#q29ru|RAT>nBtnlpR~AE`c_j?J`!7*?y-L2sDM;o=sUnEtyp`WI{sA{ZtMn zYIdMuRI}tFxAH<pjE@JY3pj0lMhd0Ti5oAK5#eZQ7)k%Eqm*-5C^(0vc5~UB4aXV| z?PO6Qt5m&W<sGDR#tt|*OtB#Nch2n^6l<jj^QT^GXT__b;LZGp_GT<Cvwj*Y(`R=m zsaI**Mqf~P>Icr~6uPv4(}g32iL&WlJXsnpoFq=P8ZPH(*#hNwtWOj(vXq4mERmoJ zU`0JVj%H>XxSnMzZd4GRcC>@XB3!g~25~J?p<+gZxO}@dPM4|cCQFOuH`+cXDY4;& zv2d(HlcQ3_T=q@Nir6wPViZ{(q?M8~uR%32zrmHxj@e=@r^-;^3R*!nG$CSdXrMd- zRSKpdQ>hUS>~eXUXBD=UN;jf`$aP?PMMqR+c4bHOSo860WQT*HgnqHn$%oW>T;GQh zQfuhebTpDZ=19Bj*P1omzAEYK=IhGW(;?a+Oi<OplV^$bMpCjrggMtZNx-52;%Wp^ z!QQ|$A8XyQ%`Dw7rR-Z{i~?Z>Y<ySECLpyEGnM;}T~F2oo)Oi_@pW{q_#oP`2OF1l zF9FGstOu9Mu;q^>zpI`jMe#ZfD$F1qCB<Iu5!4DKa?m9jHDEoNORLoq?zOXb6o*5P z6a{kjj#%DYh(tRdM7#0*+MH**IdR|Cdr#@MwcDWlVOxr_hDab|_e9q`^(*>?Z<vN^ zDZxY|j0GC1GKq!QGcap(xh`ikf!KK_FNkf$In$+Tkc-^5QgAj5u4J37<kX7Eep)1Y z>E|87B7qJLGsSUgW@Rd8)c4UbD|EM!Ym_1$_;q&pu9u}kWfTWQv<Eb8{E#;%kdRNh zW%9<#r)y`}rv9y3%*!PB)CWy6^hJ|0?d7~&o4qrX4hrx>Q)2OJw1ZlX6Ip0G48!8! zR+8E@3MMJZY?kJH>d%{dV6Te>__k)oNbWT_A-U?}(7LKc=K8_dBsjh@MFG2D$tr!r zQl=w?erOuLv4mx{vGK~}b_qsw7A<f8|8-y(TOH_HWa)^Ceta#;(dV3StSs6*#H4Ys zk4;UkzOyjc%&yZOHB%g(uf=Jgy`aeu%QH1Z-Lw`>`-;J9RIw=pFvC2GOi>%17Z`y# zBi+V%k%8O`nuM{+z))cXbLE*R5{r&gFoHLsRrwoR(N$YlUj3H(GL*~}Yu2o6S&XxA z=kr0hOEa0w$y-JzGP7VgZtm>)vocGo+ed1}emraA_BkXr+|gQGO1f+^OR>^g%q;E4 zl{-tVv|6#hAHw#TrH017GW+@Z1+6}241=YG>&<fJ=GwJt{Ka3B4<L}5lxxG3>PCAR zM#r`x^jG4ILzr-ZhW{IGx?>9h`oMN~F6Na}OCh9UWGJC%ndYSS0|{0-EzVaXU9ljE z*m%FlcO?r|_T21#6e-J%EVp<fM{*Y;Kat=ZUH<V9C9fz1vGkBc6#b?V#uuDy0h1K; z@eZbeI;lN`xtv)Z$LeQ4F1%LR;-k%vq01|7DapE5-C#g}@_1!{6yKRefwV}j;5CN2 zgt>OCdZ2Eg%J!3PzdB)VV`{sVT{pz)zMHzVq=<UF@wDi|me6n+`<S!{OhPNMpj)NW z{<>@OV;Qekd-k+Fq3xi(+{Q@jZkc=7=epdz;s*WdTJPLpSNA)rq|sBJ-FZsApm8=$ zr=e=^9mROKJa{?HP<)b8o{v@pli#`_G1)K$IW3QG%lKZ0#{9~;n(=*~NlTE}z~`ab z)->8yH4#on`4@qEdOXcrv`t^8+J6!pDU6YpFVFT%^b)8%&SQngSs?e#K1G8rn-NX( zWEoDKK^tbIt{tWL<Z>jXH;6mkvB618y0sO-0W@z>jqEC5dxWGy-9nw1qiP$WyDj0f zrl)3IpWG|%Js(6m+<3@sRmU!9ad?eYBIx1K&`y`9B-7AXZ(aAU$5{_l1|0Utg@--- zn#O!tDD8141T1VBGcD4VfdSU905M*OSEPRG&v(<#m<HV8E%ikaq;QC~>uIbU$~2y_ zc0ZMGoH~`a+c%{1j!~!aj&=>Hj2+Sxu3_Ji#!ykE@Ji}e(l{r6lj4u`KxupfniM{< zzA24ioY>FVv=2Pa@l^eYb9}Bs&ZgQVd}`hN-$koH0t1IAfm5u|Cvl4tCUJC&dLqXd zVFJf!8Bb#8Q2BX<#XEtGBJguaD#i)?63PACr7$OO3!MF5$4YJjn>byZANS{KdhcQ8 zAxh$uF#k_vnna((KNr(qoygiln#9%WgoQK?t#ZT$FS5j(xK3f@mF*FKJ)}$+LQR() zqzueba4dYuW3n(bDXHYHRO@lEXIj&cZ%GO58I~tq#j2N_FgTBo%n}3AAjkNOZKfQX z5bK2c(3}KFX5NIfNM;^SmMK($q|8k8uBRulq8wdsXI|Zt;u@_AM>m45UkR}?(<1-X zd6Cl&iTCD37a~&F#YQ9zvP`VZ(RBdQ%Mvz|Q>$lnIK|6-<6&yFC`_eYj0Lx0PmV@R zQY!FKiBy_@@%SZfS<gUXqAe7}OH@GB*TV|cqxIux1c#2CSWVq@86Y(I(i#y|xgUL> zrz(*MIc$H>rY)pkE^fokqz%Ru+o*Knpb(r+?4^UG&S3yL)(x5<QIqrdGRk8JST@~v zZ<ZbnkEWV~flR3zWjUJRsa7H(&IbUi5C<cLD0MX~ljLuByK~gT#0Gc<>ZF})WG_0c z*hVn8HjC0~nuP^t+~u$#UI-*bf@2=Ob;Bf~L{BotN-mvhh#q6Xn;z2QZ_kPQE_DTk z6U`Y&2&qZMc*SmFM>b9nIyxoWOUL-Cz72rn(Sj_1HaJE|W@Of7X3QlQ+gh4A%jg2g zjQNEtAv0zr%N8?c6kE7xkR#gY@JbMfK0=V$cP0T13zpeE)hf9-B(3i>7%*aNH&a*8 zy(30I&MJ078_-vcwE`v}k#Y2z9J)a4Yl&z8I+p>ik%Kt91`!Zbg`g~e>{SSbU<>k! z>qJ`GGw+^3i`SEfTF1~6K6oAXBi|l0f3(jRQ`et^k_%ze6edSAx+Z;XdxfOka9v`6 zBl8K)m+-sZhQBjSBYD-=@Fyf2RHYV`J`<l-1eri>c#Lb*nK*<r63Iqr;@K}^JPFHV z(xZglNr<P#Di*P6aq*^LGA9x^@}_G2Py8u8-S3*dwVIqeN5!jH?j03hytykrxqHRl zd`%<v=jc?vpmskP!g!hv*IlKW>*NN8-0h$yfp6gGFb&@OI7WA$d}W6GjZ-;(#0k8f z#g~E-;u04Hax&9|ssVP_nE|zD7?<d=yW8dU*hl1zu`}39@-<H8CUBg>=bsu3CU_O4 zaD0h6`aDP+M<sZdM(=o@M(PVnFj`IUTDv=5X(u1+`1m!!4=<tPnU{uqRUJJQ=X_gV zL=}}iweBf?$%GD9p2<S<%;-R6Y&%Jg6mmI*9Oeztd($f-c|=^JRQB$=sMxFHw{2#$ zn2xY<k|`KK!xtx|wNo?zwi!rs=eX+$z9$-fDisVrK{PPoD2YW>)5mx5ZBR*>F#a;m zYlJrRKJb^1xWvbMjV>@dnaQcpz<%pgJV;8#STq`B8ZAJHVQ!pTG=O2A%piabvz+$c zKyqP9T5wOS7bzdasz?fLG|tT^u1TJe)M$gHpyBkb<5$CxODcBB{2PqPv=~Q&J&mHB z8tjI-AB9{PsMb1yl*3_?+){!RB6|R5^Ef2y`Auo4pdqW6t^^A?M&<O_L_Z1R%Zd)4 z>@n(`qVMFDrGVF&r8puvLdq<c;yBULVh!hi`;Fp|rCY`;6Jt1D)Trrr87NOy)E%(T z&tzu54}VqI=i0v*-6};_OQGvlbQ39bYZcwr6uJ$HZZd^#qoTVxg>F#My)K1rSkc{* zLPu#K>G%2+I^rR8Z%Corq3CW)q1&nG?nt5ArReTVp}SAfQ5fdhzgRigqv+n4Lbq4Z z-IYSOPtm<8h3;WRcXtZi0Y&%b6uN_o?ky>Fk1D#~OQCyQ(NW$crQab%_tq4;!;0>0 zDRf5^-P=>>o>p}CB-72Ja7#ITM+)5nMfc7Wx`m4FT`6>n6y2^Ax>iMZZwlQKMfaW* zx(-FRJB4nQqI+)&UALk`o0?P(X026p?@yuIpy=*Pq1&kFK9E8;sOUbJLN~1Fem{k- zrs)14h3*zb_lGHTI~3gmDRes(-A7XBs4Pi&elUfO(pKm`nnJfn(S0n1Zm**IL<-$L zMfbTBx`!3rpQX?pP;_5Np*yJP_NUN2s_2OKT>Izt3$q?qbYDrKJEZ8oo<et6(S0L@ z?uerMRtnwIitgLVbh9abQV#wqg>HeOqcloLm)Q#y-D4?qixl18q|mi0y1z}KTcYTG zltR~`=zg3+w@T6dLkeBDqWh;5y0wb#$rQQ`if&&D-9|<CFDZ0`ith6%bi<17UsLF6 zitfuPbhjwF!zpw-6x|~!bUPK@zopRaQgnZjLU*5{`)LZ@9!2-v6uP~N?*B`nqdb-R z_SY$N4=cK-Qs@pSy2n%K4l25zrO-X9=>9&1j{K5%{5*y3kfQrZ3LTXZ;rAaYbVn53 zFH`8AR&@WBOgCq)qWe_}-2z4T-zjtp6&;0v_~Xy*Kjth_bpMk=*Ba8znVmwnMA6Ml zq3cj|C#2A=QgqoAx^6{xQVQK#MfdC!x($ks(lROiHY&R3rO*v3x>Hi<h85juDRebO zM|qeOzFQRC87Xu-6kTfy-A+Y!ZVKHlMMq^KDSY=Sx{Ffi_9(ix6uP~Nu04frpQ1y3 zPYmC~if(xd-2p{+K?>bLMR#!u-J^=`>=e4k72WC-x<iWYiWIuTimo?>?ueqhI)(0O zMYk@QZZ4G%Zg=NglR~#Z(XCIRTd3%0?Tz^3&u#zaE>d)_O`&U5bfpx!C5o<`Lf4__ zZcL$DrRauJ=(-i%ttoVC6<x}D*xU_@?zR+u8x`H{DRhI1E@j<pF2zyGLCU(>+?t}> zk>c+yiY{f{Y%cK-fA31+w^PyGokF)u(WR`@%)L+1rL5D;-J|FVDgN$NbSdi_bN4B_ z52f&XSkWDqLU%yXEl8m|sOUbNLiebmOIf#=`?#WeAcfx{MfcGZy2FZYP72)-MK?Ev z?rBALY%<+3#6!y8|4E^vv=zF&DRc`J-5;gUEeh#oZ%d(T4e90-Q|Oi`x{s&Obtt+| zrqHcYbbp*e*RAM2l|r{Rq?^4xg>HkQOXIgu(S16F-(W~LCyj16q?`S43cs47`|}jK zTSB@ypGl$H5z@{6VhY_(Mfar?x?LgNoX@7v-51i${%Q){9!2-H6uP}3-JCy3q1zYI z&HiQz9pwSnx7i0%=njN*a~?{eBOb!<J1KOJD!RW+p?f@}oAakBbcaH^+22c{JFMuw zpF(#eq??nnetOK)A>HgBB=eg$SJC}2g>FGeHz#F1cHY8}ZuZ}$@LQzlo=Bl<4e91k znV|6E&mB+BTN2XEK9oY&q3HfGg>F?yHz%c@&+ArnDeG(V)+)M`b?SK=6y1K<lj6Hk z(WSH-^9Dn@*(u|VdBY*yoRs!uUQN-ZtpClsMbRCAJt-bL6x~-+=yry5vs1>|^LB-F zbIwcQcb}q5Y5(T!QFJNo-@Ltw?vWIK_bIxsr_end(#`%w3LT}bj7!c>p*yJPQrg{l zk19I)CMn+@S9B@stn&^jy62?uJFMsyr_dcybZ4f}J+0`zl}vXm#ZS^NWuN5O1&Z#h z6n+a8T}nT5>>@>%($5^*s_4F(;_nhgcWMe<hoWl<=`v)Wg}-_DgE@9pCUb=HUks%a znHS(s?3v67yYJ6r?i#c5G?^c>8>Q8`_#=KamWO#7X&f=+Mux*3p`&rL82K)T7xE3P z#P7t92$6E@R(5=G!Y49ww!F_n_Y%Ad<FVk(lQOe=u|7z0L79JIH;Tv0@fZ3#x7wS@ zyseCPV#IAdUWELzLyM7=`<UN9vm5a%;t$`<w&{G#EYM_VT~dtjxC1XV-9cdbUX0Ma z9xue6$z(^VUP?R;vm1R!a~sX?F<>9R2lyL2V6vk}@GJa&3Oo5l-%;PL`5gj234dZF zOfvSc@3R&9R`@*yJM)`GYq**p`Rm~~>ty~0514GF6~Dso=dcUE%V1ah%syua-ihJx z&8p#rrdtloZiZCoKI+h+eq{C;3i~5;|L)LH9DVVSw6tGmE5uLY@t?30Kcv;{XXB~D zXR4Ej-|T1cH+aBgD;w}D{AB-w_$|YG&5w9do`~Ui%+BKl+hNOAhVd)>{+r#1-}SI- zev5#m&cZ4@X5Z=1wI<NfoJI3n0_+RlALG3a-wt32-*4EB!snFJIm_YZ3E!L(@Lv17 zI)UzDhwe&XPxy>KI(+wmj>9*LGLhWy-JBsjwZD{azVN-nq1%{1_XUS;FoBNtD7C-C zz`l6M-ZGqFvK1=x5)TR|$73$_3!2{~u!rAVs^>ag4gw3m<Jk@0%|$yK;kN_W$FG~e z!2>2+IfP%~NA%<u@w*vM9lm>jJ?T96{SMu3`#pZGA$~A(@1-AOrJro&Y5a=6C&DiN zejRr0?;c=ZJPz<Tc)(=G7UEa<Nt;LUID+?@-zR~6{3w4__{NqfeliZjcgHMt_&x0B zcg#5szi!3vx$H*#Ho>mL_Xw~je8;?+zrh10J4WSM;`@BqDeT0L(qHp?6!=Q~iQzaN z^Dey5@vQ+1KN$}ZKbp%aer6xS7ruuaemfOED(ezH>T@(dN>3lZf8%fPfXR;S!LNkx zbl92Syt84~{5pU={N~9waE8f_QN9VkGhr8gn_$=cRs;L^x%olqEd0)bUHH8XcFk{X z0>3x&H+aBg#}4CH_(@qpIOgrgd(H2az(e>GL;k`X>x>WP?#D|{KX|Ov75WJN-bCMv zzceQ0cpUpW*tNgk0bY(jG2-t}@IuiYGas1##4z1_3bUr8u<a2dJcVu`w8NIYX%T*} zL_dXb=PcR3M7qp>C*Es*`+z;+oBvk4XWp=7ZyLmJ8}nPjZp6=NhmJW6Hy^(P{0$y3 z*_(FZSNJW3o%{m7<J$35;hWbA?BREud;@2g>`la9_~9Aw8-!i+qxQhZufX5n0h7Jy z2!4g1j9DmrcjCR~NAd9SleGjm!(_)P9>T8!_PO{Yeh=cQ`5grI@%sb*1`n9*_y+u* z!uin!yYPDgcEyk8p|h6Yofx8nIqrw}VLNQu@nQVl!~Dp9=6C#suq%G^DQzFZpBUzG zywm~vK0E$2ERQk2m9PuHYhVYz%xwIj*_{7mCUa^Sjv!3OzZ9<F`)u`5;7R7UirtWY z$8UyRh3~Axz`OA$M#5Lb3&pRt7FhUQ!fwRxEwC$oXYT-h2!CRPpX@!__u1M3SRUi> zt%jZGh@Ue*I)}pU3*Q6$4IVJriTm&?;iEZ+@H+^*3g0=DF23-|ni8C0vRfD8SHjl~ zyYTx3?22FOPGDd7e#YP60h8T&7{3y}%VB4JC$zw>_`R?d*b}}Jq_2ZBOm^EKekFWp zw*r3aVAuQ}2lj;T1RB>-7_7-oQaVfcq%0vnPPhf{6~A+9z`pQp!+XtdAFzaPExQrF zkHN0^owo$o7e3kZgfmQb`%e5y_$ZF#7x9B15q<}NAHts)4$}#Lg%>J(H<KOTn)ZG@ zyMf<=Ik2nnEvESI#-AAB_iMb+{3x9#ncubSM*OJVRs7DUa^(r%g7f(sJYce~+kjsQ zAKA$-;zxGP?;x-zd<&@EP~p2}39y9kI(8#|&UpNSLAd$CH{tNx11#ZtrQ-K-*j4y0 zTm-xue_}XH3qFb$Dtxb}be`n&yPn-Bd_RU=^V<jf5dOpnzrV!`&F={CW6W<OyMf=c z=E1J`Eg1&(gzs6P(fn>b2rS`yExQrF3t(6LE}}4a!uPBf@;7+EWZ%$@UkTqP*y%gs z_X<2UzlVW+;gd23XPE45l+F^qe%OWI4%ijHrBr@ii9az!2lK2q;D_z7WpCSsUl|V# zvKxhu`c=(uFYt2wi4lGu#0$;uabW4ssShGI;`b#yHNQi^zVOj}LGimC-v;3uVmIRV zBiI$c7p(&Jh3{|p8$4jLw^O=E_-=q*!uKoKHNP6LFMR*O-{1k0y?qCMCH;nBXMS0l z6KH-1fj!~Np2pwc0h7I*=p=ljunWI#*cHDvdhZEe_9grc9x&P4pT@6*Zwz+fHv+rn zw-MMEK1p*p!({KEa7g&ZVHbY)!mjyIx$=dN)>Y^mYqEDxI!pM-F8sa#yXJQo*cZOf z@i%zDWbb$wzY@N!unWH@VORWet-!wU{R4l42Tb-3@>jw)2|M#UF$=rqcMGs5d?y~q z-{1k0y|V+q626;Z7k>0!^V<jP3Ezn?;&1SP$=*4LUkM+DLHO}Hx~zNW7r@OIzV-YK z9x&NE_u^N=cPs3|kJ3_wFW(L93*Sxr4IVJrJ0Hidgzq-kg&+0%n%{lEzVO}8-{1k0 z-O-9)3Ev&C3%^HU*Zc_k!uM_d1`n9*jt%&g@a=$I`29QVieLK@U|;xt%HQAtlifk_ zknr6FJM%l~*|2MVgTS8fo#d=5?>GoL3E$m{-%5wy!@!>Koz%(S-~p3;<3jvO_}&7$ zgpc|X9lj&LzVN+<zrh10`^IkkO89odF8tmEyW-ce7T6a)$wN59WZy_UBz$j!UHI*V zUGv)k><b_5QPDTnWZy{XBH_CScH#Fp?3y28U-<r-zrh10dl!8#;d>|S%<tp{uq%F@ zl+K>;oqQ~Rg9l9Zt`7W4_;$fA{FcG4`3(bm!gq3>zrh10d)F=amGDuUEc~4O?c4*m zP52W-bTB77`Fj_o`y`LAcEc|GsBEk7b<z7L@Fzz2-HsP*hb{Z2R{RRT_puw&?&R;m zuK67Trav*v<K*w)1>0fEzUe;v?&t84o!r3h+2`V^_$_+`_$mB}VII#u3ojJEyEg(q z$oyn%L;NUR6u;#U0q@737~%Iyyiok!Om>Oy{p?2kD6bX26`;vb7{v&`x8sH8NBJxK zKFn^!@0+kIek)f4KZ-vw!tbkiq4^yFmiX>rH}HGT>98w)FJ1`zB>u!OkLR3%7mD9o zbbdU*Zp5zwyXN;auqQvBBV#f+!(@Mt@?$^e2f}ImB7R?lUGZCW7}yiv=RC~c-~p4} zxd^`!-;cpgVF$m3XW*&$UA!OI6W@ihwhd>P?9K!D-Ou6M3%l@h);lkuuzTXWP{t^5 zhRMEl2Y&Z6zmLN%{2qf{h3_T10bB7-4AH?XbmqTr>jvF?=J!buFu&(s1H0n48tF8P z@>mS>d+tl|g6*(n-@X>V`<dUT*bV9T+yk&HewTg+uodsb2tOLvDSr3h+aP@V*bVQV z*9N=dci9m@Pxzik>u`$SJBVgKhwroOM*OI)QT)1*CcgZA-n;o5JYcf#coe_;ncqXO zlV8N|pYhcEC~rOG<#~tr8$4jL@7#so{mk!kurt5suYz6i>p^}ST?u$?49D^L)Gx3d zw(Pq$;CDasld_KRJ^wDeSNtx29GL#Z2*2C$Lh;*0>30wF`#if5Kjf$8cLk+|C%(_8 zc1ZKv1H7O4;VJPwg~lZ+d{^G@kMAi|4ivw44+0}?%zDn3*bU)3#mV1Z^4Al-Q=I(0 zm(qPd^E(joJN0<jRrp@I(;vQ5kKu3dfXUwbG=3#~Uxl5*j_{p&GoFgyRY+qa3xU_h z5FN~^6Zl~}Y}xlv`4fJRup9WDM)L~A?`nKA>j}IQ!#qx-r{cGJFYqRg?>E?u_}vM+ z;<xS)_R8nuofzRKa{~K5`(AuY?V8DtgRm1F-o3zSPhWNzG_Cd{^UM5R;IyajrS#j+ z{JsUd@N@c)4JRSE`wS=hBm8dQZ|vLb`yPfx!uK6^qwxJ3>?*!5Kj2Tl7f=~u-mqog zzZbuoIDFq_H}G3@9qfwVEB5%)Z_&&68$4jL_u<<he3aMZ7x8-nPsQ(g_&W<>3=D^9 z(GT&4?XYF<qx9Rv;rl+jf#2!muj03H4B_+eJAEyGg9l9Z0~^5$bS8gM4kdi2Q`#$j zn>xU6l0IR>VLJU2z$$$Ax8SoUnBNcBjl%bH*cHD4#Md|eJDu`P@uMM7Fn)fV-N5gR zQ(#y82Jb=mR^y!*=5fYz@Iv#u5*V~5zCU6&;`e^o6~8T1mR93WjPSb`FEl?&vo_}U z1iKMG?muL|XXqrXX*~pYF<ke~ID{99-yh)pf=$ft$LvP@egV4*-^3%p2k<9`d7SYx zyioi;F$BDc`5j_6@H_MQuq%FBcLKKHofzhE=Ckoa^CN%vGrym(8}Zu&yW+QPZvwwp z^EY_FWIuT~e)luKCt)YQh~EQvDt?m(6Zn0Izrh10`^Q(}cR%y{7ubd0f5EQ!Z9kmA z?+AZ`2Tb-;^YOc%`QaPk*U}5S;`cg)c~%SFiQzPB>BbAT!<PNjBlz9V{A6tb-?r?+ zd&Q5|`DeA@ofzTwcDzvhK7BXve&+WSyAi*?g<bJ`{n`Y6RDKn|eLDT9&XODWo%Nz9 zzgvfaAH<&+=5f{qc%k@xW<KyFhfmU$_*L*;h3^duu_?M-n1wvfa@zaP+-BP$Q-7&W zNcbLsUGdw2_|996cVZ-bU&ad+zK4DZe)n+rU=R3_UGaO%PK1xrSB&tZbtJ{_;kyA5 zXA{0(u^Zxh_C>IRUuF*e!0Mh`@Ed*?*w0=Zd7s^nuu=LOeowO-@mm4A=64&r;b9E( zKDz@b^e4OjK49VZYjz`kt6`^bOZX6vh+GET$ec~<dX3N>u0zLRIw#j4-Frbt`7s+$ zN<Ru;tFhZ34&OOck92$=1m0lN&&aHj8{&J;U*f6x?FDYZpBM?>LA=oXC=c40-#m5$ zzgD8r{OG&$@F#|Ow64MnqLXw!0?c7Iq(bM+1HQNfuBWiSG&UqU^7nc?wZ9ZT>hr`1 zKN{C5x_6ueOn+iH46WPog1><+`^9ejwz9wQFYuQ-X3eh!m}tcazYpMr<~IcVAoI(z z8^uG$Yn;FD7=&93{=_hk)+g~o@%s|RLGpv_<OY5(Y{yfFZwK&7{E1;6FO+oQ{CLNH z5OCNHsn9v;@}<>qmHdz~2KoC*yx0Cd0_-UVFQj;Ax~D8Z{940dc;P<)au{ICe(9C? zMH!;@VD|Ia4gQ|n0=we(PWpZk{=_i9b6<cLnjh7dE14hSBk6bU@4>G5wF1MRz%Y+< z@4_3+?{Q$zn(&>*ZWKNmmuP;-vkaA8G0fw<jd($HoFDJp3Cv+Pq(b)!Am#6u$x-ry z*0#tE{+@R?p4wlE?^*a0Bm6#x7n<%NU{Cs;_Zhs`{!*Gr`n9kd`Fj|4&F?W_au>sK zI`5zGLi5`MEbZ0V>;`^|@fYFuOJI5@hIuSL7B4iveZZ}pA9zZ-ET%H4!uKxv=0yC7 zVIGUGzza=B@of<zJUJeVFN2-Gfi3%Gim$|j{317s#~_}X-*WpNzt)Jq1wh5`z!KnA zj>q}zM*MDpUGwV(_N9x{f4plw=vwe6M&d!`L;Fi~5)TRkxskuJf649DyT<H${9402 z7E`&>{PqC1ay*u@8}WMrb{!9j*K_eFhIyP%eU7Hv4csC`cyc_>2TjD^M}Q?B)aMdE z_<KIpL(T6Y`yRj6h`-J{+*hb>NIa;m6@D*=UGqBtd@BCL2){Srg{FG~xCMV=Bpx^8 z1%Cru_A9ILEAi-JH;TtcVORVp8-3;A{5|{)xf4GkY~}o*vPgarKU$m6{P4~jk6$`; zi-BA4Cr0A&?|7l(LFp{<crm-dj|<L(UHf|_F!?Qpd0cQBUMPNFC7M=_$HnYM{4RxE z^Mjum>Nms)zahNPbX1;Oga}WL#{~nhYk#TyNIX`v8~OVd*fqa<fPL|JBY%SjO!lig z@GJ3<Hih_o1n)J!`+!fzpBRb9*YQHreG<4ui13tn9Dtp_fi3&h2k|TM=wUbV_rGA* z{JsP1i^mcE1`n9*SD(hO#Dm&U@(bTxh<6cwj{{Sli{UU`Ncp7veK)zc&<`7q$A#Ab z^Ea?%zt)0ZiN{OXjr^^_uK5w2Cmt8lyiD_>?+|9wpRZ*%;`esgHNPdmC*n_x#N!iq zq3Kowx8P5V#N%Ulq5a(rEb+L8-N@g^VAuRM0popO#NWTd8_n-9a4W~-W$Z@$D4#UH zVc=8nCx&?}c_Cg99gj=iy#tuTZb*f$1&HmiWgj^Szu;%m5AiW>@OR18uxo#J0@Juf zjPQFMUTA;!0{i^kiuc;z#lYgPjFre=N@wlwKHygTi4lMQ4lgtvrTdjageQk#$q!)H z{;mc-$nm|N-Qe#<$H1=m-P;0;_km#^G)>n0zD_g<pGm)s>_+^~g<bPo0_^E8FIvlV zoNxDb1AEf%BB`TrhRJ@t4Zo6p1=uNk<nLxYwZFvQQ|>Ri%c0u@>`A|iZpV9$J8apn z6U{-6Z$G<{zYoB!{e2L4A^ya0oG$thUMPOwAR5HQq~9RB5kL45;rB2w-Uo(xT=X@( z(fqoBTbUoF1-TJFXa08YBY5x0kEJwM((!o0eve;k*srBBH?(iF-xz{L{4K-I{w`e! zyXJQonC3WQgrAdd@1gYaq~Fpa-t#xGWxuf#zmk5#?1uO*eJAY7-}fv6Zo!`z@%OEG zq4`ld3%^lzBYreK(EL^b(^yIj^LWv#@Iuq=0&Wo^JcVvUXooHPjl=jAe{W(p`1>NK zUwzL$xKY0=M)>^-FSNhE1a1`~Jh}Y6=s#fRZ(z%QlhOrYG3BquZt%CwY5#V&z^xm9 zVwhjsm3X1~jR8N%{G`nzexJsB6~5g=zzgvwM)-XkFBHFnsN+GpOtKsCI|RGtcMCAy z2ZnjHQ9G&mQFvQ9d^fWjzRR5iyXJQ{a0~v#Fpu1&c%kVY1a1)`JcW+RhxT_ESn~Jv z>_-0n5$u}ZBfy*RCx&_C&%g^s_uj?8EkcB+(9u|4`+Fa-_<I|>!QcEg*fqZ^fho_$ z2*2;)g{IpL+$uzP&bRjbcktBy9t4(hbtk*Q-}ZLcHNXA9-S`v3{Mwh|h2r-YEx-?Q zzR8%B`0c@a@XOFX2-Y3nN8g0sSvzq1??>Ke|Kbr~d~eGAo7j!`{W0vsFONUshw#jO zx3SwF;tluquh=KM9P`2Zu^jOvBYJQc+V_Wc*s_1|D2Df+WPfQ4PITn&U*k#s@_hBr z?#7-l=mI1BzKb_(hb?<(2llOonBPuzBYr=Do%mUE%=edPGTSMhV%V+y@9{$M``O`4 z=5H4>zqhd)@%shrA-{Rod;x9KW5O(SYyTO4W1UX?Hq~)_Z_@c5b_4D>0d~dj4evoP z$XyJ(b<D$yFnlL|yTzWNH2kQICpY4ECZ3Alj`K2^@85=ZVuasmc%k@x?}^N;f1l6c z+r@6g?;_agn>PI6IOg>q$;|#a&0WNh8~!?wuFBuzuO0(_wh)DG9hX*q^BZb=tvUYc zJ7Dq9nK_dk3lZh<S0hXvue2YTUyg_I)0P!O_b+QRnTt0e9`DCr6|X3cC*kin{Du5Z zIB#zzGe&)x7~v;ap27RMncq;J1_sQ28~|8=4>|ZB9ZY30FrfdZ0KfwL&kp`q2OoCu zPaXV}gMaSeBMuJp0S@q=%64FY|1$uv0Mi^ZFu?yE09b(k$HBjL@Nc4cR*<&zeokgq zn2#2NWoY0|WAnfOQ=JG5@Ua1a1sLTyG{DD)$hf0?hX(H15E*wpUM7AgJMPbM@N*sf zd<RpX6d3T+<3HlB=T(HME(ZqqtN_3Qe2#-(=-_i5jP@)v`2PG58GaWyc!`6TI@q=e z{1W`~j(dlLyBthyMquzgjgbQbOk;<@0ACUSSb$eM_%a7~JNR-3U+LhNI(V&v*Ex8- zgRgb)1_xi~VBMZke6DxgH#+#W4&LP8eg_Xac(a3t9DIX=haEiX;4ue}JGkcHtqz`a zFpWb4gY>v10I&ex>fqZPe20T~IQT9H-|gVH059ZsH8e&)hMnR}@euqC*q>AwR%;Nx zonoga@Y@`GkAvUo;9U;B*TK8d#iEYSqH-bO2}t1I`vL$9@O_|t4gS6Z_z=e@Ac6Y_ z17PXzckqWDyvM;0IQT&af6T#q9sF?zf6~F9a_~L}f7ZbdIrwvkdkNzJ%I85F|5@NU z`!Mj8jL|2}=?L9tUj>YG7Wdg0kIi`^bf1GhYi@VwKIcYY%6H~J=TYFNLif2BWAMBj z_&)33+;;(kCUXm8^!fAFhwjIqjhjc|V|UVTa_ms(K5rhT8goPUdE0?+Q|=fu9JeTR zhm8&L`(d%u6ZrEE-tXWqIrxBszv|#e987g3F!1kS0AK<BmV>FB1_tim4FD{_lx~3m z{yx$M<@-3Q7mwKVJQii}giXLhjDLV(F~T)#pT)uF#P6{X8UCQ1kNTCp1@s#&{e18~ z5p=T-F-G2;jC7p!n8n9+L5yJ+%G6@UsDsZX_wO+NDP)#+!hNB|$6t%>nfrme8GixG zK!<?aEIwfgWat*6jNHcf4<Q2r{&OE>{B7*PtpeV|7-O;}Pk?@h#bJyPzsEyl;`bv5 z<GTenVTw11@8{a@7a&iT4TYG_8?PEx7;VO-V<FC-lF3|NQ}`X3%vF;ZupjV*=f_Cf zUuH7bA^g&Qo%m|tPlog-qKp;6Pux$!7^V1R=zbFT5ARj(7{iXVgzhI#WHQ^3o|1nj z{|xiJ)uH>dw`DRr<|4eDzRyPby?ICI{+wGgnO#@HozwF<Xdm8t5ao>XZ{dne=Kd!_ zjF7NFdc)s^)lB9iN8sLK<G&E=8lPC0K>ri@mY(<?@eB>{zl6xRA9gUxR%k%~REP}y z&mD|#g$DG$KzK0+`Rrn(*IFCi=VFZcCrJMQBYz&+ukgDwna?dy80GQLUWxMCVZVRg z+DzupcPjkNOy&#tUfiGGo5_3;;Rx{GK|B=x3qIv_nao!=hBy*ll%3EZ{J%n7dLE7| z-2?ikt^cQ9mC1Y){?A&#_>EYm-i`Esm@(?xqZ`o1?zZ?e#N`KvL;BM$&t!fGe}w+D z+cKGd*oP@3*FRc|ID+tHmfP<m;dvTs6{tT)b|tv~I;5uj0S9G(o%s;UkTDJ1o%zsg zl;hCA9eqP+faizE_;;LxPjE2OA~g6u8zS@lNe+ItgPr-%Y-c`X<bZ-t!2gs0zyf@l zgBLm2nIFwQ({XQc@YxP-b?~_kKF`5udqRWoT^J%0-X#uR>fkm9=N#Pb;7$jlZwU?j zUmhak|4IkH*ufZkga+TgBt+)>)egSQ!QBq-aqtxmM%@k#{CjDLjDKq#yw1VbIQV4_ z?sG8eacJP*bs;kTy~4q-a`5#Irg|M1@Oy0lU;!>Txai=12M;=UvxA2mTz2q{4jy*! zsDsBGe3OIGH-!fAsfEbIZ>xhR9elHcZ*lPJ9sC9d-{#;u9DJvP(RQD97;Q6sw`f*o z){ik(LYqMIn#}VVqYTb^NV&sp!D`?Zc1Qnj#(DhxB9!3;n?m<R?}hs>f!Y0Zw22Gu z58Y2koJ>0<?mvb5{?PpllnGNW+5L=<V*E+<ezEocjDLqamD3FtpNTRu`$1r)Kl3x- z*8<GpZ9$to`;pMS1!dp_qGx_B--7#-q5D~A0~Xu{%-^5&0CIA^a>p3pgjWLd_h(-M z_r;<6*>8sXZOZ*oxL+B%pMy5!gztpz=Mev)(7iPacS=9z--<FcX9w`BY<ye41pEZ> zgvBpJn>&}nb2(#_*}3-vU&Q!Bz~tWx81Dy08OU5|@wp2yHtPU>5o5Gz$51`Hg7I5` z_X00v{4nt2zy*uXI}?5XD&QW*h|4?*Z#(1P2Yv|nbjJIE9|JB~y!d>K4ORnR#ds2U zC-5@Hp9Vevd=_JTd+d|IgBG8^8gq=bz%OO|HsIaB{Qdb~2d4P*_vfR$%|8NsjitZf zQp|U{fnUb>UOWHEtY?fd<8kEQki{3GO+0=*@F?R)fcFEBSiA(|*#%DkFJOEFtcMl; z0Prsr#(3{pb3=U5DZnQwyajlX!YJR*TC6b2*Rv@9xV$b!eS6jhg)axLDSSKduJHS% z9|pc(;jaPj4KZwN(7wG%?DPaiSzk(VBQt+iCi9OdMrV;7e{&gASSUW?j&Df5B5+4} zGV->kSo${lzJq8Olb>rtoI4KoL4|k1ev86S!A|kx@AD(DQ+#M~9N`NM!jG~Y8erlT z7+{p8&;Z{PA`}02I+*+o4CqmoLIaGokI(>9ISmX3qX=SXfM<t@{G<P&0ibdd7~o?9 z01NOu2OsNT%BR49p3*ijz{dvw7GRXE&;Tz8k#T>PgVC0S2J|O}$k0={2n^g$4gf5` z&UiR-zJc5qI`q!?I3n*z^v`$bsT>9d?xzL-7U0ty`~nA4y$lTKPY(brz-KrZZDnZS z-V!21f0l#KcJMh4Zgubr9gMyqH1O}d5E=id9SIEF&kq1Bz!y09LI*E#@I?+@>fjeS zxXr;i2j?B!?qF&s0)y~6<NZum;0O!cmpOR3gVA<}2J{#Uga+7|572px(7+viduV_$ zHV6$c`qt0@uMUw3-=z+|%)x6M-0k2V2czu|4g9+zM8>}>9o*~Smpb?=2d{PT)ec_g z;A<Sb-oY<(@U;%^bMOWSzudv-t3!kMJM))_9v><nuL`M6`dsheS37v4gJ0udXTFmu zIPRMqTy${1g9jW;{a|1a{!##70p9H3Ee;-XaM{5(IQT{f4?CFp+Q7j7(Ez{#TygN2 zgKu*1xPz+>t~q$Z!CM`?&B2on-tOR=9sD{6)3_rrh~Mi201NP~4t|4!Z*%bN4!*;| zcRF~7gWu@jyBz!`2jA`BH#_((4*op{?{x569sD*2zum$2IQSh7ey4-q<=|Zoez$|2 z@mJ<Oj=MYldavXDJ_o<w!S^}%0}lS6gMZ(__dEDQ4*sx%|G>d}9Q=n4e!#&Waqxo< z{-}dL=HUP1;Jpt1BL{!n!JlyOCmsC94*rybKkeXs4*raTKkMK>aqvS9{!<5k&cT1? z;D;Uj=MMh7gTLV5{SN-3gTLh9FFW{vgTLb7uR8c^4t~VJUw7~~9Q;iOA9V0vIQUx* z{<ed^<KVw^@OK^jR}OyE!QXT6_Z|G#4t~tRf8*dEIQWMSe%!%->);<b`0pJ2goFPc zdxz4eoN{(1^RK|t1}*?T3@mkq@K1py%qIaqg=LpxnCB^HnRCMJZH&qN=WxG{@glgl z085|N0rw-o(nib${tsYD!+pTNz|{P?ir;?%pU?P8@aqR&rQH7uSp1{#{x@*Yho58! zJERSt5BL9pyVOy_zXp~xqwjx%A^vRU4|kf<cP>^KZk^XK20h&m)LB#RNSn_0C_E2X z>Ll?y7Wk0*etss?CFx20jt3V12rmHcQ~a{PW%d1uz&jN_8F;V4&jFS)OZ<?w%Ork; zpAY;ZroR&SRN!95W>E#WU-5eZu=ekCU};l{-<iNVerI9Z4RJPx+|L1SXFLS_Lf~5& zqx{S|7g);pa$uyzip$uY(hp@}#h)_X1AGB+P{(Y3uaG)H<>h*~qYPQY?#Odvi2o8y z!N9{B>%KC_kldHT{T_wefIq8n9$4BiqVE8f_!I8Jln!}9X4Vqm<-jkq*e+TDk2zTC zBd7n1KjFB4p7BHAw-Vp~wd4L&6t6-VG^PdVaW-TFkjKU>0B!|F8W=<2-3+{%G5f!2 zt%IdJi2JzX{w4?SX1p8xF9ClkFBJaOz+Yo`3g3Ca5+4d5@_W@ku{(wD2H;;RekdCk zqfQt@{JMcJVodxHw~H@lO#G0a7Z(^4zfs`rjCTWr_F@Sy@w*cE&lEqDjf)>s{7{xJ zMjK`f@k3f%f;wjm@p~yS%78J%4{3SHs~A)G;C9JY#uUEg!0%#A{NQ$pq!;m92mC0z z6TkJqM-;yoV+laggZNzxEbR&LyBT;5(-XgIfd>@74Zyc5eyf2cJj4&_{gMaSo%n(F zC7)+Z{H_E38^#X-zY<Fjvl&x-dw@~rjUj$l03(f!A%1rN4>KlysK2Y<&6xOY1pYW< z;)nEIEn^zuhxA=7=|lYP0)A5Qdo5&P(54$h{5AojO)`e~p>4nPC5(w5>guJhW=#Cv z0zAohH*i1j`xw6xco0~^$MxgV{mOj^?tiH;;(96iU}NZev;~(Pr*I7zbs}(w-<Msc zF#7V#kj8=gZNSpM6Tcn6_bB(ffrByhNyg!_L+sAsT{BnF@62S@oWXb@(gWdLgED1} z{eBJ7$e88u?`?3ukumuXzt@QW<c_v&&1aPRF5vGmCii=Rr9N!}-i;$RQl2?{-I8B| zbNszvlqqAVzd+t}zXNDK{vKm2{+)#QEP(rAOP=WlhF?7wFsASC1E%^(-#^ayVRonT zf+Xnq6)+{mLAawXT)u+c=fiytFydqk@%td~BS6IONybO4bEXyaNc$_$hgw5Sfzieo zvmf;L155iw{5}jU@gsM_f6nyez6aZIRG!E`3LoM1>`wlnd|fHwqwqWcEd4Ki|6nH5 zi#9k2FX1u%p4>kM{55tb{=hFiRq?+Q_y)$re=o44AAOIyauv0gk{*OhOi%8g1g8D~ z?z0wIymk${Q+Y&vSi6NW<=-2DWe!34^LiW&qwx(T<q>@URbZ4kV~GE!GMRNqbHjfD z<5A_l5AIZ6#DCyxy4aok9|T65VGQ|?vT_a5$Qbe;ys*s|`u`<hX-~-i&jRm<JMky~ zfnO&1|0M83zypRGGXX}MW(`FO_#TT)dHNjiV~mME()!xdfx$l`xF2>&4|4yIqDT3? z_9u!SxbH&cz90Dalsn;n0VaM_zkoM%!%l|$Lwq-&%mw}fzZ`YK7;--VOzAD*BTV5J ze!$mVY{?Bj<ll9azCsWDif3E*SvBx`1o&R2H%x&4z`_6MV5$E?|LdsxE73++LxF;7 z_C*%WdIJ7^1DMjo7<T9J!W@d<K`i-R6?K2rEe^iN!Q7wCZpHWCf-0k9t@|v@k4P^3 z`kNV(|KA1X{5JkQn#sKS73_Wh?%xOg^C<sUf5pK+i{gzOKbr}e%*J(&d)dKGdT;!Q z<Nj9;{;w#0jg!8wS>?EMdoYLMgSfs%;zR8#NMGxO_qA>OJ<UH)f&1H{{9gNE2Y=MT zl7Ex%?+5t)r&0HUlwU3{h37f$)LxP~gzq1R7(=&(lAZ;w&vRD8{YP;BA-fZPB9qy4 zMwEV&)4y$U(tpz(4n4|<H7A)z@dO9AI(Vsro$wY19rwE&?4)P$VaNTO4n~?<!{Iv= z#r>42##r}$DIb*opzS}~y3T3={t56Vg`Wg|zrtvn`u{=U!<o#$Vug{n149Zw1^j@* zKL`Fdi!%?xzatP0VE-jQ2RB&vV`%*H3%EP!G58t&p3BSNzeaJX&B2=;yv@OHcCa&^ zD<Ms+vFTUh@Xw?2^-FBoaC>>oQ^3ChcIw+^>90Awn?D}qx0%{|V=VtI&vLNCZ;Qik z%N<Nl^%s5PmM=TsJLO^M!l?Vu)ee4-gJr%<{AWX~M(Qv1$MZ6ovW!nSer2bAm0!*L z&IA2?(BH+F_#FrQfvA6FCw<CjgN=C(=u!8|PJWlAe_084<i!n=Uc?_`p&Mj8L;gP( z_?^s;<|C&8ql{W()Bi?^&-HL$l*!yE<%Rg24tyVzp9PGu#f{v*WKIM=7g)l}>2ag< zkK`ZH{>J~{?;&VDyDgI$&N4m~xD#0Nhww_^E7|>dz%K#rXM8enH?V~7OyFMN_pv*L zXC1JVXIfwE1O7U@Q+!a@hNb+S4tyQNqL9YMkozlu+ZogN_Eo@=pA?^sz%_QK_`DYQ zt&Hh=jIBrRXH4NK0)Lt@eZLtPeY!F9J=%^DonB>ZNzP^W7r^~S;By#r`i{Ps@yp>p z2KQZzseIl9`~$|90avl5*}|CozZn>5XbjQc0*o*ivkCYOz!E-kzb%s)Lm4pUYGBm8 zu~Ehxp0Uq4Sp2u{eYN7~U~zn~uQpyPjw~IRoXixiU)Nq5ujV?UZoTVr`N9=zuet2f zwS~gELN3>Kd3m_hUD{e6DD|%E%N15!Gf}g!2c~n|c)3>Ux%R4ceTB~6YIUO2(=g{e zIE@LjCiBkqjE`5wry6W0>K$t<12-1?RrCwFwrl!tC=JxerKhJmk9lRGP#f4>Xlq)u zyW5CqgSk^L4ZCwwU{)v5rWCMxyrvSacqDW2tU<|KGhD1zDQ9}umUC1($xJEKGxKRG zaf+o+{V3&agr*p!8F{2)lyAShGCoqQ)k<hZbZZi8G2)3BZ8LO^G?DAH!Wv7RW(2h! z(`kh?o~rdrjJFcZB*~}Z<+NfMOS<|#daFg_k(`l_DvmSkNTpIZT~M_5jdZ@Y^J%c3 zi1KlJ@hSBZE-P;iMf*u=xKc(6jc1nYx4*Wgr=cgjPPZ-{`!v(m<3TRwL$nodS_;gh zKsFj~<;V2H-Kb}3Fm&`iQ!%SsooCb@Csc-L!HtY((8_g=Ow>w~c089tiAG;jHZ;he zNh6pL7xK699E+!Bv}$)<UM>v}R@bN;YMgm2c1`5%wnz<@>lwu-o>*RABjqO;3e3po zSW4FSIOv{d<guH~P7aQj#wz2ro@@ImzL{v_B_-XPXQre#D=zU;5>2$G#3oiCqJDHW zD>8NbX-Zt&%=eb<_`s%Vah#_AO^JKFuy|vi(4;ggmuD1;rldoxoYhZ;uz_n<GR!0p z38@erFXX%I(wkilytcHZT&;~4YnAa_dso*0mI%#~USE}#p&I_ObGl!4v`zQR_7&6p zGQVuvUoM~Sm+iS}f0=i`Y-m*HHYm}ydBs3wbaQ#j#5gVA_SM=)ietTfRs5@U440}^ z*n9ely+C8d@_6r6<b-Kl(^e*rviGq%^o&N{O?huC67Ncma+=Jjc|FQui{+O$$s+wv z(C|(_Xwk;a+3Sd`wyeohEtyh_n4f-I+Tqss^niNODz@M-jR>?)zhQP8$&Os1P^}ef z<$*$Zv|K9}hs!quRYnU~N-hkR(Em&f7~EDaXMzo=?m~2}+3sA)_EfLe_4@1Ab@o>( z)ta3JcTJ2A(`L=qp4^H;Vg0o|8#cVEaQVyEt=Z6f&ALJX?OBwb*1{4=H(X~n%^IIj z#H(Di9isMhL+{aGI@OTIDqs@=+6d37hBKa`p3<MR8PufYo~n;ijbkj`>U$V8hSQ4T zj6Jk5th;FD_KS&StO=Z?TIae-lLMtO)3^+lYQ^$!u6;|XR_HGd7K+1Y8?am0LCJ?L z>|9%Qs5o94ER5AK<XP9(hBpJlmC+KYt0mAhv1w>HEgEla8eloijPe%1_y9%~zA5M6 zRJ@pKg>n;SDt=A1b)Jb|4dza~4V->OYKT{Z;fggQ(+^f7tQrheJci!vkBlvY<<hB? z=$U)eV2omkQ$Iq!{-JIaovA<W>OtxNJ7)&ii9@e?ygW$|9|PC%V?$pvWTH%w>2nrN z(xUGDKvf+YBQ_Yaco9^5(0_To%DG=fW<LB$Ln{uk0@H}^&PUVsd?pQVz3ghFbotXZ zE~(@eOPjs!3{T0K%_#ppAx|A0$5J9zI6NHvvRB@SdD6qv^7=lFkxe08oHB;}_;@&+ zWQn$zv1D;L`WQx2Mfmxm<_V4OW8bHdR3SgYRB7tK(KbMhvviA%D|0ffa5{<J6rM9{ zHfFlb?a6tk97cyCQ_Y50iq-c}3aTwiG4Z}=dc|Ao*avP&Xy6kk)D3*$gvt|3x7kgI zUM#deR*_048AKH?7I`-&b-79E`?#sz)aUHu?aa{{{mc`=X?<#A<NZ`iQu_#EL8wc_ zt=|>bxno6_mB`2RbQzHvy9gNVfE)Ovjz0*^RQ>UPGR4(Fr^LB!WNuk?VvM9Eu*$L7 z2-Os*DW0MyZY?=FzQm&9DdA3QX$u^>!J`$=`azKPph-c9wrocyp<O?`k#w4p<TUQ9 ztzBLylq<B-kD_HZ6gStd?W-*>SE^<ujSAdVc9lNYM$7Ys5}nuR*fvzGSphe8&F5-E z*pD78jF+mFiSdC_jF7p+7x~n}9m}_3^}Z2mQynZ}7cUrgR>ukhm5EWRG_(@vGEAat zfYmay`BB+!qaE=!-vw_=qjUnL!0VEm$15X++EBULb2FtON5@&UEO?eYRcb)=REg0o zTT?-_CTn4oXh<V(gQg*u$H9u?aFlr6Rc2NgacUpfHmJ^=MBG*k6voCY1K3?Qd_7;U z*o@Ogh0)?jiHkwpgIxROiBY>(luEZ^2zx+vSmlPxSlb<)80jyKCwrJ5E8-l`mU`i8 z<G2;doB+P~adA!|$+csn3^k&<eWbrKTulyE8`G6<PEM?46V=jqYJdzuYC`6^ieqEL z<pH~2=aAY%U%KL&;<K)DU2%A#l<T0C_5nJV<K{#MohwUm&*j$?M{C!Nl}76kLa-1= zv?`_Qx=O8Q5~3_=T)Wnn#z)H4Dz+ZGOQYq|pr6<lJ1r%{;`Y1)C`%?*f<~3*_TJI0 z*xVenhh_ZCO}SWcX%$&RyAmlx`Mfz(x29Md7%GilI!sOB_P$bD43}Mv>V?9Z!Zp{~ ziz+`pS{zQLO>8Uk<E71}H8k5Kv`dn2GwnC_b~jhhP>y1kWfV0kXlNqM8hYliH7$>f z4Hw36`Y)x?A{tQSF@g^^Z3^gqjyC&cgXQX2rOLJID8(U{qbf338ZIGAj3myA+V-)M zNlMdA+M=ji-%hh7Wg3RjZ8v}@D3qG2Co@tS85rBH`ib;T(u&#-4zD-I506rG<(x~D zeXM^~V*k<=$(Ql;5SPAM*H)a(tc=?&o372~z*^^q%8jK_Bg>RWsgb^~uZjVG9~D+B zd(gXnpr;2#c|!q*Tp{XF>>cRotL59kWE)P-7I4hfh{zRc#VwSiebtV_wWYBY#KTI= z-EaecrkwL_a4(IF)wW{<GX@ce$~fvKwHJLgl1D&yP}x=(u55u|gsDR7uNue{UOu|5 z46%r7OVx>y5^*yv#xibHJI9M<TPO<ylSR9S35mTzu+2$dP%7EB*$RHN(Ikh<i7=vI zu<(I?WxkacHo1&PCagH_N}ggUFkF}zElrLg!ApZ+)K^=96dEayA}DkycFW{sVGMz& zpqVKn`djIQ>;}k_t%!s(8nduq+bEk(B8;y@z`RzW53mWkL6Xgezh&bxkM=NeU!v~H zySRh#H~KmffT)wIzdVA9bzz>+#AtMgypA?hF{fzAV$Pn>xqYTDbS_OKbUsH8o$KU; z&UKE5F52UIf)*vv;flN1Kt<n2Llkw31t;v*;~@#%R3M@+jsM}Rh}Yrkn6F9Wgm@T| zC{>8kNKE*W2qK|PB8r7w1}yQgii--Her3WUFCu=+%a~uWkx$&y7>V-T>t>6LJEV$) zC-$8V7`4<vYpeP_+j{F$p0;6AB++I?x<S)H#;SGH)vZ<$*Ju&fPGJ$$Z<DfG(@2)+ zcd=yAj`_Bz=${>nFB=;#kJg4q-J?E`8RXNNyfS46=F0|#Xe7$>F+1ka3l8j|S{UH@ zS<pvO?yu9GmSl*B8PBS%OTx;9L@}Kx!YS9~1}e(L;~x3mk%P>PF+02VX~iSaVPlSl z`AC5#*A5A<P*DFpG@9=y1WPxG<4GQ|llYV#vFl<l%Re*V5oB99q%f7W{xVNO_{`Tc zi{i5Jk{KuQw4F=IR3jPTf+5;8*_gsR&2PB@3)Yz8QJ9GoUA{EN#i^~361%YQxJ5pw zpqM%tnLbs};<Y-BT55RUms7*z5!YTB4KSu&G#Zge-Sn;01pz5=9-!7OPf4W}YVKVg zCG9jc10rF@aAg(q9_}|1i^G)I1Xa%yfyNl6m(9j_$eK)3(x+a&G#DhyW|~=+&}qyd z_v&$+PDUp3oL-(LvYT1<CbOMxPS@i|y(22>6neI#GL`64Pfw(4cqaV{N=j1Ts6n4f z*E@~KQvsV&cQ{QyQo1B74jv95rr|@_tRMa2GR+~^G-9QEYF<T%_F+e%^rw0d7H8d+ zHmjVwUN^09`xrN&M7wO8UW{E2REcUvLzl+h&Y8_-i#iT%Mp2P{sGgqiWFCfCvNmlx zKH{O4T(z?t9qg-eqS-}*F0Y5Nse6j2RMRjaOB~ekwr|*6sj+J?svst*qgS`h^D${c z7-kTWVAM5}h=feihTE|uO=>IM@+Q-g^wH`}*-s%KrXFzWuNp6F4f78Y{wT9=PVke) zKeQofCt0XaO^Hc;pPG;x^*!P4eC8RS=2dgcKz*OEsJFauZGQn8aZ9B4Ak=eU+UDry zA$9_D*vZ2t?LaM8t@ZYG7Vs*fCjoDIKyx)VZp}Jc&w40T$OT>$Mk|B%6k%TvZ7+7x zejGLtq0x#v2W&R3kN^o2IvhP->Msr#M+Zv%>k}BZ6|U_onBCqHtg4v(xqj&M7{x9f z<OcW+uS+p1fib(%@@5dsrlmwzm=Y7C<(r@vSRx&X#9#@Vrz54&T0-1RA{~X`EpvlM z`I&DI(%)<g2YbFIzw3lQA-5?4&>OI9pfWOslciy1tD;dJl|)Ek5@_h~6i=rphD8}N z6KIvnlUOeAvIQ<FElJylQ^xVF!<e`=R>m)*GM;aim)^qEH11O^3rGbOxducIa_wPh zD^5)Iti#6tmeC1R)XChk0$K*>)g2BC+j=BiUk8%f`T{AAk;>MRnROtGIv{@tVS&nK zh%G>uckck+<*>~$j+U%gu2mtnU?vjR;eETMC7HVZiOor*sQ-;n(r8>{Vem!1K$4IM z32}#~G8-U&JFSZiVY<&<SfeaLe2bg^4fuKrF<fCif>>!v<N~QvS=enfgdu$$e}pix zhn&GuIr5zZ&5s7_9<vH>`im_SB;!&XxM`w1Zi^cGD3YyBli5PyR6dTQONBgb20|l~ zBrL3)iv18$r{<HR-f8w#LMfN{5_iwmYp>dXHpej8jD9^Nc6PLAVcdDe!pf)&Qll{_ zfc_&WJ(4*ai~N`tP^5NIM@dqM!g&<B(dB43Aa;amNBv{iJ<(vobV}A=*4;Gqo<Rz( z8HYghD2z>CZ5S$`;!O*rxTUeENDH(99YtrsNG>52Dl3B4u6G2DSYL(mgyfyN3I+a# z$2Z<e>+xYjVM81I=z<@8?FHKFMaP68%<z;MP<mOBBbH?DG(xm?x2})GZOu-yAz{(h zT3LjVX@b9^R)G{3HleqWzKG?0rL860fUw;Z0JDhD4#q~UmJyd-j?o~rr4MKcU0F0( z4%tGe!l{f}Kh4*X-D^m08BsipA38QeAgpJAg#E%n;|&Cn5(C%(GB!+pS)!~mQ9~C| z7%z@)DcOu6I=nRu)BvFxly2j{cSS;^6H?Y8Qr0u9a8{jllbqM%TufSbdO^rVB^sv3 zB$R!a-uEH_F}<&2vJz=*P}jmP7)3Rq3pOp6<o||f$6fC$Do4pBCP^YBJ<vf%%>{o0 zjRv^urG^7xk|qZZ&Y;Ie#uo27-E{}G^`=D)Qwc*Un@Txz9Ll7|biC&Aj3_GZt9C)I zqPztHE37??63w<Oxy~`jgwjlG#ENVOG*gbY>7lCCf#T?9$r$U$iYkPQA&@>%>P0iq zLp@|))wIVp_acj%W-h9iEu~2hn*6kpWDw<ss5>f%Ip)YTd~GlER;mRO^&dgM)=(B= zFj^{()08D|J_ZA57c<}5c2rA3BV^=JzEBRPBn=HRgMPoE7=_e9Iqv91LF06}B6({p z-yX^*K=Ba9)ltnvIU_L48D^G@FE7$2|8}Q$u`$;KxsGw8-1Gm^_AX#uRoValKIfyT zps1*bh^S;}UI?hr@RFjUdBHm>DJdB#nU)t+DpFKZDk@U)Ql@02j-i>NqGF*^q0!`p z6qO2%${I6ktenaDzxP>tvChnQ=6m@+&(G)iKHt}@)>&ttwccy({rPZE{W~DeKhC4e zKQeYCicI=|<lF^!ZDV7cj~D;Vjqds<kBEC~@1*x0>QhJ1bi04~g$WeGxtHsA!klDr z693b2_kWkF|Mo|Owb`W=;3GHs+$3Cnj|D&a!8s2n$%RvsW~4?$;_t6ZeQbvLRhHTp z^z}2~ujcqqtNo|9pR_B#$@4ESEa|tRYuBLt{`uzmLn8eS&A-3#KSgs6zmMZ@^?WdO z#+-Tcr_TJJmiXU(x$it6ulnD->*4;jvj5$U@QKZlb8RmEUwp#&*9_`|(cJ&OdjD^h z!Kvfu|N4s#|0JOQ!AZAw?NN->B%6r|qz!c7qH54caQ`Ni%Q51={-nuu)qg#Ex&Gt7 z9H`{KxK2r8{Ex>0aj88WiRr%{dGvoXe;rr&zk55>^=$wC^-;%xYZ4JTYxb;%W<S2j z`31{}2-p8IflOcj4}P?wfBpqY*Gm4)f1oS)bAZeDpG>vu{MR2o*AAS2{SUQQ{FgUI z|M`Lb?SIDCl&;^+a81J6+x?q2;r?}a{BM8c<E%%PEBl{$o9}-ahs5$9$M63k3a{lq z{oufTr~i%5f1Z`{v)KQ%y#Ewm|H>P+!2kJ)|8q$9gZ-OD|KHb$faa(|uWZvX;s5{N z(d&E`|L5aF)Qq`t^JmU<J{_BZ@Xrndoqr9{TiHK*nSU427tH^rW0bOgVS6-~?ddN6 z443~lmw$oF|GLZnhWJ~-;%|kBzm=>!%G}pV0h{|;__sm#z-}$Z|K%$CAMCSESx;+w zC;Z<A_`u)s$ustY_}}^P=Q!J7*FM^RmtpNwqU-{WSqf(VO66&w?fRM;u(sp>>>OpU z*7o|~Jg~NF#<iPG9J?H>?f7Hk*=zl8iod6i*gbJB`y7emNs~ApeJ^ug51xzf>$&2x zyW-bDo_RfWLM2WeeJ>NI&S;5K2f3}ayW-a=bHzF7ilgtvac)VRx-n9(x}&8ob!SPO zy80PSe(GjOoVuB=IIjEFb>*{el`H;LiSOkl@x8nyzE_~c_d-rMZ(a!!#|!^{FYCt( zYv8<jWx3+4bH&-<ic{_KuW|X~-$~ws{Af+q!~f^_^;~tS7b5=kA|-ykD2ZQhjw=rS zZPVH~SOc%K9<;&vthdV*r_dD#^{Vy1CI0n&C4T*2iC-UUVE_8jF8?7CzrIVi^|M@Y z*16(f4YhHKTyaoe)=z!Zm+R8NPy8GBi+_VqiQgbf;y1t=IDUiCF8?Hn-yqo)KTmna zXx-x9+-{JsJYzMZe;aIrU29U?3t%^W-JsBQ-!j*IPb$wieJ%bpz^oW&^xWW<^28gv zw-?yhz5SGDyt$WmAlStB4pE*7>>mnd|48MT$o42O+hdg{f#bx1IZl%DJiz|RVD?Xy zJb0%`9=z8{-n?D<@h)?%AJ163{%Yl!#PP3yIsOgTI&aE4eY}-tvhnx9vrjhuKAn}l zitW(+Dz^8LIqVZ7bJ!<E>g6*_>g6*>>gAIv_43J)y7=TuU3?1VxqOP{xqR@vTo)fa zFW1EfHRZbaR7qWY@a$X{pR2CtMcuhB4N-TlOGDI}>(Ve->e3K(WSulb9XZbp6D7|L zQAf^mLp(3vw;`UF_0TX=^4u_6^4u_A^4YLJ^4Sp2$og+sA^B{G=Vkpj#PhQL8`g;a z8{QQCH?k$qjZkaWf1@yYu0~PvT#aHR&y9vio*RvpJU5D$JU4=#`FR^55B$81@a&xD zM(L90Mmdt_M!AybM#uxtnMT`0|BY%~>qH$n|BY@*{(Ze9|Gs{*9$$Z1k8h~t-xtr$ zI`@qgo%>=&vCe%Hq%OXRQWxJ$<$1*Pg)i#(i0KR8QaMNYVovfo&9_?Fx7hy*nEf%^ z`TW+{OU_q~W0j|)_Q$Mi90%6^niG`gVH2k@wD+)y(|DGgwHnWnvsU9&(L>`jW8a84 z>2lU;oFQke#+jm-##zR${V{+3;QM0!{K5Cd{>A69#@IXfJk}U__>KLMhu_%0+O?kR za<3+?eWZzNA88UI`fq~T@%(SnS@ho|QuN;hy5%|F1UY1#H$mRGf15z7te+;cMCVPQ zRh}nJpjDnHO)^C1O;Bsrc@t=ub>1XTblzl}=)6g>=)6gZ=)B2E(Rq^!(Rq^_GUuB> z8+=Y^if8BbHw}~ZH|-<(Z;I#T`O|c?tg~sntg~sd=)WnRo%P=|Q}o|7TlC))b?5pv z-5~XCS}JvES|)XAS}t{IdQ$4r^s3aQ>2;}#pPxLJA7(Gt#ShQRbKVcn%XRUKlDhas zOI`f%>|7T=%qy;oAL`EY#}9SqIq!#B^PKlfle+k2%I6xtZ24T{S1h{qE0JFFE0tdJ zbDcN*%8ebLS^Q9I{#@f%A-(2TWmx-Ml|1`hmpnJK@tFjDWKB}4nKu}H<S=@K>(VUH z<&RwPzTXVFVm&mAk^D5%xibCO4BFs*zZvEU>!BHP!g_0#A$4iCLF(QtPwL(*U+Ufr z`se+q*)GXjGgp3^K^xqs%_>C?&2Gwlo7-~V=Dwnb=Ki9G=E0(e<{_eo=Ewu<p?Rb{ zZ}S+@Lv!ea_0Sy8&U$E`BzkB*OZ3njn&Hp6&Cw&gPc_ex{%yWX`nP$J^lx*_fBr1o zyhb$B{EFzLIW)jJX?|UF()_0Aq=m2aX$xq8_o)^kqK6itqK6jIqMsJ{tjGFkfx5F! zTHx7PCoNJWZ!Pfbtdkb$qLUWr5!OkIJgHX;)SdgcMXA)iMTN}y7Owf$;-=)s-%E7m z?=8CWN8S0H<Bz(tuKYtqKmMIXKmL7WJ^rz>9{<szAO8f=k3VY7bKXB$^y5EA^5BoU za~}LNML+)8q91?cf%W5`FZ%H>6rK1(5B#~w|AuRww`83y@w{A@mUv#SOUn>hPs>nQ zPs=E&OG`XE*QI5==%i($=%i(e=%nQ=(Mii($$!grlK++)B>ye(jGX_L+oZlNOQgOn z%cL$Xb&s1l)AG7JZ%f_d#vb4$bqT<;^PCUBvvXYn0;Mhi`q|C7A^>&gx&%Z^T>@gH zE&=gUmw*JROF**pb-*m?>j3P7+}8nFQm+7<XSja@%A|h-Tys9aHRl6db3VW|=L0a? zSMmCxf9~H_UQ(A<-cpxV_>9l<zg4L8Z!0`6>!cN)mvz!APV&<Vn&<qqN)ny4N)es3 z%9Oga%9gsca@Dt$-uv{vvskHCl``L2RZ0K0x+3~%byf7!3U%lHZFN)h6X-2E3G@}6 z1cu0Z0#RSqNg#C2=Yc@zoOKcyD>?}rB032~-B~Ars5|E&Fhz6{I7f66h&*ur24;y) z0&_(tf#?OE|ADT)4s`W(pesLtnE8BuYmJ(+ep>sAep>q(#u=cszs&#EfoA4+f<45r z_K6bxwC*GNX+1>r(>hM{(>h7?(>g`;(>h)B(;Cmt`e~gbd25Yl=e)Jf7yYy@5dE|+ zlX|s2DfMctzw3j}wPu2FhGG2#1&e-yuxD|8g2F^UL6M@LAk>}p6NI|+{0WK^{RE8` z{RAb;dV*%jdV<nKKS3FypCHtl=S)zx=qG5M<RJ)k=R5=zh<<_!ML$8v1M4TKT=WxE zDf$Vj7X1XF_j%3)-I6)eCR%jTrjO{PO^oQIO|0mo%@EN^o6(|^Hp!xsHkk7~XWFER zPTHi4PTJ&%PTJu6Kt3n5!SnK*X@lowowO;D{In^R{IsbMowTVEowT_rbqThmF2R^@ zb<8{r#(b+|_J!ci$}@%S(8CnAr^@H<VAPa9cL(DP_A~phlh5731@gH&7(L6MyMxQ* zb9XT2_Ae%WTWE5liPN?-nC(%@Go9_w;dHjgD^C*J6Txhsqdb`D&S&<vSaVxuthtr; z!Dsol&|6#Pd}Z(CINQJ+2f6j|wH09YufmTi*j@uR_IAF?)6Ur2`GbwUJ!<`{iQhgG zY~r`iRkrR^{ippp<!R3h&4)1O!H4~~!G{^z2w}b=x@~_|blYBk#z!1I2io5-_KjfZ zpU=AOZ;6IOT(biAr=J1AKLpRh--m<*%l9E6&<TGZ5)vlghlIo^`=(ic$PlnuXGpxv zpO8eEKOrf~GmZUGyJ_s7A^j49yz%!NA<)}z><_*1_ZuNa$}VJkF_`0&D|>;qqwXOU zU~Si2r96S`kNFVD{#TVJne8{g#(o=mC&<`u^8&LSy5;X@Zi8<BV0)CZ*Ry{gFx!(| zcFc!bd#dQ<Hmw=<-+<oaIQd|<Ll4}ix9tKOdxv1@qYk0cM;*}1+(#Xv!R$X;`lv&K z^ic=sko%}Zp7c?NeCeYOMbbwd(97IM9gt`4qYl@lk8Vc}xsPu5mOi@OPx|O~td0BV z_894-&~1{R&|Q+B&=TpRQ1mSKQD~X;Q7AOPeH4mb<~|Cols@W+yz%Gyj;JZ?tz)F< zr(?9}rz6(J`so-e`ss*#vVJ-upRAvb$)cZ*&^+s>W193!M`)h=rDL}AOUGR4myW0f z_e)1;fcvFmvFN`ea>DxWh-YUVc0^rRZyj&A?6<_;$xHIw$yf5+DHhr@I_wk&Hu~v= z=Vcvs!t=5YJ7EnQ*}qJ5*a`V(9d<$wvJN|;*La?Hx+OZi19@g0-hn*xJilXz=<tq2 z(cvAbqQg6oTh`$nxuU~6@<oSt6o?M*C=?yufwi#?@2C+Sc8QbxbcvVzbU|P9Jnw?~ zvJSh<5*>D#BRcGoCOYhrE;{Ujys-|ul!^|!REQ3{REZ9|U~R0!E>}c{U64=KVHf0+ zb=cKgblBBbbl4U8=egY#bAxr*75d+7>ev<f-)!pM6}4a;c8vqGJxO%f6**xYcEz)^ z4!fc*ti!JBT=qPd-PP}1cS)YRUV-*_J=o(|hh6c!ti!H&Ue;kZtdoCU&<&d5b4xd@ zlg};PQsmsyEnUtn-7@9e(hckU#oV_W*2(9VZr4TU-ENA`!@NZ2VaPM<JS<dn9u_7# z4|C}}3~OechhfcpZV5{iork$}9)^6f&cj?f56c&whq-hf=F)jsmFPUIMsyzT(s{T` z=i#U+>pVO~bRIrSbRLdc^Sljr={!7LbRJ$L=a%qdIk$xC?=+BSeQpWo?|3(YF+=#= z60Se{LvI#7qlKT8&p6@y*<btPS@_%%epSvb;Wy>n5)Pg4&v7FBME?<iqW=i=0_#5_ zO!OZS4b2-pM4)!8|A^7jzY)kA?;{b=8=qSupf^6ZL}W?7L}W|9L~M|LkI0vPk0_9S zkJu&s9#Jg)9#Ja&9&u9oJ)%PTJp#Jrb4vtt%jcFzFX_ifU+KrlD3`sD%N{H9Fj8yA z%z;SrvoL#}Qjz-SU$8rzqdbq9yhW}9vwxZL3}-vmJe=*-%5x{%uYisHE}JxCLnn8c z^Qyz<^P0T^_E>XY%^Ajj6*$w_HJ2FsYhbN6y-x7m93NV`o8xQd_?y8TUo*$w4(9lp zIsQ&C#|PiT@$uclJse*%$3F_@_?kKX2{6ak%<)fyIX*aw<6i)Ce9avHTQJAhj9D?$ z<T(l&n^{LWf1=Q*ydOmsi=Mm3NnN_fOI^CBntaYvs(ZT0r)JD0u6y?lQuprVQuprA zC)d3@`j_k8{i?+8p`Qio)V1#6ZQ^Uz&!X+9br18|+~G`PUj=)X@z-2x?5}~#j2(P0 z$KMF%_?kIBYJD%q*Ua%z>w7uAW{!_q-^=mA(H#FEnB!~a_^5R>$Jfm9QR`@qubJbY z26KFHPmX^9%<(mIeAK!p$Je|~>fRIcgzMf@*V^czXNlCk*J!CruLP+}FY_~Q-Q&Hq zR_jo|_tHIX;`GXsy7$sO&h|>FdoSJNY`-q?d+TR`-A1i@>+kV&e9ih<v>kQt9cS#C zvy2_J?wxJyn#+v+HL%%7bieoE_^5Rsj<1>HZw7OG%^V-K?!)mlb9~gg561`J$MFw> zIlg9&e-zB|HFJE_`aX`Ynd76@_i=o1UygqP%<(mIeAK!x$JeZT9C_1!`W8yv`|4V= zy;SPnPxrX7_e+$z^wT}A^FL3iep;(_4C@|ef6Nx1^Zj&>v%N~{-cR>9+iytx82v0d z{$izK^mn#8zGnR_+KyVsnD5^l&Ng<`Iwr^XYc4nT*T5%@9o(PeZv=CE%^ZI-nB!~a z_^5S%j<1>Hqt^X7K6n7fKM3adnmPVaFvr)-@lopm9A7iXN392NeDFYye*w(#HFJE_ zdLYNwta}`J(|-mQN!<tPTC*KzEk3uz>K-@t*d(b-tnP80|9MKqYOU5Wtb3gOF<ZFq zvAW0Ejy;{{e5~$qw%?TagY>iL_=}Yq<Zt3@*3Y8tsQaLJW7nKx?5OpiTw~XK(%4@E zR~S2ZFvs5r=J=X9K59Lf<7?*lsP$luubJbc)`K}d_<oLm5X|v4b9~hLevYr1<D=I1 zb9~JlAGN-p<AaBA{0m@?ubJbc)<ZbHX5Hf^&qIo(?n88~*<LPnAF6xY*oP)dU4~wz ze0r2pLs7d~>~n*1>)7?r&0)8HfzK`Y)PXbp4AW;4u(l8LQl8o7+F{<xp396g=Un#p zgAcR6@;uHy`e!s?&qBlrhMj#v%o?;kmOe)~_r>=W{CQ-U*{3}1;A74w4zDvYo5Q}r za1c1(#MJg}hG8Ebs60=Y^$ZUIn>7sQYw^E_=NW&^MJ6WV3@<jU<CGX5Z7((U0C1VH zYsMJ~`EvdYHyZHhYtd7~%zfi#DeEcY6E_FU_H^VM_Mym0Tm~3+hc_tC9QMb2o@4w+ zq)6RI%#yl~z~>SE95f<dJ_n7!tmfK{K>u>>MkbhNnXc5xMDr|~3yi%7c$cwjt}*t$ z;48)s9_1_XM?nu9e^jXP9{``u#$U71zh?s2=-=TqSDbWL9A3|0`15)+>op)ho^Y_% zJo2M?G}bfE<ZU!GInU&6G(PKXXL|ye?b*tc!uDJ++e?&ZKHJN{Y`@`(gU@9gXG|Z7 zGbUEzj7gPsj?vmi9KFsltT*I#jMkgBYrby$k=rrcv*5ANGuLq}dW!QrHq!VHfKQZ( zqdCslk*l#f=Q_UT9AiiR$L1Ql=96T%e*;&N-QlaslWOuX7V{((arB>Ym=6n#eVjL# z?RpKc+kb~o9}`FO5Xsv(d=BNjjmwg}jmwd|jVlnHkJ}|WALlyvj&q%V#+`Keqwn~0 zXgp>Y_eDIuL*Vbn;xQ9unDxhZ2AlQA$4WoOV=i$&#?O)Om*P|9`=#-$bL3<^;_$p3 zA4bov=k0h?BRyBgN6EY$A8qoZ?a&X;+wn0nZ^y^Vyd6J8=I!`6nYZJ0eeo=M-j0u# zc{@JAtU=o`XZGml?F-H{^H%dNb8S0tq4C#j^x(nV8((33Fw@3Y86R!0HVpfO(K2r* zB*?s-z}F(b6O69(&lo0LH!%@s!VQT(;ikl&aLd>Ol$vN8yJl#Q=j}vaW5*gM`pLYV zm@o5o;x?JL6Y+Zxdfvw43^1{X>g#ZY%-e}oGH(;|L{|xz!>p@>3ei<UmFVh$FzM3= zBBf6s$T80{U8x6h&6+jyT<rnoxeA^XZ2VE9Ng>8xGiD3Vfl1H<&w)va#(w~Ol8nFR zEMuPl&Ng<<yIgS!U2%9lm=%+FJ>bcD4O(NEU6ZxuQA3BZ9-g<8p-G;%le4AYC+A4N zPcD^ypIk2eKKZ81+eBODZDN?jNsN>@iK!ANF<s&$7RWjiwYJSV6IpM_ZKBqjwu2w+ zZ2Xbi2f1f8L(iP&2hmfU=Lb`aKXUuvEE7j_rm-Ve59*xj_?pX%9XWrn+}OcWyveR- z>=Zw;I~*$Wb_(VR&)X@O4?J(D#K^pzqSt`B=y^LO)x^=9A$gmUDS4YxB6*uqCV87u zBRZdQMRYy|`yHP@r`(eB=TvX;pNhWYzL<*H#q)M5W<Jl`sh9~oZ>J{7yq#*!Ke`8} zVlL@<>+m+2w^Ivb-X^iml~PHF!}B&NnVwzG+ayyXJ#Uj{$-GUPWAdZz&=1esq%@hg zN$E0glQLx9CS}UJP15z%y|55*vSr>T<(M^SyZL=9wHRD%=B?%{=Gu1PtHvMvkkNyl zw-5OmAI!9e{Ed&c2O8G)ESa|t<;c99#@8Z`(~Pe4yq(tB#6+BFVG@5@q{N>VW$Xd) zi8gl4&>qj*X|cwRHB1{K^LAR5sy*LMs|Mqq`p-1H@1*DL)NjG~d62HJ=7)V{-ahOv z^Y&rAcf()*c^Gq;b(QQZx=QvJT_q<=pC+eBpC*@?XPK^4a=BSE_z|9~J-|FyHOCwO zzTgDouNkw2=fES-1J8j+a*h80_^dPjnoEp*0=U%JHD7VXxhip{^Lhp=HJ#U^S+7BB z4D)un);#j&FxJEKb~-f4^L9GULVUiRUMBrM{g(7Q`mgqUJ0nu&?Tl!dw=<F@&Wsd^ zGo!#2r_dFrM%Fn)Yul_dh4qHqrf9usyXGY0kKCqk&uWIAInOERDb90Bp7BR+Q}Rt5 z&Bex!T&3uo>-gYDZDU8yAN4YJ%`s%xGxpITWOq1G=Ix`HCp>Q-#eCp-`)HcX+eh^p zP!~OKA1yF(G~;`C&i|u0qw@Lo(VLRDnYQF@X0YgdW{Bu~CiXj?w=<(;-p-71`J?Z+ zFJ@wP@w}ahna}ffCT0T9+nMWR-p(}VAKim9F_*X>XI9I+omnIE_A%DEQtC0p;d%Sm z26}cqZyz%?()0GQe3`e8Z8Q1NcIb!a?PI%S-ab|+^Y*bKnYWJ>%e;L|*H`z#Lc}SR zdHYzIS%bD?&N%1W_rW*Jyamq+G1s;OhZ=v)Mh|-4&WbfYm}#@(jE}aDHmvO>GH+*< z$-JG-*Ft}@jjr^(ot<Q2BF^k&i9b6<;?JIC>;dqZW9*uty<uhs&Q3RWtYLPB%-hHP zW!^p>DD(F5P@1=o;Ta$AO!aj*R_5*FaWZe8(0jMJ*Atk-tg9ztMORP6iLRd5Abt8o zp7iM)+dRv3rSQE4^`mB<t3ALxS2brF|GwZH<F6UBh3CK==z-_JoO0uj-k)>Q_-npt z>=VGZj2%2TMB>a1l{j;GJ(v}9c|Dr-8nnhRZ|7>wqlOM+Jv?vcLX$ji=i)5H{XWl@ zexDa5{XVac^!vONnYZ)i$h@7m!4)UZ6{p4(=c>e+A1v#fueEK~IiK~0+|Ji}({|14 zj6ZTapL<p_^vrplkDlT@&#yH8$nE?p6G!t6V@Iy$>zwQO;M8biN6u6G7`x^)vg;X} znn8Alb7kJ9VxI84O~riRd7HXR=54B81L~sZZEB5)qxrhzEfr@}p0^7kC2tF&C2tGj zMdu3=MCS{z-|@U%FiYm`f;5*u`i}cz0cID^+Xa~UJZ~3ZCh)vna8l;&0@RM*Z&`3d z-fvkLCVjdvO8Rsm&dj$=KQ0_C@3$<(I)7n1*7*zaum3DW-uOL=g@s^kuMa!w`!M^X zzWg4=!U}n>W1*?Feotdz70plmUdO^}%DJ@>jJ<&0>sWY&^6&WTd5e2F{@0Bi{)^BH zf0+9&@|O1&76nS47X?e67h%8S_bwJ;zvK5V78TMO^!~D_NcNpY#dI&nUP3;4-&urb z<nOT;nSH^rm&?Ah=%nmBi;xG_{Gv+PcNSI2zO%^WLGL?@(2x8*_9Bx9ZBO$xdBZx> z{7p_Y$C&lE1IL;*YfdtD><ekSPmwGAU2&S;3y@E}AEnJPtnJmZ@1$LkedkHO7S}w< zdy3`^iT`A##D6kN;y=l=Hvs;6?&<q#MsM=I^W+9&#~Pl@lYQr@DA{+OLhtiA|EXBg z^P;{=JvD^%>~ON|J5SA$edlTPDepT^M@fG@4V`m;Jq?|6e?5)a%k%1KXq#)79%7zx zx>D((X3d&YjlBn0&m#SdnhT5_>rCHe?3ybieme9}8~>{D9{?Yta}W5LKx3Z(4mNQ# z$4H!KVkOQqyq>}E;q_?NYtS0NzVnRMyk4hftcUlVXP`;mcNU{}c;8tZB6DwXyv)7D zi8A*VXUV>^I7jxK#l@~TB@$<em&94(D{+?ek##Q7+BWN4!g@n)muS6dyXGR}kK8Wd zp4ALJa~+qUr#R0`ZW@2&cF8Rh2b|$=?8sGy&bf}SIl<VG^Nd7e*SwDGdaudIBfG<e zvhQSIp76etf%(AuP6p;Se~+D^*MPd{eP^kciKE$1^0w4p^0sue<ZWq!<ZWrH=zM9K z=zM9W%)_PGG7p!obNQq1c;8uy*~NXav{L$FDP{uiJ4>(2zOxK-sSeh!|185?s)M{a z9H?sF!(0{uW;^<n_o-zmvQI73Ka)Zn-OJ0eq_3CZ+`{|RvV7U6mSIoieQFtW#rxE9 z<ZYu_&vNVq8_j)}hst}H%fsY7%;mAllf?dUVD?W^weK4*$C}$}pZZEI$C~*)%;o8@ zYkzIemG_O8uaoyMmqQQy`y<Os!R%iy?;9`29&v;1w^Z%>#+hDVV}BMi>Q}SQXH(_< zx@S>e=ko}b@hp0<J^N&<+TR~}Hb>sWd=_=*_uik~03RJ+UyEA*gRiY3P3ryk*=pIZ zpRF<Wjj&&l{rXuwyAa3m*S~L~c`<x$7(4t|;92<mu)<f)4=bP(K0mAomh;1kNO=!) zMYOz!xgu8dxgt*Vxgr7YUYhl<K<%cP=UOpG^uGdm<M$a>WXO47MV6cgR&0~^Fjo}F zdzdRQ$DIB}tyh%FdzdTARqcD%E6~^c`y(r=<UPz4HS!+j3iM78uk(hyhq)5E{lnN- zLbrdI^{)(-_bpe3$@`Wo<6ZVdmpxf@vQle?<M7-=tye;0{P{Y|rW)yUPL`fOSc5*# zWO>UuC(D<79J`;KbF%#9oRft$^Nh_x9cP>SW})}_=k-~k6knfbvO3E-Co9aXLEA?g zz4Zkr7%geeG}pER^BF^PzOmyxleNt-&JtO?=W09ecd$PfD(9T%!sMLu9AArdKUZMZ zqq$V#KUXI4pDQ;$i2vM4V-EmV7`x_5Ip;iAZR~mt(8Dm3pXbx$ob!CToO7PnGZ3{{ zxlF0&v%&Cpc$=Jap5G<soEKd4|AjP}=Py9dJkMX)CH<0Z%l?>+-sIY4C!1%Pu2go4 zS+nLMWA6bjHg?VWtb%oVP@`<q@0wpkU-SO^BJ{xVUyL;V1K<;7;%H7Z_6gu5W7nMN zii7!98;9337(Ton&3X-bJviIEs5OtgX?_Xo;d9PQ&?KL8UP_XE_9gTVf4+NZo$RwO z<;gz#68e2U;_E*zRmeH#Wn1FB>?Ltt9wKpG9xZWR&X9G!thH^{`7-MbxqVsdP1`l! zGX8y)%Hf{X3_Ww6bI?<qpPW9%AGytmF>y2}7&~&6qjRp~Yu;e&$azklv1_g(yFT0G z)R5ibn{v*{!93w}&MTM?e9n2rU(PwN=rtg3`keF15EDl;<`|zdUrCU>y^<?=du4;< z?Uf=qx4cp;I)9~1=KL!sWzN4+<?=`0@i}J|W*7Ixs$l7hRhS8U&RG>D=bTlTOLa`$ zS79#kIcHU(sy*kdN(LjJ`p>EYIp?fGpYrdUtSXbfUUgFXdR2{_b5>oIbIxk$iqAQ# zz2%&<8oA<g&T43w&pE4S;cR2pxjGeW*0VZW)t+-!Be#6cS&ezpO8eJWYBko(=bY78 zGoN!-m&!S3b(NfRR#(e8XZ0;P=j8gzIVTr+zG33$BF}uz$&HnBPHvo>b6zc!{p;0Y z*}q;bmvhdmC*_>;YK5G0UagdK&a2gO&UqDe=X1`Q5IN_p2_;SHbIY2}a?V+!_am&? z+6a53oO9NgdFA*=%Q<I_?lt7u@yE09IcH70oO9MB$vI~Ybi&`0tVxq|&YBE4=d8&V zeXhwBeXhYQ;&aX#)Q-<NYl=kwYmhfS=d3|r@b?~T&=>r@$C~SM&RKIq&N*u_yZD^5 z)>qCsYyIV%vlg?I&pB&D<(#uNOwKuLqvf2lwvU{1)<U;`7=5mVZvQa)Tsuq7Giy`j zJhOI#%bxGD7l=;QYRzz*3h9fr&;$3yI;>}*x$ioxXQA<5hk7kyJL<KF?J3HW#`Za2 zwqq~mIj}AV%=QB1>CgV?o&LtY9`|DV`WTlzQQnVTpG11|Jg?MxXoKICUC;Zkwr40$ zKNEj_7MSC&llitD+Ti)NewWPE^~ewJYwL@Z=ShxJ3g$SNMf!7uKDV#06m7p2DeHeN zO4k2cg{<ebDp}9#w)ns9E&dxcoBM9?bJ@{HPCnZywV{v6r)I<-#r~CGv(7hWDbG{J z{>B`Wx0jT9BNcY`Nuz%BXgg|=!v00FkGxUlilfhR@NxW4y5dww9L(C<I2(N>&c-lh zZ#D5ZMuE*5Hpa-`|FCh0{QVCb<E5`RCQ4s#Op*TGh+g3S-B=>^-H0`FeK%eaoo~D< zI^P66v(7h-7M*WO5}j{K5uI;J7oBg)6rFF%6P<6$7oBgydbp08pdZ$G9`42Vym*&= zj_5ou)#Mp^&Px-W=cSuGYkRKfDsO}6Di8g|-{a*KN*?k`Mdx{#b*%F|)KS+||H*@X z^n7->Ms%KcRdoJltgQddA+r8AugH4dye{k6>@WVCgT?<X&E~#ug}Ur<CZ9OVy`|3* zdOeyEpLPD$Rnd8VhUhb2pAQjJ>oY$~^qHS6`picySm*iWqR;#)SDb2BoElf0D-!4J zK#B8qh{SmtdS;!!4L!5Y--e!7ndf~QdR}Gn{5JHwneB5#=WnNr&fms<$2xzzLhAcA z*33G8`<Cc@i!D0e0zI?Nw<L?sx1@^Bx1@{Cx8#V<x2zMLZz&X=Zz&R;Z^3%Fj$5D~ z*7;W4i|t!eT=q=S`Bq&QT`%Z)EAGqld~2@Bv$jLeJkPflimtYnNglRB!<>h$$O+Hw zt*9N(?X5RN&s%Sap0|ybb#9B7b#A*M_uY0&?)#@;@&8k(`2VT1^w*y->$tzRM~eUU zXz|~kWb!#usqM)opWt_F(fK=GqVsn)h(6!ZpF4Ekp!0X~MW63%6Meo@E&6;1y~FQO zzjM<S=a$4Nz<qgNDDaXv1yK^GppV2UfQDJ;1<9iG0%(|ZUVt+j>%1USbY74xIxko! zIxpBDIxld|u>#bc>$@XZbiN}*biN})biN}~biN~3biM;Q<a5i8U83_HMWXW^6{7PU z*x&iwvIBZxJ?}scS?4=(FShT*%&E1bE{~bM-l^+ibiNbM#X8@)%j6k4-w8dl&UZr3 zd~Vr^I`TZ<i8^u~cHR`d?L_ah-rn_+dH$}i%=32xMgQ-Hi2mPAll8xwF6-YFEbG}7 zD(l%bMErN@-Z69RJ<aBM-%D`WGfY0GEA?Kc$tQR>;`2P;9U?m4jau`$WjB9!0iEwI z7Jcq65q<7PEqI>qfreS<d;BEM9)FX6#Mu)larOjDoIP=_IPtDHsiN~e>7w&JS)%hj zIimAD&@j*QJvfJNHu>3ub0+%A`Lm}`bYAE!^)1AjxxR&wqVvLN(Rm^A%=5eu>*Vu! zVY2A0P@jj5-U?@l-U{_O5bM$Nwh-&*?-L5qkF1}<T+vVA2GLL9Hqws=pMMLXVg4P2 z!d;{#$Bx?Z_ZxfhEL@kp$T`<#FXklAhrM`4o)3GmZ*t!D4w1a=#lFdT+nXSH+lyN8 z=lZ>vE&TaqFV@WY*_$W%*}F^fv$s(4v$sg{v$t6Cv$sO>v$s<6vlsoy`^#SRBkwPJ z&HkeEuos%-{OmP*jkfQDJ~==85+y(TP&>}gKIo0}vk%Y6`PrvurqR#7T*=SAJju^K z=#9?_`^qFg`%X%J_F>JOpM6&)Kl^S;e)ijvpZ%C8Jg@e9OMdoa_OgEVhf03-hlzgn zM~Qy+$B2IR$4Y+o4-x(BkCXiD-zNFlkJ@p5_LoS0_Tw2jKl@Q5&d>g8$<O|)lArz8 zB|k;}lAoer$xjj1%=sybmi!bAk^B_JNq&mZkDQ;Pc*#%EEXhyN9LY~nn&_t}L-bRG z&&&FArPfJNj^w8(SMpP|PV!T9L-JFE+Hrmk_)2~b;2AkT2T&u<&w((>&jHL9?ym!V zBtHj|<arOI$TJ?`&yuH=I>4VFHJ8f#KTsy~|6sh>4?^?2UmQfwvVIO`Nq!D)P@b2K z&JXfA=S!sy=EH7g>A?b%XKlakijThI_=iw0o<E0BBhJqu)P<k-5bDDHatOUvXzqI` zL%!!Zlq-2Sgtc+459J#T;MouHdNk`ba2(Wy*HfG&_F~kx)?OreC@z*f6rYql6jzvg z;dzTIB@e~bl83{g68|uIkmDatmpmNKlsp{HlRO-D&5gsmBoBuRB@c&DQ$Eie#@aX! zhbtuyhj~57!~1#-CJ*mN%6i@}cG<ONOikavDtUMxeaidM2VRng5A^&&Ob_z#fv@D@ z1HHfNeNEdFB>o4`FvtI3m*nAtBFV!C6_SS!Fhf`mAJj-5KDZ)z_y9HKJd|K<oQD!$ z$wLXR2YD#bYcP2zNtX4LTzA>EW=tNAgh(Eapl3M`N1`PUNBT$}j>JeFjtr4J9LbjW zN1)-__%)J;BUdF4N4+HvM=?V<4@Uzf4@WU43(Y!@qNbdOqgWf~;b@HH;V7>Mc{r-q zVDfNuovi0rsMwEb&6xPd;w2Bq5+o1DW=S57@hn2!kEKc;j-^W;j+MCLyXI19pyZ)6 zMDkFoXP{YUX^iBdG*0qRI$H8jikfmBO0hQ1Lusnyp_JEyJe2A+aQt$4-VYPR{-M^4 z$-{?wHX8pAvn3B7=1Cqt<XMC~e7H^W@F9P`(Doay_^!G1QJm!Aqj<@~M|w7z`+k%v zdH6`rMz&*yvmQP|O;@rVYg=j7|It-d`}Z4vgf&bw_K$5<`|llm><!j-?0p|YSI?O^ zA4h@NA8Q+<?G53R2-bGZ$T^>vK28O*f3EVZ<~SR`Y%f)wT(+YYxyD{*J|F4*w=7tB zUNt^tp;X5@+TPhP?pqcn`*Io9{3^$ZBJDZ;(T24@G_#XqLeKp7kCmk;&ns-lv%JD_ zklS=^*Y|}6^w~iFDT4+ucZhS8eS|p|{`y+&zfOL>Q-(QT!ZGvV&s;2dC@XR0p-O&E zQHEK;e-B>S4cB^Z%Ds-Gj%&;sj-!riO#I{iqMzfK8$3^rcUB(!?8NzV9C=&I{;2O{ zwkLwwj_2ZY{&74PpYxAn{d`V4j`j2BpyT*{-bS2{@LBITKELbt0UXxfVZyGzw?BSe z&R56vxg9=^{id9+PDIOj=>+Bge~vqWIlz5!0yX95I)U$V^nHD%D0L!*?(1-xoX1X} zcUYe%P#1o#6Q~P6*C$@`T%RDH{9K=4Uh&UgJ_(WUF+S-d-(!3dE8k;$g7wrf`TQhV zzQ_0^L*~FInKEa}{l#96d-41!kCORT&il^uN|ndRtSgTto$Jq)<)|Hhk5Qg1-y4*t z$>-d1tbsr0mgC&Z^(x0%m+Mu&P3B&Cfy}+~VyR<!snqUMy=L>gp9ahNKZQ<sJ)f4! zdOod`^?X__>-iM(sy5CIiSy^1V*kt*`)7#H-(!4MBHv@2Opxy%PA1aa(BIdcOp@;( zP9~eYX?vQ>U+))q7RNus<)7*DFO<1`5^Lb|?MY~x&%GzHX11RS6Z<LDwAK#I@b^on z;v^5J5?yxGk?VB|`@&X}=Tp!&f4_YyQ}ll-OZ0yVJ<Id?6g1EJKZTm|=aEx|(qE@a zq`yv;N`IZIaIL4xwH`bpum3da!s|R8=(2~n?07Ezx&LX@f`9IRx<K}?)5tCFU#H7u z|2mB|@cwnWTK2EgS7iS><0t#q8GqTo&P2)nb*7K(UuTeW&d-^6*}u-D%KmjGUG}dt z`7*c9Y?HZt<|g%p-oMV=lKrc~i?pQoqY86=u7mxk!k2nS`&VGiynj`gv#aADNP2Vp zBW3@pz-;9Gt73@kUln*3-oGl6WxuFMk^QS;mh4{@&=T)o6{)hPR6tjHChI>Hn3=qP zRb<NkRgo+2V^pk@_c1Cq$om)-yX1Y0iZa*w%U$b7?L1n~IuFp2N8cCxxh?NweC{pp zV|*Sd?_+!(E$?HTg|>e+eQ_4Ei+|33wn(1+Y_YtLakfO>$2bd}^YfmC-uS)KvnS<! zjC1}{_jAxTpIgqM7B|g(&&9}l5$E*Y#P)dUqjPDp&z{SWefFH0!}{NBI%npv!+5UR zIQgzPWwP&|!#a82KZkts{(kPd?C+Jx;R2KAN<VpDq7u&%Xx3R7EbmKHc9wHUC34Q^ zkjg&tzC>k=yf0CisA|upl}TWupUPRTIOwU`IM5QGuPU=ddzCnEa2+c*NF6INqt^2} zi{<@_%9Ad8rOSRp_V>!0vcI3lGxE9Re2DDt=Obx;o*t{z`DmJ-4#&xUcYd^-Th7PJ z-giDh&MoKH$y_~;+VQ#NJmxLe@%%2S<M|T0Z_|UgZyDX!VLS`ZrSsJ?w=dZ8To=6L zxh`Oj;ODxKBF}XJdgF7;1?Y``{&Hc1oLeqnrty0t7qA{aw_GTdbIXNl*?%w8$o_i~ zHRb*KBJRcKmW!AV{JHGn2D6{yd~z{Q&Mg=7&3>xw#d1!#SSsg)i<PpET*Ml9f4O*7 z>U9xkNPTY6^{Rr-`SV(pubf+|f~AgCp;Egly=J4Us&rZZ7tjfxTfPXD^?VU6>-i!^ z*7F5sFUR>JUgCV2Aoeel#QqiH^SR}#5IMJeRV3$-uZm6Ha6b8}M9v{!m72V1d!@_2 z%H?0}@~;v9YJWM0RAUW%4ylH=`P@>CHP_m+U3S#8)(*|^zF%D+d8jUS*-=NXS2g;S z&n?x^HlJInYefImS498S=vmhPC1{?{EtgPJKDS)*m;SmGBK>tKRQl^ul&t4cA6d^O zJR`6F66(V1yp-m$XNdhW<^%V|WyD-(G;=u`Y-Zi%KGH9jp$DE<myuik`@=7%D$i?t zZ915*&60k(oK1C9cPn){NBZURI;x{%N6ug8IJ=bR8RkORIVNiH40E|W*X0V=b6qv} z8i0G<F!8}(dn?ak6Z307u!-}v{!FdyBjKaJYtnYj@ygSU{S(3LpK1K3!AC!rwrkGA z>(1=I4b1*0jsH{dsWkqYuPV<H_P+r({x!kIf0a@-p~hb`>XKpnYhu9cpJM#Cz(;?7 zrR|zCm1imYXM@?l(D?6zkM2ip*L+fWR<M61*!X{A8~@WveWTBN+O9cRd6pUfZ!k}m zv45QLzYL#v<F6Srd^!8i0kc2Wwt?-rV7BK`oI2sSb{oZU7#etk{mou;9P{=Y^yV9U zZ8`OwW7ishe;vH@^UW<22mGxc^=V-zFutqN^VVVWePf-zun#f*niI)??>ula`8#a1 zU1u=txyE1fHuA6h0lbU+9o8Dq>w(6;tv3Fe^~{HT-}~TO<gfWVtpV*n0UT!hHOG*D zQA6+$@^{#LhgoL|>}kedvpJ8QSOYfaF^9DVbo}YCml}V~`nwL;H+~7Orudq#Xboup z$H9KaUvnt=uRQ?{BY%gr2DJY|*b|Mv<~ihl{x@(M`8&*YUkp3fU2`${?`RG#C4Yyn zn)uMb6<ur8u@3lqZ}NZp7qG51><*iL*MD#7_kGCU;bi&yQNN!he?RK?IM?z1`#sKe z{Qdd&`E*|!Yx~};)8Q+|z5;f=Hr&?+|DbD!JlLzik;bms)Jy*z$UmeSyXHdUzY$zy z?3!;H`)07wvkm@>eij{nJ6LO2-&b?GvF`+D7`x_TV?PKkF?P*5rjBz|sjIfJYv%YT zz#LyQ$3G3`_?kKX1u)0g%<;cf>PL>RS)WmH-^giTt!=E|;W)B)pAP$IvOAna_Fgk# zPbRy=sbud5P5x+f<!~0+W9PxHdjats&VycXU;XFDeC2tR8U0%aK90QrcEi`Ockn)V z&0qGxYnadc{o6InXa4@}8ur{o6Z2Z8@@!(p{+P%yF#|U-<1+%kuW}80O09oB?CgX6 zrPjY%&NJ6)<UI3Jh}eG$b=i|#_GFhG_u})?Px&spEB;Te_}5+Wue;)3cg4T%ihn&# z)qY;Mo(?w8avje;)8ynj=KoB#V+J~Pc}l6D@!y?VXbzS*KfBIFzx0vwz%Q|K9{44h z>V9drQoqcix;wnVWzQG8!oBKRRCoM5z<SYA_JO1L-%TA>-(!}m77kkvM}gZbD;xgh zUxIH}svck4nXYa71?;`(+K_hO`-$7W37$nhi>`s^5q~ljjJb{bT7QLR)nc-5Yz)pM z`^NF$=ZTk(1?M=dt{38a=gDMGyAS-3!*+5x7=5Z^X50^6M)v*Vz*)pQ(96~;@_B6s z81qg0?;8WgEYj@Q&p52U9tQjO4%=fA!9S5tcqI5&^0|guT7Qtw(HY2b1LAtU!HtQp z>wcwt+OK~JZcW$5hJf2UY|Z{FxFhiyXu$49K6NI7?<Vds0^E~0eIyt&3Tw8P{{*I- z+utD%_DJ%n9ts}su=U#{a3b;C;oxNAFBgDKjpp|U&!=mjz7zZu`82u#UP`=IuYu}f z$7xNiA^)upgEtWG{sz36{HK<Hv3Ka)&fNpvNj~=_fKARH$pjxH`%uhn`xx;t?Bn)l zbZyCC@aJT|kPE)(u-))|@Fntj=>zb0#MA!{zE1w{=s1|kdJSVS3-NuGleZDe!QSNa zZ7*;W@;Q7M+=}=E^or*;^6%Ol98UH@t-#$KR&!A!Pk*v6{{%dQ>?^(kQ~qt|+L?~s zZu}PPq)%(qT<~+`Kk8TTpD0dBPw+0{XRt4LJ|UmcI9GU16XW}M<+<YWH~Op}@5~kb zjOvTC;6~*0$Ubm8x^_uda984Ms8OA}9JaqZ4~`{n=nEe0u(d?TnMn4I&~}}NiC@OK zqYgcnRe-*$^9=c4^#Rj!S#w_iQ~%o4AAyZds{4Z9BLAK(!SuZLTJ5vnv8y%DgG<Th z7<##m$;01Hfh!%mJ@QrXSLBnM1jd;}Kl|^~z<(wF4EtnV?8UI#-yolLsZZ5`i(r59 zDQW<2Lp~>w+q#{JpLrS_K^%r&uG^b<@Dtzx4qIn1$LdnwS#vvsP2HbFpVpm5{%79- zKkBfmcmTYBuJwb4>!uU0>;}#vAK&fZmmRh<4}o7N`+(u#&E!7=Gq&ztvM&e%ml1D5 z&g))q*tU|vKazj3UfbWuz6ERcqMWGTpf@j?QPx!KOJ1EQ4&H51US{TC-YBoZbZvA8 zFlj@5aUA?0#cwzTJlpVN;KdG;&st)C)XQr(anM2V0f+66)4}BqTT3t#ynZGg84LcM zxaE7;f0~QEUZBHvektttxa_oMdlY6-y?C;ZI{}{OusVmCU(aZD6nd&&Ci#rOURG}l z@n{ct2l+p(?I*~7JLY7)Qx4lZ(IfRt5B}*2n0ios(-vQe*C(HisC9kX3#|LwfoaaG zt5{F{Fp7EcZty^dRWI~W{b6Kp^e*@z;%#x@4DxxW6L^)ww*O`D8|2fz3Y<?qOD=(_ zkF4I<zv{nF_Po!*U(&Ua?ZH2gz4$fo4dO-fm1^K|*m|!A*z9Xlo&lR@$=L#KN&YpM zjSZ-G)E@)DcQ|%?E;P{KPV(vWXK)m81I)b!bY`$$$DY!F_A=G^CfI0fANs379QmJb z0v_wIwRteOhU{e<!Djuvz6Ss1*zHAsfNAF2r%`L~I&|%!VlZjdzKH$WJB9omrXD1_ znOEIEh0kuf_9g76-o@nqB-Y^lp~ET#wevnpymAM)iu~6=SKgP&zT^Oy=8{#>75op! zZhwL~<74J?HuguK*5v;z^6b-@;%I-LJ}#y_*u!qYo<R10V9xkVao8S<`}!mkhaCk! zPCoi<<3sv!&OAQ!jLw<Ir-1z1U~ly?&uc?hK1Foxe(1!<=qDAq^(l4iYFq-C`a&H* zy?joRf9um=lan<+gR9BzJPY-;^Xv_=Cu1gC`q>+ju9SZEhQZ?BFw(_CiQ7L2pQ#S3 zP;c-fWIucn{21A{q8A#@b=dZP1H6dr`Hz69_tl0B@N)9W=?8w1d_Elu-bCEB4tOW= z$}`}@4qNIa@TbIGp}mGwYfEz@>K%0jv%QfwU0V<Hwh_%MbrC(-s2yD!c^(`}K8MzW zyOMnZ^52M_-L5wT+=G0&4F{7R?989Q101{Ewhed)UAqu7wh`?|YC$-dW}rPv`%I!Z zBi4YE$p6<8@N|mv<}mOa^3i!{w2WBiq0uYEIuDKV9Cq^1Xcw{b?9>;O2h*oc9{%F^ z*q=YI6vn1g_X$hE{$zh>9yrKh^}r!;2-%OIcYHgMe-h3czGi0rB@KKx*?VIj@r@=P zif8fdOZ?i8;8^1QIH&mzBW{Vk-j{OX^rJ87$I+xOoq-)q`Yv_+9ZmY?(6w5_zWFXT zdeEBmJ>%Hzr#}Rrr)!nI*H^>?G24B=A)oYm;Oh=s$L1^5IDmZG)`0ty&llKh8dFUb z-m_DUsa|$=KA7sIl2FISvnWp1DeydsGx4wBG_rR^4>n#*G0$`WXOWMtZ{yd9b$uJt z`BUloHa5Mlb>6tl#DTUOf8pX=bgiy$le)yE&~_6#OQ?r6(@e9M+zW2+_}HJ`1@1_3 zW@+w5_Nnc_cago72YfHtk2M6}=dk(~>uExJrQJ{8mu7<Mun9bhu3a4lrZbo|cN%yy zUE2g_q$Up$PsD!OWQN0bSzqvMvezsFQ{I%r*)IE=#Qh(J57k}ueI0CS?bv@cKC|(W z+Sg&LA)c{mXNT>^7s0fC>!}>D>C=wMVAH3)wEs-H_VY1d>PP$1D)0)j2etsyyt0BG z0>9<h)ehvaDb>+B`wjRbx^EVqw`mn|T4%7?n@TYAo8F{r`>s?9E#{n`|N1i6^ybiB z;3&s#?S2Go`lt;w>^GYHfBp=dY~mm%ei_8i{t3L!T#G#Wy-R%d82F^i|Ej}w75cQ9 z(bDZR!J%YthaPEW`a<Wh*@JZLo+R*-#H%}kUnT#e$Xm1b9JcU#pQ;(nYSri*xSISU zkhf;^>{k09lxl9yGrEq=Nr!gGSupjW?S*Tb(=%GB{$TTrD}M&((0w;u0>44`or?7| zFC_kRG58bWQCM5^i{u~h9QX=x@VEM_7vit654P|j|81BpEt-<O{&g_*j%tN7TMOzP zYuYvN7{^Dw)d`$P9GD0uJ==S*N4LnOn4|9jze6$a+zO^1w->$w{(<ZRzf#JdG;H^M z4;)T0>p>6xRCnvr46vCwpJHwPt0}&3Aow8pZ^0b)H`>#m8U4Q|dyntICjaZ-RH`M- z2NiG=+?(Q@iU1EL|MA&i%D=6@D`>f#>_0C8Q{7d518^Q)yWR#<-R-%)V7jjr^Eage z>N!64P|T2kM&uuYH3ZNcwgxo^2a|n2o;QHbwAMeq1m8*5J`NoQL=&qb@Cf2JMuFoU zRtK<m2hjYn<I#5k(;T~1bQnzYM{UCF3P`1Ef5-qoP22~y3osgsR^S)OzWsjiDvE>m zhExFQP4$G90=AKTH=aF!w5MWU2A7b1LJqi`IN(|EIfqr=9x&y{KGzidGx;?6O{rF9 zo?pUDYt@1LzdsE&IVorYroC8whxy!!_FwzME#L>pziu_y%-egngBOr}EY{y@E8XiD z_MldK$iAcz_z2n8uLFPPuw66{`~}(ZZj@^E7vi0h!GCjDZO5z#Y(TsNc?+bzwojFT zZzp?1Aeh!{5C0h4kL-c*V5*~9{Rx=*$c_pHKj!#Y8=<$r7s!9yPvCV9JI@=qh3wx$ z+kupSYa#kK@F@8>_xj0UYvUZ){~&&1pi-@=-|hK#g4>b3`$RDHwSDg{@KndH2Bd;X zC#vfo;O88>-4hSodM){UikaW~ZL;5uXK78jwXUEpttq$a^(-*u%{mpVRFKJAEVLA4 za&`D=FwH~jP0X<%%9ZW+8Q5q(3mOYDT7BUH_$BAQmeyO)>$D!N!yu#2kNbl6lYRO> zz_d@P3}_(eb6WF4?8QMf#C4#<puZAdMy}e_aoAde9&FRhVO4-R+$My4dVU0sAU=(2 z+mI%$kF}llTzfwDuQpRCju&QWo5v~6!(QOUWZ(2>Fg=U?*>dnkidi3XzRgbJo_oO` z(6#y*+faYm52B~qT%<TjAA(7%O6RA|@8n<EU#Va(@|gtf1yiqCW3e9vQ?FTnU|t1N z{_PJk!7+60_ch>AbZt!mn4ZOcstb5F*&At}bcgNR%fX~ut3G-s*qr^gVxJABGlTu= zBybVMSL?wa6URV5!StEVegpF-_#3isMjr*=aM=3hkWy{yl3n*jTY46iJ`GG-vd4vk z?;)Qam>X>e(zQp>*KMiStU-;z6jOb(QmJ+}`CmcZ+ckFB>9uw=pY4_%VDCou*fj9{ z#0Q@M$2)9Y$pb%3_JW7NX3y%|0zcx2B>Q0Kusy9u<*WgdPOKp4s=bM`A{#u(@mGy8 ztJ^0L_nHizPW;|N@GOU|3C+NCFMIxIa2okU{|Y9J*&U~VGab7<;(74%<P+5!Oy>%9 z7wX=A4f!Oz1>QjHIRV~G+y`^7J@uEWgwETOKCQi9gA2*0!P{Wkm#qQFL;Di44~5R# zQ?0Gv`hdSAdzv5E)M9gpQXx$pyLuKn59vxi4?GGUME1_8V+hsJ{%{p|zGJtt-vE>L z?0|h>ntS%XsY>0}kgh$5+}_rfV$OXS+?lR@Egft$^N&}-eaYwKFW_NxZ3pD-wh83_ z0rYd*G~$l9?`@_R-a(CSODFq=%V0V)Saa_I7dUo1{7djLhgCl>@CEWe^f~xv;_-8o z>flX2rQ5)i2W$LZ@Nlx9{}nug{Oh3CI=o1{9naFi%#F4i!Jm=+Y0Se8zY!NbgCDh# z&ei01!J&>_6<J`K11fPTcnJBQLEUekOx*E0*l4>U_Kw?MqHC|AA8)76FV?G=b+;dI z>~=~d_$%^x-y3|D>@7Mg6<XI}>z)x{Q|o&%D?)pa&*N```w%zT3Z6*3=?HkC!|Eq! zBh+YkG@d<__9lDqli+=hj}`YL_%QKy=sff^#hH&<gq|n<{xJBa!zvhk-O(cdhR|xq zcEmmWz#Yk_PIqvu!?s>$N2-gxeKdF``NwSr&n2HxtHCSC9)fdGN2-^76ur}t`pdeE zb3#X&lh&u$H#?pn|8VVN_N<z=;3~(iQm{vNB%P}c$a$wm<d1jyRHs(Nd&Yuk%~sR| zFzMX-av7LD@2IiJVJDjNY7=^=(}T{nb`8$togO2eg7a0UCn@HpAHXY#Gp~S2=XQJ$ z_${*g_<-MYSowAV)Ba_>Hy!*b*|+@(O#7FLx)c08U0X5+O#7F0zMoQe)Fb;H!@(_y zhrSLbty*VOz-F#C91J#dbrqiRjt3lnd(SsulmEWE!L&D74)39uGa_K8wOQ4^;4^gX z$1j7gk&k0H^J-j<Qk`jDSs}<<XIh&*`4w<?y7udN;NA}Fe>YWiHX7c58g({#exxIK zKKbk~2b(-+{syMpTKc@v`E^>uB;>O*<;}VYZFK&L?3%mK+_2Xk0^dt9$Dacykk8k< zz*C7Y{0uf)U0eZv%CXy_e+6d{A1MTzTJOg>p$ql9U4R^Rd7I)mcA9VMBIZn&GP?Ht zcfn@<d|My<tz%a&=$Jp!wNK_N)zzF&CgXX#l7`hNZ?HL^%vlTWLjH3$foUeFx6pT8 zsqS{d5^yrb-#QL#bbAIfwk!3TN*e^ur8xDFhpu~xpTHj1wV19A!8*HE5{KGgnq5}c z=fHoE|KH-3!uyQQ&-)@VGrQ4zuvhN~Q?J?Ip!d5`e_34`f@zkjOX&S>v`(_qI#v8H zu$w$P{*-6yZ=b@xo$l+{si*90)U=z?>Z$j^6}0ApDzMSR*^6MB`Kli@6BbB5v;P5Z zPkiig@ZH2caBWymhwbN{0uOT7vatTJNiHU>l0DmHf7iw5T>N+8J82EhwRf7n7<^5s zJ100ks$Wa6>5I>1fYV&|B@WxS7r{>bOa8R)sD0?!JE@M=xz^xg<e$9;eBNQQS5wS; zUV{A}#PjAV6&^(XE!u$1neD-+!PH0gi|Ebp5#;08;~loX`yF=bBNc(1httfrj$^+L zr<#)8)HDyh9G*|t7WjbQp_r!*f{&10?^)rdk33Oeb6(POBm5ik*Y8Y*lP2w>s9gkU z(wg!J*l5zR8%^HRA9m^;Yt#_1=^cgrG=k=&^~5@`IdcYX2QQ*~g^UL;rnO~F1Jj;s z&BU`rtaa=vAA4WK4)WO*11_X%lfM9)IpEmOlK-){VE>)`Hyy?MYDOCa&x7wFd*IvP zUgTd|2Rz<oPb40VnG;Ftv>bn0r`-{K8o8dX{nI6I9`QctKk|^vew5-&YXJLqF1wle z2d*l0R}-<{)zV>m1ZMkPq!Xp%-*qp=Ir$TKBKbdZA9xD+m*BbXT0pGN40k<k{E?r# z*0}6%5KqDUyo=W6oH6b?PWFp8VW+*4?AIyIgG-gVo93ruzq>j4KZkwlZt8LCNzACb zsmIm5$H9~6TF3qn`M-;t-@Vjj&m#8u0ruT4`vHelG4`FizjWD2pH|O5D|JsjvESqC zu-$(r>}K!Q_q`{Y?7ilL6C76QiD25NY-<sidY|lOA770;-(z~;@!v*qhPQ*=^v)x< zz@$C9`T_6_@^S3cJJyLwN=0=Qdz4vQ-#1{N?6OaD*xHJHDvJ8r)^Vb!uhnYIrKlp8 z{|Cf>35UJLW&exA>JR9!yU~)4(>>U+TivIE`-^|~A>_X=0QPw<`;)}UID>V6%VjtF z#gBi7o%RK1o!u{z&!xZNuW+QgIQAY?7we~IVDCXbM;CzaBMz+ur#NiASqgr_VRd65 znC7r`E)z`sWk-wvmyo|cGxzwI;`ELNU!`lmdJOzm@~I!G)V&SK=hSI%GxGT}&V={g zVeA{h;l$Poa4h+Jn*ko~u!Y}2RQDPU&;Jr^);#=fFr5Kx$DT{qE{Fc_H8aYwA0qn< z?3MSLTsij3WY0LFRCFDO?QhV7(LQ8v_!^kbCuBD>A@T#*X<m_?=9PM;8SLq<ILjTj zPC-}ER7Vxn9!zyqk3*l)C+J>|{S@))bFlyBveRB>EyJwt*;ed5Ly5!i`J$)E+sYa+ z<xLGieS1DeK8~F<rc$tP_FU_-Z*<sxtqS({UG@*j{?lIAP4Dl%0H#`7Z@i3GIE}`% zy;lpz-#U!`>P5Y8Ire@Orv|z0MZHh<>16*X0(R<sdpvro7uD2ysVkWF9kNqRt@oP4 zex9y%{Hq;S4}~bz+ZKE82E=`@!%lir(>s7kZ`N3x4SJ8HYxQT$-c(an34QjS<FeBp zq<XG`eS^zxYPtu{-utx6PHVFsISKm>m;Dci?HP#ECq(RhXl+*Xcd(Bkd-t<onwfT4 zHTW62_UtR*Ooy#6KLzKL|3ZE3J7jN%9_e$E{2zS@e2#o#9tHnS_T=tL-Dl24+UGu6 zk9BY+_-Trhb`SVD@^4fICe7HbFyHQ@p0cx+gO8BU*4x454y)-ugH2A(V=uVx3yPVD zUc2vW^6%dh{1f@>GwOZ6lD!7{>`Qf2kD{mg)~9QCg@S38+9}v)`*t9E_ugQmw~?d3 zeJRe)81QKF2|?caP9XliE!fPE{a)b5$=(dl+xJ<zHV>NV`+~#jWAtxdvmYIp0NzUW z+b@GZCSLOv_|J50HJ+vKj}BY-JDgNsnulsIwB3*9p&Eg;^`m)c-CqjsO#Y30z($|G zm;?Q&udR`Y-;es*I)%?B{azw}|12=gJ$o_wy<eVVSF<~Tw-E2Zn)~f`*zWLGu-VI6 zm4Hhr&T}|h_M=&3PuKou$^WH&;3|sqJ969a3h}{X;A`YFt`+$24qIR1Sz@Sm_QTLs zOmp(T4`<q#cI1B-bP^Lv{@40~qsZs2?cm<TZBVb6`^o>&Snx>l-*^yAXB%~}8ch3w z%EjInGn=lR9|=w+e_xy}V=^d?h3}$co+tbB`o6D_|MYyY=_CDab`0f5Ic#RK!#|L} z=KhUcZ1#mts8|1CWY?c}`jht5p=ZG}9lQNK_N@L39kyP;T<uT$g>`3L@G7#89tK`V zaURtEdx(EW|MsV|nf(It(7%HGQ*j>de~~yR41C>TyXm)J)9=%~lo~*Loby}*XdkgY zTn0PULdD>Fm;qrF=XT7N0rxnpMq&*Es4n)4(8GWM6n{GMJRpI5=3WQWY*&-fUjz1& zy~T@Q>Jdx7|2*K&WUu)OOlx*N>kYU}F-!4TY#{Z5y0HTsLH3%C;75q{{291_;uIeS zQ_osYK=T7%b?nxp$>6uiN8!)Fy=4FS8*njk10BDNxDe|cNasl_8X6vG@`<0rtAVsO zYh^arXucWpKal2?+Kssp>v7`P_jLe!JFE(z`B;DA1+RkJ5FdCRe22r<xjo=;vR7el z#F{)mk9@|OJU5sJ9#1}B-vB4lwP8<!>C9&9p2E+NobN6ie%Hk(=-PCD_<Sq&L9}Kk z|AWk$oB1j=D1`j+Gh{W0)@cvLxo(h|tCgAHK@?})_uy#`TPwc=KT13fvuF_Q>8c9P zJLpA<IRdj~(01bRE#UWvH%<Z@Z9I>?c+lr$e_^RogR>mA>m%mi)ec){*MK*Z{Uhjq zFwHmhE&6Eiaq^k60Bq)%ekW=$%`y93=;40z>~CEIH*oybPtec(^t{Tk-%0kP+GhmC z%!Ov|A4m54(eL-u^QwDRfK4r`E`XnReC%njgJ~w)PxJ-TOtwD$0ZcknJ!~*Nubq_! zzC`zGm<;}o;=F@g4KeHd8S`g|nLkhc34Aa4gkUciavxngqcQkFhgI(y@WW)Uo(^74 z{#!l+)BbK%ECg>NpQR6iP4BGM_o^m;zhA(le`_IT*N|J}pV3dLp$&-#d;xClusVRf zW@vk|pT~NJnmO;-dpUMH60>FKDB_$bu+jOm<G?dr_Bj-%<|Ei?ol3tqGV}u38~*{O zb*eKfl^RBSjoNey+{N)x{TqNIh%1MJjfNln5lnlly&Ze>u!kt-p9{e=hzCL2!=9mQ z@vgBNW^(x2Z(y3$_TD34+DEKWPlJulHy#3)(6w(NZ^J$!?uGd|j5KMT$Lt+Ob4CS^ zRcg3R_ic}R4L5Z^dJG)m*zK14z?~@0wcTKv+xGY%@ZDtB&pX`oZ1{TcFuFG4Jec+- zYtZjtIv3fWJp@j4e5^@NfQ@E$-T;%%t+B}4aHDh7O$}c_G1D;vhd)hx?h<$@#ra9E ze<j&>{tTu)PA${x+(ACC`hd+Ix48&Rdz`99Ul0F)uASBf{2}>2j<e|SPssi%dSp25 z(e~0(Fy&J{?+>mae`oza5Z4QUo%To7{}%W+isR&y^lW>LR4T3s`S(Ok<AR9$U~h_} z{998)z$X6}(RXo_f7S0InDTEm_%k?~;;&u=rdp^U=Yj`Q%oCca7OGn;n6yVsXBc}Z zG#~f8<FD?28JtV(_?td;xQOoM_|q)4Ct+sBRl5AYcd>b1?LVTqW48)hgM-CqgqeXl zKF+Mp{^IzPW~{UwuqV0v=eju4<^LMl`^3PXdc=9g5qn+!v==+iJK{^a_6z7|1l7?# zy%uch`07ruspF$(!Bj`fN3Y*JSI?RFD+}sS{8G$>k+jEI3tt3NeN{GkVI=L*_IE#l zsn+V<6JV;f>RtloT0`?AO|1`10h?YMfZ0CM)cQ-DF-B6Yt!JJAFQPT*cRWVY+)&Hj z2Isl#1;md1gu~WR=w~GD1*$*vGxBd_$KTDVMp@(^Rt*jy?tcwT^|Eg734V#}qdZ{J ziB;YMe1zico(lfLVS6KZv?BYO-e8*BY8mF$=>FtWH4i+}VO6>mY_#f?3^uc|p0;l! zpBcA-see^WDVX*+YwB-cdM^7U)-(D$ijSWgsL?-~d%Xw#tHT!lj%PK7)}|6}g1yM+ zY(sEEht)O29OFm!k1;35P)@Aa#$co8`O)AG<P)P~cBX4PuK<S=<GT$thW07@>Dl03 zj@?Q^Eyj@kRcuS}{p5cOXSOlZ9JUv11=DO)j@|TZ?@ZX&y8L$&7j1)`@?+J<9y*5l z)cW*Z@RyE{^~Sqk>RIdlufaFyUZ16c|4wnXM<_McCjSkXOJnPk-R=(dCH`&=*z~wQ zTaFEM?DnI-g4>bL$_#L*!`2b#ZERQK&d}}HNb-3j2Hb=A4Ek$qAL1qh!2^i@@B<HV z*h<|4Ce7GCwgShK&&(3=Wa8Oj;Kv=dANUshEb(!irN^4j;34{1a>>3<-)j?HI|82z z#{TNCwRf{p<LJy|w_OEJA^+50z*HCO&~ETk<p0oea5lxchV$pRRb<CI4r<&w;=RcK zIHTvuSpPUPyDlvRZ+Cob{9dUVw~PE=&IRvtSoMM?#~mjA5*izKoc!D4Y%}gN;z1Dh zIO+>k;|;EI?ADYC;48!x*mK8Sb6A~u6HFSg`e4qCGa6WjIT=qH(C_lAc+!BS{|=dW zqk$#Z6XRP@oYyyj>6~WAVE>9Y{hpBm?&$c~$${Xz$p3Gchw*gIRNrE+kH3%X@4N&a z=&<$8)8L_GPr>Jf_)%oP20h1*C+>@9iBELc9@-6T^44_;*yL?z0+{k<-NYP=KStMn ztJg+3R9PFqltWAZyd&P^a0dD`{-WcrT0sx-X3k91acIt1ccDh{H_7Msuap{ZX3ImE z;p1txSexR&G+V6pc$V=rTdcg1;8wIA|HWYXEMPxz4EzAa9E#aKek%Di9Si=LIG{QB zQ{s_1;4==}YuYL`f$n9mN5A0RFXvtQ7as<jdwIu#+miqJW#HQ>&WDIIp$pktPXtGh zeJ(USp*z`^{{c3iD-W#$(>%vtVh1*JY}q032=Y(Go;87<OI>~gOwVO4odKrjQtdEj zCOl%|KMS5i{AbMk30sNrK8~8O(_yR00C1thYWN-CgXHt}XmAPn97F9Ud_+F4e*`Wk z`;}GT)5M>x1=F0gj|YQkPTJ9<z~303SHORvI6oW)|4jBZiC|NA{NB8pXpztReqibm zd)!el%}IOwS#Y4^V?XdanC7INh`nhd%}F~6+L%al(oPNsN0NU^7ck99dm;K_BF#zr z@kp?lldog1oJe!hwoZXfzl??;Cz^hl^az;dq}|;D(_UlE?FFX!re1g-O!L$F`4ey| zJ=a~2gK5^;Z(+Vo%piNtQ{WZEE73a>Uv$`NjJY(CYNu9WK2N0Dsn0XOd&%cR%<74z zUV1;8Nat{C(-+`V<kMZ}foi1Q(lKisyRF|<p7?{q>H_+4qNz*33*g`B+Fs4T{~#ay zzJf}qOV>V^2lgReiG4YtDRDT~lMq1u`tPMm2qyag%$$U~$i5!^o<Ot9o_86X<JhfC z^jg9i^4Gu1nXrL)P#f@O@|gx*CA{mfx)lwk8D;0|Ym3SLAo?!B%q9Qj;LqsV+pEE6 z9kvhe09TR!_UFKtiI1b!2{h+bG<29ibKc%{4NP<1*58>V(44nt1}gP{hvFZ>41Ayg z#ecU5Ofx~9{0>YrL3KmS2L_S<k}Kfh#2H(`Gw9l3Q^B)|`+op_&S7<b9q`L!Uw~(S z;2q-l{^0i<wibT_rarY-P6L}hJ(~|UeOluS{)+s+%Le~Kajs(hlbSfJwk!lwA6a-G zN=+I}_VlY@Gk+4b|6IEE!vZj^)A|*A-=sIme&8hdfWuao5U`mcSKETk+Fm;dHu=Bi z1E!p-?l-`cXKToOr6!v_RDZ`lIh<nZ-@%{!u#4BZnCfn~#Tq7mP4*{nZkbGacI=5p ztNQ!lMAE8Sh1s4+`c&^v0pIukF?E(<Rvb+f?jGD-gS)%y0*ezMI6)VOUECITcL*L_ zg1ft0a0%}2nxKL2RGrSZ^CM5*oK*L8S65Z{%-p?K+j>Q@){Pq~o03?g#;mdCb|i2p z`(M@@Oh0&eZ-BX8_7CavBiqXPut_xb`4T>9;^IX05<VN&9HV-7>N3tIeaO*MgQt<@ zJ#Uja%AR~qugNB5Te&Kj{`Y=IooV87Az%iWxnQ<m0l%WXe9olF-{g(hf17fg<`#U| zG%oenk-@CJc1>|`cGbP3#lUlwjhuCxGA7BaOJwc~rr;K1g4`KN<`u-;F}DzJLFw3! z>REZ+HHo2@qb~CeV(v&?G(jzBBl8UkCQpPPf(DUgUO}v}-hfeH)=%%w9q?h=7{qhX z1!Yrw64>R)q}kxtw26=XDCl2us<Fm2qkn9A#C$WJ4a_gE!5P`li>u)3w6CxgTu0g4 zTL&CM{V-}&GscpgUjRIm`i#!t(d2hOfw_)G&e*vB(KE?r)bnP~$)Y!pKo-9>=h(cg zJ;C{?ABRtxJ0D(u0<NOEH|iVM#alJZt2y^LvuY@~joR25s3*-k(7wiZa4+^5SO`3T zToQE^=XiZCA$xc8F=W}ho4eX2dw28c)Mf8(?&4PV?&hv;$ll%jtJ>JxzvHV5c{cE} zT?g|FK%H@D9;0mw)+;05N6{h=`#*@<-lBo8pCIy>%Fx>@)1GzACa(njceYJ`1iXQ~ z8)u#t+u8O<AlSuB%j4kl)JIGQGmp&58^*MB{+D-lEi<W&DTw%N$uov6y$bAN;5qWB z<q-DM1lMZGI_5R44*pYhFXvnE4ccTx47X&SngG<Lmh_cLjQ(3i<h2fCEm}n<r)~yL zM2?P{)+#yqV^%Q7<{df*&Y`-U^aaeiXQxC5yBHqd2~2-_?{GF~MSps+@`2qsC(9sk zU-rKfx!KCqz-Gc+ck>GMq}3|gBwYZepKY!8;G-PFDEPS*>xMTJ`$DUGs(Wz;gP*W% z6A#RMG&hiUt+^L_iDQCe(k2iw-#R|qR(}f4Lj6D&F!vF&axs{BVJF=LS5X_=cPF?R zxd!~x+U3GU)WFvL*=ODGV3)I<5QnYZ9whG#ThHgU@P62|-s$=geLvgohHqPQO^v)y zZ0+WlrV-f9OY}BwUZpUvHg2CP6$9+*<kq`ju9s20EU)zg=b|=E-564XTTvgl96X5p z72|0$f?RF~nE7Z&V;$QtA59hP#cde>CSW~yFZ=wQ34Dzl0AIDa%YMq{1%Gq;AI7xh z_|1_xU^o5%(bLoZCf2uYfU`dgF0bt6DgmbdO@Qd`jFby&*Oopv0aL)NGq!pX@KV>0 z=&Q-^;j6aC$nx2ewr7-W^(Nrw<eitn@07g^Ka6R|__3n5OF%scb8p97Ft4%h?HW@5 zbsCssv*OQoJinQ|IlvsJmopET_1uIaCfhAwTgmHoF8(F2+cDoYuiJ6IHUs{I?&3u9 zx*g-hj9d+Vsr?wq>vr#zZ9~L)yYK8@@;W#?ZK~pI9PH+D6}}D5K)n)jGdMTxC9i`E zQvY=on7LpiuY+sQCIZ$yxV5sCybfk9wGqT-FxyIA2ahDLLi_}~xRSgMW?Xp|ehc2l zJ|(Y%_mG!t0lU3e@;dk`^>nDo!4KG{<aO{fWsASzHX(+(<aJ0yathSskYu!xybei2 zeH7|^NFnNy*C8dSBWz7bEoD#gI^<XC2cm;JIeV;c2y2}kTodf-o8)^4>zfU20p^-& zUWagwrb9vKZeEhtA)J>r0pJh3mgH~97hdcAdt=&jy)>`e|3qEB52}3uXP+8ejCwij z1?}sSB@Wv+qRr4AV7JFfUbpY1x;O3@@C4dOUbmmhwtu_=uX8%`y8Tvi=lJ0BPDlQ> zck2@IA=r&y^140uBiniczCJLavq%1RNKWqG7fk<aUUy*a@`}fS?tCtJ-62Try|FdG zeO*7I4^g%Y(u3zxm%Q$<guG-oct33<e>*Vuy>3gvj33SG4lei4LC14XJ-0|cc69MD zA92!={?zyK9qCUmpXmK*-)ktCKJ>iK;90zG=?!34|1%*TI&Pu8d?vZ$E@czp8Teo7 z^319eeWf*|6XVvb4S}AA_H!nI={K)1*0fVqw#}Rw?Be#3^wW-dFzRY2#;tja^IoTU z)MbvH*0N8TV<%S|<=oimG;LDDpPgQl8zIIpH9d1)LT%|BP1(vEJIA5TpR2$b$uh^z z*~wWva0g{0&*D0}y+-1*^Em4Gdmz)9HGzFDr#`41^egN~#@zV{bs2LPOO`QriA0`S z8k|YljzEp-QkeWo^gyzVxl1MTkB8u<%KBOEE^dF^bq@L;w2^0qUH19f9#J+|q|d+E zR>syf0(BW%*A!$KTi0~t+1LxZa$h#fyMgPdZWELPGtPDHU0YMXwgh@VWgS~r7xVp2 zLq9|td4}2brjP$2%N)CYW7|BapWWh87oT@aOg@wc>|$Qxq+34f8^(d@A0zSBjr*N< zy*ilw@g&~5g{ZwLBmKCVU$`ZBr0U*O<VCkBw9$TMQoq^;`X;jWvx7GH{FmwWin{o- z+Ye<cdt!HvS@*>5^sR035_)E~l|2!EZ!hs_n{EOZp&lK3V)p>*9kE{BD=X_+xBD+- z`TL#j&1jPxG2ESX(iCq9b~!G4V)vnHW462jb1u3kc6T{7aSU|MOZUX?oR>HCAoMeA zD|=%1OXOJ3z;6GNJ+b>6jsf2XW_mD|^sL*%<yz(u&{MIk?1?=x&_3umn0vR8J+VhY z>ibb+d;Cm$*%N!zRQBRwU3$2)itLF!I#Pd=6+Db>Wl!uehHbak0xzJA?1?>?7be?s z@NQ?1xax6`Hq#n_Z~62G<mNIjuBq;cJvm1^2tMiQ<|TV#PtMCcn+h(aZFTSKS)Tk; z0_a>X>TRg6#(ii{=7=eUdew6j^^|{u7b|OB?YTnP%Yk_7>GE3k#GcG+`&RnD!M3s| z_Pocog9n0HtBss>@f&3tZzrOHQ#yOpw@^3!%nQM8{IVy8R-k>^N8skp9<>^0LG5Sa zZ(#ag_r%b#w83|wnNa6**%L$8P+#2~eBAXT`dRkVzbN=Qb=ea`-;pCD4tvF<jqHiN zc&@N95`q~&x+nJH{$g6BgYM1@6HzC74PrkXT7c)WpNVzAysqgS8T^;(Ui;`^H->kp z3BBIZ{$FtKh_uOr>-LUL9v=>znl|rIPkLvhz5%h<yO^@+nhRW-db|%{w=XZj^Mu}w zsBhZ~?n3*v7(?$+W&0ie@6El&9zPFeU9vU1gO}0%>PE2hZJgF%7tdo5lfCI@Z;<qV zpY}_Gz)#u#q-fv|%3f|6+ZWn=uWU@8^t72i0-TFH_#^ljxkeH26=i+*)Q7%O?i)2s z@0(WHbUA5E-^^_LG8?!gZ6r7QmZe^;EZE(r-^0514Px6|+rd3)v-2sqA9?70@JO<p zWBZOLCprdRuB^G%cP;fXm}B1)<WvR0E(W#@0dw8;Z^Zg?E@sgYWBPHeHFx@PKa%gN zH2pHMpY(^oImmxZ2Uk?~-lPOqBj20{{*5f}>H4kqG4ogbhVS~6oFacxwlc4N-^m4$ zgZ+~zYc1;U@;BoX=x*<jb9jHZcdTg)ra!f|^rt_)E+e7$<+WZR2m22uU$_RI!)w(- zo$SAedSUp#{~qe%xBiF7TULTOX7yYDht%h_GG>5LR=?r*Ms!|7DnL(08}ZwKG_>i6 z=WGLtQ<wD}P=@*-++Pg1OI_k^fQvDCzd10z>iVv8V0PL_z7NbxZi}`9xfVupf1q27 zZrD!;2CI!3n+!aNEOlVu2xYG%o_!6ZA57i+VCRS8*h2?yr@i=j;9g~$s2cbhS=MXd z9oj7X1<ZR2y)PSNsdxQu%%DW%kWJv^%HE$P!5qKtiGvE$CK=Xu5XWz1PaITRbsKLT zm~+wRKZ82cK0;UMoQpmW8RTk62;yN7=c4N}$mK{L#N;5ZDRt(EDQuy;HI;QA<Z|TH zC1VD=HLYA8%p9>7hlAak${sYBIbxE-Z-cp}8YhFfE_NG&WN-`4UDkB)03RRq@pT_F z7j)f+(1&E!D6-2z>2pXkZEMS;h7W1Oey(Q%_a_he0UoMs-W&tZA|KfRo==+_FTh)< z%f2vVm$I#gv%!$_w2^&b2<xH!7z%zxJ@;cUYpm@w-<YB4sLNS#Xg*~lXYZjulS?H6 z*Cap43GPP5XZ+33VdQl)!4sAB>^*dvvNr&^GjtVM?q!B<pbeJG468?e9|(4SkoWAv zTpdte%(lwAea!vQN^TCjK^^aJ&9KMHW+8HI*h^)b54Cidt6lLCSHs+TWr&Hd*pI@t z^0%VHW3lae>_NlRQ@{5wI4kv*@xi62<9CnE@bcuwJHU--gU^hZ;mxUM#yM(uFY0Yj zTZS{1Ov1I`skAZOz_ZB<(}CA3+dA>UTgej;=fh9Y#?}O1P&N^9o*Dj>dX&20*R=mu z80_}VbAK6w?NVx;$yXnokoK|{jBs`D9CCj|9@<C^8BvJ+JV5;!!FAV~KcYT$+(()b zE(YZMHljECoYV`<7|@&@!5A>lrGL&#pLvepybON7(TrfM>N#zMi`5h!^!L1$<oJls z>_6jHV@AfOE`K*YGAZ?#@Zre()TM@xEJ}Tq=yjBhoEt|rq&{N-xF_us;rYhMe&qah zz%yu*C@Xlbvgr{QyotJ;4My&uePq<Yk#4`18aR?MX;NGUzo3oW7mR$zem)#FW>jSA zchJwMnB?4u&r!@lJ(G;eLi=;~pu2dJ_#ZVvbx)Z-B>(BtSsPU!-I4ti-fPTg7kjr~ zg6B|I-s0mk>_=+U=u67>pP^vZSWoKeXt&>;=xxlHNNoGK88`;pwmA;YOnvJBa7l7W ztmBxn%61X<rZLs2i{Hk$HM)EO96}rM+n6ro&C>r!viNO`J5x3633l~C)@95JweebJ z0Pj;)e~xkInbTwNGaBL8PaxKAY&_am>;Nv{<7z&3bxC|OwgdI@W5Gj}%}A`v*wNIF z?E<qtn`@}aW0$IKYo`bAr+pmU(~admVpcB!-=j?kVrJ|U+MN0UW{t8k-*Mror|k%4 z%<En}E*0CpMqZEO_;oKHSB&~qti`w*Wbx;?ddl8*jBT8oi}-Dv%jHSez?_Tb`#4w6 z)6IjvQrqg;b)2hF^4kRCPEwaTFwW)jdg+I?SMz<G%VnIK%y<{`lE33!F2^|!&KcIv zc;>R#S#-vUl{zrq#mR@*;Lgq-d-{0hvKfXsj-RZ$?&<g*4ZR<{g}r|KMqmHisgJ<k zH~u17`@cq;_<f9-kXG4~&w5R8IjH=rPw(pEu|D2Oeuz3h;j*$Vf|!}`O4&rh^Mr{} z$<^|LUF?nj2<Cjfsky<dS2hr5B)o&yx!gc(Ozc74@Cn?P{Y0n$cJn$n1$=?J?A;Tu zk}LfU{+n&ZW)k;46XzS4^R@C0eUi)HBm2OtrB>ddPof{p$0p#K>_^_kPpZ%U7a*4> zvF3P@a)P_l=J!VU$(lH{X`d3zy;YwBPtHa?5zZ2mxu2T%b-`7s=SB^j+>|Ued~$1L zuQzJKWLLLSl?J<fya=C9UO=1FufVL6HV1NT@^0$+Yk-}9<U4*R(?52V^#59ItbDFx z@;|gsi}~W+t@>X+7cnKCvPpnBPI11H&rwXtMVrKjz-}(r5yMm5T&B$fw`JQV6~Ud9 zy}9uJZ=cxqc>=IIpM+jF27jld*DX65>|!P>;&y6mr(<4I6Otp31SfMk)@~}#z1}_S zcT+Q|Zf0Qb#`i&MpA#d3^O2LGzD+Hn?A<|pP7NT}jRh{JY@(uWOszuuvp6SAb+x4e z&K6T$ZOK{&+?X~=H-KBP?ZC`n7sC}=fjM_uVG!8GbA{i*E}mx|1P^9E6=W`~|7PA} z@K@?_M;J3LGW+k<9L#!RHdY3+Hkz{~z>G0()KqXG+OHBlkh~Y;nO2>BmU|9n-gyN= z!ELC2ehTiU>{Y|rVA?>(MZjYnV@;>A=6E$xSEnteUNateo#Qm%U5=6C(~da~0J9c( zHLHQ|sBQvlgI_qC2VlmDS0|q_(-Tv#hq+I8_3A<p*v(NshdG^Vq`5Y|9_{gYNi&^u zv5&Tcd#i3Y-Ug4O&4WVVDNf%5=3ZvB&waFsIsv-dTjyXcrr%VZHtw8oe77+(qJ`-* z(vhVu&B#Jd(*?}4fp->r$BfFVdkImuX9UqkzT<8Nb6>v4&dgx$8_ByFLus>c7kIX^ zt%miTv5<PZPvC9TYvH->jJ@P-SkoCi=Xk6C1mB?j@fu)PtGl%UyP7%wwJ|eY-W50k zPDJ}0h{>6(1Kybw;9S(F-vYCKYCW7;ntHk<(76`6&(3T@-6ED|axL^(%FIEk+dJc+ z&!J7c{a_bY(NBQgzT6i+oVh`5yn?7R$REw|-KW4O*cP7wG&4CzZ!>De%=^@jA24QC zR<_;o5FAKd>g}vb<nq{aXEjx}Qg3IqBBN%TS$%0EYdVWLYiefzJ3oJ#0e0sZc@{A{ z0_{7N1g9d)^Xl0dl|B4jnwjl<CHEt<E7IoCcyJ4{JeQswtZX-I0}p3gd3H40#c-s! z;AOOtXGgQw(&nnP{Y1uhk(%G5D4U!g!RdVL&aN`A-^<ayRTFSC+NjQYZbxIjzYp`Z zo#o?AK6d+#Uh7?$KF95kqR(;hqwM^z%(;6LkHdy@H$Ucp87KNZkaI?|&jCN6&n3$^ z=PXgSfv>>KU#$sqj?yMSd@|=AS#oO5Q}T_fMn29bv81^+H<GeFbQyXI>Z7oC%q>h^ z&JS|~l)b>o;Q#iBtzdUf$Q2Ik&I$dHvvXbjuQnY#iEUM%!9I7+hQ5(3=a9KOluhiu z;FGiuYzU@ry<NS)Zv3*p&wWGt(EY~Xw`6rLokGF9XEAkZg5CK?&PDTBm%JM1!EP?{ z8Ps{@+4d0Pd0um6+q4F_3mLy{XyzSJ_9U+6xwGH&MPRqqvKI3`v!7GgN9HGBTd|qX z>sn>zAlY3@b><g!o^!}Mef_Ye+0EzBr>kjO3xVAjq?XR-80;<7w*|2{9vRyLo+V5p z<oJTzKD`k8$LE;Lf|}GNP8R&C>=nBY?o9o0Eim^)Jx?x}LVeps=q?WB+_+$s>UPw6 z@By-{?}FpXUYac6>(n<z0W&^rQ^e{5=C6_UUGRhUYjPN~kp48Xz6+DF?VBNBH-1^K zg<MA~>$Q+$^Q7)A<aqR1!NLvN)^x_07jlo*y0`E&``ld@`UBdC-xfZjo)dL!QC?;3 zb5RxANG)AdgM7RnxDD;4mM-c*`}kMDLun&@E*edi-_pW!e~sJxsO^i+E8E=F!MCW( zJCsH4p6f&$V;0A!zBVejH0|Z{pZL8f-52I#UW>W6>gPWfw^rS|*9rPSpZ##^`4>Z< z=hNLf&Ip9Q$EP1sHt#Uz#XJwNf4A4v?Pko95ww@Ttyr?3EPq?E#QCrt@@vUk_S5hZ z_#16rAx@TtQ}&|012b-I;<aGLt#>OrxD0Iuo&ncl+leQ^u2w4#QC-)1DgA6yCxgv= z+RM5u{e%6qi3r|JJ?T$iH%EL<!7RPz)9)&q7EPhMF{jFg-y!Ch&8}JCB(zsO743H! z=sYJ_`M$wFxL)2{oE!gW<oZYa{LzA3`ZRa|+sZTTKe$FVbA7O@38@N#m(jiuV(E{A z&VDEO1oc$Efge&|H30mAoCJBjjC-F~bUC;h?d5M+mi1SrKAtRp!?KM2p?-?G{0+;p z56UL`G-H-KKfL(_&Z)ZHdIvm)Hga#coH3?*)AFUX$uJ!{<3#Tbm%Dr{*&90juj{zn z`TzV9=pWfu)^YiFWiJI{c*RfDk30dp`j)W+xFBt+ZUX<TthHqYYn}HNv9!X)kK7xs z=tTQF7~2Zxf4MhYF^>IL{|;Wnexy#WSV6rLVt$32i`*No;9LwoFJo5Rr@h=8u3#>B z54Re#lIw27KPy9NBlTgWi-GZxz_X~!z4J=OfLZV_cq4VGKPz`Ad-6BAE6*xxO<U>q zsq*QebG^J;myKB!mG%Y3fn&3u!aczm$WnV(Wur|(_;!`6GvXioCWqFmJCngpl=W{Y zR<)vivkTDs(nkEVY6$iF*}-lu;-6KViw!UR@1ni<XVpP+gLYunKsycRkX3G95MQl! zW5zyXR=c&^g7ebqUfR~y4Fyl<b){C|yGXP)N_|-E@?Dw!(HL9JYk4>ynbq`_`f&AE zj%O|Q^fhtVkJJkMt%daIHT?k2;nVXweHirW)TJh@sY`wBd~kc8-p%Q$piiJKwPMXQ zWfSixcs+G_wzg&)^>M|)7syg8*0_90bQAnH?WI<%VZAbVFK5;!a`vbdYg3S8!e(t@ zveb&T?p)LmwQKE6>iLn6Yw1I;Ip({TW3VBpS8MmEjg58!d|cT(*%^F>`sL?fSBuV+ z06$mVtA_s9S+dx#i==ELYy`WpiT%2C)c>9bE~aec`$N`sq8<w|v#vk+_|M?6w5fnR zUB`Iy9w6S<x$#GP0N$cD-p!KW!({m$lJ(3BbF?hjt?w=5%leG$U%r=PeOcPy8x5{Z z{pu7jb5_5{d;JvZ0T}1{Rphq0!AHpQ-QDX?Dx1Z)Ut9m!r@vJ8o?u=ZB2$;|^xhDY z_VPEO8yIh%e5dz@e6){>nB2g4^W?jEH`Jm1yFK6#vV5oahA!mISjP>l^ZK3M8-8Oy zx0ga^Ea`W8Z+NA;@<y(aey8_F#)*9sV9ZADBl6ijv#~b&e<`}Vmr=bl`>AmS`Uu)Q z84PA!HOa<<Sy#Pa)P#*&)rNf5$8J2^%NeuD`R6J6*%Xs~Zs-BdtZWy226I31)*J@U zW<OKAfY<u?n2%k2ip}Qm?B@h>YI90u-M==cCs!^E-Q|nC1KnJnx=jLZ&bIRX&zsv( z&x!TgJkX~*KeRy%Y+g)VKL5Gd?IUdvdz)FKJo%pI&9`Xd9RagOQD=>^chGhVYm|P^ z^A^UiJWn!Pa&Qc}F_$f@Q8sx?u#4d}(ZD>%dQIW0Ep60ZV`)oAwvEvi`Y`J9ea>5$ zYu@oD;AN`o_c?E&Z%x!d=*%zue&#JM=HEtz?#}%3J<nU7ux;P>;2&hEfm<Ugn=B2$ zseO7TWe;1c*;<DBTbysVR-%405t!pQbJKxGQIA^}Og|e;-E3V+eOW57^SSEBs6U0@ zw$kS&6o)zdzKHH4>uZ7Cz99NGPjw^T`G)Vt)qUZ@e6Wj|_l>}AUr?QO%r1-s-Q7FL z_cL#+&;FmG9&TfO^XkJt+j>%8_XEti==UdYn?SwGdg$~yb=EgCU?_CPkA7eAwwr2i z%Hr(3?GstPuXx*c_H*#1G22s6m%V#C<J`Mh3CuBj^8MS}>2ohG;uF6;FY`4U;kfM$ zmA!WBz}$;X_4Hs@8<QhXxBpI?%G1Cu-&danGfuqj`N1wuVjy?6KUI6%^dImWwmk>? z9WKr<76Q9C&ouzdy5|Ky0`p8_BZq=}u<gWn;Nj#x@xjx{^7qj@Rw?UQbcZ`%Ew~E( zs_IsLvtY*^GM+7&9jq00;9p?IgZ^g0PPeZe++xhm$h4Q=CfFH^{h!6=x-)}M&rbbY z0_YW$y?t2Iovi1!cnffA+Q@Gf?Ce0BF)P8tl&$<`0lueC<MYfWFnw#g%mlBX{i6Ud z&p-N`1v?K>?~npIW7{mR4Su1zX^cGD<?5>ZX2Grmv`_T~TtL}&#+hnYaq{<YV8*b? z;DMXcz7*=@uD-O9-z?ZQMA<Zb1D;14`OSh|OKB4W`L*i+S$=C^*Kyh}DhB2_^*0N4 zahzW5BF5}?eir-P^s|@dGdOElKfCjgU!l(Iu1dbJ56l?$b{7OQ@9Y)S$=xpR;@<_& z<QU{P3wF<E+upx`U7X1G!S3Ec8~N_j-A8C+Wjxn?%(|_=JFq84n7${MkL&rkkB>P9 zw%w(=sQ@4DaXBvc4tv}lf!~cWdp^@f^u31t++GO&$)~3w_c{vQt)uK&djn}d>>l`6 zvg$$P&k>>bXWQbhz_T5rrtRf<RrjX7+i1TZbztvlW$Kq`A7wan=8^7Md*9LKSZibU zaZOd<$2GN63P4ZKK4s6^myPyEknj6SQ?L3O%sjGJ;)0vdM$Se1S}B_`?ZAvl{mp`X zj7jfuKIkqcWslp(m^4+#ftfqH$L(Y8m=VXJyYrIlW&7@O3}ZTiS!1<k?)$;(c0=vj z&)TJX;(pdHuj@eQIoMYAzWw=WADjy8>VWEXsgF4XJ(TvR27wtH-iwLgP1NOnVgF8L zFZ$o$zkK>la>8uTIZl1IzMtc?PZAq*AgS8uZweep&3;lMmk$*4>1EhYvE<O(`1Fp{ zdm&B^Oz`Q`l)X-mp)*d{|2EqEG9CIAvh0ZmZqvRCYTAK+Tw9#A4t%4{uB^r!OcbUc zbo*DsGSE3T{o9a(?rbm;XW)Z8k5TWeZS4?@^C0Udb$5o3z7aZeT=&+4F2_gagnpfE z`=E9myhnb47&zpG>4&0_Ya#~^<@M=Bl)X(@qeD%6x{J?e80VqkKAq=eucg>;@afx? z&1~fLp{r!s(+|0QDo+h#4m0=l3~)FS+x~(x=V6!oVt+U@_5Rpv4l{T3JNXYY_PiqX zp?6ms>dYPUyaIH0j%xiK%&~b9P-73@@Y&xd_eg8Z5$3h_bHvr^{^<Wm;V}Cn0m?Sq zQ|K*ydI))GZs;zS<hn=ZsBSK71|RU*A16Pk4*k7P|3dptgN-?wE=)hl{lW`Z4!YYH zr2nH0)y8H=9v$Vn==hJib(#GF`d0QMzgci}5A7>G2R|jtXS|QTQ8t11jXB0TtiM@s zjQM2?1wt=H`$DK)$10G+A+L|MXInX&9qUH6XTW2Wy$ct?lWC75vpKfR>GQ#BslP=q z96PLR<o@f}N$N|hff>VI_d8&Y*-HukALkiB_2UU>KQ|9_)+p-5sQ14IoxY;pTy?J! z&S1xfkmWZEj*lj%K>Qqc=M&Xg6Kr5O=&V=zn+3;Rz4`}r<M_W}{hSD|Y}X@SPH-Ld zHw#X19nFb%&?~DA^%}IFg*ZRa)2DMU^L8zVKG&x&p}jnFIN|&zzfEw0elxuvf?v>H zb;g)ohJ61sahU#RN@cHZ59lR*dO2l#N9>vV`db5ky0zZ*20CMm`fu!~(Ff?ved_zz zXXV$>UG8tX0e(z9C(Z*Wnfv<N1Sh$sHgQVm+;^zEHLZ#KJ^3rIRW}zni2d9~E}R_X z(??RTi!;(m#+&|T!AZuO*BobwlV@lne`|Bnt!dG}z;Asz_aJX(V`EMw57SR^P3;uq z*QuI5-Hokpap>KBdS7KP6l-*9fluey?D|f|oMy~;`H(NC<ExFWh`MpwT`SoFa6alS z+kykhUvb}hx|Xsx7W=|!)+N&)`FMJi>SPx`^33)$<Hzf}6wLZypJER^&H7-TUIt%d zpON9`(|5_6^BQx8Yhka${tWZW+k!La8Tx@b{a{Ps{^AVxGJT$TCY0l;)d%``WqqD` zW-9xy*A@Co>T<3)<Mx!Kh^sTFsLONCGZ&RjrHJ5X)a7~R8Mk)R^BHs2?J1(4Wn7u5 zsFP<iyMC}|o#pw~Y=CdiG9UG`e`lGG<`ZJ$tc!X1%;DK?+SZE=|C~L`ezu{uoOS1c zMu_vXuc+5XO*_k)U<bnHTnyFC7R120c(hrFcsrMYEboiYWg`zS1a{|y>^r~}sb~BQ zc6IDFYRI`xs(Z>)e9U@f<k{&tSO05x;0v@F*Z|C0YUOjk=U%h_?LCb-A3@n1?+A`Y zy(8+w`P6JXdkr`v`Bg%&Z{5$k_%AmQI@ev};XK#fi-Gx`pTPd*9l?3-m1h1m@G4$Q z-l3e|NSoLP!N;jfJe+qv-@gw0oVvur`FFJ65zm+lk*UkNUx-D$GxG65dY|t6Y$ri4 zPhHNX7pjs|TmiRr_65Q8vu%yKdSQ&}`kC_!la;*#@1eVOmw33~_5z8Ai_zJS#KT3m zw@N%*%*uWw9xmo4f4l^Cc`fm9u@c+v*#Hhw_9PxIwkGG_1MW?h7`Qmz$BY4ujf<|< zNjzM<M4L&8z;DU<FrG^;UnCwbF;;DdbKtaUqw#PlGr9RT=-e+niHA#NRkw?<zLz?Z z<yp$50pvk<!83f!vFUTmON>vGZ76Kc(<b9o@C#+F8<*VrK8b70U;nLdX>d%n@p9pw z>#r<qyK5Dg=QRB;ufN=0c04h3=8ir~`KuZGuW|}{FSeC&{>41fvHdlRHmmkQe@Gjd z*I$2!*<a=uthBw%ywJ9nv(v^bfnI?u^SbP=EAfB1jq2X|JYeqiS`RM|rG4a>(B~_g z`P0E$XfK}+xx9<|tU6%&P3Lv_3iTcrpubkuv0aHmUGBTD#3uiQJiStvHu7HJO0bXJ z7~~zn749ASyPsDUv+c7u(D%|_-W^;yOuhX=u-oh99l@1Hv^m?|n5z+$^&P=g=7mWd z9eO6}axZ)}2kj%|05cbiyd${kav|3Sa4XsrJq8XT&yNCLMgD?3y}HlGya&;D1lQtH ze-mKLHP$qJM{td6XZv8SuN7At>a4@&=>q8WsmmGlS`+s38{*+wcV&GqaBY;27y8(Z zN8S-!yT-Qij^G-7<;gp>YhS6$JA&($JPLc?b?!l)JpaEwh<z$EKB@2a={(O^c}H-a zIj%8@-$mBvz<n|sbAx`+`^p<hR5#;r{=bo5S$_-ihTGrkFM?jfr_&FfsRg|U+xDpl zcDb_|b?L@()%Cf`jdips6BqgspMHvZHpKId`($|+aD#igSEHvf_)mS7EBZ~=C=-wo zoLqG)&s%P$BL}Ag7g5%C1UE}j|Fjr7<6NJs+-$76*;fL3Z`%A)2~6MG4_J$v)2YjM z(A{MGd!dcMo2bikm76=r0e^zek!7E{>2h%9GVpt!{)N1)xiPmAkmVi0tz_hLIM?0c z_|2I#;0DzD;eO<n^K(lB?nnL61hDhD>a$cgrFKJiK9_d^x3*I6hn&6Te6BjrQMN8( z?3VNSh52B&FYGO3<a-h|W<<ZuT4$ES|F`LLBhN!_b1$>$dVx#RUfvPhuBdE3N?SJ< zc`k7~i2A*mVCQqyN3!i2_~AC=N1qSeUQ7MfcjzaSsh=fJnhgC7S?)t`yEwmv@!xTK zguElT<9uFcBG}bxc}H-EHOE{<KHjO!e&ij&onMr_cDKMC$Ws6BFyGApoQ?6B4E2w^ zBe>)0<js5FovQ0Qf;$J4%{;8d9T(^Fj^K{-`H_YAyrYX}sl#`3v#oL^vee<bEyz-D z@3te?SqmQK)5nmn*MPp1EOq!UYon3RJl{R3y4K;l+&jE;s5y6EQI|S=_k*(OzucI6 zQOQz=@5NTOTM@(evXP|@-^)WDg_>}00$J+ty+uCeo~3p89&40Y+S-`=QD`Icz3=nG z{Q}fw?)R&cW$yRuD4Xh7)BBx$dQW9<-W=$Ysmt8&^Xy@2qQ2eVMjLrgeSeR#{7r_r ze~r4#{l2To@A`rNp^eP_{x{mJtzyiB#LD`f`aufvjiu20kY(-<e13SajBRHkHy_-i z&6@zQs}J!}Lms&LkS?h)51pSyf0&4E6TlA-d9KjsBoFgZKO;6SPHxQuySVN17no-Z zd+`;xBd=R&Ab5nbc{m9?p8Bs?i-#+ySHL;y;d<&@q#su|(jfOAy1H@t1o#DQY9Zer zaxUgw0wdqUE_q=^e-uaAtAw_XxYygyjlemnC&IiQm7~4tKP#Jus2h)5%qRQ?cIT7! zVn3Mns*fT+&H#Nrd2tc&AIjePI$*A~Rh?%QuVgFeH)x+_G?=;R?Jo#+Ya#k$%tPi< zeGQoFZWhM@r=(tHHkkXSx2+wx81?(%z;55X)EDgb&Abo5ZY@;rLHovt&&OkxO`&RF z)^__m5bWxq>g#ATa0ztoryLL0$o_T&x|@rR=b74j2Rvh*xcyXqKj?|8?L&`(nRoho zLr>g(dN2y~B5W(aEA*rkuiF}DxhHjfdSh~gk<hy-+XKzO%muSQB6tDYCcruQ33I`o zK#n{)P5YcD!I#L-SAyTtUf$U~`9ytFXJekavq~WR`7{;v>*K+N$fLV}OS0`_)cL0^ zeR>G_FRbHJ)(2B_DR?IJ<2AuN(^7Y5l>`{)Q^vX3zt@;&j0ZBuK&G#3Nt`R5)#e!F zy#1^p`_G7T$TQX`yY3~pKlO-}z`v2@eb%$tZ2KB#<7X}hRo_Pa%TwsiS8Z{R`RpCr zmUwH-^T^72?s^`Jd@3&V^gcZs?Hj<)&$(ag`>f{`RW}RK=X0KKskdU=&{)v>vaOtp zo(~~+t_*fQl=IkgmxEuQgSW7))Ya#^X&*le_=2*2&j0x}@~i>S-MY`&3g)_d(NJ$+ z#G_5!<KU$12hZWm3+A0UJRHot^By3!UpSxdMQpri&bDc;gE?kBKfD-CeN9j3E<WYG z!wbfzHy}3H#e?cD9wLu|ewS@kf5P#^>}br(@L~GPXv&^^$I(l7-VpnjIcQ(y4!9C+ z<b3k-7xKLrV2)XzSHEnhx@qzWI`?|&u2xh=eS67TXSSUNuVMc!F|U`$*)~lp@L6(= zRN&`6-NjD^#O<pXZ2MPXaC~KN0mk!+wc4s)fNck(2EO8$?VzdPdeqM)0C#0Ss`n<Z z907eQIcO;OcV%x#C-6<`+v<T`t`)0h%<EFB>;22?^0c`I``68=%e~m^w$yK}1P>rf zzPuhzUflxBYw3N>>qV-2zb}KnkK8*a*p1;)1Mqw5@)@VsUzANiIb+^%U)KD3!+qKQ z_A~VCw2}LiH~H9hZyzw%SM%tNTi^6JZ@g)(Hu}ExO$WA3xeoeJ>XJuqc$PB_u@Ams zeCmD88&^MH?SSs~HM#G2<My@r*n{3YVxM1drg|HReLh3odz*$V=k2$dmAzZNz=1x! zG8xNj-UcgczP#;1zJR^p?I@o<k(_@y^p!q+1Nq=&=&bXa?{8VVOj4YO-*T<>ee_%U z+$`x}%)1EMR_o-u=;Rxbpu6$oH;c?Wj^D<@Uh}S`+Gt+9D@T5O5PFbLZ$s|53c9NU zk}vOA2fX6bz)RG|NWQ#VrEEi9fRFlg&c$xPy1#o$8_A1zZ<M{l*e~8k3)A1nB}eZH zopGZ1@}6;GI$*utSEG&O%lkU)CudtQ^Ti}z4PLIgi4DKKUrYO{>%kXjfAbyqK5fPY zgFl8b{*GPFFh=wb^qW3g`{44r=|JdZ)kdE|eP9fD%f+5PwDPR=gNxg*Nx=PRueyud zFB_oGbNyrkFIDyeP@_KV^63Yum&^<O7Ipc1y$=tS&B15Jpp5I7<?r?WW(<3H4r>0c z!M0f!gPYQ3)NOD_^4i&8x4y~?efkda%!ROVz7pU5?R+J^{rg|Fv2Q9E^N;hD*!)wR zZN=uFGUOWAcm8qLRU3C*wHd{Js{R9;&9qmW<Gy~*kPl0rjDIWlm><Kjtvpx!n9Rrd zX)ouBk44FIE`b>{R-Q3_>_lCjF@Eep{uOod<5*=~-;a~YE22Z^eqk!d03T9apPha@ zL7RUIK)<7`&lo?lws?DHKzF{9aeiVw)LQ*11>25%13iRoW$vE_lEputhSR3qO0cUH zYIDSAbCSFad*~;g2Q(KxM-Q|4%=|K45*zc`t&8;YxvtNq5&1+i=!2BKtBB#x<ETf& zndI{n>cPmV&u%=su)d#p?y{#Vf-kF$?R3JJFD^diT3@(VYHohv`NW%513K%Heg^wX zO}3T$+%NQrm3!MS&JS{L`(-T0Q~NXc58A7~nk=8={c?;f_qJbLUHzvy_?7B<U;pI; zxg6&8mAS8b$Jc~xyLvzLY|8q4^=lsL@o+x*T9qvK^<Qg|3nHh!t|!aA?bpLTX8!7Z z{a3d})esxsveHK8`_1QvZ#*aH+`o09jm+^|sIr$Ad+s-`g+6os=FXOv$3Wjidzt$; zm&+@#4}QDGwsK$pjj`%&wcu~m<^1`tr)=6}1t%uUef__TRr4bcxQOa{U;l3aZEm-R zK8L!@{a>FS{$-Bn+`osX&6@yYz9%5d{rh*9zft}IJ3p&lSZ%zdd!ScS*8BSJE|(u7 z-oCpyk^B1ZU1`(39hiHT-q(MhM12U(3E!8K<-Y#=I%V4!G4}l=b-Azqeu3Np`}OzN zWVx^Z{txXxW8e7^lPve|KR6fDtRR>%qxbbc^0Ms}to4sdt}X8CfAE}RqTB*=&(-_= zAFPx1@3hce%**}z59Xk~bQrvt{ix2fguRP%^^XJ8<^KJLtDn8FzCXCudSCzJF>U@l z1pPZ1_wUw3P&NhOSL4<~^|Y#c4Msrcy32jEHKnM>dIDw*k^6dU8nd6C@4?-aE$-i~ zare2WF<!&9pgw~(%cDSF!?w78w}yLx&4fP8pFaIO?Qgb)j%&+)t>bZPWab-dITsy| zjZXXJsArbvBDsIJHnZy9Qq(HTyrW)@eI7dvy&-LIUvF)5>cinH+smg9RJI8aNBGWn zeFlR2dTW^rCVW%yLAJ$xy|pK3Qv`Wn-;i-%Z|z5AF9iPZ;?W-W_0~&D{^cjI+sklY zZ@toNJAN<tS2FJFtrtZ5*Zsj*GkGSX`gn3m#FxkVAouUq+e!WGeK5u+{#2d5wRN5u z8;)@<_wP0w<AKaEkm)PAueafPvLEcfHXOzwea<=qb~Ot3^)?*VN%YZ}Q@Ab4a^GRY z?N;`hVco+q2dQ79O@UU>=_`Zp(6iy=v!C0sz**Q9_aioZZt9sa#_;8RdR1~;<Yo94 zw88y|4IfP2k`6q`r;nulaKv@^xyo`sV#6;XuSx-SKE(Zq4S#@bcOZVlUtwF+RU7^` z_2023;Sql_cRYu;;lGhH!S@l|y5qjyM&P=8dl07)^3w+Q^)^B=Wm~urxGr_v*V_mf zANur4Bflc_rw#7wZG>U8nYaSXG0T05jj)P(d-yDZi%->0Q14wGx{C+Z84uoB_%&iU z+K3)8s<L;-f;0H^?Bv17*N7E;I{L*pZEzXrA<A-JV<UDYXKw)JnB_jjMjT816ml-& zA7s_nDC_UrM}%L*pSVx45zmtE?EpU~<37bkd`F&F)7VHc!t_XtA6x7?^qi{8{kx5X zoELwdP6PhMr`KcKnYW;G%yOS%BlV{J^P*t<x6D!X-)a8`)-e*+Rdn3f+emwyeh&PD zI_~Q&-e>Dva9?jDHz!LTMQ%%u3m->Ddzmlp>uuyQ%3e?O7kPoQ=1b&d)Xz?V&TCOW z%(g+Vq2D9F>kM{dSb-WAB>~$?9z{u}Y&Z4*=ke+Ak<4Y)UFaCAj7Rb)N*(HlMuWM& z)ZO}Cg+HQ<qK)KHl!<J6a{_oNb;+YBtI3C>fEk~1HnUL}pI-6GV8n-v0r&Mb%42fA z;>Jdetn8(k1cu*X<87V?4x|n4>uprD7d>5KFyce{Q5`u6He)YCA4irrkNO+!vwa1x z^ywR@SC{@z`Sgp_&wq#hhPvc?)Q`$GTOnhkajiA}qtWN~zyatPX(M$qS`PM;XEE4~ zANTb(nj8PiU~mv^Brl@1VcSSp=V(KGI@Uwx^$hKzEg?(3L|a9hxhcU%sY|{@!~YZe zgQdVveY%@V6Rd6YXsT<zM2}0Gbcp}x*?oFGWiR_%=!_H1i|C9K^W#2r#Gm+I@+EpG z`;m8C(Gk0%kL?MDoiNVHHoEhnaE#d0agShQWFh06Y-8k7Hd#;yV$fG|PPQ?AQQhnK z0L=KbI49c}U8oQK7d)AabFz&wgZ<1c0mk((293iQ=of6FVO%lJl5tM9`1}@awt(L$ z%Q@M`_(YzT*4UVC9dS;!G3!xRrXS>-Y-6sVj&rh&iFlQ3;qNhR%)R8OxNgi#J{|Q- zY<_<R{ViGQLrnV0bjKKD#ZX;7gJEN(_Hhv(yYb*N7&aDtV(}Ra8!J?8>`9CzmRlEm z2E)dhNj=+qV`E2PKlt2*jh)2Dd3;>k#~qaAGZ;2DYl7St+t{cD;^(pZ!SsWC2E)c) zuev$927HQb<;)QKBJG<D1!MkbtF<mR{osu|XKWm-z4#~k3vgE2_xJ`b<=XZGS76&g zwZO=E8H3coI4!APhHv8ZQP!G<-}O<OyBJrT89p7gK*lh#5%kSuscCU`(SEZBK2MgK z7UwE$X8a3&O&x#3V&nYd^kv4zjZ4O7Fl=1<)=tBo6E`PysikoXux+n0;40Md84Me@ zhO#N06x^1&)Xcb@sDJteJjSO_CRZvCeKi@M!LV@||EB75Fvo9_wg<mg8*f`4W8*nL zw>01cY`bPFm_C=k-?Z^yC;k}+f5fBD<?l3YJXasWcLUSs)S0KAd>>Cd=kp7Qw|FjQ zD)a@@=bq|rA9;oxk4K-&XE1EMgS>7iVkh1;jv1f9u<`CHn>}s7oQv)S@jlb0(ivmp zJD<xQ5kD36xLv@EA3amWhreWAv$3Y}o3T&XJL02X(Tn2W@kdgZy&(Ps>IKq+IcD7p z;ya(?F@ufo@*SVSu<?(my(fEDeB?j+l)uxo@m+lm!F3Zvqz#^r*#t4jJEDUbC-Qfi zHi3&1eAd?{sHryc84R1?SN7Q#`INxLIX;776F8rr!Zj0cJRY8-+61TBf3fD^dp`ck ze(-F~Cd9mD?wR4Ygvf1Se16p?OiugGb-{V5;~A+<SXkL4s}6SYpn7fUKS^80t;Oe8 zZNeVZgXV(AvLDqaQ*YV<y7MQVo!W#Osc(-1=J@5i-E2b48DsON-!L{&d@`P$+C*t+ zk7uVA@8H$vcwTA~mGyB8GM<;(M5q_CE^31@NuL7|KZ({VTYP_oO?1e|$aAq5UnP1- zeo_WZAF8hsd#Zc678sj2G24ny@HYV3|25RS#8_AKBhR00;$lvZ28Mq{7oQ|XEXuWV zP68vx{;&6;o*S{07;z)I)Q7}#$XP#vw~_G~V4K**z`RCa=8=4_tWA7ZZM@&!fWOf` zRY7Bugi|(~x`R`Y@mX=31lPm0yivjd)baUSn}m7f?HmlAuDZ?q3GDLvc>?erw(W^| zCAq}5Z*iR@FQ|`3yQHi$UgXSR%tz*h?-R30o6!c}=V_DD51xF_N79At2hUw?QpBs+ zmmLj$MEiyRg5Oe?@%)7RgpH~8GdKhFW|+%QwWv!!KOwfXpCw@D+l+m|_<zz?e)Hrf zte>#hC&M+>ejgZf1AFVRZpmtpJHcnk2KwyjANd|po9s{O1uuZlkps7YU40P$B<Gmz zvmh}2qrOdEiuN*><gJyh%q96$>M}O`hLDcu4#uAx*OPIIKa;~3GS0-vvlOwZ_d|@Q zKpaCiGM*F_$ugc4xVGpro)n?9m+_=nMi&31aJeb|N%4*LGKQ4#XoK%KwJA%IWeh2s zDC-zf_M|RjNV!5;$AEW-dR-Yq%41|1L(1E<mocP@rK~<rm7gp=Pt~0EGKN&WX^-zs zwW*f-bgY^91mB@*Q@sw;Q%7|A@5ZKPpSsqmtI$Ti8!~ktpFL}rt$_Yg@Av8SxqRm; z9%Zr57yp3ibFb$%aBAvPZi3yl<V=;ODD^gd!F9-Tc1qKbym}^>YvBc_0*|LI=aw|T zDSJt9{WSEaJ_AWZe|qWBN17wFncD??l6*Hj_@1&^yb1h-oadskY2kN?0XYw(jjC)T zz)xv$ZPDdCkT#>T7ae|1Tbwphm(m83<Ngljy4zUD&9tyXTW=leZCb2>^pm_M*zLJ> z(Jt*G+PuOw)4JFwk9bIXf_>uq=xkd0S-y|XrprKk+3(W1c#!=r9pl+kW<Ajwo~{kA zdvzad`m;~j@6rurKWU$Vapu6-v{t8^PaazdI>zyT9rG6+a}@ezvefW&SXa?6768BZ z>7U6LPy^D(C(C}9KB=-vg7r`D;z9Pi^e!Gg!Ds0^(OzOH{Xk`nrS#Y*<XRF-=~2JH zdOlCTlAI+j^dq#9SW3@zw-<VV-CB>G0RB!JiKPsP3H0N&Mc!oK*ff?haNWI%xK;+t zO|F|}Ke(8(nUe>MwUIGMEM=(2eiFgY8M;!JSjymXbLt=9iPR;QGO$j14Kb$-?mQr| zlmUIowIZGeBW{ExmNNXM>@A82X3f`F%J7Lc!C1$P@n|Ell#z4svY_^4EJ7QJrHmEG z5=$B9DVyV1>x`&tGMD48z}(AB>}6oCHTex~B!4qvZN$C-e3K~-S<VcZ@c*EDQ%iue zD{EY3%1ds$6M9vjUYpzweP==(NS~{)*JbLW?9E949_j3Bfw6vK<JAFQq~05Gl<6Mr zW1IkUoL-V2IOoNuK6)6~t#3v2lNmKs`e}oh&774sEwHwkF(2r*F=}9Dx7Ib#XJ-1% z;QJYDW;gz?A>jJ#Cm6oZ%-r|3o(6YkpY4#}nfuVDRb8-);p)GDr&ACA0L;2=(@X)c zRo#}F3P#Myc(!BRGb8t8%-Q5x7zfx}_zsNr!VPnQztCnU;t{VARbLN(WMMp;8OWO~ z8EF&T6<ki)?nS(1L4L}$WR6)-Q{-CJ5R+NjkrQJ)Sq9N22689M2xV{DSMVI__|6KO zWih$HDeyOC`EEL!H8xq|CoAK`_Cma6%|ji3=V-GQW?T7vt*n))OI&5Gq3p%Q+_Sc! zjnuKM9cj~cEExaDnD0LYFQmPEUtm_mvCQk;H1HnU1dIY7q8{)9e9iF;@Lk%RLX62- zQ`+LY`)t<l%HC+t*ldg|eP*5wwMJ~3qyKDfF8FRbn~ihv`l5zpL(Iw8@ZEGaTLaq9 z9S2@TmS;!VP&=d_<*Q_Qj+E^^S)LbV`%F&%!Px8^gFZ*f&e%4WG5+kx2kA$iBV{kD ztiK;6&$6M*yJnj`h&%>4n!O)c?)|e5A&(mho~bPFnr(LYQQF?Xc(d<R*5^ps_mf+_ zGd4#GvOGJ=K|jd%ec2pbM}3ZzV*qVrj`&@`|Iasv^MlMchpXW--yA2^M!#<Z-=nSe zs=uV33-&o9Q<wSXL>rm=3;a804rQHh&V1B!!cRG?Q<wSX#2Uli^y&)^A<KMocA-rw z#9q$v$~xbizmeM`_H(`^%N%n>@G<?M^UYO{x;!__)s~F+$Tn9eWp6=C@Nl1wn2_=J z6CJff#wO3ra;+dYUI}(_g7?cd*HP8ICq2No*!JQpFvf(oUMIw0F6<xD58f}^+~KLm z!F6)Gnt=DqHg`tqRbijI4DIoL+2*c9eKy9QyP2}QN4B{+7gORGc%V;*U*uYyqC=lc z9iI=kxtAz=31kereELE1fU(eB4&pts&3%`8MZ{I^Ph{19D4U<Y7>nPpl55F(WSb{B zxdzrPk6UZi8UJ<)`p0)zsJ*;L&Qo96yY@SnYhhLINt@j0HxJic-{<B*?UQ-+jRqZS z0M_@pc{Y$E)`kvW$av)aavryL<GaLd9<BxT7qqznf96FUkv`@9a^5J^H(~Aaru69< zl)WAOp%<er@0atsHM&><?B*ixyYn`secjt&#Dw%O@0aoU3?19w$HB}y>R3yei^NOb zb!2(JoOdhvd}r_}pMH_tCj|O4W%=B=&HGl_q@HGMzC>hsznqV`pr5767f5?~znrhK zvX`y}xHawN{c^qz)U&PtPoOUEm-C@tnM?a~;5Ewn9y#A;+Bew+{kl)TNBi-WjLpyb zpzo3M$D+-i643M0M&2*ycfLK828{X0wdDPBe#QgYjX`z#O5ZQ%|C9EzujM~a?kRn; zM#<+PZT=6cdoQ;eTOg{kJ`*m0wUleU><XPZNIeJb6Bmc>eANtNE6|2*zx)bDOvu{F zGvNZm$WKmyXZ!Sp$|im`=%|l!EqO0i0CN-GJ{Ww-r{5qCsR{j^vYv+vd{*|xg)_FG z^P!xd3nrw#4C5?_Ysh${t`^LzY$A67S0u|b#)8#p^Ee6Et-HKmF35Galh=Yr(O%v! z7o12wiuf$Jk}U6+3o`G_0o0Fz^tqMy%LT8p|3Jh;L5^9Ug%&bwn;t$Z<l<AFg%(Po zx;=sM7IN{Rx{HU+7+0aXY^yrjh~N74fZp4u4^sB#&xJn6r!OY&+X#IhZRGuOp`+w% z@IxUtW_e#$2>*x=XCa>oeI<)t*i*JS?}3vm>-*)x>Bu!v^9q+F%lopz<!B!hYgjnQ zr@Q#U_wm}oLue!KmkW=k&DTQUB|d!>^^OgpbIkf)tng{tOwR@VDOui^6@H`awMP6G zL405?`hK}cTxIiZH+007=<<HKNHgm4ez^$ZKzu8CR0MWn(**HS<O+4!2aBMtiOs+0 zqsZU1k$b%&-^iK&#dB?5OY^8G{44#8PYb<(vKMUym}BtDBae!<r7n3?v=e#k05IYV zZ8g7&j#IW@B0^uJta(%veTmJGQ_#7-)ZO|9$aQbBt-KQ{`hfNZeHZ;gUGk_H#whdZ zpB#+&OP`WQ#TcI^;0)O9YjU4htSH+)%L&HXNZY=lV9Y`IW*zVh+Q>VCV)Ll)`2^nK z)Ay7A$pif^Z6wZ%JyG@sqIMPg5vCW%{AFx)u>QqU`}9o8wh7|Dcp!DjcX=-^<EfP! z%(d2c3dNnzqr<Po`>?Il$>LaJu`iSu?8Yzemy2`!b{2eCe6!l<=P`=!qJ1X#q4;H= zevA5E#Aor(WO=__!jLB~1S4+bT9Pj%(kR;%H^9YxI_F|5*Mr`KHj*zT&_?`lts;1k zPany)e@ubSIMIA5;o>CI3+RVwFZoj9B>4p9R}%A-KIPd?NsdjQ=aj_UM3-kfB`YZF zvz?Mv*>(V8p=1lP+!K{-NBh&LAteV=m*?;$5p(Fr&h7yI-KWDBq7TD(O714hvz?L$ z$tMvrC9nGQ+fIjXOS%}AXFCD(t*w&*?0hTFb^=_S1V#b}X<JX;Wdw9oHu5ebpg&pO zQv^)*F=AKdF7GS?PAKa;ivTwUd4Cb$)>rNmOSv(WX#z(6$h^cSrI1(B&nU!csl3$1 zC#8yzTTKI_)`-38b;&Jp-BMl1;*(On$m=$MC-`)<m$vH=N2S)2B~MFjBY#3YD0P7> z?<`7PQ}&jGf?3D(okgi{)L+~;wlwR2O;r$_LUkjbl_*`9EblBz2arR$gBy_Loki(p z$~M){;FZc=FR{Tm#1G=n(pP9BJ}iyglkp3eiKMJCRwgES60TV$9c{#)WwKIFh?-QU z6m{`i8OEnwi?Nky?9*G4*CJoaxR?}wmKj0)-97Levg(Kr8PB^C(D#zXpJk3Hdne(K zGIyzqKg&EJ??nIj&M#@J{tS#t`!bE7r>BkhGZ5DnKjg(c0?Rvlj5*NdRQ82n)+qT- z9vjGg!8Sl#1a4<r@n;~`N%|2k8%J56*Og67y#o3!>*7tG<CSH+naYR2ZD=F8P_~D% z=0e$FWXXlHGktuR_EI0pUZOq@`BnC57?<;WjP+1Iz(3_uD|_)#m&#%O&^0g06{k(R zjnHdSmvt;xpZ0r>fjjziH%{62%1xp!>s4-sve_^8Ykc}<>U*(n<<3%<T2byY`9mr& z<|E^jT2byZ^<mMBEe|^xr}(YB8{7OrVAQYw>+rj@y|fxS{t<m_UodNhsrmqXRdw$? z{9T^D^5m>h9{s{zxk5s=E%F2JOOh#@$nZmjJmjc1!G*}tQ1>cS^Xaw8iFQKA9Apd< zlNCBsAC(<Emb%1Vg~`;<>;`kp8mkqs1~QifXjkDhS#rF>MRI-ktio%b{<pFXDQ0ZN z{K{HaE0&>+)YXbL$P!BxTlx5Ra=d?_?@-p7Q1MS?tpgSB`1lL$rN&mm{KRkB&|jrQ zw2_)n$<?T0$dyX&tRk^gsVMD#hMy|^LVMNgQLi!@dRNyEVyRMZ>NC%QC;Ig1)Mvn- zl{Qe9nowywdB=G$eWm`dbe;AS!b8VA#kcZaxDwahbnS!ZddyR;v6WNOekl5^?DACn zU%3?fum1+zko`zasN9_PN3wutlBKRzMs7$9NG+|r*T;-Qt*e#kTW|k(*l=u`kCiz# z{k%_=cx)@as*;rbcfgpdApWF()e%p!7VTF;=UVH#^(ytL%Xg_(arrBGTBQed`QF(o zlh}{=unP0ndyBbNVH~OttL&hCrk>C*DXR~w++f>Q$lod-$r9UDzSBM_>hRA=oIQN_ zGwfuXZ{~oDQWqcojB7(TYv+S|k?$V`V?JWPs}}e@Sw3@DH3n@;B?8kwCT@FhPM-~~ zEqzWxTve?`y<!w_Tk5wECspYa6K)@P3iZQj!C%R1LX55E`d3EGNuSqtL9eQ8N7e-+ zre&Pzux{15lOqoT_ocnX_^Vx~-l{U#%|*C6=i<e~SgJRry<Dq$sE;R;<+{~3D(iKt zyLFkE8u~TWJ-Kf6yR^ZdYS~``sLQo}ak-}4g}Pk#mxJVKPr+x&s}WznxPAiif<LKl zg=<9faXMua*aCW4>Ww;q@!#UBoTv{q=m)Rz67W>oWQ5;pJW%%Jx;5UC<+?RJ+Q_wP zGJf>BH4(e$lgw-Bb!)PwS-Eb_VQQn-t%*33b&>1V+`_hU-C7Z;%XMqTBg=JbrKgQt zw^lJ9Gk)~CwUA3PFPU$xQM8fk)>=kg=35K#^xt)BU8Rj&w{|A#a^2eb$#UJ=<!B?< zt=-7S==Z<**5<YJy0u+xk?Ynzt~NT~+FUQ4Z|yH^E7z@4QCa<5rw&=JTc<T`<hphG z``Fb4)p;$wZk<1ABiEI`!4N;leCu+(^tyF_qK#a)Zm_am7r&#UK9TFzMNa-Vueu9- zyvfI>l=ZrGUs0Fq)?>ctb?b4x^t$y*&_=FX&&Am4Ea0W8dqcN@cl-FPkFg#y7g^K# zQOUcmfL*+0$N?Urx|Kfb{}$G^{z@P3@$qG4_Q~8a(&w*9RkzaTugpR1^VgwaZGWBZ z<261;P5f`1zdj*LpA9%>?Xy9U>e^=mm*X<`28<u|LxbPL`fRW{tj`92`TFFTwa<nw z{$=hBS);U{hCRdjX*k-)i^BSBcqpvThL4oB&qi*&q|Zjx!`e1tOltp)di(S#>_^t9 z5#vPt*@$D-J{u>e%@NGCaRFsJYyz0MY?8hQ*Q1^l>(IC{?c;_6Ggi%V<YME_w8?`1 z-`M4X)cMBKsjr<0-a<Z%c{jeqe)PJGRU_OadYIlMr;kUlZ79apWIkEO*@UrbN-PH- zpf2NVa*SNK4A@;u#@U2>ig|Gl{FOE`&Zel5l3&Hkf>V*t{S7Wjmg_ckeo*e=(=j(` zt2)=qjK_7F{-7@742nRGh;as`Cd)X3GAetChJ*7dt3QK^P`}U~`meN?aRxD#%#5{Q zoC74b6ChsXbCbey-Jq>Lc5_#q@u@b=Fi+TfPqBwIWBnwDs;)86tUvn+LLN7pMP0_+ zjQ%%!j)PazMts|Bqq5f#YlYt-Q=iC~o4I=a<u%xiVJgPoJQ3|>49(qqm7Do=`0l@P zHs`#&HCUhKt}exS1Ln27s&T-)mU#r<w@9IF^|zi{Ft*9RsIGHtf$>TI6|fF1x>A=p zw&+F9gY{~GwGrRS99xVfzuf~~MH`u8iw)GDW4~%~j(iny-2&s2w(CzC+cKt)bNjfy zkGb#Ld&yuwnEH(3U|dhenICnu<$dY}4}clNMz~c%)pcI2&|a<^I0bqk>N2lZC8*y) zO^`FqfAeZZpP2G5pm(Od%&S#T@|Eu3Y2@q3i&mT2R<C;{j9VKYXZLY!a?Do7wr-$o zx9$WlrM?q!-I{YW$}VOkcUs@3edmQ>&ezIZ+PIu;-3;t}D{IsyKJ9Bn1~aGh?AL}d zW;a}dPM_Pei@}U}y>1)Mk-R-@Y;Ep_vHZ=U`ZmDWw$6uv!k8O$^?%zC+SH!}eI#`m zbKCLMOC|!(Cd-)HE>QNaYy$76z4*WFQQCym0Y9Qm-x<cXV?8l)-F9hdql~`(8(X^$ zKHf*ZiFI!0)=T-l>N@6jpUJJF;_vzrkY&ulKe26vBw)n1^e<x$&OzRUwGFOHdl_?Z zE$Z^lTs|u!_J^K<CzIv6!Rvf{!N*)*BQ_x^sLOdNB%QKXG9nnUi$1+OkHO3rGW-Hv z=Mpl{wLJry9n@tmA<nny;cxtY-v8$kf|!tT{yP!+-?W#xgnT3K##*&^ekg<g-@d5o zdfoQF`nbQ3|M2mj%9_{h&nuhp?~Lt$IFPwSP6>8<af%+`%(Th*1YC$VUAuwHlMgNh zBPL|NxBmgRB+GYXc7UDCC1YbSYPWJ>@Ko9i7yxG7w#shq6+c1$KpUBRhcD!yaK?7T z_+*?95IY@FkL0>bQNufyQ8tYc;~j&@fy2P9X@4Ja+7bUPZ670_I*w7c8E%15Tcw|2 z`@!f7Y?@X8pQ3#$#C1o;hL^QE_$}=l%NRbA&qD8%fNghSJv+HIYW4$+IZK~k_kc^1 zb8iMWV%xE(*`1n`O)z+nvX=<4*=YnhxFdLpve}7T>$H;g7ts#ii=pGsgMW8AOFq=Z z*v`xg`xXAj_i>AjmuMRpG5vpTOU8Ey+s^PEbbB%*cs%vtSd-55kNIsXnEtV+*Mkq! zUe>6yi>vX%Z`k$%#@i((ZDftQ#HT)|9XOA&ku~a4h<eu4V8)WJQJ03)b6$krTUpnr z%Rsh`QWN@I+Q=GpK@FAhU&6n;U>_2eHR^JVHuVC*kCct9Q5Wnn;)nVvjO`kgx~x&x z*vhsmVz{gGp{!BYe6%TrHSAi0ZDozR)+0~&1V+xFPhF#~tO@omY`Y?FWjwM*T^G>i zEMlPRW3oIq=!#g8w!+;|<Amk8LAN5xx_5LdMGmM1JxE!f8+2<!`xB@E-O#VJEtd#< z+{gFG-7^^5J*Bd(H5AM_ddIPz-Ak)ZMqkoT;u6rClB*^L_oq$X1Yop>jb|=_7t!X( zOz=%|zJlOqw8;t|cmGVDxZBtsQIzf6G+?ZsTuYt{^~g;9cf>}IvOb&o%HA}@X^&pC zmuEyh22jtA@%NZTd-)s59`mVJ3<d9?y*xYWv5$K1zrgotKj|g-DQ#-+1%IVYYSfRO zST`A4a>PbYj8Ep9_XapQxnCJ@PGx%`9XLPjul@@zPYysV^!%B8r4_gd?d5ZcJzG+* zhq?A-Y}ltyz=$ne%a)4;KICKiR^y@P1GZh!8|VIT${G)$@U@IHLT%_6lk_8T8j62} zOI!xK>&8aRhIXU<D6DPh5M`4O;|-lm?vL0BT|^uCu8h!~K0ZgA0qKqH6_NV$#bCsT zjNwXju!}Ke#+a^kuX41xzaKWul<m4`V8*i@+6Bxpc!!3Akq_w8yz;<z$+shcT^`~4 z0Bvu~Pp&I#)Eoa#?4zUp^v3wW>bKrmslSW>y%KrPa_}hHTv-ZU;N#6cK27`H_;>GD z)UU%=y+4pww8!6m7f|*_wE$Q3G3Q9V5A}W9VB_k8^wWpe^=cvi`rK6;^L!cj9qk{* zG`6o>UuEX9r(9TVY=o<@;aZz@h}pi4*>-se@DlbZe@D~zfRC?}B?tR{A}7VT`jrl| z>BqR$zklf$8fM>bs?Ywm&;DB&_h&rly7$i$X5YUPc~C}U<#U9xUdq#zt^8fc0K}8% z)rx|#_Xsb}Z|p#f^*{T8d3}s|iXIU)V<3I2eGc5|vw0iFgW~u&nX(;;wHQ>$r@I;` zV;gkRrz2PY8^d76zg}x_W}oh2Oxg}cegD7xNFTd7sts!t`*C}#jA!rzpZ#lP9p{i3 zVfv87KAmx>{R}DP)7?7CwT86w>Avv{!TyJFvVY{ye`6kU#K-r1{4&gbX!tOFXe^)Z z@=mTR?`i()b7(UkyV|Zc%mp3)&_h0($6-7ywvT=D9oE68vrn%lVq_TVh+J3VXV^TS zjf-2k?r;;P4=?Ux#M6Ic9`1|V;eAxM+Zv(mN}tUEast$%;iqXc9(&aAuVFSLcKO&h zuMywF^pTl-T++w59>(Lz-!F_D<I@-Vc#n@Ch4H9dK5j|Qc*odLot3>@!C=-y_5UcB zcjBK>n9qNH7|mLwHltl$i_K{4EC09g#r9~%lE&5OKYccTDN|>yW1s(q>0^?F*^f!* z(*t~ZcOP#j%e=-MR@QlqO&Ml0HjA>Icnj~I3({sJ;$>_gZDO1U`{HwKd+I5WH)FBy z${Y{g2Qy!E%wtzj7eC1N4*chbu{XnbTwEXL@NrYJjCmYug^qcgZ!N~T8ZQ0I-@X6W z|F{c2W_{4{jQ7>0@yWw%#xt(e=i}XcrO)xz)P_3Z;J^OI5BBj)AMf=s*OAv{O;DcT ztA`WVKlOfLZ72BpoWPjTF-+L!vti6oe;TGwjOF8`%4#z)w@<I{V^;@cz7r?;?3ej$ zHv05)KArK;{=bCjlOlxKPfF|4xxQ*Ysftgp>$C6b(|vo^Bwx->dK+dx*;n%?qn7=* zMw3~K)VGs4N4@UkIX)Za0&ULv`g|N_GsWl6DOr7bX&(pq*qsN&pHn7Kml&SHxo8Ye z@x{rM6KbPl`^}e+zxitTZ;itG{~uH50^jx6{_*d=MMW4LtR$1l&|wk{JxmS_rBRq9 zE2(u*i^^285~h=(G?khTjKUCxun0pBA)50d%z4OT&d>Y0@6XTgeqR6o>v_LE&vjql z>%Q*$zV7S$-KxdK0sG#-#lQH4q`stkz=6#j++&IS+!5@<JI)XE$pHuV;2l0r_pCd< zPTDLDa=!H3Ko9c2G>BnoPzRQNle8~u7Vy!IQ=Xd}rIh&|CgnNKeVOi#c?)3e2g_}l zuahpfcOIJbb7#Ky^A3LQ^z|y`3fAz>#{=Ex&FRZpc-{OjlOOZH%;(ejUp6c`cG+0Z z=5v`pvnlqhW%mU7PRDW2Mt)~e=feKYljZw6J?ggu?&<BFeqx~a_j;TEU~_3;Gd{54 z9!;$2@+Sk{;_a<pTK<9O+2n8e&)&x7wfrB)ZeA<Wy>9z<MW3Y2ic<rdphm6md&BM9 z6?X??H#qisO`r$o_pYGk-*s@({w{r6uo&)Il^nZr?|{1m?C);(td%}jZhx*kFX?lo z*2r?ZQg@=|-2U7ec}sD+>aEis4)kaIvz-2|XNzrB^MJbr>~rN}ST!`zCkH&!vD+uB zltbG;tNe5QSbvwL>~S%=ud!Zd57}C`B{$^<C4H8k8St2ZXL+{x%O44JKQEWJ^6g3e z?x5D)9rQ(a4-agD9Nv9jpl@^>kN+V`xtr%D_T=54CiT@#llp4^EN8#^=s@oq*ay#D z?bp%U&kyYH2<)o@-Jff3|9PM{B<<G(`*4llht7UYP}|pBo*cWzua{ekHR}W2*Cnt2 znAF#{4p?W(_Rm^>mYx0DpqE&?Ca{0dv0J0Hza;f_QBq&$&qbWNHA-0*?89}zK3q33 z7<-K$`waj4x)+oBJ=)LKpWoBQ+gN{o&*;GBMz32<zUOxF&9G|D1=qtbdHvC2V1Hgx zIy?mb=KXwqa+GrK*`6&A_Xc;$y}nMmoZPE@ZZ;K5llB$6lYIa9fP);~ud{4p*JmYd zHXIsos0VxX0pd>V+Xsu1{7_*3(2zhc4EUyiZ*%PS(nGaLy>gF$eLN{ooW<{3_Yd^T z0w&jqcq+>S_VvN#s`8^iSDtO|54TV14+p)(!xsknRRP}{@V0=z4EXOPKXOjMK^`8N z;q>_CNBR41ZgQORVlI5Ux8IjK@rbYO@u8Q%F9&|!@_Y;D;}Plzb9ejakw3g{`^WZH zA}5dfy_916`B880a<Z|RA8Y!?^-24UZw4I9<uPA#+}OtkCv6@Z7x3(W%K~P9C*pa` z?|<*dKPzP|F+BEt(&q8XfIkWNpCmugHsC=4>rR=wAxe3|=hi*z$;nBZCucf#d+$lz zFZOeXC)Wiwp9Sn=b9LsaV1GW9>TKN4m7eOAw0|luU|)M(3{O1}=)U*x`UipjQ<9%P zJm8Z8_IH`f+tWe)*_4sA*%a*IO@6-aS(~)SZ2xbfCMMQplg_y1?U~>XdM3C-pXrmd ze<s)i&rAyR`2pV>@CyM4Yx<1#t;O@~fk~TZgFXCgu)fa*HSO7(0{b-qKNoP2+h>1G z>d&<bxM#rrytrIFHzv@p4|r9;PY0|V+FYLdIjL9g7w}O5_Ye58fP-^Xy};>i?^WL) z*gO{KZwLCvf&OPw-`p&zZ|)N4nSmbEtIZb$y80QL*XH6t5AG5Bv$Bc3wAtTTF6PZU zllt@iytv#xAJp3y{JVqGUl^RUe_?p?SuX@Jys$Q~@y~K&w*<Y`7HX))W8ZbR1p9nT zeRAxUf0F!SF!vV&`xgWI7rnjvyQg02njHJm(T?4GU&;yedjftqu&GJvFP8)y?5md_ z_xAR8OuhU`VDq)t?VY8D+MmdIO<K~v=9EAm5ZDKMtY%`MU*qkcr$?xn8%2+ix0Drd zP{V8d`Eqltc`ES#X~5rkpH@p>3HJOeSxK8$g5KbjDS;l;$yb6p`O1fZO>m}O-9M?n zni25H0c-zQfAy;BhTV^^`uw}T;<e^U``3cA`C1U?YZ`0&|FxjUcx}BKoAM;KuLX5% z>z-bp$+Nb$^8W3<-kR<>=ASr7*?N`N&F9wTp6z{eYlXM5Z>n2$#_ip9>+@cJlRRzp zHO<xkt-F(B|LgaIdsqGMzD`fEvHv~DbL}R0kY~Gd|634@_2<iv^}V7W`&?k-&xN;n z&--!yb!S=p|NY15&gS)&Nt@T(dA1l{@9#J=``3M*z5R&5UVG2k_<PygJQCP61b+T> z>}=lfYwF^EBPVI|M)0gR@{@kv@O#_E^G0Rh=b5C<HlI&dXSS(++B@U6)4YFM$8FxH z^P_*8-o>+Rdf?~T!2X?pfA==6XYzO3U7gh5^mW5M_syWzy}2{6`7w%`b7uKZ3cmyD znR@V+_QSZ&Fl#YiHgB~}+P~Fa+!~wX1N}dNer^=CNQ^ySjK8=1db!x%8Ylnk_qV1; z(OwDrSz@!FmyG$X+htE3eQQk=?VYf{SIk}URy9A5P3Zi)5spp&D2nz;=sU%|(La~Z z<KZ8IXEjRCi&EZh5=HxJ?Ay)6^gC~NNZP;6T2fbCt$Uk)S7X0~{fXj@*mJgBJ{Q2$ zV#m~jw=d+Ic*36damTF1+cPva9llPS1>d5v?2EUTN#|U?y;58bSBfXV{Ch1fp1E+f z#=Z%^5k;wq=e{i_S8snCMf)f81~K~f=1F~fOEGJ-Jw1vJkp1?~V$(B|`Poi>-F(UM z_A{fXRl<ItnDe*&qQHKnw@-=D`S)5{C+sJS&HmcJ{zloiLBEyX7f#qO5nDWW2ln^N zJ_G$RzWpTZpA?(_7X$m(Wq%_2dr@>?!k&HQ*zCUw?5S@y-;{IE|Kj&tWd9ET?U;Dp z*(YiLPFvY?KHfPrirOXYyNL1s&e4JW39_GpetHzOPuP=N$7X+iV9&kg;<*WZY!n@o zuqU^U&HkFeo_g-=m!U6=BL1#V`%lU{<kqppe^+2n-{S1Khu?Xa-)BkKlUv7Tzd5j{ zE;)Pl<2&y}QOATmxpi#zoXte9^3M0Ne;fU`C^{rzPi`F(|GO=c_U|4b`!CQBj-qtg zzk8?{|L=AW?2nWEZ|G-4(V+?Zv&3e9L153_Z1KmY^Y7VoO4wf|HvPK5zC`wipqE9_ zVF~*cVzaLZ?5W|-e=qdSQPeqM|DxFJIm3zky!*cFPe=bT(ET0f>e7z=qo|Ag>}Vs- ziBfj7(^zWV4(gbDF89ffqh&)a+HtIy`m=*Q)-~aW^Xr&+b_C~lht6-j1pP{WPcvaZ zO>Fk;u|)j*TTuSF<Y340D9T9KuM(TR@15M;v4eW*;(QvNI)6mMo`2)YvDt4A{C^~S z&hd`#qUgwk{f}a^|0`)<yQl1TMk%!i2YQBMm(N=M;+Ui4r?#)S0Q+o>-3@d8EzTy~ zakb>v)pqKl{jPap?zP2%&r<#lzl6`lVrp;ghCrvbI~!uIW$xV*_RQTeYgD^c&+QAp z8$9b1=@+AaC42KvPTW}L_a6Rw$me@|h?}GDpY-!yd-<7&-itr)m9RffycS(Gs>y8l zv|z06z9!}9iMuZco*YG)2|rWC%;i1mlFK3Y-Fwt8$E@djxAFHCCG77In>{tl*)+fv zo}2Cm(+9fz7r-w?QLn_<SH(7#{b6I9c7i_?p8|gwMaLxUzY&`~_nEUF0<(V{Ulpai z&t2JD_V067I>!Eea_wxmuioz{UI%9=wi1{=JFz$3XaB%%zr8;^ijGbA94R)RqvfXx zo+91>(?>ab_R0Hm#60KyC1PTE|IR>vLY#*FbfEisl5#(5`2OEMp8L;?Qa)hMAE$Ue z$o8Dl4IMi-$FE_<Z$H2LAkXW2P^UlOKC*e)&uBhiJ<NU&V*j8>%vygyj?AVl{muua z(!Ye+H)g*l@qfTQ?$)#deo0&nb1%Et7Qj2j`1s&^+0;fUAMPP;gsFSxCnXK0{=2dH zF!kT@On9QW5~ij(eG|M$W3ym-(LVUGyYj>J;wtzd#XJap(#^}&u@9e@J`tTW>te`- z*>A@u{IK5~m!WIF*}paP;crPlAI0)Rjr^#k{1m~5N6`uL^ARtRj)~`^p0eK#A0PPX zC;eyi0rFE0kB*`f6Mn{tiRUBYwzX(RZTN`iCHCz{v!!REQ`_CVYT$KI)HmVhKC#6^ z-{AaQ1V0h@sg{oKkLVekp9c6-&v6<|5AYxP{FwiCT*l8JSzqV#4tT$$&yN}7^vBRU z$q#XUOuaJyaUOhr6rGgtd6BpZ{SuA+7#<V&ER;?S_;|YfpnZIs*y4F0icU`Wd{}Hc zaacUfdFTH4xxgp+ayoI@?-sk*Dq+r*<68b)1ob&vK0j$8CeBax(b&u21Cu^KNtZqc z{Yd#~fctrFk_KPG?@A|pjt~>)Czoq1`{9#GfzKl8#Qq6>Ew(0^Fm>2*9{gAo^-K7C zQe1`pjK<c(F9$xidA&t5^!Meb5Z)a{rzZR~iY>N3W#1)AsoOK@r;c^E9JZh))wPo! z?CXx<&yC4X9q((7iKmYK-q~LPpC0%*M>^-OE>C{gn|0KI(-VH^Z5*3__JH$4eX67O zCC)|NLg}xdFO?tWUdMhoBjJZ!IktG7l>JZe3xS`lUf+vzSI7Nsd2X5t^S;(U;fGu~ zws;z4&$-_jC;jZ)TRQXG*+zb{;GR*GBR@OIm1E-B*+=$Q!>0s(&XUeq+sR$%;>m}p znP(>akSoW;vvZp4H^Rk%pPQxA=kL5-eoA1@&RGdR<jS$dqqDOY>%TKNJ3DoD_U26O z)Y)lT3G;4ycES(2a%}PJ_Rrm$TDa5Sajrgp%Ko!;+&eEy`IKC{dDX(bk}-e!AII*F z{&Zjz4Uqp&&lTI)^W}%S_$g=7`Q#jZN`3|=?8%SgEOg~(Z|=cQ*+0(yBlwmmIwxU& zyV(4*mz+%lyv}n=_Wq~zih~mNd<SrB{;Oou9p>J&u`Q|hpVkKR`Yf2&&ry_{@bjzK zp8JQ!UK*u*#=Y+R%z|6_Tv47<KI0BLS7Sfp4suKkpRpI6{R)^II({1Nud(Uy$Yea9 zaV9xOF3+D`8%5_Oe9jgV&u2Ht&+9Pz$NBsYzDqvsx$K|8iLsnD$ENG7+23Dnf6s`G z-G>_a*_#?`{=W_4`865Ou4Yj*L_T-zEyjMA>d!vRZ`Z-{ISf8rKB;ND_(pVoV(iIc z;@Neo?5QQY&K2JYU#zjEF#9A?TXwOx68YJ6YZP6O@VP{6@i5-aYXf|*_%-;ED7r9V z|G3y<cuF>3!8%j>HixOn|33Hg;JLp<QC`B&Z(@7yU*6BYoX5{qbM`#}ZW~1x$^LV` zD>~-6pLdi!V?XaErsjNpQu4X{d%FM5_jB&(p$R|SUyg0;2#uWwPZHk;^S$xnggt$- zV|y<5m*r<)*8g+z>-Y<Jb@1E=g6BRHMZ*$)HjC}KFKX;>FtyD5?3V_A97UHT>^~LT zb9sidISy7W+K-y?MR1pWLH$Xr?-z$g(Qx_sqKla4esP5S6u^DNH^Ke*`^6LX^tX<A z?iZ@t`%yE#V7!ZA3w#-UP{MwUcnbP>+3bL)CUf!yXWotdAG+?llb(kcc|El?yfW~! zT3nBQk8G%^UsMJ@bskgM`(LQGJD;z}p7s3Vy}-{$p6%bl{bHwV7Q){IK9$>4_Wu{Z zd)<6~*;Mwg!mXp|GR^(VG%>mPvV&}h`Ah18&3FH1aBrQ*3OFZ<MkU4$5R>OGb7kKJ z9xgr&W}WO#*`o%Y8AX>T#ukh1x#ZJ5>q7W8G3WkE>ZTi82UF)qC&p6e9ouuOWWN}G zN&G0h&5zxa`uydtC>oO(TQ9cfQtRAv8TTc*a?Dw;r>GamzMh`bG0&>s$J^N7n^Dg> zH~RxR!QGSjuRlRQD=bDoJ&MLA{G2JyM<1xM$HLS)=Vu7adM9d5{dC9fE~uZET=)7# zV&+$`Tpch5E|;Gh;rliBG<cKP;{PD<PaPX?u{B4hjybM_RmTpXj()}3C*t`kRsO5c z+skJje2kd+el<XBHlxH1@J!Fm@bT51Q8Yo%{pv39F7&(QpMCw+`rx@6z1}K9e^!1n zV9uxQjb?=~&v49hzh*whe4a@8I$g|vf6X4YxpaI3K0cYlum9sYE<ry<&*}&d(%39` zgqZn$eU-QfzCnI=!#B%MOL&$1a3_9!zx2NFgW@T0wKyB*8<*80doTO?U5(9!zf0!f z>qf_JKYZisr0d_l=@97MqG%$1Y)!w(6qB28n7i$<RukcV;)Sr*t9dERnRR)qf+vgX z;hUmplKCW`-^>?R!?(!KX80~~9el4J+ae97zM0P!S@2eIKFqyPn27TWaSi&{-cRe+ zF!QyTTeH8ujWw1v`j-FA`K*8s7jJ{9HHp3YEo%q6Tzz|K6iwE%zNO|n-i|$I#`)*J zzopJQ=InfXoqY2AZ}0HDS31m{YR}y(8-7-P^5EyiMesX;PTh9TGX47~y3%5Z;Ge|g z*8Ytj_uPk~l<%5~>Fd7RSI;6>-%(H9bIaf?aWza0aXNm!!_Ii`RCsC>U8VVcca4}m z@ZGiEe;ac7-F)$(@Dh#1_jen_g)sM#^J&i|Uykj$Uy6C|_te2e&c7$-M9#nO7)4VQ z!}p!U`1ro7o_jvrTRa6m$@^?c{NMAx*|S;_&-Vr5JosAqF`g|hf)@umKX-7?HJ$gV zsTM;7(+@kgm><(~*|XojAf`rs|6e`J#!`=543+S&;@T+X2hO(X`{473L&O<y?<ksP z&uR|y&D=3L|A8}a>)XcoEYEHCgNJBrE=<4Se3rno#60(h+r{?Wdpz%J&wVkO^B+Em zqN@|n{mgSpXKYv_dv06$>mPm$>~+Vr9T}xGu;1*t`x1Y{!D8m#aGbaX9_)F)bXalj zmkk$7&x6UM`PmPxf$ys>o^3GSSB+Cz!><SWTY>(46cu4(d28TY7(08Ni?;au5h=09 zer%z6QD1*-rRSEx-NeNF<LRDL@%bb3wAfO~^N-x8jtgOGm*Wyxdp?z%|M-&PF+Z=0 zzlG_$T%4xwOzJ;zmJ+f3)FFzl(OiB?_iStN6aVklg0VmK2<-bvXRUrZMe&%;P|y3P z!B>e3;8JllTp_N5pAk30?|VKV9p0^Yw!wTyve+!QKkuE?f8H<9kBXw{ivMT6jTk%o zV|<(k?!nmqB;)`24C&18=UhEE3mz*b=AY+?iT7vL%yND}1N?;NR;ln-aR&UA7=OF@ zodg$84a~czW7c9f?@<5h)R}+vW20z>#ZTC~x!)bv!^CX)KahI4yT6Oy{f_HydTysr zK&J<@*jg39%6Y4Dm^$fni$VLm74h$8pUg}=i+$qQo<;3;K5cAm@T^azQ&V>{2lLsQ z_5DR>ur>4jg?rrTMKJrsF@Ao@Pv-m=&S0X({xU;7LkTw5iShl*^?KIN@U5QH4uF@- zCv*9Q+UWX?3YgmHcni$D9Gf5JW!$7Uta+tn!XL^fckC};$Y&kQ9&`50>6bsn?2Z4m zPsaa0?y^Mu|6{!p{{N?btVtR6TCcP#;Is9t1+eag){U^<*P2jA|2JNK3gKe0`I##w zw*QeMTbDHY;{S1{JAMTwzn14VsqiDRuY~zN;9}bbZx7=CB#8fq!2i#lo1TU}_l5J% zx&D<iW87{}n7Z$tl>r|r`v~UU)}Gar_5YQ32gmsN^&~NK|Fxg|kk4Op#nkp+RV&(L z!xLmb3@#MUgcl{_|COFTk^f)s3;b(8G;P5CVfh~cvtM2O#W4AD@#n!GXzT`<JIKY% zzWSA#<JkOYKkShO|0zE!qm;(I#LvLgBj>Xa?&`<x(HuTfOs*PplJPeVPR8F@ARGKQ zYVLcmR*m>_G4rm|$bIVgceq5);=db-!#$VvZ`A(ZV-)<De3G}ux5X3S9fAH^z<-I? zMk&7~*0&1oES-3M%kaEsF5Jz>)BZ5{1Tky-8|&@jsf813N)CU!LVn2KZ<FPRoc+c( zQp@w6P2t-EUGeW}Hcv|L3%}<5w`~qnV-t7QZ@ZKE{GIn)=aV>p-$(o{yuaeihYt~7 z2OlAy8Su$s_Tlg6X)HPX{Q~h~c#3!~TomZb0$wTJgiWP<=D{yYw|HLh+^hhmXS4Nf zUjeh;j$ej9*VrQX4{>Rf@&^r+&9NEz`QrdFYw`#0N>1+p_YQQ$-^^@=N*@AGkWZfb z$Gl`d|5%dD=O6dWo;d$_&~tOv>yJkiCo%p}?fD?nUzN`qxK7M}|DoE_j2!;KcWD>r zhA8FFHsTd<yFlk#>%TT9i??ILeP?^DZ6iF|>lV+S<HW`AM8(q`X8kOm2MvI4^kWZ9 zgL$6$IWQA`NMp&*pO1=9gWnYQhTjQv#oyd){*X>C|Jp}BbKs+r`TUDsG*PeqI$QR{ z`PU%NEm$x6w{TpX<6vr*<C|gbN*5>j|7*6`#x9m0a`;!7cnhqW-+UwdRG@ztaGm&D zY<`l@vMA+m`V-5!#q&4)m1EPX2`(Pi{O^OsZ^DObY!%FX=i=N3=V~nZ`Fn_X7<{F8 z06Z<w6@Lq}Ss{Hc{Gfc+!|bcXdH?&JWIq4?Jc<?)bCinBSDsUv!rv**A7IXo#ouAy zDCHmSGK({<Im}!fXTa<O$N4a|%y9{<``Z4k@_(q$rrWdr;cjyLAv{I?8TZc|F>CnG z0{J2Sf7W_#XU|pN*e(m!ebg=w#+UhQ$NK(5t=D|xh?up1;)wHNIx)l%=f!b7taa(I z1ZMBK`EG=dmCp)zptu^&*Vqa0DDeWAe$4qaoqo)*>9=ca9ej`H_RV2^8)=^jZ;PVR zL~PqVvlekwt9U+w>9t&Jf5Hv&lgCygFE;n~h44Y*GPsv`8+^LwgKUfFemRKerd%Q2 z{3PpGoRX|#amqUWE_ub4LeJosyrn$g<2l&;JS`pszbK!@@JC{cr$J-MPs(mF`H49% z&L?`jU!ZeG+Pn^`Lf1R#LF6z#)9W3`Va!_Grr2WE!r1Z_7bu=0c$#=A%>FQ+9f&zD z6X(F|#f9+m;tH7a;_PeTuRR}Z&;3h`pC;{-`>jbAzu)-t*Krf_&mOS9=Pz!;{RqeP z<i81L*mQoUJ#N}Eif*^~(fQf7<CH0IYsLH;+|k+Fx4yV3b;I_+!C%9i0ppHGz~sbn zf0*@kd?U=6v}d)w1EwB2op_qg6n_S*wjZ1aFV(!rLsM$Ii>){OsPqzes~^knq{dC( z6}N`9KMx_F)<;_24ld{KP-8BRS;sw&lF#jMPcgaOqhFw(5$M!4H+CB~R|Wdj;t$d1 z1^S{uUn|~)O@(LM8+*JapY`z9vdM+{7UAYg{`cHpOiuQsZv3k!V$MQ8COLM`)5NCd z1o~LdDH-VWa^@$cFFZZaX9fB_QM4Ev+YfuvKNzRf!PIkGyF*69RmuIZ=Vs|QpuZ)4 z68=p59sECMAK$zvikq<)%uhP=YL=#FrNJG<9pK(RKfGGU%~Ur!n$0D$Ay>^t$R-o! zOgW#NuV!~hXAd-cN}Lb>HyBHA;O004eOI7!I1+ku;<R<|Sj69{O09N!Ief6V0zOt; z10OGLfYs-8EQLqPkJ*!R=f`Y#FL3^=VfMU>pR?9n`@CZ<yhApPF#F`+vFsDayQ8=T zF(&jDdjvYkGd%@AE%^TFxDIBYFG08UZNWY_Zqgh+OEG)}4@s_Xi%YzIsM%cRb^a`B z+(LaCe-1isK`(CcAG#I3+51dk&$n3UIksofSKG6kzB<r1d5$(>Q!TE7KNge27N3eM zVR}&)zv=XHj?wqpFRAa<D$qF>3H!Y`7mn9rPc5?iACd}FiyUXb^k&W`2UdMPBpZI% z&#_ZCSa(gQe3-k&=H6*BtXh3Y9{ihp7DX}N#J$e}aBFcce0ZQ!m)vtrKSg89;33k9 zhu@D$`WYYSlLDRI%gu$H?7hgZSN~@4D(N+FrMMoh@nci6VCt%kO>Yi=u6ex;(}&p{ z4?BQg#ot3V8SoKe^3yU~evFm#l+)k~1N~yL>60~<T(z8=jG<+Tm>Sh`d7!Tfbn1_b zvk)8gVCg0B8=5bBuVtNV%Hc+FRTS@&h<_X0HHz+FUi>HKcTgP1o#7su?=Uzkc^39z zU0fb!qMs*z8XhbE<a3|do)0yj>%`=0AH{iS4$M7e@gG_Q|17SE;(hm$&mZ7)#b$bE zF>AVSUvVj%EoSfS%ieHvA?AIDi5I}s|9^Grzhl#{3G{0No%(5W?9AQ0?<0z>27V>5 zr<OWD`RH|lzAMmw*Vwu!-j7=3?9<>*;tuc$;!OA?ac`LV<MPu8U+%e+jZMT^4J*%` zvfyQk`5~BI-Nj!EtNwS&gFlv^LiiUwi+Sz$n|Ny!r_u|#IMGu%vyM&gs<9<7b>8X3 zkoq6-7C1N1IkV2j^hC~$`F`@Rf9j-hN+UXT(%AN1>b+646y`s1>Uz&9)W+0@{Jgpx z2-COIQ@MUDm0r>2+vPa)x5ZQ8UE<r}U&L?0yiX<ivHkb-de{A<c>e>%J>f$&-*T89 z($=C=6?~Rr>kFSFeH%PRV+X>VYm2ArG?+DVd_O#2_VqAxF`tJq$NgWD&j$Ea@oxB| zK;IeYziMn+6d$l}Qa^xiDK2m1^MEdaeng=2Ey8U0zxaSt#p&>9`D7m+aDzApt`HZ% z>d6l)hRL&wzYN|jKLg-KaefrH;x2a2LT}X~(2tIyG6JymZAJfJZ2eWM<CUu#_|)Y3 zwxU;eIs6h`ck$r|!McAB=Y6LYd1g&rf7NP%w?F(T^fh`GxoX9}a?j=5wR%qRSHj!G z_FVcOXOjzmE1lR{?=7Fd!P*;#k>}Q@dz;RwF!d)fwl(#~@ep+Grhj$%=YMtLv>bNM zz-F!Va=1cV0auHOt@Rdh1FU!L&e<^E3Y?$3C~iZ}oqufFw2)p1ck=OPbcaupUIME( z>&&y-Oby0T8=W8aVVebkUK;54dA9zl%>!a`)rQ)5r`ER(eWtPXS8eDGY#lSshCfNJ zZ<~7Q<IunNy7gCW=pUT@b5Yz@_rei9VEPC1X?;}NG|$#wwPm0Gt9K9d{+_MBYJ0Z0 z3LYyig|84-!m|Q>PM|Lf^p%1BMxehfUW*@kezz{wQG8%CF}XVM5ZUCwdcW?>dL7u; z&-V!45e_^<{5+g1{vVw0{d6Ip2ddBMk^$2vxSVs=4x~?ToC`k^=zLrISKlf>7Q-jf zjXw+Q{}<@LC-t=bG&Vnq)7ts<vi>UVNa;oJiQ+PNupevvRoaEptKdREuOp9zr;De+ zrLw7oH;Tzm+H3NY4J+r?U!~C-yLC7H3$f{c`mtTfRlEI?F|?yMcJ|cpc3lIV{^wtv z`eSR?H60t>#a)TN-B8V!z1L3tb64`*?t0l5z>2?XF-)Ik_tfEa@QaS^&)vuEcu%xD zh`*yCZl|;G<7H9Y{_rSThCTm@+aKjQWeeO>`FR$mPMS~q7SX<+biPfs&+)pQo%Vyh zeiZjw`%&Vt@HoX;22b%Z*f)^&*U9ECnEG$A9bO1C7dwMT(c`tJFS6&pc?Ep8^w(kT zXp1?8{nP#-aX$Q(nEbSVH_&x1x>iQ<L5C=w8u&CZxjN`FaU(q2^WmxRDscw<tT-F~ zOq>_R9rn_*TEg6qE;ed@2i@Z~uMQW>z6357m%|DFRq!*?x4|EX>*3!$XGBqau;R~1 zgE_OdXEHKj?emNr_-g6-@CtDetlli66yECNjM%paZxb(o-}P(p;5>Mza{ev+O<@0n zn7MasCI1z0x|sMob{99oCwM+09lpx1sqLkXypP+u^Y^#J9m@lKeV{+?*#6GCxZ{q% z=F`CD@1%YRcTmFTAzcIg=s+J7=>B}U7!Dang2`u#vM4@eqUXKI;UQNl5C6cdo$b$V z9pQPJ7dbzK_-!qYD1jdl*TAoe8({7ovpF&i{>S^@D>aJKn}{>v17*W=(~pr}2=@^a zTl$%@DTRl7-Qr9i>A5A(O{c$darTEfcaHgvlupiF43)6z#*y`~`mUo=;g`J4QCToO zq2+{k);N8q*zD<V&CgN9cIf`e=N{U|^S+$%L#fs7xwpXjhS}{wn6+?Y%i;dwI`|^b z-O^#bt9HwQZ;@`#y2tz9CmX(BoDb`4cB_KlmtGEkEGGU#8{~)hJ7u^%5WkI0r^}Q3 zp%XpEO6Fztu+sycn@|rsJ*>IxfYl3iZw~+DeRfZe;=`JX$=hLC$L_hX&O-MBm>$^t zr<gr`g5%Ecr5aldv)?Q~-OFL!x!sx9VN0dg!VfCWT`+g9^TXO5_PT5uVeTe3mp|dJ z1Dij^k-h#T_0BCd$6wLgdp|wWVBNDlvS8KB9(l0tsUAfzy|KmIqYPHeJ;-@yYPi!I zV9vF1Px99JWyQ7_=ALzN+E~RInf`rJ@6s%3-(~MWXJ0v=*-_l3kC@oHoGWI}bh$!Y z0qe~6tb<p3Ju?kfZOqJqw@GL1x_l#M?YgR`%EV7s)!|I$)m6R6(fH{)$j8=X7)&2x z^J+p2T}Syn#@{Oycb(*aS3Dj9Pxt%qvEA?uQ4{;N$baIl^u4PRyx4P-BJ?u9M&0*< z?-w5lZ}f2<oe6Id+jBn>SHi!GYohq@)?)H-xN_Kw=N|qaulHguhYu8I!_*VYb1(96 zxN1nRVtBdqYM9=`+0?>si5uV_JRg%4#Tm-sF?nzY&C57FImZm@p3S|9>C`>PMeqR6 zQ5BpkpUg3XJH?)R4C|7i^*x4oGU%CYYznm~Lu-9ZE&QCf?;XKA#2GN}0_LZ8HvEs6 z`5v*4@=Wh^gwA#EGPs9q$n6pR^sF@a3~?T;zM^*xJVW+%@NMEo_}=8aj-a=3>%IxS z+S?qP3M<ZIiSvlBq~}EOkxb8GK9)Qjsk``CVmmU!`-!{3-NfAWN1hz$)FOLUY<f@w zkGv5L-D>!e^E~fY3olY0Zi3l|)|=Tqex!P{?)Sj=dYwOe5+A9W+5LU^X~kI$zbR(! zN77?h{KsX%zln>Y_$X?T)2m?4n%yHkn!vnsS#0|e^HIEWInIMm7w5ufiaB3Ljq$wi zMtHo~d|oI2jj-;QKIHi*?dLw^`KX8Grwo2fyanDI=r0C3_j@8INB!*B^%dQk%ceGp zyS4PZKkM5qRr5L&?kLWNxtnb6eT+{M=fkRLeTrdfh|QgEW^uQx#Od%7*%Na&)!ROm zuzJfr?89!n7d!tAFmW1ZrA09{#rvE9)5kjh3*b(&VZU`hNjm*lclNxqp>}oGU654- zbAKiB(EZwE9=hM=?QQPe@9^AeF}zH3=Y63&eTZA@68I54m$`JW5pRR*#EtOZo{vwD z;vVWf4(JTG^ZpNDpY+iEdwf2eBl}W#sJH^2Ag+ezC*$wI{l#3|I`&ZSVKMi(-}`UF zTzWjHm>-5WiHWm^`l#b;Vf73rWWYc9XPr<O#Xa{DGsm7<_Y;VrC+F01+qxypId$9( zzR=sBm<p3;Te}mpVcoeW=E1siPc;7<G?sk!tQ1$m&ugsdJG^dl>G^@@16lW;pJ*<8 zgX;O6=bmZsuNq6<GO3L&h8j3sTn}rXv|(>#YM-=i3Ud#deP14v$=&A|pP389nebXM zbIDYkeT(7ud~9uVVfCeLnPcXUvS(gL?;{&y^`&iV;lpH82WNR3o8!?I2=TNlhqE=u zQ{Z#N`EZ^e%ctk~=!s%tI9fUXPZ_NDtp8NQPsxTn9Q`JP@Sn!qkA6qY{ybVW{G_ZX z?$y-WpHu+16&J(W4=3Tjm-3lry7HM;0qfkI#C&@N=dM?9?t1Cm*&KW6+#R$F*179> zGhCthnopg(leWP%il+ho!1Kwe@Na%D?Z|Dfzr@V<7;3ex>B$-JvEm%~Y;iuUJMrWa zc(!!nKc>w4Y2O=OAszx(%EtV^<~chJ{z#k&tH;RZS-trtX*q9?&)zM>#M%2G+2_NV zUbj5-wnhN^j;-M=<>5{E3~>Xjej~dWRxgxY4qqdm)$mg9r$YyLxtKHCTeUaaVt8Bj zjj;B>DXIM1z|<Ja+bLPFa(GHUe4P9g!6%5zVD_i8Hy$glfoF*8;DzEwc#Xz#9*?Ep zu=yTLoX0-tZTeXZ+zW}ieH=0T%k&RTvFFcg#K&<T{i~nj{aD_PJJ0iBi{T4=-ZI<4 z`GGxgT5Zof9(|J6txq_P96Ft!B^`IYd=lGnHz~GE_%3lN{G7NFR$tU_8~nBO2KX=U z^XUDexDW3RHs4Of*@t%r#~JWp;&k|MF=w-ndWnwtuzHD(qu_jR(~;QvsE(bQ3QzOT zJ+%N<O*pk2E|pGfeeMyn7JXD7PP4IFy?$CQ{HeGY{zF_D#aXTVbM0ruSqDn5fz=zF zZu)s%KRq2L=a$c-`SzYQE*Lve+!9?qUOF*n&68dM)4$oiIz10oo=-1?-<4hhe<Lo3 zb^o4T6~)IV;@k==&eONSy=Bkbk00RqjC5Fa;EXJ|NP0fZ{cACtQ3RKZOJVKRGt8&r zIintK@HYLK#tFKQ`scu1q!++CJBLkyRZDHJo^URMc$U-87n`nrpnowuM}BJH<(_j= z;YYmvA!YF6;uY|#Vq!kwb+P&UGSI(C>L==*D2F_p*iQcQ;7oBbe5$wt&hujroe2*U z<NrkUgicpac&O>B13BdFM4h9YdiXx?)3*4DTI(~@VAa?&EuL?a=l7&(ssq@ZG}}Md za(L1Wo-_KwH*4=*4KEchh40q0nAb@UiA&(8#g(w$3(jnSzx4W9=}}B8<o3f^xp10) zR+rvz2k8Z{@^cpXIr&2A)iCch?kwC7D?e_m^3#Pmo;+VZnajzyh_}NV<fjqd;`!`U z_ychUti5-3b`)nfk<J{spWMFc!q{xZd3GUuyll!~_48*}!v)f7;cGn)z(uxd$bd9> zo%BrjS+V(4JOjvQ_Ak=Qqxh5q#P#rzo(DFE)mvsXg-`Wy+S;9Rf!Oq+fj(Jd)6rFv z2NuBP(ktO7ynW{_@YCWN_zm$U_-%1D{B58&B=vqR<&!-0>nLu7)k~a{4(E9NoE-R) z$mO|f1w2Ar4Nno9UL>xD7ilbc>sKx=gB8E!p`YUKRtIw~-2T}O|JQS`*6<FEW$yhx z7uUh+MF%yH;!}052NCC~2YZ`AMeuQAVmnoL=n>5KRMqf7)i8IW)xg{c*7?m%gQ-6j zPcPoPPhH3V2)nWOi9bZ&?D@zn_(icjSNBV9F8sUv7x4POzqlCgDlUVyS96);X^Qj6 z6|myWt%146U7QWD_QtuydD=>^pPLCkD$avn5*NbSx966?yQSmvbj5RS9ekAZMp)~9 zUN)TX_4D%KsgcV=w+i?gaUHxM&`SgTUX3ln<{5D{tUG0JbND-Ne?$TNqj*9TpRtEH zA8sM0H#nnHpmz=Qe%}9J@^FTF^})IDc<ID&#w>9;e7hfe)Bsrh<Wc5d@0(74P&THk zE)6DcXC&fpfXQc~PwU^u+uMHbf1>AJjO~B2_R?hd%)p-Yb$jeqbl!c;kM(K&M|%C3 zX7B|0tcMGI{6olF{~N{Rt$&5M1g;iW!0LgA)WBcJ=NMRZAafVI+xyRC-E&%snHTr2 zTkA~DV@?mx-N|iEFL7^}x!9f@QV(D3`TT5nteBkVOcfJPj{1%Bx52BV+t`OaUyuR6 zEY5@L#3gW}e{PRj_)qEOQGDiM;ySpGn7N#Jy5`I8?w&a)IrhxKV$ScG<30Dxf+vZK z;04~#h0OQNwc;H3X>mThO>Fj`iA!O{*^~2orsBM?B8tyazi}aRKkI1O6X#hvYk8^g zC0@@Xp0l*pdAaZn(hFdn_dN5dc=D=Y-YIM?@@nCqJYSR^#b@ig$3@xjA(30tUZ=t8 z$!&k0eO#cce{=e|@{@<n7;!mVEUt%jc6t!o*~`5jzVXCoKP1kF9~IlPwg&pPK&St) z_=l2*v;P)nM)80)VqzGOAufjPBLViAoZkVbi19yQNTBBh`jr|>-Ug`899j+Qo*GKt z257B^Ho%qM{$k=8@MiMN4*1Zq`%X20Z+eNdKalstfBB-M&A_oyw1GJJPdxAn@h*6> z_U9Y$b>i<~`Z~+Q#ms%+JznqK2~Nb53)je|5Z*2>g};!0ax(C1@sKD!Cl>dG_mq7l z%zkjO8M7Z8Z-uE{|LXKG|LViVtnWD^#U(Ij$Jv;ERiNK0o`Sw4(4S4_YS2ef^nmg+ zXs72U*-<=*yWVPJZ)5W8I3NB?yf}(;)dyb8+U4>-;%xYx-rNH<$40of=V6&JHNkQ_ z3_rQ*U5AmkT-M0NPzYZkn`)T%HPd6$7l{|Z_XIlkg|jjJMUCZL<g!ofS=Kh?ekD$e z;&b=*_R&muKk3AFZn}^E*puLH(sSXy-rjy!<lJm=4Xkfvmk`^zs<D@_7U$lkvE{Jh zOxX%6&J^n2xi83%=`V{-|H`xdOz>RpWtWq(C_az7*fBAm*FyfQ;I@kSTDX(+T9`Y+ z<)jX#wm4?bpQmprY@_%*-OIzt$$2Gy>~QjM-U`{1!}H3;yWuAT{h2`j#Ixn|Jk{ah zIWYIK?T2Guj$%r_TZ`f3YB2Yji)SO;TFhJqE9b+@;4@`k36B<&^TE?)zX_ftHk}&i ze40)TbZolfwAco3mLGC5_$?pXar?s`d;L;!GWdHx)_(3b_$M(whwLTB&yam(pAH`) zKe@2_w@b5N&acIgG8g9jIxc~==P%8Jr^pXE8FH)GZ0L2JJ^OjcePVJl<oQ5<DbVXZ zN9@lb--?<0`Ax;de13EJFNdk;wl2plgAbKn4IeF^#CHC%;$iSW+0?<~#Er0e;QUlr zIZw%lS8417xJqpLra=GLbF>ZpQ}K5Acd^B+J19RRiZ9q(F|&s+P;JT2fe)9@Ztzj! zO!!nEXMO>kFTFQBN}LVP4)hxWotkfTBfkWj=foB8c5f4X2-k|q$psB!V!nVq@5a_d z@r8Wnv^@9e0aF{Dj{SvtKguVE7oOnt5oxgY#t7oSP-k;Q4m?*j<nY2oJ!uXn>PbuZ zCD|0gI)fuhqnPX0J$D50=jp69=>Vtsn44t4T6d>w-JO1+Y+7S;v6wjXCTqSM;HlzD zc)qwCzD2wizE{jy$XhR704Hi-1DvRVyWuaAcT?Vv$$R`Fa`_<t&wt{JsE3ZTVd|mF z^PMnz!*La?y*;8D?wj;^(EuFa$NH;_ay|DcfQM)-e@^Nm_5XdofhQ=3b?_|DBgw-> zrQ%$8jkpAUK6ut!f&X_s_nm;v`~F#3<o2R^G5hl(^^GHme`r(rBtJu`^R|C3W4(qR zA<l<$lFu5-V%xmT|IlHcPbq}+<^K|RqL}+)sJ=s9RtnFP&l-4zXO2odRNt>gWx=lp z&*J>rvz&j<ukjgEuwm^i|5^Nee5mSw)=RL?@+k65Kj-E$svOpxHL4aq*6Ww2!mLH2 zm%G>kk^hSeJfB^J4eR2b^#eTJ^YMHGzgXwx@@)7H`84|qaV4z2{qlO4wcuIy?}Eh_ zf9ZJ-{(S4Ovyw3kJKyX4n_uy;(a9Kwjq`j#Uv%a6cycw2+$Q25He0dfp;PBA=Hq9> zOTCS~Zw|X#I^XVwaYk&u1Jhvj@B_QSPx$ypn@*qO{LpI+d(GS1H?d)Fh`)uo7tD{- zxfdKSh~i6{h&RE_<TD4R|8zE{A1<zj^*%Dd^pgTzeg1$g=-PV&YTyF-%!g;ozB5dX zb^e*lCEOQ|P3OM&SAQhX9}je$qk$W+*Eymek1x@@oK77!Kc)}Y98DkIEYLN_f#0HQ zjsyRMPnC`7{lyLN&_Ev^=u<qO(;S;3G3zpXaiEupTcT@CoxRrd9MjdWjxK`VQQk`7 zPyF6k%%9mGPVa4Je>C&Dw1xLMXaT&BxC-tZ=ox{2hIj=wX9fCraX$JavH4t}ef1-J zM_{uou+bU~D#S)>G-xKQeRzH&tbKSvI;{F|0WL26!uv5jzp0oU<~I-Yu9`1<DZjUm z=LG(oQGR0YQ8V-V$)*k-?s*I@@_DDTT#aEZ@^A7!2bll)(lcSzfibzT@;`>T<m-K5 zOesw5a(*hKcm#Kf<883M!we$lBYJuNgKFV(#HODo=Ddu!JkWW^vHdy7^y|bn_ImLy z_|8DTE6^YIoSTZxV`B0!LOFN3a-M7YXR?_9e<?16|4Qm3iN)f{MIYHlTn)DqbFN4B z4D@3HU1ub>5u3B6{|S!}o36R%ntqMf&m9F{D=vU<4|IBXi|1U^*Ndy+hr|}oi-G=1 zpnoK`XYKTC%P{iSK>s7DU$&n(BZ@C;CGHDnigV%K;<Ye$f!hQ1@JQ+01(%KXx?M|` zX-&@~{>!wc=goyx>zuAy=XBjc1!>s4C7&O{s&D5tz&}ej)?5Y;i{er0Ckt}mF0$DT zt2Zdfhx>V*_pNx8>HzOp@hH_Xr)w@wpC$VeZ03lm38PfU2Aj^ip{>zi(<{YW;f>;L z@T-CTdZ2&mc}P=iR0r%k>Zm`HI$Os1H~sR~;(RzwJPOts9Adi8;1JU_$02KB)w&@S zaK6Txu3p0Fs@p@@GndcwHs|wSm)|CP(^UhVe!pze(H|7|hIIzdKMmFyJl~$XQ+uNb z{!R8dFyBvXFBOzV@#wbF^Wpa5nXu+{zUjvWy4KG6jnP`W3o2puq4fhN{0tW+dymol zY{m2w`Lord`Nm~EiS-+!Z<d}3tL8XAsyQR3psOc2@f>)4;B%wKPDI}#=I5THUk&_k zmtKwjv5()rqmI@d$YZ@mf2}-_tI>_J=kEs?{kONjkg;Q8jqMB{6zGSDx1cLO7qb7y z=zXf77QR3>rt2QRkh(O6Z-BOkojva|j!oBnaUttIX1>?+_^&a`6=wsieSYCExJqN0 z%NXr*r|T?VX!_@}G5fEQ_62)*&f68m1-jGo>S4{x>4(Y2bj{J}Cj`3Ycu{9;G{=kB zlLgbfjnk)#Gtd_X`mKR}uQ(eU)n49>;)0h0UHkl^)6li17n!}*)ak6F?d`G6qnQ8q zoDLu0_lET|V|BleW$f6#-v7`oaJHB{kG(L^FAj9wBSW`iqkF`@6^~shn=*KHFqZds z+y8y}InG$!7emeFzk!X`XlMnx)@bNPSo_f4$H!?Oj>v;`SB}Vn+j&1u?<3AeKQYkx z7VUCkWBG>f;<*n_?7ac-RM`~5`W7^{6kaQx*v38OeO_q(pOsz>e;}@dmH%;=j@P%% zap~~k-ez1jth;PnK0E?L@?$w1Pw_Rj@9pDf2l@?S&e8a?K-XQsdtN;LkznlO;tuFr z1ASYd?-J)=Q!geD<CXJ^(I+V97o$&TE1R`&doekgp!@n_({*3-o)=HZkxe74_x+1G z*Aqqt`e?D~IwQj};aOfE)*D_dHeGXf`UdGM&~*<ED~DeSblrna|5&=k^QqXL+ZgD& z2Zy0wk?QqJh~Wy|gO{-1t~fH#bq_kdpY(iebPrxK1-?vr2|PypA$+a&LlL}0`U3b) z>7}sN^pbK|YkJ8hShddSs&!8PUSrAsMAf(9tzp%-;TdpO|18Iv3-3(v#B7bNh4W<7 z4IU=F0iG&72UZ;zJ_=SHvv1B5H5aEpEc<Ho$Hdf`iK=76P1k)r+;sKKmo|mJ^!ArF zhyN0zPvU&o88LlQ8*yJ)b>Px$xM!fNXLfpj>1EiQEnWeS2y~snOHJ1tFZ~c!t-G`i zR?qD8r5bDcde6Kw#giTqvu7r~80e~j`KEs)JrCX~o&f6%=FjBEE;@txb#QCH7UP+F zVK><q!<o|4;WMQ($HIZ)jj-mGZ~E9k*V<XXQK+>WQ4g~Ztxo=@1<bd##J7~f4bn5v zA4&Ebg`1?GfxgxIcYaiJCTu`gPx7Bp@W+8qzWKOk%|-uJ`~Xa!mgtuz^PR-myc@-n z_xJuUD}l8KE@QnW>$~oFay$7b+4JWpCm-$YM>fL8YV0uhoIpQM{3p8da~b=8vVIme zz5u>iV@=mR&ihI{xjfL<icQyj!Fx<R`B~`}8{hHlJ{n&PYoCu?41eQoMlu)syZmjR zn|`IvveVN7y+dH1<#|*G>~*J)N{2Nsr(Yl&(=|t@UlHh<<0$fTrRF$_J$dDQvN8Pu zaXwrf=vxB)eQ^;ss=cFFuPc8KbnWv|Go$z_t?4N2uhN=2opp4%Dnma}TnV4<_lET| zSLuEqzYU(`{a^kke3j?X?A5F01^S{u*F7@2B{sT8oc)`!H=pkWWBER8`|zZL(RE*3 zj?I)PX){G@ba@@R*68wYVeP{S?4>E%hZ9O+-IWsx;Q`){)5nR)$&`tK&Nm{LlX~=J ziif{PVv6?ONY2p|ePfxxuqnJFnEixwc!xL({?7XxY5w`n?`(3Tc<R1l;+d-aTRc<s z&4>Foo;p-E+hE;g6B^*f-lyeoYMD3(-WcdrV$RW2-38A6jX?iA82goY2=@OZ^=VC# z`m_VZ#Zf#>?<u3n!!+f5wCT#Z)6bOshv);vb+GR1(WZ|H^ckMVWTIau=3Gx(66kjZ zy3WWL)_U5*(m6-dUKX3KxsNgZ6Y1Mw-GgIl;ok!NFERSn`+F`Ro~zr4iRbF00=;LT zpDN~ASN9he!j}a4h(MnzF2hFmV8I6X4(ZkKGS6dM!<BwNT+tk^k<Au(tMqhOYijR? zS8GiRc1Lj$d(=|!q_PCry*v(Q!F#twj0-^S*{7x}S{HJ7nl(XY~2@?11uHlyHM zq!+^#(v4LI#;$->$Htnjxj227>>JVR#nhQ1)v>YY*XX_;i++uI=5c-D_TGM6Hk>Io zy?3DJh^L^d4vZ^;M+UljW~Wb=z73mM;_a}`;5gHD2FIDMIgW1)tJaNAgVi%T{Z;SB z>8jh~*)!LCDxE!ZO{3U!)xh!S(^I9F!mY(?VV%M88)2Qn2|Ratf2~Cse5vfK;LD^} z!ZW3BgNw!A!kU-W{OKzKU2A9k#&oUS73nbh(CYTdhrs;qVxpg!&Ub#N^E)TgKTq}> z(|?dY3|%$H{LE0zxq26@p5)}|@cv1kGumq`Ki{8mr1%AxJ}uGD%-}nTdoFXCahi{R zVl}KiFp>3|k*hq^z<gsj`|LLGDA{Mi1>(i<>_ERk+#6l_naKX1Q7)g2@Fv-qu6ukU z=Viv*fxbg*y6%gKtow`~r58pq|2BoYJ0_;W+UHkng*$qiE11hn?Q^H=EIa*d*_i#H zz<#{vNkh<er%%d*H7}>%EF04`N2iwuy5=~E{LIuGC$T4IekdE$>%?X7&w>7HQonW| zab*-=tJ*uM8txwG+UJutqH9ejnZ4H3>H1m8#0+$PUTJsk#B5kUue5&VTHWsx^WoLr z|K#5AJz~?J3G~f@u6tziY1rr<nT-9crm|@cH&2e8)kXX27<Anilg;Lsz(#8{ISpNF zG`TaZeRy>_tbIuBk7wzwyt)Fu&iirtU1D-F>+V438<ERH5&C}>&pWX8-W8i*ePfwe z3iFQO?D2EmUSghmUAp&qh3TE8*TJWFwrzBs@;@mZ);FI?+3-Ty<ionlCKbcFuPuky zy%xE9YO?8HicSAU%sIO5@1$O=yI?YUahmjExPy2B+$+$J3-q(ZRoLh~WiojvR?a7z zuADo4rnkScHF~j_^(xkV?et}V{-C%3n@7Z)>*AU~-x}yTBUhGVvrGC~_;<1Cn){XL zvk&n4RV`uNgIA@(-2z?rpwmy2PCT=7#Kbduc%bVZyvp=x((PH(#q77)rGc({@G8?Q zq;G>ah<CxSh#TSmdZq`DXX|%(CY8Z|$mUP@AMF$N*c`3t6y`NYYdWPHtXk)E)jFpS z(byVn#_L&gVb!-OJZsJZ>BgGN)TZz~8cUpWo|VlCnBR4=vruR;d?39FRvnnK9abHi zV!GyH`t=8T`>C1mL1OC6^{Qh|*L^+J^fP5M1s*6af-ej7F@Ziqya5~4fvM!}`Xzy` zp4sUSczs%PY#tW3gmng;t}{5zbj@+v09dtdS}v@f+3A1D5Bgly?P=_pxoxDgH|8EC zHeEGvn(3!XXT9e37k>!r3{LwN))~Co{7=_fWWcw{z5&+nz!YY~4|)CS=J2E9&amd? z^fv-sYiIq&T&>+T=7)V~{lF>5M)3{&{#Bx%xq<KeP9K7vmh3lf;P-r-UV`3Dapu8# zrz<Rl&y&6l9_M*-Dy;Xr$+>W;{5%Y+p3pnTH>~tA7gfWLi`j2CJSC=f-B2s;0PFrO zN{1WtEMmA(zb`kr0&Xe28t&xBUc-Og*j3yO?iJ|A1$wSH8=E1X=Qf4&6hFUne&fhw z-fkQ(o!@1;afau9Y4Gf14sV<<oj<dGqxSIhI#_#n`fm7c#as*XyIYp?e&gWBd<@gc z;f+s<H^OfP`nzJ*?#A!Lb78%kU&)@iX`iHillJp;*7T;%fu12Y{Uq@MxSyCj-=wv^ zG96Yex`zFHlWNg5%;hHaT25E5<@6QakJHP=X1~evj45!nxCqv~oc?~GYmQF;F{zhm zjx#n!af#+QV+-6}Hl`mfW{;KV?r`?HJ7$<ZTsGTa-5oRP;8}q_N4y<fYdXX1wWc#n zXC1A^UYP}}SGkgPEP2K64eQxTK9Wr#tRC{(A+XNxwZ;7Xt^4|CnSS#DV$*dGUONib z-Qn!dmrVxxMZwr<+E=Xa&ARKaHJiDCjn?Q|V!l~xL{A#utbKTWHT<NvzrG&cDz1UI z1^V}5a&q%eNqt_b=1UCoI{J7{JrdU5yM{VBPj%+XayUo!)$qmQT6nVec@6&OsUN$t z0lv-KSZ^>-`M)X?eo1;R{IR$&iaBR)jjk$%buU{E=Xdb_uPujl7dySLbk5iOLE>U~ zaG;MBm!n@Hrq<2BKG1Ip^yOmaHGh?uJj_?luQgpczt;5sdYf6j;Wx#s*ZeO7{hL7l zM@-HaG!b*I7qkoXg9BY>WL7mc$4ciMEjU|jy5>I1^vk?{T{n1)n4B-THqd7W`Vz6l zbEnwic_`3z$6aUo%hK&xy6>)Izb)7q=%0&C|4rNg>mDy|8pR9Sd!3#-Uf5AQ0q(6m zPyr8+&Rw%GS9&$9H7#ad3$>=j17OuUr>oXEeVxX#b_+Mj=UQ0xt+)#QNV>7+GP^UZ z_mnBkqj=GNve^W;@;;}e!`-Cgf061y@ordktl0F#Tud+U_Oo;031aHWBGoacbBWsb zwArTXj-I_3UMal{-Y7P`D$uuzx1y^K%-#ln5$IowP5;~ToQx>GB^Gys(*j**aE|Gk z<D3bwYTcYdSnoSd*ZYpsRk!D`XKooSpX`lWW{OQ$4V+{8V(Im8nfOmwXYl%#u+HH1 z_T1OB7FqCT-v0Vjn4d{m&7YDR#ifyS=2+TPd>X8IU2l4Nplj`{-ze4EQJdpZ_M!Cy zr_O`<exB&rO8MU9bbj}^bZoNUDCHZb>8GWms|TA>0N<|IYT(Dj^)T<w7W35RaGf{< z{#kyCVV$EAVzYk}$@WP}8mt;p!rX5?SbA&tM9*`{!>uQa*;lt-ApbdVfw&yzZgMfO zZ*QIB+4}Zd%fy-R2C<EOR$Kz}^FbRstqT55Tpz`^?ctw$LnBPDYc^LS-IgiNhEEgc z!SpsRZ!6(p!PtB;`{A}C&-8=wZQ4sWmcjb@`_-lJ!}3`H*NCfO-St=3!VS_JqWE^j zc_U~1cEwrL9M<pK6fyVPPxAIfJoonV#f7l??IL2hU29!b3F{u@J9K>edT)P?`BXgD zq{E*|&w}-SdQEW@FFsIuIovIBYkl)5SZC1o<l<8Uy}#J>;Tl^7Pw_mR|9P>#lT6Qn z*LwRKO5h6d0(g_S7_JtZ&-VgdHS-43f0KXmuw-v>Dcng+3`>p`*TJe4H&H{Ds8-yB zpCu!_f2UtAHvKw3b_RJ{a*H?}UM?nYOSIN}bB&igBi-WJ;r&>ymVDrOF>_z?iS}4M z{8jQSFZs#q_V?u65sQz8n<vlp9S2Asimn<mzcZ{FLZ1@fk)asK!yU)T{(88tk6|8l z`;KgJBYaVyUm`9;*V@gfhACur-sjc8s+04!!uJOHda>!7#oOQ)#oOU`6k9E<{%~F< ztp0Ew@h@#Id-SC(#ikz;=!XTmYRmj8Y_uombB>m3UQXA%oL=b1I(>@R>@~;vjj-mp zfVEg!DI3!_im3xj)sr}T^(6C6-|1}@Py?5KE@qAF-wm)FnqH>!z90?OedlzosndHY zR}I+o^E{Jy$_DuTVDAoP`O-7sY2N?BGT06r&sw+zzBSO*cR5}C)xrvFo(Sw~#hj6{ z4}-CsHLH!M-yOwwHc8st*(_;ur`BlUOl-793rpZEZ?m{5tbIsbiSJYoxws{){@Ll1 zWlyf|oGLbZ-Cr}aVcwT5o-<B`Ro`aj!7nQ(MezILQdsqNCi7jkkMtUtpR?G#FtZ*$ z#q+hzVf}7^y&o-`DLn_i-N$1&T((ra3r^(I^h7>u;8z3t*Ttsq3dYupS?gu$ix%Q@ zx%#4o=*!!Bn?)U9^|6c6;mknqEjC@f#3J&rT)o61)@8Z+BB!e_a=P}+qOI7>lAmp` z&Vtj+0)2z$Tbg2{GjdCF_@zMC+@1ch^g?Vt6;FX11O3mWz9LmjJS$p@iD$);f!-s~ z`*|)Uh81Us*;gxu1-kC>Qq!kM?+q7;b6}m3(qZtO(ko%TOJ17~>+F{rs}JPoF!2hl zX({tsp*1ZnjpDl^`9Z%+eW26RwXe*kk8J8;^-iUK!g<n-H5dA(_^vB8wi=%2ZS1Ju zwMcp`tonRw2Uzv_)-3o1*_*DpIQ=u}i_yOnm%)D}b^E)bt+vpY#Vgy0dDhBy;t%1T zfqqP&_xF5TDmG_}Tf-v)UH9*8re7m{0(`Bw5Y`#I&2*i?+f3ISZ>xkKlKn<lcaYOx z3G|OV-_D*{xl_#ESov$9|B=*J?I-RQ#j9G0vtgaV+jC)^!P|N6sx!0}4e)T;4}nK| zou8-0t7b@NE~~B+m%y6W?WQjebgiBB605X!cW#B*hpry3fw^ZB?+B~-*5P!1j=XAD zvX@x(z1REm_Z+TjR6OZXT&~~YnN<v{Po7l{=g6iS)_0g$bud4RH2?kiGrZ+GN8C|y z`OL`eld^nRHKZ&LE|WeCe%$k7_EPy%;uY|l{#llea{WBzIvcC+nb(!Vf61mgitlbE zu7?lzT+G<Jj~8ddgT#e!fw&wtL*l=~Z01U@f_0}9H^TaMH#-&PUCGV&33x{^_5<;0 z=s%0gVeO?m>Y{jcYww?*Q^l+Gjcay3e5&*!nD5MXAMx|3c=dR31*|xiQg2r)&e_$l zz8lYG?yH~l_H&4H^)_(^%<m_d&pElU)_P7s6tB@eIHwrayT%-Ru2DR5YT-*XwgJ}9 zDX!0gZ}a-~dGNiF%i*0HV4XqRlWU$0^ykH<zo)T<@DJjuC|*miYjMuSbgg=cCEH;2 z5=*wjeY~F~HSmdIe6Af5=&G4ZOjjQ}mprV!QT}t_yTrt>wo+UMt5(qK#cNe7mYSar zy?>|IiB11qW2>Whoqnb~w-#<IoxH8nTHnwd&hq*V#IuebBXLgGjq>~n{}$W2*#Yz3 zgiYLHIXds-|JwiUIA!L^QG8G5q<&A&Krc+{_wt@%W6l4)yr(35R<M^6J}b8RdD+@k zZ1Y@R2XFU#K8H9es3$h|dj4#9MZNSx;h!`wa(myN;v$$l*m=p}-+jBUgP2_1r~P&V z>wBO2lNIT3t{;0NkH2q%I1QdJ&V(Nn+p}K65dSOI!mmothk3WM=bpJ2tasZRiRb>q zWK#wommGWl3E~R$fq{N*ppO%G#%7|JdUd~Q^@?nGxpel`{o4Od*ZyB&`unmm`;U|M z>zgR%sZqRMHSNYqSUr#VS+AaF1$AcqDM>%;PZyi6`g~&zJWKi%c#fDntY0Qx0Iw7; zh94ED!%v8r?|OZ6UeOYMGqBn1`L0dqjp8j)yg_&6UF@X|iMiClN6W@^y_?_I2oLt_ za#JdNxi}Y|;q6y)9yjQH{H6j}_sA;Z->|~ltYYmpY!sVb73kaLX9Iez*nEB;=z0%b zNzNZ=CVeKnx8f;=50{Sr2aXc2g|&z8B3BP+58uQdd*DiM<8*!Fx~U3Xdxm~6en8(7 zZmNYJ)w9US18-?8d3fMm@er81+v=o!e|vBb?HT^Qiw6&q4SVuI)z7=iVb#pL$lHUe znRk`J!)0&!NU`bD16}*a*)R3aI(slSinAmOel@UvT|5DOXP|!`=zl1F=JilVudmF2 zJBc%4#k?{HR?I7l;GwcHUGY18TA(X_r>|1Xtm8xK;Y*nBL#i9jzv5px09`$y(-ptd z^-aE{IEpJfDt>ZR*;`x<pCPV?bp~%vg(rLc<_uVM?B;CvZXYx6PjRJwUT`z9RjO7v zU2!h2LRW07>R`pT>QDGL@5kwXiP0ZU({oGV?&1n~khfXJ9)4Koj-TDd4^NU!1H34( zxlPP`AHF}}2gT*+FZr?jd@p|Z2d^)04yzYhj{eBrvd8};st?O{!#Y#THo-bm%f5xr zlD+BYh)o|I=;H$Y7OnL<Y*=?YBm7)3enfqy^Z%6WtI<`{oUWR-%yfOjpO+oQkLv8t z%Y*f;U|u2I&-+=P4r|@#mB5$!7zXr($BJ)+RlDYu!)p{9Yx=0-Sx((}^jY~N=0_Ee z)87g7Z!~rrHh)V`kK&E77(W~JUS_dv)O(rv+1T6LEGvN3hs>*oM<;uLjqKG#pRjRJ zz{~u-Z+*yP{H{g9=CPK6uKvM#hR4)D+{^ktrv70d^Li}kA0AWxFfa#Q{lk1he0)zo z$N8DC`iFsc!Rj9dehGJ#O$n^pyQVj++H2qU9#{V`pIkkzb2p#)KCb>@fjvv-YmM2f zf3WXwkE?$;hi|Zt|Kp#vfOwuz|F9qzR{vmQpE$wib`5*=3H1+7KR3{|SJz}=Gf{da zth-<hwf%|Z(&xh34^CH2SY!J8vN8LQllE2WAI@13#Z|2oa{+v0(!Q#PI1l}lKv(~; z#&p%L1;y|z*^uX|Ib!NY)iQB8yi!~NtADVysCq&=^R3cZTaylJZ#x_H4{KSYszz_W zwl<2NRDD=m2PfuI1|KaO)73vLAcs$?jxDHx)juq34$tuR>rB@fT$m1*dHtSpSpCC2 ztlg99ADmt#8`IT4tgD7=z3zN|FE(BM!@4a|{FM5Kb)~Rs$U^e)lxp3&a#*!)T@|c7 zyw+^Ahxz$){FM3!r>lQhSctAYvo;M@|FF=W^{8L>g_W@Shqa?%^$%+cVD%3Rw?*;O z>K_L2_Y6FJke>_hL-Et<AJ%S!br-Ll3F|Iiy8#|9d(%gXO`jg<+CR=-{X;Il_x^Mu z&Ib6^!2We{F}m(J_gwW4YfV@Gu!!~D)Y03o>kD@hp9U-Db;DrAypDalX{c;WSNu*_ z|KRKuztdOw8lKB{l}+j&7Nx_g8_r(wuggc*9qn|*?{xJKi&)=h)ITiBh1EaU_t<B2 zk1Q&Obp{u)Z=X^Bu&54J9b420-yOMkpVjQQXVgF3k`6x~=!$doR&>R7&u&<;-J1%l ze{j0`2h*Qb|8PqVtp4Gae0Y%ee|I^ob9YM#tp4Ga3V2aqqyFJ;_QtdKOE-Q{%pQC8 zCBJWPVZP7);PurVVD%5HJ4f+zdrNN$t3Ir54(m+ay$#lxT8-&*XUV_m=V+|yqXT_h zpsRn#C0Ea}?$$rtQU|MlaQ>gt*zM@5X--#7yW4d254W&J)jIp7<g;4+Lum%wPtWZQ zYu!t;;Y<B~JNGhJ{lmHZnbvC6uF^bM{X=OXtaw&u!OzMkXQ5j0I9>h2YSX{*^C~TY z|4zoRITqt*v-*eC#I{-egZbI4{^9PKu=<D6a+vRFiEjv-uX61Ej^EAKN6`!9kpIM+ zZxXXtH?xQB-Tb^k@SS4*PLj=uc~!wQ8E&k_pzm6xtm9_tnA1nW?~9A!p91}VN&Wf# zHQ$CPe!fRC&gYN!Y~MqkzaU_~&D!@3>vNv333Pgxg#N-}pDXKaUeG=AP-}RF=EC2p z^1?md-oBH(P$`{nhA%wj<GGc6`@-vDa{B^(k>zAC&wgQ-nBUQTLACl;)@zG?cJM$q zxVgrX|1Dj7JP)$Rwj3cgn^OW^_xppU=X?DD&eWDsV$-L}C;8tp-|HK;!?%b(gx3Z7 zed1bl?Y#|a;pgS25&l><8{tpITch~JCZ5+1fSY-H`?<i2ir?v~Ik#n^>-?@yhtHFJ zE<90O2rrb+BKTG@d-cWpWK#-PE4O1|_L6-&TF;(*k-g-&24*igHhcDx<LW4WNoQd_ z`b!4~`mss-myQo~;<PnApKo+8CE~1vZwTyf7B5CuAL9I%2m0fRpV(e{&+8j<Vb${u zd9Y&MPzWpL4dqe%vd*&UFDrhhtB-QJ;&=K`#aw{>|Ji#Nc(10d|9^hh+PijForI8t zkR(Zn!bWOKCF!zt-PP`bB!m#s2_bYya*q?XBvD8=yF}?G2}zgTRV5Wd5`OPF$Czu) z)9X3sb^LzkIp=v^|Nnko&#U+O7;DTi#~kyr*7tU$wp#+<sqI=n8vlfWu-3oxqwzca z4ZW5cnD@ExBbDH-;^&oG@HeX0GtvA~%B^9|?W;53qs0Ez6|m;k>1PKzG26BJ5n`S{ zSoHC^@DSC<z|2i&GYOuqOg`r`@0?x&Yu?6F5A*k`PW&GpsyX=!e6r}H=*x$?_wl}% z=tJF8?6n{2o-!W)AKs?%SY31I^e0qrg8qy${rzyBasj+hc_h3e&~>cGqc13%>I*8S z_6ttcnD=3GfySH%cMR;iDi@+(8|XI#x}G;i6<{+_b!v6N8_MK%!2;z8@DgR_`+^P1 zx$sxY^moCp%B(pH88<t>?07A#Dg4StxR&yE_*~`Pu<y$txO<@MnST^HSvXw#TLeF& zycA{~wqretF<tn+@S`>0FO_rQ@0ANow5X!;5LjR1E23YE^vw1s{uk+4-M${N=o;ht z;%u&0E=Je2w8*lqrA5~MCH21r*8Am`>%n@j@p40WyZCvzD!fa%nu!+Y2p5s7#pPA6 z0_*w5=_dzzv%vo1Kp!A=(*8QG)%h}-|GZf5FPxtz^;+UwtTo_ttpQ#Kh!(R~+T4yN z&c)l6>B|y5|BTLqkI{B5AFnnAaIVI{*ez+UJQprdn?W$IQ#k+DM&sdigJ{XK>a#Vh z@i_ghKwqTS7GbkCh(YVq+3VbY*~Ye4ZSen*uAfD;`w{Dai=h~9CTD{?kB3?3{qvBI zI0GkqtDFJsS>mI0fzG<;&k{>tmA35pVd?9_Z`Fd|)I98g-xYg%mRS0s=pD%O(oZy= z74TQWyniZM%Dsl&cRE}R^E#<x&K@6^R+|F&Bx&pQzVIok)5ninDi^`}{N%A>n6t6% z`(w2A@k@FwbMxa@RNn>j{KU4E&l%?964A#H&$2A#TJRz1waX4y=GtX-1HFErYpuTC z51UI=r{<RpQXUTLn*aJ#SnJ_+tN&GPtUf)ke>c$etd(#5@76eTP4r2*)c%tLlt-W+ z9q7jedSksdADeEfvz~v_Q@I$vRe3plhw>^|&y#j6KGFTu_V*K=Yp=J3wYHtjr*iG& zEOb2&OfC=W`Y@SV`o#BTfQgn@R(tg2JWsRZIEMTz*L7^nSXl2t#+1OF)t<d$xz52c zd*GWzpF;f0bzhsp*e!oF&>vT}`kU%!H~fyW_4!etf1+&tZ&7CMFV{8X@k%E8RM)!6 zwEL;9b(6QlTElOUt53CtAFl;pCVrgWLHhf69=g`d8!h0$s+03iM=6t&PbcfOW8k-y zpMpP9n<99#*7<sPpW0B9pV=E7a{I;>xT^9bxSDbad~Tp$5a^u(UF+u!Yd=WZ>ew9i zan6Td3G81}o`OCn(DmN`4Xdxx_^r?1#b)vV6MY^l4}vx3$s=Knd2%t_NNudH@jJak zplke2AEGf|kNrq(m+}2v*A3@i<DWbVUGE*7uJJp4g<ShYC2W3Iu4SSX2PwCPbsu?x z_*dv0d}1uD_Xtl+h4mc!#8UV!y_PXr@ub8*iP%;=E4qE1V#SO=FBY~-^NP=f-?TA& zsoVtqKG1(k^)D)`&xR)YLgRdrn7_D4Y+j?DztHveN#g&4`+Yk%pBw`Z4{Sy#m!OXe zxJa44d{L~|PKEW1J;}E9jo3`eH_^&$<%Vz><;L()%B&|Vk5z5}HwpB-K-c@nN!DKP zA9)=tT6wRIJM(4b;~Eb+UpXo8GetQEeO{n140QHNmk0XwWw!8B{O2!gDp!RYt9@TM zSM_@E<q|_DzL((3p2~b@{+BnaO&+Z8{dlSX_VKWWd^uHp4uE|;R@e1vlGQh<pF!}R zAclR)*ss$4ViK{fIxx_6k9%zrdVTdX629D+4;Xj;qE%glGd1Au5`SmDdt}vBat64H z&zY{`KHcuKo%!yORr*}$sUr9>^;rV5cQ~Imo;OtA1Jf6$kApu^E{4Aj^qr}`n)?f9 zUudG$6_xS1`WW%~bS3z7W$J1*_ZQCIGWQpbbK$E3{hC0hw&!WzSC167eP7L5=la+O z<_vGoOSbQ;i&W<|wbk0Mr}JUX9=2wlCZDTI)TfP;{oU#0XAS?|wMF08Fc%!t_cccZ z`cZ*SjX4|oz9v^0pKIEwPkU`2<t_02YD3@GJfuwD*E|*IV*`DrG4r+WYi0}EzOUil z#P$6(n0?3hea#oDFG1fR?LLzO|DsG=YY$ZJ3!k9=iFxfwst<vit4<!)wo)#JxrcS} zSpCXC=YHSm<YDc-%GRgeTRk%d)_bdGtRL=QoIQD1yF%H<wkgnAqnr(TNoiv~)I5}w z6SjFMIY9gS6MSfzhZ1Vf=BLZS=)PYi@P*RHXRE^ON6sg4mUL6S9z0le`dBhVxfmW3 z=!}=U*6N%A9Mkub>B`pUQuUb!uU8&mqIIRzhQ6<3?zn4n;X?xb@IY^9%mVHEy2iq` z@9S98TpxLMw2pfsUjysfs@@g7tF}wcue(usKFpkQK8bUk?!V8Lz}#y%oxZPQLvu_Y z*L@i1ivxX&GJRjST^XP2GuqZ3SnF*pF|R*EZRq>@M#{M`dxvYw>Ma8O3S$;(-`8I) zZ2P{R*E?L_?}7Cm%Fg}ucd7m&toI{ht^b!Kp0R^q=9Kek<D9KJ`B}e4b^5-3y>c<k zy`HnT`fsVe;ZSAzzJc|@``n=G_ShoyChC7F+*fVr<A#39#J1t)K))@}pD<>T_I<-M z!nW@lp4UEp1W!oEeFM(`T~2nO>s~*07p!Nb=W4+_)F*x4@SVi=95HM>Ky~`Kk^RWE zOW!x180aSlI_rb8q3;`69~|RzBm1dcOP|Y!*@GMpfge{J`o8gLW!vufK%W@sD_y^g zy?5ToeoAe-*9$f>7K=3}8yO47<atvheeZe*TuJ$K_%MxOEL>0RtHBMFYr@o<^OFO& zR{Iq&wdZvDwTaquJRD}NOZ0mK{RL(ExannO^00}0hxlDzHhr4*WmAdcsL~>Az7`(M zd!#q>Ov&4CJ~rTbj$Ix$Hxhe$?Pl&@68j#aJ3qGs`cnbF7w{6{(m&(p%aph9+`#+X zvc|D%cgt4CF6J%de~FI8)<`&;zHj9@t*yhZ-C)K7KW<;%%2+u44s<=I+1KW_>Y3cW zezdiX`WyhaR~`uKv+?H(;D=SG_O^~zW{kG}HPE?_aIsmP_p;hLe0~tjdB*8u;LlZO z?r+^Kdb|SOqrBTh+bX5{wkm<nTyTE4cH61S_}r%R{dsC~+eMN$-a{H~)BWZ7Eimhq zjpwgb;YXAQ!LKXNhZz@ZV~_IN*b{AA8S8Va@&x#oK>t0}zdlMhn`^&5R++ZG&Q%*~ z=4*{}TrId`pzD4yE)V@C(PQ%e^{vXB+rJ*8vGs-DR2~AaRvYHm*XxvXO|+f+M;m{P zzMXyCvDND;w}$I0w}rI^?C&aW*BZzyg_(mc50<Z0UJl<A=$x;djnyY8uY$S1aC!+m zPh)1hw(nGZJN&(HRK-N!9F*$cu+H0Sovt~ISU0}m-pA?W@S8&QISJPD_PF`*qiRE~ ze)G865W_cbi5`>BZ>A|vg_i~TXMz5$aMT%_AC&RAqpbSe16LD%p%UCcxgOj`xi#EN zuN?+op-c=r?xuhA(LPt)ai8$p1K|ga%vtieW1Mj{`N9C0z2-seUm%A&7U{La;iak< z!{4Y*Zg&vB_5XH`iFTGr^_>+0y_R0P1)H;lU*tdUyhOPwJV5P<ZRbGYsl~891L60S zqMgKSV|$Ul?;NX~50i5j1AW;!P4yx0=jx{+{H1bRn0m1GQ?33}s_&|-*A|&*m)^6# zSPY-3`U;pi<*v1QSK(>pVb*8626p4UG`on|#kmW<Pxz&(@K~{brv|J!e<>H9tvX}3 z>wV?1F!Ro~^^Voo1^Pbq+1Eth{z-WV%-Pts`_dSgeZ=u3xQkqC<NUU}@brARm&VNd z+`iSd>!tbd19~m-f6LlyW0=+t*0WX-eff5->PzAI%GATRC4s&%(0>=7MY$&Wu8J}- ze0QAk0Qel`;cy?5>{H)ACw^?q-@hO{a|Had#@`yA9N5oL9iQLNaeB1j0hreU+!(PJ zf4@%K8VhR;%plL-|DyU-6YXYSuzjCd6RxV93v=E`^ag?6T6p>-Y&fgi{1+{S^;x=o ztz`H8qQ8vk?up9ebN2^w?Tp4S=L&nReLZOR290?G{Ect{<M>0YHhJ*zdTlPuxz5Hm zqX~S0+7!U;RmcAiTEjD}J!`MCw>oRDW2<Z3zB~wiPTRd0ep_wG$q&<&>%i>4?phn0 z&bt|vVAf%)PhSD+yql3@q8}@#`i}?ewN_{E@b*8lcQ~I`zgT0~1NRARu2L>R9~$Vo z?oD5X&KWiF$r;tL)h8>Lz}m0r`(RxwrcZ&_s?Ahb>%@-lkH4sn%}<92+nW68aN&20 z;UgvH?&RmE6Vm$piTem!huvGCH%#mEr}I_kGax_dv+I{f!a7E?h~X#hk6djO!MdKm zn-4#z?GA+P;);K#j}LUMv6&mO@ik`ST(3S?m}n2@ap!**TvK>F`QO9+sr5N)0Gz9O z4ft}6`CYiD@)r1JwP^@z&Sw$Zp6ArhAov}%X$|XM<NPmG8*9HIX!omB|CwWxjdOfo z6a9RMwA+Jwil0wX8*=jVDar-#MasEwOJ(NB&+MD7U)1f-?3<363qKDJ^bvt>4{kOO z*1jmvXKM`0(RJN+HtW=;3OeV{<l248l}xnvfK=amV4$C%%(Z)czv{u4iawJ(?`@~N z9o9Or<GWYqva@+WY-~;L{fqGI-SDFlb5F*1@3U!r?$zgPJ!_$}M%i<|T|f6uRr^cf z#hU*iu#Qo&jo~ZR$C!vI;`%##1e~Q@1Xm068iB4gR$LVuUt^QteDygWzDc<RenNQ< z{D$}`9tZ0g<`r`L3(wH(T;uoLqF=sHo(u1kYwdec_G!+GiEW?G<>CqO$!e1epP%~Q z*HqcsUmobX&pJQ)Oy(8pa3A}rjiE4xbw4d8C;MK~Ye&KFDi4I;Qyv8CT2!11>snMi z0OlUe){@nKjg--UJuJ|x2l^Qr1Nr>*vcRT;avpmBK)+6zIr8gWfqrkGKdWr7_5CV@ z=c!%|UZ`9H_I1Me{;G4i7@OZ>v9UGzTWR6Bwcv6Z^G5ifv_5~UE_$ylbk-<epTE^r z{UmhV`(7a@zv&pgM-0Dp(J>tk-zaUpR}9~xyb69e&_@Tl*4UgD*!UV73olWhQ(^XK zyDq)5)I`5?kL-90Tuc1SSpnA(o!gk`_X{=Vn_$kvwoZEC^LNf>_Sy;L>UYig9Af)j z=klBq_yx782Tu+B&rr7Z9|ig+fxca@%`-9oC+)6<4pp0C_z30s@M+3L@R`aJU|oym z41{$pnlld8GrZFWslC-lDqH(ef&Qw*(0c^>hk?yv<-zEBo^(F9s6Gf?_hP62p6Z!{ z(rYumUt>(1Ia~GC@OjE@VXYI!H_qr>o?~rp78`0Z&fF&aL1*|*jhS3!IM?ZOl{hm> z^%8W}D6P*p!<pZXZ=W*gy7x^efOU-Cw=wX1#*I7u%50am-ro)H(snDEILb-&sC=Mn zjm;f`jjyqha1-^(*hTEo&Ob5p#i_z8;AhlldH8wNcfr#&=F8ysl^KiZOR;%12iBaw zPi(Qy<@c+=hpSBuSkHCu<3FyiZCU#Z({|&F0=<V`+YlSh5-xAk;fKU#E;)%GQQil? zqPz-zO}PZtwP-GVk994YOMl~SYGd^s%II08Qa!6|pdTYK^zDnyxq;0E%9GIbTy5LR z>Z<w#SodP5-w^2c2iN+3Ey8}X>cil-m50MxCw6?ZbS}@eHao?})@0WA!t+PMKWWTQ znK+wsov+XAvZ~KO*XMZb?{T(1$LqTZ*1hl5*07GzJYvY^*_W-KSII+m4{fU!+*`Q` ze0!h|4fJR9TH?>v_4Cy+Fwah%PjZ;OM|r-9OI4C<=jFnB&-f~1TIwW;|B91g-Pf+j zhg<5kdtlA^JmM*(IiHsYKOi;}E5Ty}|9Y--_L_6o?sT=WewORC^taU48pC5IE=@k{ zUOW%IbhdImSl7>av{m{j)tMKib^ZK+S}m<>(LClw>CR%~^a8cFx~`v29~|g<e!G&` zO1~al`=;_n^hJTL=jsp0Vd)Klu6wc5e@(B=p--+~#>6?tsy-DyL7Do=IZt^Cd|_bI z-Iy=9p1(M!mvE_E_zKC}m4o2x)0)f~toj&q#>me1D`&$zN2P8vYpLNJ>c{EZU|l~a zTA%uCYGOXTMaKyLWq4j~>uMrC%dr02cw+KjhH-IR2j*VP*-&p~SbwY@k+(8hOA|}r zD@D)R1#?ESHrb3znY#o1zCeFLIAVOuysT_}&Qe|k&k1Zwlsltu)Ohy5>}xI_tLyWV z*J_x!Y*o>-h`DSv<t^};a_wt*aC_wfnEB}Zkdv~^N5|x|EH$6#MS;#b<MavGu+BK1 z1hcj{?g#&*Jix@|Dk{@fxys6gF#D0Sw|bpGZ>dbb%5i>3Z2D@<#95AWg4N@xFy{ov zE8w>ReOjQeQzj4PHYsm6artcZITEg+Tm<X+@HKpv@1*)3_zt-?D;NH=aufK8Kz}CC z-<4}8Rl;V2ay=7Q(EHO#j75bCs*{HboL6lPU)2CUOZ;T^!RH7^S#W#RshJAwDYow! z`c>gN<w-DSSErZ28fV7p_XPSQf&F8FuFuE%b;N#=#x@9MO>jP~AJzoN%<Bq!1O2yD zuc&MCq>(1B*id!Ljg?2iZIwsB`GHM;ZI`jAc!%<QSmWfGd|dHK)#-c1DU!E-#948c zGWA(e*W}l8VBI@juVLZ?4v@B@YVd)|RzEJ#YX`dCZ@%6To6A%uh66e%SA}&Qu(2JW z>p*06&ADUtbelKV?pTTc_14(vdc}KF;{!fZo&Fy1jq)CtbCk<@3lmq0mASUk;mW!2 zk;-{+y+Cge=(>(&`eCDUEi(YVM%sFVm@Bcy+I8=Z0$A6pZ0fv{u2<Rl@W<);TxpeK z`+8qoi8a=)$uGVJQx7ZgW7qjVMZ(#;V12Fd>O)}a#Mb=PXTW;zb~Ww(sg~;3!`!>M zc*x10cn)THat_>8xgmU`@)&rO@)lTMUz<_`o-Z+QUXK67-e+UW?1t9_`ubF_oF$w+ z&cu~-lxM)4_iPMP$a7^~SEuxa+lURXC&rbTr`A6%;>zr0&VD#NQh6*qRqcnsGn8#x z8c%F>jVDGwu#DPFfmuYXf4c@Ac#?2b4?ab?0h||b3uSV3V2?oOY-asLR;N}S=fc#g zW5)eJJ@ZeoZ7oo}HM~T55WFkUcc*$4>eKn5?^UQz$ISOC=V~67!X1^jzys7~K0Hu# zjx2GNzld)0S>;h>=5Li(1O4?t*YS;tu~{m5WPNT@pH*Sbz;;~TByR^DpiI9GI!So| zoU7Lo+d)l)nSSv>8uObYVa_Mc&mQ<;;kRnRdX9Z77oMkjKD<i&7-Bf6M47%E^n=>a z?!o0$9|mh|Zw-gpD{T(52Eoj6$D?2!Yp3g2XIZ_E`WXyg75E&YZH+~LSoIQkwCYpg z$?Cr`{I)XjAIurRwQKcH0)2<DS%LnYGCmK{xs!!{NO`p<pNAZut|5nT*0Sry@RsPj z4hY-#8^njS6Xv}Q@gc#P@DRDDj+{O@@Wc9Vuf2CN_TL5iua4ciRJDxgbB3C@Y8A%c z&Li?%wWgd=?fp^JTEYvd)vDYtyESS)e3mltSLNQ>>iv(0Tj{kMVb%eAHlA;7m}`!$ z&Rk3MTQ$#1(VrH6yDI#q@)(%hTKf+f$Eu&Jz6WN{wfce?@Nc3|tz_auImcRkVJ@uq z7Yp0M?7yyE@_8uxuVdOh^m6sn8SbK70AC&G*9N*i6PQ{Ho2RthJb04Y?1rZZFC?Xh zeh}!a8!k4huT>_uhjOm4`Xc&!D9?voK3l`zrsH+!FREW-;=}aJHnlH&VmiKuoi5Dh zcH_e?3%HwO`?=ltFrHCR8}_@-;=^SBa{A${Ek1_BSz9bGCvS&8uI)~Q|0;g?tWA9Q ztEw-7-_|^ggcm9o!(WQcHH_)u>y$gd+#A}p;vMvAf0DL7%7G73oqSe1MVYav)>?TG ztoz72v{jAu*~a-1Ijr`O+7!VPwXM<cT-AxEn%?`oQv!4EkX*~T!ZALNsGRCY931E; zE0@RSRAuJN5uKH5!3E0s@Sg*nJ;nLA`m=%l*Fc{yF%QUKvqEFu1Mdv%zgMnf;_9VR zy?WU|uOZh?tAx!3s#Dw5n<<me>fMwF!abD-!-JF=i|T`w>2Gz`MjQVUYP<UAz~&v{ zr4!I+Do=rzD>FB%YhR|3pXxsb`d*DQ*ThFwRVF`2>N#iH7?{1rw)^o@aGu&sg1d{p zjPW{>duMC2j2Mo*Ezs`_^rwYC9)-<w%GM|Ax$|%J>B_cU_DZK0!g_w5HXq)l`apQM z@(2^xI7oPD75Gq%lNzhhDA0AUr<u5huajMHq1aEa0qY(*ot)HoQm?hFHM6t{taEL8 z0lY+O<|cTf+S_=xD3hO~j54`BDoc4de0-pv80cCvORc@u%u;J#AZ=Y&2ljCefgcI{ zJf_?keSDx#40N53)5-HuUy1&4RrqV=8YVtkWB#}vtTBH~e~&&!ZLF^GJN?{1*Z7^@ zS7UC6{UFWrB>17gUgQ6`0s4!9uJJp)Sg)l9j^3<X0`F1#E$}|o_n7z?-Ge^KfsYWI zPin%aDO>%_KyRyl@OezWGCq&#FFtvnKzz(F<%Y1HPiBylV_s2xI6PafT~Y+I&f7J1 z##nfLpl?<t56Ao}yljz)Yhvr>5$)F0_?@otFSB|>^;rzJR9*pJBiAk_o|?Ko&m`uW zx+c%82Wt&Dn>W<HAG+>|i!Covo%vN$^E|V)iH|)%^;PhJ${S&=+r@L?lU1J&Yuzp$ z316%_F&}%Sveo+s`rUzkU!cFH^>aJ+?@E7X_JuzS>{lv}LjNYvzfJYyO6#>lOnjV= zc^B+s-VHZZd#g8Bwt6qUb_}dFFmn?8l-f{l$Bk7R`hFbu(f0gs9qZe1?<wztzfhYJ zm~)`5jhS3~d=>SB&GA)*8HV_HAE(tdPN!ce*UqYhuC=<@`q6!Gv9-S@jqUjB1OE>y zH^xTq5oXnbnP2uy!h4?M<2gUT?u>do=RK?2GwSiwusfp?|MB06AA3GIUiXxh+hO(; z+xP41nYdPta%;G<@)K}1y_TA(RYRG))#5(F*8g&=Hwbino<A!W{VLJFD1^0-Ukrlv zS-~vJlQcggVLc1YDuTC){%#Je=hb(InD~UlR9_0$6Xx~(_=Izm3*hF;_&kAi*p6NC zR9No~i|w^~E}dNo)^q7>Vm?97(z6G^i{;wc!{Ob^^u0E@vOZ^*zz1ut-h(wipVxtF zO5Z=P2RBw80p}_&g1d;HImBQ424!nMLOBn9PMLnyo}x_NYJaFa64tpthd$QUT+Jc2 z6ZL#JXAfLk?BA;apRL>wZll~9zDgONCk|IGg7sehy<%ABHQyN%pQ!g2_I1n?w@bfP zGOth6eSanPb>dX7Q(D>T)y4nZT)2Vqa9G#Lxl7?fvHxra+*jFNJ6L%NJVcqk*Lgh9 z^$hcw)tTdVyylXJI$C4zSB2M${=SXj2j#vdKB=tuSuqx_sEnVJjtcZ+1N|J~<<{nW zWnw<5v+!rk-;)ZIY3rl`fj%(M@6{N{|4Gj(Pl6|l&B|f0p22LMPx>&>7b{y`_b)rg zPueUxpD&D0+9tI+umVgy`*q_aYR0Yu1F74(THEiF|GJzl?RsL@nYw2R+xwup?E~)N z*xeJ=oge7SQ~l&oX$&Wi5#GSqoy@#*?Op}HDE9VV>15Ufr{51x(>xIW$(-NpIDSCA zoxDbEK7}_5-%thKp*BNIT(62UIjpB^#Rv1@OH?m`uT#c<z59gi>udF1R-e31T~BM? zz8+UkpUK<T{_5#kx`sU0)BEc+yG(pa1?i*JPtp4|r`J}!A9`Kojc^C$;czEqYUz~Q z1AS<qKN0B91iJ2DH_YPNPqZ%u@V3Byhw=y$*C&^D4PQgM^|J&0aJ_aAy4Lm@>bbtw z_L^e2quMWryDG1Ob^lt^7rse#`dj}2<+iZiJ3E^xqL-9MpQ_9_*8fOj7zux)Tx8-? z%PAAXsYeOVH}DyH?LN4X>Q&*kqOW6IPSyQ)J#C$;bI|EJ2c14r{p`j@>$b%D93SWt zm8qFi$+@k``Sswns*{sbHz;p6af2+i$%BtmCO-|DDG!IcDbvRWI__)7!aDA2$H7mi z&3u?=)OL>C*Z`g<ZLPI!EmWqz4K#+e)KY`5RNrFa({z2a`e_vd{WxW-Ypt%e_7_N7 zH*JM|oL0Xvu)jr_Iyp_p+WFV9UTgK2Bz~5y__PILUor?@qC5old1Ks9)0j(&O?-MO zwLw2!<9GVefv)j8{bGrEP-W~pX}eY7>jHa?zho5py@9UrJN>VEE#rH-?ztc4!C#8~ zI?HR-rU2e2`ue^mrX=0`TF<(DM%6&C7U){H>vFMaB)au^#--|${G8E8c`SUh@_hI~ zWybo9adPdN9JomI1(x3rblor3R6;M&80x?qm2JB|e)NVue)NXACM>80>sq>im>cT( zVF7VA?62*Pfi;J#ieasRRg2)4r7g#=Dl=ai>iyS(sj#k5s~f|5c3s`X#AoWbudWGe z-L58{Gj-fok%u$2ZdccUFH-+jZz=5bUV(l^pp#EKrv^2`{u%AdQuxil{vGAr=!*h< zX`t(QY{3>2pXFn24f~ke!g_vKZS@o6+SOKXBJDDb<Fk4ySA}m?t_P3OI4_5Z)5ZJ_ zJVk97ue0<y(!v6Gr~2;<f3J+*s8p&q@^M<dhWcSl8=a~)`LNdNYWy^69_XzCKUe6r zBe8i*&I9)R(1>}&St43@DqJM?_6*Qyg79wZQ}_Kr-@xqq);^~aJXiX7Gv}5@3-p|D zHq05r_WkA)Va@|~9bQ-je=R;YmcZKgP1JLvU(}}9#Enaf%_jQTxSaA__>h1P7v4+^ zjgJrbL}g-btU1|iS?BL&Vrbk<Z7g4`OwBaz5O62quX54*1bmh92=to*zEyb(`aJ>P zFTAAz`eOk<sXPSzrGQ^iW<EB4JK*WUTdB9k^8#L|T!{X8z+Wm)LjNk@ua)<q{}k{q z!rSspe0J%8%PEgSKSal91$>P1F8E~OMLDqEQ!lCk>)O7E9G*Q${Op<v4_00d>pt%E zF@Zi=edc4s+11w1q5-hh(xQ>D#{6wV_;<PX+qNb?=MZJ|a}E!5UQ=*>825A7gB%yb z-IYsV-QT|@&U18s|CTt<c|!eI{TXGe>;223J@69ov$zt>x!3w%ObqApuRY6sJq*rP zrhd+?Cj6bXsi92#=d!q4d#5)J^bYDXADe#4<mB9;%H-r+)*sjIBv|+K#Y^E?s_%lC zo7QGYCHPzM|1I&K`-8Ss#l*Q4Qa$%ifzE4Z?%G<|oTtqA=4xz93Sd36eLD!&asPG{ ztmikU>$p3eXH(9nwP!tXJQDs)c@nH^<1XUN)w=zbIL|vkVzc^r2Wre#udCP2hntAL zb1a;vTnu*&^d5n(@jH8sf2Xy7Ah6MWbLUcYoxjdT=daUe2KKX+t^H>KuT(BU-xcV) zQ~iA13#`xcbuZY7{rN`*HpeLMLO(Om&kpoU0{yZ;?;CJGVM2+|*ZSXSecm1DI!~Sc zRG_~eu<pydDsio@SI(!dS599Y*soKz_TS6i)Z~45kLY#}I)9%swRC~e{pBLKl-O5W z0PA|S+uCSt>}D;!;6SzSYvLxH?d|?m=4!aF<IIr9V9rSBnOpCKIm=m_?`ptzh(7TV znEOy`Q?LadDK=++1dkQIxEPlE<;>B4g}E27_RXltCT|PB(-@v3{5#{=MDER_0jpu^ zA&a?bCcq_P^L7)MbBm2<>o4$6qA%YI^Ze85*MDx}3(E`hY$?8w=Y;5{DX(c>c!cQX zzJyt~Z9IoR3$t!p-t-2{+Gu&z_wWT`f8Sm3MZzy13+FpFeXUJb;V(JcTzIA9Ojn+> zT{uAOFW{VZA?G3+!!@iG7v3rST0YD(M)auW5AY+xht7eYb)31s5B!4YeXYIZFd8`( zmK>U&FNNQ8Hf9EOav|q`>$BaV@TcOZgy$6(ekppdk?>b)zaHKpJequ7_`BGT$Te|O zt);#%!iR|d{a0{x;WE4rs%dTEw;qB|5k8Byn)2+<=CI0JFlR-}_dW=>b{riz1McA1 zOgRniDf+oJVacJHm<Qh|HaAg|O>YyP&VJGKUdNd)-h`$0%$hYY&uVO2woaNp?>MS) z0sN}ywoaO|pIV#l<e@2h0UX&nY07$Q^>TlKmx^xdq$z8!)n7jnUhmkfT>)<uy$@s2 zl-G%{F?ZH6akCuZU5sP10~|+N@zd;R;qnz>)@1ARPW&`GP4weAD>ge%_%GZKHp>&6 ziOlO}oFA<Hj&d;fS(dMV0G4?gt)CCy;&ii~v1@jx*fcr>e$a9BxV3pyY{rnoW|E)G z`|aSDMgQd!_${$-P0pLmbetL81709DKNrFu3x9kIyhiN5>I-iYeLC~E*>}Rz_}oXc zpT%a`N)zWvT}5}?23HWh?v3!F!g<%iob7ENKfMoTpLPAM4WBADx3-2kU!g}UUWHpY zHlKBZWo~9Fv;O3DlWXri3BF2fDzcvB@jT65d-qKEcF~)(gzpmjD_F1co)-P4YVaiC z=g4{99LG_nH>~q(mW^$l=tVZ>En>f?k+C1|aPfEl4QB17UGpyM%tgluN9V)!9Y=G% zfq6a7+MMt+EOW<n+zmGun+8+h_Kq{%n!}xiulgA7D_reKSZgDT&o^BpwUPPhJa~w+ zF&XC0MI*$1F!gZJ!@|3-fMxwL<>=Q%vi@WaqlPbfLu@YE4o?+7J3GQUcRsrimO9B) ze;3xdlS}?DS|!&mV|}<t@)MQpgm;KumG^aUyXMBF{!uW`(CiqU#ahw4ve=B=1|Q+r z?4kym*AzXwJ1q0a9CJC`RCKctmUSk2ZUZdqj9VX?U*T+`E51V?B=&ZFXfE}T>BIe6 z^ZUidt`E)sB3yeOEbB~U*N5gZkD|LChGlJus@@O3EA~66nda|1Hj~*Sn#<gA@9l5? zx#(YAjlRLL=(@Jte=+(Gf&Pow^WL2J;?k*pvCJbgDngfel$l)}mU$F?d;qNT$mueV zGGp#RKUaJ{dnzn>iw-{-ZX^Dk{pDhFZ+Y}yqHnDS_Y-|Fd+5cQ!(7(Ai|-JdQwm_s zVGeWQVy&_DjK#&z$hEFrsj(>cUi8=HTGy`BShSYfzF2F_wYyNRoxB-ca+q=L>RR+H z^?C6&XA`-0zZLuMUq}B{*tXjuOKk39Oj}fP?DE#)5Vb!Y{TR`0yDe&q&Tj(8ElwBR zw%g)t;r^B2iyXUlTeKD~u-EE5wf$-#b!aZ*T+!khxz_17ihXuz^r50x`wM)p=w)oo zvW82XQiqw|<flcEvoWq;+(+0oqyyv9V!HTo{$=el?XE>%BD(9Bu4AnCaSK_;GOk@+ z$F5<`X|Y@EU4OL>?{8+}mQshVzbz{|o2VW0uI1svB|pGN%eC!0z;%V&khhjHXEQxn zqgtNlbd!4+oF~`LXYXj)R`joT!JUM=42NYOG;7zx{hgj^YU8<8u66B74o%Z>=nsjF zYj?ExX}JUaufnd~@xs5b4!3+u*tI)TnBM`2TYf0)+Ld!cW}A(3wbLWl?ndGBSkqcc z?PXlMdqlsKJh#dgKepXg<sD~UJq@lZx^1`Bkz#+qVE9DQZM&`Ni(bH5*XkU{Zry0r zMD**~7g}8!=(+~pa3H$WUglQDrPUQ;Kalua4HWymFT%QCT>S}rm*~!3=CWBZ9$j*n zarRP&=GV#SF9q$&xhvYrJZkk$pzGS$w?DefWr_b|XA|A`Ji6pl^bJlo1ryMB27Y91 zG!@C`C7c(idDpK?q$W*o)^>j9$>}!EOC-0Mn>cq}a!l&yk`o+9cb$T+HEBP4bx9-9 zx3Pa+(oF1a9xiDqykRb!FYNqxb!;l!hc3Bw@n52Iyx9PBsZY`G6#GvPLVrN~IRB40 zj=r<;$U5ore91V`U)X{!b6otqDcABnkntt6g<bsf#D39j=%0x0{C^>QSSNI;Rq-!t zW~OCRbjhvw|3&QQuurv?+&aCr>^qt4uhC`SG0$`UY%O)0dAvR>Yo^%O6F)bzKD2Hu zY~yTwzGL%wAGlSZ>)gL58@(XVdpnNq`yBncKp!M}#QxHHSfESYW=eiSe@twixe|Wb zu{rPrSZY<`lzlwY_!e}jRngxU`*-g~ms%BF_n?zsN0%I$*UG{{4qHnOO)c(!FAZ{d zspK$vXf?Xz(D}Sna%djp9DAwm-8NU3%G@_ySO+c*=KiHR_a7qWOJ&~?KkX&v`hQ06 z;aK#(!mWCv>)dz#b?z52Mwi|l*pF}=9aau~OrT4BnlFDve<jdg7yHb?=(2uFyYGp< z;X3q>0{c%zKVumBx<LO*c#Q4u_ksSiV>5v@u#K#x&VQS7qL=<1UG{O&k8pZ4qanJ? z_so@JV5v#d`BPZtdu9jY*hXqHD#seqrlqvI;yGAqGP<fY+%3?xCQD62zgG13yTLa( zHjC%LvLCto%{IfG9yNX$UFN%aj(fB=kIS{Yx4|z6zjZsTx!um3Z8KGL7mwEG!p`Um z0$u9Uth9cZ56^KP;4f|?dwOQc+3*gr|L9^^^I7H`_;=B(9dF{x$~rcWlDEq$3BPhE ze7M+HKbIZlI4T+mORXB~=Q6F;q3oNNogMhOK)CW!be-?ckK{J<TTgVE@8U;to7s9E z`t^aIn;mCv{S96BDd$J$`+X0i>t65Tk$o!K-UPiU@H5eIbi*d}Y2wrQDHfYmd(amO zJ3pG+KAc-FTP3>7&w9tvwg=F^aqRMZnbd7miTjkxB)6_#ZKZAvZ_$X`R!RM|JxrMI znu^;VpZaNglISPSMsFx=<7unwKtAW3w#`Mi@wAn7z-*?!Z94~kbR9T`dTZN1@FVMh z*~h-zR`Th_y{+UkD*6oliNMcTxpr)XF7+w>(z)OJUUZrJ;z#CwX7^BZo%=S=ZDsBo zzE3W0D|27`$lN!#&OqNIZMlB^CS3MG6StG~)8)C{fliMOW-hd=E;cql?P@yC<b4V2 ze7Anuoh~*X{{@!$E`IVve~UQVNlm(V+I18^6WM>;4G<gW=SI<Mao^D{sKa)WH&gC1 z^q>ygNgbM3+Mx$^*iP!utQw21b!gY*c2b9#NvzfF7D-!9UnX4G6@86xpDyqw$EGpo zigvq%yWR%>BsMkXn7DoHILbK^E+aP8Z-fsL8|%M)HPI*4gtZQxURU%nrP0p}>~n=} zeYU?i(Azk+zugqK?-J;R!flDOy`GVrf61rm-V*)Jz<#)6^Ybg{vSzxqy}j1tSNEX5 z5ZF%;Zdio=cA(D^KS#fS{$ZdmbsQZ#4E;;d?Rlxa*5qYx!aA?*d9S_9>&&@%u&$Xl z{tnsV=UwiXJNzm2-$D1IM(feFCSNImYm3e1?_sIQXz@U}vG}>&+DlEk{&r~Pbo1@~ z=vtGm-2(Abcm#SsVH<yk>x4f)7QS8B#@}I><0$Vrc%<mgkJjq>tI?kibgk9vmZQHZ zx{H6hV{_$M=<^&){EJ1uh5e$#7h>=HuNA(I^H_(k1N~d!H4V^z6}Iu`ORZ*J*##dU zx{W_yYqe)BSoR>7pM0rR)8``eQ&a!>TB~P0ir!Ro8-IQa$C3SPLVmum&3}GZ;V#s3 z{*_{H<Ik75pBY0v=MN6_p<<s!eda$Xx{H65=(kTnmo?L!xAR|gx|w<@`Ws^J{LB7s zrdL6q8|Vv!mkdGwT-e3GTKJ@E(6>5v`On`e`eDbR{~~PtU!D=0x);E@emY&(&!@T1 zy1a(i+t)-c*SY^x892!2<(ki#YtSzY{L9>r9%CQ8yhEVt+@HtVd-)ZCF8Pd3;r`-s z$!BEG=a)-9O^f#M!-4%6$EJ|_zkFPvk9QocI12r(K%Xi0S2RYK`7Zut4>BwEqH9gM zJjnVPb?uC<HR<%9#Q*6$AM2<!Y4wg}q%A&29(N4Z&yI3NGUtAX9;}}oW&O;&uo3+% z@oD?pQPxk>?0mSj_;mi;i_IC8(R&1XU*WG<&pXQA?dredt)fqh(eIIKo&N_M8(t2K zJ3cKo&i`M<=E5`4Ukh}d<Lg=fJI)UDd1AjM2mO;kU+LJayAFM`*tmALi~h*t==)Op zPLb$Scn;I4VxU)X9M$Li+)3-u#@XpOvHzwRt{>P-9h$xDvz??4-S~FWIy^H%?-bZ~ z7e7z2_jS5D(61N$6W0GucLe&~j-%zJ(4`K=zt-Wcz0qZDbouWzQLcUQ9rS5|pJK;m zU3K(Dfxb-iVYSh9A9wwgI?UW$fG%|??MfYHHhya2&ZSd7on<aZm48J)G|-O}|FdsK zKQYiXhwoNHKga3Lf9ED*b7E_BIsdqRb=JM6@J{sJfgj0XG>IDSd~@JOb69yE`a^;J zqr&!ck)59l^q1t?W1c~u9O&<eK6)(r`+=@GJdbs|^9r%C_10N(Xx1%*cLeskh0kR@ z?_yHDODV_Zpl{JD2fF4kkNk8w*6A)kT_lI*A@=t!jRO1g#O5sKdzY4?+x5T8Wsc1+ z55e6;xBFL@UZT%A7rs_>JMLX>avXig_;&eopx-Ne73Y~QnnP#*q|?pvt>}_NH(p&{ z6+d5Rp-T=$e^>1DE<s-?KAoSBg&(F)y6B$b^bKM^uQ~dz!2U<aQTd}y+*RhX^WQZ` z>{qfMb(Og+`eCA<%{tIk=CbH@#LsZ*s%t~XqDxI?wvdOe%>!N6#-{8StkLfIo{h7s ztc_+|Be;K{4;1FRsp76f0$t~IW-YqRYiaj!XA|{jUF!ORu&t}EuLuw29=z-Hz>lnr zCZ97y*TsP@Yh$#o3;NnX-z0wc?zFgTu)lQOBQ`f;-z`gQY`fjc3V+Rgd^gFVi?f@q zjR!Dax=9X2*LnT@#ps$to1bnnucHc95B8UCvPYYS`RF}^c4d!_rg1LqcC*Ch{K&jE z^Up)SUvzul(M@ys%r~&?FUH<?bdx<gnz$Q&OW)Tq7@nit0A8Y84fgN-7zJ-uy%6So zw(dP4Enr;(T|B?K7|cOqOkALQvDFI>5dE}u@Zo9v1xJZq!t=v|lLGxz$I%niXTiCF zexdNOtcL}c2D;{L2lq_{k~f$C0?AwEf=cK&1opQI-+Bo8J%Rp!<LHQs(53do&$CW9 zIh?Btr1sqN?Sj|Ee!zJ2nc~N;Ck5{bcbEw;5q5c4?%141{S=glZr7!P&5k2`ZZG&w zbmvFwkaZ~T9*b`Mbl2QQoVU9l6zH1UmZQ;+4|L7#!lCGAif-HOuDR{>3w*KYw%zWM z+vuwSaF@W3<koEFT;2VeK$qN_&rd}k>h#FISEu`MvAL)%{Fr0+UY+hzlTl$~^q0lP zzE`KaoOuk-&*JXEe%)Q>b#$%mS1_-;>%1OO3Vp5kasASHy_NgW?mDkszqD3akK-Oe zK6^+$%{ZP*^a%3Vqnh|^I|aR#u+4vulO0D__JbP*y6ih<N*VN)qT6_S$i9=={u|s? zbQ@2PLh-YW{jo=o&mLN<wb@U5+!^@STK&sk(H{x)CmfqitYbZ14D?rp*D=3(yc6if zV&8i@dT{>fu}o|>y^St=w|kAg$40R~qC5Idv9Yhw_xQna^yD-X_cX%xHTs^VgfAKg zR~ELf(f6$C*c><lKE|<|Up-F{ec&DFr-^R!)>CpD_2E3(v#IDdZ#`QGU&*@HQ|7+- z(OT_t1o{<XW5=tf<TiSnwX3JjeWy!qqa&@)2LgM^t(kc_y3Bp?FME*bHVa+mzUXhe zYom3nZ#~}&{Cp^U8}|!6KMnLR9h>)0NB=6&zY%`ECi>5T{=4vnolRU=F4YVF<T$#8 zKJu&~*?$Wqx8{)((WO@1dQ~X7HKU$Hms)lAzlF`jPvJZ0TB|lcg_n!ZP21sKf&Z(7 zA83w#ldv7H!rL61=wbL?(d~E@J|uek;qa59JO9rK+vnJYTB}Z<Ecyoak-~R{Z@mhB zUpR;Lr|@Ip)5&e&=Z?*;gW(Or-B-a|9Y=S(2Fn>K!*i^-Q0{%A3-QxS^SPC?Q!mYD zclOO*n$MZ+1-&$%lc=9wnok>NFUe=rqyl`t#ADy{)+<k9nDQp9^WDyuUNYYe@AHj& zT`#fO`O@oVx%MUN=PuFheCc(+=<hRLy+#YWcAs)=y1a#6B)ZK{FTLOC$XeP<*H4?D zUNYaKmaGH4WWF1lpI$QG&E-{KT|aGpdTkQ__OnR6^sMgkvsd(=Z!~dlnd2FopWfvq zh6gyO^_DsA=0)%7qW@YJy|%E8zjr<1BR+#03)}d6OAezpkHW1)xAFIG>p0rg6E1M< z;_uyCY>r@m?=AUs<J(*FIp_p*-GglWy&n|&5$wyoWzCfM$BO@t$#d@sV&md`LwG1- z)O%K-&lUUC*P|~L-NpZz=!-r@UoX0ge~a)m_Qc+jPl;did0S%>_bDwlHvfGpI5v5# zt9^72vhnvhT5OK|39c(_^WUd|<EX=VaIWY!{yws1MtPsWZA7>A*(YD@51{`0=)AV| z*+=Jf`3x-c+Py~BN9J|ra`uHjGOyixuKLKl&e+fWRBvI7{mxeVSG~6}Wjx<vOj*wl z8dJ{m^TyDQ*mD-G;CYcT6+QDA$pe&+Ji?eto=-OBPo6I}rn2X5#vJIG&+b+6e3vl? zdFFH92Ya4i%psoNHKwZPPmDR#Gw0sJJpXLW;mS428&l154P%b*+<^Xj=Dqz#dhTRQ z4bT0JIm+`8V~+OxurbGY<}-TsdqeDB4f1oW=g*8e&hr*yj`zIRm|Dt55!(r#c~5?A z&!-r3qUTn|)bV_kF(-K*ZcJUzPa1Qw=l6`M=b87(pQ3#9fyUJLe3CJzdOp{f2A;1q z<}}Zb8gshxF?`<S49{m6bEfAu#+>E3pD~R*^Pd04o?kWQY|o6>IiAUb{d|l4t69UC zT+hvnInVRe#+>i@9%C->{G2gOJWn^~LeHP_zID$#jcKNQY#C$nJkytpJX4>|J)dXH z#hx!SriEwbNK4N*8`H}3{l@Sf8uxeX)5f&+JlmK{J+CpQjq-7kF_(E}tlN6Nz?gQP z3yf*+nR(H{^DtxbJ&!i#a?eG^bo4yUm`<J-8PnPGT4TC+{?3@L%ExCJ)6Mh2#(i$c zcBX$hV|uFIzn(FLo~grLp078iw`V@j(#JFL^z}T$m@7Ol<GXAv=kT6>=3PI}eD0&a z@&Lx@8nqwL!5E%(Ir{;ljJekHa=z0=ZLY1$cbuqxEpuU@=lRCmpf=YX&1b1qzizNG zHz{9Vi_e34p2BAhl?U><o?AR`G3Hjw{N2#fn8BVW8uNhVO8DmUVh?)0!I+0Ue_+f= z<(ujo^B2#5Hs)c^)aN6X`5Q!TM|s|A%%jS@@5hW*zU3Wb9#g*c1Y^c{o@>nG%7b4t z<_YE7`WW+!@*ULkv&uv8GeP;z!}yMN<)JSdGtu)G#=NKe=L7Y(n2Gbx%)xo852OF{ zJwL9$SBuSE<a~kZcfF#&XNrFJS^E2)mRX|~tIa*f@Od)jdx`T4<q=i%dn2(ok;&Xv z$^w6!XKtf*-JjR7O?1nViEgs?IZlsmvi6qIZw~aE1O4_uzx|)k?+onk4D6jwQ^XTF z-7@Vu-P(EGve(%M65X=b$#J4v_PX>}{7Zi&KMkC{<j1nlPm@5m?Df`xZrSUFfo|FB z%pu|t|CY;|=uw}Cif|U1<XPew71&$$eu@I!ve%~ux@E5~4|L03-x%nY$<Kc|zQj4! z#%ceEbF7Wi{?#?nb3Xq1u#dl^iJtfN{EqVT-X1?mUEyb(x8e8vk{aVTr^f~MNj&@6 zC$;zgXrI*We*Tjh-p~IZvOg^7WA&h4{HEzEzVH0T{42h{J%YSl8RTt_i6(ga4`6Tq zqlsSiI%jM*$M-QVzoDy5#*VdR^bCFU?eadkv|Yw!lJ|qnB=5hjiC*_Q<NLbTo0{ki ztJ_*_ZlcNFrWLxiv3eU5P4PPQ@TO<#;Z5(SH`jWmzf(NlZK8?Z{yy02PnhT}uRjBO zeY}a@_WDHF>-?_IJGvekem^PUK>-&9%<l$yn@mo?4Fm2Q@R)$-r)=l--<vQ0Wj>n+ z`3!T|Kd7G@gZlY<`JvrEI*v1J-gF#i`WzC&44Xq8$5~$g2je)?=ln_&&GP*B;{2oI z_<xblq+elQ{tfw@9prP4&l@q!4)Xb)*Z)C2=lC3w&-Xn42lJWqE9}d^A)g-v`JCtT zMhqVW`JC_de~{04K8NIUzUTj7K9hchefc-!b77FrMLuuDurSEyVz2*$d@k}iB%g~t z{|ED#^egPkzagJXgM5DM^F|CygM2RY`aj6$$3BPTbD8J=U_O(6g?;%q<nz-YpP%`> z5yPiJK0o*RKgj22K8NJ<bI<?5d?x)0`|@wd=gJ_TU;4Ze!^$9^tGxaX^7*CDA^BY8 z`9GM?q+elQ{tfwD8|1UZ=ZzTF2Kij)^?#7h5}!lzxz6){FrP`k!oK_)^0_g{=O&*w zV%QkubF<g~K|VM69Fot?p8tdSO!^h}<^Lj|$$eHuzJtW)f&1m;K8yRft-in9qb2v$ zrw8{7WrO>Rf5s2?$@zId`{cghpKSLJ`T76b<)({2#`nKF&&mG2-}olymVa`5|BxTX zH`xdGYd6{7|H*d$kRRGj_KW@6P4>ZmvfV%Ahjx>7b-#9#{o<c&_Ye7@-DLgQuia!_ z{U_V~Lw;!YN57ua?oYvb^`l?UY4@jpV!ir9e*Qn$?r%P~<oP$B&(rxWYOkLq&jT~H zSWnL3d+*URL*VmO9}73d-e1f6UF~y1XV2>?_8FbC=k;`_TYJ`}<hd5(m^=qQo!|Gh z?b_!>=fl>g<=*^0uGjm+UVkgtr)CBF)RN%2-?HGjAMH-^{i5CE`Q#sMcPPKf>iygo zJd=Eo-!%35!@={(=drgj+dtm>nB)0_AkGCroSy~HAy)>^A$e~{d7p=aVV{S({O+S~ zm%dc+{+kB*Y!&45x*%`21bKTR(4P-<n?vuP*pla{>x1X0n}g@5yniK$vtkhEaY39m zW*_G{L7X;b-!EcF+I=x-_l=-kY9M)j`>)E+_@Ld1LA%p}cB!|p-2;PhNott>9_ag0 zJLp%(V14TWdz&kRwXT1#zS%MI`M*6F7y6#$huD&Fp{|nW+tgJOC*zXD$+#qORuAIj zeKSe^+XQjin0=hYoUF;cgE;RF>>mv5p9t)E-kz-6w&s1m?3}g!?cd5E{xw1TjBgS@ z^`FH5ugbHH*^lGsAb#pF=`VGd#Q#U<1@Ry1{qGn5p+2|&L+T`nbH6%C;`|?8CrSMO z9eMumuap0JpE{r4`ttQ-*GbQ<(0%>13FhxDCa&RahQi)vw26<hy8UB5+CAO<J<o4P zd8W>j*Vo>{-p@_m%X_qE>OYw;%-Ljp*c{B4ZRvdBHN<4TXUeAY-M)tSwziu&>~HqF z|N5NpugU}KPZGcFi_Z^hPBP!ur}3K|!8-h1x(@$Mze=V3vge%t^1MO($J_qev(0|v zXx|Uy^!>)MmbYgdYk3>S@dQ6!`;B95ukSaGC-|{r9BX_2502x%BoF`H<4CP0=hcdT zb6!nfPd_VoJ)QYj*XN&ctn2gKgWpi``jxQPZ{c-4tJ`|GJ$Q}p`M`dBU_ULW!#Qak znkDJ{GK^`mpZ*)-PhN*2{^T{ae^vaf2{-xta8^mqmd6F}_oyG7GtUanndb-R%#OjD z$yg-koV$a3vbHDh8<`mBoV5~tbCBn4L7smM&MkX`bIX5s{Ii01sE1_SsfXkoNIfLy z!2RM$&Qx`Se4ZZU>YU(wNIsLi^$*t18-w+e8c5d9p~3q3V35y;gM2c7|Ij(`KNbJ; zL4U^w{iQaN{!R<}`~O%c$r<J!j7xGJ`yV(i|F-!5yT|3MVEsQoSpQj1&hzUz>&bb3 zJ-?CfI`{hRu-AX&d(6GQ7gn7!PuxWH4C`AHuh&lJONJWo>raOHc%ipv+%NR@>^n`p z-X8XPk92-zdI#$RXOASF=4m`;0pA7e<6H)-AG1EN-;vs9ZZUDLZ+9r{?Ry9I{Zo6+ zQE9t2CqB;O_}*CWr!MUE`vU(Dr~WhB_+C_RkI#$MJ}S$1H>)01hP_UlExb;gExi6< z>L(f<_#qFzUlDom{fagRI_-Mhv<mvwChgbX<c({S{+^ZEXBfvs@0iwArbk*=nH%}u zVc%ckzsTq3ne?2Hc`-dFWcH?d6s0;jN!Huw;GiCCZL5F#e!Q{j-`E(ueq|buxi6@5 z#>LlphMfDlvfrbZ^o#x`b$)(O=dFS|Zxhrx?Iv~JJE-&P(tg?6^XI4x<CxSx<CxSx z>x184$WOXIHcjKCze$|`H}&5t7?)N)Z^Z2LVEPCCshLFoG1W82{r&n+{F7(z{~y)= zB^r;d|4V$GldC^k|Gr&Y|Gr&Y|A|gtyl%Sk9eln{=x-aJhtGn#S`*Y2*CzJVs<+SB z8u0mSpVosZ#pma}|BAsmkQ(de+d3?GR(y2utoXR#*>&yUxio8O@*I`Vf7$oGW_EE7 zrydG?TkZAPwbkikfp2R`a7J1doKZhBaT$N@%HX_2-*2+l+H?MTY}AjPFaG(h-3$D4 z(ag#;Z<+OJ-ZIooZ2jXW^IPgas-3nQF_-<BIck%(6?IHwh?rkKhKTX%u0Eq1VU05y zYNA`UFVWqw#vDyFaSyM*0egK8pT+h12e8){@V0RD%u@d4b0`tIWAaew?YF_+o<90# z=@GTzpP9#HO<YOsV``w1+Q-$?IUXOK&hfZ@T1zqexZgwLR_R(4lOMn5#@D55PD~#B z-WuN*_~#ru(YO0dy5__$rfW{jnb4oT<7vU!oA{IS_QAoq`ncd(0egM&+63d`$J*SI zj<vZvc!qEvY~!(YMQq74jnTmwbr#PJY~HL5<KmwoM6~74uF>h~*)?jKJ{O9br_UK8 z^5&l{P*=$_BI+vk&lV!)h<~;aJz=6J{rEl)`|+I>)aM65O)fEU6>q-`_V#Ox{S2-9 zv+GZ9uYYIagS}489IQGyOV)g9CLJ$Z8)_eu^JE;UjbyyeNym#X_fO)dPLlZJj%nWF z9%<eTekQ1YUN4KU^n8Bse4r`1#%XR$>(k!*`}$;^N!CES|0d53dIvUFrhA{=U#{|P zT^Gba4PWKkx+REVXc}8)e43NY#55=NER@7a-6sAk20oczKA(pA@%gj^74f;IHsb)= zcU%dk{w%j$0rMFf%a`?q`EQmlErF{j7r|APTf^0aTTg;(C>Ovrl^ejdltEKR_>zrq zJ>gc1VC-yLe0R7p4TW3IfEx?9cnZ!H?y?GQqMQfw|MuDf;x#RVyN-p4&+1)>*R&Px zTmt7S4~IJociI9MD35^)mHWYcm5Iynzpc+s)!+fb9kXEKw)*80;6cLqyWzpY9hSpG zgs-Rq4-@W-W{AUHdsQAhLTy&SBh`j}m{H1A;W5H}is7e}YrtcL`8>BV<COW=6e$xg zzk%f1;`8XnOcL(Z7@i_rxDlSJTnC;Z+_OAfEIhCUJXiR7Y|VV(8;8J)gm0(>6Nl~B z_4LmyS8ffj5Wa2?yh=GAE>X^biNjudE&ttYQ7(eFE02J82@e<u?^dn`<JVq$O(DEb zxPKG&HvXs8hxCK9gzq30J`dvbp=06l!gtn#E2$0bW~wL;fU7F=Z-(})&)WyVHI!?? zHHB}Z{S5!x+T1oDuA@8wrVXnP9tAg0ZVWdRzI7PP|F$-_6vDZ}BPYR4lxaVcC;ae6 zxP|av2Ewg{AKDJLRh|OpD|d$Zf9wCj8E}DeKbZEMPMev&%H?7Ho7ErK1rHD&u>z(& ztB)80lMBoD+x`v~zOM+TjW-#D^44cDI-I>6o~um1GhAc!?)b|rGVv#N(D>tA5-<0> zO8pd|mxz5S+ei9uuPsHtGh2lFO@R6CkHpWez|TJQGZtIgu-Do%jXeihF5Q=ZbA*Rk zt$gYy;`<tWJW)0EQ;bawu`h!b)fCPd!oRhIN9FNvoxo4Mz)xfGQ?4F1xnf^_KL0im zE;ELI?e&_6sD<$KeEw}6_@U1(&o$5|iOoSX_?NM_*B-Eff2Rt!r_E?a5KnR7XOYHJ zgw0a1KV$^|GG^A#fus1>`hqJC=HFGqvv>1vN#JL@#xn$cm)IP>k$<fn*B&~SfA<LA zWc7V%Jh4gr#N{=fe8fs(AK^Q$qC6a~Ds0!|xSH@xVvcJBe(I<n;)&~tO*{r}pv=Ga z$AE2YcI}B93%^?o=LUXSs2_3@w-%c$#wu>BeoA0swSKBsfjbM&tpyhZe)_4OJ?I0} z&n|eNvW<U`a2@M&u<!@?i-)9ssGE44jXB4da`eI0Ko;$n%Qf+*R_Cu=o{499CT3SB zCFp!#TXHRa-L>1%`v%tz2(Bd_cdfM{hUD5|qGuPPj|{HmdvKC=$Lh88w_H(h?F7Ac z75dcR+T!5a`C?=5$I2}Yu3avAsTJrY!L?h0YssmNxk4pu_5|1N6TLKJT|OthwtS`Z z+VWNP+G^O;NUtqlQ}mqO==FkY8;V|@+_K&!`6=H-^fLTgzI9-qulD4#d_iDesP<#f z2L$$m)P4{8kidSJ+S|U24D7ky^*sxHY+yf5^s>}K`ALEORJA8p<%<LRxoTgGzBI63 zq4qXEB_@8&)>sa_QS>avygV_v7;3?+$%&1QOExuIo;)Ttj8S5vW0XyeRKT^jp$-z8 z3bbeSQjM`GuQvE(yi=PhqL<D^uc|g};c9_R4bgL2px0EJfpD$BrjF=YOVR6@xY+iW zzX}b~Tvcc&Hl>E4H&H*MVEiWW^SyF@?o`MZz4Qod3e{#T+%K>n7}yUIJ!cFywBdYC zfVn>LKPreBJC~oS*znytNzBxP&vS)wVpDo9Hq6b$W<p>yNo;a#->0NDd^R?{C#oFW z2XPOQ+<)17u`HJ=W1m$f_hJtR_cd<>_b+b+_b=Qtj`jCb6=Cn^Z}0C?|K|s<`8E$; z^W~l^dG9^<cgg$h7X<NepPSrg@jN8C*V`8KYj1Er_*;4pXg`bX@4tACl-_^+3*%4T zdr$ny`^o<o#h-kpkN6kbab)h=XS_*0{14B6^4@sjU;4i={^ULO#GkxB|9?^bllROM z|JwhB`QK>QF<bM*zwzG~f3gm<E+y;maVEaU$5R*f@tkGi4qj(1?cnw19BchL+zPh3 z{j+Ph*PjU1&%d|s@!Twl=gJ@+o}1P6et1?^*Zb#LW%3z~@xkXD-!k#N-hLYF?Rlnp zpVybbUf;oY$6MXz|2x>~mVY$y{oejJSnV_QO+3Qt<++zUJ<Umm{EV<RR_D3m1A1+S zXNeE^Ysr<*Tjstr&-QgOpXbaQChqUAeM?^Nh>P$^U;2ALe0QIHufEf_rTbBa_><S# zel*c|?}xo<yk5)eiSdJ~M@Pe6C(ehw-U{~m-Rby7#OcR3BF;|Uo}715`}nXl9-i|j z@z`g%KAyOC8c$3u`FQLze;<#1wx8&?2l~T-|IvZ}IcdGc3(|Uv89QHxS*21vi#WSz z{8_}=MdQ!ndHYtcb5_~vb)FB8^Lq1if6r=flKnlaBkb*mns}tQXRJqh{fRXGtmo7C zv&f-8S7gl!^bZ1kNuV?CcYFVg``zk4n|^gxJ)3@YR^6V*l6g@vm>1+WnHP+8GA|hG zWL}WxWL``R<^?hPd0{rE^TH5YvR3R!=Y^eLZtm2O`Q_#d%=<Ib`N9|_bA*_axnrNt zYrmLN$$FJ(9?YZm!92P#m`C(6nLFhC0`KR=^tD}HTS@fjtU$-79~b)?il1K*=SE-8 z_BFU<em#@cZ8Scu+sNj@wo88_^5ECl=tp!rMpoaO#vdP?&O2T^OXi)OFMeF&rs=rY z*U0>QjEOm!kJHjP<2h-Z@yayLn6dNoE~{dihb&^az}Icv^gRYyr>E~R$RhtfKUuBP z{A69nV-U@A)-AC2^Kf8Ku6#bT7NqfHElcCcCI&x$v&qAi>L;6ceEnw=Pg4Jkk)PMu zJ<@rd-QOhhH2XT(`*|>(r`e;^d78Z~jWheZG|p1gr~7UwhOAUYSpAeDHlK%5M+f$` z)A?AcelQ<PrS)vW{TKVXnm2=eUG;BYH%!j?ql0t)6DGde+drfG#YTdo&ad{@j@SLd z>a$Gzu($sJ_BPvs_qcu+yvOyobltG?)bFR<*CgvkhB5N%hTRi=ecC<IuN!tx^!usZ z6aBi8p*E8J^!9Y!$PCqaVfWL!gY|*&O4fvjgSBE=I;S$9rSr(X$ELsbm)GLm`v+p4 zG1&Lp_%(soy=6bO`q5%z)57cZPIufY9p9*ZI=-w4={nFgonNdE$^I1)zn@=rO?XJ- zv3qE;&r)yx9A(!Bzt7rrAeq;P1@oF*`Fe}-@8^+y9o(-=F*W1YrTE1(o|txhJb$we ztPk`b1OMdE`_DQqosaC5$$ZS}5$IP2`ZIw}41WG*eUQ$(tR?BZ%UT)izng>omztcY zdCTH#Gg0d{yHq;AvMZ+Z%kG0dKXxDV@n@eEtPkf0>qE!Dp1vgZtQ-D3kbPqsPxgbs z`ZGFMe`W=K=wsrC`b^?knd+38dnUZQvn6Go3mKkeJ+IG^IFH7aJoCDP|IT4vhfQs& zn)m>3!}BZu9mVV`@n5~pk<mY2vi@K2I?u#j^o*aEJli9tWqTgR{$;Pji9NB6_d2m9 zj7@2;W0T_<n^Qg0u6wSId)t>%UMK$KTH-&=>ora6znhoWk<)(h%q_8RVB(CoZ)oCd z&y9Jc?>X1R{`-Du`EPRaink%QB>&{Ze;25=4|C$b7u4n_vH5#BsbnJeJ*(2+C>a;7 z_1`H<uA`@X4CPG}j8XKo*Q=PwegCTUQ`JQN`%7(X{@I<4XOg!kp4UC^7ylbx$3C$k z2KT+M);}>MV@*zy@%`HvQay|B`tv^VGsQE0ws<BF?)zY^fBa1II(>P_b2SsWzF3?6 z`W5((6aTb3(_c%w{`CbL|2D7h*Y3Msr(O3ww6-PMo$mGh+O^M1-5>c3+ntl@k^eqe z+wRw1->==dUZ-96owwF0?fU1d{I9<m$G5ya{Yv^sf9D1Ie9yGI-Sd9!e&}`Db>FY6 z?Y{5z{n~xo>-)94DA4`))7t)i<MsX8_1{}-YxNOtLw^@|-ml%MUf-|Xj{|*~XWHH2 zdB1i)@jC7L?+3Pd{>bb5wd=nV(yq7R_<rW?iRW|Aw7b*ue(kRCI_>)JBDU==_xgVA zCiTBxyI*>H+Fj+Dc6WK+uie#Nr(OTO$F|)syuM$%NuBT4Zi%<2-F2R6_gl~VwY%Qy zwEMVc+Fj#$zjkMMeZO`$rFyj4GwpuodB1kQ@;dGM?{l{O-Qe~8+D+z8*e*8VdY-Ha z`{}d2Pu9tBzTe?>;&guOoFY#DJ<@i48{%z<bEs$H{Ilm8CK~3srit$IT+2jvd#+=m zdpy@O(QwZVOmwg3h9<htb7K?T?>W~*BRn@T(F30M%TKa)k)LFZ+Aj~uT0tHX8|vgX z?~^>d<oR#+i*%1*KTY-#_WFct1Y9%VS^?Jyn0-IFmVG~A_Wgv}_Y=+yxJkhD<pUox zec9ugzWm^sF&*f6zq|$OaGb2e``ILGFaDEthISKs^nKnx?f&AK94_#T&vBOZJhss5 z*d%N6erJ`?K3S`=Px_1fi{20MBz~xYgT2m~t+MAZ4_uqrGmZy&n;ItmlV^OM;2EE_ zJ>#>X=g=qTz&c*X|8bu2nfR$`;<LO?ZJgnmdPr=jhZDWt(8R}jrXJ4poNMCKJrifL zPcasIz0O$t?3p-k@XT1a^NEf{vZv6;WK6LM^S{(zOa7C+j6P2A`hNDw9*2Dr8}{LN zC4OkPn)gF)t9lM&=Gw%b@jBew)G+ZOp2@>ep7D9KXMCRRIrPbR)$}_4t9!<0;)n4% z*XxW|W6z9NV#9bH<MoCnKEgBOb&ls;6F2hAV*$J7#Dkd+RZQkyuUBPyc&-`fwbI{k z;r*qleM6J{o(u0IP4zt97vlZ24fK4D#9l89^uE0Q?e)QdKEx!y|HAt@Q~x8=--6*i znW;X3?Zf+-8t609--zKomZ|-s^!H+TFJ-E)N`E_s_bsLRcGBhj?+NsM>2J#L9>~Pr zz6a8;1H9KU)vKkyHIu0o=ykXyQU95Sf!;X%4I18~nEGjv{vHkQMNIY1>2K5Up2Jk{ z$5Gk)9~9_=)8DMg3=i}Xyx+>(j|udr(%-Vl6b1SO9>se5sewMjB)@UP`x4W57MbMt zZZazZeU(Xm`-b-)ruN%;JGA$|C(!qq<Tr76KVf1YRWZr$<M4jMRIi!-R!+q4Px<<f z8t@it^&jO1dXw}wba;PYYTq{fJ)Ni^&<joS+d9#ZKp)22w!Qz6fzC6Fle`|}Ga{dL zy&mL~_ZcR?#lw3D(|A^x<ac>^KVPczZ0;2G6KAD*%=%m3>-@Hq&jauAOMbhD_wuDW z^Syz$ZxQIN)8F)ogLxe@ul*ho4-4#vo8-5C;&Fjql>Y8dJU7tio8&iu;*Ej6#U#H6 zl$Dk0Sve;8ZJ?~0fnLibzY~<zB+&EH-wets4D`O~?+0ZK3-sZ<g<kWJH7?MLO!B)z zS#tw@zDa&#C~IS&Z%Kb|C_5|FvvYV`zWUFu8R)gr-yzCw66kq+)rPk(4D`O~?-OMY z3-sZ<)!*BX3-ltB{BBY9+(4htN5;JU#z5ba{+>~(tW+<R!^a2IzEm*pN-^(Rdc9#_ z-`FI-c~mOcFG{grT;lEf1@;5d-$E)iJkUp^zl&6AY@m-ze<P{Xj6g3=e=n(2Fpune zAKUtNcLnyl)8A1los;UN%csAoRJvxM*Ghk1sdVE&&*h^N>c4b;pm$Dxcd7J%Kp$w5 z-(ccBZOMEr%|6)4`xzJLMSL8?>&1aS*CfBwRC-0AuS$Qjsr2qZ-;@4+Q%?C*HO zS`B|WwF144>cpGVB+&Cz--2Ec=!GWv9jKgO-_IGs$3`^%oKb=OnDqCdawY}(l=Qcv za^?s6B9r`XRL;ggCyu_}|Grc&Lw~MNy-bxruPX7|_xP8o6X^ByH>bF+OfbG>a?{_U zD$_ZzFW_S@-hWWfWvFMT=inz8-!hDEguVSNVVR=9&jkHVE8A|cFO->){?=8QV0_Ck zzSsD6_XK|S@zERA%Lesaw!G@ZQ#KgivUT)#vS_z#!_-gN#_8{8mCX<I&gpMyl^qo5 zgZV6rZ+Cd0k5JvV8}zp<{q^^cWv2%AGgP<sD*}C0`ukjE_XPSreosr=Ef@5+9Q}1V ze#!;?Ek}QE^7ai=Kjj*yzw=eDZJ_7#ktJ_m80dXfxBiC&`Y`=nF!ITJypwrdZdCev zVdW+S`Xv4BFl#>}(2LXG6e}0xp&WU*)yEUmIo(ZuYmE0`C+(K6DfJc&=bWA!=uK4L zj-DUrokh3r_b)#v&<Cr|eC55<sek%q>p3n#59V)q=C9S+lMSEKNbMJ?J_3D9pc99) z-^G0c)5D)zDrEg1rp^XV%Q5@oPc_w4Q%yD1^n$4dQ+k;cg)k|KMkYp5$wU|wA%v_D zLTqfv3WF$wP_!!yLTCxujm>U$+uiK8yZu+Yo85Nz|NULp?|GhUJ|7?7esk_~opYW0 zoaerud0wL4d^mcNSKD&yThNod+OnSf=zT72>k>aRtg}wr`H8+D>Uuv*+lEA69(BFv zrEO!PZ?HZeeS4zsh`Qd}(k_$N+j0C|u2;L_L@%+<`O~f}(aWtDqgN&RXn$uMb#7Oa z=(X16r!LWFSeKvqiN3(!Hzz+y9osFjE<X*4{qp?x)3s|%^bMK#U3K!aInk-dV&yA8 z+Y^0<b>eBC$?NS4{5^LZ(mvUr_Uz9+_S3#Bu`kbmFJAkqL?7+%$djLBf7-J@_h$Xn zCH6C{E1vm@z99eodhJ&x`l|eQ?X};M=v(vOyN9dXd0SkN{|>(5<ng7rGXH&i#Yx{4 z(|1dKo)j-g{4C6WPhausL|>E1eP>_swnX3V^N>C*PUb@g_C<ZsrjGmOo_YHYWl^U` zGaW`GdR6{=06WZ1^f~$O1njUZ(Ho*4z1OKjW1??}y53jSA$h#+urul%)^opJkhkwx z7<IjWs$+SgS43U!)#^Al(W|4b_g;0ZPxP5l??zl5lgHnVi=(dhSanSHvm^Vd{n2}o zI&Mq+Y>#>$;^|bF*E<zOy<!CV&_riW$xnZd>og<L>ob{Et}ow@o;y!E5zlj3eN&=u z&VR3Br)1wcdEXA5!SfbLJSC2280(ZI=UYi-jAsP<QIhmUNo~|e&PJb;U$<m#)K8d$ zzBJL7MSUE<FG=>N#QUT7%9ZR*?Ds|ciK}@YB{{D;S4Dj~{yQh<f9I*z$**&AUUhDW zy56hUd0pOrc+VdDHmeMMUtZ@cNyGkMO?|tRC3<<(uVMWzNnN_IU#i!F0`$d+J@uA; z`vUZ&-@9-gOV@i9yB6f_yB0?M!A<C+6CFF*H*7~=kmw8Z-<8>QWulX(>{sl;erKZZ ziuwyBJfBpN*Gv0nGVfuppVG03UY-BW&C>crpP9*Q%-SzZ^hNpa;w)X6=&LfB?DOrV z8xws~{yRELcP9F-OlFh)cPq^6-HP(x-Px@?(JS)b<Jqk)(PzYbU*Y%N<|X?4sK3hj z(=9nayZQWF*NDC*v0oSMf6DsZHYfU)sO$Zqyd5{!kKH*BwEucvWcSKM9~yPN&#`+F zXLrY`_jPtp&Y$i}qP^bF*u63Fvmxqwe`5FDiO%s~df$2^^Q6b{{P&smNcyzL+~{ZH zVxAXVp7+yZWz;_+{vI0=ePh%&E#>*bg1p|dFzQ=s(UWz1vaa^wt6k`|iT$Lg|8g(- zl0?U^?0>rkeSM;{U()q@o}OD0eXDi$Nw4=?=iD>pTvuheipS<G*X5rN%*@L_7pM32 z56arGx7p{W^j`Sf-$DMK$qcuR-nX9pdq<OQ*7;uLCPVYjM>RRxdL=sfW}jnkGTr(q z=){nH-oD8#)`_tR@nrul(Bx_BH=q++_IdjzKeJBlcrG;eeb!C>&-x4OO;P^&sHUB* zH=+~MNaxb@2<v=Tb5rVfTvk8J`fl{O`RAjW-Wc^JT!1xQmVZ8~>66yW&{^a7te+38 zAB(;t|9n)_KU=Tix}WoBjP09ok)eHVaw&TM{PR)G4zoTVonubS+Mj9tQS>?a=cAfk zZ+$g7=he8Z{bSZYL0?ZyS$&%sAI<ie+1G-e`FsC@;ZfK9e!)ol*$%UB7u!$4%=|rm z0pH6Ua^XBGSe(DdFIbtsuP@+xsAZ$~#}{m}|IIMRTw<R*2blY=>gH{2U&?#?EAsd6 z%?DerM6b@@zc-(ezh`eg%Qj=NS(v|PZ{Co<PjBw?t!W)L8}j$*&3(S<Txh;Cf1j?G z4~Bd8LhhGZ*+04JIlb(?x!x}tST@JoW+luT*}wg@xX^kd`hxuZc#CEEd+-)M$Ml}~ z7T9I)!S%dcVEO;Xes;rq^Y`5?i}Ux|E#0%tn)4Y1L-Y6AE!nqgwCDI~d3yAt_q(^8 znZLhoNo?0<ZSJzo0Bp!7dr#fcHEqT@-*R*Qp1S3iwx5VjY&!RJPhH447MPkB4v(yR z=R(di={kQ4=bE>}?1^;U7Z<KGFM_w3$-QuIWZm<I&q}~vp9RsXD(bqoZ8gKpx~+&q zK6MY<YE@+2x3(gF>4o#*J(1<Fb!q;dv~^|vKD71N{Jm%E3C?#m_A~SMo~_x#yYZ=g zZcQ$Mi(%Kd8L_l(%->`398UaxbJ_3C-%Gas-u@f7Cn?F_OX~TV?EPaK_9!s^+nj9s zb#Q(Dp0N$NW$zQ)EY05=wt39<o3US?zc*~dK4$L++w98U1Gf3Q?RWCL1nXsAmsRBR zjqS`7jmX~v7O^MyX&<Ds5BF!;`%qAU&e{)Tb)P?~ds~iKYMu8-=e~!X=PPpebZr;A zUgXsF!5CY?Y<Nx7+hE)Fb?bM-?6YdE`?$8>SYH9}%iqVfqh~a)3b1K6G=Cr0&X0G^ zi_m98Ke~@=H!IpVKOS~Gx{qt;c$%LNuZ#A&k8Agq?Qem%MP2uC?S5yS`NTs{h*Q_^ z?LBjve-5)>ieL9}?L7~9pFyU5b=12x!0zi7J>fY~*L_@jKVGyL122oZ?&I1&8P{!r zZTrnp*L_@j*P_KX?vW|1*42GnF@@3ov@C~*MqT%D#oiyylH&UO{aW#5w*M4;RsMdh zcx}`RNw%21mVe!^6=Ns=g+1WiQP=%i@%K@0Mcy4sqpth44!xq@n!GwxMP2u69ZrmT zo3mh!mw(-_b#OdISHP~9?$<iFUTtrOsh{k1zt&-&c{P_{&7;q@@57^`u6s1@se}FW zov{7uJmTIt=(;cKxFzzeGWhH0r`;&-e|tt<_hOw6w0<KzHtM<;>omdo<FI4ay;vv5 z+>ZV4v?1E-UaZs4qJ8`0x!){`y6(kFI$Ou4#CxTCu@di9`)^@>r`#LxS#npjFXs0p z8}s*KC7)V<8hv-P*S%PYYgGIy_nSkbu6wc0J~ujafZ6Npy;x`RRIOE$&JFo{vCjAn z`pxL9o4pt7>~%Zbht9emaIAhhd)*EzxDVyr$li-}>197ZL9fc+i*+HN;Qu4^`ux3E z7vcyy_2E7@^RfMR@jiF>EBfY`m+rZ`d>QRK@_5&Uc(iZ2=j!5kI&zM6EsnbGxw>|< zJ-)kEMqT$@U5~K-99$E1-E(z4(>gWczBu^TJy%!PrQ;5GUDV%{|F>+<Ioowt)OF9* z_3u&dL@i3oqON<c(!SRF!?jV@Jy$6`qkZT!8eW*c=PJF&I&qb5$=`F8`h4#63+^A; zf9-?rxw`d=_9dK$-JF;1xw<*8lI!6)(O&ml-T1fGEqM@jUb^S%_Lg<>>gK$3&(+O& zb*66Ji=!Xib9L_)?K`ti-JO^2xw<>A&VPpIM|<6Kbzf#)k_kVB#1MW8m_y<c{_Di` zL00c-=J%O{c+Ae~{mjyj;Bh6ZA8jr|XHSDJ9%~*7PfF~GDcES;a}&P6T#9~4!k3%N z(XUCE{S1EOe-Sf18xOS!T!{Wa!Vj6(pg)_~zhEXV-U}9w9S*;3u7~N(;Ij(;!dwe) zGcSO*n;T$ysbe;t@65!*`^7SytT*A}J23m%q%&p6>eM%|^a}bvtM@m{&r$SYR_8i3 zu<Xav4_W<Gv-Ihl(^>sIv;55AJj?2H&9c9Z^Cqj`X_o%u<TXf-n5EO(xz`}QXqNxR z<TXee%+fzkUV}tmh1VlV|9$crq(7SF|NG=MNdGaT>mE7#dO2Pr6j}NK`PU#d?PHdH zX#O=wyuUTR9!WYqoP7;aQ|4!2>72LO*GV?z{0K~(O*wCK%y}DlEc(@n{dH#Q#`|HT z4d)f_eaqY5m%NtgL9^CfnY@;1m09|0$!nS3G)w<Dc`egtX6fG~uVwn3S^A#*^C$Xj zvGBT3<@LWjH*03D=N^Xn5NtTLn=u~(m%{re+}m7*&g=~~)$jl_`=`$e8{qS*8FqnL zx7nD4$C=ryW>XUTv(41G8S`Oa)(`U`FnKk*G5=gpvs=vazbIkmLwLSuIeJ54&%c9S zfzEu$G4mlXKAJHfDzob{9|Ft&2MPbotoXl9?7uO~|L)|qThwB(e9F(i6Q&kH$4^1~ zynO++2s(avpMLJOUc3)6GJXo!^Y9ul@nEz3j7;n~=Yx&>Fw2HGFMTFjU>(bz=a_Ro zu>4$+*mKSYU4A&Xhi3iUVV0kJ66Tx_HuCdiV*j*Re%9q*dseXCEI;og{JvR!m?4K{ z*ZrlL^Q3?ol6^j~;4kJP^uH&}Y>`cq{@i1?%G>L?nsBW2l7vgmL(vaNxQ}@>I**m% zSn)vfO87AIYWN8A4wzmD_Pbz?3A_)c7jk?`WWD~hIoD*;15Y-Wp-)fvJhS4T6PdFt z(|oR3`V9%+Y_374c41xip7(V|ZiJ~_(8bKFz>2vc;pLG-Z1hnsPWmWt8TRy1I5q>* zM}f62eH2*h(nrBw`EE>66^jVEYm9pUg|)znQhq|1irZj~&4$^=!fZ1!f;w6x(JJ z%<n=Bb#RY_v$dX$POk+UakkbCFufLZ)@_lkHS6j*w6In=TxHg})N~ke=%>YLX3p~# z)HLYgY36k>b1!Gl+zVWReoew$7X@ARi}KHPw^(eJ&j%8I$jrXApkCSM##>OY!1Dh} z!ap_Fp}%FG3BPORTx&tSvhPRG^Lv4{?ynR6tyyt?m)QT)tabmJ=ax<L_ANW)pObId z*^K{|Jrgc7lUK{i#D1t5|1FP7_*gS}wLHO0UM){DlUK_#^UwLWJj<+gXCz#2Ca;!r z6Z?5)txK<kza5BgOYHB@|Lve9*IME42=f0}!pzK|E3dVQ{ZGvD*_iMKv-0}Lth_!k zE3aSW|2EO`H)gH-ZNh&xD=+#e`?n0;Lj-2sLXOFCQQlt9cVyr1P)HvI#<q|?$}xQu zn7j&)Oze*_%m48SpJ*np!WuJq71o-`tMJ_X-%tuKFl$}<sEWAtm|I961tzb;n-Y5- z%Yv?T?@E}*vYdTGCil0P!sTZ9q>sYiXvFkUVCD5@V*id={y$9kW3%%5!mPZ$G%K&2 z`M>oP?lNmF`slc9Ui495@@myGZ{MnonRQ!rOt?#8e_;M^My>jq@!yI*8fE{jhMLK% z)#${2tXck<Z^2&7d<#rot(b3t$*UFfEiietnw9^XRIAI(T6b>3^ig;nwenh&*fZaP zuC<tNIcC1)?4Qa1ZL8JuX8EU&j?d;r9|cxkJRSw+RB6TIQDFJslJHiu@?yRP8|B4( z3#`0&JUT)C`Dw-DQDCi0A7xqh*@4NcHS;ZN-<tUrm~~q--*Q}**bmD84X*VNGyYrC zN8xXCV)`gBd9@y&*q>^af96}T5i{Qc*TKxUz~t4s-b`MtujV%2d9}XIthMN)po{6F zz{-pHma}KR1=d=RCCq%w*{{j}t&rD<#=jfNCw&zDhA5_w0xPf26Z>D7<)8T$Y{bmB zz{-pH7Fc;P-vTSIefhsd(k}6J@~qW{J~~PHiupxg;%dWu3(T+DFy8{RRvYG9j+t*c z`y=vy(`<9JSw88baasRk&E(Z)Qer>VEdR{6U@vCA1tzaH%(uYg)rR>Nn7rEDn903{ zzs)UXt-B~;`lwnlux6Wv#Gd&UbY?&s=39=LZ-J}P-^jlgpv~K6`KOOg&gMlQ1s;z6 zbz=XGS-I@azjvU`9<%)XJK_JCiL<DE-oB`lnK+BOC%nIzIEx14--A#z*o^-oVmiff z>Tf-P(TX@GFx$fC5=SP^qO<ewStz0wHQ8e?N|;&%U2*;(v8P9Zt~hT`_%5^JT$X?D zLlL!@koCVJVQLX{#raxdPmcs$aekbCuSC&jX64Ic%BfkO)FQCrq!$7!-~Tf!&b<lK zBf*9^+tLfC$qzqmsYPJ?x8*S<$J8P)akixwa`pqw#Mzc!sLlErX_lX{3A0|XA<nk+ zLe9R<Oq^}$g`kTsHY?6+^Y8U&OD#@!?rrIX98-(Hiu1w5{$aD?T$O)sNZZwB#rbN& z)MBFiE6$G+`%lb@?dJ)9WmcTu=HFw|mRg*Vjgwx;@m@1=wqxy}vs}9(GjX<KE=|(0 z(wR$vv2Dj($}zPFOq}hGOze*_6KA{Q6F$*Qob5Q~%&dQE5m^4|g&b3hz>1T{i=6#+ zX2p3&{=G2m?l#NMeF;;G$==U)Pbc=znHA@ngx8rB=ll8h)U=}(;r%u8PcP({S_D>{ zzfbJ{XjYux=ih_V?muSy=rzpYy*Xn33(VfMFU{Mx?`bB^_I(mQ*i4-556{1sr#-be z%XM!*GGS^FbmG+CLjzOa_Gg-jvweO3y+7?|nibm>2~&${-p}^8CH8lk73aMP-)~l& zPv+l4)Sg<LosDyK!qg(@igQC^ztOBXd5mtVV-^1|&5D!9=%9<KMc_H`KN9<YnTfL) zAHhc4+)UoZC3*W|Y7uOPqSFgGrWS!`pdV^xtzv2s^m#CIDaRwtJJBa3_S7QS@Hna0 za_6|tydC}0#GYCNo0aI-Cd^z4`c`xv3j%Acd(6Axr3o*Ktk*T^Z_qh=Y9Vey-ujzm zj+sk=YtcVU?0Jj`dQbE(68_Rm-HVCiT-U33m$?xAyM+H~p2XiiTjuRMv@uho4jmKj zV#a@m1M}|@>(JMX{|+28L+gsEU*O^J=)``kxdQ!+{CmneOfl=&a}qw^tT?Yq?5V|h zT1#=>nD8xT#knN^-n0%&&GP?f!cUkL=gWybwK!k?73X{T_p)`M78hi5{4`-|5p>1* zyTtxmv*O&H@E$X9c5Ie^Ph3Z8QE&ep+a*jbf=-+rdnfh>nTfOGVfok5bv(jMz8$L) zrWO~<e;qpKR$%_wk+=hMUUj^{=Mv{?$BWJMUB}B4rWWBm+>Cx}V$Wkl(C4B*n17vK zM;@0i*1E;$^j?lvnzy5`OYGO1E79Lc_<b|Sb)*-9pEdAjW{&IlP5!li9jV34?7H+q zj(3}Pgg>k1-UHaFz&h)8q8Ea_nCqp$vfn?SdnalU^4*F~FXVVYWWDyRljoBD4%TU; z^$~E5xdf&bI#%DY(}`XPOienSZJq;Pl7Ee2Cu(tt@{-SM629I{ew~<0!KM&qE(IP6 zFHLxvc@a9j5N!B;rxj-Qv(xkDjqpom`F|__+Q?4tn%Tcjn-bn^ZbYZXmnvp{c&|j{ z{_vj?{;PR5`ajI`U>--pvBX(|kHExP(%jq#m*iiESyE~)Lg#U0w)d)}kC|Lbh9vgG z%<NAI*Hpn?e4KeMe4=>)e6o27Tx)KCCz<7+KDtcnvi~LYQQ%^j+U1x&3cLlKKFZnC zM}ZXswaf8+X01!@g06M>FR=W)kbg~S2{Y~TYz#k5_zm+;?CGOmL#QS6QDEv)!edH~ zzcy<hs9n&t4;&wO4NUC<H^MyD1m^dho917?+PQ_9edyda;ST2A=)DsA1I_G1XJWcS zxri&x^I>Wibk2>=N0~WqJ5#%$Z-h@U%m3;5*UEN2)2w*v5}sjZKReG!?8$#lHijD# zzS+D4dukVK8sNLl^1}?gQpfVs`7v`LyfWccX6+j}<m?;G>_KN{V9>=MnTe}2wF^3R z>HKr^8kpJz9Uq;)G0Q)Dah2jx413JlhkqyhKQp#nn1NaQE}hIn(Yq(iYz#K@(WzZv z>e7YT7?_;8RGK%!93OP~AC-TNahEY>;^{Iz;Zq|wDMvpiu|MC8?=G_vzRbK8otWl2 z-!AM?VEMl@;U7lUcja|?G_hwk27CE`CShh{(3RI(v-0|hc{9wvugR{v$*grhPxu#+ zLtcMK?3s<>SgrfFgqe*&C$Fx|z-#TlYb!JU^}4U1i^)f<yt=Y?Ir|DT{<{uJc!-(2 zx*lmJkFLzdaO`H78JK-NcGn5!Li9-qPc`pEpPAUtHggVly*lCR%!|=)GB?1?#<12( z_%8Ey_#X2P7`u7e2Y$LPH!GfJ6Mn(0c-~Cx-!Utm4-;lK2A_)O3v&a^Yz(^M*>2|l zU5O*;iia5(9>*8L|1`_bfAd_*Yz#KLc)d@@ynSgG^D6ZH67FSYt<p-fj-`)+pFJ=$ zFvrJ6)@$8MPf6@gvtEim*<21!OYG?*`3c9;M}bFRGdJOR=B4P15_|Ft_M8i)4<!7M z8QW6&DA?#&`Y14aTS_10m_7=ud_PF+e`el*zQw#5-kR9cN4aC^qrlX?ls?KaeI(ZF zy}R+)l(p~H+Ij(chlD$uhoiG!xnnEL)#&t5(8csoVDjz8e9PH0-vZA@XTAkyFT0(Z z*iTRRJo6H4W+u$>;n>~i^Ar08=GExTw_qdwp?L@Vh*`%zZr%$&o$zy!^&W?AuP63z zS?`Iy(aaun+mzV<GT~pFtFZZf!hbYV!*2gd?A;^H>v&xo^G)#wX1)b(L@ze8e)keH ze!BNb_+axk^nnQ<8d>kr=zd&ce}b8P=zem-%r~vuVl+B21=g`M%#+}Y6TZ~E3;l+~ z{$}%B^g9y1+q@P1KJ#|?L9_g<On8-f5BkdqzZzNZG3ow(V*inK_N@D733HvGTv|>= z|D9RKerui$?@pNYWUu$F^x(g6EcQJL&5Pmo33oE%qX*Xs!JfVCv47;?XF$S(%|+M@ zPk4lRK6-UxUt_L7KO^BO<~isWnRV<X=7sQ;311Ug@4M-7dt!f=c_sRigqPZ$yn8%q zE{2~l%g;**zhW*&cOSJ9zhxbNJw8qBzc5#!Z%deSLVKvcsrLA5{(V3_zB8Ag(?@q< zqt^`gppV2&s8!E)dHbFn&12EKCCp<@IJN<u_yTjT^{g;&h6kC6t0(g<=bt{hTkEn9 zJ?W#s#L$yI$}xQuSjSFJ?3r&tS3ENlo^2-Io>!aMtDe`HSHd@$*TA=$<)1$KVKyH6 zC~zq{x#f7dc_%u@=j_*+N1(r%@H=L$`=MFuer%SXuk-JR>iLaX>+-wBibuRFa;VF` zygl0=ZCH1|mI=2pFF~hv!4G-t$8|zr>argP2PXIZdPSE1{VMbCx7u&0nHcsvD&b?z z#JJxniT!D2#lv;NJ&IpE&CEXRN9}^nKJ0g)S$^i`-?z2jJhRqi2Hxv^*zdN;Ax^Fn zg3kG~-$Q1t#bZ;@#ZQ^F56_vk4=<Xv59`d^;PsJ%e`es1v@SpUePS+xnSntUe-&A; zx!#Y*rkwp>%)`<Dp78hPMqVF{-(bHHX5RyEfvH`N+nb4Pe`*(WF|$#ub@%UU9e?{X z8-q<XJk%`z#1ZtZ@R-DYoSEP6e`>-L&8yMRGRx0&v*N5zc&2$L`V|S&gSj~AwGe~i z<gqL;G46j)!t`L!sl)!u%v!g>yc=GT@UxLsul<>yVJ-11X6?_rwpWfHm{-EoKG>JQ z<P%u-zqL&b{0H+o*frI2@B9DF_O<c#>>=hIaC7VUJb?d#&bkM1OkjK-aDaI`+{e5J z?w9bu$ja-0!xBEijK2fM+Ft&tcko{Y(}Q9@-!yXok8y!ze}4Xbjt5+1md#}eUm3ZH zV!I`==P_=HdO`jdC%nY=BhcwV+30T;2k;mdcpXd+2HpxkW0wD)M8<38fY;6Pzaim` zwpWhyV9x*N<~8W_V9x)q%<})|$eEt-|Cx#XfV~OtGdE;1Wz7<9X<m-rE@5V=*2*-Z zcT1RA8uXp$<>uXRMPz+GLD?WP`%^Z=Oy86pX`TxoV^%!Jo7uOr6V2P<Ns%)(FuuaN zweY#-dGH11P4FdV#dCS&5YIJc#dEz`@hmVao`q)lWZs6gw61HNkv;P^=wjD8qhp!3 zK^HS`1Mh>^MQ$Q}y?Hatyv^BUYpuMPx6*Z9m1S!!`)~8_)h(me_o*(0=z9|08(E)c z(2M_q4Q9QH%wyqB33oMbLT5k+`(1GF$W4g7S6}m1n0YIkCOhDv2@f~#MCY+G*oa3( z*5}vuI>}6qy~dl_pI*${T%6O*W$5(@v)92!@y|(ku9^Mmbwk28o0ZF*3I8y16Y9|G z{)B&QR*uv+#4o14;-=)+i~8o6`UX}m^mUHuYjN0r_EfB&Uc?tz@&6*>Uz%s2|0dzz zo5`<Nw$@_$I{4WL?=>q&_EEa#XK(sC$MkjJHR$wp;H@xyE!O97^ro)^lS^;<TCDhc z_m7;Bj-B+(7I>JMb$cHbxk)2@T;!%Y_5||?_++#EOfYl)^sbAn*Ov4q|KMM-U2K;B zOC#%ZM|xisIrzWUT!nt4S^k;fAs6{y5;?;<y_cG|!_4Zimi#{vxk)w5td`zn0sOpq z6TCKZST|d1>e#!{`b?Pka_cgyga38t*;;E|W_9qdwOs2a^6$P5{$1;)^1sJEmDgUg z*7~1$Bk%okt@XJkeO%KF>-OmqZ8Fkb(<b=r(<|!w+|E7~_EQM=HxpYQW_8Ggb^Ey1 zdJkD2W_8fT*;=!=eVEljS3KETYu%~&&lBi_-TmyX=2ahNb&jdExM?~1yu^OK86SOa zOPF4kz22A6=U(%0m|hP02KZs~Zul|tUU+4~t0ISWUyDq1nLclt$HMO={9$B0Kiub2 zv)28>yb0cB*1Fpx2mgPKtjFa(-<gNP|4R73X7VlPnkwv%xRrS}T%0g*1e+!3JrX{^ zOs?ezCEU+U-sOW6=2|QGS%*F%;VN?@`j~{rnaQvG)PyHSZc>SUmYMx2pKjg>*PGd& z@|kApQhr6kS4Y;qmERgUqkXu;ycxd7_LJcI%!+53Sw0&gH_gB=M9%2gmu*u4|J1BF z-!RM1yJq?MAad}tHL_-4`8Kocf1B_h%*ydE3I8p!-k(+ey;<x2$6U?(DGSV#;6ig9 z+%^CC8wXPB2RQ%rckKgvCrquSH(7&zcw&E~xe9$`!dz<wKjd;CYX{x|*O-a_z%vq_ zVrEYcJSXAvBZqabv`%;jUSqC>=bPn!fq4)7qs0CJv*LUt;m6Gz(4RKT&vRzQNzNgD z@w&)O3SfFU?1}gtGqwkQW_!i?b2I1ufnO*5jd?RV=WcF)c170wIgnls{>A?^m%;RM z(BXqPaRRgMK^-Dz$nl`g=Jjw-+f>3Fld~UW8_tJ=hM1?qu4$8@@G*%!vscFk{}aqJ zvElfjFN8Th@K*TT$U5Yp3(WF)m2DK~wPvk*qj?|9<7|kt7+#d{Vl#Oh<eD}SKV)70 zd7RC~$>VI`vFK}UQx5Yu8~n?DWBzky4%%ccME^YDUqo)Q9i1Lrs-*Zi=uhS<m>vwe z_#d_(0n>xhb-jHs{}0T0bTDfKX0HyW#(}rP^q^Qj2QzO2SHbjPj+wW?emFYwHn993 zW?loccF^UY;{$JpPl>F@i-S)yv#$qFPI#KR0sXv$FElSlpPld=b0hk73EyDeiGHhj zH_W^Z@f5?%+g$wjnK`cxUS^&P6GyO7JS)t~>sj-5_@|L|A9wH@=34k&^E{Y&D?b_P zeDG$o;@J{e_i+dR(mWOZwOR4}-mG~3XqHdrZSbjeU2EOPRWKKVE_SVTA6L=dy10{h zAKX2%?&B)<HxpyUfW#(SYx1fXZX4p%=kkR8kv)&05BmJ6pw@v|zhYv-)LOc(!z(UI z>@P8oMZYp(=56r9zE#XO?}8UZ)_q*Xo#w6Z56wH^`xE}Lc_;c~2|pP*d=JSgvvOQ* z*8VVWb9pgu1DBzHnDEDD#sBk!zcOoozDf9ZX65qdg#RzH?&B)<CQKY!m+x%J^rgNz zW*^16kLyc)b4+~$lS^OvI>+?2So`01U}Vn9Oy5Jz#NYRbgpW4QKp&kjcJib1s&BT| zV){Dh8)4TvLympvYw3FY>Puhen7$6Y27R_!InIf!`?$XJwQQOy7y4Qp;=enx?&JF2 zYu*AsXx6$9M{d#xFORJIk-jU<oWFfvFw4)&<{j|ck#!%}_dT;>`<Yq(KaH&WxW4=@ z#3}#V%vCVgQMve;;eq9!SuM`g!T&OEkDmh(bo}>g9(CQv^(!(jfQ!wW;I5ICSHEnn z$HKj>&xD!b*>(FdtAqb_=-FCp-KwaEwMLue-+dkYyVkmo>*u~!UHZA!O|{l^ueA|& zt#u#QZ%(rAT(fl7RQGZHZuYwLOFw3Hh`A7Ut(#WE%<7<PUDsOoas3*si<g`0U}kl& zS3KETYh7mbkG22&^rO~+wHC8F$JAP^`u6)evH!+A9DQfPyUeT6zca6cxsD2cmcait zFXOW}nws%{NC(>!&mo=7L*bqYmzhVSS0vouyb66t!o$qOaLBO<kBZ!+3jL&n$D0)! z^$jtLsc&{44xwko`Z;8lS@BTcpo{047r@jv=!${*20x2n>Kj=8sc+y7Fg+XW#gCb{ z!7CGc^32)4W}7|OylGwQer%>!4&mB3*jK?{ChVFvS&Y6b>KPro+svAW{Eyi~zO9z> zx#7*s4RGs(+eL0uht6YY&Ym6&ycfN1!UH0=ZbYZXvT3~$9v(UP8Iv$QC>wpYV*gVU zrbg2Bxq|)APwX!;vrqjmOPI&jU_SzVo_RDp-z+~rO!!CU&FDW)_>su^9K!z3C-yHz zZd-x=lZ0P4Q^)?)RWY>P0kfVs_~Baj5m-O{e`zj&f0HoRLb7RwkN)(OSl3Sd|81`1 zb7-i`qxLg^x&$snr>An<EpoHD==~D=f#$L3N1NBfBO~i?Mg#br{4^o=0oCR;@M&h* zpJ6870n-vb$ISUKfIgBRMnGl&eH6GHrjG*mhlwxnX!y4LUJc-yC+ypNbRPS1e1Bwp z4&;ER68mS&iu1*U*V=vrI&sTSd#%-ICcgpin`gownc4pVUqx2!2K>s5j{#iUgm}c? z+FrTPQ#t>8%)~j+J=Kmi2e$OF+hO;V;u+Y{_QWu-S90uuX4$hw@Gs^(5bJX<2UaEa z_>#^klNsoq3e4kLu<wcPp6XBzGxu_Ss8^1uS77#GAoa>I^%CoIH3u$C>=#AW_a_W= zPX&I!I&~T7p6aNWA5Z+aUcsm9)oB?v*oC#kjgj@*;enfzW4D<1pwm;qUi|CGCE9;_ zN_vU*?T?XzpYId?kC}W26(mePI#!<xI;b>nKd7g92YR1`502br7dpMBW4jQ~phF`E zKO+-9-n;~x>V#_|cWXeeOYCQu<^SS@FO6Kv{tUXxtX!^*9Q@p#@LlGW*s!+Z>?U3s zS)Xe<h<^uNF|0Dn=gSGdYWocO8)o)w(A#GD`844#%!+?o!rLS3b5jTHPVCt`#h}lL zAH)pIu^+Sa8j#8sQQvPk%xsj6{8TanbG)CK8djDkToGBH%UXFvV$W<0$5MyN(Fu=@ ztiO|2x~C2(gPD!8FPja!r^+_L)2x$ICD)3w>9rGful4Q;bBy%fRq!11V)#091AK#d zHGHd?J*>PVa-X5_J?5$KeP(=DE;Hl15?@*?<oiP8uvf0BUMo@gQ|n^a^nfDx-Kd9r zKQPZj-yAvQwIy=z5$Nv6-pa-OsK4h_x*z*!58aP_dcyw~kL^<i|J_^x?=w&3v&S;# zI=Fr0{TIQV%&Xw;k$acG`<sbpu&+tV$Yn5&LcPdw@Nn}c7`srT0(g{J_G8Tb;qeKd zY95Pzrnv?_%gmk+o?)H`vtIDO1im`5YBAWg?!*2JzR9}Swbt_xgFQ=w{X@2CM1Lmo zf#fmxd9!@3HSdLg68WG?m}3;fL9*Xqo&@``PtQ9J{=~ZC|G8Q5e`RifzcH_be`i)a zdm@LJSzBvWRH3_P#fSPavHy0sByWFcshNE`)U#Cgnui_|^?t))&(eO&;KQwNf!(wH zWIxjSKA74lhJNDe$cM1bq3+p3%HT7s)9Z)2XAi;l&~vO)!$U8N9AduGyaRn+!t*2R z^Og_2C$YaT@_-8TWeGQ!ccQN_?}nd^Jg5qO$;@$wzG7~KUyoe54t~qL3*H!ca522e zTnB${o(=!PJRkm*c|H7_$cGld-<tcwe>N)~*Z0uT@LucWJEUb~?az=lkq1z(AsrL$ zV%~<npP77z^ol%?Js-jzsb0!!2y2T67r{f!<T7NKxgI{o%pMLo&b$jg(JcQbn~8Tw zZRA7oJ!F!(622hvfT{4s=6Uetkt=t=S49r-+!A@9a=AV7AmzK*ybNAq=KLJup4H>t zkVmcWgP%&+y<Ay}{$kWC%V77i9*c&ow_Xi5nzjG*>?-z3KSQW>;6j+5%`vqOtX%$* z*#FI}_`gs1KW1_nT97b)gP+yt%;6k&GUI<}Z*x!hAoEI?Ih?Z}oY+_8KihohXftaL z9hdMak(*&Vv@WrqVV;Uk?Vi&<h%b%Yv<9Yj(gR;>o{4^A!qikY&E%ij1wXhNy3{P6 z)Gp`$iO6~$Zz#13{>9AUz{E9_+U1xz99Zi%CcGhXSeM$#M)&DM>C?d5VQMFCqFm_H zz>0@H4LlE~PXjN6_n6nid(9hR=5Vmt#b;GAhs8~a^RU+D*>F2E^*XGxc@^Bvybdli zZ-vXvJK#eiH!Fe%nM+~%RBI`(!|2lx1MwV2pXQi84XoH|6P^@V&to5Uws|Ieu30f( zl<*~yn^mD-A33ahqiu$xvqxG>&*>eu$gKE(l<)(Qn-!oxlJMi^LiDE-e$HHkz9!*y zX2tV<<PgtCk(-V{|IDm-es1Qt!@f@V8}nB5oeA%X9OC>g;eVPH=YR8jcvCa+9Nr<a z;yFB9Yw10suKhW@%=V@5!3k$;JskZ|>*B-B<aPMb36C_(Kj*RbKdhUrH8nYWO4OT( zUF#+*;q$GFU2FY)<nYU^i?1|u&L2K6;rWr9jz+)Dti0}w+)VNOIC6-`wQe#M{mG~Y zcCGc?$l<H4i(P9yZ+!S`Q4jm}X5?ntllKz-&^!YD(}ce;D<00p-2Uv0tk-EA{?~+E zYt4ki|7Bh5T5I2iHMcHqm2h#wC6Sww@30<b_Gj1uk+na=21d>_z^-*>JA8z7v1_fr zi40?}L;Pa)CGc+8Gdv?cE$U5*;K>P3Gnb>Em+*z=O7z(Y&oOUBzb>-&f7lIXY=_-y z);`=3Ipp<V{<|}VJ!~$-W_iLK^SsX0Ds;}X!2EOAdUF{}FY8)G*M7r3F)IdoIq2fA zBI|oMhW#nAr>4OMf5ZNfFg2Ba_>%a!`+*x^YATkW;nXh2rDpOSPVIs&?h|<gF$^D? z*mGV6n@03w6CM@$sHNy9nc0uw<0A(@XC*w{OdW<3lYEX4vz~aQVz@rBztOw_ePP0j zB3CU#XAbMws+BNvIOpf7gr70b#pcC?*GAU&k_@Nsa>vqlfj6SlcR8l-#K&uIx0zSL z+am`*u2Eq6PWC6v!^SlVOy5b@_nsWlK7Z^Hoy?oiyC=MV<dfLjBMvmLhWkbieq5u# zBdpKI#x)uz9uswaugVdVl4GYvuI`V{W2IsXd_m-s$D;FCDgERH@a2(%pBp2Gb#F26 z!e&vzizA<0kM0@;KMzGc_;HPbpXZZfU88aG$#qePfq0K-G%Fs?59z_r=aEDFzpzam zHor>jf0Nk%Ut<4vv-WwPnRSoML_V4G<j9t0);+R~c?;Yz^7tyaiy0qB?icx#8n{>F znwfBgc?sO#Oio7*i9CUN9y!cB13tzq`{T^AKheAy=DJAxFhT3qMn1I&cCAk>fzP&1 zjz_xIr!9mpih8a5xYnnW_mNjd{q$AvHD=k&H}8Vki|qa%`J>3%|07-NY90HCb=f~2 z`Q+K~(`M}_*F~YeTj4d4$5+AYBA+7rH_eOScOuvBh268KE3c2Ee!AlP!mM?_G|PT_ z<cVeQ4)X~3yM+H~9*zFrJRjB6yqeElcHMRE9p$=DB+jE;_rR|E#FglkdH+WZHP1jl zD&b?z4d~;|TI*CZ`*GBn37-{t`W$rEZldhnr)S8&YZv(XXg_H_`U3NMnDapUAN;s> z!H@g&jB;#TyTG2YlN6_GH%WdxV}qZ@=rj1)5IG#{$HBm#IEE!0>&L<1=c^>1Z+)zC z`Lpep!h6hGm%3)-AK^Y#z9ZbHXKaIAuSw)G!u6W83U<A;?g-cG%p%x*dgffXfAl|@ zx{Yw3PG-+W42$}d<*@s7$|l%-I)%7KxKF2YZj5lBPF)7q#$%_-ev(=C?$fghVfX1- zTGxGg)@azZKC2pbpPr>0UF&J={RnETJ*ktQ1?J)Ko#q|z4<k>P&Hd(b_{Zisu=_OZ zr)zzNj$IRN!hWtZuS9pBhW&J(o>`3UJ`MZnKAkLk_vz#fu=}*G65bwt)+sO63-wi; ze=;l1znW$L5A!7WUuNPzx>dq$&GXPp5-v6GM6XEfUH9q4d9>>u*ma*yj7Oi4*q>yk zzDG|;_;mAD^ciNYRd3!6Uz+e0k@fv$M=wb17e+ou{$0DkKZ^Rf)Zu8??%X}FXK(Q1 z+D+HG?$dLo!W^T$4ZPld6sKz!{JbCa;KzL${J2lUvEL+qerG?N+ehy*D<1OHTEWl% zY)>x7G_%cSxOLwCn09&lW8A08_n2O`p@zp)n91cB*Xvx)mt$Nn#ea<JHDfgFKAo`| zcAuU%6Lz1TNADctK0SXMTpRsgPykOdSHkYo3s%DCTHgY@PwQpxKCPF%`?S6acAwU3 z-TCp@`g!mIGygxveR`pCbgeJk3%gG*mLJ#p;@R+H@z|L?;U~?qS!LG#kaKqbk8z)d z{mj-{$9@=X&Xv9U^xW;R`!wvQ`*g-wbbcqFVLx|7K2P@U)ARPh?$e9wVfX1w<@GPe zL!8IrBgDqK$2K=(e{7L?F<fjWr(+LDxQ}@adcTARMxIrM?z-#TJJxldNu0;J?txwR zS*7U2k=?6f>&(>mSYI2@6klxr#C7bo$yz@!SD^dac$WC~s9()K9qZbK*xaYH<kPha z{B*RxWH<Wi$d~qq$y2cfKdxQy<363W1RK{b@Mk_&ak_TF&)12cU6F$y)|3Bm>^~F! zcjQY8xbJFeCZ4Jmkrhu>XWNrYRX5ud!qh-MwQf~;V(&gxzE$qiOR8bl>k@LQa=k9? z3A<jwkLz{mJoH-o-wC@<XD^4{r?csuD);H-C9wPS@)5B6^zwSxeR?_PM%6XZ=M_cp ze6#Eqm}P&bc`ocey+Z4{Pp?=5yVh5%haZdfbCjcNePt!QD(Y9sk86F^O8C{NUrl~h zubE}@ws{Hso_PoCJ`MZnT3@1L$w&Ji_7l5Mi&FGInft@;(@V*<%6)pN_S1cO8TR_V z2pxObP}qHXRRhc(Nxz!BMsl77CeD#v&BQsfhgtT$%^Tr^%)~YFu!N5=6T`@=ghxld z25ls{g|&3-q{wr7!mfK@*M07Cbk}_@`#sWipSuQj-REwBUH5C)laUJ(|BLLu9Nmw( zbHxu>SB~!G;Q#TchdBM1JGTOxwYDD%b51D!VBcs~44)*&er}fiR|)?r@`3_%*DkE} zoo)7@yLQ)z{~Pt|sLye(-F4LKxK?>T$5CU&BR|KnkAc^~eG)!6@^zfI$9cvEKZizL z@f<hO_VROlaxClReAYz1jy*i?471{y5;^#By%hg(uGe+!;c>24Sl9Im_6zM__O92p zGhx^3TIJ$;T{i-Dy@DUt>$+v=p1t!5VP8AV+W>RC;=i7KI&NL$9}I>4c>05>@H^It z<+u+c-;jYnHus0WFw5S3dV}n@TVD$AFl$}+=?z<8*ZPKSu={kra&)b4WMB2YC5rPV z{ETv~Z`ueKMg8VEFz116ZkCPv^k(uK)g$WK&r$s%YyU^N*4OIT!=kSJ9OXW}Za7T6 z<x~4PYP7il9v4~rIqH<i*UNsQxfY%r`KCsAdgPnQYt(sW#mT=z%vyK0S@u_(cf!|2 z4)NcS@ZDy`a9_d?M%H)uj(R4sf8I<^qt+(;lgPKo4{Ix)TiDA{8zSFY2Y+N<54)Fd z-46de>bGr$-OCH9$*6ClzOWMhoq0aI%e)xgZEk@7Y33Xl_3y~Hm-BrxP0iJ?AD3?@ zp3!Zs&wx9a$#-;FWbM^xj#n-VCc%d!JjlEc{qV@jcl42FYBG9cWaTyb_{a<U!^9z< z3&~}4jd>w_M&#Ss!_n^d+l%0HtjquT=2Cc;8GoZMGvjYGenZUjVDbsP48Ak+Lgn>C zbAQ<Vev5K(zu&5S-S4-qhu!bD?twYa<nvb9uZw(JPuTq)*!_OnaP$vtQw6)<Z<_(T z-*1}<yWejk-qAawz0SSSyUdGV&+yyDuC=~P`grzB@yP!8qR4l!?(v-x?i%?{dg}Q7 z&5PmQk%OPXk%J%i^6h)E8DU*a4qEHZIq(>>{J58cANOqVGc7sxyo4|GvGp7~JMn{G z`44_>jvR8i%{DW!chBCbb?;5=A4}|?G_S^Hm09ug?+`!d$nme5<>xi?cKGeci>hH? zN8QC9AOEwc-!&EfH1geZ;jQKdc$;|>{M*Ps91Z`$JRAOtS@wT3%l>;aK92uS<i)Ie zLV>vycC8ne!R@V+(+RHiJxk#3QNI^IC%D!>DuNG;`j6JZea*6|H1CCnM%MnHFe<Y4 z{{+|i4jnt*y6jJleCIs)Of&m=!dd1W@QldX&lBn+-zED?%}e1cBL9e7Pq@~synbL- zoVS>@?(LD6$e#7WIny5||Lpm5!V?LvFe`@V6MiZ3gPYLbN$lS@E0>QG{w(r+HR$fy z`zFD@Z@PaaOwNko0mZh{Tmk<z@>12#y}Yy*{+IQ+@PEx4`QEDL=B;omGycXDM}Dvz zE-}x9dzjgSF$b7e!oHS%a24FoI{A({BC={d=4dnL<e1S3^E>5oAKI8x%;Y=fH1itR z{jR*mxZjt~fzOLJOE<#q_obWR*-?LxJsg9b{6AO=UuTwoE{=j;2j6O50^ea?3O^Wm z$p-jg^A31<<fYXx`O8m;$Nhf4a&f=kuYBF_s@E9z`vW6j_xl5~cfUU{1EwDG8JP1j z@O*Ul`vVJM_xl6dbNBlLYhd^L1MI)PH!S2RcC8=W0vA~qyVecc;a-XTf#$vF{S&T? z{4hSo4l}dv*rOspQUM<q`BC<E><Q*Y@X2PaH6e0CPndcr&IZ;QJJq}jKG)m`Utrd; zS4Do9*vGn;A65)EMm@xEOXNq{+p(-I|Bot$#b)_=AaaP|A@e-+$IY^T%De>jV|0UJ zd(paL<3ITi@oX?F9$$}zcs_~xqeIbsJr?5m%DUqDCUS`9cV@-2%dB{In-$ML&5GyW zW@0(9b>wBM;dYT9o&$F_uZO!uexwjCGvnvPax?Lt=<BgZSo6d|);S+e^!3=Ib?}i< ze{=yn(!3Eq-b`L6R!3G|C)Su*^TadE<aOc{^J4fMGdZ4kzIiEpW#na5@HJ-TINz)| zi6hiP`TBb7VdeWn>$~9lBR`^ie{5F1kD2A?Nwf0BE}TDgFzW?YzOR~<?`!7mu=_pa z>wa%2LwCP7C|~z`!(w=AJhnmkZZj+2KSlnr_^;+=@IMm%mw9FUK0U?uV{voq<bG07 z!o}vz=v@=;Vcvt@JK=*OKU9c5AmPDge4jKt;SuIi^ic_qF|!XRjZfH*@5?yvPC7H{ zf&KWdTAwt-y13q43tyVBAK#bFMZea%_y=b8{G?kF_T&39_WvaQ)4m0!27#BOKa}vJ zksoILlROgwKVy9!x@W?};<eTrU}_+r4~rYkYvA`2&dv($v#$Zvn<sfzXoj5RYk<Jt z#A6@nkG?bEUFNaqz6N+i>{;=s_U*sX=FvJ{7t++c9riWAqvEzv*Eu|{B;itX6}qnh z8pM69llwSd12oVh;|5x1|Ht{7U+4e0Bdj;V9IyRp5RW!*hkXs8eIDmop*cTpTC~wV zj626nUgLZXpuQeA%ew4|N&X*^&HO~a%}g(h^Q?GeFMMy*HRs29Ry3@JJrjPs9)3F7 zJk%fNck=%bzQ?hicv&^<nXqg({AScOhsSv)gj_zfz6;$mA;kYh)E`m&+syLAzJy#9 z=N}?JS_gYpXbz9_HNc}AVb6+&GWb8yUUjJ^M)_%22p5_c!A0i9a3}K;*t4QxDZIb+ zM%c5WfwijpS|{FW&x!`(tsW8ehbrN!$m;RxF_CqiSC2DSz@7<@>ez`<*Lhg&nV{>0 z>gm?!!S!b4HPft^Jri_ZRbOpgK5vbz+Ew2XS@o*E$IL!g-xpc+s$OQM7S#>rUGR#? zA^vC0#po|3{EAueziwUyzh#zB_Ab;^>uxer-|EjJKUxR>!mJ#BW#+i*-$ZUGgTFP) z=FjGZ@E-Fb7{8(Ji{by7m+)GvW@hSpa%*!V?CS^B_vFsjx52)CP<>CXurBUz-U$y$ zcv$2W#G==Dg&1UC9r>{$__T!2h`hWE-Tl5?F}UBK906Y#ZJwF~yWgK`fcdxlKc%(i zMqW_~-(aqSZ#Fl=J_lB8f$z4iV;_#ZoOAW$$IOahW#kaUs>n}GLVww;7+y8Y&l{0L z3~!s+|C2v3%l>C(e4k7lihqS-+iF&9e~297aleN>aleOn-0x3~#oqm{JsFR`?4FD- zv`_YAJo_HjBA)S`%(CxlCZ6%`cf~W_{jR+l?`wc3Ho%_k%NN4bMn0EshN~h!*%NlZ zKPf-%_a`^P?)Rq(VE6k|#5LaiuKJFj9{oJU`8mGc%y~F|rg;y1MP%*s_^ZuB;UAcl z*G=Z-@a<;hc$aw<ye#q)wJ^shmyo0TeYxUvzlVI??;&6JI}a6^@$UDK?_1GN$d{Z$ zE#zmDS^0i$R=&S5E8kz4mG5uN%GdoK@^!zjP`>;w)KvNIH7j5D`wH?srI~f|J*8vh z$HZOCtKt0;?qyz&UXgHrGqpZtNW#O+JJ63w__)ZA7owk-@X6+$=(Pz?GMAyBo$$G4 z)<5N<gfB6(52sw2u<sY17>+(a>VX%SS@V=T6ZZYW6ZPo#TNnF&;fY1?W7fsKHh6+P zKV_A5G5Z+KANK#0R}=QN!4vDy-?lFHwZZavuxCPGUmGl6jJ`G62j-lR|K)4Yf17Z2 zR%}H7i*<2!R%oBUkGgvE6weCHkeUMP;zDy3+&*E?iYKR{cegI~taysOsyQ&~>ff5a z<~?v_!b2nL9IiPk;bYCU=qDt6l9_#|nP6TDpKfN)YltIz{@2u*x1e8;@Wp1u<NF2e zbB$+(=4#C?(I)JPXT_7si?!uneO<G}Ec++Svhl1?zt=o(onEN%tk8U``AO7Q$d6~m ziVg6ls6VzD=0C0VcopoK@HlJM{4(lK)WMz!noBjmkGkekjb}p0<^Q72X_~3oYi@-1 znTc~kv&fpm6Iz;yb3!}w9N4o$b9jQU0iN0hdsb-vOel}`D`Zn)UIq^`H^811E0)7Y zT3-o!R;-|hCLC{l3+!33LTlAn-woHA_rT{yetb0STC2w=cqZsPpKy7!QB5a!COoBM zueYB{c!9YJW*@`3v>5hG2zmX;x?=WB&|~6+N36@|bCDmHpBE!PQ3tP!ta?pYZ)Tkd z@0d5j??+a>CVXsG{GXZ2;V%>Z+N}6@m>c1pX8HVU<WS%5%&PCd%yZ!XnyKBX&CT23 zR*_ZTQ;W^ADKRgDdzc&G1I)|egUl=8erD=>>R|I0*w+uL@2MlK?}n?)d*D+tnRn;~ z{hWH5nLRvpa>CQh8_=nH&Yrpl?vGC0b4=X>Peor~o&hg3%g+Nz3=f(2p+BDRQ;}a_ zKTh?W*R}4cuSI=j8SFV9_`Rq<TY>I5|EzNVH0rBr;H{CLTMY9%orlk@hkqOS`Kj<9 z%-i9=n6>WTA}gNLI8MhtI~;aRwbp6WUb@ygtvK>?bKtIK);i5KeV%%q);sFYv({;@ z>GQ00nrj#Q9}#VW|EkEr|7iQH$9|ky{;8>A2>yNT7yMJxpv(V-kykdtv&_`xG-8#_ zO7UFtX84ALZ#M5h_jUeC@!i(<!uKWoVC1KJqBkVG++2zNY{D;?hoZld@K4R`!D(+L z{H}Q{`lf`5Te&<l8r^d~@Gq^`p?l6hBmTX0_TV(n`DetQ^Uo}W$u0O4?=w@!+GYuR z&Ofsny`6P&NAm`_Tf(06s&#F7)B|%KYprMJp$|&fbN<=I=to)?d(J=0zSbUZU3{W> zBV3bkt$7>zl!SdvxT+HU{HO=^HKESE+RLnquQcPYmRJ?@D)D^tZ1}c>eNDJ(2l~C% z#l9w7#lF@)Y+d|V<mbxal?k)&TI;#F=r5ZW!=4rD>)JQ0i#;ozqlUE~SQmR%JYNiN ziF)9z=4$j`C!C!XHRyk|F3!%1sqo*ei@!I|&SXx{BwS#oE~mFixV?D~dY6Q|oA;sj zO8CIYFBGEpPq@-tgnn#foinG8GH-)VimaNRKHfYJCeTnv_T%(3&9bjgY-T3<6=ubD zb!64+^dCfiemi`VnOdKIPvmDd!}mpgb{Win;hdLELu8$Mr>`(89?yzZisz-MKi3oX ztO)DAZhbNOTjn(|dmYXh>VEpB$g1_}pPQ>;&x+@3;9pr+jXW!!=eX0qwZ0GbtYB<q zPUqk9|4be4XXD?2H^ZI@&$8A;*IM~b^h|h`d?&irt4d(cgjM7_(Y02-6Dy)m<vX#z znSGw<nV`qDiNmau??lf8o%0iqi@Nfic%qqnC!TDsfosj=J8_bkd?$J)JWqZT&yBkB zop^a<&Hss4MSdC|6R$U~f^Re{9^%uUJdN*(OCoC~Pkbn{YCZ8$v*LLwvL2TwK4VsF zFPitjYa_o<1aF8OV!$q}wFvzav*K~BpH@6yMLn$RTCW<8{yXbp*Ls!W+#7XW159Ku z<o^X~afauAVAuK;YIR0w-u?{if_)WwpM(#N{8BCYKr_D2I5hIhv*9BmuUQEnZQcSC zlYFk#T4T*K;8V<V;M2@|;K`9+DTJq)b?mIjFHM3y+h0-)bE6(&m=}2s`+3IAX2oz@ z<PgK%X2o!?c?0~QS@sW`x53NJifv`&5SwRsi08Gahj={0Lp<+AeGPG);TgV0{y()( z<+atUcvvs&mE!rWS@wT0D<04AwTkC&QCB>Z*kc|0;$FCU<d@dNoO9A&E`W>8oVSy@ zn(;HKhj|~|JMx<0@IhwIhe-p>?7^hL=1nkmA!d9}8et}{Nu$i<HEE2w9`+1hOJ0*s zway+)@(f=~j+4%^z8#(!`Nf4W=UFbtt0TXpIIlA+-<u+bd~Y=mMZe3eeD5(U-=&d5 zzRS$Y_X)G|U13(f&qrRXd|xsv-=CP3@9SpeOD)6xDBq1{<?DVA`MTfND&OBkn-|2t zH}8P|obdmdccbr3n0&O>>Viz>%w`F<G?${cOSq$X1bVlG_cPa^mnTe~!GA6KpoBf! zSJ$EYdM~hN`)c;#OkeK>_H2KV+MdZ8p{8Q|23`nHN!YXfMe1|r`PRk0-g~hTzRbG# zN;7+Y=DdXGo7w*}Z%f$MdoS)nzt_6>{>U$_hCLGkKW3fUp1CsNRpy=OFDIOx75mWN zurAKd3hna;QGZ$NS)mznCOK$N0uy)OIq1Jm*t6p0#pu4?3+!33Mtk-5Xs`Kv=J$~` z4;i<?XJF17`CmH&-PZtt+go3V?rVUx;_lYjhsnLnn_yq>smCYxw=S-Xta&wgSi(n{ z6_2m?w9k`0D>PRppB`<r50gDBUM8=}b=LR5#2xlW_E(r?<5}^t^dCfh4ZSegvtmsZ ze0$V2S0{T`tlbN9ynL#sCO4Spz@7=KH^RQ&dvOWunV`8e`ITs|IXu}jA>{H_)L$No z&ha5;t;^o!;{QCd=F;R}m=))*%qwBfiZ$AEUjt|^P4=u<TMy$`KG({Id;)KV|7YHk z$xQLASi2Q&ZG9W;S)sW!rE}C(yD6R(udvpXGVA3q|H;3uE2a#Iym~I|TC3lucqZsP zpK@HZQB9|KCg?nza&pvl?oFvR&w(eIH^80=%4^EG))lj7LWuK{sE2s2kGxubZj7vY zO<5RO^_sHCOueT3$h;4JAhPN;<q@;uf80!5Q=U%vIkVzlW8MR=Gt1|jkyYO*@0h9Y zln>1-;g8MA@r%f+@02gi^)R)`)_2Md^JervnYX}yHE)IgVcrJ+%Z!hy)GgGm5cc(h z>N~Z_dO6I$v-O>NKqm7Z$LMEjAG40_m+-*IP0G-zd(NJ^2kwtf-E&Oc11~|ZH7|$R z-=Ob=FUVxx&#rs1S?gY&@Kuq+x?BU~?C&sZU9JIwF22vKb(fj7Zi89tzL3dm%&z;g zS?m5Z;Wr|Ob*Wv>{xh@IqIN+Se{I&f)Gp{+m-PZ`-G62>A7t14x0!X%YMOA1$XfTT zE_wU2n9t!@);g<K!p!HOv+h~^E->q!RcU73vyRPVKJ>b0jWTQ9lM)^uIjlP^u|LPG zbuUbKmRal0F>BqqX06NP@<-Wq?=)-OdlSAta#;7N#Qqtx)_pPIwPvlm-mG;S&06;p zzBVSiF0(hV*8M8sUque<{w1;hn_26ApYVUotUIm1%(~O?8~n5Gw62-V&%Exm9%g<& zt#`r)nOCA8p4cC0E=M1kFxOhaXB~RAc_v(AmLKNl$Juq6pMkaRMG0RLxj8dx+6{^Q z&1TM*Y4lV$R(yBlro}KlCB0cG{GfRR++e2u)7Xn(GY{r5H1JlKUK1D0hF>wyhv~JT zFNNPSZ-C#8++1sI$<L^1_zLq%vHd#X-$s5_F?^RWy(art70-Y3d^Wu%eO+TFb9Tps z>9wG5MBgvrUXg!Vgg!Xo!^|b<?1hf~skkcgYm?xbglo-H(WfL#?R4zxi_qC4aX6NI z0!zOxVQMFRJ$rRF^DyvknA(YhA8HhiRSXZC@pm>g3c8r{Ch&Hc8j05rg_(ze$HLSo zF!eh74f6t+8cBb>1pdHW4sSNkfVY?xziYI9H2jCCuh+WtUGT5?>ARdy`Yy11(szOJ zSw{_mJ+ajln`>eEF6iPO=6aaE3%Z!T3(WaYH^59@b*}091@Lg|#8c;*zFr8Ai~4J8 z;8V=&;E4%OHaDVAPxw6ZR`i((&o=KuzdB*pdOi8o-4yk}*;=zFb$3}8^Vk>is(_a! zyv#fl{fUHqt-GH5>YleQe#xvo{7J&Eo3&RP65eRugwDJTF^HMBfp@@PnYEwHTj{SW z=HDg!t$7Ce-pH?MulAYQpXtpKZfWNC)7vHNUS2;Iy<61R6Z7=_%nRWDk<}y9E6t1H zVF@1<`AzCLy*jb4F-t!q;VF^dAol6!M1GSTr=M?@{gt-Yy4RRj!o(N$L`;0*H%ee0 zD+AZVKQzyS?>BQEPXDoa9sF42H<kO7=1K4>^HO-VS@FCX`Hi{oJJz-Chi1k9u~|O9 zFw5tcX8GJ1`3=Rk%e)Zw9DYOmPwUHI&*3-Vb3BLNAg*&-*@nE%X=`2w6O;Bq`*}{O zc?5iL<kwmMoI}j4f6k!^A8y`*essbkBfn9EJ~rWMa~b++3A@&Bj7FbkUF=%F!JeGM zby297nCqgzQ{g!Y&o$ShdxpOuzS;V0*fabM@!i%J!aV*4pW+A2+N*|ymq(_wnR9sj z4f`hcY=4veJLeVa+E35+Hx=_+*2V9dm%>{jhrQZr*8coD;oq7o(f^q6U(EB+|87>y z-<#KEGUpaXezOs#9wFupaHoX3Mt*A#dPQR2-z<Gd!ozIO@6SEPOkU?6XO{g0+iTs^ z&D&sV7Ge<BMQ$7mUtnGaUu@>QJ@<0+PWUSGF8KP$Z_R^mG%tb|nm57xTWf{99*W$! z3jI;*TK6fl;(x|0pD&u_bFEoE**p1cRBRi~>tWC5M)Bv?H^ZLKjbhK|#vQQdbEER| zd~VzY@Ag`XhkXq3&*pP{n%QSh*z>uu4EB5u?D^bSf!@vbV$bKsDwy*!#4qM|fotJG z3A@&fbJ35qE_SUO*^?Q^TNj^bUJTbHjNjmY8M<e9qxfv=%VE#(M)5_~*~1x^C48ls zy_zvE;rWr@8j5~f!k+DKRioc)o&B8Q+5VPde%QMBG4m#Pb>y&DYs}i8*Aiv`guG^; zznAcbW_--})U24lFz<qQMAkVugWt)|TYKTZCj4FG4b<nng1r5Cg^}Nu-ag?@k>9C9 z?`|fq^Y)J%{P=oI>z+5*#}>oG6CPn^kIx%r-VBd16Z?7NBfrxVKGj?XpJ^ud^Ug9i z!t9Z9+>n9m&5Hl($Zv0lud}_@y~(WjZ#B!OugBhz&wHXCd^SXWTd^%S?}j~}-xj}M zKLxPo^E+bC=XXlsw``-l-ZhuOoD+)w9mTWR%sS_JKEGW9dp^I-d2*iTb70Tsx2K~2 zJsum_^ZD&LnGC0Y@E@3%wAR}T(c2`Pt@SGOF4o1a_1o;p`Ms=*4>WIp`zKs!CXe$y z!`~JkWqm8`8UD8T1naxulM|j0S?9p{lM*J+uvgUi{BslbY=37y`X$!c&+|RoRnzmY zu`c#(C;ZI$*o8gOUM)6je;!EqA@fr7#}j_ayaWBY$RXwz&1LAUC;#e^^I0%3dv^Xu z34ap#J@Pw$dt#5@U@!eo3I8?nyGzjjVP>84{}ow&F7Wl3*1e#uj~xw{BwT7<jebDn zcMIS?W`2J`KXVN{&|C{2W+ui9jxg_mt0KQQ6lOieAL2R9HmrZa8D_0J%}o3koMV<x zUyr>jpR=MKe9p6tVw-O+hdrO)72j!nIPCfSuGsVW-D=qL`CaApnC)xfm1f1W%Dff! zeBQ7C_I%#Jd2+#f(I&9x^M=LfpIR4tK5xMH1>3BPx0~0)e@Hl6Ykq&h->i#W>kZnI z|5%6X+2e4Y?1c*xE{d$0)_aBr?rNRi*L#M)EADNbJ*@AW@BlM=RX;Rg_EhV>yA1u< zgh!dzpr2%Jggx6;)B4k`i#^*_-}?HfYp?V<i6Jlcr~ZnBuQqQ&|3ShxMSiyw{dTir zzRO$-6RUjcoUCs!*TE|iem3$(YFE$NIeT&lEdBk2KZ^YRM)c3j%IoKmgP-5oUh95q zo(u0zm}7$f9q9j#{62eJ|37neCUap6Gw0!jt<4MJ4v{yK`-Pp&6>v{;JzQoc{tE|1 zet#@H#LT)E9%&|)3y-nAd>(I>&lAn^Imz~ljocLf`)C)QoA3o@>Up8(^ZR1Y=lAEs zp3m<qFVE-q7sC8I_*6XnTfDId_I!SC9qjr19<{pA^Et5R^Lrc6pNq!^_I!SC8#>2_ zJr{F)U}|#VI|;ki@0Xx|9QDB2T5C_fv@ZVI+#hC7L;T{M=Haksxaxc1ch;+5&+zxf z|Fu3TlewsQ!mZ5g%|*ot6JJ<sGkTANJ=@=B{fiE=&VF9x*}jpOFB%;6z@F_J>(NI? zU3+!WSTp-`(J2X^7MX3zTr@f1Y36G5^UR9*Li0j+ZYJ|3HPz2W^UMYC%?aNYxkVNF z(!_q5nHVp6BH<O0n=L_q-n<TeDRS`hmhH9fyJptEXj8)Mqhf2e82uM!`T1q!;OCFF zm!H3w<>&7Se;>KY>P+Th?Bug)5nNy{hucIh;5@mwy}1_dV%`aNH?#j2_ln$H_6M5T zkBf&!ZbHl#4>z+97c-x=ZWHk+v+SAAK^KoVD^BKf(8bK>z#HJYglCu)8;J!Q@ulW{ z@Kp(48@VZaaPf@^-(uFDEJ~Oh<g;lBI{ltw`aLkYUQEB|n0^nu5}kg}G5s!X#<_Db z^~>>kv+U{jp!55SIgtbJfa&)f)9>N}#Yw;Cn0^neT5wE`*^9uc1^u35`aSS&boxEV z^t)I!o!Q*X9?zuTgFYWFHZO$Pm!PkL>GvGd?}4|X)9*Q^-ve($r{8l-zl&QGppQtn z%3OgyCgE{rem|3b*ReXcXVUNDrm{aTvd-t3^t<$e;qYABl*9APOJVnWvvsihz1bG{ zZXa6&-)pXgA2e@-A2x4>*^68Z#1xqGWag_0zh)kd{&vFenYEukiyY$l)VvdYYh;}R zGug+GR~h_UbAR{`=HaksLV@D^n|0;onb3Sa{GX^dZ{)Lgseyd9pboPN&Fu56u9?hN z==zyOtpj5_t9QcGT6*){=))5Gqs;90tm6_sA#$@B=qH<HGa+*DQ)hdvi(Ob(HdiG2 z)#hsSA0&KJ<faSIZ#S=m?~2^49$sRWPtF7RZ${l_J!)pZXFU;Fe@~qCjG3Cwdfr?M zuQgACe`3}?u<v?I)HT?wO=i}d^?Aa-i2Tta^qq<QF7p<2dN%kG|1<K3#V|c9{X=5A zq^Ws6OwR^=4cyke4K9iN5&L-w$H+$OUUG0`#d*mgX4b#t(1Z_<{J|ddqa%lPM@9~Q zY7(wBFTs9F!e>X`v=p6Lor{5*2408Gtj;kt6>lm>XI2Lu3RBa-!(rkM%=x0v8V*c- zFL}tUyr^l=6%VxwtQcN0H^9^`=;GHSZ>fbpPV7H3Z$SSt;jbfqvKM_v<ju=r*Ywj; zm^m!}pH;)I>1T6c=5WwA!LI4&g?w%`b6EQ4vtieC3&&oHFX@}9<E1^#taWLh$Xe@C z*YvYWcwp4E)}^lLXRLMU5m66oxu&0QK_4CUu+~^J`*7(Qk;A&K>Hjlz2SAaYd4AvD zk+6hTtx-$rky=t~)uU}mtx>Pk+C@@J%Sx;UX<FLWZm)wAT)_@;Q7#<g+Ljh+`y47E z4o*nI-ElT|?sF&y$0Q*!u}O-=Bqk|hlY~^*UG9#vxm$LZy(KA}U<W58MG`8`_xHTN zW}dC3`1JGspWpxgyv_758U}R6@BWE&J@oyPseik~`k%4Y_Y+%vc^uBAGxBRMSbhK1 z)S)l0!&=w<|L$+3{!s`2<<xs)_^;Zl_}{ZHFpstOw-)f4y@>yoeSrVAeT4r`YCSLC z<#kwlf4hZ$U^DM`c^wYx^O*he?~LF>Tl4=S^?n}nI;@&~?&Wv?k*)my-R4{^uB+xp zW$fo#XKZD>PM=mbwa(jm!sdLfr)~PTo=dIsws;*@=5KM{)|YMNyk>LWRxP#8+v>MD zZ|k<*#&>Ma+xk{&owxOeZO+^Jqp5Y?)*rJuZ;M&O*_A(T>%8Aj{euboFWTz+=OX`W z_7v;C9QoI5&C`j@Io0b2%dG#k$p3-8!}{Nd{GZx~tozsd4`ly(|AFq$wrgbehx}9g zqsV>@|G@?8zwdSVr>TFG!T(d_e_-pmK8t*A_p|>0M*b)EDBt(|zQ|v&Cs}_a@(sJq zdLeSro@4#R$bOyQ8)n_F3Bi7y-{U#@#IFg#-$?iFasNN5M{d~M|4;s@$lccp?#U;A z-0O1mTJg!BO4s$e@rhq6ev8>Z;cVe!SZ>=@{4YoLYsGI5u>NnR>-u>9<X7xn{Ogf_ zGqqmpK3R&)-0Jl^+WXfd|4qBa`hOnzzqC87|2L8UTYH~%dWTGT&pyL{-`0KjacceA z`Q#5G|Iaqh+b91p@;|m~tg~PF`|_pTpCq5&8~J{lbA5U}@}qW>^(P}gV-K-jNv)5E zPpdZf>C-n;>-qZhYqt8nXD{Fn>_z-Xq8h(e=ymDSQLk^{G5ZMr>D0e7i2b>Nen0xu zp9B109{aW8hdtPz1N?9V`?cbS<b6sH-Jc)wTz~54TE8AY^=rc31@?0t&f?bu{hs(~ z_qo<yzb1qky3h3?>pPxPIqV6~MS}gBu%E+zuJ!zW>emE4U!QiL>wfIl1pOZIY4^FV z<4e!a8NWwvI1BaP^K+{6e(yoAbKdXyIn}wo_jtPgTkQLupVQ!*Ugti1&(EoTZ~b0h zy1uVWKc~U(rt80d$~qq_;f$*1EqEFKvyuO~)W56xKWS^8e<AhXJHwx({yoj`nN9!i zP1y}Ro%;86_J7@;!2g!Lfc-f@nE$V&>-%li{W(DJf0(ZS?mp{lw&q!Pj^_NkssBFr z<9q+TJ%@j2Yv$iheNe`~XRH1vb`u{*KCv~kKi@l;#Q%raJNW;xm+=2*ZzRd&L#cJo zCm*rTaXxY(^^ZBrWF@L+COt1drgqZ5PJ{iN{&<FU|2qBg0`{-dA9wJ_-n)grWAiaS zIc#$uCi(aX`I^VSPQwiTb$ZCh+vMkIP4J&h{fl+h{oIB6Uv*81_1}o>=k#avocycl z`Vk)klYUN*+ITfx|2gj`*X#rQw^IKB_ha&J+vE7}*n9ZDOZ^M&{oT|*8^wN3L$9NB zJ@oQ(`tx~e{?~N<=j!F>H1ztv()B-3FF&Wh=u48%cph}G)a$c9WOE-r%cWM|&+@6& z_p@hh&iL7vQvZAg-?HiZ*(<5l_p{e+`hNCS>d<$<R^LHeef|6LPcQI4ldk`48~^dt zM;ZJl>|yNRmygczpYi%7o=pAo8gAS4{LH^E>v{Rizc2rsd;Xb!U)Fv5%)c-H{0#qk zy7vz@@o%OM^Do(Cf3|G%{<FVsEB|lWI@f=l`lqwl&viKC|B$Z#OmqIg)_M0+hx0O% zo};6F)_-Q}yuYw@-v1?aIPX8Qb>9Ee);#~W&3XCo51Bge=RG#({rthyI`8KXr`CBt zf86H0pFd@D-p_B^<bVFW&3Qj(k7hpH#hfizecz3I+dgFdqsZT~HP0W3{6|y&gn2(7 zjXY+TS^v|KziV^fKIg!i;U}_xz5j&!^ZCExb@|WR4Llcl-X3QCFGc>hQ~z{=^?x_= zzi;zgfBqjw{!i>h);A(=+FPvu-N=5O|LH#KKlHln*ZH3w;NSDQ?AQ69p5kM#%O|OS zM$gavnh@;Q`Je5w?$?B1zs~=R`~Q8vCIml_=IC|c``O4jdzkg7BR^}mS$`q2Un`EL zSbxpy^6NJD`}_Tod2aOF{d|e_JN7F6W@^38eE$ze{-^D6*8f=Kf8N$!t|{{m<OzEZ z^GQrtm%ndc;D0IdpG&P@7vKLkBLA}8WPQQbJ?YrG5C2Z&zh+Of{vSpD8#epC|DQ$v zFYHCu`B>4MzmT_Wo#lUw{3Cmf^}iSS_w9Ao|3PYfJbeEjrVh{VxviNmZ1wslHrLzt z+Lzd$*Bw#Q_G`tF*8O?i&-3_ZTK{vNPyL*yaG#fPCAIEn+n)m*p5b@X^`DGke-7}I zP3+f-pK$JW_cej%v+d_vzaHD{QU1{|_H(V@E8Bie(8o->`&?_UUlYO%ey)Gf&$?d| zexaQ1b3KaZJ@X`9u$AxEgkN-U_qo<R@oT~_bl&cBy@LImhBN+GKCkLIo8}Ma-LZ9E zKd0ebzmu*XX&yhP!9Vr7?t`CGeQwkK$Labn_}FP*M7~UYKEltnddTb4|I#C=kNa>w z_5Zen3pQu@rI(}nS6$y={f(&pZF__D4^xL;AKPQB4@Dlf7g+amcP?`t-IH_f&oBA8 z3-+(m^WB8M5a9pRg#X3PrhCIWXX)+M6qDqEuFFaCg|4ef@?h7sB*}C=kR%UvT~Cth zT{n~D;jWoK+x2LYJkm91d9>?Rl04RRJ4td~PbbNZu4j|v@vi5S<cY33Ns{k+DM_B} zdL>Do>Uu3np6+@hNeW$WCCM{g?<C0=yWUHZXS+T~l493KNpiF6lO%br>$4>JQr8zr zQnK~#`L27D<b|%YN%CUX`6MZKT}+afx-KWlt*)y{@^aU;B&l>gkR)I3x}GGjblpsn zSGyigl4{qZN%C6P<4N+Bu3Jg+)vnt~(%1ELlDyvaY?8du^?Z`N*>#7XgWmNLKLfk# z6@J!o*K7Qo-L5zI*{)r0@pC=9-r?s>cD={X5$yUP2|q_L;eXeT__<}>^%H)URo7?y z+@r29_!&9&J?#0Q>t24wM%P(>?n2jjzAt~*MZU*+*JZx%cGp$D=W^FIzCUl*1AK4R zuIqd+&aRt$f5xtd`QCh8kMjN9x*q3ydv)F7`!{vn=KK3}J<a!j>3Wv$71H%Q-!r1? z4&Mu)>m~k8c-JfZ+u*L(_&2CsZ}9IMyWZm8$aTHLzq#sqkFWFY`hc$k?)r$Y8SVOn zuO00AjIS;0`hu@LviU7B`BPo@^7qy<@9)j>_m^Gg`MZ;@i~M)?Zhe{muG(F%^54t4 zuJPYlx-|p*IlQ}G=g)FoH~IX&TQkh(bKUh(e$VcDoY(!XTfByL-A<A}+x0X*n@;9` z_s%BCRM+!K^2>5I{rZ4k>3S(iezohBB$@AeElGZ@>y0G&3tev|$zPQD-@QBhY^$#K z__;b=A0)|dbbZ9nmg)M0pIy`S89yhd>kEF4gxy2#U+KD+pQF+>bFX%t=X;xVUF7@u zbzS!NQ6!_M>VLZ}*Zl9P<pKX2XSwcwcPuykZ-M1u|NC5d)c<By9{0avm0Rh*{e($R zJN^6X;OX@5WM%#DVa>+u2?q-vz?>_X-!qepy@WYeSm*cWgtx2uVpLy>>N#V0jm=Tt zXLHtsx3JFd<4M1*UYz$;%~RoxYr$MkID7CMrY?9M58DHH#Gb+2hwz%rIg$xGgIjhH zPuk3zwCyaOvU7OWuiMI@cX$m~4!whmc)?aq$5zgwt(+CV&Xb+2+GHndHrdI#O?I*s z)o<I=tnb)5<F2io1DpGi9NHuJDD^eXc5GMhiLE(LZOwU+TK7A-w1@aTf`{SvDdxS_ zV{hVKn_ky4_7u+B<XkJ*$|>5)VWyC&oU*MP<_qh}so7h&-`>Fk_8uOz_c8s#@1bN| zqhB!lu5n+2H3L0@S-UoBH}IIPna6GVT$`}#xb5GUmCt<P_h{u$+sd4=>2qz?*4{Z= z`SZ5&7i`XPZOOmaD}UKm{)(;nS8erLvm1EbR{n;q{7qXk?D+Es<?q_c-?NpuZ)^So zTYC>}<saF~KejdhnLj5{{<*FE3tRJF+Vs-r65(?g=D(-MCjXvZn|ytJUZ`P)d-68< z_Y`dM?<q$0C7XHfsrvIG)%V$|ui2V`$Ki9Q5lp{e^<sap=HYQL*Y9E0VCAzvSo!P^ zR{m&IKNi)u{JELxCvDZYZSK!KQ?_QCw&|&_-3g!9X`WeI^UT?rxnnDT(N_LaRKIL% z{xyGosQPtV^&7Tk*tAFRmaSgfw&vNfHP5cC`~zG0hqm&MqWa^g{>-1Fs{Y(o{e`Xj zb7?c1J{Jm~(>8FA%{=$^+RSrr#%AVw^EUbS7HsnGE!wIt+01`$)t@J;zRy;D&DIP& z*3abD??3mlKUlrkAFO$J9ISk14OTw;gO$(zVC9cS^<z<e%b%;Oe$rNb+vfh<J7sIO zX`7z+&e)n~)*irfwr1}5^MB<p+R9(DmAPz>;1yeYS8e65*~(wHb>1!inL_#7w(@su z&A)4_*Ph+L`?m5AY~>%?n&HHMPEr1;t^6}vndi3Vzp%CU(k8zrvB~e@LHM%|^Y>)^ zXCLx=ayI!rd7Jrr3O2oZiZ=82lx*dfZRL{{{yfDD`aCfFc}n@@1}mSsU}Z8#@Cas4 zu=dg;SoypKE1#KyHUFspjHdiCTlwR*=AW?Dt7VhjGifWoZ7YAu)(o@$bD#3(Y~|0} z%3QEDf5+C|MO*nxw(^&4&A;Y9ODcceR{n;q`8RF#+OjqOwypdfTlu@TW;pPlPnCaY zEC0w==CM73Pi*ZywUvKnEC1YP{y&uX&#=9?$IfFOhd<kvamKFVtX;r4yNG!UfBscY z$yN^g!@BA@L$ESy{xh=bIZycWvg(;HST)QStiE+yISpHVhyCYk<&4<M8MReEW-GJh zKZC1&(pG)jR?U>HzSFjHW^DDH_n+UDvtTQyW2=7AR_2QTtgZT0TlH(UYSwM_-LRFj zX{+y!|D3LzU0XSOw(9q7Wghv@@~S_!Rexfu=G0c-Gg~?5Hhu3){NDk{xv$42=RO{X z|2{zdeHoj~`?#k6Zh4J+e;?O^CooyT^SER)`+e*Q>n&Wdr*X|zPQR_30b4nPwsPvW zavHXBhW+0q`tXQN_I;!FBBn?9Zx_pW++M)+3+o+BZZNalH)(4IdW3c5&)CYJwUskx zD~COyp4$7k7OWhu1-CIX1yA86oBsDPUs$LAeJi%+S+&RThOK!v?Hb;)HP5z9&--?4 z&9iH3o;_Rh?Aw~>z}7s6w&ppqHP5lFdCsEsb9;dG3%h|Y@7CX+*n>%Oe~(?q*=Ri% zt>^6~H3gf#_m`9Ozd`lkie1B1dmVEv{CBDi%(Y<d<^7x?cnvda@G@qmVDA0>%oMzc zIYaOgW{%(mJY;w9uswrE>{&c&)ARl@dm6WFX1ssWX2$#5_A;KbH4l5P=Ap;cJoLDl zXU^6<^EMgxGi#_(U#<ny|Ncdr{`W80<Cxx|W&+bYSo3r5f;q?i8@A@(v}<_F*8JPH z=HIdDdH=3W&-?dmX1ssj*8B(d6h5>y|B<cvk8RC=VvplfTl1gU{rKEw{@dT)<C zz&aPg85=kg)o1NN)^m0p7o+u3v|hHG)KqNs<sOCCL(bRBOu?M5m)`O{?CYgRFz4!} zN2oc*%oNt?-#hGe<&4<M8Fh_v=y#Pf?i%GxcwISduXCSzr=s;~TRAhf=9%|@?`7WJ z1-pei_7PsRmAPauW8T7lD_+681ykF*YE#?0VJm;r9>iO=a<*;d?AXfLwUx7H58-`V zb8^2z-#R|Dxv#w^w)&ph>dP5Iz51Tp>U&|U@1;%O2NIjU5A@jdeW2H-?*kc|z7OR6 z-^^>cV2|UXy@pHn7B1UUxMI&>_J5a;pF}zRHt!!8i0TKUdgciAnt``q^=;bhdw?^9 zb@n|lYAb)tRz7<|jpmuKH4kUL%Ad5A-?o*{o~!)XB>npWt<TxIZ}avBUa)s?$5yXJ zn|%+g*veV8HUC;vzaG_-8~&bxvp%qCtM8Uw$J=%T@7c=Vx0QcjYo0?}^BmdAKem;B zVk`gDR{n+mt|W&q?L2>%o7hXZ$EN=mdhIIC*uyw$moZtN=wqXTi&1^a?qi+0P@{b6 zg10fb!8J@>u<{3N^&Pa8Q@54Fd9HGrwsMAS<&668gP8pbV>YvYVcb5z6ZQ#i+4FeP zUcha87Ejr8c-k)G8Jk(YK;5UhCq+zMa0z#!`bE3K`jV}_%eMNi*y_7#tM8g!#p|~E zZrPe=+gARLt^8eE`FpnV_ig2KU&74F=i@C{`6rQ2?H222wldG{ReWJ9laIHMGtbux zaBG6OXAkz+%<y2=ZsMHX!g-tg2Mad&4|0D)4*3t3Y~`12<yUOw*Zg;aWIxz%ll|a; zeS`<?GhDYjxM441<_mwfs9r<1W*fGvc*JJy!BLyJ9vrio>%mr3KWX=|-nP|u%2wZL zTYWiOm_dCxTW}3?FM`#V{lS`t{lUs#vX#GVD}TjS{;I9~HCy@Xw(_?kZ`*CwcWh<u z+U$F9&sOHXtr-q%W`FR|)(j`MdY#(JKeLs8ZY%%7R{o{kNs>%rlb`9a$<Jhy^zVgp zn78nE#CgnHF!w1_u=jD%uHuqCjLSCfGZmZnnOaoeZ}+i2U@L#n=Kf{sHv2LSTlu_& zdDM5rR?eucoH1KD<F;}pY~{55ci$O2WpfWQ)Aj+Lu}|=<J&)(?1<d2{cj#Qt@Hm+3 znT}n?i*^$;U#KbKWxIseqWX2a!up1-zMHoCZrSR~Ij{Qe*j3hdZT00mp+@r@+R8t& zm49q2|HM}QsXd3!Y~`QZ<Uf=|?y*~}_u6DWl(AQF)+Y0zoIQ{8_6#oA%<xdzR<DY! z{Hm?|K3n-UTlxLA@&|0?58BEn_jCO|#VijE+063Lu+4pXXv99lqjm?6*^7AGR<8+L zv$gChp0vq+sBLq;ho)@K_YgCMc~s9Cg8MMJ!RkwHu=?^inClPmI9Pp`>>6IShw+-N z{B>LT8#Z|lZQ9D;vX#GWD}TpU{;sY3gUE+=n|1Ev)y&5>{U189m3eA+@R`j$c<9__ zhU<w<uj@TF`PX}GX1<=W$-kbp$-kbn$-kbr$-iE(m0$MP!1UpYUBgv-4|DDNe9T-U z?>g7yg!^&5-`>Ro_7)zrxqsK|_6Ba)o49GO;URk+58Eqv#9qatb_b8yi+J2-mg^Jt z0&d%Vc*?HfX<O%-Ngd8L>-7!R=j=^9Z);9+!`U?_a|CNn<_OlDOE&wiFWZ`jx==&U z>(m9)^E$b~%y^yLU}n6|9KrpVIfC1GCtBaN2Uy>;HUGZNzUv3J=0CJG|B<cvk8RC= zVr%|WTl1gUn*ZF^{1^5VzO<SD;lv)nJvQ?{+-o;+#va01dl2XB1}@tDxMUCDvOS6` zw(_fX9rxMFVNbY+TBk>_)_EK}hI!n*&kqmVWIW6n!g>wUFIY3PCs=13x0N|z>x?a1 zGf&#|e|Xwf{*0~sSzGyYHnTk3Nz$)RQ~jc?`Xze@FWaYh#a_d!_6Fv0_&PVPKfG>p z{b8<!b=~Jpo4kj~4eRQ=Ypd^`t-kxV`X1QIKeUy9WOwkft^5;v4zoY>n#X7M3_iDK z@rA89FYR`cWP9(fXEQeUJe##waL#6)Y~E&`Y{6!pY|&<(Y{_PxY}sa>Y{h1tY}FpY z+@mnR=Be3D%&cL32s2agAm%N&fvF3oHcMTw<{!34F+IY%@_8Iw$78l~TG9Gsw9cMT zPi=O}Rt{$f>&%|z%)vE0Z)@fSoBr93tzL_^&bVZ2=4G4nW!G%wuiMJsu$8}Q591ww z?WO8>ZPoADywC2Z*6Vim!0YVG9@^~79@$&?*xtq`HvO}wHvO|_HuGlB?R9)%ui#62 zm9JY*><;d+7jduMk2CfH&f9&sVApWb=3I}IQtMogl)b)zEA}R?+RXU~S>fwc*D+ba z%=rktgEi-XJ&y<N1zfjhaKoO(O?wIt+0%H~Ci{^QyN$=A^$DAvkF;#fKWT4b_Jr9q zKRvGIr^nU&%yczBGX-n@Ia~AdIIL@a9tUgwj!pI>i?-%pvPbZ;t@&5%Cgy&HoFUA7 z!Gn0+<~}{LW%uK4djRj)qj=X={+?aO`?hk9qV?lw{lp%l=G0csh24iQ?Hd1PBC(nI z(H@&KKH6*3>(PwO86VBs%=~E19>hhP{6|Z+^2@gJEA}wvTKKwX)pIX`RZnj44kkC4 zb39tN*Dy1M^$pBS!7G>^!K;`a!DK(md4iYmxUIeuw)(bg^_{fUw{0tb%2xig-N7@q z@@MTi%v<O?k9iBG_R$5K+DF-cHRqyD&qwKZwNAfa-SahD^Q_yNXT#P!o3`fJvNg}P zt$B8A&9iH3o;{m;_UOK?c@FF*KD3AMkv)iy?FK%x`|-K0`7i8Id})*aSYp?4k4?^F z*=Ri%t>^7AY6`Y;%61>F*fm_WnfWoUh5I>zxfZNm%o@xYA7j?;J%5a|1@rzft_3Tf ztYGC2+sY?5th4smxWDF~Sst6PndPyTy@V(24cxYQE*_h*=kT=6^~Yvx)*hoS{F{P0 zrY@Mg$L8%mykKj7`h^<Jvutag6<hPH+L~w0R{pxJe6EEY<!{=`-?5dyYb$@xR?fcN zzz6mKKD3o{WGnyJ?#E}g^3QGMU)ajOw8_sUHu<?8oBUj_O@1z8lb_2c>A%Y$KUc8H z&lT+@T(Y?bxw1Wr*%SUv#~fx)a2wMjcpBGi=FHJAtWRR*3)Vc$7pys(w&oeKHP5iE zc}8r_Giob;%vS!mt^5gF`OFu3DSygVKC^~(<;>U(JZm#=Zq8QDysi8NoAc$E?<#-U zR{n~u{8d}|Yqs*&ZRK;ekfZ!fTlqWwyI}g~c5V9S_H6p+_U&zaWS`?>`x2j|*4NeM zPVExDu+@t?{r&a5%yxsiU}nD2W4CbDUcxz>v);(ttGHk@<BhUS{~HyX{x_;N{crT8 z*4J0wptt(!YaVY5+C#W*4`Z%{nkmfV-~~KlckrmajK}O9%o#$x`c9_S*Y4eD+nn_V zxvJ6E+})V9$-XgXlYL{}Ci@1xL%rr%it6bd)>Xd})vreN8<98dY3jFZ`rO#I$-BWB zLMC(F*tMDK#({l~4{e?C$iBqKsqf3-v#6duAyf6d1*@JnS@n<iM$XuI*0XjQQy1#{ zG1r2NxL}tsbzyxHSL`;f+EcjCUcduU{a{pIkLnvy{cz+FyF<>Xy@JQ=O+0Qd;R$;g zGn3}LpR+#BOu?M>@o77UXKc>#_<U5)+*kGV4p#kQRL>k?U3*t;?!n`0Hs^kP-5$al zb`3Lk*xQeH>^Zz^Gt1+9HnTjwZ`0@Tqp1Eksy~V9Pow&a$d@)VK9Sg4xW}f?6TLR` zK9RAR_lbP!-V!d@Wn8o?m}@#$?;x&5^?gx2=MOci=loao^~epIwI`bPFdnieFptAt zu0JtibNz{Ndl^#~YF2Q|Ud5C4HlB{^XQKMqsD3W0??hg-cgR_?4=}w$-&0KQ;5|(5 z;C;N2`T_326Pxw`-m(WV^Qry;&i4fSgH_M|VAazvSoMcd{Yhlz2sNYBoY~xuC(i8| zd|{8{OM4<o^1c4IpLv|I3pi`{;hbH=)P;X5TEf%?moaa_+FP-UxN0*?o-EZ|>%nA& z`VHJ~Z(`0I*4Hp+4qnG~TQf9l&XsT4^vMs|^vQEC!d}+$V^RIMea<@PS526w<#o+7 zX=|Rgt$C*Gbv$b;f6gAp^R{vpY~^%p<t*CDS+bcczijJVEA|LpwK-Fs+^chu8?3%t zw)$?{>bqmB@2;)Bd$#)S+v<B@tM8$$z9&iYE8MFj&;L*D0zR|*@VQ;X7j_9>+GW0< zL9fl;Co^^tXKiMDGH28ON&1Dp9n7BKCCr}S8m31u^FK+C;3}@z%=RR8VSNbqNA&}? z`VQLaTesD>VXN=3t(*~?wI@fT`mv~f+~)n06Sn4T*<?I9X_N8fw5@#V!pzE_wKdP2 zt$F5c<uBOEr!MSO{-Uk?75|&=JYKa6c+IZhb-NF5MK#-Yk@X#$+9!AI6TD|@@4n5v zPaZ|<$96yK?D<uFTq)<&R?eAS$LID0zOV=Ir9H^^#^|+cIAfFlRMsZ{shoX)Ie+Ne z#GF5v{HHiuFnymY*$rH^mEUJ8pU2(#pW<<_@|iDK`OFurd~$=8Pj0aChm-W**XQww z&0J57+7&!z)BmYfR5NKa`%`WE98aaz>)TV)USGm9_70x4l{shg{;5v1zG(Ne&i?Ry z0F=L+I^?f-eU)|ILd_cHEtuM;)@^E^+OX?*)1JUv_5j|t2l1X=!~3@8Ik46D&{p3g zTYZmh^*ynh_|#V4Gh6d;wlH&p@3WHF^nJR=rtj0eHhrJY*z|omYt#4XoK4@S^EQ2- zF4**ax@gn)>5{F!)u^V=o@1Rky7%^J<_O+lo%<E6UW4{3CO51vVRC~t+ps->M{MPf z+B(aat^9FY`RoZftGHz=f6`X|w7*9L=YD#|=G;%u+7(Q{U(>IB&i8aDs#&y)tdkpR z)-k!kCzv^|_A*B>c~5Ud>zj5z>sz*Rwr%C?*mb;XPvAX!0Pov__{gr|V_W%TUCnuF zAFzIAH}Scx{0m!sFYQK>6nbs)3mKdILe^&fLe3_?khjS%6m0SfMVtIW$yR>V->-vx zg+7~o1^WF3Jr@;BzhJHx*dMGK_6L()pkMGg9!jm(fx@uYm+*+agGX&;j@fg#6|GO& z^e?n+<xiy!`O{usWqrn8!?X4>CO6Esg6D0{QCP4iaK|3Ni}oO9PuR=-D9|HV^Uxz$ zeb;UE-LTbn(^lUtyNS1L_1&>G&#v9T2e$ei+Uk2`tM9R`z9+W&p4#erW~(pvF3dcE zFKqR_wCVdy@7<bbGWHznS({$Z<m?@sx9Rmv!Cu8hdkL3pW_zY;PvAaV`J6M%rhLvB zto#96`GdCd>$dV6w(^JlJ!i;%X2d4@nNfQmkEOoG?9a5K`pKxi9o0`o^|MhubN@yC z8d3gyRKF0_Ghe9DJj{1h&w1o)8P+*Zu;$rtjpp365Ac?Kh_~${ycgB5C*-S!J;AEs zaquxdv1|C$p2TOV!#z2-S^r{^q~EuviF@oe?zN{dXIRjE;NE;OAJrG4`eIaHit4LT zeP2}1d?8c${ZW109%8*=4`b#F^&^;T!J2c_*8F3(_Kw@yJ7H@td#?7<`)Y=1dybkJ zdmi%^YR>RN>T3nuv6Z=KYo3*;el@CJi|W^-`mLybJF4G_>UX311J|F^>(IWyM^XK; z&AGpL;+ji*>h&yU&(*oO7EI=|iOuzAdu*;h%bs7?$3PwD>^Ypb$$qwwS|4N2mZSPg zR9}ti`=a`RsD3c2r(fu+{6<ti?Da9$N9<`lYU?aq(_Z}=e0JRH%9*gwaN8#P*(tk; z$qIc{Gh-`r)*ixhwr1$q%=_%3t;{7`naj5JuB8t5YTYLL*^SiqsAkh<-e-4QQ^UJ< zKi-S#_oMm)*9=f|Xe;N$R?exd9L}lphQ8;v>MvZQoJ*VaVy{h3F=LZc%%)aOF=wkj z?;3K71zYQ7yMZhAD6XasIeoU)*&m)$<qX=qFV=0|7s(1W${e;e=ZLL2$qF^vJ7#Nd z%P!$bTYKBK_D<QFVb<n-an4@G^QrHdzzg;<Ub4w6QWx$y`-&?z`--bJ`-&S;&1O`y z71eCpWEA(J`u(W>AgVu%>QB<|&vtE*y{9%a7SC**<=keLn~6P%du;B<&0d?mH#0VS zZ)R=Iax-Vs>t^1b#s!<R-z?k1xMHhUHLB^em07bjL%*%edg_EeHybv6ZZ=(WhKKA6 zOuygI>)Rk6u{ZFjP5+x?HvMmo+a)|<GyBc9oyW`+GS!!v<ZJ3XV_)D|*QoEDt-kZN z`f|>YqrM$meHU%@U5VCLqxH4aq3^n_zVx^{@20K3JN5|PwYdj3_v|seZ;#`nsOC7T zIf-gcZSKKMdWXJS_|o3ydyyuouhnpmJ&b!@!(7j0Z1z2ux5;^~U@NDXI^>jW<&<5c zoQka+`gP}duHRP9K<bb)Xe+1g8s#)><!~+JaBrR)vCr^m>X0*Lv+uc<Ym_r-@8Y)2 z{eEuBR_3g|h39O|Id5z4f~~zv{$7im>A7W_Gd;IrpW)TiVYZE^elx14-(S+N3)Rz4 z4)yd1>&j=oVC5e~^@maYNmPFt)sq`C%j`YBTmL0mhD@%1smJE}mwN3BoUt!)KB_51 zHN~i=lv>C6Qq}9s{G~p77S~+E`!8{}Fxxt=yJiSC>|xw=O$&1^)X!nAh51J?Z^6nR zw@2|rw9fvpS2>fma;9CQIcIFmKvu}q4Afoq>O}R6QT<X>zZ})CCF%F!Y?8BXxABHO zg*R=@zZ2E(M)iA9{eDz`6xAO`^(RsNX;gn<>x`H7aFX!UrE`wp9-BE!S)2JwIh(zu zysf<jTYJm4_EzjET(!BEr9OKebKg7u_%98n*607Fx~<HHtxWn|)pJb_^`lY!SXAGN z>L;Umvcg{FPet{!u0Lm;SwpW2%&b@S3-$!-9oJmqMXzV^ir3HZs;$g5Tbb*&_HOxm zv~up!woU)ij(v)EQ|oiu(m_;z7}Xy|^~X^?bNr_6v+|iESozEmtbFE>mH&LN*SVL^ zXY6Ur*+M-T&*xmv_2=2s&3V3H)ARYV-M|&QiK|gfpRLTAJ%syh&A{9tpZCv`6|79M zf|bdhVC@}E9nQjjtzVmEeLS^3?|pv4=Kb?+*U<m@DVzS!b7t)g^)pdDSs`<PnmJoJ z9a}kzwsMwIhn!_w^((GX&Z@2T4O=;zwsN*ohn#I&^*gRn&aSQX1G|9_?NNM`I^-PN zT0e7*a?b5Rd|}t|rA_7wy*6{ckg=Kbg{;lq7jiaxUntro%v-pJ+FQ1@w_-EH3ta0y zcQ0@)c$sys$@fg)LHii{<Kdn*<~a^Eb9mUE$0POv9*=6s3iYaKMKzQ53hUER{Y+Fp z8`aY<<fy*m@3*{x7gJv&`-LT&wHKD{ZM<d|@VZ^Z?ElN0_gV>W+Jkr}s^5+3_oDj! zsQxIbKaT28qWaUQ{vxWsyj%Zba<~4)p1bugX7AR&n2YN3Q9Wl1XJP&q%TawLs;@@% zeNp{DRL}m9!~J=&9@RIZ`r)X4B&r{c>c^t`R_cU%@ZzL>hTHZzo^pK#&qnogQT=>W zzYx_gMfJ;3{Yq578r5$^^_x-sR#d+o)$c|1`%(QtRDT%NpG5VXS@%<)i@wNPu+Ga{ zxX+xo%;m67ZMo-eeYy8;eVMwe`g~Mhi0X?`eJQH1dY#$JeKs?eYc_M0`)%eb*Q5GI zRNsv1hobsXoBLWGv(;-nwf>x5p0K&E<+f|K@RY6fX?q9H*n4>1R{nymy&YS7=@IUs z_O95&c-0=mYc|>Cb$b?*8}?4(O`BQD^a$(Ym>$6`%uK<`=bXXHKd_a5Xe<B7R{pWA z{1aRGr?&DhY~^3t<iC{I<iFHolmAk$P5w(6oBWruHu*2*Z1P_!+T_1fvXx)9m0z)E zan)9SpRN3wt^9sl`E`Ho))H>mYq**E3p;oywZ5mwOUx0zHtZaaxJEgnUO&Oi7i!M% zxP5>pZ0`3<><Klym|27OaogU+Q?_Q9wKeCQy@uyghdCEghdDd0(VUB}q328N54|+! zvVDeEY|Xi9YfgGx&AD!C&JA00@)l||CvWl>YM8SH_v1Z#1hYS^YaaRqH}Ij|#7FiZ zKDO)l%&ub2cGc^`*4|5-UbhmPy|;R7dfn=^`*Fsm*R6c&2bOWcUcp7z?BJ43|666( z$Q7?M+b!NS+XJV#&pyN4m$1&cZ_zvW5D(b9m^s4wKCataxM6Q&&KYV}@sPcSM^o#2 z@Z1`+FY$Ql2RYNN37d1=YS}qFX>$*5we1X^va@*FPVkJ~i|12+fxKG_HhH%?Hnq1F zZPsor*<{~Zw#mM=mij^Fy|r#L%dL&nnL)g1@8B)htl(|0moe9Le;%agtzDa*xAtt! zvu|sj16%VP+M4IYKEtQ>Ip(qQGdaxTVD-JQd+?>*%g=>KQa{Mr%Ulcfti7D|I(=Ry zE6hyx%X!ymZ^7pJ%SBszOE!5g(>v^CmX|BGde!U++;6w=Kx*C3mw5~GXua;572L2- zaMPZ{Lv{xb+cS8?p2ef~Bp$Qdm>yTXxE8E+-hw-L%3i|L_B^IXs9C`D2v#p<3f64Y z1(WeIb-|jAtl&MoY#-s3)DIow)zsGq@tW65c-_`K8+IOV+C{u&_u_3kgLhJAF7d9{ zdoXi^c~0@ZeSw+jYR+SuwU<v)hdJ4!nlR^?*EQ$4y@bh9%|n`#-oeH2<tV9{v%(x< zJ%f2HYt9Of!#dY1S+CQxlC#OKkQHjiF};H)aM_;26`Oe~ReK8e+0(dYPvU;NjqCO( zZrJM8w6%B0R<B`Odq-^bV*k}_W43y=QfKxtk5!X7!0Zq8$C&-{b?!lheqo)nR%UF? zHft9!bA*~Ap0|7Pf}O#g)ZsoadcBABC9j|1W&0ej*oS!4KEfNR!)%*&p7kxehPUkj zykl4KuHA?C>@wcBEBL_Hx#%74LkXXxeu#N1r#ACem^++(9W!?@Ju4SBvsW(dHGVEx zZ~C)`t_|aiJ&&`g?<MEUIh%8Qx#*e+%pCf;Mb}hcj_NB>J?9TKs_(bkn0pb{r|_Vy zoMu!%6xB1|RsBd*KW;Pcm+28|be5LAizn>^JRQ}~*qrIhvr+wARL@Kyle2z#!B+l~ zUB%1M`iiZ-tG4=XMD?3?AM0CD{dQEpW7nu5>*`!&1*`9&t(+rUeUEMRJ+YN@Y7gU! z)Csj;zO<=*C9%2wN{{QaxYz4sypplcao!%p1-p)mb_bX2MO?OraK#?RHCs9TwsHn+ z<#0`BPn5&8VC6Jy<?t5P>G{ftO`lgrZSr0jv(;<d=6=31VRJuUY1_(~vXwJ!D`&=5 z&aADRIa@i*9p=ek<_^~VT(Wup%CfzVSL`voYER%byMd_-IZeD_*YKvT*><A!UAv$4 zJzIVEZTh@&U~@lSIkeUH$X4HDTYb->_48=`!dCvJ&G}yKwevV*7jV|*Ot0qbElgcF z;{v8GxPy!KBre%)T(+6{)r#H1RhxaU_Sx)vbs(x4w3S)67cplJeV6cXR6i2ck4E)l zQ9Zr2SAQS<D!KAK%=jv^1`pvWn~YbdZF;^sV>j`v-H+#NW_)$t=1i|H*frd-xd*Ru zhR~~uS5k+0R=r+iea+T9>o#Y7b;IV~yt-+t@0P83w(SADV{4vWTl4JMnrGkEJV&X+ zJjY(wJSVp1Ikh#<nXP%wZOwCGYo1G+d1#TIoq4J~HuF?_ZRV+FY>KP-)S9PSu<27} zrf?6*sFrN5SIe%Uf0ZoNT%&)L9>H4gkJgzf<j}v$8G@D5v^6tl4(nX64%@u1j@Z1f zj@$IFPS`q2EA_n%JZZ1vwrfW5l)Z|lZTeSdZ2DJc?K+;bl{s(M@PgfsJ9ZT>+I@H> zTBlz)m)6%(hdI}6-d8tVvxGP8WxQoC;BA|p)g7C8tGhNcR`={Nyl->X>Vd6u9ojnA zkzK>bw$62CPvCRAg)eN)b7?crYl+P~ul3l>^IESxi8D6yyq34yxL{A=qOF{gt(>ZV zE+l!c_1RfmvpMf;%pHDq<TxI%Ipb@C_6V-q?0b!Cp`O~;nsylv*%dr&GvjOQ5B1FT z+Nhnw^bYHJ+_E(%XAbL{vu$h6DO+<++nRI6)||7p=A5%N=e(^s7i`Vhu{GzStvQ!$ z&ADuA&NW*(>$Y+>Z1vr=`|(axzZ=!>MfLkp{gItv@3F1>aAG&`sXc<vZ1p;~Iqz2z zo1Cxo*yMbr*B-)L3-@^#bGG0KT(DcXnEGDTa9>n&ZyR%d`JPE!u@7-Ib)xk?uQSV6 znCU8i&{lpub;xhn%5SC)`OF%6DW5q)j`BymuKaO(6LW@8zlG@$yp7otyo;w(C)9pr z#@0Nuslz;Tw&t04%@JO(PjJURz>Bu#T(Z?`+1|%1wq{$kHQSo4bFJGOn7VM@DNJ4P zG~Th9{VVhc>-7H$b6nLk$5s82&6&P(Y%}{;&g=<%ZtFf=*zEhtrOkQ2n%MODYL88y zulCx^^3{yJkF)j`&e@#ft9hH5zgn<2aM7N|C3^;!?MYm*r*JJ=@3-5m57<k1&{lrk zR(``){&2KD60MKg%hZh7%HbY`dn+?j@Fs4j*2nEvnNREYXq|qc<`UB{tS5NZ>*sjR zzQFVL30|;IamU`li}o&FNqy}Qucp37`D?c3S+|+xt6Ne1c2rMpm`(NM2CM$S^;4K0 zTEC|Cqp0TCo@1T4Lk%;2_0-mEXEyiXtLOG?_$O~^J^6h-UMIh=H}ySo#wNcn>zXB; zv&rwv+vN8ZY~`2jO<b|JaMj+%eYSE2>?u5GYleF2Fi*qQJWbbVo*`SkhHcF=Vr!o9 z)X4^(uvOnmeUCCH?KRv^eU0<=F;lp=yzgTsIl0922<trTqeocZ!DI#R;*M*E@uIC9 z=2lJUyKGb2NAHlS`t_)OBdXtw>ggBi^VHKXxPbTUBHp)^c@)(jNA)LB{i$7}{vz_F z-Otal=ggtk0PeBLe?6NzA@B8^P2THy`y4Z$_9kS%UQVrFJFi#lL0nCJZw>d^%IC56 z-ZPGwBX|<mZRIp<=6b!EI^+!5%Hi!QXT(;{sNIXlZ035sWh<Y$uvhtQTk}lW%9*yg zAFt2Y%9*v5KWArf$5#HLt^6fh`OCKQS8V04+R9(EmA`H)e~Wv@eY?&quW#G4cqjG4 zti8T#AK*QE5bxU)m}?=2KCd6z+IwU(`|HOxv%h{~&*4*h0bkfN_|j&cH<Hwv=Zzkl zo^SNpgE(U|&l{XS%(H=Ww)W<2=6s`Ib3fiF+RXVz$!5+s$~JSpQL&lxjha1!`)$oR zkUGrCOq$_g%~`iud!u1%&SvWCnsdnB#>2Me9I-X$sI582Y|S}tYff^**)?a|p21VL z=A2F)=H%MdoLmbYq=u|u%{iYs%t>y@-)6mIYffeg>zb39f;H!|tvOe0&ADo8PR<|d zndOa5TXSxu4s+5^HQ|2l*n`yU+M07Ob(nMCX5SkJw&pyvHRqA7Igf44d17nMQ(JRh z*z9}b(&qh}N$Q80;msbKd-G=YZvC6Ns6HRn7oz%dR9}het5JPlR6k&A2JVIK4=s~7 z>vje=>>_U3%=qSz-HS(4KdhWFuPbNVR?dX2oR+PeNn1J7(fUlZK5Hvy&Q=chD9kJ` z+Piou^&=&`Y?JrqT2#Lt)o(=gn^FCaYZll`Zs?`wWzS~coBOu<9@s1R&|bwyHgmms zY%|xJXZ9REx7F*y)?V&u=u59!Vzal_W7DhFYj<$QrdKU*mvF%@<6>&vpBit<f24`I z7J4;s#h$}eyC3)2b<9Aap4uAMg1KJf+Epf5!NaW6Be;!+>}kxku-?KW_9Py)$MKjw zfq5M2sjcxinCmri<?Jq=viC4O!uk=OvCr|WeSqieL)=OI$TnWI_wiEd$0~T)Ucf7< zAML@bHhpSqsUNw(>-Htyur<%7t$DU=%|q{SF3rOk<VPErIf9#*y5JV3E?9lZ4IahE z_82~~hw-UBf-merd}-6`t;A;UTRk?t-s-j4`&P!L*IQYe+1|?8^m?n9`jH)6vUhPg z^<!;Zu@`XFX6>y$djQu`>ps8LZx3Rw>Aa6{zPETBe2(k(5pLMWnE67@9v-sy@o4JD z)N9Np<E?R<_is(uEzFy89%J8IlQ#R_;yht}7*E-{SJO7LyftIf|E>AdkFxgGg1v-0 z_9k9*eS%k_`qij@EvjFS>bIi$?Wleys^5+34{UnAb!gM)t)tX8YWUdJY$vI6Tz~7- z>lu8O`Z3ntI(N-1zVN#0FKzPPPHg(W-DA`L?OuBqlN;{sKF-?A@OIATd~fG%?!nsy zdjps4MO?90aW(agA>3yxv*wyp+@Cr(fd{<K{BIB1n!j!z;D&vOoAxfI$JPA9wt9`& znt#;R{A2b8Zl%sK<J*&V4YzIb-k!2G=d{gSZ_n7w_4cgIIo_VL2XV));6+=#mTc`^ zw$*FJ*4|ZHz1Hj+<_tP-PQA8LKSti$+ctS`@1(w=^<8@t@7Y6m-yX*YsUJJThpBU# z`N-?MfBV?x{o5xt``$ja+4na4!*fB;x6f_*ynSJ7hD&=ZNxqiYE4asA#o5$1nC)vh zyM^=iJTBNBT(oC#$)3Yydm2~l8C<m|ai2Yf2U6=}@@s>(GVAscZn!>!hokzDsD3o6 zAB*ZaLwN3#Pw!ymx1)OI(E1JKbM2~T&gT8sIDc4Q#0&Ns=3az#*1pEIVBMdU)HgK$ zs(p;vqnaCMcs=#wJ$S?GCwS97#XGigc5UVC*~-~Z9dZu5uAD<#IXn)1wa(*Ut+W4X zp7Yeo=}#i_ST&EYvEFM_+n-7O#1PI$^@XUu7}b}e`l{F4?CrCsaLr!C3~|+Wz@B4$ z(4NP2dj>b`Sv+jF@QAHmqqg>r+3GcJYwv`uUhEGuOyNmey{7G6%;Qj#!R!y#{b9fS z1oxnyeqp_e7i_ZoJGN?=Bh*yzlAXoNb{?;#4w>tAne`33jyLTl-m(Yqwmpb<>>A#+ z`|+Nw8TRcye3UwT3>@3^??180?mx8;@R`jl{pU8bd_771!~*WImvL|ECkr@ZFX3$J zJo#VG*<^p6dlByKF=mgPpT<S6GsD+Q_8~6YobT(LE$rRLRa^Oe_AchWgqn5SZ*SrO zdle7bYq)7I;30b%52t>TyswYgI@hRcj`3LPJnz3g?sd&SVQc=Dy@x05ecZOU@szFk zr|oq-V{86dTl3G^n!l4eU%`uZ6*FtNw@tikYt9vW0FxDJ1~FN|HB9f|e!OLu@V2d9 zJGS=j+Um7uYcJ;vIqG#_SMi~(UMH!a=-^YEbA0_Q^^-IB+~!PQzp%CU(rzTlJ4xy% z$a|+Jb-sjqy?%f*HvQkp+RXb-&Su_s^7b|^*qra3qP>pE)w!P7z-61+-l^EjnE6!m zq-N{4hwy+si3jZ|T(>7Md&1rpZrWp*{b79^58J$dXT%=GTvLrcCf^||cp8%xyp8D{ ze1^GpRX-Ee&qnogQGF+>UySOPqWa~iel4n5x9RiFhP{9{?G?Ob)AJo>4YSSTz0^-~ z{hfWA>+c-cti5w+pWq{V7a!YXymMwN=iFA#g{_=Ro1AwOo1AxhY;xYsM(ep~J#Ulq zZoyVgIdUcSQ){eOQ$Ib5`)uZYw`TX^ew*v>)>A*J%tq>`7I4!wQ+UW$4!OFAPmSO) zTfN5ZX*^*or)Bg0-ASAG@3w9By-Saf$-Z}IZF;^tXRFt|t-TAjdUb5=U9{C}$<}Pk zwtB6le)1Hr+h=$q_0v0e)7E*nY-W6S+h&$`sS7jb@UA_C_v{|LZ)fpA>L<_fp?!%@ zQa`OsW>V(Uoax;&o4MX)PgrM`cQ5QU%>J;xo+JZ_y@Kf-)>m<_y@)gRGR~*gb3IV7 z$s8!UhJ6DiyAM~RdLAoZA8!M-sJ=g{uSfNbsJ<E14@LE(QO%gWPX4&PjVJ5_+_E?E zq`ifwQx|&hjIFcG+MIh}&aU8jJBt_W9A2`OvurD8#a7O$t(-MmIn1s5Q&0{w1#5jf zTHmpivui7dvxR#3&_2gUsh^q0$Em-l{1dO&@Ton9FH#qjb7_<Pjl?ypxF@x8zQKH< zFX#RSkAs(S-rmLqTRBC09hdA4T(*@@?~t>GYjy|s+v+u7Yww_~UUgf08@75i?PWY< ztJkPq#bb6K9#8$u1)fM9&fD_3_D<ScxShH%jHm1lp0=6m8#6ZjzcFjq@SM$=zQG=y z{TXF0+B<m3KEa$J)STfJ`v@~rSU<*V_5ohE5AlY*i#P3kOpkESRnN8HbG+x88m2Df zk74><)zj~)p7}zJ>QAHki>UtcZvA`7-TL=>?$*DTjcRf>8Smv?(~Ao>@82uh<h@t2 z$$PJw`irXRv#EWL`821#C(wKS_5vPA{oDo~^t$TnUZ2MedkHsfW_)kRp2owepVi)x z)Hk^|?~SJZBJbZDvz0k+ll|U=P4;^&n;GAmv<Gn8uHq@X4^P|NgZF0a3Z{q7`$aO| zTd-Msuao*YdC^|Nys7@V9A387cP(|uS+}*9`xWZtO<OrzwsN*@<?N*nIs3Nu9=Jw6 zw3TyYE9cl&&ROb^b8c(zg=^$Xo1EK;P0sBeo1EL()cQEN&9!i^ia4KIA1AlDru8o^ zV6KJpa_-wDudBZ7b!BqjL(Md<rq;*9ZL+kkkB8f})L$IK{q`hgziPh7$HVPGyNT;I zwYRwzYSfEs!SuO3WYg#Nu+5COM{MT0?T@!-RWp&UKdYQp>Tq7>P-Zx9JGFjY+@A8f z&NA(F?VYjde|t9dv*g{LOC8QT?{&^}d%;%ylFgZJFGuSuslz<0Hv4X`r4I9~dtLJ| zpJske^K9D6-%1_k*-jni+4K4&HTyPay?tQoyoWY<w~uVjcl+4pOt(*L?#=B}dm3Lv z>z8-e2NRo|!5*9YG?=wpIA=54U_Q0(!(hQ)z{S+M4}&GIvo=^x{VX#NR#NM{gH^9H z^B`HeSI=s1&1UAoep|B**lo<vp?(TC?QJ|{@8IFoVa^d-bB?BdZWoW)+^50u)Hjtg zVQWs#A9|^N((CjbWWKPj`Wah&XH$p1bGG_&PSuCLJPuahPU_Hi(N^E3)X%E#ve(sj zEp^CQxA$1zu=nw%eTbP!y^6h<tl$i0j~wP?Pw*t`2dTq6?ALmDzK&8C8`K<oUGp$& z$Q;C{b{(JDHGFRO;|n{FFYQ8-yw7|ghx+%KFPQrGvo`tf=WO!dFWT&TzhtxT{c>uZ z>-~z|z}3_@4>8xe=X#%hq1QO;^b6j_1Ge_kJFIiw_vszX{O@xuSo06t${DdI@TlFw zWA+N>aoDT+$*8^^)lb>8)bJMS<vE-8@6X%3e}BPV!Ap^s?OoQnrkrpeR_znkH=_E@ zsD3M|-;V0{qMCi1wf7HPBOltlfB(oer})_G6-@7NE;8QdS}+;!U)a0&(kAnRB=t?X z$0q-SUe}!AjMvHkAnSGVKgikSe^7J{wI7shYCkC3)PBJJaIch8OI_T>{kCQpaE&}@ zYo5Am&Tzx)8Qk=`<{7dz&!}tEYs{whgK>KsPuS|!j_RkP`st{CCaRxL{j72p>>b=m z{iR8~XmkC8rPReLUbeXhAFSAAylQLaHM@Y<?GoOwvv||a;jPqqefxl!!t>sX_q@*g z5B6=|e{f(QV%}8$>?uBp>UkX2Reu)MpWD>lNo;!F>9Kb(y~7MuoUu9YovdBPIlF@M zHs`&=TiDBa?-XtJ-QjUqXWt$6huN6%4*SD8J@3#jtTXeSKAZF1p?6r{#r^gku1D*Q zXuWBlQ8ScUulaX|y?%g4Y~_zf>l4v>%RZ-OGIhwA_Bz+^%-CGNGiz_+Ih*J9&b+;j z7wiq(u~+e;y@r=;-rrfad4FfcChrb=!aZT%9rgq>*ByEUGs_)%1h+9W1yA7}yM=dc z&A(?;duQL){0BDKcMff`?;P2h|JY`hJ16!MKD9OfnLUrs?L~ZHPvc9Q`Rj?z{PiAt z3TN-u*K<*Q-e#V9!DgO%(Po}{$!4B<+3w(q%{=v5>YGj6Z!h41)cU-xK4|Y^2Gza2 zsr81vjfZXJjMzhXG<C=svz0UM8s$vb%4yl;)hF#KJZ&p~##a8Ut(-YqIrBFC>zpUd ztelRm{6(92>npbMS8e65*~(wHmCxglsr*e_`CGQ~sS7pA-%I^Pvg`Zy4nA<r2|i5y zTn_VCdqe$cRDTxLpWm(jFu7a*Vb9(A4}0&{f0&8t^Y(O-d|0sOaWVCmc>iI^?!#r* zEa8gHJ@~L@E2rO9&OqvrGiWQP?i%GZY~>86E>$u2OJ^^U_u**j7dP=(>ay0yy{`HR zdk(i!mlpA)*9*Aqb>{kT%5LIWo4Gz@f9R|A`P8BBLh8`B<Mk>v^icha>dSe;UiDq} zy85m~>+818&Y8pBP0X7d^0&OM{B4`rKio-OI>EbMSN@*Ym9uXj;{$sYAKLW)@W^Jy z52*_?ui!JA_aC0yy#Meb^^5fU@G`aL{3!7{bAHrgH*s(37s&Z2<Mjg0rY@29QO-3} zxaf7&mu&ieR8FnFA5~I^zE!XD{-Zv-iEF7tU*-$<R(%IjhrWZZQD63i8s!Yx<b5=3 zllRexO~yy#sh?NPgsqyEYc%I%>N5A^qju^r5B;v@nNIyY*FTzZjpmv4I(Z+>+2nmR zZ;#;xn^`{U*qrI3MZ1nyqWaaSe$7_?x~=>zyAN;MI@eC>aQ``5nE#mdJ-Zk0+XZ}( z`uPQXXkXwXyN%heoac4k6I=72+I7sHP@|knyOSi}OzcJ6W7Gee*}L`M%tiJ2sJ>vY zQ(ul;u{T(++MBq~R{lU_W(~73<2RW#+>>71u<7&7;i!HjsvnK&$D(?kkE_f{`;we? z>KEiG*Q?jG*YkMBrsp?jZSK=I=WOoNH#@1Hzrc&OGM8K<FQ<M{`72&8;8k1sYqs*a zkDB=f<!{+Fylwa69eV)p+R8ad9p*W-HN%l><m1#~o)fPZSU<JZ>&(_X=Qi^+cpPS< zSA)mFQ<$>_v#*h{>D9<b_4K%^FGlsHsJ@!Iq?|sR{taf*Uj5o{^xM2|45WU31P|I{ zxNZ+&hSuKaHFMMEdV_0WowWwnf|W^DFxidK)OvkukQ>&StI_iMC7$$pg4;ItqcLUY z@oZE-7uC;4^$T{6`X$$&;br?AuegR88>_a?yJipJb(=FaHf)`D({AD|yB}}c19->Q z%)53U-m`VaeY+PQqz?Dz(7t5-Bw9a>);UkOhXrcRZRKCsJ(&HWhWw9t3ugV}OthZ0 zi>&8taz5s<>h<}_$0d6Smu=?yxMDNc$5s0Xvp?)T#x<MsecW#!;sJXX58B+DkL&g( zZrD4xX|LiTdmRtk%Xq|I!Q=KKp0G84%Ra%A_9<@Lnt#gH{L{APpRo_|ti6lpY|TG! zZ{h`e2Y2jM%uM0_Xntl2*8IE$ui&+)p1Q004O{cjBdlwlEnD+!+nR^op@y}OxfZN> z*e|~@h1nlW#>Ypg_4(w-$F?$0T*KPOr}i1Xu$6OZPbbN@lGMuiR*y~2w|ZSe&bKl) zIp50KGdO3j;G#|bw@SA1%eHbVwsNZW9PYD~Q?r%dZ_nbot^9_q{HCq^AzS&ww(>`8 z<&WCRAG4L;N?lsQllC%h+sdbRcwSC0y@S^=S;3o_tYGz`ckn9iMC*&uI{mJ4=oh>} z{aWhsKBkA(%SV`Na%B|LFIekasb5z8w%4n8C-qAMc-J-5erqpvS?6L;$Unzq1)pNB zU9F#_4t=?H)%PrQ=*#}FuD%zkL*Gl+(D&QDch|q2u?JbtrdIy9b2hVlJD*zl-!6Ea z_unq2erXPuT%-K5*OgPTXE8HrwwIc?&mP7#yN>(q2Ig_7U%)&L?qK$ZGq&)MtvSik zdYE&>K4+ad!n$(CY|S~I`lUrY;q@YJdtLQYw)#$|uBh*feS|sNRo^*VedlfE@D^&+ zmn=E-rFU3Y-xYfwui6KA%|68I_Aw?a<fvxbR?SZ8Fz2pK_P6&^zpQ!aaWxP7<y!^T z*?%<;XAA2&*6A0V$0v3#KD9IWEcHuV|Mt1f^=5LnzS(oPzRCV>ev|#({3bo*mzb-` zOu@|6<Q~a7SF>c#;&SSjS8>JW-ZZPJZ`E+0y@+`ndXe4ix5;h}q}Ke+L0j{4fKacT zA)9^8VVix;5xb4Yqxy-cp1DJg>L+b7n$wYIZ1S3%E!2<VIa~Ri$cr}bn@g#~eOR`) zSYM0k*Q5H4sD3l5--&8=ZL*ttu95fcReazYGMb0>B|fs5rFm?x;4^y>pWDj3Nd2<R zew|%s`A*`RE!<;s{X4xj`QORd<bNk`AL4?2go`$_e5Yh9r)n?aK6?q*Qfr>?^xK+e zz%^TV&_2X<Tk|w*%`<GP*GTG@i+I#tz+?6jZbkKzQGGkApNi^dQ@^B~IlF`BQ&%(t z*K|KCN0@8j<0`?6b}y#4)?d27oFP~<vp@J0bN=9Syk;wN-9E+}Hre0Vv=8u({r@v@ z2SM?dcfRjiLr$?^!GZ+~7A#nB?`3kBDXK0D7Mv>T6jj5SVH6`K#9(ZdXsZ}8wuZ!x zwh^_Bt+v`mRE(%ZTkRyw4Cf4UE^~%6!@ZY#iv<gA6$=(DSg>Hhf(48F{(PU0{GUY^ zFP{E9pXdAhz<>Vw=O51byM0^F>cFP^?+$JD{T;n=mh$w5l|Re!%oOXK`FG46ZeZpP zHw%S33d#Q~AMfa}x$hmkBE!Brx@`8{(QVUxM~{7pdu`^rqt9lpJNj*AzGJ{X!h<$5 z-!Wvj@UXp#N9;8`o~=)0>y!2lnJHWS)Ak0QvDH7HtrxTP1$&oF$yQI<=KMRBZO*@= zV%KohuHzM(wL5q(o*`>@@LrgXI~q0}cQoxq%$*~%gxBnOylyks9o#1}-0zN-J&W7+ zB;K^A@Qyu>ckKzhXEWm+`!+M)abRoyLtFFnEN<pMwkxck*o*ko*8FGoJU+Ke_`;sX zm$v4=vNiv;Jyj^&*?B8}XV<O#o!vIi^UfZddG74Bndi<vn|bc+w-@k$%{+GwC+pXo zJ4fsy9!=Ko_wF3C)j96W3ZAeVc-mIajLkWBayLD<=$W(CL$B8VH}!B{SUt=a9>mNS z)^jM^>gUd}uKtRxo~o@LK99^WuG#9T+v+D5nIXJptAE{A|AwvpmaYD_t^Q40{ad#B zw{7+BCI2rIc;BAH2e$eT?HWF^d46{u+w=Iu)>)_aG``5zFSGS4TRqqIT%j=2nLKoc zyX<q^o%~lFxW_Ky-sHbz&Y3=&GiP{SdWL_=Y%>G)A|6a0X2zKzuTSIQ<iF6~5ofmW zsMmRaX3SRSxJ~!WgiZI%q}_>m7MkHNxW^1<$V1$9X2$CsnES`N&gK5$E4<(g-7_Uy z=PoA4y_Rg&X3EKNuVt@yv%Zr27wW0m>Zv;;H*EDZlcQ(V>+0D^j-HmSy=`aYO<O%% z$<edzb@l8eN6)^ky$8<7hqii-lB4I?>*_g6j_;Fmn~yUW$?<)1X%|_)N{;W7Yn$v{ z1)I*h_<HF1|K&99OxE|qU0un;-03cI%KXI$?y-5cclFu>xX&KM{Wg7f@m}nu?=Iep zuQjvWHRN^9ziZg*I+rsd!|ZpBCx1_w37c8&noQPx@0zlUcsg14y=%r+=d7*0bM^q{ zx$CU&an4=rm*c(*UgxfNm2Bn9Hg~;iIa{wJ$2?V=zPp%1oiR_%);x7v^E7PrH<M$Y z)#R9G!|M}dTJ|Jv+njUPrp-BbZQ0!Wu5FvU-nC;-;az(gA7tx?+4_;Ko@09spV@kD z=eB0MNRH=lX%|_)N{;7nZIk_eA^CgE{QZt(-S_*QUT5a-ciG(W``z|5?y;He`@Qxg z?z6e$_Xq6;9<rNwI9YRkf5c|a?~f+`<tiStw=wsO?+x`#*jt$M;`>K=&WlVxp7px& zbGFXqKFY+ooEO%)3(0YA$=11x$;0YdvUP4b`FlEd+3PxYB{_O(_8RMTdmYoIbN{l1 zc~Ab{5$3({G2TdyImyMG6RfwBW1dZ0^YBvUKlb5muWOziulL|xyBF`-op|5w!UxIU zJHv<eIX=nqr&*p{oU49vVf9}n$Gxs??saz|S@*h|SKN!4?`95pxP_S`%$@G;PX3Rh zm@}e(6>~;ddwGSq@7=s)&42fR&0Kd6JENWvdkph=>>bB^9xmg_EI*ayr?dQwJxhK* zbJ3n-eZl7ayGyqEdEK0~Y_GCjNsi}GwYONWXZc2!Z)SP+t5g5{-o24!TJ{?2ZD-_7 zoA>W#Pt3E8d4;d>j=hd|ZMyG1usQSYLtC9k$;0xot^N~d=)3#WR{xo;{&QRXS2i7Y zlZ$!im@U|J%y!tkKih4u;vRbq_a<we**=?jX8WDl!2|X&9<-TfcF1O)*-=|(jU^A$ zF*|PaHJP2T*YI?fpULuEAihS*&t>_A<nL*{WH<3*@?X(CyJQz}Ir%>p@Uq>BE6Lxx z!d3ekuh=}}*_wTc>-GueY|Zw)Q_R`nRm>}Vgn1TW-LYk_<F?J(?54eqce4C$mfy?r z`}P)j&WL_ynLW0dWtRE09`|Lwu<m>2%oRSjuknS=+AQ~sPCm|(3+uk*!t~u!u$lRu z4x3r-;f%<v<1V{}yX{rnW3S=<Y<(bGAGCMK4B6@*wm0yIt^V<BeIi?*w0Fr&+3K0K z*>}&J&Axl)?HVrHb-Z9#amil6i}o^JvMac3^Zq@&7te(E@8P{L=iEbAn7(`H3QuFs z4m0CDoE_#K_cZJ&yk?K%b$bGD*mT^}vgx>|ZEOBbTk~((nt$77#(Q?`MZ9Zk{ylph z@7pDOU{B*iTk{{;n*Z3I!e?3jJj-9$n&;BiJXf~nxwe_-2L*cpci7DHgYIPgn)8Dm zyNG*}_4~RX^x3PJoSyTr)(7kc9=6ppV)OnFMw6pw%vR61GwPYJ)iY@iV(uSj@$m<< zw)*F6_0QYtDcb5;u$k)z-1DY~=Mq-`l0Aegw)(5K`suy7Z_QSJ-Bv%J-}E<a^>fcy zSN}%xUo7L6P4)+EXSVRBeTsLo{BD-t%kukK{wT{IXZe#XPjAel{)=S&yWtNm?Rk7< z^ZpO6ll6P59~Qj6i1}PS`kMZ*+otD-JvKc*?6v9nVPA6e^m|=B1GajG3xyV)1=fBz zVh`d`yN$=}Q#@{y{o#aN!qc{TW^DD$+Ul9J)x)fDu6l~LdKPWY{Na+#nLjMs>RGnc zQ?Vy-)#jWZ)@}7PZ1ps4^{m?JS+mu%ZmWk}%&DGDTRmI0dbVx#?ASAS*H+J-t$x0L zqH_u#6$)SJ`7h$*<l8&(iLG^dmHCd&J@a}OKDWE^RdV!P+slQ*9M#%;J3Vt9b_;Vx ztkW~cD@@NEFZs4h+~ak!bG=^Y%(*`M0{15uDtN%I;$eFckJy@LG&$xOvo#NQyE%8l z>&!kk>2;kuW$WDO<T#gSt-S@EJ8$dUqOEfmlH=Txt#irUoV(<8om=+0&SigObZ#X% z&gHzDbL+OwZP+@unH=Y?+B$bFIiB;n*LCiO*L5zrn{(UAaqgzg`ExtA&fT?j?p|`7 zyKn2<gXG(;@S)dr?oo2|AKU6bb6)fCx|!#~zGR(Otkd};y5!sW_@fTH6Z4AoF3c<3 zjeE0vUzYFB@&j3ZIJv+be>7rO@TfB_JeK^Oam-6+6>4}Q`L=UB?RE9c*y@>0zFj?Y z$<Z_KOoR1e@@>a>(cZ>O_AV~ld>wwo8JZ#TD_NeIVqN)qmgkIE-)DU-%dcnojV#Zs zH~FpPcs|Ue^@8rTlN|TrJgvvQm@hI-GMpDZy33K*nf*t{wt7yIzte?J?QwjT9R26^ zCF>W-g*D9Q-}c{IaE5d4?Xc;-x6`KkUd~YdcJ|%do8|kme1Dc7u$krF;VeIr<wvvp zSeBnm)^ode%C6w)WZn1P8G9VhChNZU&e^)ld~#tO7n5(>#*1E8|B|i#a&q+Zp6;u! z%e}l8cUOPa-oq=&1+CYTqraKuSM5zQYxWjqrsz~pJIj-cb>+#0m1piSAMa&PSm*9% z`GYKfnB`BB<9VLi-09x4<hbv-J<j@tGt71GWwP$|<AT?hafeOMk2{mq^J89`?K^|G z+ZpEnaZhse^m|=B1GakDqrC;4HI(H?v;0_=A9rSh{6v<YbY_?JDX%y2tgUnB>?)qO zS8y@QFJ}3rEMLy@bZO?>YV2iySp9q+R)0OqH?sU%vc4`qUbicl`@~*8{<vjtW4<0* zFYMt>uWRp)*X3PXJ>+hB_HFeXIK#&uA9}rnPwZ)YYV*u~d}hz#^DKXr<*#q$=L@&; z^Bp#e^WC@d^F3L<H_P{B`N3p8pZOuXf`^^iz$5lH9(9I0&5wDVyUb5|T|HB_dU)^K z=QBTJtA{(sb3Vp%ULVH`_5kL2#a`x`U$iyPlC7Sy&Aju=wt7}<_0(+j)NS=NZ1ps4 z^{m<>m|V=Do|dhiwymB`TRmI0diXr{s%I}bp7Xw~=W}46;6vwi7N5uSS;nVX{>;8$ z{oMIJe3j*|Z{_bRIMY=q+}Cj{e_yA~`}gr)%*on)z1cdwH|zbjdYCWPyD|3+tA~5u z<VUmoSeBnm)^oUT%C6w)EHh(s{(bXVzL@0~vV1Aamy`AD<b9l>dA`$wIU~&d?yK5^ zxSr)3S-zR&S8dI+k>y)izMbVav;0n>@U?zD>16M&-HrF`VZ3jT;{#hWAKLx+B>g+= zUvby_PVGf}W^?9!=k^x9u$l3`OS_G)>~(x?bEls$qW)d`uWGo%u4Cqo^$PB?S1`{p z)=QY@5@w#CFl(53ellP)&rb$z=K0Bx%{)IDwwdQABev!lwQG3H);#03=9#cH&$O+1 zX6!{gYipi4Tl37@nx|;D@q(>+=!&~&9=gJsXUVSPvaNZRZOy|g@|uS|Va>yyu;yvl znx|>&+*MoWuGu=5_hPTk<-Kqfw``qDm)8GxowaQ<?@xAYowaN8{!jMoHr}^2+kvea z4sFi)$&sxYj&1JolM`F>oZ6cC!d}Fe_7c9bHP5xpJogvuHtw)Dai`5Z_jlRMbAPv8 z$31of_u9;Jf1k}f_Yd04bN`UdJogXV%ya*Ut$9Z6HXgG#@wlydCTz_!X=|P-Tk}lY znrFt=JoEM<F4{|Y!PYz_Tl0{MudmJ}7uLCDTjws@I=5o4V9t)b&Lt<0=`3<#I__`U zI&0P5!E5#=Ubi(HbHrZFz$@IwyuzA+Jz=`<XHQu3a7I`&@7YUu-!9_=Tk{;+n&-%- z`~G8_?)y({&2wsNo-@0F&+R6@ur<%6%{;||y@We#<|%gC%v0>LnWxxoGf%O{W}afN z%{;|En|X@;b^{OC%u^h+nWs2pYo1YC^NiVLJZ@{A30w0_+B$d2*16NR&YiJ!?yOzI zbGFW1Nd8Yct7I?ZMO$YvlfI7sX%~|VZ((v_%~r8BL)G5I+%qyw%-P{p%-Lbh!>nOG z7T0Xevu<mi4O{cHY|X=Yu~+kOURd++d06xCd06wXKdgD!AJ#m3w&vNlHP4Y<#>e(D zKCv~=sjYd=Y|by9+nis#ur<%6t$D8OCcd^;3xx*?HuF5tVKdJI-8S<)&|@>t1HCr$ zJkVz|&jbB7=RPoCbM6C!Hs?MtWb52vyN*X}ojacVpLN!RUBQ#K&YH4$mJdwZ+jz#- zY_qmzn6tO=ysa6E_8MNWHBZUb%w=2i@Y2`uKWiRdVa-#uHP4E@jd`Y#*}?RNH4pa; zYaY%BYaU)<&BH6KdDd;s)3%xA0lFen!E}W+4`+up&yLO71H2dOtUbVcVa>B|Yn}s} zSspmFndN~aTk{;-n&-@3#^<)?xv(|QrLB3cY@K^;bMAu$n{yxRusQd^PP>7-Y|eeK zH~Fu%-e+rXf3p5A>4O8w`uV8`2c2Qw2Zx-Y<H2FCxA2JF#-sK+X1|`*UvJ>aWc?lG z2dC^^JZ<mc8T$aw+syJ{(dPUI7n1*r&MhVX%{VUG$}ii@_+Z6m#s{l5Gd@^P*57e| zkY}Mer?j`3te<y#a5Xue!&>s+u=e13^51UZw#~c`Zf5Jer_Si%&hq#B$#Bm&OXu#} zI+r_ZU4P&4!NcUgRp*H_J^0k_#b?e8;&Xc(UpUi;FKy0!sBkO)5NGQw{T;!FI_(kM zWshRchz$J?(RGujE37<ohn1&G*8fkyL%bL6#=I99x*r;|>3)b=wf;BPc*5(<_|SB+ zzAg{V*y@~hMtkRM%{K3h&MMkHcrjVe^Pwes7nhUu_Z=TvwmI{mip^XPRqY8}PuAZV zeW+m{;ifa1dDYe(*POY;>-H6H+v?f0)w7lSx9Zup)wAP_dYC(&m3j`6_0R7^bZPys zo0u;7zo_Tf?!afs`ui&no!c|`!k)vNp}lv^7YYmP50hD7f0)cdXO>~USm%BVy_x&$ z4c7Z@=3N-DnRj8(-o-=q9v-$g@rb>JN9`6Kv)g#m<{k@E_9dQ9zLR?_%-EfnyT#1P z6tm1imMPh~Z#h{%v%IiubLK+DrhB1k&*FNPX=IsZmRYqo$n(-X`q{~amVJo1o7QKy z@n-UUOL!|;KcBe3dy(O;3p>f*KgGND8Q!yxF=xbCC-^A&?n}&jTG!9VE%07+7BF4m zPJH3a9A;1Ci}=bJoy&f$>t}p^%APR!pLW>`xZ5t_9(xh@C+lY?e>z}m?_lzM!+6N% zIsBB*qyG?(B<p7!emZV9@kF*hnH)V+_AD7*aTlG-d10M9pL~xxxu@2Dpw2~S==dpf zM1C5VonhZkmu=R5T5)CuS8dMxX+6s~Y&{>&h_m#3R&CDw=|+}sW%+iN-^}tm$#;*l zch}|_{B+M5p3P79ZOwmRkKjXl6rUu=*X7h!=b1Cwdv4F;3ukoJr9D+BJX}cD^L)6& zzQ&!&`gxp(yX+O*ZSxEt?y-5U5BJ+-A0DvDK0IhM^TR_ncYJu*X6<3_7SEQohsSO8 zkc)NoOxo(1veh$ft7pbm&wR4}`F*%(AK-;#{k-SHC3_5WAD#8170i9YHO&3P4P3RG zxSnNr?<T{0VP#hBW4w{MWuLI#PS&4uKD=pn;Voyb@wV3sc*pDKc-Owbd-f^bx6klV z^1XwYIW*h7LzuI}qnJJ6aZJ}u<}%A%Wf^9Q4EKJ7x#js~++|mAw_U?Mb{+R;nSm_B ze9@x}^M#r55$2Qi-&`LVvpMGxX4U%r%=pMea;b$Uotec`&aB{RulL~@n^_(q7yZom z$ei7a7n1egz#b{tBY4qfu1A(^W_hHNtp8^DNY!4&oUMNSw~a??b{jWs<;g{64f6`G zV_xA6%pUnCocYM6t-V{xCFXr(+iu~V<OjO&ZnFMe;gJKc^YM|xZ2c%XdXDWnnX}|L z_uSUG7s>kf;72ZPI!gs-cm|~odj)qo!@Wz)q`N%O#@)`;aF1Qb{aJp%=Gl}uFZQnE zA$tRlX8Ex!Kc3|$vix+i{`+)k#;)L5XO{7tt@-C|E?6qsi<sB9UzgI7txjGsr}okn zZeq@eyw0lHd@OP2$PD6!J%ZU2>sxr$-oa~j8?W1&n9n0Wf%!Z<iP;}!-qN<sTqU|< zy@+@11$<zu=g?Nqk*%I%TRkVXdQNTiTqNtC-_oVsiLa9HSI@P*R46>kdzweTZ+g_< zC;ENUqupNL$36A|?zfd0$TEXjW++*|uX%Jd^O)Vs`nb)<M<;APK00ZS;3=DqN2hJh ze00X<%tvSKK0IeL<D(1qJTBQq%>8v={r=_ACA*9(S*Dt0R<caZ-Y4Ho)~^kZuG(98 z&ECc9_8x9$8TM!f{W|d|d&0_WCzpCLpKJZmF<zV(p1=pmj}PI)<fl*Zku!CCoc!1h zKJoetCKo-k_{^Td=k_$dN`9<}ukBKy@L0iK#2t1ScPDGc$9in$daO73an60L&*sd> z25ses>?1sEGy7vBHnTrAp8RMFPuSW!nf&w`p0c^$W86V^TqOG#XUk8_V_xA-T+G%N zlB1_&?~&nd@vL<2vaNF~$&2c&CO@Ihx-;9jVejCk^9Oj<KErFy?BaD>=eD!_rmg3* zW$XEHM%?iPvnQ;6<_jy&=V9d!vpjpWuJ6akPHnm$W2VS+=40o!=D)C+@v%#LqfmIf zkgTuE;~h4gk9Ru5-p9LaW_i5Z8P0mV$L1c7_d7F>2ka6av^ihj>oMCE9=4hH@e%tR zkK4<5!mi*+djn6|-0|^gdlk>vYnVCWEcFy^^(@%xDcR~-wAHg@tA{=DoX2q09>*)m zkEy3-w{SE0N!^hy?S1kZ(<Lu;;B~tbx3dg$++=vZVP&@MDZH0?-{u)SeqfjJp}mZc z>=Hh<x$EO6_8dO7=kb|6gU{_*d}TNBwY?fYZk^`bz}zin=1z;<S*FKUrZ>y<B|pW! z#lhsCbLQfZeSwE<&RiTxe!76iv&=-6nana%_B46!pxK^Q|D3IU?yU7^ICHUR)4jNm zTyEi#&2wE`w7JLPlC8aETX$KuJ8>oX=}TO-b(gw*jvKb-X(q=!tG4D@OOAQg?L*c# z?0(Fwx=UH}v~A6~Y4_nRTXSyPnsX;P=G?V4=Yg#`IWL}}<~&M{Igf44d6FD+p4yu8 z%+{QA-ONc>SaV+5n)AxmoXim!=6s@%tT~_Hy_kphpXj#fexk>w`w4oL(VS1v8)nWY zm?Jt{c)(`PCkAcae}X-c(cWR3z9&X(`kolIndONwTXS-T_QsqOw&t9+&+&|{IcJk& z&N*9i&L``6K2fwa=Yp*{OSa}*v^D3FtvSoK=3KTlXC*o2tlFBh?#v`^*qr}F)7A{D z$<Gw<MwVyRcy7wKv;1b3-^ud3S$;3e?`QcVdydXyTm2`=znH?O$<+>g<_zaQai07v z*(WZ%&a-*q(&pJbab=e<_t*T-EEWns>r8&Oio5I@?zZc=$L87mtUvh~&ivVc%{f0C zO#TJu{%k0DneLyBdR_T3n^}G~ZZpfzCY&$e>Evhj@r<p#v&k>);JIWyho8+SFBdT{ z-RqYXyl6Am&zR|Ey__69%k~+WmE<_LX6sz;uf5CaY$X3uoomh<<8}K4Z#aK}Th4dl zwlk-A(>}vHS$@~n^VzfYeD;%nS-?kGp0i^%<vBa7JZHpxm1hq5nFD-j)A2L*ME(%7 zCrrna><Kf=lN~m*JlUPB=ksKbP3M!n&S-C+&6!X3JHuH|4%p25<ghapJYv`IX!0*P z=gBdf?kC4>p5c=db{C#bUS7pB_8OkGHS?U!9iN=Hw{g+l!Hc$fmTdKuZS^eM>Z#c3 zsoLtPCqFZX8}>YICO@kl&d{@cR?l!FxuQF^>^|JKd1g;;+Jl%gw6~(nZkC}p)|H_* zT*610k8SSy<cZB(PoCP$_2ijd!{;`4dh)_v#+P;lU)f9e+Aj0^zfOA#ciG#x+h*RS z9{T|IXBqAs^D8r$WrmV}&HGEE$uH2oG-lJiG;a6d37hVv=`1soWoEO?oV`eXA-Ssl zlC6H;(`+wm2JRfLV(u)jY~W?DE6+2Ebv`bU3)k_A-GOU1-AlZu%!}Q)k^IsTZYEc! z@v5!PHG2%N+vAuy)KeY8EqfTZ?S8yz58y4k2XEVbc+W24eOu=qB(KPab{#Wo+)?*B zwsr1Va#cO&w)S2)BVXF;xw6%BZPW8qXR>;p>ayAURJSuSclh=>Kh<l~^Az`qb@dD; zN6(P0y}TD0dBm>cQCmG@wt6O$^?mZxl--S|ll6V_)Qnxlv&s5Cd1}t<%FlaUoke>Q zFC^>x;i*!xz8{|AJ<VCA`>7?HeNUBbW_)Vd9>?4#^4#?)<_PPo6}unT>;YW2dvL?< z!)wVeDzk2@hx@2A?%T3C=c#sb+;`LK-K=kUU3<6f3A~g1;ym6>j{EL;eT4OWTX~*^ z&V5n$J<irol4G7zyGrIPIp#U{y5_m?y5_mG)qj;7^IRuuo}YJmy@<Q)1x#1Wvw?eT zp2yF7?K1AOE4be-;Q@OQGe`7jojZrMK5DCnJIDGmp0s&xKcBKS+jO#?!_Q~zDxOW& zbNKn3*Sj(Mqf;}pUyl27w^-NA%oNsMW(sSzC0n!cigot=ocY4K%Zj~;YxWkdC&!!( zTXQy(SGMu0eT>(VUsBJyeT11Q&QhK`$S;j!&WLs8c`vMUcar1WU0dhwCC9n@w$43B zj&l!foy+UyTyi((o+U@mxy_kBzpy#;=a)9;JY7hB@d|g?*SIrTb3WZ=7jbv8=6Slu zW|pUWlYcXY`@GI`c)H)~BbYAD`I}KZX!G&uA)Aj+58IsoG<zb?`A^doR(>MOPul9A zveiGE9QT^Db+7s4xEJ?P=gXRTA^D|!T(XbwV)Ae3dwR*<#${W3mu=m*Vr%}Yt@-P= zdK&f|ZraTC^s3F;(;Hd7mF3%6e$!@_r*|^%+RXLzp3PiObGLYg>OabSY;UuEk{r+B z)F%7%MV7zJ@>f~@`c}To{o^b;%iKTAjOA`;<Q|*3%Dv7oOS#YMd@T2Soja8WZ0=MZ zw$(pkt8+B@C3(zN|F|<Jc*5)IpY*!=r)>4l+Sho_`2wD|J8;of&!Y3&c*)+uWoP7N zTk}+$Il)!?8n4)zr)F!OX7WpYc-0=qYxX8yw|8(m%k!R|zkXdRZ)N%IEYBIryr>@L z3zID$B)`mE%ZE1emXDHu(~pnsL40EO;!|5QpV?jb-0r~_b^%}79r!BwMP@8t+pIm) zY42dVV$NOMZ8Q5b^u{`KJ;Quq<p;7nv&OpeL-r9KwKwsYy@kh<b>C+uY&xEqw0rTC z-G`^`E<9s1*E6$r0ngdo_nG<R7d3OyzQPOkE-u;oc+uX*OZE<~Wb4&zeZ@W@Q?u1y zxA$<vR{vVIzMidb*r#M#wtBYgdCW}lY>RluCi~2;-Nu|38M^iF_F=m9-wVR4_|RsS zXO3*<edgF^-e*qi3TCF*Tf=AeB0jgv_`+Vmmv)JNH!j%oxWg{uPP>J>>^APUng7`y zoB5yZwVD6fK6?%K+jTr(Gyk)Lb_EaFH9TxD;t`wqpB=TC|JgCSgeSB7RF<E%HP4K# zd1h_RGiPg_d3yzO|8Jk?v&<pu*N|tI>?&p^t?T!7&o0~BnEOOt>*T_lnDcIWI4?ZG zdNVnCm{sfgJ<PMr8X5Jh+v?%-Sf9i#ThC$3)|~9W>EE%{vumqo&*nMlzmG&-JqNb> z5A7*@Vypku*8FF-`p<3kU)buuwAFuQtN+@j{}-LfRi42wx@_+Bi*9F*a8L3|2ky`E z16h7B%MWGw(JVif<+)GXUH#lgj(+A2FS0&kSMY4|%gptQIh*r;G4D(r7j2%&FW7(6 zvt+BMoE$yNwt9Fk^6IJD>fv*(zr2PUw$_`;uPV>8Q>HPA$wmGWuREiD_Qd)YZrR(o zZS(OLn>HVRv6KAD9^SPNFrTaEl|#I5ALAo?81s2#M)67Vt2*~Ixi*C_Y~`6%`Pvx1 zvd8hYJ;8q$?o58A8+Y04UFLJ`ZFJxsdlL61*EVop@@w2<dC)H5p=_P5o1PJy_m`O? z?xJ&<Bdl{dL$0ZFD)}{a&N|bN=j;JI?+o3`MVo!g3(hdtGW(-{2$!?`vOUIn#b&PM zsy%`0S-z3wn^}G}%WovV!ZTZL*?qX}OfTNFHUE~~iMQ=8yq6qbmwj8E2hM2kp*@0+ zoY7gwww~2lay-v-n~vp+<kx2Kr9FqQ>?wS0PxEII%oksm6U=<!Q{3$gYrpKVx#KT+ zDf3zZGgG(&4<^^tGi0l0*ctV3pUA6c)K<@!t)9u`m)G!=y^fhxdtX%#cMCJ)FXxl% z-0_!1o3&pq*nIqD$>!rP%UNbQ%T%&V)ozooXKvV=tT*jrylS7|HTwWFx8|%L;thKT zx9nZa8Ijq-^oF-Fx$re6C%;j^d$yj#zTJb5vJ5jtUYV0Db873ETqM6WjW6vPd}YsL z&Q{M`#X{j%owqW-qBqvb{Hi<4Fh{I!vfiKEp#N6`HvPXEOn$F~hwObkoZP&?BVM1y zqh9CUzZ$c->#xS`DLi3s;mPE;wU_raPm@`G#T;^@iJ2p;PIBQIp0n$iyT$q<=KkR& zykP5@lx#l!id<xLF1aurzpB_RT(x!XN^(=?Y~`Crn6txExM7#^T5>}@>$di8I3x4k zO;6ia&!(-Oo#g1*wY8U5?3MRz&2wO@=g?NqNpkd@+S+^OjC^jZ=fYOcrA^Osg=Br7 zJlA2*;Lc=ypFG!P@8j-deV;tn<MmnG>veVZ*;}|jS>F%O4S1ck=LVA-t9Zz6;bFUm zN9;NtwHNW2y@bc@BA&2Ic+%FnQ}#UOb3Ny`mGSr6+hxpqT95nE72aokAvx~Lo>*5W zbI48YWsYzS^SS)?2442M?pyIXYtL0}<+)qrS$nRLtv8cno>g1(tR=@h>t5G9oOd%% z%T|9oIp*2)y5`yOI@#xTZL-hp*%z4eVzx_sV6*SJL!0b#M>gHh9ot*@EL%U%*6EE- z_0SvU{7S**9+eK8*(#mMdJdH?dmncv>p4_<yv}pbpPPO=v;Is})~`PmUa`*1l>u9O z2W@7q4B0z)*lyzyn>$v<?Q1-d{7wN+CdZspw&t9+xl?7v=KKn?YMyu1GnX85&L_X4 ze9@T|yqNs9@=MO>+;Vc9yKL*+imjfiJ%H)DIk%P^=hl<s+=eqccP;rn^{m^Sc*E|( zExQNv9M%8MINr7=@QyPjylb<svX>msVLv(MIY@q|O6JfR&2!{+?pisvxohRb<~dbP z?InC>PvdiY247|Q>s$F>7i{`}-C@)J>u!4-_t+D-H(AgB*L^lK|GGc9N%q$RHfz5g zOnzq#4<*0bfrq`Wy(2dF{q?BL{J$Qvng7?5wtA-Qbxbav{{|)(KEd-@zL@0~vOIT) z{0{kYW}Zc?@3LO8_b{{G^w%>tlH*>@<aiFNc0YTW?`Cf+%eS-qW|n6r<)f21!kzRm zhuoC+?H+vK%m6;Li}=Xy!pC+uKC?UUxvkEN<mkV&)qmy8AilQgf4*ST|2$nWC;iX! z3Qu76hbM8bJ%#&h_0Ss`I-Vc0ndkZ8WX<#Zh)v(~qt3AJ`7v8(joX@s&u`|Lwu`LK z*eiI}=1$MgCC6C{S-zCz7qk3Qmaio1*Q@8N$@+EjdCt%b@3nBv-p6%kIOq9>P51Ln zdmgXant9D;_UG4a=6!y{p2VD?v)-A)ZMy?++T(b~?!>!x7v8gbF!M#v06xm{$65X) z%b(i)<S&xrIb3?Z!1|TFfO$sI&wXFuz3@Elu#1@aVx9ZyXI#SE_l0hI5;JS8bKe(w zZDxL<&mPD9HXSeUUgX*L!l2EWFAUk7`NC+nK9;T16?@tD!i24U=7@FXdVx7^`e(Cs z=Dt~<w>k5LqOBgDg);hm%L_|(3zzLnylh|LihYi&_61(CPjSsY!*%-zH|%5FwD<6; zeTdiWExc~;VCIWC+nD*no0#0q{M)wXXHTqa{$2YDb6%`#{(W2XAK03oIU=L^k8D1^ zz}&H}`A=-k&z@M<{Ok!c*9)8x*8H3i*8I#A-i-e%?3;YG<5s@fY16Hrafv+L)oz=4 zsy#OIRC{giQSGytr#hJY?g}2Vxp#FqS--EVjwI{%9@SB2v_58E<4IdRQ+5qcCr8gr za`enPqn<fiJ@a-Q7wt{FXsdt8R)5)6&$6wairvIjTRrU8vwBzk><>3Exv=_IZS}9& z>R-3jzhSGtWvjn!tDnzr`gf8Wr>yTLzg@t4$@;xkb>E)CM_K+j%b#R<y42rPp84eH zzs&MiS)RGS&A-@bZ}DfDT{g4m=b4mwZx;91CEV-G5$>}&^Tk11Jwvv7hLfXb#8%I! zGwK<$)ias=JKleB${xql$!kqKWAhANoK5~{9?yB5_x1BYn*W1sTy&-bFC_nN0y9Ts zHgP%m{d2r*Yo1DSoLjYbSYNUGam^mW_2iFOd$D1kVCL3YG3TmH--~O>9}ePmuXo^$ z<e0zZOegDYuj?%4zL|f^9$=k2$GSRqlHb3?yI$|c2VOtNhxP?NN{;&;+no6#cet7V z)UL9AmK<}^rObz#lP)>V<?NWJgP&z7B(L^kKG*sx=l_O1k)h)^UCHYCO>dU(%ku2M z$q!`tVQ1FaJ7OQ;(JVif<tMZJRF<F4@-ta}KFb%g{6dy5W%;r*8_ck5w{RuPSM6)o zSDb0%n!Ssgw(hlRt8>j(C-24c)LvfUalC0y;4OO+Z`)INFU#y_nS(6D*C{%S<WG`6 zAp4tB`y8Jof20hbEB{dyUuAjjsr3)&eyMOP|5C@T{7c==u=Y}q&Du-7$!l%gXYb(t zWc_pZ(typ3FAXMtxQmBuW_fAY=KYsOY@WwUqsbqTeQC_*`RUJbV`jQvny|HZI{8Co zW^DD$CdWK;_8#jCS-zCz7qk3QmajOo%-*Wq!YlRxuGzX*Gx-C}xoT_9wd9X9!@8~K zv*C>HOK;qfJH51JtB3o<x_Wk!qi5Gv55195&%Qm1kL(V7Y<FSyD6e1lUOKgP$1`U% z!?~?zdu6NV+NNivkgOj4`D=92v(o7dJuBp5HhNZiZL%wUwtD)Lqi4Wo{uO#-FJIf0 zAzMAX7wZdn%r4<^dl66AOPDz#uMAybWoEO?oLys`US&R<#Ow)AVfKXSTcI~h-%2IR zRI|)VmZ3ND^sO|L-#^5w_7PsQFYvm3i8t(1+_KMb+djsd_6gpx)xT@2f6rF`zODWP zTm9_OobRijJz@3p3ag*@!s<V_)lYA%tDoMm`mb#DU)yxNT(IeWxx=Pkf4&}jw{efn zonG#>xzo#iHurdWFv|~R`Qa=-lI6$k7JDaboi&;Kk!F}mUhBux&giTe`vA|{nr+V3 zYzuZ9m+URPm>m5}$<beSM*YjS`YX2jtG4><b_+Lboz=8;)~c<0Z6yD03bQAkt@g4< zUQ_?3eS+Dqb^UM0%j^%=FgaPjH+Y#j!h@Ju<=-iDnEd`6K1z<BV_O-{xam2y)pL;? zJ(tPRbCn!D*ET(`6p}U1D;+jH`t$6VXASoxzu${_X<a?9^x5iRPvp1pkj-6R8Me9W zD<k$E9?vopS!OcJOxY*oXOrLW$8$DougoXM{6(8tURliYOIg00<(ISkN|xt7y370O zuV?v2mS1y*`@OPmGw&-KS-xfSoL<>-W&rbyqF;0F*h6^NR_B4O`ySfbdt__xv8}yl z$-i5`=Qj6#<-+FPuUy(S{@lHg{P7g-uxD^*^5?DeXY-o#bN0R3oz_32^VJ?_IP2Bk z<aOqKm3u1x8EdaHxBT%eW^Q?X4-Y4Q!uhX`*qs0BXmXr8W*@RXZj*g=!e;H&$>h)0 zFn5S^FY&a!glFs~W)5XOrTf)6ulM5l<e0zc4EK1IyT!~pt7L2bMVonF<&4Ovvz+`% zCtmhC_kMN7>jhl1b>Dh&+_z!xvffON=e%mO_A2*`vkvfj@~4_}BRS6HYZjSa*0;Pq zg17B6yp#N?=HWc$qlaGk6Xg%H{85%a&hm6co^xJ3w@>j!mcP7}=ju24TF0$?t@BpC z)|KVC!?*o4?ir@P)}Q4Eviz_!+_lCXBF|lGqgj5;?q+@5nO!_#bJyCm&An<fwmN5R zb<Ww^yI_;8m29%LMVoAG$)3lREK|)gD_Mqz74w(LH<Q;-@M^NYcD1$S&y-oW$=2Fg ze$zf>eJjgzAN7Bx{GKztc;6nt2g#rB;zOH{wWDPHb5}dIFER6}^HbihabEQE^{kzF zeGH%5bk{DD*T*sYmDjHiwJUoRU)$_`tuy&kGOy7aXVLRoce3Vrt;c4r*ZQ+O_qoXr zX8EBk&v}ulvzPP2JDB;x-08Im=Q;ni>Ew0x>1VT)S=XGi&S-`?oBO>s?+ksf6>UDg zwrHzo$yQG}`7`w_+v=$}qn@fgg_%2M=*11YA2*Zr>)vatw(hv*jAmH3^=#X=dNytK zY$Zp}wymBWXVkN6tLMO0&!MfJqvYs0wl)8WGYk0CR?mgKjJbc@v4XGcD!#T?3WeWx z-pc%zuT$j7{I)yG^w?{xGm|o(&fx)j9uL|@JY+B6(JV8TWyZ72gk2#&o&5VVJY%2Z z+2l_;FlTE9{TlvT&X#}A{eH{YVea=^&JOcDep|A69=|Qy>R-0i&)Lzb{;IA16=&36 zv(;a>)!(qyzh<j{-B$lba?Ibd)!%kT{hPM>w`}!q+v?x55AeQyi1|G3dxZHse1ds} zl|Rk$%y*M#zMDLAgm=g@$G3Z5FC>4)46pNywEp=B<__QPeZ9-(oY%W;W_i8GX13S+ z?Oi-zbC1^tlcRqqIr@j4;U2GZUYw==QCt0Ew)!V+=6`+4)>+fG&YH1#Ca=#Yf6T|% zi(c2>h2+oGU$QUpVzU0X;PoYY4VRPkdxO`PZRUD?CHZ4zYRSK+<Mn!S^fYW`=+zyg zXVq5EMsoDDlB1`c96g)1dbX0IXWLfKUh>CeU*Avu{SZD#j-EqXJtxld{_CeU@4tR# zAK`QR7++<X>suMF8~6H{OufUt#NEliAHh9#3HK&z{yMLCCS!Oo%QJU;KPW$(<>|V~ zk7xObEI*m$r?UL4Gi3EMwb4J1c}1t@DcYP_Uvy>^FWH*2Y;%5n*;eO@t^3w&?XBC| z+px8FE%{?Q>gzTg^$nYjddntT-zpUTmG7T|X4|&8YkkLN_WG_(U;V(=JcqVsILh+J zS^mTxCv$46|H9U}m$o{uY;|7S?0us%&Ac&>yX*zro%}U-dZQ=#8$Q0#oBUNB_c>F= z{mEZ4%NqmEaPAv}$r~j+<P7(CV>I~-&Uu5G^fmoL{mdkPy^kl7<6Q2h^{=*BpK@jn zPkUYS%-EZFHo3+7Z;*?<numMJF=x@4Vb-~GtkdxZvxblHqRp9aEZOQTCx5~7cw^b? z-06*#<ga)JZ`5p^TTlMF8#iqAtT{7;*R%XamTzVGt>iCx-fwK%I(NsJQ@ooT&uuR` zp4+}Nn&BY1b%76^(ac9)*KFKh&!KgOPm;f!!JKjPe0VQB#rnCey;sStb$o4e&YK0B zwKqGG^{n3PPX3afH+yV)-t2XTzBl`l^$g$S{&6nzyvhD>84ug)8L`zfn*5b|#*(9F z+!^&u*z=e@(aAY)@?Lll&nD~p>diTO9kb_VhN6AU`l79#C0jkrs(kb;+v=$}!~1Vm zZS~Y`^)zhtG?Sxe)n=AA*PNmIO?qQC^|WpJ-rTh5dvnXC@6BzSzBl)>%zl<R$TEjE zeQ%y5w-)iKy@bzf-OJx6EzNe7Wv*{!-YVE+-s-TK^R4dWFS+|$J@zo}P1g7MTYWa& zZ}lg)j`4uaEN`*r+pp<cBer@*lcQ(MR?m2H^i0_5nNE&*W^DD$I>YmLYtH6*ytR<5 zU-#ZB+1%r;#bo`u_tuiFd^uUa-oCYLZ{kX_ejR(On%vU4E6MtG>8+YGJcGBIUgsWf zt=gA(ExDx`)@}8)vpnbNS$(1WR+it+@_WwglHm@KzrY7s{xHj*WO?pzljoVrG0%CH zzsmC0xAKj`t-Ss&S?p#0Mz=G})#$OAtHE>mw!hJ553t_v4D&YlJmz7p23_G@JYuVJ z)K=%1t-X`>Jf5<Pc-mgTGj<7+i+*Kzg_YqIR)$x&ip$AgUgG6sJ*!3~`Ktydr~Fr& zxSr*CPwQXuEE~-%znbMYlK-Gg%f80#Wc_b+gWi~@7jM~}c-!v6J9Yu@+8y{HIr<N6 z^&dH-{$pGHC${=eZS|ko>OZ&Df0Z2l^lHvO@KHbO6EoBQHo0%-f1BPgAK#`o%*VI8 zZT7v*o>*t!+x^LZV8*ux>=Qg_Gt1jU_5~icPw|M&>~D|T>Y1?BGij@5%2v;`t)3ZM zJ@dADine+dZ1t3E^(@-zS+dnrN#0=X?W)(+xst5k2fkgi_i;U0-(zn#>}}jk)~`ix zuiDdiBY8u4y7WB%z&UTXlcR_Cw60%!-`+}&9zNH){x|OJz2xX&j+>r?<mfrH)pL{_ zJ;%0sxU=?d(D(Lv@*l?WMRN39+Vs3raGvM(PKQm$JDoNi?{wL8ywjUy`m#)amKjL? z10C-S+mm?2=4<lKXtL&iXUv|)<l^qiPi1-Di)W?$OqQR|^2IE_kmXBRzU<5_J<IkI zW~Q6|sy)Ga-5F+ir(tW(rp+wxtlH|_ur+_n*50<Qy_>f7?j@vcqZJA3vT-nZHJ z&QbC=%=^x<y@F4Y|DKQUoF@OnAU;dp+`#9~sQ)7Q&mH*E8O?c>{7nsCC;y3$?{+5t zaRhhSqqsX+=f2yM{10T`?e+Qs?z5M0fAZ!b9`O1g=B4MaIo}<!_wjJ@pBFJ_M`j9h zwygQz9kZwLc=Dfg)`YG3C+!kuzxMt~o$QhSNXNS~UZ2JDUgykri?;5&kR11=OMCzR zigmi=n4h!5`>dCfW6ot;b5@e$+-mZlnCsoT*E#3ihS&RWGx^V&XVq2@&nxCvzLn+M zS$;Fi?>K)>e%JY4yqD#fTb+Ma|527d&hjT&{xr*9WckZ1f0gC0Z{_uO4`P1yHM?x~ zHM?)+^><5Ro(a~OHS+W|c`ovw*w-BNI`?W0+3Fm&)j48o@3_5!>5a}Bp0w+D%5LD< zEHjs7=Ce%EZjoP1{xh>Tmu${&mXkM?S+@5vbHp8$ui3qrIkX=6MwVYo*7r<v-Dbw- zMzX#qo1CG&`scCPPS!tn%}r+p@s`)S@V3pfY3?NJpS$L+*E{fDvi|vM?%UV+z%F6V z(7F2Ot9g?AXJt;4H`Q}yYo7DuzwgG(9nV2|UU7Hw?-g$4^>f}@SN=U-k>ABV_9gCh zo{#VK+1%?r?yUTunDf0Mn>pVbPL9qIo9ug|&Me_EyNM@l^-S67nNE(L8CyNG&ZuY3 zuHXfm4*eaon2mk!(G~YnCwp%0SawD;EZf(3#a2(vR!==yU&r?vww@LH<1F>8+UnV` z)zh-o(@u__O<VJCIYY;L+qQc4Z1%mkZ?o^c1Dk#C9op=B?<C8dW|^}rb8fTmy{qIu z*D>eC^J(z&It811{m$Pfe_qAiS*9n;^xDew*_(JU`H!sqZpiM(!}cg1vBxl<Ylc6P z{T-i&$^LHK9>5be-M^c*)jwmaf7Vw2oUQ(OTm3~_{R_7GOSbyUw)&TC^;c~5S8esL z*y^v@>aW}CZ`kTzvpev*-HA8sF5I$v@K%=J&hk51emBb>WckA^f0X5qv;0|d`;xQH zy{_3VlK);a^Pavgf4_jQoY8F8b}v6;RIocS`{V1#UEc3bZnN)w_QX0_{R~!g(*J&+ zO}~CFDl%l>AF$O=F4omQWUGHPS@XX?X6vkRXLQzt&0OzKCx6qxGtO)8Y_fjM*Uy>h zEd4(4{rTk0eO$B;@j|lxxBmT-y@<=n-zc-3++N3(<mjo|%B&<uPt8_OGdX%zlcQ%X zIeO^TociCU_cxNGr)8^WEBTu<yq(<UPVes|N6)UUo&#q(FrTZx-HDIvE_`fvV|s5g z=UL_=%Us%n{2haWy?{9*_Hw6H&X6_#DrbZjac`FI%kuqMejv*aXZevVKbqyovizho zWzL$i8<;t6=9#gJtj{}B!h9a{YfkPHUc$T=Rwu8p?z?PjZ^hQ$s;#~C<Zs%TIkfki zZQQhX@Tz@?HwuM+Bcnf8T5Z`QnEkQ7jyLTqyk)OodLvWA^oGlL*Jj4mJ$nxC+e`Ss z9>vTNduQ>9&9hlO&GKiq<~g^?u3p(Ce0?kbLE%>ZgN|GI54vsc`$3OAf_v>L+-FbY zetQBB*pqnBW`6x0gP4CD^LbePW48KvFV@vhS6KaYh1Jh{VfD`z3jgk}%Lj9|dgkqQ zT(qz7g1v%Eb`3AuWxQlpFrP<1-5)I5y#E33#ri0&+OxQBbLIz)EZ?*>&#HZbH*9A4 zpq1s@S$;Fi@7TlSckL0pXHVgMdm10u6Zp`c#7DN~Keos5nXUeFTm2Wd`Y&zuU)k!v zw(0+{vryRc*X6@5o1PE5ZJxu2JvJR5_S!4B&#vKqyNn0y3LdoQ@Q}TPnLExM#he$O z#oX;?9%c<|9%c<|9_|*t!rU#a{ux{Sbj7;*c`vN~1-pn#S$@%0Kl>wpg1JMO?1$AX z&;4Uv`C685+T8EMRa^6~+06bSdtxuMf4E^!;Fir@KWy8Yf79mKe7Iw)f7e$3o~{0U zTm1*N`VVdOpA-uJ=eJ+?Q(HY}_BuYdukeMvf-mhF=Dp}C<7>OZ&yg2wp8ZE1_7d*2 zM{$=ui+k-N?#uH1HuHQmU^Dwi+&|7OVdf62pWd+YV_BX%$2$8ynzGsV(X`FlM>95S zA2CzpCop#i)A7-~%{ltJWU)Su7j5-3N35&AY^#6SR)57-f7Mohy-@hS{B`-LVXLQU zuj5tw3a{BKnD=6D4R6?-|53~4%#YeOclv14Ucy`UDBiYb@t$48`&s_L);x#y3FZ|u zl<;YmKg;sxS^ml%CVy>nU#^vUrf`QnjXUiL++|PVZkzendhBuBZ_~dvV5@)7R{xN# zesVFt`pJdWPuKtLuge<mh1J7*;dM+`m^-b}6<)zJb`8(kWz5$gG8H^;v$j^Wm+*qE zdzEZD*4Q6=$*wJDdAed<^Hl8<T({|1Yh?LmmS4^C8#d2lt!3-JZF>rD+T3+*%bvj7 zHqS<Xe<tP`#k=-6KCsn)XsiFoR{ycBe(n%G>OZyBe^DsxfBSX0wAFKEuj6Z*wT}z- z3huCLxYI7<F1v!e?K#|IFX3K$6!+P)c+f85p)AimV@~GznEAro>Em&`geS5*ce}|? zWqHo{_P!r8Q<y&eTws{&$DAGJxqZA~)BQ1L#5&y{FWQ=)`@}l4d|a`a_v5Oq{uNvO zHCz34Tm21N{cDB7|D&%<CtkO^@P^GSAGd7QK5pAOYtz<jTlOH{wukVJ&9nb_*B-!o zb~oO)d+?FniI43rd}5dIsjYd=Y|V3SYn}^x5MSCu_{!F~*EZ+=p7Z`+JqLPz&v{{b zeos#BSi<Dw?`pj_`8(X}_q-xAj{B1fE0}v~{q{Y~9CD$EnIl}qbcJ>9n5}-gV!ezf z>}5P@FXAa%vrXITpRr4L-c~>FMW^}~Z1t0ib@lUkxQ_WeyoM{u-#Nm}t@VyxOfE7_ z+{p5LuJy>TX88?g*2%YQ)_&i1<_vEp$8+BD`V#Bg_AcJBH3Of=JVSUdIleCY_7Up` z$pyN9f0!I!7v78cndSG#HnZsG#baG_p4*!9BDq6zUM7E6GhBIHzP6d?lR~o2{iGxL zHv09m=HH(CNtdm4_J4csCw(^Oe$t<O8y`Ozu+=|kv+ol=*WTOM_sOu`jYsSrJZf|P zCu26}e=?q2xWW@Q_xNPeKF3ow_x@zsKEN~fA)dAO@SMGm=j}~gw0H4>-NGfijmueP z*;Z#I`L-ckwTJPF-G^&-Kd#$7xMBC=rrm{C?QXo5T)4*TUhl*kUcbaG`wBB_e7z3w zrhSgL?0vj#A7JhfU!xJsd*M;cdtuJ}gsw2>d~#$n<0r>9Gk$Vnm+-0Gz-RUhKDX!b zg*}EZ?P>nbOu-((9X9i<bLW_W{`D?<1$W!@ulLyWulL&YulL#NAGG)JQ1a~)csRME zi8)(mb?jo!mi5o?I$hyaJeho(dZv=2hcjZYdYI{^XEr%{=4|yW*yFflYtBVm_gb=x zxMKI=s;#{|i<nJ&Yqs_>ht_X9$DAkM-h<cd0laSWY}VUZW;4rdWtnYzl>DAOhxcvn zv3`*J9nM@ow2$zKGrG%ZmOsn#%o=x5{wm8{+no7nAz8oHecEA<;%;ZS)2G}s?z@4> zg_-@+K3hHgHuwH?z}~{cHuHZvVylxgqDPrATb<*!&YG~*Ic+cE8G8xOCdd49Hr=1j zJ5$C*TQjg<{|)mW==+rYVLCn~7v`CLx}5xv%<^f)>xZ~%AK?|7Ge51_`?zV7{gm^f zvw_!a^{*%Y;~?gqkzwuAmaV(DZTddlv^D>Z&H111+I75VtDia48T|)dS3h@%v((QW z!s<V^)qiGJF<p_-Sr@j>y0p31XNAliHl3e!+H`)_Wi!KPy;;65%lBvbfh<3q{EzAx zvDGu0yv4`Q#_Sp%x9R(A!lv)D$>e|Bz*Amlmd|Fr&U5-~&OX8O&Zxg=FX07ecpjgX zY@Wwwi}ood7tj9;SL{PvwU6;ia?H=%%5SN^?u_~y_9brG>gQS9^mCu^0qZSWXSHpe zwQ1{KJDGQFb?(`kdEeFyM_Hb(I7@lDZf4-~u=2d*E%h*WSnF5G|Fw#*ZMr`%*gVV6 zJM2Z=nY=~E=UrYe;$FKC^HTqR9m4%K{htrm-1YN8dkm9{{5T%A`S|&W&BxDqFEaFf zK4H`G`J}D>DO>&1w)$sm_0QVspR?7!U^DyYC0l1L+B$2=*1am3IXh-k=ZdY)nynd{ zS$;LkuVwl5EZ@%Zn^}G<%Wr4-z2yI<bN6kXdtmeN^TXtS8o)<hr|<J)o4(Ia>~VZ* zGt1`}HqYtvOS_D(Z1rC!|5Fz~A6f7^&ts#*=6P&%+RK=np4)$`;9k3g`|Ks$Z_~fQ z+{#D)px4zuWUGJJRzJ_;rl0$S7g(RLb=IV<v!-nBwK1D{&Q|BVt(l9qW?0Pfbj4Z9 z({(cgpNEy_71mkIeUq<e`9_vsOWv-MU$=RGV<Y*W2XM>Qxm#I&JIn86`Q0qf^VJOh z)MoFY^E&IuzQD)M>#VaZf1c&Zsb^dH%Uk(B6udsh&+m5FOStn^{tsQw_psiZ<@>UH zf0kzso%PSk4`=z2EI*p%Ir}C*>2*H-Vai^>(^-DTd1m~>yw^2<(H_U_iTh6AlC92i z@;`0iWv?^WA1cW)bJgY^f2b$_cjX)Q9&RT8AG3JXZsUzC-^%j5r+Fg3ndNtq|M`@? zyUyz@&WOBb*td1oQI<c>@+VoIuA8$ioLOY=rOk}`dHS3FYkQKv6ViDr|3%lWy#9X6 zw|V`Yfw1!ZS)N(7{@>~UVlc}OW%*HOc=lh6*{gUw%TL(6|HZU3%>TuVy@YudaaI}6 z*~@q#`Jc~m$?L3r!Ty_>*&n9ki%Rm2@>Tm9uO$CV4f9g|UwE!xG_(9_mS4;A>sh|- zOfP#kZJo8{jAq!jb=F>%-_P;~S^hA~pE$#rUofBM+&RW)S)TJ^{$<v$vi$X}{FjAW z`7b+e<-hE{mH)CQ%X6RTWd1MvvizVk-22NRo7uk{&hjJnBJ1PMF#nem_6DA`TX@P= zC+Ec-`|+H;iszI6Wf>Rk8s-e;|5f=Vn_0dr+dG&&%ItEdFITcW`(v;2^(^1W@@vWe zgBic%4mW3Uhp=X7**a@0%Wr3S-n+@~X88l>kJx+Y^={1PH~C|`&H7oEKhN?PS^n}? zp3$P`f6&+JxRq~p-paSSvV5=er{w#*&c0TEmLIU!Ss!*@{UbK>wnps}JZ7tN(w@On z_5q$w{?|6<y|_EitTmtfKb0@qd~7Y)m$;PtZ}hdwS$;XoSF(IH%h!{4dB4?gMrSqc z9lUDmtc@(+%JR&ung6Hqn^~UEW4(*@U3&uWW%+&kly#otO`hi%R{kW*lZ$obFS0!I z-Q=&b{PnH;SDkh*e{YAGB0q||Z{@%0v6<zoew(cR-f!f|el=*5{c6ZoCtb?yuHZ4R zci?fGnZKH_nfI&d<bPLw#%|)-<UP*$YR<0Ug)Cpn@{3u1Da*4*^ZeT;d#ldtEM8jw zcg;|9UT1OkO@1}YuVwl5EZ_Dz_tW1&iq10L%JSRJ_p-j1<@dAvL6$$v@+VoIXLr+o zmgUd0{FT?IIP2Oj@%Qr!xAI?iIN!y3x7V5f>mGXoGi#hRiTi9izvdam^Wjck4|#nQ z4=3-j@9Pnp?AP@Ee>~^g&oRC7cjhs@@_$f<-Z0s(XPu$r>p5Hf?1{Z(zb@M9S+KRY zWYhh1*&f2nwmK_WrfREm#nxFhTb<41+b{5{eTmnSWBzqp`Hkf7bmEq+8QOLMZ`vJr zEBW>-%rn&;Z@<QS_A%bK&+$QWhvqp<{;v8@oH@n3qDT3&EYIg!k38o^W{wQ!h4=Yc zM&^qQ=YPX|VLHC)OzzNnm#y{g<nM5gZ+g7W```2@-%kHG1Gf4HlfSE;AzMAe$<aSz zYkf31`p3Mk{>kLqSMikH!qave&)7S7-Y(;!t-TAj_LgkzC8xW`xy$wu>lItGRqb<J z&oYfH)66oQ7oFGSH<E9wVb0ciJS)z=dFGqR`X2jc%j;`++h*T4+)eoo&9iG?;61ww z@7t_>!yO{eyx$z#%=^tr@^{sLYO9~#$a9Zx&TZ!U=E`2g+~?a)#!sfR-C?u0-E9xy z9(x@3CV!W6+I`9Yfqm_MXD0A~%~|c?WIea`Nb>Dnc+?s7jM*1>GRse8`ROb_ljY}~ z*ZjpSzmVliS-$LioBXo9i7WONuG-tUo@F>g&+Rs4nptMmK4g6(S%0?DZrQz<^WvH7 z?wj@yrc3L$_hHTpbJzBst)6{bJqO7h>fyZTRL_w!>N&R6b7rgO+*Z#;a`ar<>bY`8 zJ=Zopf9$jeF=xk|e69c3ovfZeaz@O<_rf3j{h)jO(ccfZYn}bEmo@zzm9RQTZ94RK z5o4V>|M>qmb$>yXr}<sSpWb03F_;iT3^5qdprWE;M1zV-6eAi`RE(&oSfXNyii(CP z7hG_GRYXxyiNysMRLKQZGSjDfPEVhmK0SS=`}EA|p3^<2d)W!Qdv+JAD1#*%x!{5e z-=F9C{JNj1I>qaJf8Xcxe4nTPOz+NNX57|V_ItCIndHD+@6OoF^6qT1e$RY&&R)Rt z?pejW*V<bvc+qwCd3VWXpLdt-0Zd=qOLMY5T63=1I^(8&j<@U!yq$cD?00u;vftgc znd{v>n_1r7w@2}TJ&O-*&2war;A1=BlHHHX$>ADT>>FISHD|-toXzB0+P7to;}cu^ zp4!^CZEN2%Tl<n5???NR8?AkLFW*uo@1rOA{x{Y~FX0ZG`+2X^p2A)BH116fYq-x| z$Lt;VYGY=NX0G=JZO-@Jkj?qt8@B71^ThrJ9<?iY%&y^a`v_0iWy~4k+Fd+lA7W;W z^$k2@Z{c~n6EE1^c+u8uOSaCkY&Y<V-NdW5X5%j6UUj@~Yc}?db)99?KE%us>qmIo zruN>Bt+VioJ><Q&XX`BcHv7MKV6*>w<i`GSOm6f9KDGyN$sWYa7khdz^F{aJdI(?W z*YyQ%*q4|ytNvxp*|J&p-ih6TPwge#PVQiz_s(p3-#br!XC1SLGCRgFd>j@RfUp z@U`pI^!?|thuZB<n~d9CHW|0OlQpNl=Qhq<!M*k<?z5M0f3iN;ahp3*|1ITnM{zIq zy**^B&iYutz+<-d9Z$Zsh$rk7JZaD4DSH7=+p~Dap2NJ4Gw}R2@1uEsoAuG`bDQ<i z>~ov_qDL_2iDoW+e`a(qW{&7SylQvjHM<9|C&zo(aJ`HArt4RD%f80DS<jxW%zc|Z zZy(s~dHc|2_S;7`v)?|p=Wxm9thdYd46fL-xN7U{HG3M@?J?Z2$8po{!!3IRpV&S4 z)b7RS_8Pvh*YTxI?e>+;*W1_j8NRW}C<Pnn`<&zbvrnnh-ost?A?~&}aF4x<`)%ea z4cN?68nl%^WOLTiu&w+NTlu55^2coDPbPnfb)_j={nN?%TtsQcCZjZ)tY5#SxnzzP zN{h)cXUSI1a&pXBv6Zu$9CJ9E?kDDKx_&^<maQ{x+hx3C*YUosd03;IceIwhqqX+P z)>>Ywe~I&zDmJr}sy6$VYBu|qnpsaP>p97KPVGJV&u#Kb7d9EC%jAxLuk10t2bK46 z9?o)yhtc%k>3rLNrz`94&3gKh-x;F6Kl#gK+!?Uxy)*0{^6re-<lPyyS$Bsy;$10c z-0r~>Hv8O}wwd?NjIGSstY^+v=De-F7HnlMCx5AhSL_qKnjGg}vwNwpyXO>dB)_8> zwv+Xf=FX0-d3KY(T)}(xCEmA}@PWOB50mx32k#uYuFPZC$8gCmV_v$eu!`9uT5GHJ zB(B+0xNeW)hONw|J&3uBm@|S;?0$S|58$@li_h#n%-(TrH@>iY@U^Y8+}NFbZi&%j z{}AR`^f2aGH2dD|vf1}8xv|c^cgc-r-@Ckz=J{RTNAvtH=ZRJhdqgXTJ)*TQ=Zx0A z<2JM0ov=0Mq^<lZTluqD|6JBTpY<<f{mb?mYgg<oyqes>*SkE^Jo>ZB-A(swVEW>m z>fg@#ce4I{_ngpkV4ved_l)5qTYIrb%xvRI)?dx~YgvDj->aCdzDs}0-oxyt`lo~V z)YhEjs{Tm{pV>UW%S<sxvt1-VCFAa;>+Ey)%4VOt*LE4-*cCn#7HrP<euvHZ-tV;c zahJ_~yx(i@;y!y1_a{G{!UOg+9<(R$kUfcq?NK~pk7M5JTu)i|{+P|W_jwlU?DIZZ z(d_d+S<yY1y`!1&efEy-#4~mmp0xv>vpev7a{U@F*f)65zQjxR6<)T_@rr$cSM4TV zvs-xGF5?Zmf;a7byk#HYU0a!Zwq~F&o@*M@7d?Xy?MZxOPvK*G9GC0~%p7s;5N3|( zQCzhLaLpdXb-Ncg?0(ES<JvCFIiq{<iQR!u?M~cIuHWD@*8@Ix{R&^$*O*t#+`+7g zCcDfUS-&pI>=DgA<!-xznIqOYN4eML9Ob^Of6(5b&RxX*O+0KL;t~4@kJ`*r9<z7x zq^+DOTRGFVa%ODh%-YJCvz4=${Hf+&vNiv5a$_E^*y>-kd-0mxhu4!otz%}=xf<L} zc{}-82WD^8pLJof<j-4pFS#{?_mf|8rt*P%G(YE2e^cfqzqrK5$<MS`$vvzqSCgNg z;F^7knNMq5n!jOd-)8dXotT;8Y|EJS^2=4s`e@db+x8Sbv(<l|{6hH`_9f<}wQ>F{ z`<gnhSntC(HuK*Lb`S2b$-KvW>VMAu_qtrC_a4t;{RER0&Aj*elXc#E12*TqH<+w@ z*5?=1|C0Id4JT{Pdn5KW9!-w>jwOG_neI*6%yo|}<$PAb)5%TEz<#PXl{269FJ%3T zS^rYjzv`YX)~?xQyq@)MWc}M&|4!DwoAvKy{fAjUXO8nL|2XR}W&Kt6u+P1k%|7?) zS%1U6px$&3``>HX>~pVeZ{agrndi1LSs&-o+G~3d-`GQZrZCvUxWgX7-C0jh*3+By z^x0GNlN*1GDwy2pQ%tV>avGBxy^P1R{t27A`Cu~ZC-+VNY_fjNd@$#JX8&M5`ExQp zSg?8i!D6z0-F>iRH!yoE^TiQfvD=uwSntJa_5of`Zua2~TlGzwyZK<t*4o|V7kijj z%vAq=^2=?^`*<$RbDZ^;vi@?`U&;FG?pa_h>tp^7ZrZH-pk?b^ywuawoM*P?JWr1I zb75<?OZVu!SN1rccMLW;_d9HI?sq0DN1r#1=OX8Rw|mIB&zd;HAns4rkE1?ctNLfx zm}jzn-@89#bH@9_$xY2LVjp1M$F<6tu$42J9CM~@<xD5XoEcj=^T}}@`rgd5m>hGK zY|X!%++@%DE4Fgh?OD8G&*4p*eeQ4B>~nuN>)FeC_Ol*xHBWPm{^R5q!?<K~ANt&6 zyth$YvBz*d>uF>?&8(+o&(Pnt`Fj7%zQpIr`up1b3wr`zyNBoZZ{GGZLYznam5#Ul zmG0!{Rq8!<4foooxX)&WO25s#l>wW1D}#0&580fr!ufR%F@MZf{<y9D30wJ-w(_TJ z<xktn=U!r_^5^X;Ua*zFXe)ooR{pZB{1sdItG4pjY~^p-2YAb_;O*p>>e)$-cf0SN zL+Y%Fa~@;f%d!6`>*rbQDbd3#TKSwOTKjUIXl2%IWwQ61wI|8X_;IUnX4RkdVa_b; z&tsJ{`x>7o>(2(23!6KrTqf)9>6NQw{aUN=K4y;Ko8;$Pe0Djw-j6%%Vcc!cr_VRX zIa&J^vSjW173Pax#jKaLuRaSdYu~SsB|lRR>*eRl8BLBkW43a}lVi?Aa?F`dezro- zjLo^fGMgN8=4|CGx@Q|N**loI<2<{Vtmr+wp7m^GJ)2n%_Z9m~^s_$t8na%0&RM^* zpB(2uNRIO#XZ@^y(_hZ|D_OsPo;*{2BkONw{jIFO?Ve8h&+Gwwp7nEI+V@2lb#mkU zH<(wPC-9kOUeO(xS2UR)cDtW-ANJU+`>@wNTH9x9?Vx+c@Q^);xudx66dtkX@py9U z2v68$%o_E7?Hsd4{-P64yS{*D>@7TNci}mE6tjocw(6KQ@+;*px?aIcb`7t(X9cfi z{p-nJQ~rjn{B4`N`EbYX!@G7r-pl$AlUohyM|Kk*C%+oTC3^%jYn*uyGi&q^uG-3H z?pPndoHJT;vPX0;W{>C&+_F3INpkBNpSm7!+w}{4W?$iRo7#swQ)Y|WhnF@PAJP}= zWPC_&G<$w{W3%T2_Kx)<++}kI54w|I4dEVp828$o@j;(Gh&jJ<Uh(_^&!VY4;8`^L zJRmEYeIAe%9q@?Vfk%^D%>H1^zQ*JBIi9dD@TA?wQ}!92womYk&7J7`BD8O-iRbJV zp113G!EWG1yMmYO8eX<bc*QQ`b(`!58#Z|lHj}^D!CUqP-nKh2&otW??DJqZ`D>$i z&sNTU@@wTBxZZ^ilUthM$kxoqHtQagY@R=$FW$o%rZ1Y=A5`rXT(eg(_Z55QaLd*_ zC&}?#r}hQ)wykrW*-Q95Ii8C?WqwULm&x&5SFU$azfNvx{u}#<?>z|i8t$;yG5f_i znZL^VXy&i>+RR_=v)Q-WpRD<-12%J22W|4IL-rCLPS*U@5nDOD*It^xI_5h2SI3hz ze|5q>!jrb<pRzUow5|DPY|TG!A7J*2=TgpMa-4t3zM#HrYksoSub)>{vg9~Fdq-=2 z_Lk%P8?JXz-*$Z$bGF#Chj|};ig_R1#{2dWKCnyp(B^rSXR)8>)pAy^Wc8}8oSJ=% zn>MplTefC9NsjlxOv?Y_f;uxr>mJVRC48Rzn&<kS9QEk$Db-8YHS?9NGhW-8`Nlrt zdv$`nhdb<j+-<YZ!ycP`9`+_{&WC-r>isrzJ{+(IF)z(_qMV^*&G~RR`8D%C9C6PI z9(P^+6SndvljFWqw(8S%C!Vnf@oaM3cP=^ZJD(i)U2u=~T~5}Y4Ic77-nr&nwY%|} z%^f`4O#bQ+-m-`BwtK30$JU&?$#EX;y7=*WxS#x0_J4Tb9?f&;`XWBEm+-O8nI4vG z&h)TskKu|vj_X-}BkOP4%5T}qZ`(uo%pS()$zQPU;f2lDhnLA;3;4?J!q>@P-NH9E zy&uu1v+KMcb=aKuqfVRoKVp6CVg8S}>u7R5>a(|TzrBM8>;@jr`bV<<(X5|6V&)P3 zlbNUNW9rj(3D4NdpU=EtUsC5Dm8pC9Xvyxvt6BeA*1w+hZ)E-3Sr2E6b6%0Nn|vbg zxnFzjyWWitY-a!HF!`(3_{hG&Wm_{>Y-LuHV}30;o~7=34?Ub;^PDKZnH=+5w({HV z8OCS!2tKz*@rA7%=8I>%#H=sQ`-ro}y_oG$N3!O5)ag3&JmP+14|_f8PS!k+couWW z)AzH*9`<@PV6Wgoo4Fnh+1iWw-t>=U{o`5xMAlEP`d=$&#^!vFW|Q^%)uTDPiszHR zO7Eiuo9B-f?J2xuYvyH}{U5E^lX%r0!D}|NKUz=L?{AMbT<3g`wq3u%JN7l+bx**1 zb~irE`j4{y<E+1AchO&UkM5ynU*NiXW^lvSd7JhWZrRiL#MXIFZJoDmkKi*~=Vib6 zW38FlFM0@HCcoAhuUyv|c^`kgc>d_d=6S92ZN1i&)ya*SJ@oJ@@@u{BA*0skI{CH1 ztj-*<U-e;|b+r+j=e2S7@8Ai07jxz~XB$u1oVzw{pWqprd#cUaO+06}@Vs5a3w9kZ z+9kYXSMjoafLH7zylU^^HG3a#+B<m5*8JPH=I2>Fi{|H9^a&;_`V^BDt@+tIx`hwz z8fK1I*ZjwJ3G<3|&0n@Pf5q1PJc~W-StBc&J!|Y2t$y~4RzLGaYaZr{);w)n^PJh5 z=iFw`+J&uou9Htz@QuxkABW^G=5U9-ggf2Co*#GFWPjXilk;((y^8yjW6prBoI&>} zXUJC0u)T&y?0r0LD}TaP{-mv(DO)+y_6DA@l{0HAf6iXVi?;HaPxpDE{AFADJd1VZ z^DJ8VWJN2VtZ3!)EL!>7$*&jij?JDQ@7kMq&)&jhY3*yxb6{(pV_P{TTRCN0ITc$u zRa-eVTRF|-U+%*#djOx<to!)XzQ%1^YtQU8d~Ofo3!6Lpm^GUJRCC_g-0S0z{GAcp zVRMehoyp%i!d<TO^>KG{TkdhsH1174Wv|DaL3_2yd(0g2H%9T0J%)#qzr*~G*;_r| z(Z2M_-(JM@MK|$y^0!X#gzMxzo^<^PPuc39PHroI#&v3sXI<~Yb2hcd^U2>_!war! ze&)~&-(0~<wlbHKzrkFOc@}%fc)afVDBiF+$K%c9c-}2r=iN?@_q<~_sqZGod)~7( z=YDeB_aOP3I@hu5x;Jv;Jbk#F+|~>gTRHWtzmfH`x7Nn~R@UEk{{?H$+~14Ovwoh% zwaUNF`fuL$KM8O9pK!lL|C8>w{ZD$be)cHldBS<#^bflKlJ6xRvaj%P)<0rTQ6F^= zb3NfMl=IClJn1^KKcP?cZzyxxR_2VYwe$8SUa+_DqP>lm>>a$C^{iz*>sil+eMCR& z;~6>Y6V^vF?~~o+Zyn=3yNM68e%8nSe(LnevA>k{SCjQ~=1I-wOi${`-#)+%yMoyx z=A7V`>qD6LvEGGG?Qz^r)~~xKXRdeP^JM+{dUD|&)h}IN!B;kG87H0P2GbY!;%mLr zW?h}VRsS~g==-1Lw)*?B{{F0gAnPA?e~tbToBivf?kBH4W{=~^Wc@x+pRzUQw0lnQ zjIG&b-Lr=0?0vjwD`&}8&T_JTf2;E>o>w_MlXY)(UeTMFS2X+Aw`}&TZzt>i>pQm2 zxa%Ixu;;q&^U!tW9NEe_c8_vOwsOkuQBK8m<<wnQPQzAC(>=;**_!{vJqP&Ib>*D9 z&OY@En|<n+b`@XQ%=0w7?Rm=jcqjBc?aX?*Z1#EDo7~>UeKz;>wBO#v1NI&s&U!|& zp3$sl%r4PCnf$GBJY`Q~UYbpRUwb-ZAK-cSu<q$X)=%G?{-vycHTfIN`*h7_-lyv} zvpn6fHN&ROIi7CWoa5=XJ&1SgA-r!ZpZPSyH<W*9EC0w={;{om&L8`gU$&KBv6Wx9 zmEW+H-?WwAvXy^gEC1A1e%n_5nXUXwy8~a@efT<AzgIlHu^0IqXQzAk`bn4Fjd{iU zr~i|ltiRVi)IK3Mo|mtmFh?}|e!`k)WiofPGMPJCYdM>Ix{4?4H9VQDKaYJfWzXX2 z<Zm_cjD3Q6rku8V=Im8GpM1K57m~kzffrq0$4mA$W=))@ikU<Hy4KPs$9*^K6Y87E zao;Ul`|c*6DrYY_=IkfOoC8}qhsiPL$W~4{`Lu;A$zPws<i44wW-Et#iSu7#)<j=n zo<(2dQ~L&=XFV5L59?#UdRQ-iy@$`o2YVKG*xcKvoynU2(=K}z_h$WlS$}`lKalkg zXZ<5t|7g}fmi14%XOX?QmpJDJp3eGb>?P{+?wP|2HnmS#AJ<a*l)h+Xa)#(xyk=|d zx~;YB_hv13A)oG1-?0zzu6=}g7JI6gXY$z!=2>(bA17ap;gYR=S)-o+HH2$6GwO53 zs$ccthOM<H$^V;KK0URS&rALPPd#Vu*V@ah=PLPEwAZ!!yYY?9+D7Nwo<>*l{~b-A zbyogm8TY(h+vrdJKYVQr*nDjaCdYpEi)-1lG3*{{jS*Y<<2KJ56Ip#SIp$2+%9(YK z_MNk}@4T)21zVZR$rrnL#ooiK$=@BtYc{pUx_b`rhJB2;?L)ki)ydTvV-C5|%Arq= z`yScam#kP<e#us5)$YbMy9d{kzgxx)`x-ah(}!F3Aa2|J_$;fRC&!!%TRFVqJlglh zX5VMQCSRX%k3D4S^XT%gtYiA3w{UOrua08YsQ#;~m^HCy7Z2F`m|0_e8xPq#nDw!~ zfyZp+k0;0c30wJ-?os}ft^8Sg9naayoVT^_f~|d*ZDx74Vvk_<i1W<gHJglQ<i<Mt zKO;AK8j~BX9CD+T!+g=o*|U|iZ!71(R?e}loRY1avaOtot(>Z@oSLnirag>XwsKDF zS$t|Mr)?|e%vR2&-N08i+4_8y&h=fsKD$ZQkJ0nso)g?*llQ#aX3yt6S-m$|InVo& zW6q#^*!MYi5$}+F^;xlK<#V2BWsWCb%-{)o7IU6B=PI7E%Xr#7oc%d#)N`?fc^|!i zdA+GGCVy8s^u<i&@ILlv-!*#{uiMJsu$8%OYvvuhjdznTukl{8es6ic@1ApfU|->5 z`vRA;dO11fRFY#(-96g3VQb%}t^Ag)OrGgn`s?{w@)hfz)7M$l>5J~Aei_2|7Io%} z?xN0ler-{|v8jJX?)SO=S%=+Cy)%TaqE275>b!nkQSY%wsI&L?7xg}yywCbW_<^E6 zV3(*5hR|Kqhiv5!hwy_%o!n^EM??7aMSaZH{No|~P*I<-nf<fL5PFLGl&$)72tQoZ zXKdxnhVUDT`kbx)`4E1js4v*6FNV-t)R%1KEQj!;MSaCq|7r-ov8b=vs;`IeV?}+# zR(&&szM{TmD}OtL-&E9hY}I!|`0=8?XRE#+!f!6>2e$GLL+CH+N4ENpL-;L4y=1Fi z4&k>J^@^=}HH4oi>NQ*SdI$qWy<w}~4B@vG^_D$J{Un6nUer%*^|wR#9Yy`jR{cDL z!J>X)t9}{6?=0$9w(8d*{H~&YV^e3G@Vi}acG!#5J3|;M>hwi-Q|I-2ih7SdO1(FP z-&@rCY%-etA^g6gK42eEALKtJThxba<qU`L`-}RBtvautEb3#n>f<5&fucTPt3Jtp z8mg#I*{V;6@CS?fjIH`?2!E)k&n4etuI79QKULHh>@xMm5dLscU$S?pFNg3)iu#JJ z{?!ovXi;CY)xRFXSW(}w)xR0SA1mrxw)(e2_~S)=$5ubj{zOsVv(>*J!gx{V-lNrj z7{X5%^&?yT$07X5qF%Dq&+AVW^@^?jY6ufWy=JSw9>Sk4>J3}{%@BU3sJCqOpM>yd ziu$Ro{&onHMg7cH|9J?1wy0m&>c0%(&lUA6Tm9D|{A^LbvFU#iLYQ*>MTb30y)%SA zU(~zoQR>|x{Dq?4W2?V6guhtS`)u|1hcI2#2W<5ZhVYk)`jD;u;Sm0EQ6I6@&$GW$ z)W>Y~kB2Z*)F*89PloVUi~5wU{^<~YuBgx0>gV;>iu#<b{`nAQi~54C{>2dfdQo4p z)xR9V-ze%Uw)$5?_?tz2%~t<<2y;b!!&d)h2!E@nZ`tbK4&iSX^&MONyCM9YqP}OV zfB)^DA6^{T%=O|h^O1c{{Wx<e`4;!_q8!5CEAlJ0_O0@th%4$fTl>~S`1?h@VXMCx z!apeLEnEF3A^gLlerl_~9l~N!KeN@(tpBK}U)b~1FSD7iZ1#L{9l}2@`fuz`z7Hg1 z?y%YOCC`@J|FX+ge|P2{o4H>0zTN9(U-FkWsrQHQPm7!ZTRDT7hiqnlIUK@2EBZ(5 zDs|4hT-3*G<&0;Zu<O((L-^-K|CFu%>C7{Bi~4K`|Dx!hv(Kr|hwv|p`hu;T#mq~# z=3fqBrRZO=)xVl~&DOr_A^fYNf5X<kn<4z`qP}G-XFKzbt$lYx`1zuL&sP6_=7Z#0 z1Jn=sSEUsFN4ENpGnbNY^-wQ|@C!wM#a4ecb1gaM*F*R>MSsIqe=~C{Ip&{)@NbL$ zQ~R9$b_i=l{mfRKm;QG_{5f`E^YtZn5$p0*@;f8=I`fUqoqZlMci8OtIkPI~9l0yH zV*+<)?y<M1_h#<1ndS5T%mc|^9;H5*dC2BIJ|E7^+?wHgrm3^$jmK=x`1yEd=2OqF zS)@Lhc`CWHgF0F2iJr07sn2GfOa5NY@%en_1$&n|d;B6f`s?#0yAv;GUa`BWuV!9L zzNLBAL-_Ya&W5d=&CFZ2a<((?*r(K)=|2=Xd$w}+GauN>Im~=ypHn{$VY|pF*~%$r zuGq?{X09d2bJaumk3~+yR!%c>%T~@wX3i7WYMyoo|Eb71vz5cMSeGws<y>aIN{;hf zhwz_^oSWoZD|{bI2w}(dR!8zJ_H2>+Uy6EH@;lU8?D1cVdQb9~2B`Oj@ZXAhU-GRI z_5Kici#mOB%pVNlmx}sOa?BqN;lCI4k>p!7az@|&+-r>`f8RXy@yrv+U3Kb{nWvJ! ze~tPy|2_30e<t}I<<Iip$u8=1$?vREXAk{)iE9^<f8d1rV&<jfAFNPc&b*TRLp#*T zQcg5;$Um(9^~@W|Ke9!AGc)hi|D*fVw=<Kg`j4Ga-_5+2{Np{;S)-olgXEvkJcpT& zk_X4AA7?Hl54EY6Gc&g`f0FxXRrz=KWBt{t*_x-$zqh@pH<I5Or{3h>(_PeCw(8vJ zo6OVXpW=>N?abt=XKac3dFG4cpI)YZnfWUDXI7|RXTC}P*;T&ZjJcH=-I4rr+{3HR z%w0Bj^Qt>@Px9X-|5b11KARa|^=BSPUOJ*an0YAqpV0eiIP*yI&vWiqqnVjcGylRk zbzW~gk-Wh<UQK46O8$2n)TcAgB=6AsYBuv+@-H>0&u3mp-fvT1%)FHRKdz`R^SNIC z_`X`PYt*@G%^7>vlK*E9_4Ulmr=Gjq&8tm5^Hk()CEx0&zRl-aiuz7+tnczUhN8Zg z9P9i1^XZ~~kR0oW{PW17ev};R$NY1tqFzdl^)ml_qNrDrW4+4%?_AV5XEfQb>imC> zMV)(;_4oZ(&FqY=Wc_=mUY%q<O)iuDs-5{P`GYR%=b0~(@6S@d%zTynl`ZPmnQxLG zkpDVl?nr*fy4RhV*-t+%`fT;<?#w;O`rO~^-pqZ;^=<0?d{2h&;q^fB_l#2~>x-g3 zl>B98e?6S79ZCL_`CpG_9!qZQQYTBZMNcH_-*@zSGV@fjzMt#$bY}Xr_LsSv*Rz>9 ckLuqkQJ>GekbI@{E@ob`cc?FCUa=ehA6x<EQUCw| literal 0 HcmV?d00001 diff --git a/rce/rcecalib/server/ThrottleStream.o b/rce/rcecalib/server/ThrottleStream.o new file mode 100644 index 0000000000000000000000000000000000000000..1b05701bf348a405998e21b0b5fde67df0f9dbe6 GIT binary patch literal 660216 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⋙l9D@qkPddkNq>#ZGF~fXf2AgMwJsL9v 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	W#o`s!w#daH>PQh*n;f6+^Z+=2 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%0AYJJR79T zF*bPt;Cr?GnGXPdSi$jW6z*G^&*m=y=C~b*d>!<Wrr-Z=j5El0O4orm0oHZZX$Swo zM{7QF$^qAFnu?bJ>$t_@YXNiIKKD()U(__qQ5J*GRj~7D0x;+2Q#SzKplQB47%=(~ z%7>Z*0qeYV-q{_nZg;V6l*!-^HO=L#Fx45V{XU5@Ozf)dKS4MN&d)Rd4j5%XX(?X^ zxK`7A<6nU1Yx_Tq0{o7)ulW_=e<(P9=%*cLh@;^(Xct2UY5K3+4w%!sa4z68G)?7a z0PAtqIqg2cy4^XiYzBO>ra5o`;L8>4>~{~~YcxEh3b4)xXa7F{M!qA?@g+Y2jPNK= z?nhrW1nq?2AAK1x{1eSr765+GfL}D=zbH8N4*I~MNGIrHOEA_AMOhM`GoJ*!kG8)u z0~qljo~!o+jJiei=?4JM(e%r|4)`>K{!9ZtPr>m4dxHja<oD+}z^DhrbLbZUqaPvr zH$DsadJWSYVCauEOml;wC<CHV_OEI9nag1RM+H0ErUU-7hL1=24*jc!zqbl7aQJop z{!hSYCj_520&h2=Ac-fXaTw|oV3o#U6SY01aTwPPO5?DUL65k)e$lpx=O=?fbH0Z6 z9Ss=yOEl*_4){_HKl>)&D>ZxqXoqpzoQSjzyFuGOiu@b4QNhlVF@W#T@P(-V!|qaW zyd32@jN8Ip7XyA;(;V;^;NNR_<#mAH)9~w4aQqinaBMKjuvC||hB=LoeIE9QYx?^! zhL)lpQ~WED_oa)q{j{3_w<<WE{taNA_V`5Pf9Xn1b2{-~qy7F9ZLSpUAAI8TQEsJZ ztAL$9?FaZGO|$C>fKir2^J%1|^lD9W@}B@B4X}@$io7YkQQObC1n{leelW_nbd!SP zYrYCt_iqm6N$C@sp7NyhcN(TVDSb!7Do;LEu*!#BP-YYs<q!6mRXizA=#4Cj^KCx> zT(99%UI2{tPjRmK4B(SByt)(c=M)?}3T3rRleQoCDBvXucK$a7xJ}!4%>kU#^iQ4z z80n#~X1xsfi`xDZq+^$_Xn6G7fWM|`vZa7^zBvlk{ey-%AGRW#T^`o-3I<=|uVAhl zGw#Nl6uW5tC)EHRr)egjj$lul=wpBVFTmB>{zIg9_+c9U2g-9e+=%D5(N2fMjp(ns z9B^L2@xx97tjj%qDC*8|UGC0Cl-F>s^Jl#V_#Wo@F5vq${M^xif2;Y#&}N5!pzWt! zi?_eZG)(ayF<HT}vj|51syK85*7Y`i?(u-Xpy~G^`)f2@`dPp~)bPP~0_ME><Wj(I zXg<G2*^P{A8VYx$&J*X$DF2bum3{ooZvmdK>2rSu+@;|c7Xd~(DLz}!myi6OhU?K+ zjN~*bo?I>~H^UzOK_3TuXXHOL{Zy32s8I@bzC04}A=>`(+X2^U``Ir5)^Ui_TQ;N4 z&@^SJci6jDakv)sXcXtett$Y3Q`?W21o%qL=YffUf2`q(HGuEa@Fi~n-m2-d>jD2= z!SMq=#=B=I8%pEuLjmiy6Z<*pb{P@@duPnQ0PFa~>7B8%Gc~<~wqJ(0lHXtK3ix6L z$4`6&@D<wc_nHBJSKF7OE|hVd`7-KS+0B~f!UqAPy-~h>>nOm#P;l&T%K&fDG*!g& zNlh~!WsQAl74DVbUG|!$sXiI-+uHst#H;K>ZU1TH_vjLBU->j(lmVsd1Jsw%duaF@ zF9JS5!SOFW3b;nwzl%CJ8gV81hc5)I>!kDe-vDzNtw6oNUbLcl^jm<>(R}i60sfA* zr}^(_o!;2HO@M!@?T;S__`ek#Th{>if3<xl@}wMYl(*Se0qg!Pp8XNveYE|R-v@lC zhF2l(<%es(mwg2I1Py<C31GAn%G)*IQ4XBaaxmgjuHzgZfOwW;{z3NR_6DrW(fKm+ zuN-xS;_x=|t^76(x1k)%AJ_CJTm<+f1;;79<@hH)Pm}`I`5!xBF1A1hX&MS^*C`5) zwOt1I(;A-nW56eBnuCxxyQ1w;xYWLPMV=D;F5<qco@1!DGIrJV#F=;<>``V!^B%st zqAV#6cYO^o>MPm5g}Sq=&fC~ci1Qeox6TEB2CVZfb~(yw4CmXYk)LBYuYLgcG2NQa znMVQEc@=wX6=0oL@xwj=%ysoFq-o4knx5+0nBVF6P(2*O_4A@(fd8rOPhE#S+o2ln z+8yw23XUK0d%$SV6#ri$&&E#G_Fuaj@GNb=<THRzR<QH!1%O+${d;c!&T0BJrvcV= zGIkOAzp<BS`-2d7>>;bX`r~<k@6hlmLjd2e;8;7-HCCr3{(1Nt`?|J&U<Tm#H2mH( zs5b+&UrOUR-M->u$Lsn;@t^v4z`CwFlt1GR)AaW(1bm$4Q-%644(TEKLskRUZ7p^W z%4(d>|9Ho<fY)ljPYee9O-+9T@?e}!OT6+AfKhM2$9d-@z?(JA%dY_Ddiy8jKfP~A zG?zXC81(>fJT(t6+7H>&VqrJX5j<mmz$hD{IT2y*cA&Pu2>G*Hoq}WE-v#io+Me3Q zZaOVa`_+JTU5e8@akmwkCW-d98}c1IV;5`!%x!J&G~PDUJe^0o0RMkXodcL1Nf(Bz zIyN`f#5O0^#I|i?GqG*kw(V?eZ=4M_ww?UnIbZFc-shPo?|yT-`qV*n-@5nq6r=r_ z(%?$U+H3I;J303JYUmxv-*$mV(WXs*@O0`cM}n78uZ8%;+p28x6vf{~>`I%TfnfS$ z`XdJMk#Cv%*PCEBPVHIXxzzFAxQV}*oC7@)e<gVi>LUJnWt$m!iO+L+X=R+<w8?e= z>}u?vBH&}Hd!do*_-AO7X+IeKBXgYH41AsX-?71WsK>{e93Qm~8&CEW<FmiagfQ4M z#gF*kZ5}u&ZKAaW!&lK$ie8m^SJYL4Hp;dEd{5wdd}}K3Oxk3EZ35Pn{RF=f22gLY z44hfnEJM8{L`=n>)adVo<&|w~%q3wh+T8gLW}kY!H-kG;4`>MPP5Tk>FX3=<Nc4U} zSLeZ<zzeCj4GTuTaV{GqHW$c`(2oh9D4Rg!Es>!<<Tx0y6Z=d!Z=#H}S%-5bs_1m| zX(F6M;&X5ycntZ$A@C;J1V;vA{xZ&$?%)sP3it6hDie?g;XH}qlZ;at=Sqy)6<&;g z6W1VDL0l8Jr~Qnl-~nXWGfT{RGZFp(<9IptBKkG)QQ9<L0{%zYOVZMqB&Zv)SuqqG zoi^v-dlL4kja(gEiS{Y(g6V@jh2JOXOuam6D#-+nb2$ch6}cpOKgmXA`vbL{<UBbA z@{r^zIXD*Bts&`JgWs#}P40^=e~cx*#h(g}M}GbioQKCoO$;tXJ!Eol17%PA3}{ZS zz7ITv_9@_dz-a2SHxsacy2%7yPQ5egHee6+C0LgNkU#ifCp`i`AV<gteogz)$H1SI zP5ltYB*lEh=K$1ZQp{hDU5MW&%}VZzT1`ryt=xYmEl*wUQIpo?v8BU<5epe-EOM6= zwF36W;P*+9C*e5bz>}42hxlMu+qF`I*V88AN$_4}^BnU^dWswo`ANz(!S+rIeoTD| za+vfZITP}hETpm>SsWalJhuWk2{{zbn=CUqSx#_S@+`5buWTY<jAX5py=J??$fd+2 zP95+{A0H&=KLh<1dEqNCdPC+LTm}5|w=VBnLN{fy;O~#34rEMI6P$wfF;M%-;kO(+ zx*WI+?Te!>lDD8<b`ZE7IU(vKIsRY9TpSxbLfO{Bypk^=NACk>ZQHDEz|W}fK(3Sj z`pqfgD0?Lf<E^R^%BCFrO3{)wOU8gZkmnu&_as-D0Uk-deGWWc+3SRVQ%s{ia1wYf z_1f?)#TK8A_=^9BPC{pYc^xW(|Dnw?#3#i^+VqYK{z1Jw{7e~>ob5Rnd6jWWR0X@b zEspc2bbVKR9+<f{6X8!v<VNBgtt7ZBkDV;`y{Pv^tWwUQ-X<J)G5PUy@L^?J>;%}= zXJXV&N>`IfBY;r{7~h6TXG|*mzwnN=U{{lm-+(i!?iE9wr^-Pdi+H4}MElT)RVvJ1 z=5>52n0{K->8B~%5xR@B>Ws79DP!*RjdOtG7d!;r)#~(u;D2e;1~r+=)x#|0I(2BC zH*gO)HMwyza3=EFv*04+EPKJFl)ZeY!PM2L-&+T6?PFJ~s?YZ6`+WT9H>U~jW9Ne$ zo2Cr)!g0Xp4T(?S3b5;oUfsaMefl_MdkguJJ@NnBZy+z637vVgvrd99s_qqpziFQE zSk+(CJ`>KLHWImcVsKj8oa+zfI_bs6wJa_B$SaI`Oj}QFs5hnk3e-Sa_K`^+7CeCZ zgzjMGl)B4lhfmNq(<XR6co)a)gT6?6p1NG8(q1JWm;ioB8(BBfexUvrY9k$M((8<M zF`cW)oQO?2SCgu<CharSLpt`3O?4T}-m&`<fm?CRV(=v$YEfbv2lGugjQaKZ;IZVo zxxnxnHnz|j@G{y@$_7TAiQcON7&Qv^5(b0+@#zm~zb+*H-ftM{?cae}8#W>8GksCo zd`8~Vmv;8?!OeVnTOOM>19bXn)ZY2|PZsE?Cz;FC*5LKzMWeu|kN@izI8L6t(2<+} z>p!Uv&TdQw#OOag1J+Zp7wQFc)`^avp#<%xA$}QJ(7rZ$D?@wQcf@*=VF+376EeUL zjAN%Ewi&Q4$e5}lrowSVr*G7+Q6KUQ`j_AK8I7`)ebJ1F(SPG)OiIo-4?26?mahsf zrMk&F1&p|e52|;feZ5)GQFH&-r_=uVGU$K#^yAc*FM<Bjr@Q)$j=5&~<F}qE0r~Sb z=!JcHN%Ff%&|4~-_EW*AA@O0~B`|xRI({d5GsHO42A}<QWiJHA&cxpF63IBMJ#WNk zV=|-WaIET?BXFDvSYI;-`gHnc&fbCE#;13t{hz3Z%+q}OTxB!p0rX=&{VaKE5cKyx z{TuE7>19lo6u<Q>>6LAi9ndTJ^qRC^xET6CpFV<|5L%W^J{|Ls_{e7ovi$4QQ8zO8 zQK-+X%!|e$tINxJ%qc5;6`M}*A!|8~b9)Q8JGm2TCu=`tbM*=sYmJ<1c1|$+%RVj! zK1W^dle5B3Y~G&$f9J7B@o%;e<j06pws^{3--O@*>N|3Q@gx59{sAtaZ1>#<qmH4Q z)5E}ZsLw<#Wa~tGxu4JGd`@;7JjbUaj&kgu7$e&upMH{h-R;m_taO~W)I0Y#CVO<+ zj|&5iOFcpva2}uT)`axWp*QpCT(3+A#5?<FpN_hh_)ISioq05w;A3{?(KMFxURN9H zcgcf8;yv2Xzx5oEI8JrUH%A7aj(U~(ra?{RaB=I7^W<RMOp)1O)S}p^&KfiIQJXo? z^Z(b^Dtl#6r#a5}^vl#|wuk;f+4gx1X0B~p)K5;#S>`BuPOR_3!zO@B`t%CQ-k3$u zJNWc&)a7%`InmEJ){Ary%$(YWS-^XII&*4!Ar3j8`1IGxrg}yE-RP*lb=m6|e?DG? z&U!Po-+*1cr4I(z=dtp-G8c1d4wMBWH#pX)j#?DX4%=L-eY(r({Myj(`E>eb^CiLG zmB!ru8z*-JWiRo0=$U;weX}S*le-c1Ebt+BOWJoo4jw}ufZESJS=lbk0p3jeR&&9- z$Ukvi$bE<Q0YAZysOLre@}R!qkCy<y&y!Z!CMyI+tfAZPMZuh}E&BpIh5B*KH4pM9 zHW$8uk1Bh4-+@n)tIPr;)-vC^{lT}%2aADSOtOCjzf#?P#@Kl<me|WZY9Rgvdt(ZN zBT|2h+6iQD+Fn(_sc93C6`YYA2C)jnImEYA>A~nX8K(|>46IAt<OMe-ue=QIN*)jh z?x}3v!ZvV%vR5$*cpCMMH^6JiOFDsF-UASyz>Cy}-UPFky^*!RUsSil5c9xav?(+k ze-}FzIjA8xA#DN%fwNP80l)IXCyB{R(NWVnFT^u%4e~VMnY8(k3_M@i%Z?h%yPA3< zjFEREdB#34;w$6a3I&Ew!WW?BJx8u5_J1pTiC%+Q&t4JqcizXUn;T8R@5#$bg1^!} z!Z_^7a=o$(5&wJ<sVBhNnJ*FTbFBcodV5+3%=)+Mke7V;f0^&Z+29i7c-z6qH*_xm z`N~&Y*|xh2ZcdwJb-?Y&L(sqZdXSsn1|vo?=1crO-)LpKKQ)-^jIH+&%yq`pK@9S( zr@edzG9TlkpNGtM%crAuWlXWjAJ@nE$SDp(uTGZNJNfI9msbOKQ}!ldzWE0#+xm!K z{^8_sxxsVEX%V;li<M2)ieThV&U>RT80V0f6u1VyL;F&QS^h`l#;DW$-^r(2;qR1( zpnW`C0}Dh}R{sm6q0LyVfd!ZglXoc?eqekXA}Y8b?SpoLnHR5c0&scNy+kL#s0s0{ zd0228a^<ApgX9=P!0Zt#pEE3Qo%$&`mOkri!vZf=_qyV|1zj&({QyS1WWJ-%fzf;7 zo2)+t2XLI_{lM&5TWmUb0d2A(w*@!Q#^Aq#2dHms06s?jSz+)c>itrIZ;+!Q=LMZ_ z?+~|w^v%|31V+xphqIVVA<J>*t^-G+{$T((CiUr<W1%GEmg~Vd2aYvMCWEule)cPH zAoatI!6lTv0$6_vG0ye~>bFoM+MIj~ZpmZAt_AlZKP?2F<>OsG{#)6!$9RQsy!bEn zh3T`#zp(Q;8fvyMdRY97h1?aUpPnrSF0HyZ5P2?Ki5zhzxIM?LvkCksIU{^5JW<&k zMotUQAP32@TgmAvfcKC`2Z3E}^vVamOT8CzQlvjw-p?w+UN-p<t0L$z@l*9JWYt~0 zjZO@kr%peF&*OT^b~Ng!XjtlLT7zLH<K+JfoRc<QZ?IecOOyj6))Kc#@S!O3D%=~s z6~#IN_R7aIrdSy2&7Xr)E1Rx}b1@gUq0PWt!_7LZ3B_=3Id3TBt=Ld<=%e6e<hrPt zV#mn&;A61|%3j+=V4OpIm{|+_hMeoMF~!T0`=<bJrhRXmqxeqh4=;fCQy+@+7e7LM zP-yUZWmDlB_zG?MW9;H?4ZMi+7r#$Ecmenck4=agE{-3WOLN4dIQmw6`&<)@u|!Xa z+6cnG!r3uS5M$-dL@a|?hxScga16Eavc?C;<v6*Kw;-3Jf`5Qha-2KM!G&p`0dWmN zearZ&W9<{p*&KQ|pFV-S1hzq3Z_Q&|FM_tIZYNCzvnFlZ%V5UeUTF(vU3uxD1+iAG z?BxeBFLnlE74(ebPeu-d@c;0^rfmTJr0n$?1pYyrsoSw18iF=$g23UZd&$A*fARnH z95CiA<J8XqMqI#N(oEn0+H|i5PDPuMJHV(>u@AKioQ*c4P)jB9koO=4B?^+|`>!R6 zlW&g&mr=H*mVzrOd(&}T3B*^%Y;X=-kM<42gPW2Yq0UPL(>~g8Fvfzt8FU7WvBc*d z5x}ddCmsWauQKKvIWKF{KD`Qdv0a0Bm$*xtDyWwd-<7?R$8lfo;x+_hmyArC+{j_c zB+BL@{FQrm8Q;TkCDW7pX9eR&e5;%QoSS@n8n^&$4nQkejNBM@B}>yL2Yf5Zn3$un z!Hk2w`VHKK_TRC#mvpsvDm1tw^_;W7SX0EGnS;RtIp!YJQc1*1^jI^&E^fo&Z%K?L zenu9??}YElT;`KIA{Ql5XQIn@!%D7Ewx7F#H&K`Oo=P&#UV?+*!_;q;1fL|I?g2he zo^}^}McFPr4ZcOa-dFH_>g%$DpOE7qFC||qdvL>)a&Ze20CsVkiQ`H!Zg%?@FmfaF zU5>n!a<$Z>G1$d0T5GV2VLkl5R0p*;vD<<F<hkT?WTkp>oQN|1XxiL(4|dm`>g~bP zY16(B*!BA_^i!$D)I0P8ui~*E;({M3dnvboUr;Z)2>gyLpEECAhy1ZRxRJ6=1>Z`y zQ1*ggUz+FgO6LJDp?%*KV0W%(m~ZI~v>!AFyp7|G9Rl7%zKGf`eUKcq8ho6b1$ABe ztg_cu#=NX-JosMv2Dxhx7`a58z4TSUoR>K<8_apxYRFq@H?M?<r+nU5>~mucEQ5Ly z?iCiCSJ~cP2QH#)UTp-UhG1igp?1oYr+uXp;HtDA4d2Vurp>5y;D*#!q7TY6Cr?3a z%CuGXdV~UZrv7>sxQDZu2S%RcT<7k95hJi|5ee+_F3<5OGl@1U#)8=+UPNeR5J#Cy z<ThZ$Q8?NRFy<f}^AdPFIbJ;QUUGtK;6vmj$a5LYP3)7V2BY_cQ*;FXt!zd<1m9G) z`!j;?lhdLn$~+-wT?T$dej)MvNDc}Fqqi}p>7C4&vd9P6ZY&N)4n)s@n3RpI>{Uc8 z%VN%=_eV_1!f)a3sQ0n~<d?s|%$?~z4(xKb4{<14N^R^|*p_wql51Jn2Gl#?JY}1a zqbvq9M`mJAaCg-`d0(z<UuARf2$*>>AJ2kE@z@y2!4qf`1HP1<#$)rL_R6B};j<Tr zIG0^S`$vtzD`}s46?i@MFLJKK)JKRvCzZXl?Tsmib6^}>6SZ6}Ep_?ae!0xlzt;!n zB<C3fE}?9y^aqzG|FacbP1&oo16+rC)jz>4$uTi@Ih;?<6#_Xbhu?|+a$jAp7j33R z2M-``hX3V;k+Y&M%8j9Y<Md$Gsuv2qQx3H#<0P#NX5HFR;<KyUdTYUdahzR<ce!Ka z)L1jh{i|%N;{4^FlB=PX%7<3=yn*0|)Ia06@~M^e9>07>+N6IBy);?Y(()B)Uu7k@ z4Rwq9D&L75DB}myW)|wDJl0n6e>D6lKbX3F_M`kX>eKduHz}J*Z^5V!iD9Ut;Ahm^ ze**ucJ_Wh15R3Xd<gfz$)IP3Im^RrFw+gkCy{@mp^v!O;+EQTz_0|}#!UEcdE(_kQ zY<h$RpQ64dH~0cs?eEd%BH~x!B{@rL@K@R-?Sb!$GPXwcUMj|<%?6yaVoGH%Tz)We zEHTL&0i26ALG!@)9dt8I^peW9MGSCx>Ib`kIWIdf44D0Ba?AMaM_tn@y1dAmR?+1} z*0hSjI*zVs6<uCrO{<8y7k^|;t9XOwoxcivm;5j0SIPUWS3-;=NA(gxcXO2QMpeRC z;{Vq#;G#Zzt|#Vnb?EFPqxS40uM>Ku(nQ+NoD4?pWqf6>d&-rwQNM!Pt6YLCuZJo( z^65R5^>u4y^sx9duqJF~kyoJCDlee@TlimjFZEpLp~{!YM?!+H)21t8TiIO`p9X>7 zQSX9zR4Gip^*6Y$vNsHMQDwBUxrg7&XQ#x6oXA6!<+N{%8mY3C`a8tD$|3U4GGJG4 z9?n|@YquO*G7i|)+qtjC$g}I9TiLU$8jW1*GB^Y6r#1n*o|Qeisx7EzJ`cvYa%|jP zVB}ahdN(lUFP!5F7(RhL`K)NQ_|ywL0Vh>9m7rDQx$K$~;Ow+HdKz4aHXq-BnImt= z4{%rNgSLZtEwByYPc_DeyqPwEd7#5T_+WnC0K-oBM=S7EWiQcOu#3s(df*SVX$Ie_ zM<9z{JvzB5)`99SK0m5}>9biD8_ZZ4)hp3{DSWKnR$1TIu8!W5n9RU@tB<9Pyzg9n z3T@)v0<WhYh}y5dje4k5VCK~Ps1IgrZPeu8_s+f?_#62re5(<QJPmbHBOy6<0Wjtd zAFT9djgI8d&%l#tQ+Nm1#j`SMrUvdI#9m%w)_~u_XJ&&LLt6&*SmPn}s_?M}{jmwc z8&eaxm-%LR3l2w{x$vcCBA<>q$e2&?Z%yP(?2F?3H47@6Zm7eWRegGG+Ar+@oqn2E zZNR*)nLTU4w|VT?FJQ!1#y<&vYrdj>prtXjLQ!vrx~Romd)4QF1E|lf14i6&tcl+P zT$uWK#HyC7$w-JzEyVr5@oUv0KROGYYpH#F4h;XqCNcb~)k)dwh1k~$rk-^JxG%Y9 zGVow>`U>EYw6E71%sMfhvHsLzo!I6v!EPOx7!kZ%?ai?VVD_UI?;iLV$0=SHe1>du zfL$*Heg?a>B3C>x`@&uc3I4A3HqI4eY9p@_lU519ameGJf>Y9_G3H$x<HE+1F>9Bi z4GuN6F&~M;>qX#3w3)F7+|y@2j`r&i|JtrE%Jc`%qTV+#cmeGv$oR{s&#neuLwz{> ztBq@k_$hlJbz)GTnj7r;SM?yD4eI;<_I=2*$6jX;Is7f~T(Z0eU1y21Hvn_0vs>9F zeFQ#8y$t4C=Nk1msNXs+wu=M6AF0b{VCwuJ_xA9f7X37btAmjP@#j@HaBA8Fqrd99 z*mgy|$an3;M)q^+?(*?vAHO1JhA;J8?qpu|qESB#f9mmGLa%rAvZ-!^;ak1(w2}GN zLwx02a=%v3t!XmfdR=JWumgAmS>{!5yt0=KF|NmYvq{E*FHvuw28_DFn09n`@N06r z+Q!sJEJSaS1RR#U0e;m-{zQLN5?qQLG9kFJvdJTQOLDAAVESg(MFyjX#s5S_z^=cV zq3`OCq<*avc#5*uIR=>ZW*g(U`m0s9O(uf(kQ)pDAEW)uPhdC4lj6^P)lEtqSN{ol zX(8}W9-Hf>G4iYt@#g|;8pI{XNd-oI%N#Rc{07;{@+^)9fy!R4Nnq5R*qjalc6q6q z2;5qAa|r#^0PBm`Tqq3gMP2s%#c$|dm^k2R)K{Tq8_Xe3O$XkjY#Sq<4R(+#)CZp> zr$v1=z>kbS9r<eTOxcUH82pBMQLOn5!#Mjq;7H0QZ&Gk-pPo_KYa1UrbE@w{HFR^l z-W0l<m%KmK(9P>pS@0;188{C-fxHm@G-SSv>Kl2kJy)ThcJ`QG!;93bv;`v{GM63j zzu|jw;_${a!jI^6(Z7wNDw|?+!70gdjc$~ld?PQogwxA`%PZRih+CspPDdOX(SNfJ zF=+Ik|DvO|<Xm%agV8@=6IcVhnfjy7V8);N-%iIG(1<ZNd63UWpQ)$BJQ~N~IHEU> zNB(;&I0sqwFB|8heX2lkP4ZyWaAU5A_V#r!>&L1-P;I=pm{()=g1G>n8y}}0tsdC< zCh=^1Q+1P}7TDFs!=vC&)LUgRrb%RF?dvA4{-v**<fe`Eb&~?*4wt~LPNc7!uue?y z958Y(F_gY;(vX}j4Y-Z6_H~m^)YpfF?&dNu5_pp8rU>HPWG?NcubW^Fl8Xw+Ns}F9 z>FXx@l<mPLVE82GmA-C*c!~YPW#Ct2>FXvR$kR|GO<i3{UpHl4*?ovj(-a&>`nqX4 zWv}8+FxCzkQ~J7T5N&QE#!Yd&=+f6sYmna|*G=1zrLUWIA<K7hnvPJ`zHT~>dUwRR zDX(Q#`nu^V>KSnUrU#U@ubU!ga;}x<q2E%r@;-9Y`{b(sf`9(jn}sBosb)+w=2ZK- z8Ruvkg@NwoC4JqD^D_64mu8LhSnXf=tRBv5HzJ44m@n$XX>$+rYPQJPZvwBNeZsHc zLu9GLW+!OVB`5d}b?NJ750$+F?ZMw^BYoZ6qfM6|V8lq~9#{^XoGi83yr9z&hvqIX zht`At^I!Cq949Yg)_jn&N3NQWB)8uTX8g6Un{(~5?-xLKF_->ren#!R{PV$2c&zHL zm2G>>r9}kl($_7blP4|%XQYkvZwvOmmo_t)^`m{=!u9@?jnLT(+K(+<Y)5B@j#z6P z5aSkqam=UX!S|KDj7Pxlsqa4p{zZ;^z?hbylue31z*y@sj(#?^WdQY1sF9Y9smtDY zOSk4o?ph9@&5Vm+#6o-+iSx9aqikQJR$C(X(Cys?VD_mu203kcR&_66CipUsy*wWG zuOVqK_Y$pQQkOZ(di38MTV<ooHTc-7s<IcO2)G$-_FMpWq>aq6RX5u7K>S*bCa1Uy zo=BT}=-*bDgN!eG{;i%<mpQh2OFaeZwl#V{<|1RZj!eB%e{g>4;&W@%qKqRxw{A|B z`?}U`Y10rnX+4Hq3%_s8HO;Q619m;4<FBL5Ui4z?!^)bM)+ebCK4?svh{{IZn`o1Q zx*XdEaTg!<<KH&5sf%xIT2mL_+6*F#Z*4}9hpz{(Bu_>R+w3C0hi`3AL;uaa%_;I6 z<hIQ{W%aGiW9k*LHndHnY~;O?w#be6ql~fs8>ej}^3(9J2_{R-+x8)kLhRcjXRy~g zX*+{@FXXE&<D>N^pGOp%L9L*>_(;9A#hNJR%{L7Eh@3SO_yz6dUa0M7>Qc9DxlVcm zbK%)xaaGs4ZRgg>yr_$IRj5lm+chQ2HL)Fi)_dJ{jIGUyUT!y*<I6R%-DKM5+zFmX zmTO|WCFCMU!N`HkMecRmZ6y!DyxZY-GM8_NU%RX1ocX}0C$X1nV!J2Q7a$JpI2XOw zZO@+a3cteR>)gELn%JK6@`_~vqb6j0xhA#`Bu8EduApq?n%KS?_2-CBd)AWP>$Z2j zcH|xOA+(WeV*61%HrEdDRO)g~l<(r=Ty_NNw*5xxa!qW%o%-4I;4@^o*KL1E*_%-Y z{FJ&}6WhO5HjCyMBhQ(ZILN(j2iF&=%Y&0T`#j*(v?<mET-2wRBIh0rojKKOVh1<J zs#&4CdC4`g1LtMVR0J>8WA)nCVKq5UTj(xda<ALrH1%mC!0ZwIEMW)aKw_Q%bLkjP zS?_f_B1RIQ2N$8czLslZ$8^-!iG5)nE7!!1C8$@625#(htV1192Qtoh^k2upPDdO% zI{#C^ua5uuFZvqVCq%DzJm&0cfX`BII0MZ1>ou|C8`?xjfM*`Ln9H@V6KYrHHElCE zBU$wv9H%1k*$J@|8@VQS!a0P)jsbU}ja(Bup@u|%(GSe}(Q9HS<XiL_m7%j2Y$J@< z=^^z-*^TKOg5xwqzjWq#O_TKCysCRi&w-r}m-m3NPGL;Ds{^<V`AKMSC)&&B)H)BP zzF{SJH1&ojzzdZ1Ua9jk+MGp=civ5X;&t#}w3q8`=PT6fBA%UZ(SG*^FxDgSVLa-z zGuI`Xu7@#QBGG>TU9gL7l<#0y&-uE88D}pC#_Lj&_LGqJF6B99qi*0@<j4Pl8_?#? zAK;PHn~w)iAy*rY$6IC~r&$Niuk6Wt++7(fGU5fF$v8&*e|!@*W67&gYhBTkVk5oT z6|obW6zjqJsgEoGKB8>WH3Z{$u^F5Re2-iMbL#qnEcdrv-_ibKczo_ZGFf`<&zQ8S zHxrEGF^=xd{^@F9Q55Jd@1LK5ITtftj%BX(e)7*?9vc=u{)xI2e?lO4e@-HISqfgO z?9C_$My<of8-f`A`GqX8>K5I{>|c#lw_-lMp0eJz%f70dD+=b<4Qq|~FKbS>!Q|vK z_+5I@Wxm~(&^}n~8BbkXx-p(!D%3_d)D7&tX`8^0$bFL;6YTNW^lQLjmCYo?IT*i_ z@nugtI1O$36$R60{Z3YJY3glJJHgFpFZbcW>>V#xO7H;MNZf*l(WVjVHh3X*$#3v- z>K#AeJ?tRrQg7W|jmhUIy7y3BKU2|tB5kDK<vnlsY4fAzyE7L?dcV8NMVeFKb82IH zq6fP_B+EL`{W*{QfI8{HIGD2NL3xi*#(WPydnBU0#JNXu@`qVq<Xdc{4to@*J`VNL z1GNiX>%2#Ea^4Zpd()<Yj5&~c55%Vj{nyutJ?7FTUL@%B-^eww$4=^Rhk!X3eVy3j zZ|WftzaDNba*gQW){sKTS5MAG>$#`v5&7<2Pv(@m>ya!cp);qN_nwHa%yHrg=q{%g z_1lv@Vy6!WyPV23s3&{G#K(Hl6F%Wst&^V2i|vov>v>#t&128|zquF2mAFZ+doi}; z#y-85k0<*Wwfp~Lk0{&3>oE>;FZ!Uu;Ctj;@VD1vWpi;0_$PTCdaHLx+6+Oh_Krtg zt_!`BDBH}l!8yrtUFe;Uyk#}Gva(n70k|ghVky9g5q!|sYrS2r<=(qD>I}N>>-OG8 zK9L^!RdRmBzV{RItfb)g%KEya_g7^v8)~UfRI<F5=@W}KGyVkcCU3yMeOw&m^E`d- z&|bJNek4B10X`1ovC^A;3sINnZ}lysY{sFk`&Ob2{sxHYTbKG<_}G{EvbW%S-*(g^ zUjla_&zcOzSaRNx-NECi*NhEbLcJS&>AOnV_I?IFK$|j%U*DtD?;^i_(eo0+y6~kh zYsti{3jRWyy=TF{ls)<EKtI$a>}|#c;P^at^fGW3>ibZq{c=$c^#)vy`jHOcD&(E0 z^L|(p<-9w-ft!*urUmy@)@wn({<NPO9{N<;$QsgbHuc42!OXj^A^lKi;#)EFbU#-E zvX=I{t-4nPbM1%t%6V014VZI@@fje_%SaFQck|j?2h3X4`?UV~c<i?g&})!oZSP-C z+1^2}`y(GRzFZUg_oaRUzwbYTENggw%mFrD%_!iVw3qjD`|qb-0yW?N2K5h!egC`4 zHnNQKoqQhazyOanE#S|9ILf+a4oF1(DPlPwJ6YDi0fFTB7-Il>Lt-Vb3kFoDeq{i- zE%gQPb3kWugi+w(WVt69FqZZ^!+;knYyA)4nyEZ6-fw+iMjw~(@p)yF6}3Fj&GBU) zFy<`22@m4D$XR%-tZ#!@V|Md)Fl)?{b#)MH%<J9=+=}C$E(1pWNz4<Aj`@Jig3sUu z<XqFisAD;A#|z+%)Fp26e!ST4+YLTL8;RSXOXR-o!B5E&w?VJTSy7vVvBt@H<(_SD zL~{JIV5~=SE{W&h)XFCHGjKEN31Wb;28qqj6=3-He@4Fl&nJ|1ogaLT`u8`mf2eGN zWt``<k^7(_u4WDl1c#-42Gr7!WVDY0--o0jPx}ZiMw>zyb4Y3G+YsX+4XMj~hcu_2 zWHPunSzezG!8ydwwN=6NU$4bO=2D*%0{UjM#B&IH!E3n+%(-aXhM=D@j_F?jI_IMO zK7{pV?HxQbIudPUeHe;4%XwSEuc53x?f0SCX*0VC^a{?tD7YH!D^~({q%QqCv>W*~ z&N*~~vq!BBou=%i{0r>rMAm_!tP^{982F;Im+`NW{}g}TlXd*B%61;=eb|5N55^zH z^~ct_4bDk>8Gl$la`bWFAv{(-Q#x#sk5QvCchxWZ_~maNo>18vUDKH1=q0g_hB1a$ zR5qdagWHmW#D=-^3f=>AzFyJu;JrLH{s{0X^4tsHtK?pY&v48^au*W4Ji^Uu3UV|e z2lYVI_K3XXBIuV9HF&Jrw4ojqu^-{)EAOR_aQ(Y(B6tq%TO<K94(8et@D}Rwp6rNS z9A|7~F#MMJ9zyI#Tp_oHKO@n@;%CDaVAiePSB%8mME@fhbgp#<hnbP6QPI<*?ndq* z%NjoNkg}Jl6ZkrH`Ap8pyX4*IsgXaG?X?g1+<8oLSj22pJo2;I;LNnoGX~5Wu)(>& zWoaYtxsO60%3N+d0plFP@}9MPk6nC=Q4~CsEbnoT!dRkz3JrF1Iam+u<}w&-$*3c= zsoD&DTG=ZXWXu@$z9+9g#<=;uSpeqxW2PPk|IK4pqy(c@#Gk~-?HE^kFGP1WzkL~= zqZFDp$DxnK5A3}tX~9{@y-{CdgOv5N!DAberDn!9r%lvSVCKs%#qY-sSKaom1)fEl zQER~PRs89l8@ySWW1gXY<UaIEv@i1>{LE*A{uJMW`x!GX?r(iuR<igr4&%bcBt8aa zUQB_xVE7@&M(zymKpS~>*0?{($#DL0uAU`F<51Hw&N#$x9L5FP6f*vLWpC&t@Db|i zQM2QiBRe1=7;}(w$>(&&JykXvP>16%u8b+4r5PWB$F@%d#*d62B@mo~HfiAFc+{DU z)3Xk^0QI4NfDvo4m);rg)`|f9emrxbYx4MZv^U$KGZ*^0dp!D3j$JSo`byf!vs%Y* zpnhx#7{|cIw2KPfNBw0v@Hz4jXye(lrV?^8{)y^dGdcD(kKLHxm<h~<*E%`45_Rd# z2{p(CSA(6O(wh^ysBRl0t`kN$`xRjNY)T&nyY+2b6MWA$0`28>>%{1^Z-nzq%s`fX zhKbpgy^!!{Vg>4QZJJn}d@2}>+{k<bH-Wn=+g_N9JiiIL?lVlBN&V0*=x$AueTIp< zX)^%xo)n5U*ATZ!v6M~Px!^25=DMM4+N3HxHep!UbfAsY@T6|aw$2x@t3w?Jy()ex zAMo)VA0r?C*-TF4W6b~mx{JSzGnsSuiXdi_Id^k+BpCG}_R=Ghr;s}$=9AqTC4Nrc zsJcxM7krvFs<VGh#<$R4QJ0>Y{E>X{nlV!%{nn?TA8;-^IwkaU)VpIXnG)o5_%)>* z`3uf7r2$#4DN|VUCM{}tN^jM@tS!NVXp_<dW1bkFI`Sgv)>esYT>;G@bWN;EM1 z6Pqv7z>KZe20b*z`7hUkDL-g0@5N1xL2f)79FJV)EI2dAk!$GGT*_WJj6c=QMLwfD zwJPn`;`dWK(mp5RJ+&WsLv`>)veebof64Ox?Npa*iMf3K5<Z))IBr_f-!{{DUMu#~ zD*1GGF4Yl7nXmF%A0P8E)<Ln6*QwK<D4PWvz|IG$lj-!q&if0TfHvaW^kn49#lZ!9 zI{shA%-<M#L+Vl|(_2t~-v!*4`f1ef^cmFU-edZF>WgsPbXSK`57T$hrp{n6av<YN zey9IUzMcjAnA{sRGW``fXHz_{oc(JgzcV7L?#bsIXE2^d@;f69?bj6rJO3qLGnhv! z`I<rBblsale~heq^85n$W14&hUna}CH{%A!98wDWhPuRU#wY6GP`@(^DeIW>U0E4N z#+=!Jya8j*{F5wW&g`XZ&*cSAaP}B;<}~uuPGHuR$y6Ks5A7q=1V5vV?6=RvHAc?0 z@x3v#0?0FP?5u*cm(Taka&c()1zg{!Bc?dk8yN|DAD`}e^Lb_Hh$(FJbHcM0lAFJS zzRRZ{P&Su;K)>$O?@%wh-<a9Rw~W&vGI%dpzV9>pCHXDtefCeXe3xfVhTr-e)Ry=u z-{qOp)~EL-%XfL^EK=6L`7np|X5@Rsa}!gS`_;MG$dbFcfjl-u2XHm&R}8o=^;qzI zZhL2sJkE8w+lAxij-oDkoI8>Be`79l*OAAdUgjRAjXd9R?nz}Y)DZAp>QcjVA5ot< z6pYwOeB^$0UP$W0mVo0?m;2Ru%&$!~0?c*8NI%XiK$~I}z-}&bzdDa|F->v3m=~-z zM($VV_2u}Z8-hPkm-x(&K$iH-k52C08q8ei{rvpw)W;=*9^~v1pZVpK?P1j2{3g^T zKJ#(B%qubSJAat67yc%A4)qtP|M@O=Sqp=A@K}k@{C%`JpBa3aEb*C-<1wZ=ig?U_ zOI_kKAN4JD5)b-<D9#4)SrCi*$o^nA7m3dTH<t$|z=)lUDe+l=H9}av`?3JN1h&mk zvkMSM(Ir+3*b8Rt1@Kqe^vhw)!tmrwJHe@GFZ&`35hEE#zNfITypLPbM%Idj9hAMY zIR8S_ikwSgxNtOi25N1gJFk2nVIlGa8!yfRFk@v@KjQSP(C@l&s(`t!dUaBO*=zbe zg+-xgUmIgDN}{aaQ&^OWdbpy{i*TIJPr#+fy{3Shl4U<|5#l92|AD$%gql|W>w}R? z;ZDf&qUFvW^|ELkIpQ`jav(Nxom_+%fjznJUCedfyu_Nb*!9BrIA9ms!YRQyX+OFI zxR|m%iWth@tdentpneuNBFks>7cW&d>tlmAQy)4Od{EiSXYUu^r9KidSp10kY|L>< zRO&r(-X-X589)6wa9Y~rKo2bmR5n#mZ%Yt&nU^wa$%H-weH8VyeZUixy`oFNSVzQO zdT_}~a!8D^<eRcSdv+<}0vj^pVCC7fOPM3P@D;cukCprPrA=tBdMjmb9Ok=pFm;1# z%F>avABvnV<$3klvrE_0=Ex@Kr+BP9LvktVUi`d_TrGV}mS@i{eMz3**_dVFm90E` zcA1OYF!;C(xe@>6*|W=9`xxUw*JsZz+f7}b+q3MXvT0Ta%-S&L8-bY@>Mv+7&l_JJ zg7&9}fy0sG;<)85UrD2bv#IVWm-VspXFzS(xcIE-2_DIDX8!^sPvXCPzGL|+9$UKv zo<oiKi~mJ$gVXt#HA%gNPe*;oI1~PW{VZk8`-%nRqC=rG4*Geg6$h!CY0&@SvGP39 z6%VPWLF`vxy^}FTU+LmdXCv74b+Yo{{Isvz6wLb6=aH_&oN=uAHvx3yM&=S5zO4-A zm<uC;$IvEySny=>kP6_HK79lETTJLjm2L2R@EK(<4r*iNzhtSUmCtA&;fXP;aDF*& zXZX7c=MWAK04G<r^4!r?>1ZEr4!AIN`L4mLlGHE024mg9u~wc(x(f3Yt}qqci`=UN zcp&XlBF?KYme{DiSlLT}9$dAL`ucp}Bjha~!SvsZLXEBF`f1PLoU0jU{m#?sR2)aX zBe>edye4w8x)}BG^}sIXtvZ1lar~YGz>K+3y|3!#6nbbiW3JCLT<vP+N@(beIdxob zWG)?YLTAj4JV$gjVki2_THxo(UR0cO^*ic4(;KtK&82)*a0Keb*MS*xea`2atg4$1 zsD(AGAN{=58jOqa^*Kyyx{~E{SZmNfa$ebAS~HWn+_$V*pzICF3wAzVM-11vn4jqf zM&HVqb5QSVuF^iBAov6IpjF^+<ZoGwSsRBowjDSzxfaG;TbP`7AK2AN1jKJ`Gu3TQ z__MYxZF=E6YcV%D@9utJ#@wV!3BEv^q!@ecJ=#1$kF0%5y)g2&&Ld||2980N?|QFG zL;EWRoS8iK7r45zU4nD2LrqAmT9*O0B+Ik4*L5e$v$fZ;9`xDT>xNJtI0^b_WwRp) zyvV1!-n=ydI%`;;t-bCvZDLM@?&`UBT<|m1y?kHrXTdoaE6>(m&$ZM}js|9(TY0wj zdROP8(ZA~h>4WUetamX_hB&QnOkJL>y}lK>N<8o=vOHURJ^YZlU!4!$L@ss$ypy~; z68LZ0%d@rD-=h8rF<%c~<yd*P_6EdPa#s~O-H<@pD+V7oARnT?*aI#|dwEv&2E<GB z@yO!_`l-*>-atRSi12NLi?iA@&i2M2=*xZMpijhye(j;3B+Ik4H@KQ<i}P%FL46i- zz2UvGdG`^o-(ry)!^e#YX;Th8xY5;#JhyOTF4_dW0v9FAbFeqo^l>L2yK9!(tnukw z2aM{Uf9so^52A0%LtUP&y$OCueB_>FQypa+Vk@|tPwzv0K7zk#x=)`+md`S8a(R?% z)20KouZcR^bcL+?ZSuDB&|P2WM9pr7AL2ufN8pUgdTrXAgZ3k0LoeggE7Lw)ap>$L zeTMet4z%f(20C*}-Q~2&Zs-d+W-#h-Gv<u*dR<e4_fb!Q-*09gS@|67=9{#UYuV=e z%BClL+{~KPYuOgoq$lrhZ*eu*8FSx)e9OFo@Uw-zqu01Cg{gPj0lkK@Udy&%ErY$S zR|NW>WLY!ic?2>}bNstyEOogiZkeL&$urcqtfDU0xGfuLUmtzF<+M+~M7`&5=pU$0 zM4q>@HoPenz*%S`uLZW|rp+;|OIxe>^xEY2hoRF?eXoBj{j|%FldaQeBhS{}I+x>I zi3Y};WiG1kryc|G-1@+$!*7X0nZ3qri}+jL7DL&SzXPz1b)w^J%R!qG7;jrOvRo6l z)unwZT=TbeA<O4mw)LQm-2ZNy?9*}05Z@}wdFh+pn{7Kvn>;cOY7{oqUn<*bnCtd% zzxC}=mCcI;(And9ZQY)WdT?UsHF>ODi?=r*ulfS+=hKIh(_y~b;j6?%?YAj=%@CXI zH+{OR&od+NnUWB{^&O}W@i{?7=$U+aPGvI!WACU=mTUTsdbEj%Jnvxd>pj4Z!PL`W zj2-iQ_DiW(`~jW4qtA}s;cD;oIp}ZIhC1dcaXt$lccS;iH+dHKPUqXfgWy^|y&*Z> zC+O^J+K;B5brAHeKKnh&=0QQ|_k22PTFzAo^|H&=lAL!}JlgO24#qM6`LipCJPLKb ztD{d3rhQ|~d)ES=zFgTJfVS&`PrpVzEatkKc~Sp&yS$Xf*t@gSzS9nHUfL%`ymvPz z%d@q2w^P>VYwqSctk2fo?fNTfCD@>L;lGWV7!1F`=HG|lr)0S|+x>=Y%NesLtg=2^ zdruT{nf}mIkb5Jid(tagxhC&HU&)yA`fCq-l5=&g4{ktvc_#KA=kt{V;88w(BJJB$ zht4(1Q+v!=#;Mc`I%7rs4v#e}jKQ?T#*=4j@5PVU|6LNC%BOQpu<`NlUanWP=Xzzg zppW+U^w|&KI6c2XU!bhd(B8{Dn$1DbkNNbov~T4>fA7<Ay!h5;J3b$SbAWZ6eMxD* zt}ApGx9*$3jGKOMW?w7XtIis;T~oqlicg=d>_rX-eYa0XpGX`Q#DRXFEYHy1=W@La zWAA5;>9e)>WBnCBWBvg>=WqM{`ISx4{m|?A^rqC)jDXJG*Jo?*XHLz>M$mcPq3&`T z?lbf&dMx$Z9OuXe=s$n!2SQOVm%*3=tT%nO_5s$L7Z3g)C`+4?h{*xw)XL`r5488` ze{#$c_n^=8>CCBZigo1x)*#7?j^ljGjP>NeTc7@g<77b1|CQ*s{uh0-J?B6lpt^mA z-~Tm%9MBoebD6KGm%lJi$xANe>#qak9mwZj=aoJAJLZ4ESMjI)68v4R&^~tc0~gIf z){mE^GMMXwU6BQxm-eS`f@>(-!>IX#^_4yOKIK8?!p<!LW`B9j5yOLw19is1PM!h% zCC8M#%7Y)srLis^ia?gV%0tmPzPwj{D7CV_rapxD%3Qugf?k>|dzFVOkqaXxhv1Xg z$g@)px!etD17=-OcXc&53G}6IoG0Kl<T+`<7)!^&To17y&GiXjSM&0j#zSw^#-6Ha z%whaL?CpS9;JV6Q%&1_TTl9?Z=P=g<TLrl|JW_SD0PES|@wDk!3%rOd&wD$(f?Ts3 z7(FB7JV2}tA0datHRSL$WpCJ2@QdGk1m}jm>PL_>u<nZ<VSc?ZJB>L~kv7>8rz6dk z?G)taNL%v2DByuScEeckaOy>{4jq}R?3K<6UQC{bUO#e<Hc}5qT;9JO0ApP7Uv=i) z9^Z%k_lT<N`&>t3kjG%YN7Im{9*$-vM?svA1}SSj9Ca}tu@HJo+DJVd?Lc0PJRBWD zmU=ikn%txj7{^FVRA-#cy+_awQJ4GDqbJGVhk+kDd(^{G#@Xh}X3Vj$)TJJdAzl*m zj<>)r?@|xPn0Kv*V<Xf?>*3gRved(|<s3)q;n-U8wY^}(PU0r@aO@~~DB^wWHd*T7 z*uUiG$lI|`%9{7%5qzA{$7PkZ9*$S0UZfZPE>wGE`z$?pFj?y1IBV4wsScjcW2GLB zFC|w;Y>xAKq4jY5FCN<o^?dvXIawxSPDCPC?F>%oW7M(aLS7r5C{Dgt65NnBA=7{v zL#>k&{Z;qs1w)@od#RHXv&oNFfwz-K4*;K0w(?&5iA&Un2ZCKMqfE_-*VJ3Wx07LL zFMgg3pf0|hOihl1`JQBr>Hhi2L9~~@>2{Jn=wABCt<+`D{3PRJ&Y&Jny1q~ywIXwG zDChc2d)Z4r`I9`kwK1m>DeGSPspPbeg<3mRh`PLHJcYT*I1j6W>yl+J{ZwOR8zCIH zFIo1|Pr3ZI%K$z^UG~yXUG*{7H{DA=otC=nrJu&yE$5QG^wZ3pEiYWnr{n*{=JZnh zbaIS7I*pt`w@t@`$0+Om`RN5d-sxlKkL;zNe#>KJFa5NO)mh}>4A%|aOFt8rHuCor z&an4A*-Jk&gJUXh^zmgMzvQv9mwp!U68|OdXAx_#mpM0>anRRgXS2|zH)4Ml{V(&9 z{fD#2f!Iey?#|-p|2pGf_pXCJmdCbv1V+8W#>~$LKEPvT&;0B$>iJrLF$Wn_^#{~b z4}kuSEPLtaJlcds-JOf$(-V{PAV24FDC=JOIh;>?D~R>=TxDfXYUv#MR`hL%?K%9& zc{?WocT+Yike_oCX(M~-=NMbN@go>>lVfGy;2ivrV>28CpQ0{%>E|wxWe@+{6SC|l zoO3-We~02c*DhV>&qt?C|7rLa^(y1bUix`n%j}fW;L56-?c#42Wn1AH{&jJdJ@fNZ zs4vZle_hN~->ACDTLJ&Nn9H8|`Lop9mBPO+=Bhte-Dbu(7hKHc^~(j;jMpB%Utr92 zFa1JFjx)IxbjDow(k~R{I2Q4|fclnL$zJ*e{Ky=)V6D2~<|41hFZ7_k2!390F;{&) zkFACIUSR#`>*x#U0U2}XTIlzbsXr$7L%uGeZeXLI0k{~&*{6X{pRMc*U34+eg!o-_ zYqjj9Uqs!@vHRD9n~-HM{UYWm=M88F9!i$I^owI?(;*Ld9d+4DzsNeV^AMYh7gg82 z^o!SNKMHfY=;~bd(l5D~clj4wfHv_ifUA(BR07xHI4PQfvEIQSE7zb)^ufy7erYLn zW%wa;k$%5)m^=#oe(4Tv<QjD8tFwXsD0{W9FbEurEZ3mR326UkNidF=F^il9m!~e* zpvznz?5;v!t`GXTh|3+-#%qV;E)S!<_;z^##}VHyFQ;A`^>!KglksKlf1~DvW$u4R zQ}(*Um%sD-Y%2R~YLX{ygw0@|%?zK-JaSXy<?oX|8^(m^dPsfaFJrDm|7~+66<Peb zl0n%k`8Sy7)$67_ryf3&xmN3S^9s+a??GQ#LYu$#;@JIUxo%!L!ZGb=@LlS1-MsRM z935-L)iAUfT@D<H+y{PLMJ{n(UF)u*Cd7xXsI{xbmG$qRUM)kL>>r@Fpp9HNuePI2 zNA%6r6V&Cpd6nz4z8`({6OWa@e|n9%FfC9c*NV|z?h~&0;vmlp6CdRL_iLlbGRJEZ zl#N9UuC4az$eH+G9JP1tG<BK#HP<^w(X-dy(MINe?F((TW4*lo2X$HJug6z5*OP;@ zkma7?dM?^;eF<hy>HF{3Yq?`5L*GgpnfrBL9IoG|jm-T<LfXhZ!;Or}<{fJ1Mh@~H z<G_qFbyuIQheK~k8`=N4(LvcOh?v}Pbu#Y-7`aCr%%wTtMap*iYw$|ihs3;Z{6(9S zW5LJC^N_n656FcsfuEBvMK<OpekWrlMy_v0A%{UcZlZ1^N9pH+-CQ<d5xB{kp<Y&P zynzFtH=+IZ)L_@+T~J3i@jDqu_2IOydltIuwGZ&~Cf6meT}$vDwK1w6;<0JAK)*rm zgx}wEYx_p5KQ~>jMZaZeGyOXld6n~q+6+!aPBatDTu?`!!^Vq%-``^1&3LRaw`!|y z`XmFpHLAsWa4_w|W&)4lm@}h-Q6Dl+9n``t=EADJf#WRM4*e)O3+8g`43AB98~m?N ze?~4<!kF903C2`^Zo3>A<m)!);)y@EQ_v<K@_ZXLCqBsYLT?u#CxP#`*>}_%Q13Gg z`k!QZUg+)K%0^!2-k#{wXHZXu@oukEwj-;8*$ZAEYT@=x+Qhg5#{A)fO^AB=CmcB( z*2#YmBhllv2dAgKychXTHu8u#V2msCEf4^%qwJ;Y0Pdn}>*8Gh^d$cSzy6u;)0Zim zA6=nyeK4iMgD=r$6Z-6*ue1^Uj*IQ8H{ev%R~`ei9*i=5ATw4r)?(O<r@dU8?o8wO zIZ(HEHj;bB1Mi?spVeU0y3Aeflkfbk>_vm`ci4l}-_a&zY5WZd#>#6B+q)U4|NIAB zl*h{b@LkwRthOPxcN_Zj7PKEQ6?z}q$bItN!PH|TZg*$;^aa#EHio{9EcdZ@_mW4V zKJU612E*sOH&pk=`~^nr;DcUM?tWG_6EOZg)TsC-`{DQCt8jMY<(|vCd=Kd!^KR20 z1ed2xIoRH-rtD2NVAQT0yY>Ot_1*BbU>EaY{lRn9#%`?urq6o6ckeKdz3V}D^(pVa z++%%uHIa*Zt{z0ckMqd6(xN8sCm^eyOxc?d1A0N9j(Zx|dw-UJj@ZeuYLE2@Y?I;N z`$NcbKY4#N?I%qD(`Vg>zrTbw`4G$d`)MQl_V<rce}{kX-%~b=YJ;DU&o;q(4<X5k zcZ1=#_;7d>IHgZ#{g~*8?Y|{ew=+9~5ihaNjavH`=M$e*??io7Dd_asR>gS#PNL0( z^I+sa>{Z`FUR4PCIdU%K`rj+$Oo@znfZi7S{uu9p>$M!2z`a%1`_Bgh$r&);2Xn}B z9ejX(!?9i~^zVb6%Gxgv4p5)65V|{;^w)#i)Ta&rV=cq6W;tr<A${<&wFPISjr7sO z9JJ|z3&%s`QqHA1&L<pwK6Lc9j3a&Yumkmxcfiaqb;ion!J6?9KEYmJ4?bMMV;f)| z5BE`*K6-eB+;l&f^{IXIko9RQiTxMa$m_&MhWvdNIDq`N8@LGh<9l#Dvb;We)KuAQ zm<{gd(}z+|B*!i#OWi&~&&wQlo&X>6>4>SsVOAsP4}JOzWjpnmF^|JhmwtcDwad1s z3udnM_0(e*^V(;i7viz9PChQdV@osxJO9&RjK|LZ%n!gl)kgc}@c<rMa5{9%O?;Dn zdAx|@w22PhOO}3le3-l#>+9n?Wa*d32&l|=`b%S;c)#^0oQrMs1bTASwJ)BeqfMv8 z(1Uz>IqH>=hbOEP?TaU@6WasVfhQwrFa7ca{g3ln*;jwEnq2R-F;ATj^4j5PT-Eiv zkWcf{W_2~_u0As~2P3{RPSYgdj>_6cPmx#A^C6E<-MOSMp1L(NxI1{0+IRu$z{hDX zHTm=``NAbI;x6OJwcsgoEPM;S^9(Tqd*$HovoPf0sIO-UX(OMBe#SM^r2hpjpt^pp z?^$v3!}QS6Cm2URrzd}FN5(%^7&`nDmYRRYx;1aMf@jiRo>l&AfwET*d3c6g$~f_G z+_Qt^s>8u<9hjCD%(<9C=;`P1PsW$;wmiq0E-c?|dEQ9b8-o6O&Uo5)1Hgl6qdZ4h z_hX;CdJDA>HpsE~Ag_g=@1uQc<mmZj>asuo{08}^=x==bC-R_%_<R*=SI4OWjzj+E zD44yY`}Qxgt8No)fnI?u-xGX+`oOVX#x7u24>$UPT|GS621XoZzV{KQ7p}*<qXu7G zRNc%(PG7jb5Pr#6ss57rHN((bFPT#-HTkkU&nq?gvH{0$ikf^0KV&X)kMyz!Ic0wE zWZFngzGP1Av=3nVW_qEYUY??j)a1(x%3k7!;K$UZCSRg&WiG#l;u+r|$p$%m6<*nl zoC1a)Vk0&ADkb^+J8)sz$UfMslGK}Fey{3Nm;J6+&6K_9U%<U+BQ^PIAZ;G)0nZ^z zO}<)8`-<_vtO2dbS4VhkLFD|^UD`-ZzH)Q9_sW>pVQC{Z`8pO^YVvhEWh0-bd)=G7 z3i)|Gnj8i3e7(fS$jyH-f9>)sf7|5sKTb!TynaBgjedFkjV$%~2Dy@06{rbL;M0>i z{X29VFXK-u1jY~8D-#5UucCjR3dUH%UQsZ51FV0i_|1B<{GH-A^i%&%=$m`0>)$DU z<6;sJ4K~P=j8nHi7&!oY@$vs}U9Pi#1iM_9M1Q=EMSJ<Y-&^``cOV9DQ&E45UU{2= z<FtTpZ}B5z24n@7qD?JaFW$NuPK7n<Eo;D3NDK~E8*B1{`;g;S1CJxivrpb4f8ukh zTVV8+j9)Pdcq2J_LGUr!EJ2OEJ)>-&p_bp`M~)qO6a0bP0QT=<(nj`&-=Vf(W20g{ zewT$dK@GvV$+4z`F;5xiMOQHV6CaA9_THgJ<=9k+=ey42D22f%XfNN*d3T#EJ^PMz zV#_Wy=DneQ1^>Pe!(+?e0mpUrsEhYWsGot4?{iX@_3(Xuay{6-M|{P%;}5}Hqr9pS z!QFW5hWcPv+wwi8_Y<kdnFL<$xGH!Z$Jx3Pe3-g?kLmp>WiK!4=RNC6UxU1VLYv%( zJwmHK$oH5&a4ue!5#XfM<$FvY($K!m25=9u>|cF=PZC3A#6?*4uRiQ2%l_4eBjgY{ zz;}H*{FAxw8-VAldemkA>SI{y9WnOD)XMsv*T;<He5k9BrOC2?^|2zkzyfe{W!<~` z*p~WW#N*>|W!=B}IF_8ZDRk70_$>QZAAkMkPjQs>Jui7K{C{)&)X>K+4l>_Q$cNa- zd_T=lHY*VCPn&)EPU>l|LcdI1=KJXec_sS$6W1S|?`OnD#tc^u>qtUny&wLZOxd*B z13eE}_Uk^QH^ly`*dsT>vRC=J5xH<guv=$jzMn5pS7sb^zF$&Mm;Jggu5RDm0q0lU zE06KMR8iLbx-YC@TM>Et!W!1kYklGRV5%I2?&?JL>%L6pIOBGKSMgl3U-!kW2`O;g z7uSQbU-#uaZB9o9<9N)=$bQ|I_Z%l=U;J&SsMKY@?ki#e8?O}Bhp(BGbzknQn@g@z z&=DhvkL=@pt;%B?X9l}9LH6aox;5b({QZi45PQ|f(|$@m=*!5mFZXpVZIUJjvj=s* z?kjuH#O($BK5b-Q?(0)>TJ-uimuu0#A&zpcnE3s-#AMm8`<7DK8;Cmj#$4!r-M3=Y zhl<X;>;Blc#;P0ndyC(?(?<5kzV%bKhmwG&kY^%(-)56%A>QAZ3*E2#wuAay)c&`# z%0~9<zWq(T&sXqspAJ7H{!*Xc!%>(0!|yl;bhCRL*v&=!`JRFHk(Yvtl4ZZ{JA2%2 z`T=I&>3-e!7HVT3U5DO>_Of61eK5Iq7BK!_d{BJ>IWyw_eVelG*L`O%m_+dX`@gCi z*{}P~UNBd`;r=xm?Pb622iF99vnx0|?Pb62M_$_8KMt--UH0pKG$A*{`G4Ttl2h5Q z`!P`2i;X`1vD~MxqkZo+(78V7e%%jT|K!-Anelh0xK676)5Uhp0qCrA-Ix2xdLTO= zWbf`LW2O6bKd19ta$Wm5kKA$}cqh*#uS0)gT#4b-Yhc7he2{z8pSNj09Ap1{@6!=4 zvANLEm|u*Q7Z>&ND+l!*(0-Ls*8PNEmC56yKyT^OJCNl&>A!|3>wdzo(d0$&;nzZ+ zjyd4Grt>)Hn1lEr_rt%AD0>A^=f7MGgXe?qQ<uN7_Uj87*Aa}MY{DD`$0FnPyEO@E zgJ<Me<MNLEI=%0ab2Z5Uu1<UG*I84KyuLrUI~n_R*7PH<-U^<lY=?;r>R!hA@(E0z zW#7!2)3gs526pwS`ZL;(Z)2==^&q-+^)T-_I6041Jsr8-TIeNwdU=j>{T=kyKD`rp zWhUrjoK1c3Wb(hc!Sq@78LUOD;lGE!b89W?Ojvc~Ugi}ZF|l0hWWUbZH>#VG)A4tX zBa*TIV7(aRm$ShceLCyMe8>sCqUy5$V7(f&xw#qK*{AoQ-l#ov=QH*htT&4`&GUe_ zl2zZM>?JAy{VH|r*IDl$Wpf+$Ay7jy7wp&B5SgfBzs`mjOhzBs5F=@mBRO~pb?n#K z5Ua_z&w~G=4f@E2I8F{#4a{>%f7uWZsW-@OY{(Ggqbb17hknRc$egN6A6a?cjl?|v zX>b*vUYo~mKLi~;2^;An8#0(Sxp3Z)%rA8ptB;|eujH}lBO7u9dGB2?uH_O3^pOpD zMp>S%ZbPy@<^IHmWPO^zMtGkI=M;OqPPC!Il2@hzr{S^fVu4GO58VVeqYd`!Y^b)> zmv09T^XX&Bo0~&lOB<>4P`D<^xz?8fpYrJ!mAy!)hfptl`Ul$QxNB@^uJdwlY(sPH zGNsOenQPgv)9-P~_{Um;OY&H(lQwh(j+vz|*!hqBIvbk)+g9*1^gy-Iz6d>n_Q~%+ zU+mLYQD6QVx?2aNUqZWeU_fZ_W7<f+gnp%LyP-D1g#WFF;aqIeH_+45M*1a8HrhPA z1}^W@t5KhXnh(P|k^MRwhIL}^HU&?lz3MZ_crKI;gKGm~B6~zO41JS5A{*vAZG^-A zp)7kuHf((Al`es^P{(T`8#b4+*E1uy9Cf?~w_#b&w$)~EE1%v$+19uSoqZ>JK{o7o z>Jv+Yxkgc6O?|>x=&pvbM`Xh?wl<@T?_!HRA{*A#Nq*EoxQsj&dqg%|K4pVFA{(v@ z8T&#uTmv5uCF5BQHrzC2c~*lB=X_9h`IVT2b3Vj-3+A;+_RVa#r+TcH=O@-scWsiG zgb%|p^Tq}9+9c0vu;IDp+d$N3_=5C7ViG=xoC3KBU)QHM;W&7nv<=^vEPWb&2zlE? z@O;{Tega;m>{aXy<~k<NZnfdLj(JnQfVmFHbC_*-w+@7FW^9De94D|GI1<NSiJpy+ znmV4<U?XHA|BMLcb<@j;`j0S&dPq5T4Ua820nGb1J9s1bFm1xd0rOgK;x+_-qAu%m zgrCaZ@NmXPbk}#WiI{_9rV0Qvzh1q6!8Lq(eI8rC1aw|stlIZi-5e<k-CbW)Ur4>q zOX$45(Ebp|!QO(6=+=C-e@ML%){01O%@jRSSn5sCUy+h2>o}3pDx2D$p%?e*Woh5& zIP?}iy*>4&h(jc<KOBes;^A*V*+^V}sBfe_{^pyF<myxXxkSDGO6YF=QT?N{k7R6Q zxBjF@{YU0nYVjEs8=32m4Oj?nO?z24BKK4_z0hBg$NHG{MtwhZ>6gf^cTUa$yIf1Z zM82ms_F+iyXWC0&L}uPi?pJv3Ud-Qm6t@<2#Pu!;ucx|J$R47s^UHDVj>7eay1Sk( z+X?+o+Q=FbrMI#dVLh1rF3;byQRdPn0N3;=FK8q695tS@{Ebl?H3@Bks)L*R^mf!& zUxPl}r;k(iVo!ta>Ppt7s3&P7>r&L~WLcM@x^+xA8s{s|*0s^xbwSpmXob~Y*QjW9 zc&x-ZT4U<}4gs?tbzO?qk2X0fLZ3pGI7geU?1ktCX8q{86m17}ZxwXbkH$0F4eBLv z{}AmB$C33a8gu6bZNUCT4Au4iAv)t`2jQMGI(t^W2Wq3co-KrRFFJcx*QMy}S<?)) z7o9z;>r!;~te5Kq^jSQwtV_|^vo;Iz9-Xn3&&J#6u4lWn1%IWz#4tt#`X(`q;qs^) z=*C10V=%T}hudK1o78Fy=iBS<;I6cn7{=(O>?JP<p5W7`Q%{EVImRaH5~~<Hsdual zKIhY~Q18$L`dej<VT>=-XMD!~!hgMh7{-iGn>*-{n64LOZI9`CA#f46rrKx>WAb`u zFNT5Mle)w(<^Yb9?LC<FpfQZOh&D6D-sO5m1!MmRM_rlMFLMAj|A$-CYEJ=kO|uJ@ zgWGca!~MWr$k|a3f1FqL65zalJo(MBLeS=HY-3~9CLh}ib}^UhLM-Qh)Lr1IKAZK* zrXSYuSX-&%wY81KbIIRSwXqmy6Jibc8|~NPeknHl*T}qL^Lk32PaBzI>;oKA<{0}J z`4-mC*pJCF$JktB@xfi}v6fR^=NPA%kJ*n_<`~EMCg+XAIOuufhE#ivZQK+bU(Oqs z>ws4nJs#J^S<V}m>z*Bq>q6WOzt0u-xR391964`1cRiYO37kiDvk-k0uOxX0YAGJ; z-&V)~=C#SQIl%OvJcITH!a<+M@o}$e<LxCUF9de|m~S2UF6~$40zaZnIUE~56gh8I za2eX*@BiBPO{v#74dyk-#3=$EN<B348-FzIqfQ4qe<lwHJAXn6@1woMF#cgOzEf%A z|4Sa-$Jhj{JtOB$kbq+<2l}|4k2mw!GW}tHnk;@MxJa8^X~FKAD}E;UK$~b-hZB0V z5kKV_qqu&V^C7^gX(N8h=g;K27PAYOwPdH_{}Z~NlJh1ULK|iFtX1YUS2<C1wK07Y z8=EK{?ZwYTS*Smn40hv-pNU*8o!<d&NE`7p5wCY%Z>+<KT>Qn)L@xeAAA(oW9_yS< zbb_qsW$mdCiDj<%5j}BoA9qyt@Hd@p;^97a^AevEub_RkabTB6@j3BH>dQxfuad>* z#J4$43cSWl{8QPA&q+d(ck~1&qy3<R;3BjaACffl@faWP^zl7%t+lX!tZYwz0`pv6 z$gIW&@LcB9V{l2eF|(_I8~T{n5i4^H7{GCUj0Vpk%Nzq-93tX68{pPDnPULgI&--> z_;1?F90P80{4@8#Zml~I0nfjVM_qhKn%l>9d_2g<OO@@yAFy9deP~y(n=d}6V3S2s z-5ZYjOqRmOg?X&ZE18>nTC82knoyT{C1YP(?;bc<btCgi)|dQGMDSeN%e;~;ArBb? zW(}D9N5KzNS09oy=H%2qy^@dJJ)z7id2iKC-<;sTl<khKU|ypw{^q+)exJHB<LM<s z%u_I)b^_*=A_>ROlMS4g+$$E?#bHu+Ft5v6hbiiF%myu?Gv;0&-20_iNWC+zeJPf6 zoHAFyN0m(htS$04)nt9RKLh-nHe+#blfvCUJW6M5%4oEy@e3SV*@TM@&Pn?Or@;AW zGcz}sHDGhZ05_sd6x2-0{ycVBB`|y6i}C=>T$o#dVD`QZ8VqLd+j<|sjG+mHZz<h+ zcpf#GlIx*YxGvt)b@w()YJpvS?#FdJ73<SR#Pu{)0s650E7;YiTsKqAqOR<EL9W-S zc&*ns%V(4&R&k<2|4EkXX6jHpc2j;ZYr_=$1KgClavySY_>h|QX49iSQ*)j7f){`v zstx%U?PC=-HjNv<_<nG5)$P;F;I!m@!mcmYwE++0u^G_gX~xm!f8@OjxKGvg|3BB- z8`~wRBuUzpB)4{MZ4#R#$t~SfDx5A7+DVcmDkVumlB7*4-K4uHp^^$oCApJ?Ty{c2 z^?S`Z#$0P2&;Oj~obUIX^ZkCGzvrCiyw3X>Ys@jn9P_e1`}0}r`+MMtj^k!0!qY^* ziM{@`1!8Z{MW-zmy*qQ^w5@@S^fzuklJ`he5_@|_s;2S$a0=W+?D_j+RP9{hKiD6u z=^ACvPSvh=dVD(LUhP4#;eF9jHHp()a5X$h^zYcqs_Fe;1;)DC`=awZnyA``;^&N= z@He7A{tUd*v6))|-Y(o=5d4eq9LBo3<TK)L<x%yLPLI3Kh1)rfp1cN@vx@MYfj&n3 z+{ArB^*2PH$X;LlUE$mKEV252$8kgIxrXeU!c_uYauwfv88%m^eria~#3hKK#uTTU zFP6b_PKbxU11}Umj@Ji#K<s~Ht*EK>KfVB#^(5N#2mBXj6RkZ9?k)WJd{}BGj>uch z@#535)QRZQu4%x!U300}j93Y8c5FVS#%k^mzT|y=_pW)i`KhIO&b$IXO>DZ*Zmk;~ zM=z{{W!;XBXH07i6W#GM!gk%R^`cyR@+SCG(d`_prEBbm)MqWN+ZMe|WWRT7=j_q+ z_w?#=tzC;wZ|FE~xEVfQ^jei*SyxT3pWtp{GlZB=m$fT)JXY*)u7&=&@K(m_^zX!e z(9iJCDd*_?weu^dxabenhov5(e&4_~oE}~J8+@tQ+_C`HHS^0=@Uu=g^E2U>gb%9> z&zEcMyvWfpD#<*``AKw}w;YMbd|AarXB;lqPQ4LsE;fTNfi>rjp9}PP0n2`2ii|K( z?P{rByH&svb7cM0E(mmqIlAH@blHQPO&!@&gzKgDb##xje(Ky2=(1Le{X2m!YpLj3 z1NPdwMN^x)x|i7)>Q)W(I>JuZb--PFQ(*H@z>@?1EMQr4TnzQfrFuQxAFa=NeF8o3 zQ}6p!ub&yP?)&!I`d0;d;HUoGq7Ql$n^yxHS=(Ja^*08(t`$eIADvlD^lM&%>!vnm z%HHa(Weaul$mS=vVrr9nYM{3c^zH!%dCPr1&}Rp%bJ_X-A<zqjt=^zisy7Jgt%0s% zHa`uX3T)mC`162&4ET?f8y+2Swy<rtVK8<LFA8jeJ~q5R&~-lAcpC0Z^|NH&xqP0b z>+_9Ao9HabVcdYd=`6{=Db)e)5L_$cZjO5dUD`FT%!Ka^Y=ZG^B(-fSQxA=FOn-bD zmh*{=p^>a_!dgEz=0>v4h%WgTKL@2P>*ws#({|6kAmCdA4(93Ex}Mm4o*k?w{QWYi ztFwdn8wX?EILJd|t$*vMaS(IkpsmIqi_ag)XX7oxPqVHzmU=dgI4?ChD%G2u;8^tP z!n?_TlXC)_c7e@6(QU4p1ohTrs^~VhCUXNDS(Dwm*Cd$Zc~NSUS2<wKt@V@FBG6w; zxvAEtjiIURWp2Eho+~!?TF%5Sx6bB<K-c&$X3uJ>dzr11rn(l{@ooBHaP11mt_GTJ z65ZM~3u0&{d2@Yi)=X?{&YQKBYi-V(T_5N&XI;*lJuJG7v)Pn@Ulq1}X*NI5H3sK@ zm(!h}b52Wb&e1$rpZ5De_6*?on}D^Rt=?Q}z}YmfpV~C<8nBL|wLdqoIkzCSIX75u z&(+$q_AN|m)1qR)jU31J?;|aO^`yo9fz5Q`2l`_3zVe+WI<JjzC&tnKZiGI%F*@%S z(d`(W7sPhnTG7XsN8cvgw5W+%)=Tx4I(AMUD!TRGQv5joEngPh`fs^1xOTI!z4rX_ zseb+`fqs*)&B^%>1pHFK^8%JLl^d7yb$zh$pRfCZZL8I>seLP%M`qJt^yY!C^>5p4 zb+6M+Sw1&t^;}@{b-+J~jjh`YYNh%GL0w(&Mxg6n*7Hm3*9W@h+3KxJr+RCR+39Bm zI)!3u)#=>=UDs8oj|=o!0k289O|Z7K3Fbwc)`3mWfcpuzU16d&GlY5fN7Uvc;f1Z? zFNMFW0PhvH`E09g*?HQwl+(?C(r}%?rm?WIIX|!oYQF8@z+P+2`PVbvka|3WJ0rDe zC%H2A4Abr+(d`+g-HXC@zO>V8A7H+;TkUjn!JqI}vAL7aZQ7R+eg87}c;Us=M*Ew^ z#>UY8y@0<;`9fL8Tzz(^o$4JzeMF!Kb>87^r^hwco2Y}Vx8_lD+aai*4nh4~6!^dB zn$+h-cLw};z;6WnMZi+qF6N7irTWDu2izp!D+9hg;L!o=T5WT6@#lg5W6GBVV|Pig z-d>{hZ^!GBmSS(m>k_R)>+=%HPh{)!k|oZ@4CH?Q5*gFz`+g?6G$(EA(oSMy$Mn)0 zh3%MLIytZjV!L#g*w}sW(m%z<u5XtG>&9ilK6RPSL0iw41%1CPn1dZN)3!PW^X2jy zseZZiH|DeF=<-_w{g0HdC@%a^TN7O&XVkbhpXXn(A+XslY~#7IXsTZsv~}f~fsO3T zt_H5WE3khi<xckntaHkaMW?q?Kb;l^HV0C^>co_<4)(sQOFG@%KVBWw+toq6U43bA z?XxLg(;;A8H|(0wS>~+kOXqV^o6h+GPYd|tfL8_lOUhkJ1RTWHC5Wv{7qQ{D%u$zt zseRYHfP*!p>zF`)C171+ZEm~%p6Y+ea%}q0N4{^GoMHYF#CdHH=e1Q*n`?C+w?41E zKG5$8SaM=|vHn~;%ju^4wXoExv2*9T4AJe}xlY$fySH8^Ik(@<kFJybC4OKJTwm;e zAt%?#Sh&6TI;~F|&-GHnZoIlRPUGn&`+_?|cDvk|tcb!fykGVz<uY(zV~TsdzcQcg zce_9E^9auf^EOW#Q^NBz%GN%Zv)x!{oIRgccUxdgNpDYWJGS=A1OMyQp3hRc{cKDr zZ@)*GIBzU%jQviJjsM0YmFvRg^x6h+cIxv+a_C~<v(Ov4Un}je%~j4sZxh&e6t?sI z#%{(O?(KUhzll!$JD<a0>eKN{@KBz&<?T5eJLXJv<I8$&HauN97oMZn&W2grU0eLE z;l?kN3*hz2J>Vad?}N#YYnSs6Q`VHxcDu7SI?h6ux^nf<opX`1=QF_Wm5n*V+gDX) zEV}FctgWT)XNx`GiH^EooaU$dHEDjj_c7*3@28(~OY8^ewMWCllo_M$W7LM6bRVZo z9=emCqr4yT<JiU%oDI6Ow%GV1?jO5<V@z3Z|DCe6CqMpvr27uFzYhHm-hHI@H^s`> z-$X5W`<sqY`+n%B8dJ{OS68<7y3X7D+?1#G)X7cljXB2KlPky8zH{LJMzx=aeupu! zx4%o7^YBfNY0X%ENx37;d~x>F>P<^j9|Ug<uHCHM*+i78)ZSE>dEx4C2~7OX4`b1T zvw_q1!R>-;FH**Tk6_>Iq3f`n7d=K8Q(oimF-n=b?J-vS_!>M#*|s}P+KRGa>fGnN z$1-8(bCWU0dY@aB%Wz(2yu9ACs4}_jS%KeVt9{Q(%G6TNleAs#k$cui+v-_Q^te1a z`;NQT`e!Y5Tot~|nB%<9E0wd*gR@G{eDzZuo%vqT+YeW^F^p83#_&YttKb)mIo{i| zPdT>suc=Kw{DCr`NA>(v^JZ;U8&k<&yI$Gq)V!S+G55JW*}ojmHBql3Y2SO5N%P$6 zILGFtudu1Y^E}jNuQQCXfBWZO)Qem>rj~j&P@iAJ=PCaJb7si)_LnNpK)*t4GPr;2 zb!`wsPu2N*R<GN&UmaoU=Opik`f)rCo%Pf9CF2~JTJkm1i@Z6#EBZU?hg$8m)R>dK zAL`1njc0}0Q@6dCFNvS+s=tW-tNLNS+<XN0`s(NAqm_y0W?ers7QiQ`er~45Ts-{E z>*o6Ehnl~+y)mbFKdcFkiRWha7i*tM?cLlp@N<*ur=#Dde)hqS7*oaj8Le#Nd0g$= zz>@+$FRI=H{Y~)`Gw*I*Y|N?N54mz|;~`frp2y&IfuAj^v)|oJUD>rFZfT<Y!;Gn_ ze)7qcW8%ptSI!UjjQJ;|e)6lT{xf=Q^+TQKw>IW9?}uDDCZ2q9W&IT4el7p%zz=iK z>Fn?Mx2PZ6?nA~@^M1&cW2=)ZXV2dO^PdX*Jf}MMMETRz&m8zOW2$>U<jS#)hg>;7 z+_U5dXWD$7cSYE{^LMJB%_h2~xG^=<&n@K2G4b3&uACqK-gJx1LANj8Qd#u_=(WU8 z2DNbuYqGD^TbNUp?K*i&cVlXL|GktuqW2a*MJvODl$krXke^!Kp8Pn@Mc4ck?E+6y zd*;zCZv^em4%#Irr+Yu-#IbEx>!;{wnE7S<SoC$6oaA_W>c_Edm$~L_m?OPeqa1T4 z>3vMvZg19b-{0QU%o*yZH}lIe?e=ac*B0Y^(z~VdiSR|n)b{q5DbsFm)^podu_o}1 z%2&g82JPM-v^&<AI^GX!kz?DguII&WfnQcXBjI<9sq5`$Dcg2+Jufy5UZnPX-=_E4 zpk4O6q`&)(sptLtp-j8CvJblW*TJmkj`_UhR%)rf+TY5&b4<IpvPM~(tmEM`lpDe9 zceX8ihPkzE+U~8)wKKgR)+NWb-Rt$*c5ol%Uhv(<<a+yim2JBZsLgQrG3A%w0%IC@ zd)9Nu*8fzsVIJN3w(@Ftt}zY0{m07IKYOC<7xU%TZ-tAqR@}P5n6te7CS~iN+*<qM zHQ{~At$8*j`Lt_V20r_gGp3PV+oyuE)hnrecUaf?;(Uj#Pkp@>|9x5+bGE;hd^)yz z2fcOz+*x@R%=~rjvIh1UXpDWI0RN&s_bA(TsY4g@ckmeHeeguRmU`>+x-m`swdBpQ zZFi>FmnaD@Q0DtceZDfr{$0eiMcy3SwpOYQYkMDE^Gn<SA4u!uwk$m-lsD0BM;X&p z{oHnp^0nyHp^dpjfA}=zC*a0`pDqF4$unH7pDb*sCC3|KYRUO|8GbmhAFKN3=mnaG zsqnkXg)r-q&21+Ax{Yyn%$n9$$2zkBW{#Yr?e=AkIA%`uJyrd0ftfFUj`VFPdP(B! z+gyFlfUi=v*Y*`ILVo&=P;L)Dr_5OQrG~xF+o>hkKF2t^{SRZB+jxwL`Vpt)XgXX} z+dTs=tBlWnm6Y#;iPPDah3hHj!0fGw&fe<S>emVz_Vj+;G`6Ae5M|pgd!@}=k>&84 z%7rlTTfHcK>_;uxG2-__Q9sV5PS1mPD|a-}9n_3%*R+RADUXDy4QHPZH&rHvJ2)3P zy#Vg1_Sx_)%Is@*FfW|V4ES-ELv!42ctU#5az}x1l#9+f<Ko-~Ghf`bOW==`3*lwL z#mc~&)z1`ooAP@m>d&}XKc$#c{n^uF+b?|fKSJ9gHv4W`r{l9fwPZP>X8P;-xl|>X zy~)==fBM+M`mr|j(Q;H3zD?U=t?tjfNbHBIekJ-SjoI42q}&hIeid5)uNOTl2mVdD zJ-;0-t=tW!4qXhZ;2e#iJWTzZr?K5h{aB7FqF<~r+yP&m#&)Nk%}R|!r!O|oSq1Pg z<t6Yl!o|zLbChii%aw=1+m*R?KuL{ZIefS>V?BU4eNG0j_O{eG2e9^9=C|6>fDRhx zT)0zUf1T><&~MhZtbcNAV=hq@o}}Clo~=y$1GG*`6v97=Zr6mnsB?R5$sG73jR*U? zs%SjS&AX@p7pK+F4)n{7IiG874cv8=aAfVfXq<n*H>L64)kpNh*wgPCsO`3dnF}rk zV!ms-@(g&9Fw-x(>j&j*m@|g8FO_Sefvn+<JHuyaJPTmf6BiqGKCoq=QyYm+4g0Ye z$iCl7`!et$VLKKBIdj^%b65-biNJoc>U=&k@MVpG_y_7bQ_9A$M)bqV!|X>k&cpI~ zk0X1K<B@Px<*D$w%H;X(Ycw9qf6;iz?cJ=^E>5fW5A?CdT%hsaJzm(3#oZG%&U@jh zY5aG;rut;`S=#Pq_-kQ)s~6p^^<26mzjZI6dI3zG*!WA&fzMQ44l}>3PPs>edTBi5 zVNh>n#$wQrKz}gMpHE{O#9C*^#ojLr`aIC7;Y8nLOl$4$Aofbfh1l=VezDIEI;gyr z^CJ6^i;aE_F0Y&iS69x5n;O$beGX<U925WG^TkhT*1*A+DW45@(QC=c;9Hf+$zWaQ z4=104SvP!*4W5?9KbX1M*0(iJ`D^UwtAEbtgBc53d!<LhT1#chz<Z>vGPx$YCrg<z zy61THWBEkoesFzb+S#@kmwPx5I3~_}8ms?zVdjNvYdL(W`n1<}QyvF%=CL^}W3PRb zt<n2@Oqu@P!yK`G4le~WrjDz_)SJ83+AI)0A{$<*+!8KSW-RV4V$6lse->O^xez`~ zeO?0}r#uioMXx2!dmAY)f!itXgE>Fg7>=afdk3ZCaxe4U*VVmG8q>kI`?NCSaxdfP z`og{8y*hUe{}P_1K8gR{rOGz`ACyPJtXIxwNB9rrekQu_h*ZDt=s>S#%tbZ^gH0`E z@^)WsjbT5WCtT)On0>_cYdYLT+1j(-TK%XpFmuguE<8cGGfZDD*8bl2mU1EbyXv3M zXYTt%xd;5EUON=ttUL!kpiH|%$_VqWt7yo{%CtMANt*K^#O!m<cW2Ed8pDvQmC5;# zuG($^oUi-=++TeX|By$OiDwAsCELfcQ(@wFKFRrz_m#={kR^f6{Bkx{-(t+AHU<N; z?m4!7`B~ew{HO2{#d!V>HR;+~0A~v`gwg$Vl&iummD|HtD$~~e^yM<`FTZsWCg=C} zQ~zhdtRc4Ej<^CIsn?Q+`<YX=-J_SoGlk39cE3=z?QT%E?NV=k{ds_xVfS~p2e`=U z%|A5J1B?+IKXNXdBR2N$bPp67)6vF>{|9ypN1U}D*r&0LFwxLh{Mh^Pp(R!4Ts^d+ zGHd?On!-nxfOX9|@_e|tw6%wrhcZuXe~;vIn4z7OUxT}AU&!0gJC#Smqct|pnM3vb zP;M$bU9bHDCO^*SKKL`?qiVp6yUk&_IWT>3Og<lE<FfsY%ELz~b8dXFN}yK@^gO+m zv3rnx!Ch<Z8EePcF#BMlvkxZvP-Xi5;Be)Z@T=nUm@Ig)vh_n9+BlENGtn@{(fZ+e zLeVhRL&wwMs%p~_ZlIhGGrwHBePHI7<Du|PfqrwKlh4boe^N2*N#ST6%z9|^c~mR- zg>>A9v0po#?~M=pQ28mCJUg9ra@dc~K0YfG-X(fj#_l2d;@TqT578IL<nSR~&yOKa zz7sEfFM!*sO?$Y5>NDV5)aRY>1FA29UsB!-&kn9-&vk8GjQ&lae;4S)X>-nTAsSvn zbz&G^T6ro=Z8$#*U~0p0A>2%_rC-A@QqF<Nd16D(o&T2T)Pv1c*;ip*$I5qx7pTo3 zcx7<yTIJp7#F_Zqo9Yi!&sL9?o9JQc+3`BKjxkrD+wpz)OyP_y_$-ZK5qxesz7Lag z7aMc=;frO?+V37be2wTwH-+<+r^Bqz)_=4S9w^K*5k34!ppOppSA^|-{ll**Go}xJ zp*#})O4<6~80ec*eFPnH{lb1kW}w##bmoP#nSxCx&Fwh2r!xLW3{e}#WyFK3Grl7x zOCQUXfjRTroRn)0zpdO4p0D=gdBj%XW9j=N*t&LG!$p+a!xUGdvt~NBdTqTn8)ht= zPCSpCAJ`LrqIVAT+w|I8?C+NGYVr&`Qg!Qpl5#%$u3T$Bb9jWk($?g$BjIJ*FMeC} z$U5b{Fg50ErkiMF1!eLx@(lHp2W!qF@-wn!pmWZ&F+07hUb_w(Vs<()jJ!jc^<gAy zW1<tkW2>|NxES`qtn-#Dl!50+fAa>xU#eae-lA+{)A%cNG|{7#(mH?iG+}$+@hEk2 zB|Z&4A3a-n72H(va14GPZKupx^wG=Je?H7w<l-3#-={nW9;>_#*7%Rhf{D44Z|fuB zC=;EzZ)@xr_QXe*DRcgOl(De>kIR8||2nR{iAI%FeJISmfU}tn=P1+eDCV+14~!ya z%eKFxZZzg9jbRjX!SQBv`r=~P1XD|v%NKzk6rUB#z>}28^QbrV+8*!><>BxWwP^`| zubdC-SX3NmqS37XS8EKTj}W$b7=5(1TMOo_;$q-jI=ZI%A-AKMBeuU4m%|-}NkKIF zX60P?9_4N@dz`gD-nL83J}09;NOLlp_2(KN59^O(ax(f`jbSkSgK`19Q+*Q8m}1Jr zGln_ht|cd9s5i&tWDIj8(W$pYZ==`l!=|%vrEK_CWpX&?(KO~U6VjN+ur77hn8!?4 zCgw5p(dF$^c%HJ=7phOjV$4S6q42MIt&RDBGBH1PWU4<_F3{QgY(6VZ#fJIfcnREI znZ7)BgE3t+w#V29E!**Zj4`sY9eV_PmvRoQ`}hg;{jsOT&k4Ek>&l(sPnE~PtCSbO zKP%Jj*i7MU{ETHRx@rt#84JrchOsAUyVt_Z7Z(qonT&0y*S3T^DAVrP>y*jW*a6CO z;761T;VHr=+IHVjwtl`&$8PM}bnM157knK)eqq3@^M0N_-ou!`*!T(i@qFcta377C zwfb@D+{MrL^d4vZv}181<NG*kj@2u04uAX&)knggD^G{1ZD+p(-lG0n!`qcPFO4gr z%sM=-xY`%O<j}>2pK+Xv94~|$2YRzW@1jhNjU%7Vo_vn$9q4@neT;G+Y{msT>;JWy zlX0_!BXT}&p7ysYOr6^t+V9DaTc-MX@H&bAr1G$?r6;vF(G!QOPhxxGD7EPZQyZ?W zDR5n7#{G%bflkdk8>>_2j;X6BsB_2G=Y8sP5d66ERCt!!Q0Gs4pqvL2zq{7zO9Gv7 zxla531T}Bj_Wg-H+Q)qO&$RF38824@kMKSl->(I5b%}xHH5%VkeG=#Rb5$ol<GZR( z-^X9CJO>^a==TKrQ_A#x{3K=T^KJE+1GC53dONuzyiINB<M=}5Joxuie-c~QU-T!L zzt{8s`4>HTlCbUjlhmH;;|!Sb^5gy_bJ^+NqBqxe`@zgF7Xx+sB(>*!66cfDp3}+C zlcQCq?@uyb&Snn$YM?Wx5`D2UeSdPPvi13+`dkP9CR{noL=%oz8~Q%sMCClVR-o4o z^mfMFpnackk+ALigv+Fl#~HXw+V=_6q3!!|C!pV^?N)^!R_+Wxqdtjq!t<(=p9vqS zPTwamUas9a@VY?X80gfSv!U-#WhmqGsq*S`B&_>IWya_!&LqyBzCYDLIS;-j(Ek$X zgN*5>eSeC1WZCxpsiE4(mhh;w?@vuooxck|^_<4A9A>Ss<9kXOm^In?v~ez1o%}q- zJaRgHe~R&POy4ISk?IqV4s`0x+0gfitPkGj#PiiB{o;4;(r!2SZndHB6Yo{FHX{R_ zb<g>+`V8rp{k&!3hr;&!HgQ9svnKfc;^~-o$Y`#fE~-4$L{FE{oG=zoGcK++xc7XT zdE|036wX!qif|+4%J9X?S#U?SCnrzeqB=Qzni_NMT0hj7W2-+J=&vZ#_orV|?g+C7 z+4yZApZ+D~0&1zd_NAbhaLly@B{lx#Fl&PA%dc={xz;`(vfy;lEAm-%L37ccdJ$$U ztbIlHwSq39PZ|RE62A6G_ztz{4KrRgw!>?{!yTJ1*=Gw_6P%wXVb(osGnKzH7ED#0 z&)5s5IX!O1cee`ORh_k{fI7rJt}qY&T)4(cc)4)@@-Ta`8<#>8O)}DVdk-}!Q@JHv zQJFfKlr8pE7^6uIROkMB(%H&O;7bDi@<3-CZCh2UVsod9!R#ltN%Yt0`S4?6Z}!1Y z=(WT-=^1AqjcyFnUzd|TF#WY-Xa5d6>3!vFnEpDS)XyYp*o|*Lc$4w~__sj+J=G^4 zrPnU!T?^GkkH)}^wQGz1PQFRvv9&ar_1un&oiCFIOTX;z(I(3{#?2?eZw2;W2D~b` zmNgtd?ze2uP?OfD_5Vz1$Ij0)>_Lf6&aM6P&9EW2i9SI1`&sC-0zIhzXLMfMn4gh( z?b@BfKJNWYDJyJkrcm=Y(H8%rDOH6tsnsbpWGr|dSTv=+*xR$vlswfL>nW`?pVZit zuEM7>MpOE!Pv-9wVs`$ifhnv@cI-}V3C~cyGyI-%H~7;)Uli!y>$TRN@pV2KyD5yX z^GOXn%URv(@f?_W?RXVT{E5z<p6JxGWiuR`%a!r@Y<KlJ624jbej9W7*&(W1|C5wA z!@4h2&4#}bKT!evo$?g;r$FDC>dze^eyWm_=cq&5m#X97^TZ~D+&*`KaAqcay<Yn= zOq@3UXd(PSzz-=C+jEoE=RR0-9%sSi+_rUE8Cc_t55lYE+Klq>9$}|z&aM7D_2Y6# z)6bVz#^>`j)n`?>iE<vy8N;>J8NN+<5X}DT{N%vQDaS40*V9^k{{6I8pQj#r5HtUx z=b3Acm%!xQt{ca*Uq4TsIKCgI{$0CMSzDQRj<KJ5v|gJHAFE8vQ_oP&g6pY0d7Ii+ zxSF-+zQeWK5x!Bm4?H-~sS{^ob<KaZT=-4ZEi)E2o@(u3;&=Ac-c-iI@pSm-K;M(< zFO*TvG0_W*g|o-!3&d~d_}weu#*W?JZeAcB_x&7e^Pq51`triVnk)A47ub*d`tU-5 z>R+HgC;DFI{tMGp-v_@f{?9xIo+Emt6XE$zk8APS{tL_G+RRe$I<;Z0y|7jL-pxcW zGMFw8<6vsZ@eG(b>v%bQzQmkKu3l`TY_HWd$38Fp#XH2lI^+1_BVv<5K3^QIdLB&t zHV;KA!;FPvt1k@nC4tVIwKf^V{33JKF+N|)RG%GT)*Pqb2eanbn5*Z*XNjJ<8D=iH zwwS*!F&8X5owG!u_Z7}y|9Yvvvi0fv(j2BQuC2~6iL)H<hS@iro&|pv=!=#2p|210 z9|HY=#yr$SFOz@ga|&Eh`6IZ2+7!SSDl;xG_Y$sA9;U`@-)pplsU^qVVD>5JlbpQ# zfpR}sa~@k=a~@lrz0zGf$V9IcQC<KaFV_|!wpUJ6o&mQOw)Ol<d*Li{^~%LsZ=b_g zOC8!h_mvw|-wNL@e8N%iU1>eP@__1%(3vB4UhEkO(=WTWoWOT@UU|ytaffm6^Qu1q zza}x)%z;0Vc#2hqKUbanys}w!_NG_1Dep7UH0sLcsu=pTtUy0muO*+;a#hcQ8!6NG zX_pHZoeE#2%-Bu4C++*I#Mu-7{EJ?FNjNhPepTb=?>Mi%ue=>5e%s${=Jl(KG=@R& zx2kuB*Q;It|Dn8`uXG+RT#GoTpQxM*pDFFe^kq78#Ex~X_Haklx51r+Gwii}0=-|L zGZ$=MVq%!ixHz^xUsj)%XDc&C)2T7n_df8~sxN?9V-uY<)-ip2t(0&EWA|Da<vf@( zlC^PqjX*z7eHLPKjqvHj|5^{_Y<Ps&8|$C@P22a=$;oTaXg;ac*BA?@cZQiSNjx8_ zJ`|n!7jf;0d@lFeI@PDbg&L3L-O4YU=ym$yd@g}cQ~f=-rt$)~RiL*G^qcis`t>^d zwe^!z1|F}R15X!w+ppK(RJ|qqvBr5Z{H5ys;Pq<%Cd^vo`ZxprJ@xYj?YOq+%Ns|k zpNX)pu{reRjap)#u@A1Td=RED_S!QHe1qtA4|?M!<?=9nvF$p2c%Z+c*JfkGUgrGd z!ON99!#l*@%z<|)GuPfMp*#pKt@iZy&Equw)$pmR7r;6f?DwDFWG>ivB69NPMQTGI z-^^Ft`tPG`^+yB!u|R)YuPwyp3*p*j;PuKm@ULQT7QzRV@%h$K%EbTHF>22^zExS` zKj~CBM|Jx3R-U$Nxw-NHnE7k-R-3VVi+$PkYdCzD@;I3KN%V<<PR+Y(7ht0~ue}-G zDtetP6VXL?tyvCdDzj$3&7Ng_+B$qYTkW%9>U<IUNw>hdm(^(rbFN72+o*j$`qgUB zeb(FERUZknFT0q_zyp=b!eiBDI;``zj*V@h>V@!j;kv~CPEqBmaCv3od57G(cs9ay zl{dq!)uuCiqqfVOdZ(wd)rST8h(OnP>XMUp7O0;Bc!lyDxKQo$U|l!tX9Y9Ls11FY zK@M$fyt62p!NhV*PG+<X^bUc3t6sYg8|IfC(|YA$#@cZ%%v$06<ij(R`@oBZ%~W`) zGV9ok&B_ztZOZiJU24GjY!9EPjL&x)D-VTrO|EC{`>DPFCU5TALbyPD+TYB+J4Lx7 zJX71Uer79=gqNv}ZI^u7zQl~nyT7G-?o48{=LdVQJ+rJay|Ce5G?Q_6OwMOgw~NqE z=6i`Vt10t+n3>dojjetbd|}{|`IY$WVa(0mXTEThjeQ^WGacp(;QVu*pQ&R}zbeeW z<F2(aJg?jl<_wVNa|50G6sKF8@016@oReLgElo6w&gE-7v*^3!h_!cCmd3CTE+<_1 z7&u$6?FOHz*AmYx)<frqwr0_H$5y{2(3uN~4RgUU@yxngeGY}6O!GGD^?>Q4&EeaX zu=z^POZMD2>s#T&robyTPTTGl<<9Ug$`8Vf^%DA6f2xVzE3Uj8t|Wd+REAGdt_s&v z8|v-7R>Egy!JU<@O>gCv@B_--;HSh-@w)IN)#>kh)TBK(mRthQQ{DzslZn12&^6{W z3rzGr`;@gQPFwFEsoWYqP5sY+84G7K5^kbA6}~jkuLyMJm$M&-&455Bew(W^iSzxL zn!`2lN2+gzSE)Vg!29cz>Eru*gzfj?-zR?S-;UAjQp){c)~iIXrOdUnYX>^@V`IoQ z=$s84)A!lbkDVi@)PZkTy&L?nGJT&tNtwRSenXj<XMZZ(pbWf0IT!v@nHWA`j@z~x z(Dx5?UN<O&&lkO67JR*OHatjTF0~N8Pnotpcs$UlZQI{cR-dld=D~VyY1k1apSInG zjKv3<!xEM?hb34`=P)0wAFI!)plo%Gv*B|1Jk<-}3zW(KoG#-3EaIP|YyMePVO>|x zY7gtUpVbe3U9K%T6n<OT`Xq-o2B$9ybk2u1{<Eyjugb(Tx43X4az0mc+o&Z>%)SQZ zGRT%o=b$&z@x2gk;pTpPW?Q(u>iIDBVAlkDpE$R-aIdm3>xtES@!jdUte=)|8w5Y0 z%;*1ee>SE!ZSgOfOP(F?hRL(5EA9>FG1nZ=fKO27%s=lG=f^!WXI_r#%!_&TMZfWF zSYkGZb%8Gm^lP=P9_Zba8M}FR1o~Zp&bYYPto;aO`abXJKxbcYHddbz@O#SE|5nXE zHXqV&J4TI0!mM?Ur^BopjtgPto%8t~e7W)h_{KnI4mumF6SE(?4+je$W&ID){QL}$ z7OrvxOpV#xR%r+mzis#IELi91*|{+1AM4ZpCgQ_|%8c)aYt_Czyj!`Oi9RZ!JQUU% zJ9{d8hUyDoofn5^!^{iU?mC#Uux%Yde?RJ>Ox=E@bJ^)b16^ZoO#OUB&h52_*M-Ts zW8(klEAijBJj}ds`T%%~@)#3+OaXfR<IF(UJ?QZJu&EO0#BXD6oP$m+xg0(M_fowj ze81XvhN&OtpZfWjnz4LTCz$vhGe#flyguq$m~}qUmn++AR|Wc?+7|xjAE8X1=O3f- zY=lo#ot)1<Q@Ie<oHxmWuM)ipG0(qMIUi=u+CDZJ2fv`q7|owAoJZg1vp-s!y!P-f z%H2%#344mu2f@`O<|AjowUobxn+E#1fqsQvTYyczvb~mkI-mPs&0!hF<rB>z@9c^` znInFj{*kiPHO{8FFl&y@ZJFV)uI*(;@{Y-p;=d{JFF0PAYZvHx-gG*w<KA>R+)4Z# z(Fg9VjL!w+(E4}!?ScM?_-tmdnWRiS3*J!9hc&m&rozO0D}MMFEnt7NobeI7Nyhio z*hHV|xHnq@pQ?T~!wrPb;o47IE0>46D(Arc#AlQZ4^XZQk5QYJ@bk*u;CGb=!K?#z zEY2x_zt=daw@-gmKV?kxS%%uofsa$0gYXG~4Qqn!m;KLY^#Z-A_VFb2cIsyxe2s8( zYtLG3V`!cYKd77sQx8t>3~S8IN5Y@0J_BB-Ox`{_sIjpQU?Mpm2Wy<h>L&+!qrg5d z(5VO8?zvgmvvxTqw$HV0&t<GXpR9U5{DJaR_*><5@J`_thCfjiQD*EGW-I5w#9;lm zz|X>qmFd?)oi8o$v+zENErWGtA#0|qA8Y@F?1T2%J`1PlZ}#iL-1D+W$Jg=Q#f39X zREU56MGNPO{viAQ!ue9qc28OOneZ{T-Niay^<dU3yVrkwG)&#vweeKW1`9WfpEHkx zcd5?3+d}g1`m)bNi;9cSveV(il&P6T#|F&YwDap|>T}U)0oPP!ycRVG_-tizvgmwi z>%1~Bd#i2tysGfk5_3=P9~b>a>}|gm-Jo0u-=r}=58op8zvaPw1DpQB<*m<wYCj() z|98-q&F3Q4Rm&Ou;E`(c159n$TvaUszpSxY|L-Xeg1=Fo1Cv7+|8f&8E~QMIi>X_y zx1^7YnNyC5XEAH6<MuH9bxaJ4iQn-^c(n2oc)Idtn6b7tq%T^`9CzFj{!_V|iM}YS z{ptvpPy6^q^*}#8(3!-}5B>UrJUgBNlQ+l2@Wm))V)%mkw0f&D@F&W-@EYazu+E)U z^y`b?HJ{~8w4|8YOob~clfxyoC7#IIaBj5Y5_N<xQk&&4<L=rmgzpi)APat6?9B|A zdkQzc@4=e43$kI2^MYLXJH6KWFI1-Qyfe)Czkt}j)V#$t;ELiiZVqeSoL(o;+otvQ zWe4HoS%<&8RQui)?ku%x&*xv>sQNwd%}zJ=Z;@Z#q54bk-8vV(gdcJoKQID*QR8G> zzMP}XxO}-<+O60RUa!m?{PMRzXDsZTt%$yqK3cBO2d0mX2f*wFHqWgYf~8HB%fs}= z={ayeu|Mujc!2sW1yi@ykJA|!*Ot{^&}*rUrE`_L!7J2$0Zje4YsuTvy@9?z)xSDM zuVuWx;tb>BDS(?P&w#I2-Ur{M*Ji?lm9t=t?KrDbGp=2$>l|-Gf4^EHe%j>1zbKD1 z(buepw%s<w{B<?ub?}+WwEH#n;MS0@;cLbJvGnWfZpz!>LCOnZ_6Qrpv5e{06O_ln z1<JOqR|5UDKz~2b$*uEa?a8f;;k55y@@ZpkTgF7+=z4xE{=Ydw?I*yMQ$OES4fMu( zZB=Z#s@@MK&#o<M=9_`a)Y3Q1O{ZI%ae8eYtToWKGfbQ=o<XpWlkc#7vr%HMRvl*C zolSv>mg!p2b_UE^YW-JW?3U^NQXvbbU=zK)vemU7+LGI4%r6()L0D^}f`LZ{I_ECu z$LgAMXQMfH?S3jY#}oguMatC1vJD#ZW_XuyJ955E*XMS*Ci?bB?IWM5eyj7YVp%v_ z{8S{*-{vZ3!;O?H!<Vbi&M@nS%}+b>{OxeHX#{IuDt3gY2Kvj&R%bnQd1wxQuG|`4 zr#|V+x4(*B-ugVCoX5}Wv}UZn{OCYGO|PAf&K_rLui9tuC8{rhdn%Kk<y!ycSHW8U z<(VVPA5))Je?r;n)8yLrjOp^Fs#`zHl$le@w+SDg0~adO-|ya(wRAq8b$s`=@J0OA z_&aLPo{`#Cgny7V_Q_26C(--y{o(JJJJzQD4)~z(ZoaR$qLkQ2TVTf2+L#Mq=20en z=U=pf^}*^qXChjWBle@XUs%ypbiN}WtvFBg)4ITyivIn>a3{y6Nq6`L;WOAHR**w{ zn%`!?)U);fthFbfmM3z~S@E#r_^e-G)@1bfq9@_Wj!maQFtuU*d`Jzf(EQZh3(s_V zwC^$aW3lPN=MpQZ6Kl`+^rIEuip^@yNGnzgFP#l<5x&aWa|W>ORw{(4AIr_i^GbYJ zKP#_=4-<aAC47|Fl;r+>C1)pWqRBPjQ$(-W06s(QuY{Q+*3XbC@cCkY)h4*T=vPv2 zE4zsPI=@+4$=Yk}e`*T%5&drdCb;rW;UoC_=E?`e=9kam5u#t&1s*T_g^hWV*i3vC zens>>gJH>`8Ar{poFg{fro+rN+wQYt;IG7f!cJIf&wR|;VC5#!ZJn&7hOv*9b3R|m z9JFlfWaaO|XEJuHvV?7&tSar;Z0iMA5Vm!)DqC#&Gp|?G5Pd%16<JkB^hQPD7NX~` zhdT&=MZZ?D&d_fB=mxll<LDFWd{sZ;i*JPWe6qGYtmhN^UEfus#O8KB16=j2@GF&J z)=%4)7TjyBn&CJeX5;+Gv03m1EHxG#Sq@$<HZ5)ZYsKdN4`I#EaOU-@UqoNs&P0@< zi@8`CxR~SUIzG2tT~=&X-VPrp{O;3mRk0sIK38+DBR2C~Pnh-A@{|tnIbt(lJS=q; z*P*soU*`1a2R_?e&3%gP*Y7XG-G#?jg8K@$s0!cZIL@ICS3e>=coaO=v6;;rT&;8S z=N0e^a_yD2t+&MHFdN%@a%}@@WAy^jc_v-7`U|mdoCp6XdbbJie&G>sm}pHYvH4&w ztn=%B=Hr?(#pVURBf6%QaC|x}Yf+rfcedB)T2zH`T%+@--5$7?_}t1`w5GpsJ^H>z z*P<r<;Njxaey4hk*2aew;E7`Y)@|?<v5D%y(?xH`++6dv@ayB?55=a$VeqHI`*y?2 z#HJ2&ZOtmtm$DA5*(^H0*NN8b5d9!?WR2t`vcEH>tlZd*T?%V{uH)}|Yh^t*dzZtk z=XQLz@Hy>TsgvmET5x^QyKtUg+f@92#rnUtrSPT)V3|iIn;6zgZI}(juvXTbxSfGz z&2f9gT3xrZ$^Y63;@{5wwNe|=S=<+|eN}Wj_t#2oMBg`o=SaJD?ysHiIL@5}e<}74 zGB4KZoVt^7U%N5Tb-%lzKDw+q<{^9SA7b;>028e%k=n203}ENT?FZ417ySk5e4XUV zy!{I-`(0F?wPKyrSX8nbEORRQnDu;})LZln^K_lmn`?L7RpN7RF8Yl@yZMge2bc@% z1_bTi>)1@}jQ)t|uHCU>-)0%Q=Fqh(^UHjD61vVW+uwEXiG8lMm-!Xhysi5}{4ZMz zuN42TzZ*n<h<#z5*4X|T@E)-#!RHC<$&;-g8_)VI;il}Z>t$VXc~~#&Qhdz!=%<Q} zZFhYw$EGD~@A`(K+jiGWy+vEtQ`WZ;8{6*si-q6s1a}sD=jR6D51XOi8rbWc<#Xt0 z{r!Qx)?wQZ(4P={o1gUs!mWRTUk>cw5d8uh^9Q24IHeAw6K0_=6&n}lcfwtmU+d-E zCHdJVdjFE>`^1kOul0WlAD>~O4Kh#Tq51GpqSqqN8+1*pHXp7cdIRR{hT4uzgO+du z$MJ2e;B!S^Vr^OrcX$ZyC_Mjo_!`GiCDx)1JseBBn!_fnw;KkDjcZrtvN?Aw`WW%! z+I>=ZH8rr|d12S?G~wx&q0ba{?ap-^y-3|`SnOEZ{YLbCtUnv1_9EBr7O^Qd5`C{@ z>F@8t7d_3pjf)H0cE2y<IQslLxT5H`-S1C!9G5QzpDs4`{YT%|6TXVI{d=uFr=KU+ zF1i%`qQL%g$8ptl=+_6j=CB&;*!TSceV}7=Pg(R~fj(07V{L4@9*(XJ>s%f^6_zuY zDV_yu9qw-n&z5WNod$m-{8#}jb2)N;B%kp`)Z6###K!sAB;1?%^8L?&A6*-dAP*a3 zr#n9zbzZ;6y0lTx8`jUp3S#pDHN5fE)X&D6qPJz;+bA_Dewv8hiE-H|YoqJe#`aE+ zAEW*^b_)D-75hB)_l>=TZNE155u1<hh3^)2@eC2Zg0sp-&8^MPMqMXIv7T(46!?)^ zjXqzGuDNx7-W5N~N1@9)X`COaRkOSex~`Khp7mmXD)VdOHeu&ym$a3`e!Wrl8t3PS zOtD#5(?ma%5gY60hjPMEH~1v6v3`E2D!h6tEcp~alF#@e&X7N}4gBaj`Or3Wnd2_c zKV0W*;^S>ww}?;MuODugYhQm2mc7P}*AEYh%~w~UKPK$r(fQuv3iOu)Kd-CJY;>LD zu3w)xJzBCEUDrwHNA~L|dmQ@4z|U6Uci%>r`7ZGs6usbpi8e`1x_)gcE&gwN61{Tj zXHzxNGiRa)b+}3LW=b4|9@OC`sYAoF2ck_u9d433G#^z**E-~#lhLNzq^%1%uWr(H z@)honI2*Y=@smaHDB&l`)utyL$0xGSZkiJ4FA0A%1pRH{;a%bP9GiE_!J0#RF50w6 zY<4s6Hc1Z6h#l}6(cd^0)*QY+2rd-;C7TCXGb0<%k5Y%xqpUwa9xgUcmpU|a*>`?C zQFOZ={-||0{uQ`Rpv&HE?r)4P`%dKSTZ>K6pU`FB5nXCBzMXmTWB0(1)MQkH_<tM_ z=z9LS<Z|>8fvz>Vl6w15_HOa7^ZGf?_CHEZivF%#TjnkFj{-k(UuI6Au6|q==&OZS zvu^yj*>T*zJiJr%hRmZM4~TBx?X@{}Y{oqSYfaibY}PgNFzy95XUny1*~>P|K5ovZ zzng1|{w`;&&AGzmn46oM3p+nrt1q-bzckRLR^y)3)#h%2uC;n3=he-3ir#k#JXrX- z@vxqSY`->-c6wZg{c-ctfuCm`n~P_lzZU54i2h9-^bZ65Q(^nA+s(2EMXtZPW{&?9 z{YSBJ{oOA7JM(VyZ-Jjb9h*k=xj!kH>fEci^ZBkn(JP5=`?aOA=vRFL=QwubwWYr3 z-KqI4&BWg3b4yF%bN9fqX1Y4ra)szmk3iS`-NwH~_V=hS`~H@GVq@dqGEg|z`X46j z{Eu{Ou3&xMG9l0>3m@?^`m4e&{<j>*cb<(d>!-vob3Z<61Nv8ipYMdPe;56SK-c@7 zdBf0UPj~s>B6B~ky~ada<-8Qx__xa3H<MSx$EAL@%G@{W$?aC%(`~=D>f9fF9-Jrk zHh$hs?$*6x<a28W$1eV@GWX3s_O-3o2L5&Kv*$!x`v$tq{kS#rVyo;y@#CyHTOV;Y zW+L^r^+~a}<Fa*<<M_1Eu<S?DFP-~MJEFfI*h{UNH&{!zE*9P8;cLf+``~EnTG3s9 zCAaa&JJEj*bjfXeLQxa_l#%K`Np9mtMbM8H-NyNo<knnHetwd<@8bNahS;=XUi@@s z;OA_|ac&;^`GMX}^ig%uuN2++?;<>fGs90>tF~W1^>(@`RRX?CY;3=N(seca3|MmO z>i;KMSL2#J&?UF7etwd5HGcAFbj_{vKg0Qq+iyb;)`6csm9}~`Lf3V`wYyU6FM1PQ z*8vy5tOI7>Q|SBTTIXNRPSMGQCfX*sb#ZQ!x{ZcigD$xhUF(+pD%vJ>YaY2C*1Elc zTHV%I{M&f8=^ERbI@~5_0P!Phtofilde^{S)>zZ`DD*yo-e0)iRp|Ez`f%a7?2p^V z1-h=WldZj+0pixfVOe9%5x2v01AAEqqN5%{57vQgx(*cIh`!C)n<s98b?&=9%G@`V zKQ__!Acxx}hjG)U=s^y*OAh0~-=Nn@W7u9-{CD7NuwCcA^}k)_ew@eJvR&rB%i(sN z`!(3hwg+>6yUzVnnB&`nxxZcKe%q7LhX(DAkakOPX4pPH&}H8@9}Y!-CD7jx{(wAe z{~*vmb{r40dH6EWzZKrWp1%G2K;I&K!&~Tk0{wtvGnTzzN3m4jahT{uzehhd&`)q2 z-^6^Rjd*Be?7wJ7FyD8`e2?zPK|epZww>@Ztn)jr6h7+<SZdPLD+Tv-y19t6$_}YX z^T%L#kl24*8J3zf$8k>HF<Nx{x0M~5&+Zq%&xvlwbjQoWLzpi+WRANr-7(wg@wvaC ze-_v;5gt(;eN~`qJ~wlw-LX@ywROHj@@bm$`NPg4sr^pb>&<2CzdMf!^yB4Pp8p-~ zJT1^=uQ#1oKX*0~8|#0k?DeK#G91+8PN~Vb>|N+VP43j1+_oA$sL7pDlctc*PIm@1 zxl?O0_Zjq{CU;Jf*lr;|JEbPwyxu7_X__!cb_VO@&QHaD`yBLOo!q%n^yiO6*LBj4 z%g!C5-@`cW-0#@=FQlOC=az?YPAe=UHrBqdobdiW@JWGQRrr~b=rXU}_!c&Fdi+Qm zbeY$pw{f~zz~?rFmy3<fbKy0j54LUH>{#q?6aDES=z|0O0pTs24-2&pU7Syd{g>2m z;j@9g)M4DB8M@S=^jGRI+Bp|}abW+o_!(9ceO;h$5`EU^=(_^_H_;#9{QR@jq4WQ< z)?trK^k8lL`9!(4_X6~q!Z!Y&>o_)_yaG1~^m9e;&Hek&7Y4f2Vbq$l_s>#?(yrFw zv#gCj_YdrKE-!u-UH25%?kHztUc3i=VqmX1e4sSC>?z{^9kD6eA6@qp=Vy`V4Mw7W zC+u{|Vce-Zy6i9FM{;O>UT>mZacaLSOZc4o(aQ#U1>sff%e$%sdJV^M^Qq{$fv!0$ zUx<Ez*w}j8B{?(;y1-om`x}IhVLjP(YoOoZ*c|mE`j9}^9A=-3KF;Z`U%MoSW?*~t zX@UKl!apxUpCfF~ExYDBHmjLOyOxS>&n>%_i_S9%qFozBxB1+))p2|~pSSGV8|Vjx zn=mha(HvU)UrIaOyq^PW4xOGYen!*oFOowy?|!K*_Ib~vHx{4HzPWJMedz52{Zg@? zUJ?B-fqtX#C%>c1To(U#iao!#h<?$z?EF70di^`lWiE^T(@u{Y@Hy}=FNsfQFEtrW zU5WmFpzGRLiS_4~F9KcGM)PPk`uafs(XrW_f&NRN%e;=}G&Ip}nb$6!-KCsOT={kM z^1`;Rc2^R%@$asc`q^FAv1#)tdS0N*+896B54}U6cNCu206o}WcHboW`EAi}ckJqI z_g%tc*r#?&4kb=m8_mvA=#oRxbzZ;rA-d+!=5x2s>rd;#!Tz#a_Gt5p)t3eB${rne z=ghNvo5be)=)9iJ{rK)bM7QUSJ(|NFN5Hbbxbw!IW5nkbebIycWsmGH<|y{@J(5Eg z{~p<2%<0ULJ(5GwTRT7I6VB>;G>0~xJy(nW^N)vhZFG9R#1=Cydt{FmKlg~ArOe+w zBgDqpj}fkL0(wE9KPTLVdf4-NpwDn@%0GerQJ_mcqi+YIOFpGt$)|aKDf;HXeuwxe z!8u{i{#4&<9LH_g$M;H2IzM}l6#JrlzOh$o(%paUtt|GZY(~!!KX#qjTVMEeYu{AZ z_IK}jj?Gy&!xxEe*Q>pk3;%E-e4ViKqxD&b&t3QS72Wxf+?wy{@7|$-uDPvzKKl4T z*W5mO4*JWYyLL6Vwa-GIExK!0avP5rioPW9Be^vTIS=gJ5a^Oy!|(Q@y?dPQz6-SX zfY_W!eg0a)vHLF2uVuvMIL<A<RumiiU7%m3R!z%VaIla6DzzF{VgLFynD4(zKI2Ep z?XQ|oo1b5=5dV)H2464!o!&$AvoA*PC%VnUuLDINxey*Ey3NC{BZUWXzx?Y2VdrPE zV>7BI`m{iQOSmTIqF?6*`U1ys_5t*-1AT>K!?OvaUpI;F;@Kwr@>S@+3cGlIcN~xU z&P4mNM7QzmD=j>@8(bmKvxU2I-q=?o(CauhpR@k&3(iIRbnZ{)yt=PLU@!G)E}xCA z_37Hx`h0d2x~!k>dj<Ps{WKLAuYFpd_Im~Uq(0+TjbYu7?C0nEbS?dp{bir*N5+1y zV4tj|=7<&WdqF(&B>wBGqc0ZS=53$kHa`9*c&+F*Z~J}_ZfxT$6n615;qBkb>yYQ) z;#B`lb9=%j^s<32xs4yBPJXKr=$hMh+>`#68|aN4n`w`sw+i(3!Z%-p-YL+#3Ripp zy;q?3aU7q{SpPOC(C>F_2A_>SN_3lt-^Pi~JA$I$rigCy@Y{=y<Kw!*Z;Nj8@SEoL z*-v1pRk!Z_rn$YEG5Sqv)vbHKtrP$8-RN4Y&i^jaTW6yGk^0}CDcqNK_siUO{`Z#? z{TcSP{U-^xEecl^zGDDfSNQN_;f9XQSF9)drB=-)FT$;z9@m)%>sosH;qWzb?S95_ zzvlBVr^1@gW5>gq&mpXV`!%2Ax5JuGo1guXPg@Jo{%6JK-Cx66s}tFa_v?JOb-w=- ziL+rLENf<D>wNzzx%O7p$^Dzf#@6}%9ik6sU*7+luxs~EvFY%xi4K$$-R9@O5yEHu z0Us}H^K;;2$FY6J%YoA!yZjueC*1Z7^k!mj^K+o3=%4br*@4SMxA{46mFO!Ug!Rm6 z^K(G&C9h^*J0NFHH;xAe%eAw}&w=2)bU@Eb2e{unpmW^CFFA~}$l(D!FS+>Naem?_ zSPu`#c}e2e`|-P`p=&-}{F=`TDxm)q#Q(GK)qI|F;CEpg|G^CL&-(_WgNKW5^L+4V z;ftSxPYm=^#eN8L=b)^ak&XXg1F@N%0iP>u<3D(T@V%Ui4oW^<{0B9kJ^P?{7aJS@ z!F<OiZv%X{=r;cchlu`rCHPU%UHp$bjt?Vm2cHq$#s7lvAFT5Sbq})jd2p8KpO1lc zUfcRSDD&EEdk@xmZR_)(&g)M(KOB^K?bhLgGOwc}Yx4~HV|i^@WZb_>?9s(NH|00+ zo-g6I>7J>dQl9VPvk=eJMrqH_@%vrR8~Kf<=U@3frSb_Scz==SYW$AYb0gmC;<+uq z5A)oa_lJ1CmG?Y&Cb#yx==R@fTwC5V>&CI3`|^E%&&0_&MeJEiD|(*IGZa1VCNIj> zO7qM!&y{%|nCB+RyX;N1E0Xuon`*2@mA%afeHT2fRhyc;+uc-~m%N|dRHNprdi%Zl zZglLc7uWZjTdt_@D7RcIdFQyPo|n8I+*H3PdH1)eetq)(Zd09eQI7hrJ}h~^wy8cL zd3Uy{J}r6wwW&TQdAGHxzBGA1wW<DtzHi#burGOkw5h>3=Boc1#M!`eZt_lNQ=>!j zzGhS7c77}GZ5~VBr)+A>Ox}-dYAjFQcWi3xOx|T|YBJxO>a{hGN!}@JYK}_Y^J{AE z(s#%bXRR*!&eJUN!J2TMz1H%}`i@RG=Td#grR8<{zDW3tq58f>xb~6B`x8y=?#X)( zP3>p(y@A$dQ}W(GQ>S+FzCTlk8n{r~t+Q3%TZet!s>yrnOx;1rd*w`B`tIJdhE2V4 z$$QpJy<W+C&`iAr^8P7$W9px+?=Z5=wf3Da_TQN^l6SJ0+_K3#Q%o-F{8iS5eLHti z@(vNx;4FQo26_YPq_f&I_%3-5g=u(B@;(UD@Kt@M0ItsB8uz??%lGLs=ix?&=`+|Z zkJV?A!)KqO&*-*H?YZY&!;MSp^NKCAUfE}&+JAW;>vKNgrj_&=MDRJKl4lB;a~kP0 zd8|HCpNC_a^~XI|0d9Vs{>~R}aiRX!4>mFH*(%Eal5@j;Ff3C!Hs({S+kgD;r&hQB zyxtP_x@E6-3Utf(e<bk#$f5oR1ooEsJK|Vx&mLgk$>C!2{)Y$lmc3pO=$5@cJ<u(C zePN(m_WG(oxBR!_C(a~q#QCg^+5S5+$YD8jpEvB2JRD-5<mA6;|ALPJ|1bD<>+=j# zuXE;fW6BzD8XNPm*PDqR^+0cdy}!1Vj=QyQi@n!7i0<s^*DKx+?Y`n|YViz8uh)jX zj{jG!ZtJZT&tdd7ZPBfb)jRMUL$6=K^8r0y4SPS=bFJs@*n7U8XP$cdVX)UZAHU)C ziLlpS<XL!Lp9XuqJkN;IIcQo2%;#~5J~iOwDMwi;+j^ei{ga;=-v8gqPpcq5VNQAl zHP$z%tH0G>+Wlw8Wu}c&$7Pm}nHXl;m~~v<^ZMTzms!4#-FX(3=f4%_KRYh}g?uLc z3j6XO$ma(^KIizn5yJ;TKIeM<@8oli&msAo>-m2$pGm*MzWfLB`B9M1WbGn`kAi&8 z{|EA!tYhSJ{{Mn}CjAQg@*l{j+Y5BQf9CT>3~sO2`Tn`r|4w~==5t6sKll7USf5G1 z!oK_m^0_#u&o6x5h+%P1pG&;{ck=m#&ms9-;`x6tpGm*MzWf*Rne6+ec`ks@1Lvh= z-{<`EmG3WShU84e874eO{ZoEQuz&e+Ii%fWU;78!{ipoUZn91u(r&W;|AX!RQ+{YS zSx*jWH(4kD!FK;CKeU_7yF=Pd){}p*-G9mt?I!hkNW00r`v=?or~J_FilDAm2KBtc z&v)8g`480dKjnvZ*97gZ4cc83w7d2nX!oD;^Z&zkH~HLBSDSo3>j(Eu4TF0t?x$Sc z+IuDLr;;;93%$1*iry-?x8i=v%?oSK=P;HdYr}e&oZG3N<bJBYiMIH0ZwC9ZzMk(5 zd%YLz^?Uf9tB-$Ja1S+t?{0d1RB%5v8GGNy7qRg?Ke(UzEV!Rq7Th<j2=1GRKe^u_ z{^Wk=pN;?RVEvyRtpAIHc$TK|MBPnPp#6$^!y11?fBpSnM1TGLU_^ftd;06`|7QLf z>tvp`fPJ1X4aSB0(_~!OuYd95LJYrnd)nRY^H00Uz3nvqe(&|ygK?RMy&ntmzsK_$ z))sHSDP3oxqCtO42mP&(j#pIa9~iHHRe!0CB+d<KoMvw@zWdYhjY|A~$Nx9Sr5S%` z@_A-lk~z{A-RHbRFfRT1JBqiz2lh5&`8$En=fq%KCi8p(uRj-z3-x)>kHu_kJTDE_ zXZoJ3$&695R&RyXK8l0>+P-_eTrgf0{(<rOSLJ~kOZElZ7aNbg7ogsf_&22Sn;pS8 z?h3{+?3b-cpPwWD#`@OG#IYZjzaGap_Azw$t8t7oy!|~U&hR#4O`Pe+>#xT#F5>mS z9>+M-$2Qx<MLgTSd;kC0as1ch;om=waS5NFawaa}^IyxvC4HXj!#<yXJ*Me8**mBo z=4NuvA0OzG1D$d4>$zDL)D<<Ee7?6S_<Zk3V*6Lb`C`y6Yjsl3GlO<n2a?YfX}3(; zZn`d2LHD_;7S!_<!T!=U*k8H_>u0ZE{j|CAc^(+#hjl5*53wb2&JW_GHj+3?1o<f) zj3aR-<7mg!k7MItjkROy`@$F{?LHT@`+CqWv4!m>`6(UvtQ6$uq`-fNAU`%&zFl&a z>@U{``ME!^9}(D(5A0bVlJhw^N#b7|#J?hle@zhozk7Ub%)Wlc2Jw^Uq`%}jiT}Sa zFOKp4%LVyo+>i0OJ)}O9^^lw=`vUcu><hhueWCxqu0E4EO9ydMCrO-#)JYO2b&|wM z%t@ToiQj(>b&}YV^TeJyN$jbU#QwifCrSMOjy&6#{Wwx5N&M7F5<hj4#Q$HYljFVr zL*hUFe_5R*aUN19Nu2-7>m-T)-;w8kcbzl~?)zE=_kCSWe3Gpn`>#7}YsUV2-NYw* zeI~4W)X>D0RgW6OUdPWVUdPWVUhkW(Gm%|$ygtmtRlNNO*z4m>e5%(c!(M;e#8th{ zIk2kNgZUmU4)%o>X`I~GCvlq3Ok7R<n5D4#F&hH=9jQGr$0z!B?}5Gj^?`k_)SmNp zk{|A&l6E83?Hb-sE!f9T9uohfQvcCb6W8?i_^he+aS0Qjrh3dCcbeCUvzFJ1vzFIK zq<-SDfgkeV+l|SC?^nDj&}rA}rb6)dbk_Fd%vL4%dwT8Qd_tWh=aXi^`Ghq;xd&v; zPtGT^gZ+J8Fpi9Aa&Ba8OwK3&?s(XDlJgsL)7Pz;7U*vW`lcZMtwH>IgZTIV?f8?k zR;?hP^@Ch7*OGH7b2-UduizZQTuaVf1A}wOJ;6D|_C@Q&j0)lp=8;((#J?hlKRjO@ zlK=l${F8(Jz8LhEu}IEcGlTyAH^(Je^Z(AcB>UGP<C5(Aj7zfbGcL)#&$uM}{=aEl zlC#a<i9b1~{V$CFKbC*$Dj6^8Dj6^8Dj6^8DjBc;W?lWq#^vALuZAXi%C9G^QO!M5 zOHb(@#CMkB=AM}g$@;@wNY>R7!TF?ga6b8K|EW**lor0NR<QTqKlpwQ{*%95vfm}K zvEL=}Y)H==W@~!hF#Cfz|48GEh|S-JMn?wg<i9ZfnYLf{Gd<#;Y5QgQ|4{rN1o40H ze=z<}gZMxFKNx@VcT(yn`5Wthpnj5dfO(P3ea^kDeLgw&@_QYrXU>Ohyv|&1<Mmc1 zZfkY>uPtnK`)^b*f5!*&w}gq?d;8L`w`a|{(ChfTQ1!^JOR7h$(m10_({`h)({`g3 zX}b|?g<m%!&h|de=#SK%^Les9#CEOFcH>IvIunx<e_!)Azkk>@jniD8#%b@-l69|l zu<lI^zE|*E@SUsIc|N+&!`raW&pcj<>h;fHuWvQ+C04g<4(I<%tZsRii7)l``(d?@ z7}LwFUW&hu)=tMXs*i4Mtj<{bF(UuT7)6YcANT0~v`(U7X`MvVOx#i1jb1m#&dq2F z|D`V-eGGg*-_BE~FE;Vz-hLVEZRpn(UZ*ctsBZ6}{QYKJAsv^PzWDKtiQm^@Ol@4L ze&VjM_p>RjlbF2uI>|UG)ibIEIzD~78RW#*Lq-P^cT)cuSHS8&gBtkC>%G$N;bgGi z`TaEGo^+qe7?IXt2IqWVhZ&QDc3%wIoo(W)y#M*IZ+C@>FYx*XSoO@JCcawr%+j#x zwx0d`vVRjy)`5X(9t>mc^J8WP`n*7={(Zlw|0Gw`e|l!<mBw#+o4C8iV>n|ZG4x0G zv9TT|@z@yDKH8P$ig}&pirVmTX0%F~KBjHa_r!ng)Q_p3`my#sZCiF8Vc*lnWBDY$ z2kv985_~6|dPw?0yNUm+gYVvxpX9sucHF(6VL^VT1>b+rxnu128Qu=QBVp$b*ShbD z&knx-Fi+-`v!5S)U*a>JYxcY7)W%J|U25YdpJ(#<nAbT+J*N6!{q5VXlivQ{ouBbR z9wthEUB4y=d3Y|!!;3*4_zj3V1K7Ng!;gK;<j}1-HV^ZIJS-0KuqMdErZf+%rO6&) z|IVJ|p=eOI>>Ww1RxxoqpU+ybk70y~`+0p7?Dfxr`LZ;aBO8Kti6>|`zSH}mK9kRO z%9;31@3TViJr?SAtJQ4{R|#@hEyz#f;Ip6>l3U*2ZR}@p1AJThy&9*pt`6{REjH<A zL`#FuotE+J9)Il$Y<vvld6;MVSg3wDpC_L|MHSM|pxD!s@4&F9C*OgwbAOBVPrumH z6aR6wwB5K_8c*CIZ7aSaje&h3i6QP~;=9ym+!xk3<9kf>sP-kkAJ&-TX(k@%_19sq zvo_xCb?WVIuQMOr-{lAKzf1YA)h#n02YLIgu(zj={`*Do{`7l98O*`M)INh6I85y` zDy22UUY68MM(uRX$!M6aIT>x!&w=e;c8d4YJN>*jgFN`pdox(C{QZ>Mv%LMp^z+_~ z=hDx6Gu}==kII-Ce4a+P?Qbo4r=I)gxDcdY$-Or9oP5?%CHS60t>AlHz0w*m{nHw- zdsg!Ohhead)7Jlp;B$kq!RH3E`ObsQr?p|c{P!PX+VY<##P!q96XF)>cUt0B>31Yz z@>#@>BlYHgUqihm-;1zkk|LV7cs$>g^7fNqug?zZc79N+i%neK+b@N^{TdVZ_4+2* z>$^-`!Rvcr)#+<Gj=|dQYDVod$hlv0Y|Z%3bu${L<H$an#83Ss@pBeR@|MB;N<N3l zH1SCPJD@BR_wroI#63KhG4U|ZWlj93=kg{V<(cvsW7&=uK1X{UpO1M)AL|+2|Gt<r zZtQ=XZ1A7h;NSlq*;F*K|1Go0Hu2-$5ABY#tnEJGbz&ax89z^Y#(qLz|CHB>EwLxI ziC!nRgn3rNPhRIYP}@9XQ^#`|p3UdEEYIZi%yR^iYl+|gZr4;cacyr?HRxAPU|*N# zCwiM)o}28sk%>?DoM+-QJRg#ir@c;2!rT^k{g9kY@;W(5Z2neG=<kExp8ihp%(as} zldHrh&trPd>s*`IaBWhD{5I_wZ$oThT_rm4ByAlM|FiyDVn}R=VT9L-;d#&GBpKho zjv>_<_vzjqKd*Vl&r;9yC8>G*yyJEH;^L=7sp05luOHH{Bq#JMiH&w=d3)M@&ok|Q z?fH;)-}gH0CUb;#-}U+-?N0UjA??md^=PhV+Wp4!A??odI_<josQsPo^+Vcy!Rv># z`*EsA^F7n<GS7#!`-#_SH<|nN_d~BA((a31KcwByQa$?IGwpus`H*%OdYyKYb%S;n zc>R!eU-J4P?S7H!(Gt(JyWI03?SAQX+D+Cp+Fj)JL)uO1Eo>K?a1EU1uVucx>X~|5 z<(YWC^GrMsc|N4AV2;Ge9Kj}BpI`UaGVk8-%=(<HGl$r}>20u2V#7YkIWZ@G=wn%L z&zgL==P+ijP3+lIj`B9yCNAxndAHj$dD!C_pY=V5KAG>odYy6E<vBa>Q`yA1UaxB6 zdY*Fvo4P!c%j>x&`q?w<{F$EfOkCG9eSga{ajx^sc&+wKoWnhn+cB1PuYB9<<n0~L zhuF;UI{p)T+D+`yH+mb|{oXU<6|Om94a^K|lJ)KH)IhTC;WO#)AvKWrp)VD@f5xkv z=P(ako7htW$9fxT;AqeEG1D_Xi+ILoW6z;a&Mn2fj{nFrJ`+FGKr^pX17~~A32f?e zJL2_R`|EtWkn)cjXzDr7#Em=?XR_uq78|_ISgiL<oDX|8e_aE~`g}+YgyZ#rzn1(b z`vQIZTXQzqFR)Ky!#<p|i67d{_WsFjMbBZ(T$|W4UjCUahTI<K?U}O&J(GvuJ>&B% z&!JD|?4Mp|&i>|^Ih*)lyz;!xcs2B#6WB0k|L{6<cAsa)tBGgEtAXdT#w7a-_w&h_ zwsN3XO`p|c>IQml`rIDVJkVRF&+su92YN?7KKAWi8|d9k@@yZ&GbxgI2J!Klw;vwp zJaZ#iOQ#0<%O-jL5AWDc{k)ex3&<=8^o8kjfy}x<-<Uol$Z*e@#KUJsem%Egc|FQZ zpB)sH33PJn=X;bL=#|rF3Pm}APHtoEZ<H74%~i)XY9Hw2*4cMP=f6oj*QU=ViUtMx zed%+GqLG0<CVgg66y!4^pT3@>AfFNW^z$NG68QN#eXdcoIncMI&p3)rs@r>RKX>eB zMn3+yqDh{86z2wdqx3mQamPUKls*$F?ic6-(&r<^;{ts``mCgQMxei!J~t^|9_Xvm zXDG${0{vk6Jf)2Csh&|WeYR3YZlE_Zrkaj#M#n(!WK4Ch_Y3p^>GPK|#s&I>^jS<9 zZwC5|^tntK)V9xO24i%(_aBT)2IG>WIzy4zXYzl}@Os5S&rYA?lvy{>bJJ%!Wd`+` zd2#xDr_64FeUJ26Pnp!Dk27;9&lU3R(#J$ENS^_fNgosaz4UodnL!<9Qipzh%cPHq zePQ~XDEs+}*NbGO&x|TU9}~SY+nmNzggz#EBc3JXb^4g-9eK=)*Xd)T=cmt@DncI< zeYi1xJugBZ6Mc$Fo;_70=x-7F>-Xy-3j+Ivs?(1mn**J`pX1}%7w897$G&L!R4-c5 znC5C<G%wJb>pC+C`%Z!0na9_7`=Gx?>95nRfBNYARdl327t5ee2=s#Vd09o@3-meq z>?~_f9}_=I(r0QF4f<P@{+{pS3Hn>~VEWvxVr5f5#pru0wJ*k4d;i6%s!sgH@&cVa zT;T272Rb$2bZZ~vp%{5+?d=By_JdTn_CX$s73lN6=x?!?1N-T!Tl*jn#mGZj?|)Tb zzfN^)Pv3pN_`jx|+GkY^^lW3=d%aPh=jrprxGt-8pwssYtvwF2g8pXF-wxi-fWUrG z`Yf`n34vaaK9?-(y+EI%&nUA^1pUpTzZd&<w*~fv`W!QBe=yZ~tX=Yav*Hy4Jv)8Y zS@A}Jo@dNu8h`Pizs2dV)9G*VpuffGZ%1!GF7PuUeNI~Oj{<!``pmTA#O%kV_-=iE z8u6Ckzg{nqsXFbJC==+^@Rhb*v=TXiURR&JX8q&^I(6Gg^H!pLpi{R_w|?>iy^lV( z&H5P>==Z5^;~5#~W76lmm6#srZ|XDOte-i7PEM}&@hl1SuhVD5l_(7K-TJ&Z{O~B# zBtIp|&o%0&WSKxOn?7HzWKN*h)o0CFKY4*pemZ+U?F0Sd^x1SJ^8>w)F<q=Z|4I%D zbn@eL@>6nTppQ|#4Eppye^Z}vXZ_3xbn?^H$Fn5RzgFG)DGc=8>GSbQ1?zb!YW`Y{ zvs7+sUy7Q)?*B1$KX7&BX?@2pf0B>{5|WUFBxHspWQNHwGt3M#gUTu@yNfI9qKhsn zD!bw?uI!46En891qGF4cR$5U}(V|7g7F(*=qOyt>En2o>OBGwJSXsr2%DULawx92F zzW3f=UN2s}d3etAJil`|_a3-^l8^T$@xEN{z4`cP5+BRu-j|QhCh@skZZIETP2y|C z_t~pt=KRld<!<pk_jtR$LR^nceU<A}wI%WP;(PH`^(FEC?Ea{vmERlYllVdwKVMIL zJ&ChFKj8XT=#`)63diY#`FLFtXZx?t$LUeXXSU&dyeEnGW_>F<_<dzOiBDwlss-Zn zNu000HeV;1^U6k+f2EoH<o4|f$NKA>f0fzt^IUDn@^4J@`%p&`@66(Q?Cff?->&vM zPQ9xmN&aZ@{Ryuob6#am{eDr~n2YyGDEzI1zEz$l*Pi??M*Zvg_*n6GkQ_Dh*ZH}% z;<bJ5S97@s`TYIjwSDfRjz7)sHRZ)?`x1U=BA@+J!b}a`w&Z2U-$A^qcx_+8d&x#V zbCnDiukA}d<T&q}TQXC;wlDcX$Jw9yeWx*B|HF>+K9nVU#cTVLKXQDX{gf+S+m~|3 z6Mg>&arV{ou2cGg<Lv)Zj!{!S&ig|uzvL?Mq2je)>16SGuXMh6jaT{;&aWqbqj-&1 z%4~7HS3%sfmAsbA@m8jV>$)<}R`OQjP2_2Yam;?pU(1yZ6tCaPKHy%1<S@@$J#*Q7 z@tUnHKM(KGTgE({`5fj6Gf!E59`<e7S@Alpyry_<R({{TevF6gT8r0a`kf-K)2LI< zd+o-);`o#g7q7?4neDUHS2?`zape3aUMgOLl`~shk12=mMb17xEM9k=qr}@?=UjeY zopN2>P`uVU*H*l~I``(RPH8nc{l)96b6@FrBk_si_0_rWa=e}RV)6Rw+<Nhv>fEn8 zr<a_A;x*Md_FG(EG5>i6)%>OG1Kr-e)BF7VbB<3E?<ihJ>AF3C?R5StoHI|(c=6il z{A}@h>HLp4hyAQ;@-N8O|5eAgiSHM$m(H_~^4CcEyJO6D$n|Gk@fzvE<1DV9#|!+t zeW7b!7%N^E>AE+rZIrW7y#BecSG?xA@JFuG6o)&zh9SSAws@UW(OkT?srV%4vp*`h z-To5y)wOGw{aG<lyoRapF)HgLzF545saP*ww^ZyFuT?7k!1cLJ)%9mwlQ7Rkezx=1 zCl{GD%+JY1&PnZ`vMJnMye7FgSiBCoI9|N=xcHsUUm%~4cYFSeYsKr0i#x?@jEleT ze7=8?;}X{r%%f|_{B^~p#^SZaCEtFQQR7lq@tWb1Z$HaEN}RRjuNf|Jp2z&3AU;>T zX1MfYS-iZ8_(t)X;nHt9&h7c7qvAEgrH?sI|I6&F_j_HJeLGP8nZ!Ga*9Mp0?)-NV zpU7^zbPaI%yBwdvTUlJ^#O2>{{J-Fn;x)kKzjgf2`Fmtr@fx7=%~|{$>#poAUISFV z+i^Zujuo!~D!<L~Zz4XQ_0=^%<xe=yzNy^K;<^T?<o%7c-_G+<$vpXMfJ)DE{yO)o zwOPKd0jeH2pS4tV7Ow%Se1CC%lK6O*uWNv+?{xmJ<HanlYk;Z^`xx&R@9V2Rn&s>K zyHcIy=)V5S9moG|F8&ps3sKI`6SL>|oV&rXl=YAI#||t04Es7Ce_|`nIas)6c#~a8 zydyDdjGPwY?EgZ3pIt-z%M-uPW}oFgnD}e$2I3z|{EfEiPbJqa?7OR)xq^@HP5cA) z3h|#x^0^L(eCEpiqTPyr*&f6nvD+~}hmqfd_v{J0Z_i_X7OV67?XPV1TL~8y*Bs~h zmYEg5S-jRN;dsS$7xS0YCuaQ-XTO%P<}j^v&V-xrr`g0xINu8SpI7`FIM1ce-ZNi) zzase?_*dGBk0yTu=jSONw^IBcCVvC}Zd-Alw|P6it{=4(|C!=-V+lWhwLUH-Yl+uw z_Ot%}964Ioj$Mm?FEQ6)k<(86f7xC5Pi&53$=@V@1Lu5<$L!dj`Wtn@d>v+AmC_?j zU;Vv0taIr3;@`|mU$UuD`l-dgnU{Wst@@vpnA^AbySnOsNs|9=yOH>C@o(&<Bev>% zL*j3?Rfm0k-}||g|BoQ7I_&eO^6?+HRp+M@b1Wi9bv~Tr|EjGz?DPD!z5Zq%Rvq?v z!GCD?6X$2UkpFR;{io;F)q5VEyO^0eW!Dn(Gaost#2?%2|FY+7<|%7V%+GwiYAT<f z?T7jLZ?#qba}x72A33wc-;?CO*H--xB>ozkb(M|ULwL;Q_>}SU|0v&=V-Z&0f0p?B zZO!?UN&dgI)t7T2wv~TA$=@vg9;Cnd$L~a{|J#ZGtF3kYagzV1wrc)m;=i`FF3yFh z$-2r}N0@b$^Rxcg>(VuRn7-xr5<hLTu5!+WLjJ2Zeam@|^oYxxBVpxpE<BU3|GBp6 z_a^4NjU3ih&U}S@&XKTc{@ui!BN1m^<=<*+UEgkNUH`QB`(XL^+3Gu=c)`}3D@i_I zKdYJ5_m>j?N|OJdi@#Tvb6pa@W2*k|C;kIl>-vi%|6{i5pA~&hE!DT5-xn^}tn1um zn{}PLTl~HC+*3Av&v70-r)_1<qcH0@_en|qn{4`?>qy+0<iD%<`|r6gwpEk!=t;gl z=TVq-o%=gU{@=4z|63A&o2_+C*;?1Mt#$oy@%QU<|J+tz&ZGFfTjo3pYhAyX<o~j* zzQ3OMH<SFmT;cchbNjYxavsI+?=t66SnK*klK=l~>YwNKEplXT-@>fxJhyLQ)^(oS zw=nBE-%xyv?>yVQ;C*<W^Qd6Xqi`?z+`ff5l;^p93v*j|p4+#AxqS<F5r22_u|oYm z_+q|3a}>;Z6mBJdJjtK1wU+NGKDK!Nd+iG1Ka}`KZO!?wll-5xHRmrR{;;h%w~LQa zp5L)m|MwFA4_kBod6NHEHgjGmEk34sfnyPmZ&K$%Rbq}s#F_KLgCw7GB;w3@p(!z6 zN1Qn?d|L6b(F+`lSG+$jye%=uBI3+>;Y*YJ_t={AYl@GhUif-jb8?^ZYQ84NBCI*5 zll&Q5bN)bL&XLI1oSX|Ss>8nv9E-5(bDvT$$0DpbITs4~AF(y(e(^Ef3kSC9a4x)- zpOa$|)|{LRVft2-+00qNxe#&rip`uA_lu7OS3Iz(UqSD9j9BJagqgFVEy-`U$*p)t z@v-BIciP(aixP7z-q6g<S@FRn|7&f{_MybzXlu@?;$zSi)3)k!F0^_-RB$Z9n)9cU z{C{O@PHva-k6BmzvaLGYE=64CScEm_?<e_xU~A69#7DN~<aX(kH4pzPI2K`QUgTUT zm}3!U&Wqe%<nu2+Wj7Lkq4-$&#g}c>VVihflgzOQGp8O$3)5GB>j*RFMeZ*O{$iWl zi|;Q!=6;c55s$yCCg(!I9E-5#{LUo*yKK!lSA2~A;=HXo{~|HR;!Qs87yo^d|4X*! z{I$ftVQbF+R(z~qe{YG${Z*fHq2NPXbDk#oXEt+Qx?Fs2z@@7;buQgX%(3`1&w1%d zlK-O3oR?lp{7E)*Uh2#ho@1cD?X;_o>T@m>%&`bF=cV^0`CnygPVS>W-9JB<zR6Y{ z?xQ0vb1cFG`1_LlAGGU;FBSiet;Y&KLp7_3|6F2@Ma0>cm;Pgt|DSBFmusiUk$*SI z|7h`V;Ftc)R{fL29E;CX-+lf*!Q5d!U#_&NdHF`-+x8-H&V|Td!4K^<%(>9v{d1XP z5mwE%#O;|&mWg*K`8_uK|1#%7Y%716^E>c+ZMM72Iiegrrg543i|{<=90_aAiOj4r zcX`roz~7ztdz{Z)m%rau{U5TI@lPlDKVvIr)z*Gs{W0?q{uP`3efd9RE~&x4mH0o~ z&BQs6VrH51D6IO_D%JiR$HzA7xcu?NpUAAgXH;??MLx4savp`LQOWTNZ(xpBco#pH zng2T|SIKRf;w9`K{XOt4>Z>^WC0vc)n)tIbmoyURcop(FUf~wv9It{oUSZAiq2l8v zmEUNq{zPKdsmEDL>WI%K`E$1F|MSHE!rmnQFKw-n`}cUfW*>jJ_*hKkuiEOnm3TXI z><6~VKXy}jU^kQhr-}dER<HkCd>p5$)TVyb#l%&a_4815KgoY!Q@@IR`dQlla+A$5 zt$NjFja6^h+xRWT$A+rjW~=Y#CjR`)T2~d<x^Gkc3jCF}dJQKYu~}Eu-!DF{RP`OU z>i?s}|0Hv)>qnFPAGcMX^C%vlk~xpUTGy(rb@6q?w=uVSUHLh=-3wO|=XS4PZui2+ z#Q!A8|KB!0CsiLy{5SR#f8%8r#J01z+@}8(&ZCGk&lS$2eEln&M{oB$S2&Nt%yWhF zs9?^cu(o|ulK<&8^IYjn++~jv=l&?R<vh6ZE_()lsXdS1W2-*5d!Lh^hughyHSw{; z<Ms~m=_H@Jk*|4vAn^~|>dUc<9QFN4TXlZE_!!@nU$EJKdhGrknnz~7@H*yaD9pF6 z?AcBD4-@~fJxrWq7x}E?%3s<#UL3oK>v;XGP5rAJgZy*1uCo4c1##}P3chC_5`R9) zf5~Q^tFI^iWSir1m17rmI4)P;Y_H%hTQhXqs?TlU=lZx@{c@YRu5ud~aruMxG5)3` z|66U2%hm5p{9X1qagI&YVV_)OUxfL&y~?o*v+u8R+Za}TZUa9rKhMwFnt@{%arwhG z$M@<-lKkJXH4n!w^5uP-S*~*IB0i6~Z49f<|0zBudzIV9czm{kOPzCxxowO%`>py; zF~9o0&2g!2NZe?1T&g*Cu`S1?n%l<k3g*~_IWE<oYODU+i;w?SbKBUXeZtzSdlUEB z?6>NnB!Adu?bUxb@i*Ax#5s0RljBnT?Ka1ynqwF7P5h5-)n|WwzK=`wf~|ReD)GOv z*`L+Fl;r=4t$BVU@o(8P#5s0RpFY+9%~l=uMgFnu>La^?_+KUdxJ~Z03&s3v+&0Fx z9G7d?6W_8qF4s7Ak;8Gh_P}1jjrKZb`^ZuKPbofbe(lq2_QN&q*W&SX`E54)?b;V5 z`P?=}4*TI6_iF`nzZT}WTpPAIF4snEj>|QUUF2-yZ?;wcAMtCjjtl>;alaO>#NU_r z2Q%xrFxP%M$^RL<o%m{E`bC{H;v74<L^c0|U5hz(5tsk7U5`0-5to18R^Ow{jG4Q} z+)=*=bL<NBKVjGLxYng&{`D(%JMo)|IR~Q-wXf4JU*|gKV3^sibNg8^=U}*rIJch# za}I`?^ZI9H)|}Tl2Nln?VP-A3*ZIo%GMoK#o!if-!|}b&?PtLsv^$A^ec}(<{lv%Z zS<KI3Y&(y?Cv&bHf3JOjf5<t^a{Whb&7VJ}ivL^Z_u)0?$m>b|e{zoM|F%7Zf7f2d z|J^>tf0S9*($_y~t0v!z{i8Z(Ht`!}&f%Ec;M|OLwPGJr{Vs5Wb2H-XpBp}=B{Jt` z#8ro5mal)K*;dXQ&gsIOn}vMN!Tj@8ZhVeiLC)tV{=&>9`@}g13;7?gS<8))#G}q{ zBhERf{1VOf_w7~u5A0q1k8IWF94yrT5nJ^a6E8Vm`{du)s{eEL3jRe~^?%t`{f}hk zHR8D&zhh71y~O0j4D-afA1s*r!SDj{zfAns_B!#uExLwvNB$v?C$mq(oYOUxnM<ni z4V(FEZrelnDSH$@w3(;oIh%FWykIkLO<U$%H*U9k@LTOM{Mq&v{ybard_m@z=SytO z^KM)74BDE9ueFvE)#Uaz)}_8a);Z;KUm0=P$2zBNxvz}4{7>yOJeOIIx7V=FsK1T5 zuZ(=<<d3!1_3xb1hx5l;`M+6w&Q%S^`iq!TzZ2E$Cf>_jrub2k&%TKKPU0U=%<XN& zw|M-&)MmSz=QHa$l{c$w`rN!`bNh3%HgTPONc>UaXET?!5P#8TjW=JhS^LdT&&+Ca zH@RModFpXjVva$6{+qpt*+&s)|J>xZx8V2LTFX}_{<_S1Zo<vKm-w4(t&!uaIwdm4 zSJrFVZgPAJ=J<xS7S8K}e<ZW^|IOvhv91-H{eSb{C;laSfcUQ^{tbJSc>Y++oY(55 z*F@gjv$e+k%<;NL&THj_Ij_U?zsY$W*19;a<<e%%c^zggw}{D_|5kNoy&m*djlF~K z+4Q~jbmo$E{7mLjZTrM-!!O&a^P0`i&#jKk`WyZ&_KW)FnC;d(Y}J2f=8_HkMVX`i zm)h;bxsEE#&uw^E_1RxhvmcMy`<UD6h^zj0WY%+#Z*g0#c*z9*C-xTpzRb}#f2^7J z)`H_hc+pm0ZmXmID$XBk_2srY>Z_NJb&2ZxypH-l)}^Y?zEFOt_M4A&se1jP<D1yW zx>S9AO!eG}TmQ#15Wh{0=u6Gp=WNcG+m)_Ufqkq?ne8^W)%m`+eXL7+iE~>WaXEji z*|)d3t&TYJ+|D0s^=&Uc|MPZ-&Ck(oZmYjo$6DrChgsk4FH7<{mm{v3-=Fw{_7w52 zw`VceQIWrh$L$q7VXOZ46rW#u`+IH8@I#4zG_%f~+y6Sr|5;n}{6gXn+w;U(f1lR1 zgtu(%=ijz9!+*^j_5WA#`K!18#I7ahFA{&uKIC~%9J_e#E61w#qTPo1I^r_x39}z+ zId)<8LoMfNSarA^{!-1UI<MIDt^K6LZ_2DWYu}#af3B@w{2W9bxzC=#9J`3KPio(1 zvma_Xb`jshUz<7Ve@pRswzc18YaWjAmuXIU+SdHkjkxAtur<R^CFZ_0a<m^fc46%Y z?pwpE^XtXu>(+7(_UC);B;K`^&qw5_?~$#(f0g*-w)*~Go4$9rZ;frKapzj`dB1mV z+N|+TUE=!8+CO)ill&H&zIQ$)@u%4{#NT4GpYFWP-o_lecWaG%`13PI{ej~1ith~C znuq(%_jsS&`MS)J&+TW#*$;QP{S0d!Za)j=_A{(`xcv-k9&SIwnulW-);#PlIqLsh z@wHKRxc&Tc%}_xOx1R-b`x!nU{$G;(-?dwb|3TtEvge3%>|$H_*j~mQyNJu5u&ICd zl3j<d*vxyEW0%jrdnd_nEIuFmZj;UYcVA8XM&^=w;%`mzxosTKdfD#o=Oz9EoBetB zOKkSv-FMrEc)0j{@4F+m`hG*=Z_XTjzdOnQ9$S6CKQXtBU!i%__s4AY{RvxrSBuXl zzq@9u@2@2O51FIye@*g#&sN|6nV8$g_vZWlnXSIuHb$Jj_ZaJa%HiL=a+|*QE+@X4 zxul*rw}FNHM>c)$JxR=MW8|>jd#~B_y~k~1#MQU6_<Z<#UAFqZGx57JM_+CO2lI1& zm94(q21Z=|JGT0MqpiN*Vyo|T@ilt)$oopwRNo&+{KNJlac%=6hqQbD#%{pe21Z=| zMY|vWsy&3cZHye%*)2ZL|K6TmPW%rO|8ZtrC*R{ddVhYspRikaJ}kF^5tq+rE}6nr zHfyTmwoy4HC%87Vo~v8OhvIr|R^9WNSyry@CA$N^p7@h9>;DU``*d6N-<(-<*7Z2Q z5BJ*ahq^CI^1nRE=Xk~Z6XbBbV$N~Q@d~T{x7f#+-VxVYSf?C)IbO1^6Y4l#ku!*Y z++M*yX&>RAcRt6z?iZ5$jU<0F$>;ov`U~X$UXsuG6}?oS^D9h^x{o>k4F8SejXdwT zqWC(F`;|7a`!^Eb&RpI^oNc~J>*C*iz799zR};Ts?-Kvi%%$u2Gi+wK|5=&K1~Ati zs#CUxdoq_dV2+pK(U<dUDBqX!E37#=UIlZ!!rR2ZJ<0zEHnZRV$BF-`-A#PXrsw^6 zTXi_UO6jY=U)|^Y3b$d-uYx(h<n#5!|5K9x+x8Ig-%b4AGwV63_qor~w&jQTqnV@5 zsq@vB{T02Id46|U;tQF}ne!>`v+{MGx}I5eo_gSX>OA$>RvnIAp=NVty+6lO9J@lD zPsx04kT}OqaXsJjskhiOm}3|5P0Y1NcnkO1nyt^?#hh!(IbV+7XIJ76+BKMC8acK2 zLv|hJ9E`Zu#T>GpSN_y==JI{~y*B&vDb7LV#LPcxYaY(Qi0|Q_womZSWIkVwS8dI+ zW~=XiOzdN==Yc-;UmTZxto53sr~V|#|KB$I<|)p{Sc}a07(V8C_qog$h(FCfQe3aG zdz$kxa+u+1&c|>cek$=p=XVl+&Q_flGFNEZHs{Ojw(7h!@n>hg!1tg2JX>|XAhXu> z^jA245PzjTiiZ=A*we(nA@Mh7zR*RS^EB3|`kbe7)c-!`Q}5{?v==ZRvGzsGM{HYx zeV)dC^Lctf>+*SeVHx{8y|96Qv-rBRr$1ts6W>j|m$_W~;m?x%zp(p>pC&%btk?e5 zbDn;HwS+lO!~4WJPYdQel~up~LFOF)>N!sp&-LS`#LbyY*$4HUr%^}dJPk8@J?Ck` zZ?X4@zdbSMsdAz(J>=XZIRo|~<~COG683-nSKDKl+t`S+@9Y1by@J0bb7?jHHoFdU zo+@8|bEu!TH7Dn3#E&rNsjSy^)^nbQ2l0>F{2bN)v^|eGPa|guuiD3W%|64Nr^<<S zah}S$#;E5!EtvB(tl9n`@gLc$&wP=ykLeL6R{!zDpUABJ`QTD!^?i^(*30;&^QrUT zPUbS|Kd4XKV6%T7JfHX_`+)fCi9gw9t_Po<_|2JPo}SDxPjBW@j@<*UfAZ^kz-_Wz z#(sYA{>0oSM|__6*C*ySIpUggJn@9BIsake@6H_a{7~kY$H%&qpPvUmk;O~*asF6y z93Sw#=q3ADmp9^Ha!vVH>=yhRiGRy(C;t1Hqpy#3iTWO9@vx6|iDvjK$L0L7F30~j zi|h4g4@>Q8d@*sA&Abn5Z0bC$&8+?K@Y&3o=b?|a9*=nVN)`|MSeGmkf0N^~k9Fx9 z?#$xaZx6dNYyUiaXX1C+?4O5Un)p4o=J}e;F^`XRNe6Le(*6&R+rz}aBe9RQ_S?gM z;<)_J>_g0Lc+`=9By;IDUbL0Z`JkNGKmR^+j_*J8vCe7RUvpgcvDW`F@$e&#%fDlv z;=RQ5h#5F05C1svpW3a&|1$Ak+u9F*Tl6Dlj5-Ir-mAi9o=26L^|SGa`)lQdZ`<TP zddlW!=FvmD2|s5u<D(aB)#sS0j&2(tF<-bJf0{jjKhqw>Z%h0+Hv8bw=i93Jg|=p< zR@6Mk)RJ|*{phP~`akmRe>wdheN*vu*^j=}*1Enk@pswn#5wLCq^ABo`VqSxFBf0O z{b<Ej9gh1~D_`cg%O%R^Hay~d>(Ou9&6wNph|B-oUci53^E376qnV=)KNG|GdCqKl zHIyah{#rRD9M1-hT|U3zo=vX?j$Op%XY6Urv5WXDemQg0Y3FBwn!2`W;3M3HKRfX| zGV3+z4gE>}fIUT=;}YA-92Z&dW!3O^>|M<Lvf@#P;}ZGwY~Z*Qww+1LtWjr#oFBHe zmVa(<;h(fs|6khs_}^x}G>U)Tp1|vwFK=V!Q~gSMHvGrTRfCvgs<@ux*}$=j8MIIS zr>z{0UBu--vp4aHt$9xEWBmUz>wOd+b4<0Zo@@X3l1;D2S8Qf}d^5A&hv_l*%gV2u z#Pyjq+v5g%4!@eYVjI6<AK_2Uto`u#Gwd<^xtVn=9&-+=e$^80OYCE<_ZE0ezsONO z$0N-CfBX%Jzu9IVJpT5~damf>e_&VQ?<>BK!DG(BucdEJaq1SlXsga@lD}qm5$AYC zKAS)0c!in$F~_SA=Xe$3f8iOlmXF!mw`WCjy2QHl-U!cJE9O7rV{wIj_)MMSa((8j z%lKJ)13#ZR>ToTjeWiW)jE_asd9&lH^I6`uA9vehxW`__Uu>)Xm)Y$9XWpB+dH}!Q z9>!mj`Pv%(`pnnIF?BW14QfBb*Wo_=-I=ep;_tDQ^Zki`$X+4-W47k`340H-FI2O- z29p<V!Q6g^)$5mR&HQVb^_;0^e#0KYAIW?}`M+cH^Z(32<|}LX(B8#=o;mizU)h7a zj<&S;J{bD{*1k?ZZ{@_R5_7B-*Lx8?`!KVfv+*oH5Q>*H<JYp9I;PKll0App6L)0R zduTlS`APm4X4dmlp6$<kYYGq8tmRqXe%?C4U+wrA{-(^)_ggd9)DidXXVmfS=PiC7 zo}KZwsxzBekF`GgFKo^BQ}#Ok*NK1DJ|^zta$ELsxqXU#T*5vsdJm9ixnKK`_AURO z<+d?gf!V%bW|GTBd7bgOVt(UAyOVgW%|2;loyspE*7(RC!<=goU%@Zh%I6w2;(M55 zRPdW@=5OQ}Db9~Yu91G>2K)}Y3BS`OxA8sMKG7N*-)lGH4<z=vcK?95k5S}*yK{z! z`xw>A|2T`^oyW8GCZ5Y2b$pDX&cAY<X>xpw^q6Ghzw@>n^TrP+b$&Ievy=JGC^@^f z_Tm3X{D<}g@jprYzino0{8-|@v6px~H~UfN^&Pp~-o}>`U$xmk&)rIV*FGfvAn{|H zpO@#F60_f<*BNo&$K8=XC5zv!!=I7(Ep{96w<rEwdy#l=;y!zw_?O!pm*?JRYt9cQ z{@ToXY~;BQCH_X6{q`LDR5Ra`Co|Vo;_puE+uOPt;=aAD8^yl8t<!${u`K^S`}nz^ zu$le2WqS;-*g6)zy}d8{_V&Jxi_hz@&ujg>J@?<TZSQE#-_LwkbMigSe^+bgBi7Q0 zKc3`#!d~Td_MBLezlqNm^Pf~@*1Dctv#I^0HnZ0CgyW}e_4oBB&u6|{jbF0){*%`e zf3n>~{L>S^*<K^wWow>pdk??MW=&7NIP<-F?DIY5d~X)l{(s{0{eA<^pYP3>^~B7b zc+Bp>|1k5NVeDglNAvtM$NAZQ;$yAHX`lQ^7Qd@GeXQ?l&Lzh+=dyi@e=f6rmY(=n z*R^3EQ$1hc$!}#jI`^OWwpu@9PkgNPxYm<>*U`4DQ)`K}|7qqpE`M%o?SE}+z5mA^ z<3@mEeV%ROU+U^CC*rmIo{`U~=l6rW8@U$Fn|*pY?^Z4i^KR$*G;exe$-A4^PUPLo zbw}R)JhwaVL7o$w_b}H!d9z>iT+;YA&U4Z7p5!@9c~A44n7n6sUPa#X+~(!I$oY}? zGUs~UtL)3X*ZH~5dy~Jd=e^C}YV+RZ?{|6c^SgcChy1RX_c6aq<bBHZtF2GZ<Xyr2 zZr;`0cIREod7F1V$1m^3;(J`^TBj)=Z}s~>P`jkP_<jy0oqoRs#k-5|pHR|Ud=G?@ z{^I);lnfT%b3lK$ZOPXkExyLTWW4x#d_8XZMm}e{`1<#f+2U*1OXiEOH`m{xJ|&;O z%+uxbUM;>xyJWridg_wR;%lPyeo*cC{M}sPHOnRY#n%y+9Qt*;6|DC-d(CN%e<i2I z*K%^Rm%Vn996gt=Q#IvkzxGhBExwkpwBE1XQ@qiyo0FUUnl-uAuOpM&{Ti+u?)2-Y z<Zi!qNjbfKJ(1k+*YYT5(66IWeAusTkw^Wy66K8hH64mi`uXjOPy2bo@@)28JD4k- z_jB8-@uHt&CNKNBUh=A+b0x3)xli(@pN}MO`*}g~uAh@5@B29|>UHSnnaIa}?uUHp z=VRb9KH@nNa)qC_AX6)zOCZ<!v1YkGdkh!m${PK+s@$CYeJSFt#lI1iwfpZj%IVDh zeiAv|#osr}di^_va{9AtNErX(Hi}vFyGOVkGiR9l3;hlpp2y4?=Jr|7r!VB!C;8kK z7xI}|x7+cr#imb=`6Euf9JlXb)oiylPlwI@LXLGs4s+$YZ06E)WDE8CY}N0#Re!)% z{Xtvxhiug!wpD+`R{e2XH7AmsNn16i>?S;ItLBWY8D?$OoU=8<qTP&_>=wLicj6Vh z3$NPkc+Kv>>vk*Nu-ovqt@=B*>hIdBzh|rdzTJ)wY}G%sRsYCV{Zm^t&x$!Z<Z)c6 zSyFEI;R>6Y`Ws*5FoS-l4O3IEJr1|ydf%@RD`~Kqp`_7P{U*By^S!t)qfZI7!t~L7 zM3{Q|yL^~>y1xk1U(a<8t5>h@@2IWUvD9lpnyuefuK}A}-H${LHA;r;Zai$$zhuOw zr|wf8s;25s*s4EitLBtV|B`82+s@dkKWnT0oXz@lzZ3V%s=s8b{<5w4S8VlKwY%_| zt@`V>>TlSZVcYlhs=s5a{;sW>dv+h*x3%qot@?+y>L1yf|J2tHs()rvU-xBkUBUc% zoFGgu-LHk2zqHb(zV729PW{pvn;CQ;7uO`zFKw_@ztL7rz85*nulv5Rwr#OhztvWK zwvQa<*Zp8z=cs;{t@>;eam~+1SiSfNlUqu^u<G~Qsy|?BhGAbjss4zq`lGgLj@i`H zeP~>3Y1;`~^(SrBpRzUotgpvZf6i9@d0X=@*y^=tYyKr$^_OkcU$HgAy07t6f5TS& zO<Og$Y|X!IYug=L^>=O6-?KIUp|2ZN|HxMTV_Wl|*y?p^ci}Ue`nvCaUgs(G%gSwL z(0zAYi&DR=#-_gR$0JV7vO2pD*W22*!B+i7TlJ|G+cJMytFId?Fm>Y^lG<hDh1sr* zyl^w7ZkV2BtRYNK-S5XWr|K|ASates<qz1ZIqd6F<&W6PAGMV;W~=YGtvVBSJ)ZV8 zt?JC!sxxaVf6i9TMPJjl;3c~iFWW1akI&GtSjBvV$t_#6$t_#A7x0En?Xpdqo@HD1 zJl?jMQSTWYHJPz&*Je#+d-f#Wx7+Z6J&up<7JOp2;!}G8pV`b)p0k;!oG+p;^ORTE z%u`-zGf#Q7J%(#+`j*$)!??~K!S(haZm@@Nquqv^>;cTIF+&UHdtqYb?e+rhur+_D zJ%_t&&EIWn{vKQN_u6B)&({3?w&rJ!=&SjeJIv>D<_>Fq^1{qmPF`5^Q>zf4u-l1G z+RRu!mE=#`tf`z?V_Vi#KA*%FlK7&{`pTDV^<DMvUoCje)_z;J=kSJ2z4A?)p5<G% z_RqGhb?w;9SiWzo{(-Ifhqme**{XAFPv8?<bx!S3d}fdFJinYhjLYp2TwycMxk`Hg z*V@c;uFh`7^)~aIYp`c=qdkF}Z00%FY%|X}YJH~8Yt2Kgu;!t6So5^ony14az}-o_ z$0qk&uib_FlKg&~8t2$P>UU!Lg%zh?A<leZ`kZ6Fu=-BsviFHv!Bh4sp3YpN{2816 z=VqO=gXbKt!Sjx<;RSmgFWaimhu%v{w|nRKkfT1^gjJtyB4-zGIIjAej;sEbt@`9e z{t4c*Pw~Eeh7U69di>n6<IHl7ZDLzyImb3JgVxJ7;lB8jTb4tg^X1NGyYm(H8m_dN z=X|YQkL&CP%-4mQd>tMq-sqeb++;J``DUB%pXYnZ*ERO}c6%CkB>A10OEhzrJ&1dg ze7+ZTRKGvTA4u|tox^@OKVtXbQJZ?_$860ondDC;`Ft;WDSyVM_WAk53pRbuFWU4u zzhtZas$GNE>{`5TH{%Vv1#ffRqkY9(=XY%8I=^f4`TSnyk_No*_zXU<sdxU^R-F@D zbxv*7Im@g%7ibxMsdJ&+rp|?Gdmh&$@miZY7wR%cokst?tCe_@-G*7`TeL1_ztEDo zgc=vfi}(&EFRYsF_7?82**6zDZOztYZ{luy4fojVxYu66efBEuw-@k$y@&^G`d=8b z=kciBipOl`y)bU?;fc(#u1Uu?h)>y?bJ||RGxj>3wKeCQtvTr(`-Ip9W({i|W(`yC z!jetB3(GeBFHkFT=zoD);dV^#F!Nqurb2wn?jXKxYyKTu^Y7Z4f6vzZ`?lskur>do zt@)4ad3<bZ{u6r!pW2%L%x3<IoIQlg?Fq~`V*UYKX%FIRyARjc{kYcd!F6^ouD82z zgWZjr?RMN^ci>iA^R(HThrF0ab;t{=4j+X$y$f-Ahlj~w*0AcZhA@5ff69dEQ$b!> zYaFpP!>Fw_j@biv+@_EIKbqK<J{6O;W}C9LPo`~Vub8pB@Vx(at$7w~&9i9l;wAe8 zFWYN)#ooZHHn9r6_g38|5UW_X+c9|&r-q)Z6jt9ITYc#laXwe<+3LG*tNwwl`iC~N zR~*@@e{9cUwvU=~_|%@pXZ8$_M=@^XFz3Z`djeM{@fy2>c&*Jm7wc^1xma&A&&39t zc`i2E%yY5HW}b`9HuGF;u{BStJ%rnA&BJ^#=K$`o2XUv}hr8^4+->(@K4RNm%tx5q zi)<4nSO2e2So?wAVftJgwl&X)t$9Xm)fux@XEKRTCGlySdKXz|)K{H(n|15|Es8kn zzPM;J*Tp4!2rt`O<BC0iS8dj(|MMv7u)d4ywr1O~*&i1-?GC(Ucj4V!_Bc)p-m^8^ zzP*hPGVA*7;-TZzyLe<%@8YpdfBoN`@z@akFP_?~_{?VBOF5hMT`IR%aD}~yEA1s* zZO>xni28H5)^5Xf_6%;cTX2)zikt0i%=c7B>$=4EqUI{5R(K7!+nSSo7x5L`X=~0d zTXS~X)40c;!M*kb?z1OxzdeQr>~TD3Gs~qRdld5#GbqkBVP?F<Het<AkMJ6%M_BVu z*_xmEBCh$FFRb}zZOuPtYyNp#^Do$%pY3B?X1T=nVa-p!a37{$So1SqxEnKHxCgJ> z9eBg;!rOKm-m%;9uHBFKY}MblJMn?7I>$-;B#EEe1LU09)VW+?x8O><6<6ELe7VN% z!?iZOF4x(t@p8S*%$FPN4%}?3J|D3kRG*LhKDpdx_Y!A4pQZa6<<ldqe0qd8agTk3 z*(T!4nEAr1xZhsHtU2OKc+jTj<so|kkJ{=xW~=YGt-ces`cB%aKV_@_v^|SwY}M!M zn1S5Ob2hn`=WS|VCNFZReVMvp%}L!bGhSXz;%jz0@pW7CY}lG-)7Cs&w&vNkHP4Q% zd3J5hvuA6beY+1I*qZ0i?#4$p$LI2~-GNW+u3WA%XS1%#a+~=pE9`zuQhvRa)pjTG z8e4VhlXycCZ?p%<X|kEKvej<E^p5((D(M|&=1OJ_v&KsLh1H9XFl(&jBdnR(Cd_t~ z%pF#JdWThi&{q8+yBCl8`2)%yvz0$?Z{vx~y4|jvbbJ#}*;{zpUdJ=`2A;K7@tnPe z=j~;@V6Wgso6nU?HlHiWdz;Qj>Q#~#rd}m=!)=(lVft4xU$_M`U$_;so-m&)cQVJi zb{(f)<(^Hw%6(gN9@zA+JhV0Ek*zt8?P+{s&)`#=eOY;CPxAaDmK5`h;c|N%SJ-X1 z(jLXNNxaT(Cthzee^rCMh8u0>uWGWHzpB}0{;C$6`KwxO=C7i6%*Omx^awM5Rfnzl zJMA&tWo!O!yASu+n!nfP`&E1|YV!T6ew*4=12*-lhHYl48nKzBidwNP+f~s!torm0 zGglR}hE<346ymI>5TCW_Sv6;?4*Ml?S}^-1+=`cN&Aei>j;d8#z1D24aoyI;8+HfY zwpD+}R{dRD_4n*veCX%)DF4V-{;|D@Pi($lb!szj)tSA@bKG(^>$_5Jv%V`8b{np= z7jUgj-z#-CeXrEp^u5wx)AvfFt@=&2>Nnf7m|CB$b6NGN6`sQM4o_qDS9k(<*ps-^ z)|_4TDDF+-eKs|&^xK+ez}7s2w&oeKHP5g;g-2}7Lyy8dW47iQx9NF>StCdD@V#(1 zrdGHIQ!C7xuFTk7c;42!m?LsDKXZp!$CV{p^_T5Vyke`)dJ^AA;+ysWIa{{s?Ak4O z&u+#0wq`!CwZ=nRy^d_H@z~bPCw2$VC(7B>zglin|7wLz{i~IBFRsmH@Apoft9AA; zuDADbgH6w?jrIa=vKMi)J%{PtrJuKX+-~#vD)U90&sRHb)nRQBSDkKKb(pnKhgrj# zpZyZnoc%WSt`6ALyUO<>M}0?Z^&Pd<cg$Abaa(;S?0GzCtM8PpzSFk)&e-b9HgDJ3 z+c7=D%BM$o6))MFc-f}s)fJmQSJ!RT*|0k>+e97ZZzcKLw&vWi)pys{oO`zBJhWB+ z$X5MhTlG(D&2wt2{+Uhv>YPpe>T;X<)qEq~OTPy55w692gy(Ucy@TuRX53)+;zpa# z)lD{^t6P)&HoJv5>nYS{J>d=F%ok?6YUT^8J|AKA?Xy*<-`1Q1w(1PpsxxG(&ZwW; zsrZ;pZuPjmj3?}MJZY0#J!SL#>RDTL=Il1i9PiN2mGT#o{6(8JRWI4<OTWl($18RR zrgy|uf5TS&O<VQ1Y|XQ6tNxCy`n$I3@7bz<n9Kg}fJ%I1SL0)w?W#{~a;s16X?$kS z@Vsx9+O73Y;&OWmSJ;i19+A_H=@G8SHFg8$>xe6#uft84ufz1!d$Whtx7nV=Ew=iy zzaoe4Ut@oTyK$$j`dzl_^Swg-9$WQ$ZPo9yRlna>{Q+C`hZB$3#IB9nsySva;c;6v zC+ulVznF*EHNF?t46}ajaSficYw^6jj~DD?ylAuCHTuQ>xxjYUmTmP~u{GPO-Hg}l zUc7EM;tjhAZzuUXb_?-cTYdLz^<}=8L46Nw^*yv(@sX{*r?%!fv#EbQXH)-rxlR4+ z6*l#+SK8FSUTstVdW}u}>-C8n>`~&ZGrzB{v(E4eapnlCW{a&Es2lMq+-7TrPCq}K zp4YqVTHI~V;~skl_uBNi-e(iL-fuJ4^#Pl?t`8^qBX$e%QCs!L><v6_x8ey~^_lha zbpEREjIBDew(78dBS&@kI;=Viw(2bVIq;Qu#jeJy_AXwt5AnK9|LfF!r)Hr4^-X&c zZ`o6L+tz;AvAZ#KW7~SXXE$JaL|pktb`w6f)%V0!-&0$C&useMV63RqjLU8M-l(>z zf1}2x{*79j`Zwxq>fd0#s6+i5%okRDwlCCY`>^V_CT_EbiMQLT*<ml?PFpp*Y|TKe zs5yaqY|YSb^ZgqG_Anl_Re#7<eZE(idBmP3K5DD}n63JJ#Q!Z)gPAGJzR_!I!~2*X z;bS~&^ZCY{&F35Qwt6ktnr+c;#>^LWdhxQ|h*#_;yq@H5*e%32ZS~!<)py%g-yK_h zckNcZXRGg_t$B`Y)jzgX|HM}PQ(N`VZ0gtKZ0gsP+tjbAPE1m)ca(UoP0gA*dj;3q zs@Y)AV)jdHJB8UVVP>dlwR>@!J&N0H)$g!XztdLzE?f1xZPo9wRlnb_g{i><b}b&X z=kbuegNN;AJYs7$W{UqihIQ18*{q{xGRdcR<g^f{cmDsHshP1ih%;-%TQO@3tNx;` zzDu_1EZdrM#a5kFTXoiK)!FpxeJb&mU5&TxUA$u-V!n?5cV-&z+00wBZ?nFd1Do~L zuubGQ;v>5oAKUf##BSjAcDZ8y&2qbmc!f>ho0T?wZ&us%y;)<^_hzl#jO*-f%pCc7 zZc;a_`sC%;b+g4*{Z?D`+icZuw^hHxR((FAj@)Ap<6c`e`|Ks$Z>#2jJ&gzL2|Q$L zhEZGf$86Ofw^g5QVg}V`o3QHhQCK5A!m7_UVb!1aYrbmmg3Z3XxoGcW>b^_&gU5K; zp2aKn9A35Qb92qsZ0mM2-mrV|rrn6Q>?XXM<nP%n#F-;zP~QVveGhH*J+jsJ*lxuq zHhpigjHtsrx5{nm->R^wf2-1_{;g`8`nPIq>ffrhseh}^R(;kJ^<~x*9>w$vt0w)z zE12!Ws@Z1G;&yuqci5Vt+gAM^TlM+6P`}Ss{eD~Z2W-_Jv{iq|R()#4|8c`Cx5jK{ zxiy|y&waWzVN?4S+Z6KY5mr7u<j9{(@)wi*r6hkj$!G4^R`u7D{EZ}k(>dMbY$f@- zw&vWk>+rr^j}Pnye4ON*Bsr%^&Y8`zy<L%6f1kNsX*2unYUlLh8k_#N=@<K?2h%Uy zi>VcBoW)Hx>%QIWoIc!Qt3Lf=Th;GK;+>gGRHw^U9ePAQ+uf#CSTnGFSThXR>NT9? zk0kk{N&Z-pKk3(mcC+o2P44Y!o7~$oHo3Rwll+Awe=*5lO7d5e{Iw*1J;~ol^0#fR zamUsgcWte4&(@rWw&p*wwe7L3ZBJ~rt<BkNTU&0A;R>65P+MuU4{F)q3w@heTbH?n z&$acoYBt!a*_`CJB>AmLep`~?ndEmR`K(8M^*q~J))Q9!e&@5M+5!6%4<`9THlJ&U zopXjq9IwXXjvwO*TQw(b)ts`m?W|uf%)GU8Hs7zEw~z2bX5CiQE+_dbN&ae*zn0{0 zCiz=Q{&teTljQF^&OWF;uvwGdD?$H<NKR{ECb^^%v(AWXPQDi=c8An(7cRHEaYd5D z_L0MOcdG3kTw^oCoqC)7bEm;p%|=@_n`~{{npykmPMbZ6+cTFcr^6n?Y_Azg*zOMB z3$xvw-Xy;-$?ta#_3kiV<g3oGtvVyN>WpTNzGJrX$DN}(6Sm^hw(88-sxzB8>de{7 zpLdSxEZB-K+g*6Y?#HW{qt2SG_@;AIXUk?k-PyLa|95QF+_yF7fvq_YZEbsGYui)1 z0iW4ydpBpZ?cH*l8T6hev2Q1FjlF<tGnWqGI{N@O+M~G1p2E%cG;XnHFg;YiR5=|< z4zosFIbHT5?oIOhlKlQ8e;~;p_G|x{SO3?;7wg<%-n+~fW|q5Sb}JsY8}Nk9n(i`p zVOwSj*At($xA2_3hv#j+e|Nzqc9%88w(7NH)93E8-Hcak&9-j$;Eg1I(^g+TqNe(8 z+v>YxtM9(8ItO+yK1}kDlKf+Pkem}+bDr9L_{{F-eMBm3>ffuhseiB9W}bUBHuK!8 zwW)uv&ZfTJ*Cy6N{d*0z>a$<^bnMvfUW?6k_gZaY_u6b?_u6f0-0QF#aks5)nKf$C z^Iorgg6XZeUZ;MK-jTD42kbS>+!0^KL-q<Dwl%|uJ%LAU)^TslZo!jw51vZ$r|lEs zGnr$aS;sZcoUM80ZOyY_uVB88IaQyp!@Zd83+rP0u<ESas<UCM&Zf<}?`_#y*S6h< zcWn0Ay?tAK4{Y^4v^D>ct-i;$`kvV8duprinN8oioZW}ZZTi+#`#n8sag9xK9bbQm zetw!TUx!<8W0J%7B3@6t*=B}1@*>Xcb*;9xZL_CvXA<wS`F>rutvWrn>h#)dSJ!6` zVb&16+VOzhfroAS*Nxb!KWeM~n7xa~ZTi=-zoMq<Pul9s+!1Hqx>>sw&)KR!Z>#=- zt@?|$>Mz-<zig{M+Z5`r`~6jFiEr3-c++meTXqYkNBkdH%GtB)@xFb64>Ie#s5^9= zdFzgBYS$gxs>wD{bBgzM$Q9%F**@Z|_kM*<uKq6%#Z~`)wc|^;#%8VeSx;=cfSEPC zh?zCqi5u)8+-SGsCc6W-+I+sx9I>tDAup`H<b~Cjx?%P0vemcS=JWj?TYY<N&C_SI z-TgsZeaS2I9k!Q<kJ#!vYOC*<t-j;7`cByDJ87%$l--4Albku5@86%d)r%f6&nBiv zn9ui@Y(C#7FXC)>f5p~p>wXWPTD)P`VQR(yYu1Ff>=wM6<m}n?#P@A#-#@SqF&|M! z+aB3d_%w;1*=@XsR?eo*Q{^@_o~p1raiu+ktL=7NV|QR?ioUJ5!B+i7TlJf4*7Q`f z-Hn+wwpD$$534WRhr2Le7wYqMSoPUHtol8+>i62J-)F0SzpeTMw(1Y(3jcrHQzLdA z@lm@8kJ-%o)MSz~WwQ^Snzl91jD3h_ZEZVev)xmRNqos}Bfe~_4j=uxk5HXeyA!Y3 zLwMb8#~Zee%eLK$cWl+)wN-!5Cic|6-Hi`y)u(sNpuR_T7e2LB|IDWT(~KMW)PK6% zrvB3vHuaybw5k7ewN3q}Yi#O2UGMj{s>Ka<9d5LnFdy;%;<aGr2rGv<!qj-W-9EwW z7sYk^`853^XCBipyos4FteQRc6z)&r12%o09<)_|D09>wc6^EWh`o$Q?FBq$FXC~V zxt^Y|srU4x%{rcDj+m_j&)Tf}={Z~Tu%5_KUwVYqmmXpD<$GcE<$K|7yke{Gs;zm} z>@K`%tM8VrzS}mnpWd<6ch^?mJzIVEZS_5{)%Va=-y^#VpC&nH_EaucpR?&zUv4vF zeTBV<EA1s*ZL^>1Yiwq#r%>#NA>3fAext4WO}6Sc+p6DUt3LZB>Zm^ZC9L|Let))F z+-29{ZkyWmJvQ~~`;(jjn;Gi|?GrqdSwC;}!;Y)(h^;wCZPgsJr|@JF=j-?Ac7}QD zr)|}r$sF}(9bY0oXD?&=#kN`_AK^vJN4OKSO?U{iO}HJe*d2J?X8+Z1*qUe4R^KgK zeYb7(-Lcho*Y3u9w)*bdn&-go!pFAyvgVjgeNS!mJ+tZiAZOF}LAg!e2NgDbA5_}( zeNb)F_d$(K-v{+cPJ=x~ywO&#CVLY%+l#oxUc$^BGtXn@4r@00g@<sLJ%yPs;;P?c ztA4Mo`hB+Q_uHyJV5|PH-(!&3AB@<Ic+^(?G5Y|I+syu8!q#llw(88-sxxb=&YZ0} z%<<*=Syi0{TXo2bIQ!tiirtP^ZPi(`RcGDqz#DcS-nLa|$5x$PTXptq)!DaIhp%G> z)j76R=fqZ>Q(JY;Y_@xtvwLv4O`V4oHuWD?+FiIdm;HaE&A85P!S(h6Zm{Y3kbOF! z{Wgi4>?zFl5g)~DA0Ef8wq|IvM{v8%_a8D-<oDukdjPYBh%2A(g*6Yg!uxp89>RPS z@`sarwlCx}Q&{Vruv;+eiFg-gJz-{fIBhfI!x_61&)S-Q&Sp&y7j4yFvQ>ZCR{a%Q z^;d1xU$a$z)9<mVI$O5tY}?uoJN7BwwI}hO%{m^kkG?|3YZM>Y?1P7gHv977kv)Qs z?N)qZ_ws&tl!!V5xV)JEsKRERN0l}`AJy7JxGu@BPx2d*eAXHD`TU4=hWY%6Il^7I z&F;qSb_eDoayl^|VYYk3Heqrfv4*hfv*xhs_uHyJV5|P1t@^AX@>PG-?{}&?W47vy z+Y5NYKE;zZpC3)xe10@-Q}5A?O^rvhHZwk&vq$i}-HPe)ULDh3ylfBPl_Y=F);w$W zKHjuh)1$2<e>=(FN%GkydTG4}b_+hVyYP|SjgRdPd}4RvQ(N<&+3mSpLxoNKhDw|I z4b?XF8)|IoH`LnHZ>Y1W-_Ypyo>iSDTXp#QecD&-hX%e5GfM+=geP&EJ%yPm;-i=z z;c-lla35x-@Cat6F!dUG>|We&4`4nD`GdCR8M5~={UV20!&s6}?}#gZBFUe&wcZ(< z^)<}e%-AqzGh@TN-GQkUHCa=`qOJLt>~_3rtNxm;`s=ppZ`i88X{-L0t@^vU?Eg4c zojqH1_HAZqIIvIgp*@L@>?wR~kKz-19J9@!j&C16vqyOUOF|KE#pQM{uC@noO_E=0 zGtc8Xn;9QB+C#W0$!9%LU-_&jto(MH??3La`Tk?}MdWm0KEmCYk1)B9du(zaGi$^( zKWht9`|+Ty`pgt@)gQK1f5cY(QCs!LY}KFidoowxDZ3I++thwMV=v-aTfOFN%{Fg0 zV)n&X>R2>kwh6N@A1~Prc-gMTD|QWDw>8g(t$8+W&9h}w`|-A|d3J2gvuiivJ-Z3- z+v<B@tM9S@zvFg%V)x)vdj+4_eE%8ddp~O|A^#cX3wL1ZhRJ`XCdse0JBhO|BBuv4 zpPZY+%om==&CY4Td_;a5W^G||pW*8;xz8|1Y`ce<BjVJ4hJF#>#$7i1=9zAL6EjET zY~fye8TZ*6xZhsD1NI^ww&(DOt@%eYmuUVmyA6-qnt#G>#*=nEp0XS9v|Wp5>^eM~ zIk%1J9rN#EdWW?xW-Y9XS;MQum+TF^Y?J%UicRh_>-H!nFScbJ&rml!j@e(~2~6*B zFW$5J@V?!T4{X&u_IsXd|D4#Z_%w6bJU+`@&c1p!m$`Humpg|#&sJp4F~hT!&Kbeg zj??$q8haeq+w^_5!KUxCjkdO>-&g5pQuUkdA<Q-rAI5AGR{b`65O><D-({<Qx2^g; zw(7He)S1Eq_8g{`;-%}D-eLB~vuqRjGk7e?A5ZcplKg4s%#+VHvF!q$&0MyI>8E(? zXYvZY$dk(k$XU#sTgFSy(OURAYV!SOS8TrjEOSR(eK&0N-OOCJi?=dI-)-lp{!Zo+ z)giA?f6rF@&^gWc$Zo;Mw)&pfn(fqP-Orxcth+I158`rr8duoexYF*!)pjecvAb}+ z-HaP-=4qsX<}XqGCVK*t7je}mFRc314Xb{et@@prbL*I|m6O}RY#;gbY3#A-)7Wd* zV(Lat9qzZQ@qo=b8ksM0D)5k9iH9@iPVtE2<#^QbV?1V`;Bk8!v(A|F5Kr2hc*@?w zv-UimvllR57iQ+`a3k?WTQe`&TH~@^iC64uylQLaHM;_@XU=Kn4f_-`UtwnE3u}$6 zC#;!wY+{YOHZ>aeY-%*_+spXCrf1`!y@-$OB}{MCFU{dIyPEgU=Ie+PdyX~8Wv!U+ zMZ5yDFT%>NP4erK{Kh1w$sQrU**R;t#b!;<wL7O9ci26+(;mcKw(5`<GxTBd!UMS9 zX1nM3I^wFy_Jy1wTQ!Gm^`dT}=D1x=e8R55lbLlp_S}@M`KO&zk7sPnFl)1)o}07l z@M11Eq;skQFWHrN+3v+FHuaucwN;<qv28P6w>9U6tvR=C)!(sIf7e$1JzMqnZPh=p zRsYad{UclTPi@sdv#I|iXH)-4xlR2i<i*U5n7sV_PpBK_^AqZZ`TT@A!ff}X!B%~? zFXT5R`K>lHKWVeuF&~ky89MB3+-<Ynlb$4>xeNJyN&aB=UZCa7@?^+nmM6oR&-LRG zdkT*_rxTCanqk~-!4o!fJ(;vw(-XEY<!7T@Ynip_^JLDZ&y#tZ?Vc>ys=sK{^U0D; zpC_yKAYQXob3Mt~uvK%@R<A8vHFxa>yk|G!{mii+4s6!(<j^^t_{bi_$96kDu{-do z-HOlbHr^LMXE)(;oBi{Ab>^};Tw^cdT6+oC*~_@mX13?4rTrY+QcFI^x}I;b`!VxH z&J1S0LO$y$<aZ_cz0MgUzt2`LYAL_`5Dz$Cy@s7Lfk%@3(IlT*g<g}HOZUj9uHvOf zc-lV3%o_0%JfB&=H$A^#GyC(4na^pqC3_n$JBQfwE165#?)g>6hw+-tyw9)OgLuOp z!kcy%-m-h}ZsyWD%o<|Odc1GX;RAafAKKIS$ezW=w)(Qps56OA?QVQ#_s6fsSxy@+ zcbwUpD(nVaX}989yAJb_pR<Ws!}M)pn=t#NsnMoyQ<JT}&9?fs*y>A<*j9b{URZrQ zZPg?%;-i?l;Tg<+4A0_TdmQ)K6PWoTNAaN~PTfMC5nFZ0Q@msuvwe64PdcXtPuaD2 z+Aha4b_J$ZY<q_19M9o-$4~HreTo<DL%d`kW9EoDTbMb*2YA)ybJLo=jyLUg%r=qV ziMKPCR^T1G2JhOMZO_(P_A{4gHu@FT!hB)Pc4TWUd|jB0ufyavv3*#xu`j~R^#c9E zE0}&^*75@Lg_m%p%|3Xc+8)Nt9XTVo)*i%l_7JYOyKsZugPSv7;QKGM*sYik)x5wy zc%dzG1+`!3betM5P%CnpaCeeVUBx56*Kzv1&}XYY^ToF6J7lXS>nYS^Jz;G-?*D^~ z*b5VxOGojfeSoJjm$&0-$H(xDO^p}kGv`!i!B%|HIY)RYb6G!Lc3gE<Y~`=oJ$TL5 zJnMEB-mtszW@i0;;Ds%l*<aYTHP4={`umx68~y@o`vCj1tREjbuD*Ov@zP;@Y^(2y zt-hz3qwkqb-xn)v`o36ckK^jh>ic3%X7zos)^Ym2SZCAs#d@2*FE-fpeX%jK`o7p? zt8c4wRI|-iopxJ&J2ID1??r0G8V51G^Xq-FH_7iy^2t+<j_->@_Bf`8;!%_Dg*C%y z=2ER|%vPLjqE{DY4PmW|HOR59DO>BBwbggdrpAl&nWOK5-A{ZmbM#%Z6<@a1cg0rU z)y&a%%~sz{TYa}|_1(@KeRpit-_2awi}!5B_cKTR16%cvouhe9Y|V3O_uw;|nlDw@ z!?@BO#ntv0uCbZ(rTQeF;~o21`He|_Q<C4BIj3#g><QeSxvU>|WY+D#OP!fZ4=`(p z`bU^G#BrR)tRdoj|0TAM_&6T0RevyZ8Q*_tD09?jow2RzkJzfu8luh|X3deqye~~U zuKH89>NAIOqW(<gs6XqRd2*-~b*k~A<Epb{tIl%fvOT<#IqIxB-cNkZ-o)#fbJTlj zBXg<hZ#zeQcWmYC+J~4PG4nCrx0&T7_C>@uG2aWT&WWu$r?%>x+2l6oZ0a<Z+sxZs zZBwVY#->hltxcWgI$L$>ZPjV8Rfh)od74{n)oD%g+w5iHotbmvxXYfv-Of?3p3K_M z&ApEA;XYfl_1k=I9<b-}VCJ0W9LlWy-#qI0I3Barm#_2tyqT}%=sW4S`cB#EJ8i4) zj7_Y0Hgj$T&t;Cji;k-=GpW9A6PlMZmmOoaDfC@+T=my%*3`V7Imh>#H!?^4ZO2uA z$5#E_%;im(H5BUaXO6xHj@OdI+LTk)kB@BiWxkks9iL=Y-<NaF;rlO_+o!l9b9pPS zwA(S;MEx^d<2Zd^u6JB@8f?{RbdKt<hWz|5H#<jlS{$d(%k+r)s?%YsPN#EJr_0tn z-Of>+9>-Ou-*MF$uvLeBQJ8<o`8ndFnRDZK%$~q}9Wys!z7A`K$;@T_c*>^s%hQ?l zx8Ij%GRJ<Ncbs}JFW9QTm|4g7<t1D7morEG6<hUJGnX9Twaig}J#%i0IK4Gz$u{OA zOrMu`Y-+!}n_1WSFYnpac;7kne3>4FI>)x^oY<;!nmOul43w{VUdcI!I<J)5%=HT2 z%g^&ljZK|bYBQ_OD|NQ&)H_FY8f?{RwwdRZ7F%^%ll(S&m3U|7+&J#CCvbOW?f+ML zY-+sHo4KqX_t}G(uVelLJdinN=6j0k@xE7voTJ%B9UsSIw)*n5@}n<bht+p7b6G#0 zvekDwvyS^KGnu3BZ06i9@j2%ZdxhRH=P+KfNAYsz=*vDW^j&ohGrqEBtInpaI$O5t zY-f%-J9aDaUFWFIp3OR5IkZ*h$X1=>%u(mWR-IGlsLq*9omVSt>bzQMQ|Hy{V*aZ& zHv9P1`ph}G!DfHI+L*blA2->9xH+@-^Q$eHwVz*QChe;nYkIZKIhvu<an<j#RlhrP z)bFuXzc+K#@5>zZnIr0}?|^fNy-JUWtNw_s`m9;;GUbffs!v|zA7b+45@vsO+Ht=B z>Wr;AvzepLoUJ<Z&N;;knM<1Svg4|=Vyn(-=BTq~tIm4nk{Y~WtInoffw$~xyqh_v z`g^wO?>nafAK0pMoaCP*`OF<_SN>TszlDAg=W|Q`=ZC&6d?;SlkC`<*h-;lstfkJT zW=o^3I{x`7QJrRQt2!;V>a;pvb=qvz>9keHKR;2YJIU{{nWcrgF+cTM2JCiBkBA@O zq0IWZY8iIC1CQ96ZQNF!30rk0ZPl5|9CfB0SDhJ~xmxCJ)mgArXVF%jrOZ)h*>Tlb zu~lc?R-Fx7bvBdyExVKWZsxK<?4Oe|*4nb~II$Lb$8kKwe1u2vk<FS~PHojWv#Il1 z&Zf?5<u)~5tFWo_TBSXKYi;VhR%feDy{$S8w(2z6s?%hv4(pFORj18X9ri_j{?|I} zQR3a1b)WlMkIgKv_1Xux&t~1P_1nz&+JH@;*XW`8rOfpjGliM!HF|`b@mP{SndDC; z`O``MOp-ruYt98*b1vGNbII16%eH1%u{Fc0t@+n%&Ae%={+6x!+qUZO*s8y4tNxy? z`un!(vrS>29NVgYVypgXl7D8`=W?%C<Z>Tmf9mnd*DGzdeVvbpH{%++9aAgf#9pU& zSan$2SF4W9tYKoWvwe68x7e)d^;VnQ*V}B>@3ebym)(cE?IGM_k7M$p{s1N~Jc#)i z&d<X(Va+pa&*Bk#1CQF8XUx_-leXrWvNg}Nt$Ai_%|qSjrFrIT&9j*OEwo|>FJ-<+ z?Dgf$Rm}DJioJkWGgngM^)-77uV=ozjhS12U#)D#o0%`}V)7KfG>Z8;+=lm(_<rU} zYQKJ9tNwB3sB_}{2I8mAnZsu`+rCkeS?hYE(x&Gd)i$-?sId=mt-XiqY-V|*(N>)% zTXmXk)oHO+r`1-SHd}Q%ZPn?rRj1ologQ0tdTrI|vsGs>^F{i<F=SKwjp5AN|8I<B zu4LVBj5~)J-<YtO>y61Ie=5nJc1}AvGq&o_+v>YutLCDunoG8}UA3A0jWwIxH`X)j z=jx3On|g0Bw|*WjDu2iB$Lyns58^$W8Q(Ze@{f}I<0Sv2nBSVqTrro+wU*oSxFU1q z7Ou>!*;=bJ>u0sKCbRZ!Yi;I=O<ZR)Z)?51h8yg4+-R@hCVLe(+e^5`Ud9Zn^;WP? zTHEYJ+-YmhE?a%OGspZrnPdLm%rSpo=9qu*|2K7qKyhYk8pl5pYKywV<Z@@YcY5ab zR8hMK1Y3nbG)YfrZaRb{P0}~%-DP*#U3LqBXhGd=!B!z!AP@)y0)apv5C{YUfoOq1 zAP@)y0)apv5C{Zf|IazkN6xM4%CFz={hsrl1H&-6(Czv%_crY|UbHn^%hq0&>^00i z;h)(J%ss&?m`Cs`UQg=uJ=HgDu9voK<*>KV!#brsn{`V2(ccf@1DhF3%%}da-y_%i zsB_jKhg#`4I_&qvb**)3lTkXeHS@WxJzm&4lS^BBys^nB-P&Z7?xMq-_x23+hv+cp zqfN$G7X3Tc9P5t$ZWgnLFhBWY{Wkeyg=poE6>ajz2BMWeHfSrKzL2B*;pmWGa$Wsp zTltmfkW;mlGZp<E*T-r$*T?Gi2yWP;n3=ThcdS3geu7zlY|duhv3Z+$#}@1YZrbc` zY%w~VPs{aw>TTCG|B9{oSKXsI*KEzXZfnjBTXSyOnsdw6oZGhM+_5$1uB|!uY|XhJ z{kwa7;Ceqkbo~+^+1I#ZpW|cu0<(vwj~Ca1Rp$}>fXNEy*@v%O=g%>6Lyz+BlKOp8 z=l;<1NDq%Z=Vg!Utn;$hW}TO;k!QYSKf&a^<XnQ)KbZ7$j-h@_opXHZAF-M3<*0pw zE7AIVep$7-{&LDL;hJ5>Gtv4w_Hx!<#&dQD&)X+>!9KuE`w%bMySQcVVRFOF8<^bS z9o)88@ru2Mc^-PW{*vdxTz|P~YtAiOb8g$3libjMf|(;&b23M;=G?cr{*r5<t~t3D ztT~Tt%}H*kGuO*wTXV8TsB6wsTXS9{{g+Aqm92TMZOwCIYo1$M^W53n_}<n$54Prf zv^TTtRZq0O7QO1Vx%X9H^!GEk-{xcWs^A{>^r~o|;UQZ&!}c5=i4HlVwsK1DQBK)b zPQ{+bReKfJZRIy?<ujko^E>5mEm%2R3vObvf|aviE1zqjPVLo_t^8$M`E6VIE4K2< zddgq3mA`H)pR<0--;VB~_G-u8#JhF}@7X7K-#)|#_7Uc}GJClGis!*xf5rX5<h^3n zVDes(70mjtPHonIbzy6sOI!0?*_!9t);u@1=DD>s&z-G#?rqKUU~8U7n|aEa%{=99 zn|aE8HuIGGZRRN#Z00E!ZRRNt*vwNNw3(+oWHV2B*k+#ch|N6ZQCstrY|X=P;jA>z zR8p@c^}4Nj8n)({v9<23t##*YtvhdP-Nh{X8z0B48@KEpykrmHWt;t#+jcKrvHS75 zt(*;8Ih(d}wru5W+sfIomBZX&9{Ip7;6wWe^9ViKZ^y3UW4npD7JAC~)UMz&dl;YF zBlyDBY?t;BzOsw>+8)4nw&uLIHRpp}$B*_*mi@+A=wteVd4FTi^6xirU-XZ&m@L(Q zT*qX|KdfTb4nD-JE&t&NGi#{x=Wom^|Na=WH@R;fmu#;8R!-`b=pS~eS8e4p_ft;8 z{ml5=jC(ZCtgU+&qF-oVO<OZ8+Gn_BpW`L_1TWjCc-2<Unys95TR9uHayD({Y}v}$ zwUx7HD`($U&Vj8Q_N@KBP|lI99G-`BC}N%mk7DkZ!})W6@B{TL_YB}`dkEho{kKW~ zoqLAqxwpxGo!PAWy4xo6b&pNv>t36CUl;5t%spYw4a_~VKCfO6+Us~E>1VyrU!z{K z8@OyQV{$`}^67i(uP6Q76YA=pi+-_+=j}DT5d8z^{kj<)W?PKb=j!WLw9fYRQuK=h zOs?`@ba30=#Vht6X1&m}jae^v2eaqkO}t@mVV;LN*I)BInCq{}4c46G25a5@=rBJs zsUGI1PY&}lw;bj_aeaY%Pwgf?vo+hf&6=+->?M3@v)9*G_9DKvTlg-i-zW74dzqd` zo1F0;dmi`N%r@Q^{bN7ok?(7~5Uu@=7j5#!2cr9!d3-Qh`yC&0U26^7>~Va=X6Erx zn>~(~Y|do7Y_rGlDO>B-Y~|OZ!<-GfN_{3e%sFeHQ=g0O>tOaAJ}zXBvqt!MDW92w zmA@1n@|SJpvmf<@{1sdItI;8UE&312-*jF1TekAIqeIS)t(@KHKX7K_dp2h_zHb-t zfjxl94SVUw<OUZo`wZ^I$95k+vAgl9-Gk4f!~Dz<?#-xQxvu%IZOwn<9?f}cYtB1c zbKcvU^TF1fk2Z5wSR<da!c4);Sz)GNY8CbnOs&E-xsSOjWQ95z6|zG81haPV86L1Z zc+ft^BT0QUsh8|)ddfEQRw_1UR;k*`uP60JQlGIor^>9YoCRAmG;PhiXe+a2U*UGr zzmoK?+86Y!CH?ERayIO9ydAC2=gN*ffOqXdyk`&L!)SdSs~p)2xMR~>Ikpe*iOo8d zQ=4@v%n?2o%u->F;7!cj!EJnLGkfLAZsBWt3E$XFd}}Y_2U~M;z9Ex2Co-EkC%SFs zoanKcbE4N~&WS#oIVbvU=A0<l%sElCnR8;mX3mL0n>i<jZ04L8wwZIHl=PRA{))X# zPu12uQ?}-**_x+rui=KRd1mZ3p0!snXQ4CE*P;n#3f8^MB>%{o6YL?F`zF{!=-J21 z_7PsSmBam^r-oVkDTi5~a+vigXUkR&`waCuW}m^VKf!vz%0IA`e`sqS?hif6>DcUh z;@DQsiLLxoyMZrk<zL#$zp|BoZ7cuAR{pK6{5xCu_cr-|$)aDhakssKd+a^jYaie~ zdk6R1ySQL);iA2b2kZ?zXm8>ndkqiU>$qfVp0cfZDz@gS+L~v|);u*^^RQ2y`3ud{ zu(vVi66%^~*48|8w&t0)HP52m#w}a(EZLf8+15Ptg?!CJU$Ev`wKWfGgu3QojbP2g zBUtnB2-ZB@6Rdg2daASbQ+?moJj@a5n&;5gx<|Iw?burP*w(sdS@yr2Th|Oex3%s? z^mAoi+T8b-8}~HvZPI_2^xuE$f0KRdf75L*W!ak^dl~oItox>r^cR!<fuw&h=^wHC zxOdcMFK<frDK6U=cq-|y*<`<|C;g42pR8~`todfvR{ny``fr*^ebLssEnDlhll~Q( zdEcxi{cB18x?Q4Y!`8anw$|OTm9uMW-920D?%T>au$9w^&aUyXeS=Tz2TWGjdmlb? z{T83w_xQ@LVzShqO<}TvH!=4FZ{a(;fw@1_nTOk>LABc^r`ltaQ|-0MsWMZzmz-+9 zt(*aS5c3E<!+6N9V4jD%)*7+-vpQ<?XO+Itqa6C4a+oPtIW=23bz3>i6nd01XES?s z-tNN-_BL+X2YAt@x7xC~UR|<Tv$|}vX0>gX@QPi*>q&jXE>q_m!)#iYa}3_YJP&5B z>W-~-cWtdpU+B@ghe`b?sdsGUAKT<r&+Gy|w~P3~*4{5|GOAZLvsbTeX0P7ZEqrS) z;X7M1-`k7$!5+Ym_F$I1?fKU8w$~=}ZJ)h``)&5}mixor$$ZQG!RjAM`iGPLQgjz{ zy)8#SqxWsaZs4jtho|fs=Ary&b<87}jJMnqOz+zndlb*wtofF#(8DZm=j{=^7#-$e z?$E=Y-Y(giXW1tEZQEwXw=1^RU9~mOnq9%`w&vNeHP5E4dA4lLvl|`e*>hd<?Aw~> zz}7s6w&ppqHBZOZJjb@?Ik7d*sjYd=Y|V3SYo4p<FweDpPyNO{-T2ln;yd>|VES~P zU5{BdnSHBIa?ew}C;AzGPWIa5Ocrcrp5%G>xK#0gJ%b1BS<I}VX9%;mVD>V}-sI;s zT(%D|xuItclN-E;r|dfBo=|UKo(FS%lIOw7WR76gnPiS&)|n(Xn7JnBZRVO>OzN$q zz7!qiT(%GBZ@Xt3uh=_y)!x8s_9kApxjxCYFaxzot_3s8<d#kLB)OrkeUTfieeK%X z*Pg9?9okKNWV5Hqj;(o)ZOwCHYo1eE^PJf&d~R!=D|-oF+nmSbjjfzpTR9K$d$#^6 zezf<q>|GZ96EnQ)whwV%^dDL0U4QhShH=3?^SEg1-l3$2K7Bv=r#0#$?kV9>TlZG7 z?EmP=dN4Buv*x=gTRk;<0oQG6?;7?jp0SnB^N>UKyE&V=-jNmR%=M0}U}k^Uv<LB` z&0gQN>;i7vJ$S{|oU1n3@78Rx->uu4bHmo0o3`fMvNh+nJ%o2`&ADr9&OKXm?%SI4 zz}B1{TRF$Ja!zcmduo^QMbdwn^j{_Y*Gd1K-OIiAw$9<fuHi>}Hhc>g&zZHRx?N|# zQ`{5IpPVW75KL`~Jp?y!(VoHVC)AsG*j~gV(a+U0YA@kZ^s^RbZQc9q60>&5QN8MV zhU=~?pS44e^2wD${;aM1x#*BTZ!3QxI#WJbVO`~OPw)|5wmZ0OALAAK6t72TnrFk- zJe$#Bo-JGRY`f<Q@7OnZ*S^4ew&vWowbp@sjt_0k#;oBSG#k%@wJ)9r(>rx$v!^NU z5A`-?y<qk<#d^V8n3;mrf1C8**=yAA?aeHEpV>{^ZF3Iqd+aORYm@!H&u0Di{Wj~r zFW9HJXfyBo0lR|-ZT9zm$Y$pE!}cK_vD<jmW{>Ynb_<v7WjvMCYxWZLy1k7Xw(@6e z<<Hv6Ur6fBq|RA{^W33_wS$$z{ZHop;3Mj*(fYi7zh<kx?w&`y;d+KQUBAa$_5)__ zka>eyJNOpw+9!C=KE=$Wo~}#Gdh#>ncWljbY`5`Q(tn=xUnKoxg&g%WN625s%n_{m zUDCrILjM|d_7Hlu@S{!Mhs@^8K6KlwxX&j4L%&V_heGr-xoDIBVZc4xc+gh<kgfb- zTlppX2$$^+uGq)8YAdI1FXM*Y#xv1jo>^P-%(-V9&)Y|M!PY!YTk|YM>-UI1u!hbm zQ$K6uXZV48g7>L&PdLv4X1!qU`>-CJJ>m`5iTbeV`U&2$Pw}pMX7HY^9M*VR_rNCO zLnrA!PWs7x>L)i?{TJ>j;7hxRuj~PQZO`Dlr2jtYe@OZt?NXL~>`B~fm#O#J72I!= z|B>}HTXus7?OQx#v*yQPn>9bOM%W9td?YuxipiCqYX+VND}Ty83%F*tFxQ@PX6<h3 zbI~DZ-c}CxhkoTWZRIT5J(%aAhj~A?ZOyr2D}U8i&YG>9b(?egxM3@2(^meL-HUf^ z<?q?b-?x>2U@QO7R{oK#{En^sV_W%W@q5%?bnm&%K0aPV7nks*%{m`%+_Q{tlm5G; z|NdKljk)!`@h>x3R%7m9)~YdwTqLu`9KqMPkn|Um{(+=_FzFwO{#lu$?l0p~^sjBq zbLIc4{EB-{a5cKvkL%HY);taS5Hq*#{qqr?wL5qr>1ifCi%Cx_y2$=&%n@?d@ru2H zSEGMD$7{Ccq%ZVuV)}v)@V2d-9a}lON&lWrt;Qb0z06)?55aSoJp}9CV_R#T*vwKp zwYAony^POoX0Kh?EqrM&;VZj|*-uz&5#QMJ_|{&)57EEe<42o6r!)8T;cj~v_t?~? zdu{%lE<`J5x@aqBz&*+tw3RbtlQ+%tFsE`#(ZAf_vaQTY^sno<YVYBx=s&OGn!SeW zHfJ*3u$S?Sy@+S+7M`;g@Vwo`JkLLN(>xF6`ZV_k4`c2RCU2Vcf_pLR1^3~0^e>Ni z#r1ByZjay%TREGy_O)fN;cZ*{+Ob(@de>&I={;Nf+PB%q^nu;Phc^43KC-p1lW6^O zJ$-85<Fjb}Gc|o~_v5Ri|2pZvN&0V-{s;GH=EraSpR#ZLpEwtto4!7L>T?h0@rmcE z|Gb3@Hs|rFXmcK)hLWD)q-P}Q8MTk-uh`7;sT%zYvwWJeIgd{@n>~H1+syc>VVCe+ z^v}wfcU?IPwsM-bau#jnv~1<HqeIS$>&jWRm9u6mXWdrLhOL}!yASW!!+6(L&YpdV z4{haeE;{F5dT__?#mBZX&!WSe=dNqc3tRV+8*+5-jr%#XPq+3AzKbqi<NN4eHN%7J z{g^WipAY3M`^*~Qb6^(J7u>?k6iohS?g=LUb0J#!pNrAT|2*J2y`Kkd<qt*wto&hH z`6XNV^gZQQqC<W)I^<8euKb#<{CafAC+lhcIh%~n^S0Jnh%V~hroDuDgnP;Uyqxs6 zlm3;Ye?7XeNdJc2!khL1-m*{dw!MpY?0w8b>lQQv_XM;4=fmh<XYi4&wL0!m=5h4T zReYAz&+SX<7xp#gdC0%PJf7CQwYBbD(sOT9`}|-l^U)@=-eWJ}UYneHpG|hX-zKL% z5S{VA`e3xapQ#V=SBjiNs1Ms@)JOOo%Dg^mvrfIl@7?D0vaNcB-)YF}Ra^Bbe#b7a z*KFn2v+Vo4-mqDxKEuxx<n>v*oBA9-vz*uG?E~ry{LEKgZ`zzqeUYDS$?Gj!^Kf22 z<aN#~m>KJBe&!{wuh{Be&9eTyzGkbwo@IZ`>l?P}oBTa)Uf;4+-_Ek1^7@Xg`fl=Z z*|SHe?<Z!T`kcu)gZg3OBb(Xl9X^-y{9}88`U(G@$?K<fAN4c7F6Q-fyF~qh?^W~q zrQJjQihqyg^=n)GH+)~5*Kcjr?|6UKynb)1{=j=`=JiLLef>4#SL<E>Yqxz!owffy zuXA3(o7CCEKjig(Tm1#z*C($RZS@cEzASlt&{qEt@1K#^hi&zb@csvRebiQeiPxRa z>t$R06<$v~uUBpLPw{%tdA(+<zs~FY=JkfH{uy3(HLuUw>gSC9F|W_t^!{~$*Eh`T zO}j*Wk=L!u>n&UTOT6w_USGD=-{v)>^7@Lc{#9Q0C$F#B>R;#eT=M#ct^Q43zay`2 z+3MfsH5&5zj;;P(e&0T?@7e0#=XbO7`hl(fLw+YVuOHd!@9=wxdHvW{{|Uc8me)^h z^`G&3K6(AzR{sURkCE3eZS`OA^Y?lE+E)J!KR=z<Z*BG8@$;;C{oYpp13!<L*B@>A zzhqf9;rf?ud!Bj^KlhW@du?i8`V#ls%=M+f&w1qiMO*y?i3e@=^ks<upFZy&j_%^@ zzl?nQ+VW*Ix=VBNn9Tdjw(={9tI=I#f0^R{=g9kOw)*Rd8_`|N`(=i|*UtNAZS~J3 z=3La%#Xi0)@b{8=f74d~V&YbG7w7b4iNCAL`<HF?w-c{Khx}Fko+9sGv(>+zcq2OG zZ}Q)tdH<HJ{_Vs&_8s+I{`(>C-?P=fpZLH&p?=8sk$L}-t^Q8pWBZ&s_k7O#Pi=a? zobk0duhSQNL;Zr!(Y$_XEB`9-wXOMePu_oPt6$etm+x)O^N?j<^ZrMhjIXpdT>si_ zbMIFkp)U8@WPk0;vVY3^`)&0U5*KaO{W_3k|D5*^+BejPvg}{-`mn8>k;J36)-CZi zig|xIT7OsnwUTB3n%Aq*U02knvh3gTdM*07^6Odl?|Hppt3H!>)@H9?=MvA`T6clB zvdeRtwsIB|w`}DsC0>s1;=I4Mv+O_eoE2L+tBKca<*X;(uy3euX4!w{Ia{`JwiEBz z%Gpi47aiu=&$9o@a}I3f940=pmD5RlY-^qqzqfmaPi^I#B|f*6bCH<yozo1;x$=8z zE9cr)4%hx$J@T!soV&#L(P3W?elKI?Jlfpb;Q9YJr_pVb)8JaD%e~RcY4AL}=P&m) z`fcWF6#SmBsu!cX1~8BCo}{V|Mu+;4-xE{y;pk8w@q03=J{leBCBG-2>gDKAulPOk zRIl2*c*^f(rg|;<85xawd`}t5S%b~%{cE~ezcJ(YE>V5<+xwU_=Dz(qs4*Y?cLVe+ zByL9cuzq7Pz6KOAS)&!*UBOF!O()ftzrF5LqwUvLQhg=5YXGnMHI7tYi|*>h>&aRh z(ckY--%Pv}{bGdrwtvS{IrRNaAM1O}89l?HXD|9kvK#yHXHn?N8VAwOkMUvBa}@m( owMHi~eaiglj`~UB)9Atw^|SbQ_#yv1`Z;IQxJY^~qkp~rf85g^<p2Nx literal 0 HcmV?d00001 diff --git a/rce/rcecalib/server/TurboDaqFile.cc b/rce/rcecalib/server/TurboDaqFile.cc new file mode 100644 index 00000000..20bdc554 --- /dev/null +++ b/rce/rcecalib/server/TurboDaqFile.cc @@ -0,0 +1,914 @@ +#include "TurboDaqFile.hh" +#include <sstream> +#include <string> +#include <vector> +#include <iostream> +#include <typeinfo> +#include <fstream> +#include "PixelModuleConfig.hh" +#include "rcecalib/util/exceptions.hh" +#include <sys/stat.h> +typedef unsigned int uint; + +const int numberofcolumns = 18; // number of columns read in the readoutenable, pream, strobe and hitbus config file +const int numberofrows = 160; // number of rows read in the tdacs and fdacs config file +const int nofchip = 16; // number of chips per module + +void TurboDaqFile::dump(const ipc::PixelModuleConfig &config) +{ + std::cout<<"config.maskEnableFEConfig "<<config.maskEnableFEConfig<<std::endl; + std::cout<<"config.maskEnableFEScan "<<config.maskEnableFEScan<<std::endl; + std::cout<<"config.maskEnableFEDacs "<<config.maskEnableFEDacs<<std::endl; + std::cout<<"config.feFlavour "<<(unsigned)config.feFlavour<<std::endl; + std::cout<<"config.mccFlavour "<<(unsigned)config.mccFlavour<<std::endl; + for(int i=0;i<ipc::IPC_N_PIXEL_FE_CHIPS;i++){ + std::cout<<"Chip "<<i<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEIndex "<<(unsigned) config.FEConfig[i].FEIndex<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.latency "<<(unsigned) config.FEConfig[i].FEGlobal.latency<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.dacIVDD2 "<<(unsigned) config.FEConfig[i].FEGlobal.dacIVDD2<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.dacIP2 "<<(unsigned) config.FEConfig[i].FEGlobal.dacIP2<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.dacID "<<(unsigned) config.FEConfig[i].FEGlobal.dacID<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.dacIP "<<(unsigned) config.FEConfig[i].FEGlobal.dacIP<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.dacITRIMTH "<<(unsigned) config.FEConfig[i].FEGlobal.dacITRIMTH<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.dacIF "<<(unsigned)config.FEConfig[i].FEGlobal.dacIF <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.dacITH1 "<<(unsigned) config.FEConfig[i].FEGlobal.dacITH1<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.dacITH2 "<<(unsigned)config.FEConfig[i].FEGlobal.dacITH2 <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.dacIL "<<(unsigned) config.FEConfig[i].FEGlobal.dacIL<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.dacIL2 "<<(unsigned) config.FEConfig[i].FEGlobal.dacIL2<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.dacITRIMIF "<<(unsigned) config.FEConfig[i].FEGlobal.dacITRIMIF<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.dacSpare "<<(unsigned) config.FEConfig[i].FEGlobal.dacSpare<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.threshTOTMinimum "<<(unsigned) config.FEConfig[i].FEGlobal.threshTOTMinimum<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.threshTOTDouble "<<(unsigned) config.FEConfig[i].FEGlobal.threshTOTDouble<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.hitbusScaler "<<(unsigned) config.FEConfig[i].FEGlobal.hitbusScaler<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.capMeasure "<<(unsigned) config.FEConfig[i].FEGlobal.capMeasure<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.gdac "<<(unsigned)config.FEConfig[i].FEGlobal.gdac <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.selfWidth "<<(unsigned) config.FEConfig[i].FEGlobal.selfWidth<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.selfLatency "<<(unsigned)config.FEConfig[i].FEGlobal.selfLatency <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.muxTestPixel "<<(unsigned) config.FEConfig[i].FEGlobal.muxTestPixel<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.aregTrim "<<(unsigned) config.FEConfig[i].FEGlobal.aregTrim<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.aregMeas "<<(unsigned)config.FEConfig[i].FEGlobal.aregMeas <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.dregTrim "<<(unsigned) config.FEConfig[i].FEGlobal.dregTrim<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.dregMeas "<<(unsigned)config.FEConfig[i].FEGlobal.dregMeas <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.parity "<<(unsigned)config.FEConfig[i].FEGlobal.parity <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.dacMonLeakADC "<<(unsigned) config.FEConfig[i].FEGlobal.dacMonLeakADC<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.dacVCAL "<<(unsigned) config.FEConfig[i].FEGlobal.dacVCAL<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.widthSelfTrigger "<<(unsigned) config.FEConfig[i].FEGlobal.widthSelfTrigger<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.muxDO "<<(unsigned) config.FEConfig[i].FEGlobal.muxDO<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.muxMonHit "<<(unsigned)config.FEConfig[i].FEGlobal.muxMonHit <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.muxEOC "<<(unsigned) config.FEConfig[i].FEGlobal.muxEOC<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.frequencyCEU "<<(unsigned) config.FEConfig[i].FEGlobal.frequencyCEU<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.modeTOTThresh "<<(unsigned) config.FEConfig[i].FEGlobal.modeTOTThresh<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableTimestamp "<<(unsigned) config.FEConfig[i].FEGlobal.enableTimestamp<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableSelfTrigger "<<(unsigned) config.FEConfig[i].FEGlobal.enableSelfTrigger<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableHitParity "<<(unsigned) config.FEConfig[i].FEGlobal.enableHitParity<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.monMonLeakADC "<<(unsigned)config.FEConfig[i].FEGlobal.monMonLeakADC <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.monADCRef "<<(unsigned)config.FEConfig[i].FEGlobal.monADCRef <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableMonLeak "<<(unsigned)config.FEConfig[i].FEGlobal.enableMonLeak <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.statusMonLeak "<<(unsigned)config.FEConfig[i].FEGlobal.statusMonLeak <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableCapTest "<<(unsigned) config.FEConfig[i].FEGlobal.enableCapTest<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableBuffer "<<(unsigned)config.FEConfig[i].FEGlobal.enableBuffer <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableVcalMeasure "<<(unsigned) config.FEConfig[i].FEGlobal.enableVcalMeasure<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableLeakMeasure "<<(unsigned) config.FEConfig[i].FEGlobal.enableLeakMeasure<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableBufferBoost "<<(unsigned)config.FEConfig[i].FEGlobal.enableBufferBoost <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableCP8 "<<(unsigned)config.FEConfig[i].FEGlobal.enableCP8 <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.monIVDD2 "<<(unsigned) config.FEConfig[i].FEGlobal.monIVDD2<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.monID "<<(unsigned)config.FEConfig[i].FEGlobal.monID <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableCP7 "<<(unsigned)config.FEConfig[i].FEGlobal.enableCP7 <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.monIP2 "<<(unsigned)config.FEConfig[i].FEGlobal.monIP2 <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.monIP "<<(unsigned) config.FEConfig[i].FEGlobal.monIP<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableCP6 "<<(unsigned)config.FEConfig[i].FEGlobal.enableCP6 <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.monITRIMTH "<<(unsigned)config.FEConfig[i].FEGlobal.monITRIMTH <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.monIF "<<(unsigned) config.FEConfig[i].FEGlobal.monIF<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableCP5 "<<(unsigned)config.FEConfig[i].FEGlobal.enableCP5 <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.monITRIMIF "<<(unsigned) config.FEConfig[i].FEGlobal.monITRIMIF<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.monVCAL "<<(unsigned)config.FEConfig[i].FEGlobal.monVCAL <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableCP4 "<<(unsigned)config.FEConfig[i].FEGlobal.enableCP4 <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableCinjHigh "<<(unsigned)config.FEConfig[i].FEGlobal.enableCinjHigh <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableExternal "<<(unsigned)config.FEConfig[i].FEGlobal.enableExternal <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableTestAnalogRef "<<(unsigned) config.FEConfig[i].FEGlobal.enableTestAnalogRef<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableDigital "<<(unsigned)config.FEConfig[i].FEGlobal.enableDigital <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableCP3 "<<(unsigned)config.FEConfig[i].FEGlobal.enableCP3 <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.monITH1 "<<(unsigned) config.FEConfig[i].FEGlobal.monITH1<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.monITH2 "<<(unsigned) config.FEConfig[i].FEGlobal.monITH2<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableCP2 "<<(unsigned)config.FEConfig[i].FEGlobal.enableCP2 <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.monIL "<<(unsigned) config.FEConfig[i].FEGlobal.monIL<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.monIL2 "<<(unsigned)config.FEConfig[i].FEGlobal.monIL2 <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableCP1 "<<(unsigned)config.FEConfig[i].FEGlobal.enableCP1 <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableCP0 "<<(unsigned)config.FEConfig[i].FEGlobal.enableCP0 <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableHitbus "<<(unsigned)config.FEConfig[i].FEGlobal.enableHitbus <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.monSpare "<<(unsigned)config.FEConfig[i].FEGlobal.monSpare <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableAregMeas "<<(unsigned)config.FEConfig[i].FEGlobal.enableAregMeas <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableAreg "<<(unsigned)config.FEConfig[i].FEGlobal.enableAreg <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableLvdsRegMeas "<<(unsigned)config.FEConfig[i].FEGlobal.enableLvdsRegMeas <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableDregMeas "<<(unsigned) config.FEConfig[i].FEGlobal.enableDregMeas<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableTune "<<(unsigned)config.FEConfig[i].FEGlobal.enableTune <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableBiasComp "<<(unsigned) config.FEConfig[i].FEGlobal.enableBiasComp<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEGlobal.enableIpMonitor "<<(unsigned) config.FEConfig[i].FEGlobal.enableIpMonitor<<std::endl; + for (int j=0;j<5;j++){ + for (int k=0;k<ipc::IPC_N_PIXEL_COLUMNS;k++){ + std::cout<<"config.FEConfig["<<i<<"].FEMasks.maskEnable["<<j<<"]["<<k<<"]"<< config.FEConfig[i].FEMasks.maskEnable[j][k]<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEMasks.maskSelect["<<j<<"]["<<k<<"] "<< config.FEConfig[i].FEMasks.maskSelect[j][k]<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEMasks.maskPreamp["<<j<<"]["<<k<<"] "<< config.FEConfig[i].FEMasks.maskPreamp[j][k]<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FEMasks.maskHitbus["<<j<<"]["<<k<<"] "<<config.FEConfig[i].FEMasks.maskHitbus[j][k] <<std::endl; + } + } + for (int j=0;j<ipc::IPC_N_PIXEL_ROWS;j++){ + for (int k=0;k<ipc::IPC_N_PIXEL_COLUMNS;k++){ + std::cout<<"config.FEConfig["<<i<<"].FETrims.dacThresholdTrim["<<j<<"]["<<k<<"] "<< (unsigned)config.FEConfig[i].FETrims.dacThresholdTrim[j][k]<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FETrims.dacFeedbackTrim["<<j<<"]["<<k<<"] "<< (unsigned)config.FEConfig[i].FETrims.dacFeedbackTrim[j][k]<<std::endl; + } + } + std::cout<<"config.FEConfig["<<i<<"].FECalib.cinjLo "<<config.FEConfig[i].FECalib.cinjLo <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FECalib.cinjHi "<< config.FEConfig[i].FECalib.cinjHi<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FECalib.vcalCoeff[0] "<<config.FEConfig[i].FECalib.vcalCoeff[0] <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FECalib.vcalCoeff[1] "<< config.FEConfig[i].FECalib.vcalCoeff[1]<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FECalib.vcalCoeff[2] "<< config.FEConfig[i].FECalib.vcalCoeff[2]<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FECalib.vcalCoeff[3] "<< config.FEConfig[i].FECalib.vcalCoeff[3]<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FECalib.chargeCoeffClo "<< config.FEConfig[i].FECalib.chargeCoeffClo<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FECalib.chargeCoeffChi "<<config.FEConfig[i].FECalib.chargeCoeffChi <<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FECalib.chargeOffsetClo "<< config.FEConfig[i].FECalib.chargeOffsetClo<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FECalib.chargeOffsetChi "<< config.FEConfig[i].FECalib.chargeOffsetChi<<std::endl; + std::cout<<"config.FEConfig["<<i<<"].FECalib.monleakCoeff "<<config.FEConfig[i].FECalib.monleakCoeff <<std::endl; + } + std::cout<<"config.MCCRegisters.regCSR "<<config.MCCRegisters.regCSR <<std::endl; + std::cout<<"config.MCCRegisters.regLV1 "<<config.MCCRegisters.regLV1 <<std::endl; + std::cout<<"config.MCCRegisters.regFEEN "<<config.MCCRegisters.regFEEN <<std::endl; + std::cout<<"config.MCCRegisters.regWFE "<<config.MCCRegisters.regWFE <<std::endl; + std::cout<<"config.MCCRegisters.regWMCC "<< config.MCCRegisters.regWMCC<<std::endl; + std::cout<<"config.MCCRegisters.regCNT "<<config.MCCRegisters.regCNT <<std::endl; + std::cout<<"config.MCCRegisters.regCAL "<< config.MCCRegisters.regCAL<<std::endl; + std::cout<<"config.MCCRegisters.regPEF "<<config.MCCRegisters.regPEF <<std::endl; + std::cout<<"config.MCCRegisters.regWBITD "<< config.MCCRegisters.regWBITD<<std::endl; + std::cout<<"config.MCCRegisters.regWRECD "<<config.MCCRegisters.regWRECD <<std::endl; + std::cout<<"config.MCCRegisters.regSBSR "<<config.MCCRegisters.regSBSR <<std::endl; + +} + + +void TurboDaqFile::getLineDos(std::ifstream& is, std::string& str){ + bool readline = false; + while(readline != true){ + if(!is.good()){ + std::ostringstream errorstring; + std::cout << "Error TurboDaqFile::getLineDos: not good file status" << std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + std::getline(is,str); + //std::cout<<str<<std::endl; + if(str.c_str()[str.size()-1] == '\r') + str.erase(str.size()-1, 1); + std::stringstream s(str); + std::string field; + s >> field; + if(field != "//"){ + readline = true; + } + } + // cout << str.c_str() << endl; +} + +int TurboDaqFile::columnPairMaskDecode(int mask, int columnPairNumber){ + + switch(columnPairNumber){ + case 0: + return ((mask & 0x001)>>0); + break; + case 1: + return ((mask & 0x002)>>1); + break; + case 2: + return ((mask & 0x004)>>2); + break; + case 3: + return ((mask & 0x008)>>3); + break; + case 4: + return ((mask & 0x010)>>4); + break; + case 5: + return ((mask & 0x020)>>5); + break; + case 6: + return ((mask & 0x040)>>6); + break; + case 7: + return ((mask & 0x080)>>7); + break; + case 8: + return ((mask & 0x100)>>8); + break; + default: + std::stringstream a; + a << "Request for decoding column pair number illegal in TurboDaqFile::columnPairMaskDecode. Mask value: " << mask; + a << "Column Pair value: " << columnPairNumber << std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + return 1; +} + +void TurboDaqFile::intMaskFileDecode(CORBA::Octet arr[][ipc::IPC_N_PIXEL_COLUMNS], int valflag, std::ifstream* file){ + if(valflag == 128){ // Turbo Daq alternative file found + int j; + for(j = 0; j < numberofrows; j++){ + std::string readstring; + getLineDos(*file,readstring); + std::stringstream a(readstring); + int ncols; + for(ncols = 0; ncols < numberofcolumns; ncols++){ + int val; + a>> val; + arr[j][ncols]=val; + } + } + } + else{ + for(int j = 0; j < numberofrows; j++){ + for(int ncols = 0; ncols < numberofcolumns; ncols++){ + arr[j][ncols]=valflag; + } + } + } +} + +void TurboDaqFile::boolMaskFileDecode(CORBA::ULong arr[][ipc::IPC_N_PIXEL_COLUMNS] , int valflag, std::ifstream* file){ + if(valflag == 0) { // Turbo Daq alternative file found + for(int j = 0; j < numberofcolumns; j++){ + std::string readstring; + getLineDos(*file,readstring); + std::stringstream a(readstring); + unsigned column; + a>>std::dec>>column; + for(int nrows = 0; nrows <5; nrows++){ + unsigned columnmask; + a >> std::hex >>columnmask; + arr[4-nrows][column]=columnmask; + } + } + } + else{ + unsigned val; + if(valflag == 1)val=0; // TurboDaq all off found + else if(valflag == 2)val=0xffffffff; // TurboDaq all on found + else{ + std::stringstream a; + a << "TurboDaqFile::intMaskFileDecode: Turbo daq code not correct (0, 1 or 2 allowed) " << valflag; + throw rcecalib::Config_File_Error(ERS_HERE); + } + for(int j = 0; j < numberofcolumns; j++){ + for(int nrows = 0; nrows < 5; nrows++){ + arr[nrows][j]=val; + } + } + } +} + + +void TurboDaqFile::openTurboDaqFiles(std::string filename){ + m_moduleCfgFile=new std::ifstream(filename.c_str()); + m_moduleCfgFilePath = filename; + if(!m_moduleCfgFile->good()){ + throw rcecalib::Config_File_Error(ERS_HERE); + } +} + +void TurboDaqFile::readModuleConfig(ipc::PixelModuleConfig* mod, std::string namefile){ + //std::cout<<namefile<<std::endl; + + std::string readstring; + std::stringstream modstream; + int modrunnint; + //clear structure + char* ccfg=(char*)mod; + for (unsigned int i=0;i<sizeof(ipc::PixelModuleConfig);i++)ccfg[i]=0; + openTurboDaqFiles(namefile); + std::string readString; + getLineDos(*m_moduleCfgFile,readString); + getLineDos(*m_moduleCfgFile,readString); + getLineDos(*m_moduleCfgFile,readString); + getLineDos(*m_moduleCfgFile,readString); + + if(readString == "1"){ // module + } + else if(readString == "0"){ // single chip + // readSingleChipConfig(m_rootRecord); + std::cout<<"Single Chip assembly record, not implemented"<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + else throw rcecalib::Config_File_Error(ERS_HERE); + + getLineDos(*m_moduleCfgFile, readstring); + getLineDos(*m_moduleCfgFile, readstring); // here we read the MCC type + modstream.str(readstring); + modstream >> modrunnint; modstream.clear(); + mod->mccFlavour=modrunnint; + // MCC + //mod->MCCRegisters.regFEEN=0xffff; + + getLineDos(*m_moduleCfgFile, readstring); + getLineDos(*m_moduleCfgFile, readstring); // here we read the FE type + modstream.str(readstring); + modstream >> modrunnint; modstream.clear(); + mod->feFlavour=modrunnint; + int feflavour=modrunnint; + + // variables used to temporary store the information from config file + std::vector<std::string> rmname; rmname.resize(nofchip); + std::vector<std::string> smname; smname.resize(nofchip); + std::vector<std::string> pkname; pkname.resize(nofchip); + std::vector<std::string> hmname; hmname.resize(nofchip); + std::vector<std::string> tdname; tdname.resize(nofchip); + std::vector<std::string> fdname; fdname.resize(nofchip); + + + int runnInt; + std::string runString; + std::stringstream a(readstring); // Chip 0 geographical address (0-15) + + // scan the config file + for(int i = 0; i < nofchip; i++){ + + for(int j = 0; j < 4; j++) getLineDos(*m_moduleCfgFile,readstring); + + getLineDos(*m_moduleCfgFile,readstring); + a.str(readstring); + a>>runnInt; a.clear(); + //mod->FEConfig[number].FECommand.address=runnInt; + mod->FEConfig[i].FEIndex=runnInt; + mod->FEConfig[i].FEGlobal.latency=255; + mod->FEConfig[i].FEGlobal.frequencyCEU=2; + + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 global configuration enable (0 = off, 1 = on) + a.str(readstring); + a>>runnInt; a.clear(); + mod->maskEnableFEConfig &= (~(0x1<<i)); mod->maskEnableFEConfig |= (runnInt<<i); + + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 global scan/readout enable (0 = off, 1 = on) + a.str(readstring); + a>>runnInt; a.clear(); + mod->maskEnableFEScan &= (~(0x1<<i)); mod->maskEnableFEScan |= (runnInt<<i); + + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 DACs enable (0 = off, 1 = on) + a.str(readstring); + a>>runnInt; a.clear(); + mod->maskEnableFEDacs &= (~(0x1<<i)); mod->maskEnableFEDacs |= (runnInt<<i); + + if(feflavour == 1){ + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 Global Threshold DAC + a.str(readstring); + a>>runnInt; a.clear(); + mod->FEConfig[i].FEGlobal.gdac=runnInt; + } + + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 IVDD2 DAC + a.str(readstring); + a>>runnInt; a.clear(); + mod->FEConfig[i].FEGlobal.dacIVDD2=runnInt; + + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 ID DAC + a.str(readstring); + a>>runnInt; a.clear(); + mod->FEConfig[i].FEGlobal.dacID=runnInt; + + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 IP2 DAC + a.str(readstring); + a>>runnInt; a.clear(); + mod->FEConfig[i].FEGlobal.dacIP2=runnInt; + + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 IP DAC + a.str(readstring); + a>>runnInt; a.clear(); + mod->FEConfig[i].FEGlobal.dacIP=runnInt; + + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 TRIMT DAC + a.str(readstring); + a>>runnInt; a.clear(); + mod->FEConfig[i].FEGlobal.dacITRIMTH =runnInt; + + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 IF DAC + a.str(readstring); + a>>runnInt; a.clear(); + mod->FEConfig[i].FEGlobal.dacIF=runnInt; + + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 TRIMF DAC + a.str(readstring); + a>>runnInt; a.clear(); + mod->FEConfig[i].FEGlobal.dacITRIMIF=runnInt; + + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 ITH1 DAC + a.str(readstring); + a>>runnInt; a.clear(); + mod->FEConfig[i].FEGlobal.dacITH1=runnInt; + + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 ITH2 DAC + a.str(readstring); + a>>runnInt; a.clear(); + mod->FEConfig[i].FEGlobal.dacITH2=runnInt; + + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 IL DAC + a.str(readstring); + a>>runnInt; a.clear(); + mod->FEConfig[i].FEGlobal.dacIL=runnInt; + + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 IL2 DAC + a.str(readstring); + a>>runnInt; a.clear(); + mod->FEConfig[i].FEGlobal.dacIL2=runnInt; + + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 column-pair mask parameter + a.str(readstring); + a>>runnInt; a.clear(); + mod->FEConfig[i].FEGlobal.enableCP0= columnPairMaskDecode(runnInt,0); + mod->FEConfig[i].FEGlobal.enableCP1= columnPairMaskDecode(runnInt,1); + mod->FEConfig[i].FEGlobal.enableCP2= columnPairMaskDecode(runnInt,2); + mod->FEConfig[i].FEGlobal.enableCP3= columnPairMaskDecode(runnInt,3); + mod->FEConfig[i].FEGlobal.enableCP4= columnPairMaskDecode(runnInt,4); + mod->FEConfig[i].FEGlobal.enableCP5= columnPairMaskDecode(runnInt,5); + mod->FEConfig[i].FEGlobal.enableCP6= columnPairMaskDecode(runnInt,6); + mod->FEConfig[i].FEGlobal.enableCP7= columnPairMaskDecode(runnInt,7); + mod->FEConfig[i].FEGlobal.enableCP8= columnPairMaskDecode(runnInt,8); + + mod->FEConfig[i].FEGlobal.hitbusScaler = 0; // : 8; ??? + mod->FEConfig[i].FEGlobal.selfWidth = 0; // : 4; ??? + mod->FEConfig[i].FEGlobal.selfLatency = 0; // : 4; ??? + mod->FEConfig[i].FEGlobal.aregTrim = 1; // : 2; + mod->FEConfig[i].FEGlobal.aregMeas = 0; // : 2; + mod->FEConfig[i].FEGlobal.dregTrim = 1; // : 2; + mod->FEConfig[i].FEGlobal.dregMeas = 0; // : 2; + mod->FEConfig[i].FEGlobal.parity = 0; // : 1; + mod->FEConfig[i].FEGlobal.enableHitParity = 0; // : 1; + mod->FEConfig[i].FEGlobal.enableMonLeak = 0; // : 1; + mod->FEConfig[i].FEGlobal.enableHitbus = 1; // : 1; + mod->FEConfig[i].FEGlobal.monSpare = 0; // : 1; ??? + mod->FEConfig[i].FEGlobal.enableAregMeas = 0; // : 1; + mod->FEConfig[i].FEGlobal.enableAreg = 0; // : 1; + mod->FEConfig[i].FEGlobal.enableLvdsRegMeas = 0; // : 1; ??? + mod->FEConfig[i].FEGlobal.enableDregMeas = 0; // : 1; + mod->FEConfig[i].FEGlobal.enableTune = 0; // : 1; + mod->FEConfig[i].FEGlobal.enableBiasComp = 1; // : 1; + mod->FEConfig[i].FEGlobal.enableIpMonitor = 0; // : 1; ??? + + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 Timestamp enable (0 = OFF, 1 = ON) + a.str(readstring); + a>>runnInt; a.clear(); + mod->FEConfig[i].FEGlobal.enableTimestamp=runnInt; + + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 Decoupling capacitor enable (0 = OFF, 1 = ON) + a.str(readstring); + a>>runnInt; a.clear(); + mod->FEConfig[i].FEGlobal.enableCapTest=runnInt; + + std::ifstream * ifp = 0; + + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 readout mask mode (see end for details) + a.str(readstring); + a>>runnInt; a.clear(); + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 readout mask file (if appl.) + a.str(readstring); + a>>rmname[i]; a.clear(); //cout << rmname[i].c_str() << endl; + + if(runnInt == 0){ + + std::string full_path = getFullPath(rmname[i]); + ifp = new std::ifstream; + + ifp->open(full_path.c_str()); + + if(!ifp->good()){ + + std::stringstream a; + a << "Chip " << i << " "; + a << "readout mask file not open as good: " << full_path.c_str(); + + throw rcecalib::Config_File_Error(ERS_HERE); + + } + } + + //ENABLE + boolMaskFileDecode(mod->FEConfig[i].FEMasks.maskEnable, runnInt, ifp); + if(runnInt == 0) delete ifp; + + + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 strobe mask mode (see end for details) + a.str(readstring); + a>>runnInt; a.clear(); + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 strobe mask file (if appl.) + a.str(readstring); + a>>smname[i]; a.clear(); + if(runnInt == 0){ + std::string full_path = getFullPath(smname[i]); + + ifp = new std::ifstream; + ifp->open(full_path.c_str()); + if(!ifp->good()){ + std::stringstream a; + a << "Chip " << i << " "; + a << "strobe mask file not open as good: " << full_path.c_str(); + throw rcecalib::Config_File_Error(ERS_HERE); + } + } + + + //SELECT + boolMaskFileDecode(mod->FEConfig[i].FEMasks.maskSelect, runnInt, ifp); + if (runnInt == 0) delete ifp; + + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 preamp kill mask mode (FE-I only) + a.str(readstring); + a>>runnInt; a.clear(); + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 preamp mask file (if appl.) + a.str(readstring); + a>>pkname[i]; a.clear(); + if(runnInt == 0){ + std::string full_path = getFullPath(pkname[i]); + ifp = new std::ifstream; + ifp->open(full_path.c_str()); + if(!ifp->good()){ + std::stringstream a; + a << "Chip " << i << " "; + a << "preamp mask file not open as good: " << full_path.c_str(); + throw rcecalib::Config_File_Error(ERS_HERE); + } + } + //PREAMP + boolMaskFileDecode(mod->FEConfig[i].FEMasks.maskPreamp, runnInt, ifp); + if (runnInt == 0) delete ifp; + + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 hitbus mask mode (FE-I only) + a.str(readstring); + a>>runnInt; a.clear(); + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 hitbus mask file (if appl.) + a.str(readstring); + a>>hmname[i]; a.clear(); + if(runnInt == 0){ + std::string full_path = getFullPath(hmname[i]); + ifp = new std::ifstream; + ifp->open(full_path.c_str()); + if(!ifp->good()){ + std::stringstream a; + a << "Chip " << i << " "; + a << "hitbus mask file not open as good: " << full_path.c_str(); + throw rcecalib::Config_File_Error(ERS_HERE); + } + } + //HITBUS + boolMaskFileDecode(mod->FEConfig[i].FEMasks.maskHitbus, runnInt, ifp); + if (runnInt == 0) delete ifp; + + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 TDAC mode (n = all n (for n = 0-31), 32 = alternative file) + a.str(readstring); + a>>runnInt; a.clear(); + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 TDAC file + a.str(readstring); + a>>tdname[i]; a.clear(); + if(runnInt == 128){ + std::string full_path = getFullPath(tdname[i]); + ifp = new std::ifstream; + ifp->open(full_path.c_str()); + if(!ifp->good()){ + std::stringstream a; + a << "Chip " << i << " "; + a << "TDAC file not open as good: " << full_path.c_str(); + std::cout<<"Could not open file "<<full_path.c_str()<<std::endl; + throw rcecalib::Config_File_Error(ERS_HERE); + } + } + //TDAC + intMaskFileDecode(mod->FEConfig[i].FETrims.dacThresholdTrim, runnInt, ifp); + if (runnInt == 128) delete ifp; + + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 FDAC mode (n = all n (for n = 0-31), 32 = alternative file) + a.str(readstring); + a>>runnInt; a.clear(); + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 FDAC file + a.str(readstring); + a>>fdname[i]; a.clear(); + if(runnInt == 128){ + std::string full_path = getFullPath(fdname[i]); + ifp = new std::ifstream; + ifp->open(full_path.c_str()); + if(!ifp->good()){ + std::stringstream a; + a << "Chip " << i << " "; + a << "FDAC file not open as good: " << full_path.c_str(); + throw rcecalib::Config_File_Error(ERS_HERE); + } + } + // FDAC + intMaskFileDecode(mod->FEConfig[i].FETrims.dacFeedbackTrim, runnInt, ifp); + if (runnInt == 128) delete ifp; + } + + getLineDos(*m_moduleCfgFile, readstring); + getLineDos(*m_moduleCfgFile, readstring); + getLineDos(*m_moduleCfgFile, readstring); + + float runnFloat; + {for(int k = 0; k < nofchip; k++){ + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip k Cinj-LO (fF) + a.str(readstring); + a>>runnFloat; a.clear(); + mod->FEConfig[k].FECalib.cinjLo = runnFloat; + }} + + {for(int k = 0; k < nofchip; k++){ + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip k Cinj-HI (fF) + a.str(readstring); + a>>runnFloat; a.clear(); + mod->FEConfig[k].FECalib.cinjHi = runnFloat; + }} + + + {for(int k = 0; k < nofchip; k++){ + bool isCubicFit=false; + getLineDos(*m_moduleCfgFile,readstring); + if((int)readstring.find("VCAL-FE coefficients")!=(int)std::string::npos) + isCubicFit = true; + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 VCAL-FE gradient (mV/count) + a.str(readstring); + float c0, c1, c2, c3; + if(isCubicFit){ // new TurboDAQ format has slope, cubic and quadratic fit pars in one row + a.str(readstring); + a>>c3>>c2>>c1>>c0; a.clear(); + } else { + a>>c1; a.clear(); + c0 = c2 = c3 = 0.0; + } + mod->FEConfig[k].FECalib.vcalCoeff[0]=c0; + mod->FEConfig[k].FECalib.vcalCoeff[1]=c1; + mod->FEConfig[k].FECalib.vcalCoeff[2]=c2; + mod->FEConfig[k].FECalib.vcalCoeff[3]=c3; + }} + + {for(int k = 0; k < nofchip; k++){ + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // Chip 0 Internal-injection offset correction (VCAL-FE counts) + a.str(readstring); + a>>runnFloat; a.clear(); + //fefi = new TurboDaqFileField("OffsetCorrection", FLOAT); + }} + + // two empty lines and TPLL XCKr phase + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); + + {for(int k = 0; k < 16; k++){ + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); // MCC CAL strobe-delay range 0: calibration factor (ns/count) + a.str(readstring); + a>>runnFloat; a.clear(); + std::string name = "DELAY_"; + std::stringstream b; + b << k; + name += b.str(); + // fefi = new TurboDaqFileField(name.c_str(), FLOAT); + //fefi->m_floatContent = runnFloat; + //insertField(*it, fefi); + }} + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); + getLineDos(*m_moduleCfgFile,readstring); + sprintf((char*)mod->idStr, readstring.c_str()); + delete m_moduleCfgFile; +} + +//FS: writing out config file... + + +void TurboDaqFile::writeMaskFile(CORBA::ULong arr[][ipc::IPC_N_PIXEL_COLUMNS], std::string path){ + std::ofstream file(path.c_str()); + for (int j = 0; j < ipc::IPC_N_PIXEL_COLUMNS; j++) { + if (j<10) + file<<std::dec<<j<<" "; + else + file<<std::dec<<j<<" "; + for (int i = 0; i < 5; i++){ + file<<std::hex<<arr[4-i][j]<<" "; + } + file<<std::endl; + } + file.close(); +} + +void TurboDaqFile::writeMaskFileFT(CORBA::Octet arr[][ipc::IPC_N_PIXEL_COLUMNS], std::string path){ + std::ofstream file(path.c_str()); + for (int i = 0; i < numberofrows; i++) { + for (int j = 0; j < numberofcolumns; j++){ + file<<(int) arr[i][j]<<" "; + } + file<<std::endl; + } + file.close(); +} + +void TurboDaqFile::writeModuleConfig(ipc::PixelModuleConfig* config, const std::string &base, const std::string &confdir, const std::string &configname, const std::string &key){ + struct stat stFileInfo; + int intStat; + // Attempt to get the file attributes + intStat = stat(base.c_str(),&stFileInfo); + if(intStat != 0) { //File does not exist + std::cout<<"Directory "<<base<<" does not exist. Not writing config file"<<std::endl; + return; + } + + intStat = stat((base+"/"+confdir).c_str(),&stFileInfo); + if(intStat != 0) { //File does not exist + std::cout<<"Directory "<<base<<"/"<<confdir<<" does not exist. Creating."<<std::endl; + mkdir (base.c_str(),0777); + mkdir ((base+"/"+confdir).c_str(),0777); + mkdir ((base+"/"+confdir+"/configs").c_str(),0777); + mkdir ((base+"/"+confdir+"/masks").c_str(),0777); + mkdir ((base+"/"+confdir+"/tdacs").c_str(),0777); + mkdir ((base+"/"+confdir+"/fdacs").c_str(),0777); + } + + std::string cfgname=configname; + if(key.size()!=0) cfgname+="__"+key; + std::string fullpath=base+"/"+confdir+"/configs/"+cfgname+".cfg"; + std::cout<<fullpath<<std::endl; + std::ofstream cfgfile(fullpath.c_str()); + cfgfile<<"TurboDAQ VERSION 6.6"<<std::endl; + cfgfile<<std::endl; + cfgfile<<"Assembly type (0 = Single-chip, 1 = Module)"<<std::endl; + cfgfile<<"1"<<std::endl; + cfgfile<<"MCC flavour if applicable (1 = MCC-I1, 2 = MCC-I2)"<<std::endl; + cfgfile<<"2"<<std::endl; + cfgfile<<"FE flavour (0 = FE-I1, 1 = FE-I2)"<<std::endl; + cfgfile<<"1"<<std::endl; + cfgfile<<std::endl; + for(int i=0;i<ipc::IPC_N_PIXEL_FE_CHIPS;i++){ + std::stringstream iStringstream; + std::string iString; + iStringstream << i; + if (i <10) + iString = "0" + iStringstream.str(); + else + iString = iStringstream.str(); + + cfgfile<<"CHIP "<<i<<":"<<std::endl; + cfgfile<<std::endl; + cfgfile<<"Chip "<<i<<" geographical address (0-15)"<<std::endl<<(unsigned) config->FEConfig[i].FEIndex<<std::endl; + + int enable = config->maskEnableFEConfig & (0x1<<i); + bool isEnable = (enable!=0); + cfgfile<<"Chip "<<i<<" global configuration enable (0 = off, 1 = on)"<<std::endl<<isEnable<<std::endl; + + enable = config->maskEnableFEScan & (0x1<<i); + isEnable = (enable!=0); + cfgfile<<"Chip "<<i<<" global scan/readout enable (0 = off, 1 = on)"<<std::endl<<isEnable<<std::endl; + + enable = config->maskEnableFEDacs & (0x1<<i); + isEnable = (enable!=0); + cfgfile<<"Chip "<<i<<" DACs enable (0 = off, 1 = on)"<<std::endl<<isEnable<<std::endl; + cfgfile<<"Chip "<<i<<" Global Threshold DAC"<<std::endl<<(unsigned) config->FEConfig[i].FEGlobal.gdac<<std::endl; + cfgfile<<"Chip "<<i<<" IVDD2 DAC"<<std::endl<<(unsigned) config->FEConfig[i].FEGlobal.dacIVDD2<<std::endl; + cfgfile<<"Chip "<<i<<" ID DAC"<<std::endl<<(unsigned) config->FEConfig[i].FEGlobal.dacID<<std::endl; + cfgfile<<"Chip "<<i<<" IP2 DAC"<<std::endl<<(unsigned) config->FEConfig[i].FEGlobal.dacIP2<<std::endl; + cfgfile<<"Chip "<<i<<" IP DAC"<<std::endl<<(unsigned) config->FEConfig[i].FEGlobal.dacIP<<std::endl; + cfgfile<<"Chip "<<i<<" TRIMT DAC"<<std::endl<<(unsigned) config->FEConfig[i].FEGlobal.dacITRIMTH<<std::endl; + cfgfile<<"Chip "<<i<<" IF DAC"<<std::endl<<(unsigned) config->FEConfig[i].FEGlobal.dacIF<<std::endl; + cfgfile<<"Chip "<<i<<" TRIMF DAC"<<std::endl<<(unsigned) config->FEConfig[i].FEGlobal.dacITRIMIF<<std::endl; + cfgfile<<"Chip "<<i<<" ITH1 DAC"<<std::endl<<(unsigned) config->FEConfig[i].FEGlobal.dacITH1<<std::endl; + cfgfile<<"Chip "<<i<<" ITH2 DAC"<<std::endl<<(unsigned) config->FEConfig[i].FEGlobal.dacITH2<<std::endl; + cfgfile<<"Chip "<<i<<" IL DAC"<<std::endl<<(unsigned) config->FEConfig[i].FEGlobal.dacIL<<std::endl; + cfgfile<<"Chip "<<i<<" IL2 DAC"<<std::endl<<(unsigned) config->FEConfig[i].FEGlobal.dacIL2<<std::endl; + + // FS: Encoding mask parameter from enableCPi's + int mask = 0; + mask = mask | config->FEConfig[i].FEGlobal.enableCP0; + mask = mask | (config->FEConfig[i].FEGlobal.enableCP1<<1); + mask = mask | (config->FEConfig[i].FEGlobal.enableCP2<<2); + mask = mask | (config->FEConfig[i].FEGlobal.enableCP3<<3); + mask = mask | (config->FEConfig[i].FEGlobal.enableCP4<<4); + mask = mask | (config->FEConfig[i].FEGlobal.enableCP5<<5); + mask = mask | (config->FEConfig[i].FEGlobal.enableCP6<<6); + mask = mask | (config->FEConfig[i].FEGlobal.enableCP7<<7); + mask = mask | (config->FEConfig[i].FEGlobal.enableCP8<<8); + cfgfile<<"Chip "<<i<<" column-pair mask parameter"<<std::endl<<mask<<std::endl; + + cfgfile<<"Chip "<<i<<" Timestamp enable (0 = OFF, 1 = ON)"<<std::endl<<(unsigned) config->FEConfig[i].FEGlobal.enableTimestamp<<std::endl; + cfgfile<<"Chip "<<i<<" Decoupling capacitor enable (0 = OFF, 1 = ON)"<<std::endl<<(unsigned) config->FEConfig[i].FEGlobal.enableCapTest<<std::endl; + std::string path = confdir+"/masks/enable_"+iString+"_"+cfgname+".dat"; + cfgfile<<"Chip "<<i<<" readout mask mode (see end for details)"<<std::endl<<"0"<<std::endl; + cfgfile<<"Chip "<<i<<" readout mask file (if appl.)"<<std::endl<<path<<std::endl; + path = base+"/"+confdir+"/masks/enable_"+iString+"_"+cfgname+".dat"; + writeMaskFile(config->FEConfig[i].FEMasks.maskEnable, path); + + path=confdir+"/masks/strobe_"+iString+"_"+cfgname+".dat"; + cfgfile<<"Chip "<<i<<" strobe mask mode (see end for details)"<<std::endl<<"0"<<std::endl; + cfgfile<<"Chip "<<i<<" strobe mask file (if appl.)"<<std::endl<<path<<std::endl; + path=base+"/"+confdir+"/masks/strobe_"+iString+"_"+cfgname+".dat"; + writeMaskFile(config->FEConfig[i].FEMasks.maskSelect, path); + + path=confdir+"/masks/preamp_"+iString+"_"+cfgname+".dat"; + cfgfile<<"Chip "<<i<<" preamp kill mask mode (FE-I only)"<<std::endl<<"0"<<std::endl; + cfgfile<<"Chip "<<i<<" preamp mask file (if appl.)"<<std::endl<<path<<std::endl; + path=base+"/"+confdir+"/masks/preamp_"+iString+"_"+cfgname+".dat"; + writeMaskFile(config->FEConfig[i].FEMasks.maskPreamp, path); + + path=confdir+"/masks/hitbus_"+iString+"_"+cfgname+".dat"; + cfgfile<<"Chip "<<i<<" hitbus mask mode (FE-I only)"<<std::endl<<"0"<<std::endl; + cfgfile<<"Chip "<<i<<" hitbus mask file (if appl.)"<<std::endl<<path<<std::endl; + path=base+"/"+confdir+"/masks/hitbus_"+iString+"_"+cfgname+".dat"; + writeMaskFile(config->FEConfig[i].FEMasks.maskHitbus, path); + + path=confdir+"/tdacs/tdac_"+iString+"_"+cfgname+".dat"; + cfgfile<<"Chip "<<i<<" TDAC mode (n = all n (for n = 0-31), 128 = alternative file)"<<std::endl<<"128"<<std::endl; + cfgfile<<"Chip "<<i<<" TDAC file"<<std::endl<<path<<std::endl; + path=base+"/"+confdir+"/tdacs/tdac_"+iString+"_"+cfgname+".dat"; + writeMaskFileFT(config->FEConfig[i].FETrims.dacThresholdTrim, path); + + path=confdir+"/fdacs/fdac_"+iString+"_"+cfgname+".dat"; + cfgfile<<"Chip "<<i<<" FDAC mode (n = all n (for n = 0-31), 128 = alternative file)"<<std::endl<<"128"<<std::endl; + cfgfile<<"Chip "<<i<<" FDAC file"<<std::endl<<path<<std::endl; + path=base+"/"+confdir+"/fdacs/fdac_"+iString+"_"+cfgname+".dat"; + writeMaskFileFT(config->FEConfig[i].FETrims.dacFeedbackTrim, path); + cfgfile<<std::endl; + } + + cfgfile<<"Calibration Parameters:"<<std::endl; + cfgfile<<std::endl; + + for(int i=0;i<ipc::IPC_N_PIXEL_FE_CHIPS;i++){ + cfgfile<<"Chip "<<i<<" Cinj-LO (fF)"<<std::endl<<(float) config->FEConfig[i].FECalib.cinjLo<<std::endl; + } + for(int i=0;i<ipc::IPC_N_PIXEL_FE_CHIPS;i++){ + cfgfile<<"Chip "<<i<<" Cinj-HI (fF)"<<std::endl<<(float) config->FEConfig[i].FECalib.cinjHi<<std::endl; + } + for(int i=0;i<ipc::IPC_N_PIXEL_FE_CHIPS;i++){ + cfgfile<<"Chip "<<i<<" VCAL-FE coefficients (V(mV) = [0]*vcal**3+[1]*vcal**2+[2]*vcal+[3])"<<std::endl; + cfgfile<<(float) config->FEConfig[i].FECalib.vcalCoeff[3]<<" "<<(float) config->FEConfig[i].FECalib.vcalCoeff[2]<<" "<<(float) config->FEConfig[i].FECalib.vcalCoeff[1]<<" "<<(float) config->FEConfig[i].FECalib.vcalCoeff[0]<<std::endl; + } + for(int i=0;i<ipc::IPC_N_PIXEL_FE_CHIPS;i++){ + // FS: Is not used by read-in function, thus being set to 0 + cfgfile<<"Chip "<<i<<" Internal-injection offset correction (VCAL-FE counts)"<<std::endl<<"0"<<std::endl; + } + cfgfile<<std::endl; + cfgfile<<"TPLL XCKr phase"<<std::endl; + cfgfile<<"0"<<std::endl; // FS: Is not used by read-in function, thus being set to 0 + cfgfile<<std::endl; + + for(int i=0;i<ipc::IPC_N_PIXEL_FE_CHIPS;i++){ + // FS: Is not used by read-in function, thus being set to 0 + cfgfile<<"MCC CAL strobe-delay range "<<i<<": calibration factor (ns/count)"<<std::endl<<"0"<<std::endl; + } + cfgfile<<std::endl; + cfgfile<<"Module string identifier"<<std::endl; + cfgfile<<config->idStr<<std::endl; +} + +TurboDaqFile::TurboDaqFile() {} + + +std::string TurboDaqFile::getFullPath(std::string relPath){ + std::string newPath = relPath, basePath=m_moduleCfgFilePath, testName; + unsigned int pos; + // skip config file-name part of base path + pos = basePath.find_last_of('/'); + if(pos!=std::string::npos) basePath.erase(pos,basePath.length()-pos); + // skip "config" part of base path + pos = basePath.find_last_of('/'); + if(pos!=std::string::npos) basePath.erase(pos,basePath.length()-pos); + // now skip module part of base path, but keep last "/" + pos = basePath.find_last_of('/'); + if(pos!=std::string::npos) basePath.erase(pos+1,basePath.length()-pos); + else basePath=""; + // then add relative path of DAC or mask file + newPath = basePath + newPath; + return newPath; +} + diff --git a/rce/rcecalib/server/TurboDaqFile.hh b/rce/rcecalib/server/TurboDaqFile.hh new file mode 100644 index 00000000..94856ea1 --- /dev/null +++ b/rce/rcecalib/server/TurboDaqFile.hh @@ -0,0 +1,34 @@ +// Reads in module config from Turbo DAQ file. Modified version of PixLib's TurboDaqDB.h +#ifndef TURBODAQFILE_HH +#define TURBODAQFILE_HH + +#include <map> +#include <string> +#include <fstream> +#include "PixelModuleConfig.hh" + + + class TurboDaqFile { + protected: + void openTurboDaqFiles(std::string filename); + int columnPairMaskDecode(int mask, int chipNumber); + void boolMaskFileDecode(CORBA::ULong arr[][ipc::IPC_N_PIXEL_COLUMNS], int valflag, std::ifstream* file); + void intMaskFileDecode(CORBA::Octet arr[][ipc::IPC_N_PIXEL_COLUMNS], int valflag, std::ifstream* file); + void getLineDos(std::ifstream& is, std::string& str); + void writeMaskFile(CORBA::ULong arr[][ipc::IPC_N_PIXEL_COLUMNS], std::string path); + void writeMaskFileFT(CORBA::Octet arr[][ipc::IPC_N_PIXEL_COLUMNS], std::string path); + std::string getFullPath(std::string relPath); + + std::string m_moduleCfgFilePath; + std::ifstream *m_moduleCfgFile; + + public: + ~TurboDaqFile(){} + TurboDaqFile(); + void readModuleConfig(ipc::PixelModuleConfig*, std::string filename); + void writeModuleConfig(ipc::PixelModuleConfig* cfg, const std::string &base, const std::string &confdir, +const std::string &configname, const std::string &key); + void dump(const ipc::PixelModuleConfig&); + }; + +#endif diff --git a/rce/rcecalib/server/atlasimage.hh b/rce/rcecalib/server/atlasimage.hh new file mode 100644 index 00000000..79de9cfb --- /dev/null +++ b/rce/rcecalib/server/atlasimage.hh @@ -0,0 +1,364 @@ +#ifndef ATLASIMAGE_HH +#define ATLASIMAGE_HH +/* XPM */ +static const char *atlas_detector_small[] = { +/* width height num_colors chars_per_pixel */ +" 150 98 256 2", +/* colors */ +".. c #070819", +".# c #2084e4", +".a c #79360c", +".b c #34441e", +".c c #96893e", +".d c #b0c5a4", +".e c #404527", +".f c #53643a", +".g c #d48946", +".h c #968d8f", +".i c #4c1204", +".j c #04261c", +".k c #746018", +".l c #404a5d", +".m c #d1e4eb", +".n c #9aa5a2", +".o c #af621e", +".p c #426583", +".q c #738359", +".r c #766157", +".s c #8ca68c", +".t c #092850", +".u c #baa798", +".v c #6185a2", +".w c #dcc8a6", +".x c #664725", +".y c #0a4685", +".z c #787267", +".A c #626a78", +".B c #98a17b", +".C c #2d2719", +".D c #977461", +".E c #5e5058", +".F c #95a8c4", +".G c #d8d0d0", +".H c #719ab3", +".I c #656346", +".J c #1866ae", +".K c #3e3027", +".L c #43543e", +".M c #27150e", +".N c #be8445", +".O c #bcb698", +".P c #78757e", +".Q c #2e3614", +".R c #622e0b", +".S c #415665", +".T c #f3e4ce", +".U c #899970", +".V c #b1c9de", +".W c #292f48", +".X c #667447", +".Y c #52758a", +".Z c #96b49e", +".0 c #294f7a", +".1 c #665724", +".2 c #0a1721", +".3 c #858567", +".4 c #97887b", +".5 c #838798", +".6 c #b4828c", +".7 c #7e7110", +".8 c #99947f", +".9 c #cea88f", +"#. c #3e3536", +"## c #7a7b6c", +"#a c #67747f", +"#b c #dcd3c2", +"#c c #43463f", +"#d c #3f5a82", +"#e c #b6b5be", +"#f c #d4a2ac", +"#g c #999794", +"#h c #f8f5e0", +"#i c #204464", +"#j c #a9a597", +"#k c #87857f", +"#l c #67645d", +"#m c #f0dbd3", +"#n c #193753", +"#o c #a79b92", +"#p c #2e2a2a", +"#q c #51585f", +"#r c #9a5e28", +"#s c #3f6a9b", +"#t c #c7c3b0", +"#u c #6587b8", +"#v c #b0753b", +"#w c #774c26", +"#x c #18558e", +"#y c #31352f", +"#z c #5f4b3f", +"#A c #061738", +"#B c #a68a78", +"#C c #30455a", +"#D c #edcab5", +"#E c #8798a2", +"#F c #403829", +"#G c #50493f", +"#H c #d0b9ac", +"#I c #607ca1", +"#J c #867365", +"#K c #1c3210", +"#L c #c0a280", +"#M c #97b6cf", +"#N c #b9d3e9", +"#O c #cbcfc5", +"#P c #dddada", +"#Q c #515644", +"#R c #bcb6ac", +"#S c #2f5a86", +"#T c #898f84", +"#U c #9b5518", +"#V c #615445", +"#W c #040c31", +"#X c #b9aca7", +"#Y c #d9c9bd", +"#Z c #e7bcab", +"#0 c #42665d", +"#1 c #6e8fa4", +"#2 c #4276ab", +"#3 c #f0e5e2", +"#4 c #696b62", +"#5 c #09386b", +"#6 c #316593", +"#7 c #677b88", +"#8 c #a9a9aa", +"#9 c #655c49", +"a. c #506881", +"a# c #5484a4", +"aa c #64a8f4", +"ab c #4789d1", +"ac c #8bb2d7", +"ad c #cf7821", +"ae c #ce9986", +"af c #9d7247", +"ag c #b98a6e", +"ah c #d1b48e", +"ai c #4198f4", +"aj c #5c2404", +"ak c #3175b9", +"al c #af7a5d", +"am c #618584", +"an c #787146", +"ao c #745445", +"ap c #c6cad8", +"aq c #f1d7ba", +"ar c #b79c92", +"as c #3397f9", +"at c #ce9452", +"au c #613a14", +"av c #765e48", +"aw c #dff0f9", +"ax c #916857", +"ay c #b79580", +"az c #cad4e2", +"aA c #4e705d", +"aB c #ae6c32", +"aC c #0a2736", +"aD c #085ba8", +"aE c #a3ad80", +"aF c #957d76", +"aG c #6d9ed4", +"aH c #829dc1", +"aI c #422411", +"aJ c #2b3b4f", +"aK c #8cc2fc", +"aL c #e1ad7b", +"aM c #615b59", +"aN c #764014", +"aO c #34503c", +"aP c #b4d0b0", +"aQ c #281c12", +"aR c #7a7c82", +"aS c #413c39", +"aT c #976742", +"aU c #835327", +"aV c #74928c", +"aW c #807e3c", +"aX c #687461", +"aY c #325062", +"aZ c #2a69b0", +"a0 c #174980", +"a1 c #a9b5a5", +"a2 c #c17733", +"a3 c #a9b6c4", +"a4 c #ddb885", +"a5 c #5098e0", +"a6 c #a78554", +"a7 c #77691f", +"a8 c #6c90bb", +"a9 c #79684a", +"b. c #c09054", +"b# c #88909c", +"ba c #bcaf7f", +"bb c #c06d1c", +"bc c #5e3d2d", +"bd c #89aac0", +"be c #1a3635", +"bf c #160c0a", +"bg c #4f4c58", +"bh c #1a1713", +"bi c #161b32", +"bj c #d0bdbe", +"bk c #5179a4", +"bl c #e2e5e9", +"bm c #4f2d15", +"bn c #4e3b2a", +"bo c #78685d", +"bp c #858f68", +"bq c #4f462a", +"br c #a68e90", +"bs c #1a260f", +"bt c #182b49", +"bu c #a9abbf", +"bv c #4e5b80", +"bw c #516a96", +"bx c #173b68", +"by c #1a2731", +"bz c #616c93", +"bA c #8a9784", +"bB c #b1caf2", +"bC c #f8f8f8", +"bD c #304634", +"bE c #b2c7c7", +"bF c #997c67", +"bG c #a79581", +"bH c #c6c6c4", +"bI c #874c1b", +"bJ c #53655a", +"bK c #4f85bb", +"bL c #728482", +"bM c #8b6f44", +"bN c #318de7", +"bO c #969cb2", +"bP c #54702c", +"bQ c #877c6e", +"bR c #88400c", +"bS c #291d29", +"bT c #867d7e", +"bU c #4e3d36", +"bV c #885c2c", +"bW c #70879d", +"bX c #a6a37d", +"bY c #51333c", +"bZ c #855f41", +"b0 c #1a5a9f", +"b1 c #626b44", +"b2 c #faebcf", +"b3 c #7e7817", +"b4 c #bbbcc4", +"b5 c #cfada2", +"b6 c #214b66", +"b7 c #879fa7", +"b8 c #bcdefc", +"b9 c #f0eceb", +/* pixels */ +"aDaDa0.t#W...2....#W....#Aa0aZaZak.J.0.0bv#q#C#i#sb0b0#x#sbdbu#Pazb9#o#z.1.k.7.7b3b3.Q#Q#G.P.zbo#G#Vbo#Tbj#3#Pblap#gaMaMaM#P#P#l.AbgaM#a.haRbT.P.PaR#kaR.AaM#l.PaM.z#GaSbUaM.z#o.GbCb9#m#t#o#J#G.z#ObCbla3.n#TaWa7.cb3b3an.zbTbObCbCaw.ma3#d#2#sbkbKbw#S#sa8akakakaZb0#5a0#5.0aY#CaY#C#n.t#5a0.JaDaDbNasas.#", +"aD#x#x.t#W......#W..#A#A#W#W#5#xaZak#6#S.l#dbv#s.p#Sa0#xaHa3azazbl#8.E#V.kbM.7.cb3b3an.I#k.5bTbU#VbXao.h#RbH.Gb4bjbO#gbub##ebCaRbO.nbO#8#8b4blblb9#P#e#e#e#eap#ebobQ#V#9#8.zbT#Xbl#3#Y#P#R.4av.z#lbLb9awb4ap.B##aW.7aWana7.z.5.5bCbCb9bl#NbB#I.0#s#2aY#S#2bKak.JakaZab.ya0#S#d.0#daJ#n.t.0#s#6aZ.yaD.#asasas", +".J#x.y#W#A....#W#W..#W#W#W#W#W.t.0#6#s#s#S#6.Ybw.0.0#ia8a3.V#P.G#ebJbq.1.1.k.k.k.kb1.f.3#k#k#Q#G#lbQ.z#J#o.u#Y#Pbj#e.5.G#O#Pbl#T#jb9bCbl#8azbCbCbCbC#eapbCbCb9#gbo#obo.z#R.Ebo#o#3b9#b#R#X.4.4#VaMbJ#gapblbl#e#j##anb1aW.z#8#TbO#EbCbCbCawbB#M.0#2#d#u#sbKakaZaZabab#xa0#5#5#C#A#A.taJ#dacac#S#xakaD.JbNasas", +".y.y.y#W#W....#W..#W#W#W#W#W#W#W#Abx.0#2#2#6#s#S.0bxb#bubj#P.G#eaX.L.3bp.1bG.c.c.8.I#T#kaX#Q.l.B#Xb5#J.rbTbjbj#obTbobT#X#P#P#P#gb#blawb9#e.GbCbCbCbC#e.Gb9bCbCb#.z#X.8.8aF#zaMbo#J.u#Y#H#B#9brbGaEbT#qaRblb9#P#eb4.8.h.8.nbEap.ZbL#EawbCb9bl#N.F#u#5#6#2#2bKaZaa#2a0#xa0#5#5.tbx#C.l.S#u#Sbt#2aKa5aDaDbNaiai", +".yaD#5#W#W#W......#W#W....#W#W#W..#A.t#SaZakak#i#d.5bObj.G.G.GaX.Sb7.d#8.8bQ#bbG##bQ#g#TaM#y#8.G#b.4#9#9.rbrax.r.rbo.PbT#3blbl#PapazbHblazb9bCbCbCbCblb9blapblaz#j#R#kbT#VaM.r.r#9#J#J#oaFbQao#g#X.P#l#ab#b4blaz#ebObO#Eb4a3.ZaH#a#l.5b9bCb9blb8.F.0#6akakakaG#x.0.0b6bt#A#W#n#n#nbt.t.t#dacaGaZb0.yaDaZaiai", +"b0.y#5.t#W#W..............#W......#W#W.t.y#6#2#d#ubObjbj.G#Y#l#Q#S#Na3.n#T.3aF.3bQ#o#j#4#p.PbT#P#H#JbGbGaoao#J.Ebo#JbTbT#l#qaX.A#k#a#aaR#aaRaR.PaR.P#4.P#a.A#4.E#y.K#p#z.E#9ao#9aobo.ra9#o#Rbo#Y#3#kaM.zb#bub9b9az#ebO.Vb8#Mb7bW#a.A.Ab#awb9b9azazac#saZa0.y#5#i#iaJ#n#Abt.0bv#C.tbt#i#daG#s.yb0.y#5b0aZa5aa", +"#6a0#x.y#5#A#W..........#W....#W..#W#W#W#A#5#s.v.F#e#P.G.GbTbU.S.p#S#Ma8.AbO##bQ.8#jbo#..E#X#ob9#h.4#H#b.r.E#zaoboboaF.P.z#yaS#q.A#q#a#l#l#a#a#4.P#a.P#4.P#k.A#pbSbS#y#V#9aoaMav.r.rbo.r#H#R#R#3#P#o#4aR#kaXa3awbCa3#Naz.Fb7bd#7aHbW.S.A.5bCbCb9#NbBbB#s.ya0#5aY.laJbtaJaY.S#nbiaJbwacbw#xa0b0a0a0a0.y.yabab", +"aHbx.y.ya0bxbt..bf....#Abyby........#W#W#W#A.laHa3ap.GazbT.lbgbv.0a8#daHb#.5##bXbX.3bUbUbT#X#X#J#m.T.u#HbGao.raxbobo#JaF.A#qbgazazbO.n.na3bHa1b4#8#eb4a3bO#8aR#cby#ybgbo.E#9bo#zboaxboaF#X.u#h#P.P.Pbu.n#8.q###ebEb9aza3#1.F#1.VbW#da..S#d#EbCb9b9azbBaH#5.t#naY.l#c#C.laYaJ.W#Cbzbwbw.0.0a0#s.0#5#s#s#x.Jab", +"a8.t.t.0#A.t.0aJ#A#Wbi#W#W#Wbf........#W..bib7buapazazb#bv#d#I.p#s#u#dbvbz##.B#jbp.1.IbG#Y#Ybr#o#k#P#mbGbo#zaoaMaobTbT.hbgaR#cbEb4b#b#bO#gbO#ea3a3#8.n#e#e#eaR.l#p#p#a#V#lbo#9.r.r.za9bo.Gb9#P#k.5.P#4b4#k#T#gaXa1.mb4.V.V#e.F#1#daYbk.v.p#0#EbCb9blaz#Na8#CaJaJaJ#naJaJ.WaJ#naJ#daJ.S#Ibv#d.0bx#Sbwaba0#xab", +"#n#A#W#nbx#A.taJ#ib6#A#A....bh#p#.bi.2.W.Wb#buap.GazbO#C.laH#uacbzbv#Ibv.5bA#j.3.ebq.8.3#Y#lbo.zbo.8#Pbj#zbc.E#J.r#J.h#obJ.5.A#ebE.5bCb9blbuawbCbCbC.nbCbCbC.A#qaJ#y.h.5bobo#lbo#J#VaMbqaMb9#k.PbOaR.PaRbH.n#g.naX.F#PbC.mbOb#.5bz#d#s#2.p.Ybv#EbCbCblap.GbW#y#CbtaC.2aJbtaJ.FaHaJaJbObOaH#I.0bxbw#u#u#s.0#2", +".2.2#WaC#i#A#WaCbibtbwbdbt#A#W..#Wbh..aS.P#8bHap.Gbu#qbvbwbkbk#ubz.5.P.5#g.n#g#G.e.z.U#Y.B###4#4.4#j.u#V.K#9#9aobobT.4apbubTaRa3apbOb4bOapa3b9bCbCawbuaz#gbOaMbgaSaM#c.h#3#j#lboaM#VaM#c#c.hbl#g#abOaR#eap#P#e#8.5.Aa3bCbub4apa3aH#I#sbk.0#i.SbJ#gbCbC#3apbjbO#q.S#q.S#7#CaJb4#Pbg.WbvbWbubwbx#C.A.5.5bOb#a8", +".W.2aJ#A#n#iaJ#Abi.2bWa3bv.Wbi#W....biaR#8b4#t.G#ebgbgbibx#IaZ#SbvaM.P#g#g.haM.laM#laE.daw#t#4.h#g.ObQbqbQbobo#zbr#YbC#3bT#caRa3b9bla3b4#PazawawbCblblblb4b4#gbgbg#c.K#Q#jbCbC#tbQ#lbU#kaM#cbubH#E.Pb4b9apbub4#8bO.Abvb#bCb9azb4a8#u#s#Sbx.tbt#qaM#obCbC#3apbH#g#y.S.A.l#q#ablbC.P#q.W.0#I.0#5bw.5.hbrbBbOaH", +".l.Ab7a.aJaJ#dbt.Wbi.h#P.5#C#ibtbi.WaM#8a3bE#O#e#l.E#.#W#W.t#Sbw.P.Par#obO#qbybgbz#e#e#g#t#Pa1#g.uba.IbM#m#Ja9#t#R#3.4#Gbg#G#kbTaM.A#q#qbvaMbvaM#q#q.lbgaM#q#y#yaM#kbg.EbUbU#k#o#k#kbU#g#g#Qbg#Razblblap.Gapbu#ebzb#bz.lb4bCblazbB#I#i.t#WaC.S#Cbg.A#jbCbCbl#8#8b#bT#ebl#4ap#Pb9aH.Abvbt#ia0a0bk#IaR.5aHbwbw", +"#y.l.AaR.Abe.laJ.W.E#8bHb4#7#A.WaJaMbO.nbHbHb4.PaM.W....#W..#Abv.A.h#8#g#laJaJ#C.5bua3#3bl#O#P#3.OavaWbQ.O#t#9#9bUbq.EbU#G.Ebo.P#8#P#e#8b4b4b4b4bEa3#g.nb4aRaS#caoaM#z.EbUaMbU#.#G#GaM.P#c.z#V#qa1blazap#3ap#ebu#e.5.l.A.Sa3bC#PbB#M#dby.Wbta.aJbebJ.A#8bCbC#Pb#b#bl#P#X#gbl#Pb9#ebv.l.lbxbxb0#s#ubwbw#d#5#x", +"biaS#q#k#a.WaJa.#c.l#8bubj#ebybt.h.Pbuapazaz#a#laJ.M........bi.A.h#obu#aaJ.A.l#Iapbub9bC#Y#m#mbj#9bM.ubM.c#H.4bFbnbU#G#G#z#z.r.haRbCbOb4bEb##8bE#ebO#e.nb4#k.A#caMao#GbUbU#G#V#F#y#laM.I#kbg#l#G#qbHbl#hb9blb9b4bBbubza.#q.la3.F.mbBbObv.W.W#q.Wbe#C#qaX.nbC.mbubu#P#e.5#Xap#o#8#e#gbvaYbxa0#S#6aHa8bz.t.t#5", +"aQbi#p#yaM#a#C.l.laMbu.h#obu.PbTb#apapaza3aR#qbgbibh......biaM.P#g.n#7bD.S.AbWazbBb9bCblbC#h#Dav.D.O.I#Jbran.Obo#J#F#zbc#.#zao.h.P#3.naR#k#E#Pblb9#Ob4#k.h#4.PbUao#z#zbU#z#GbU#l#QaM#l#g#j.haM#XbL#Q#ObCbCbCb9blaza3a3.S#7#7#qapblawap#o#l#..Sbt#C.SbJ#q#abOazb4.Gb4bH#Ob4.G#m#P#P#e.5btbw#da0#6.0#I#u#5#5#5", +".W#cbyaJaJ#p#y#C#q.h#H.ub5#R.u.h#o#o#o#eb#bg#q#Cby#y#cbfbh#q.zbT#l#4aJaJbv.Aap#ob9bCb9bC#h.T#9an.w.8a6bG.8bGbQ#G#lbcbUbU#z#z#zboaF.G#X#ea1bO#PblblbH#8#8#R#g#T#G#z#zbYbYaoaS#V#G.EaS#k#q.n.h#ka1#PaRaMapbCblb9bCb4a3b#bO#a#4aRa1.Fb9bl#ebu.A.A.lbJ#a#g#a#4#lbO.Gb4#e.G#P#m#3b9#m#P#P#ebvbzbk#s#Sa0.y.ybx.ybx", +"byaJbyaJ#y.2biaSaFbr#Xb5#H#X#Hbj.u#8.h.P#l#4#q#Q.lbD.AbD#G#4aR#g#4#.#y.2aJbE.P#e#XbCblbCbl.z.I.O#L.u#j.ubQbj.EaMbobUbU#zbcbcbcav#J###R#8#o#TbO#g.B#8#g#X#8#obo.EbcbcbcbmbU.E#z#V#X#lbg#kaR#8aRbObubH#aaM.GbCbCap#e#jbL#k#T#a.5b#bvb4bCaz#EbO.5b#.nbla3#l.PaMbTbj.G#mb9b9#m.G#m#mbjbjb4bWbw#dbxa0b0b0.y#5#S#s", +"bi#c.2.W.SaJbsaSbT.4.6#X#H#H#Y#Y#Hb5#Xbr.P.PaSbgaSaS.5#c#q#4bQ.PaS.2byaJ#8aRaM.EbT#8bCbl#a#9#Xba#bba#j.u#tbo#J#J.h.EbnbU#zbcbc#z.z#lbT.5bO#l#8b4bubHbo.z#o#PaM.E#zbYbU.Ebc#G.E#T.P#g#l#lb##kbub9az#e#k#q#qbEb9apa1#EbTb##8.n.z.A#c.AbuapazbO#gbE#e#T#8#g#8b4#P.G#3#3#m#m#m#Z#Hbrar#o#8.P#nbx#5.yb0#saZa0.0#S", +"#c.lbybt.W#paJbg.P.4bT#Bbrarb5#Hb5b5bj#Y#R#X.4buaMaS.PaSaM#4#a#4#.bfaSa1bO#EaM#cbo#e#P.5#la1#t.w#h#P#R#b.z#JbQ#JbQ#J#zbYbcbUbY.E.r.hb##jap#qb4bCbCb4aM.hbT#X.A.EbUbUbUbY#G#G#J#kbQ#k#k#4#q#R#eawblapbOaR#q#q.Gap#TbubL#g#kbuap.n.A#abJbO#e#ebHbO.h#8#P.Gb9#3.GbC#mb9#Y#Y#faray.9arbrbTbzbt#5a0.ya0#6.pbk.Y.p", +".l#qby#y#C.Wbi#cbo.zbQ#B.4#Jbrar#H#Xb5#H#Z#mbj#Hbr.P.4.E#qaM#Gbg#p#pb4bC.nb4bg#cbTbl#kaJ#R#t#jbCb2bC.T.3aF.4bobQbo#Jao#.bUbUbUbq#GaM.z.5bHb#.5#e#e.4#l#8bT.P.EbU.KbUbUbUbU#zbo#kaR.n#4#e#k#a#3bl#Pawbu.P.A#l.AbHa1#g#kb#b4#P#Pa3#kbO.PbgbObO#o#8apbl#3#3bCbCb9#Z.G#Z#Xararar#BaraFbo#laR#C#ibxbx.0bkbx.0#s.p", +"bE#7.W#C.laJ#cbgbU#z.zbMbFbrbraF.6ar#Z#D#D#m#m.Gbj.ububobgbgbgbo#G#8bOblbC#8.5bobj#g#q.z#T#TbG#Ob2#b.4#l.8bobQ.4aFbo#zbqbUbU#G.K.EaSbo#l#l###7.z#4.zaSaM#l#laSaSbU.KbU#G.E.zaMbTbT#l.P#Tb4.P#Tblaw#P.5#a#aaR.SaMap#O#g#eblblaR#gb4.G.5bgaMap#PbC#Pb2b9b9#m#3#mbjb5arb5#B.ubr.D#J.r#zb#b4.l.0bxbx#ibWa.bWbW.v", +"bE#8a.bJ.Abg.l.PbTaS#z#V#Jbo.D.4#Bag.6.u#D#m#Z#Z#D#D#m#Y#X.P.EbTb4ar#k.hb9blbHb9buaM#l.h#q.PbQ.8#bbX#lbo.4.8bo.4bQ#J.r.rbU#pbUbU.KaMbgaS#T#8###R#T#4#V#TaF#l#G#.bUaS.K#.#l#gbg#caM#4#4#o#k#l#qbTb4bObH#g#a#laR.lbg#Obl#PbC#g#g#k#ob4#8b4#3#3#Pb9bCb9b2bC#Z#Har#f.uayar#JaFbobo.E.zbobub9bW.l.l.S#Cbz.Fawawa3", +"#a.5.A.A.AbvaM#o#T#9.I.K#zaoboaxbobr#Bay#f#Zb5#mbj#m#m#Y#m#mbj#Xbj#o#Y#P#ob9b9#RbgaM.hbT#l#####j#TaMbQ#k#Rar.4bQ.r#J#J.zaM#F#.aSbU#G#l#q.PbAaRa1#TaMbU#l.z#laS#F.KaSbU#V.P.z#G#caM.Pb4bu#8.5.h.z.5a3#l.FaR#4.PbAbg#q#j#3#8.G.G#e#o.G#m#mb9bCbC#3bCb2b5bj#Xar#H#LbF.DaxavboaM#G#paSaMaM#eaz.l#q.A.AaR#7bLbWaV", +"aJ.lbeaJbg#paRb##GbU#paQ.Kbn#Vao.E.Dbo#Bbr.uaear#D#D#Z#D#D#mbj#m#Yb4#P#3#b.G#8#l#l#8#g#k#l#lbo#8#G.3.P.8#o#H.4bo.z.z.4.h#z#V#pbUaSaS#l.E.P.5aRbT.P#lbg#G.zaM.K#.#p#.#GaM#l#caMbg#G.A#T#8#k.PaM#aaS#ab#aMbJ.Aa1#Xb#.zbg.z#8#Y#t.u#P#mbCbC#mbC#3#D#H.ub5b5#H#BaraFaxbZav#9.r#laM#caS#p#c#l#o#8bTaRb4b4azb##a.S", +"bt#q.W#c#q#c#TaMbg.E.K.KbU#z#B#zbn.E#9#Jax#BaF#Bb5#f.u#f#D#D#m#m#Y#Ybjbjb5.h#J#l.Pbo#e#XbobQ.hbq#Qbo#9#9#X.3aM#J#JbQ.hbo.4.E#G#.bU#.bgaM.hb4#8bO#gbT#l.4#R.E#.#.aSaS#l#laM#4.zbJ#k#g#4.h.5#lbgaMaM#G#a#g#lbOb4.P#laRbQ.4#R#Hbj#X#3bC#3b9#m#Yb5.u.u#Hb5bra6boaFbZ#z#z#z#VaM#l#QaSaMaM#laFbTbT.h#g#8.FbCapb9az", +"aJbvaJ#p#c#y#y.C#p#pbf#..K#G.u#V#F#FbU#V#lboax#JbGbFaybr.9b5#maq#m#m#D#Ybj.O.u#T#lbTaFbH#X.uaMbo#Q#.#.#V#kaM.z#X#j.4bobT#X#JaMbY#.#.#..A#oaz.GbHb4#XbT#j#X#c#.#paS#Q#q.5###c#q#T#k.5#laR#k.P#c#qaM.P#p#4#g#R#####k#j#X#R#Y#H#R#D.TbC#D#Y#Har#f#Xayay.4bQ#J.rav#VaS#Vbo#l#VaM.r#lbq.K#zboaM.hbTaRb4#t#Pazblap", +"aJ.l#yby#cbhbh#.#y#.biaM.E#J#o#VbU#F#p#paM#9#GavbQbFaFaybGae#Zb5#Z.G#mah#m#Y#k.r.h.hbT#Jbo#V#V.zbo#F.CaM#z#9bQ#g.u.z.r#Rbj#JaFbo.K#.#.#l.5#ea1b4#R#8.hbT.zbU#p.K#.bT#kaMaM#q#G.P#8#kaMaRaM.h#qaM#k#XaM#.aMaR#l.h#o.z.4#H#bbj#H#Zb5#m#Yb5#Hbr.uay#JaFa9aobc#Vav#G#V.A#T.h#kbQ#J#9boaFbG#JaM#j#8.h.A#gbz.A.laR", +".W.lby#p#cbhbSbhbS.l....#.#kaF#z#VaS.CbhaS#F.CbU#z#la9.4bFbray.u#Xbr.ub5#D#H#R.zbobTbobo.D.raMaM.E#9.z#laMbg#l.z.z#..zbTbT.Gbr.rbU.KaSbg#k.h#g#g#j.8#j.z#l.K.C#c#l.P#k#laM#c#yaS.P#qaR.AaMaM#8bo#o.zaM#9.4.P#l#GbjbQ.u#Yb5.uay.4#B.ub5ar.u.4aFbo.r#zbqbU#F#VbgbS.C#q#g.n.z#l#9boax.4brbQbo#q#q.l#qaR#a.P.5bu", +"#CaM.lbgbo#cbgbg#c#lbibh#yaF#R#J#l#y#pbhbhbiaQ#y#paS#zao.r#J#Jaybr#o.Da6arbGb5bT#o#Jboaxarbo#9bnboboaM.K#V.zbT.PaMbg#..r.rbr.6#BaM#.#p#F#kb4#O#O#R.G#Y.O#V.K.C#Gbo#gbobgaS#..l#c#c#4aRaMaMaM#q.P#k#VaM#JbG.z#Vbo#b.4bG.u.4.D.DbFaFbFaFbTax.r.r.r#F.C.K#GbsaQ#y#y#cbJ.h#o.hbQ#9#l#9bq#G.E#4bgaSbJ.A.5aM#abOb4", +"aJ#q#y#pbgbSbh#.bgaM#yaSaS.z#ebobo#.#y#pbh#p#y#y#y#.#G#.bUavao.r.r#Jax.4.DbF#obo.G.4#J#B#B.u#J#l#z#V#G#G#caM#4#lbT#l.E.Kbo#J.6.haFaM.K#paR.GbCbl#O#h#3#t#G#y#GbT#8bO.5#.#.aMbg.5.P#c#l#qaM#aaM.E#lbo#B.4#k#J.r#9#m#Rbo.D#J.D#J.rav#9a9.r.r#z#z.EaM#V#G#y#p#c.l#G#V.z#j#X#R#g#Q#.aS#G.zbUaM#laSaJ.5a3#a.A.P#e", +"aJ.l.W.Wbg#pbU.K#c#l.CbSbUbTbr.P.zbgaS#p#y#caJ#c.l#c#Q#..K.E#G.Eao.Eao.Da9bFbQ#kbj.r#J.D.D#B.Dbo.raobq#z#.#c#Q.P#a#lbo.K.EbT.D.h.h.h.laS.A#e.Gbu#X#t#P#g.E#paR.G#e#j.5.5aM.A#l#lbg#cbgaM.PaM.E#9.r.rbQax#J#9#z#9brb2aFbo#J.rbZavao#z.r#z.r.K#G#z.z#4bg#Q#q#Gbe#yaS.z#R#R#R#8aM#Q#G#4.P#l#4.P#l#cbJb7.A#7#7.A", +"aJ.l.W.WbzbY.Ebc.EaxaI.MaI#Jarbr#JaS#ybhbibhbh#.#caSbg.Wbf#4#lbT#Jao#zao#9.rbo.O#j#9aoavax.DaxbZaxa9ao#zbU#GbgaMaM#q.AbobT#o#8#gbz.Ya..A#7.A##aR#k#aaR#gaR#qaR#gbO#8b4#kb#.PaM#l#qaMbUbg#G#zaMao.rao.rao#zbc#zao#l.T#o.zbo#zao#l.z.8bQ#lbT#pbg.E#g.z#laS#y.eaS#p.e##.O#t#Oa1.z#qaM#l.PbT.P#4aR.P.Ab7#7aH#E#I", +"bzbzbvbg.E.E.Ebc#zaobYbYbSaFararbTbU#paQbSbh.2#c.lbg#q#ybh#4aMbQbrbG#Gbn#V.I#G#oaM#z.r.rao.xaobZbZbZao.rao.E.EaMaSaMbTbO#gbOb4b9b8aH.v#NbE.laS#c#yaM#Q#8azbObuawblapb4.hbO.5.A#lbg.E.EbUbUaMao.Eao.xbcbY#w#zbc#zbqaM#R#VaM#z.C.4.4bo.E#lbT.KaM#q#8.zbJ#G.e#FaS#F#G.z#t#t#O#X#laMbgbgbvbg#c#c#l#caY.Y#CaY.Y#C", +"az#8.hbzaMbU.W#p#p.EbS.MbS.Ebr#o.P#GaS#p#p#pbybgaM.laMbgbh##.h#8#o.4#9.K#F#G.zbQ#GbU#Vaoao#zbc.xaoao#zao#V.E#z.E#laM.P#kbO.h#ea3acaHbW.Aby.C.C#c#Q#V#c#y#caXa3b9awbC#P#E#o#4#l#laMbUbU#zbc#zbY#zbUaobc#z#zbcbY#G#G#G#kb1#laS.Kbr#j#X#R#X#8#c#4#k.z.P###4#4#4.z#4##bTbH#O#P#taMaS.W#pbSaS#W#.bg#q.l.A.l.Sbzbv", +"#oaMaM#GaM#p.WbUbU#laSbU#..r#RbTbQ#lbqbU#y#FbSbg#Q#caMaM#y.8#8#X#R#R.h#p#Q#G#G#9aM#9#GbUbUbUbcao#z#z#z.Ebc#z#z.E.E#z#l#k.5#ea3bWbzbLaJ#CaM#4#Q#l#X#l#4#c#y#y#Gb4#PbCbC#g#8#l#lbU#.aSaSbUbUbUbcbnbn#GbUbU#zbcbUbo.z.zaX.z#l#GaS.u#j#8#j.8a1#VbJaM#4aX#4#Q#Q#4#k.z.zaR#tbH.G#eaM.WbU.WbSbgaSbg#qaMbgbz.5.5bTaM", +"aM.EaM#z.zbUaIbS#p#zaQaQaI#z#J#JbQ.zbQ#X#gbTaS#caM#4#q#.#p#l#9#lbo#l.4#Q#p#9#4###4.zaM#G#GbUbUaS#.bUbU#zbUbUbUbc#GbU.zaMaRb##gaR#aaJby#.#c#TaMbQ#X#4bQ.h#F#c#F#Q#X#X#e.z#lbg#GbU#.bUbn#Fbn.KbqbYbnbnbU.Eav#l#GaM#4.z#k.zaX#G#V#XaX.IaX.z#kbg.zbJ#g#k#k#j.Gbl#3#O.z#kbH#b#P#X#VbSbS#..WbgaSbgbg.AaMbo#lbr.5.5", +".E.zbc#V#9#zbY.Kbc#z.R.x.xao#Bay.4boaS#GaS#c#.aM.PbTbo#zaSbo#k.4#G#Q#j#4#F#G#Gbg#QaMaS#G#l#laM#.#.aSaSbU#FbUbmbnbnbn#FaSbg.P.5ap.laJaM.Pbg.z.4.zbQ.4#j.z#9.h#G.KaM#O#kaM#..K#paS#F.C.K#Fbnbn.x#9#QbU#V#l.r.z#z#G.zbp#4#l#QaS.z#j#G#k#j#T#R#j#8aMbT#g#8#gbTb1.z#G#l#TbH#b#ba1.3#l#G#g#o.5#qbg#caM#k#TbQ#e.Tb9", +"bo.hbTb5ar#LaxbZbcaTaxag.9afag.6.4.z#G#paQ#y#paSbg#l.P#l.KaM#J#VaM#9#j.z.z.zaMbUbo.z#Gbg#caS#GaS#FaS#.bU#.bnbUbqbn#F#F.K#c#..5bu.W#pbgbT.ubT.rbQ.zaM#R#j#jbQbn.KbU#P#k.K#y#.#.aS#G#V#z#G#zbU#9#9#9#9#V#V.E#l#kbo#gbH#o.8#k.h#l#j#G#l#l#Q#T#QaMaX#T#kbQ#k#k#j.G.8#Q#T#b#O#O#t#j#O#9#g.G#8bO#q#qaMaR#k#P#tbC#h", +".AbT.A#o.8ar.Dalalalal.D.NafbFay.8.z#G#c#yaS.e#qbg#l#laMbUbo.z#zbUaM#k.z#Vbo#laM.z.4#l#l#G#y#G#c#p#p.K#.#FaS#F.Kbq#G#z.z.AaM.P.WbSaM.r#o#R.h#obobo.h#j#o.3#V#9#VaQbT.G.z.h#T#l#Q#QaM#G#J.3#VbQ.8bTbQ#4.z#9.z.u#l.8bC#jaX.4#o#9#X#G#4#T#k#X.P#k.z#kbQ#k#8bj#Y#b#T#4###t#t#O.O#V#Q#9bJ#k#gbObJ.A#aaX.q#Oa1a1#h", +"#7bO.Abv#g.3bQ#JbFbF.D.D.4bMbF.4#kaR#q#4aX#aaM.AaM.PaR#l.zbTbTbrbobQ#R#J.EbQ#J.rbobTbT#J#l#GaM#Q#GbUbg#G#G#G#Q#V#G#l.z#RbjboaMbS.KbT.hbT.4bo#GbgbU#9#l#JbQbQbQan#Gbg#P#kbl#8.h#4aM#4aM#l#T#G.8#o.z.z#l#9bQ###jbQ#o#j.8.h.3##.z#t.4.3#X.B#j#l#k#l.z.zbo#3#R.T.TboaMaR#P#P.TaPbq#Q#g#baMa1b4bL.Aa.bLaV.m#ObL.m", +"aOa.bz#qbJ.h.z#Ga9bG.haFbQ.z.8#j#g.3bgaX#T.nbL##.L#lbT#l#z#l.8#X#X.u#Y.4#J#J.ravbT#Jao.z#l#V#G#lbqaS#z#Gbg#Qbg#c#Q#Q#qbobTaM.E#.bg.Wbo#JaM.EbU#G#V#VaS#lan.4av#G#VaSaR#4.h#T#laM#Q#GaMaM#4#V###J#l.8#9#lbo#l#Ran.4#J.z#J.4.ubQ#t#8#g#8#X#8#l.h#4bo.P#kbC.ubC#h#Q#qbp#Obl#P#R#9#4#jb9#8bLbEbOa.#abJa1awa1aV.m", +".S#ya.aR#q.A#CbD#qbL#q#qaM#a.B#8#TbLbJ#l#c#q#q#lbgbJ.zaMbg.r#kaF#k.4#H.4#Jbobo#J#J#J#lbQ#J#l#VbobUbqbU#G#G#Q#y.C#cbgaM#8#R#Jbo.MbY.P.P.rbTaMaIbSbh.M.K.I.4.8.4.3aM#cbH#gaz#8aR#qbg#c.e#laM#G###4boaFaM####an#jbQ#obGbX.4.z.z.z#Y.O#X#X#j#k.C#4aM#l.z.z#R.4#R.u#.aM#T#Obl#P#R#l#9#T#t#O#4#7bLbWbWa..n#N.Z#7#t", +".Abg.A#Ebza.bv.l#0bL#qbv.SaMbA#8#T#TaMbJ#QaR##aX#q.P#4#l.E.z.h.u.uar#Xbr#J.4bGbG#obG.z.zbQ.z.z#4#V#G#G#V#Q#q#ybibD#cbg#j#3.PaxbS#..AbobTbo.EbcbU#VbU#V#VbT.cbQ#JaS#pbH#gb4#g#4#Q#c#c#p#4bJ#QbQ.z.z.zbo#T.4.z.zbpbG#X.ubGbo#9###O#R#R#R.O#k#p#4.z#4##.zaM#G#paS#GbJ.5.d#O#ba1#l#l#8bH#8.n#qa.a.#7aRbzb##E#a.n", +"#q#abJ#a.A#aa..l.AbJbv#q.lbg#g.n###T#QaM#Q.A#QbJaM.z#4#l#QaM.4#X#X#o#XbG#V#V.z#J#kbQ#Q.eaM.I#l#9bq.e#F#caS#G#ybS.C#p#GbT#P.4.EbS#c#..Ebobo#J.Ebn#z#V#V.r#JaF.1bq#caSb##k.n.zbg#p#p#p#y#p#p#F#GaM#V#VaM.I#4.I.e#JbGbXbG.8a9#Q##.d#j.8.B#g.zaS#4#4aXbT##.z#Q.Ib1.zbJ#TbE#O#P#e#Q#la1apb7bLbWaJ.p.YbWbza..A.AaV", +"#qbvbg#c#q.l.WaJ#q.Lbg.l#caM#g#g#T.4bJ#4#4.I#Q#laX.z#4#4bU.E.4.u.O#o#t#j#Gbh.Q#y.I.X#9#4#9aM#Q#Q#G.e#yaS#.#c#c#yaM#QaMbT#gbT.E#p#p.AbTbT#o#B.r.xbnaobobM.3bF#J#J.C#p#k#c#g#kaM#yaS#caS#cbq#ybU#Q#G#V#G#V.I.X.I.3.8.cbG.3#Vbqan#O.B.B#Ra1#kaO#Q#q#cbD#c.L.L#c#c#y.LbLb4b4bHbuaMbTap#ha1b7bW#0aY#Ib#b7#7bJa.aV", +"#C.S.SaJaO#Q#yaS#QaM#4.I#Vb1###kbQ##.z#l#l#Q#Q#lb1.z#4#9bn#F#k#j.8.4#gbp#9.Q#G.fbAbA##bA##.q#4bJ#9#Q.e#Q#G#V.E.E#FbU#GbTbT.P.5bobS#Q.EbQarbr#B#Jaxa9.4bG.9a9.1#F.K.h#e##.h#8#c#y#y#G#GbQbQ#G#l#l#G#G#F.Lbq.fan##an#lan#9bq#Q.q.O#kbA#taP#gb1#qaO#p#K#y#K.L#y#Q.XaXbp.s.n.n#8#g#R#8.BbL.Z.Zam.S.YaVb7bA.YaAaV", +"aYb6.S.SaO#Q#QbJ#Q.f#Q#Q.f.f#QaMaMb1#4b1.XaXaXb1###T.z.z.3#la9#9aM#4.z.z#Q.b#Qb1bJb1aX.X#Q#c.I#Q.e#c#y#Q#Gbgbcbq#zbq.EaM#kaMbgbO#y#QboaF.u#L#Bay#B.4#B#H#H#J.1#9#p#Y#l#V#c#GaS#F#p#p.K.K.C.K#z#9#Q#V#4#Q.Q#c.I.I#V#zbqbq.b.QbJb1aX#QaOaMbJaX###Q.L#q#QbJbJbJbJ.XaA.Xb1.qaX.X#4.X#4.q.XaXaXaA#0#0#0#0#0#0#0bL", +"bebDbDbDbD.bbD.ebDbDaO.b.Q.L.e.e.e.e.ebD#c.LbD.L.L.Lbq.L.I.e.ebJbJ#9.L#cbq#G#F#c#laM#QbJ#Q.L#Q#l.e#c#c#zbUbq#Vao#z#z#z#z#GbU#4.PaS.K#p#g#zar.u.D#JbM#BbF#V.4#z#Fbq#Y#g.K#FaSbq#GbU#G#G#p.K.K.C#z.K#y#9.Q#p#9.I#V.I.z#G#F#F.Q.e#K#q#Q##b1#cbD#Q.LbJ#Q.L#QbJ.LbJbJ#Qb1bJ#4b1#qbJbJ#4#0bJaAbJaA.f#0aA#0#0#0.Y#0", +"b6b6#0aObe#K#K#Kbe.QbDaObDaObJ.I.fb1.bbDbDbDaObD.b.e.e.L.e.b.3bJ.L#c.I##aM#9bU#Gbq#c#G#c#G#c#9#caS.e#Q#zbq#zao#Vaoao#zbn.KaM#k.zbUbU#p#.ao#RbGao.uaoav.4#zbqaIbn.r.8ba.4#F.K#z#G#9#9#zbq#zbU.Kbq#F.Q#c#G#V#G#p#za9.I#G#G.Ibq#Q#T#Q#Q#c#####y.Q.L#GbD#y.bbebs#K#KbD#Q.nbAbLaXbDbDbDaObD.jbe.j.j.jb6aAam.Y.Ybk", +"#i#iaY#CbDaJaJbebebebyby#K.C#l.z.z#4#ybsbybebe#QaO#Q#4#FaS#y.5#Q.eby#Q.8#9#G#Qbq#F#V#l#G#4.zan#c#F#G#9#9#9a9boavav#zbU.K#GaM#V.z#4bU.MbU.KbYbnbU#Jao#Fbm#Fbn.C#F#Jbn#9.Ibn.C.C#F#z.Ebo.r#V#VaoaMbU#pbn#G#l#9bn#9#VaSbq#c#Q.ebJ#j.I.L#p.I.3bJ.C#9#T.qbJaM#Q#pbybs#y#Q#Ra1bLaXbtbe#i#n#5#ib6b6a0#iaY.Y#ubk#ubk", +".pbx#n#i#naCaJbebyaJbyby#pby#laR#laXaSbJ#7#qbL#ebJaM###F#c#GaR#q.CbsaS.BaM#G#J#l.z#4#QbU#cbqbU#z.r#JbQ#J.r.r.r#z#zaSaI.K#G.r#l#g#g#VaS.K.CaQ.MaQ.M.M.M.MaQaI.Kao.3#V#VbUbq#F.C#FbU#z#V#lboaFaF#JaM#V#GbUbnbU#p#V.h.8#g.4#l#F#4.8#yaS#c#k.8#9.C.I#gbQan#l#4#Q#caS.Ka9.O#R.h#4.S#C#Abe.t#n#5bx.y.y#i#i#i.0#2bk", +"#Sbx#5bxbt.tbtbe.l#a#T.hbTbT#JbT.zbTaS.AaR.L.A.n#4#GaM#.bhbS.P#k#q#G#4#j#4an.hbX#g#gbQaMaM#J.4#o#H#R#Xbr#J#9#9#z#FaQ.C.EbU#Gbg.E#G#l.MbUaF#9bm.MaI.MaI#z#J#zbfbnbn#G#Gbq#.#z.KaQbUaSbU#Vbo.4ar#obGaraF.z.r#Gbn#k.4#k.4bp##bq.z#X#l#GbQbQ#l#F.C#VbX.4#k.z#kbQ.z#la9bG#H.O.4.4#j#j.l.5aR#7a.byaJaJ.W.laJ#d#sa5", +"#iaY#S.paY#sbWb7.mblbC#R#T#o#J#T.4#JaS#c.A#q.A#g#4bU#.#paMbU.5bT#T##.u#j#9#l#G#4bo#k#j#kar#X#Ybj#Hb5b5brbo#zbU#F#z.C#p#G#GaS#G#l#J#G.C#F.C.rao.C.KaQ#9#9aI.C.K.K.8bobUbU#F#GaS#F.K.K.K#G#z.r.h.ub5#H.uarbG.4#JbG#k.z.z#G#l#G#l#t#j#j.8#oaFbq#4#z.4#J.z#9bo.z#9.Kbq.4.w#H#B.4ararbobU.5brbT.E.E.E.h#g.5bvbw#d", +"aY#IaHac.HacbdbEazb9#h.O.4bX#kbG#k#g#caM###a#kaR.zbo#9aQavbU#X#RbH#R#t#g#9.I#V#k#g.8#Rb4#Y#Xb5#H#farbGaFaobUbU.K#pbU#GbUaM.E#G.r#m.z.KbU#G.CaQaQ.M.MaI.K.K.KbnbU#kbU#FbU#V.K#FaS.C#p.C.KbU#z.zbFarar#Hb5#Rbj#R.hbQ#k.8aM#9.Ebo#t#mbH#H#t.u#G#9a9bQ.z.r#Vbo#J.EaI.e.8#O#t.8.4#o#o#Hbc.r.6bTao.Eao#f.9b5#B.h#q", +"#7#E.vaHa#.H#1aV.mbl#h.8bQ.4#k.B.4.4#Q#G#4aR###T#k.zbobq#G.z.8.PbQ#k#obG.z.z#k#o#g#objbj#H#Y#f.uar#Bax#z#.bU#G#Q#paQaMaMbo.A#Jb4#PboaMaobq#z.Mbf.M.M.M.M.KbUbUbU#J#p#F#GaSaM#G#pbhbU#zbU.K.K#V.rbo.6.u#f#H#H#R#j#kbQ#o.8.h.rbTbT.8bG.3bQ#oa9.r.raF#Jbo#9#J.D#9.K#c.B#t#t#obQ#o.har#obcbr.6aobY#waLaL.9#f.uar", +".F#7#I.v.Y.pa##7awaPbl.3an#k.3.8.8.8#9#Q.3###k#k.3.z#Ja9#z#k#obo.8.8#o#o.hbQ#9#4#R#R.Gbj#Haray.6.D.rbYbY#F.K#p#laMbJ#laM.h#lbr.G#H.E#l.r#lbY.Mbf.M.Mbf.MbnbUbUbUbo.8#o#l#VaM#GaSbqaM#F#p#F.KaSbYaoao.D.4#o#Y#H#R.4.B#oaM.z#o.4#Xbj#t#o.h#Xbo#4#J.3aF#J#J.4aF.4aF.zbX.G#t.8#k.4aF#o.h#Jbgbo.EaM.E.6#Zaeae#Z#f", +"bOb##7bW.v.p.Yama3#O#8aX#4###k#j#obX#Q#Q###7####bG.I#BbQ#9bobX.h.u#o.4ar.O#Y#HbQ#R#t#Xar#8ar#J#J.rbcbc.CbYaS.C#c##.5.zbg#l.P#YbC#J#9bQ.r#G.K.C.M.C.M..bf.K#z#V.r#Gbj#bbQaM#z#Gbobo.EaQaQ.r.C#FbqbYbcaoax#J.h#X#j#o#R#k#X#bb5br.u.h#8.ubX.Oan#J.3bQbo#JaFaFaF#Jbo#J.B#Y#O.u.4.hbrbr.4bTbU.E.Abo.raoae#f.6#fb5", +"bO.FbWbW.v#7.pbW#N#N.n#l#4aRbL#jbX#8.I#q#####T#k.4bqaF#Ja9#9bG.h.8#oarbj#b#baq#X#k#Y#e#o.h#J#J#zbS.M.Ebo.EaSaMaM#l#k.zbgaM#XbC.G.r#JbTbo#V.K#p.M.Mbhbfbfbq.EavaM#z.4#Y#o#GbU#Qbo#4#VaSaS#p#V#lbY.M.K#z.Eav#JbQ#T#j#X.4bH#mbjbG#H#R.u#g.4#g.zbQ#kbQbn.I#z#J#J#J#z#zar#D.O#Baxa9#J#JaFboaMbSbUbgbzbo.E.6brarbj", +"bJ#aa.a.#7.v.Y#7#M#EaV#4#7#k#k#g#o.u#9#Q#l#Q#l#l#oa9#B#BaF.4#8aF.hbjaq#baqbj#H#taFbj#obT.z.r.MbY.MbYbY.E.4bg#l.PaRaR.5#oaSaMbT.4bobo#J.zbo#V#GbUbq.K.Mbf#G#z.r#9bo#Gbr#k#VboaMbT#l#V#l#G#G.z#F#pbmbfbYaI#VbQ#9bQ#R.4#j#H#X#Y.4#X#b#t#j#8.O#k.8bQbQ#V#Vbq#9.4.rbqbn.u#Yar#JbZboax#JaFbT.EbgaJbzaM.h.Abg.5bObr", +"bzbLbW#a#7#I.Y.S.Y#7#7#aaX###T.8#X#j#l#lbo#G.K#.bo.D.4#Bayarbj#o.u#m#m#H#Z#R.uaraF.8.hboaM#GbU#pbU#cbU#k##.h#q#k#8aR##.z#q#G#zaMbTaF.h#J#l.E#G#4#GaS.C.M#z#z#9.r#z#9#V.4.zaMbQ#l.z.h#Q#V.z#9aM.C#9bn.K#G#G#9#k.r.u#l.4#oar#R#B#X#X#j#o.O#t#o#R#j.8.z.r#9aoaF#zao.r#X#X#oaFbo.r.PboaF.P.E.EbSbv.P.P.P.E.5#X#e", +".A.Y#7a.bJ.p#7#7.S.Y.Y#a.A##.zbQ.4ay.zbU.KaS.r.4#Barb5#L#HbG#H.8#o.u#Z#XbGay#B#J#l.E#o#QbU#l##.z.C#c.z#kaR#k#g.A#o#T.P#caM.K#.bo#JaF.4aMaMbo#l#l.z#9.KaQ#F#F#z.r.r#z#9aF#JaM#V#V.8aM#l###l#Q#4#4.KaQ#l.3##bo.r#kbQ#Van.z.4bGaF#H#Y#R#j.u#X#o#t#Y#X#X#o.4.4bGbo#l#4#R#j#gaF.PaoaM.raMaS#.#.aJbtaY.PaR.AaS#k.h", +"a.a..A.p.S.Sa..v.paYa.a.bJ#4.z#J.4bG#J#V.z#X.u.u.uah#Zah#Hag#H.4aFaFbGar.DbZboboao#9#.#V#Q#Q#QbX#g.CbJ#g#g#Tb#.h.A.h#laM#G.E#VboaFbrbT.rbobT#l#GaSaS.CaQ#p.KbqbobQ#J#z#zbQ#9#G.P#Q#9#TbQ##.zb1#GaQ##.8#l#9bQ#9bq#z#Vbo#9a9.ra9.hbG.h.4#g#j#o#t#Y#j#Y.u#Rbrar#Jbn#G#k.z#4aM#9#GbUbg#lbv.WaJ.WaJaJbzbz.5bzbvaR", +".p.Y.pa.#da..pbw#1#S#C.S#c#p#obG#LbGbF#Jbr#H.u#H#Hb5.wae#BbFb5#B#J.4bobo.r#z#zbcbUaQbUaXaM#y#p#c.B#k#p.z#O#8#k#g#o#laM#J#kaS#JbT.hbrbobo.PbTbT.z#laM#F.K#F.K#VbQ#BaFa9#Va9aM#zbq#4.4aR.B#g#R#Q.C##bp#G.C.e.z.z#V.C#F.K#z#Gbn#Ja9bQ.4.har#o#T.u#X.u#Y#Rbj#oar#R.4.zbp#9.I#l.r.EaMaM.EaS.A.SbtbxaJ.lbvbz.5.S#a", +"bk#6#s#s.0.0#n.Ya3bdbJ#laS.K#J.4a6bGb5ahah#Zb5.9.9b5ae#BbMbo.9bG#9ao#V#zbcbU#zbUbo.P#lbo#4#F#p.C.P#8##bD#k.G#O#k.z#4aM.zbraM#JaF#XbrbT#l.h#lbT.h###kbQ#G#9bU#GbQ.u.4#Jbo#9.r#V#Gbo#4#k#Rb4.Ibh#T.B.zbh.K#F.z#V#F.IbQ.I.z#9#GaMbqao.z.4#X#j.z.8#k#j#j#objbXarar#o#X#R.B.hbQ#J.4bo#J.zbu.GaR#C.WbxaJaJ#C.0#C.0", +"#6#6#x.0a0.0bx#C#7#ObH#X#8bGbG#L#Za4#Zb5b5#D#Lag#B#BayaF.Dbo.9.4avbn#z#F#V#z#G#9.P#b#R#4#4#4#QbJ#g#g#X.4#y.8#8.z.EaMbU.raM.4aF#obj#g#J.Pbu#o#8#j#o#o.8.z#9aM.z#J#o#RaFaFbo#zbo#Gbg#V#4#j#4#y.h#T#k.zbq#G.I.Ibh#Q#R.8#kbQ#V.zbobU#.#z.3.u#o#o#k.4.8.4.3.u.4.u.O.uba#R.wbj#o#J.r.rbQ.Tb9#O.l#Cbg#C#C.0bw.p.Y#d", +"a0.y#Sb6b6#S#C#Cbgb4#t#tbG#H#m#Y.9.9b5ae#L.9#BbobF.DaF#Jav#9.4aF.IbqboaS#F.z#VaMaM#gbHb4#yaMbl#8.B#g.h#8#TbU#k.z#G#GaMaMaI.zaFar#X.4bo.PbTaM#a.h#o#o.P#GbUaMaM.EbGbjbGaF.raI#9ao#QaSaR#lbJbQ.8#T.4.8bQ.3#caQ#V.O#RbQ.z#k#k#G##aM#9.K#l.8.4.8bQ#k#o.8.8#o.8.u#H#j.w#Y#Y#Y#D#H.u.ub5#h#hb4#cbg.l.lbv#i#C.0#i#S", +"#6#S.0b6aY.lbJbL#O#bbabF#baqb5#Zb5ae.9ayagbF#BbF.4bQ#Janbo#9.3.ObQ#Gbn#9#l#kbQ#Q#G#c#j#O.n#c.z#t#P#e#j#g#R#g#paM#G#z.E.K.rbTaF#R#XbT.h#eb4b4#O.Gaz.G#Y#t#X#o.h#g#o.uar.4#JbU#z#l#VaMaM#ybT#T#k#g#o.8#T#V#F.z#t#O.4#Fbq.I#obQ#l#G#V#G.4#j.8#k#g#o#g#j.u#o#jar#o#o.u.w#H#H#Z#Y#D#Z#B.u#H#H#g.hbubO#IaY#d#d#S#S", +"#S.p#i#ibw#abubH#X#tbG#Haha4b5.9aybF#B.DaF.D#Ja9ao#9bq#Fbq.K#G.8.O#GaQ.e.8bQ#4#QaS#p#c#8.G#8.L.nbl#PbH#j#j#j#4bg#Vbg#9#zaFbr#H#earbo#8bCb9b9bCbC#3b9bCb9b9bC#h.haFbr.uaraF#Jbq.raM#Vbg#4#g#g#j#j#8#R.zaS#k#b#tbQ.C#p#F#l.z#gbobqbUbQ#g.8#o#T#k.3#j#X#R#j.O.u#oarbGb5.ub5#H.9#Zbj#Z.ubr#8.h.P.5blawaw.FbW.p#0", +".la.#a#C#q#7.5.n.8#jbGb5#L#Zag.Dax.Dal#BbFa9.r#9bq#G.Qbf#V#cbq.I#o#t#Q#l#QaM#4.z#c.C#c##a1#O#O.h.Bbl#P#R#abT#l#G.EaMbUboaF.h#Hbj#mb4.GbCbCbCbCbCbC#hbCbCbCbCbC#P.4#oarbGaFaFaobU#l#l#c#G#4bJ#g#X#b#kbU.8#h#Y#j#VaQaQ#y.8.z#9#G.C#l##.4.z#4.4.z#k#T.z.z.zbo.zbQ#JbFbG.Da6ayar#Zb5b5.ubr.h.hbTbzaz#Paw#NawaV#M", +"#a.Ab#.A.l.AbL#8bOaEboarayagalalaxbF.Dax.rav#z#9#FbqaQbh#G#Vbq#G.z#j.u.I#y.C.z.PaM#paX.h#kbHaw#Obg#T#t#T#laM#Qbg#V.EbSbT.4brbj#X#X.G#3#PblbCbCbCbC#hbC#hbCbCbC#PaFararar.4aF.zbU.E#VaR.LbgaM.z#R#TaSbGbC#P#j#k.3.e.C.I.h#9aQaM#gaE#l.z#G#y.I#caS#4#F#F.ebU#V#9#Va9bFaFaF#Bayb5ar#Zb5ao.4bu.5.4bu#8b9#O.mbCbC", +"bo.raM.5#laJ.5aV#T#e.8aFbF.DalaTaxaxaobo#Ja9#V.r#9.3#G#Vbq#z#F#V.4#Q#k.G.zbU#Q#l#TbH.haR#TbA#R#3#8#G.P#Rbg#G#GaMbgbTao.P#obrb5#X.4#l#o#Pbl.Gbl#P#3#3b2bCb9b9bC#O.rbT#oarbGaF.4#G#G#c#G#Q#GaS#X##bU.8b9#P#X#o#k#k#g#R.8#Gbh.Q#j#Obo#G##aM.eaM#G.e.z#QbU#G#z#Qbn#z#Ja9#J.D#JbFbrbGar#o#laMbo.Pb#aMbHbC#O#hawbC", +".r#J.Ebo.5bJ.lbL#E.n#g#4bFaxbZaxao#zbqbZbr#V#9#V#z#9#Vbqbnbn#9#zbo#V#kbX#P#k.KaS#k#j.n#X#j.h.h.d#Yb##c.zaMaMbg#Vbgbo.h.4br#ear#o.PbT#ebH#8bl#P#b#R#j#P.T#b#R#PbH.rboar#Xay#BbQaF#G#GaM#caSaM###G#k.G#b#o#8#jbX#o.8bp#lbs#Fb4#t.z#y.e#4#Q#F#y.Q#F#l.C#F.C#y#zbUbQ.4#z#Ga9.r#Jax.4.4bo#k#..5aRbObu.5b9#eb9b9aw", +".EaFaMbg#kaR.L.lbLb##4bo#9#9av.x#z.Cbn#9bQa9.KavbQ#JbF#Ja9.4aFaF.4#k#9#G###3bT#G#G.PbH#Pb4#X#T.h#jbH.haM#GaMaM#QbUaMbTbr#ob5#X.hbo.5#j.h#k#8#R#eaM#l#g#R#e#k#g#RaMao.4ay#X.4br.z#VaSaM#Q#GaS#c.8.G#t#R#8#o#R#R.G#j#4#p#G.O#O#l#G.Q#G#T###l##.z.z.8#l.z#l.8bQ.3#j.h#V#FbU#9.I#9bo#laM#l.A.l#ab#a3b#bOb4bl#eb4", +"bT.PboaMbg#k.5#Q#q#gaR.PbTbTboaMbq.Mbf#9a9#9aobo#JbFaFbrbF#B#BbQbQ#G.zbUaS.z#P.8aM#VbQ#P#P#R#X#o#k.8.h#4#l#VaM#GaQ.zbT#o.G.G#Xbrbo.PbTaR.h#4aR#j#G#VbQ#R#X#o.5bT.4.E.4ar#H.ubrbrbo.CaSaM#Q#9#9bQ#t#g.h.u#t#R#3#tb1aS#G#tbH#G.L#Q.Q#G.q.I#c.I#caS.z#y#V.zbo#9#R#J#4bh.C#G.I#9bo#l.z.z#qaM.lbzbW.VbObzbO.5aJbg", +"bTbT.5aRaM#q#q#a#paRbH.5###o#R.I.ebhaQ#VbobF.4bQ#BbG#BaraFaFaFbQ#J.z#l#9#G#G#J#P#gbgaSbo#P#h#RbQ#z#laM#z#Q#V.E#y#V#kbr#ebjbjar.z.h.h.P#4#k##.8#T#V#G#V#k.z#k#g#g.h.rbo#objb5.ubG#k#V.C#GaM#V#VaM.4bo.z#j#b#ha1#4#F#G#ta1#c#y.eaS.e#GaX#9#GaX#9#Q#l.z.8.8.4.8#k#9.z#K#p.e.I.8#j#l#T.P.A#q.A.AbLb#.FbO.5bvbS.W", +".5.5.P.5bL#4#q#4bJ#q#kaM#4#T.O#G.Q#F.C.Q.rbQa9avar.D#J#Vbn#z#VbQbp#l#9aM#QaMbJbQ.T#X#p#ybQ.G#k#l#l#R#R#Y.G#kbqaQ#l###jbj#R#X#gbobUaM#Q.z#8#t#8#VaS#V#FbT.zaMbgbo#k.rbTaFb5.Obj#X#j.zaQ.I.8bX#R#H.I#c#G#k#t#R#G.eaM#b.d#9.QaQ#Q#p.e.L.I#Q.e#Q#G#F#4.4#o#XbQ.z#J.C#c#c.Q.C.e#T.8aMaMaRaR.5.F#g.A.Y#1bdbzbibibf", +"bz#7#7#7.A#7#7aRaR.AaM##bQ.zbp#Q#V#Q#G#Fa9bQ.Dbo#BbF#J.r.I#Vbq#4.z.z.I##.z.z#4.e#4#P#X.QaM.PbX.h.u#Y#b#P#b#l#F#FaMbQ.h.B#X#R.4#lbgaM#l#g#o#j#j#k#G#z#.bQ.z#V#q.PbobU#J#o#Hbj#obGbQ#9#p#9#t#m#b#Y#X#Vbq#b.zbobq#Q#P#Xbq#y#Q#G#Q#c.Q#canaX#4b1.z.z.3#kbX.4bQ.4.3bo#l###4###lbX.8#4#gbT#kaR.5#8bE#e.H#Eb#aJ#pbi", +".AaR#q#qbLbW#qbva.#qaJaM#l.8ahbq#Qbhbq.Qbqboaxbo.DbQ#V#9#9#9.Lb1##.f#4###k###QaM#k###O#8.e#ybQ#T.z#J#Jan#l#G#F#Q#o#b#h#P.h.z#kbobo#l#lbT#T#o#o#k.rbobobo.E#QaM.z.P.zboar.4bX#H.T#bbG#9#FbqbQ.8.c#4#QbQ#g#V.e.z#baE#Q#yaSaS#QbJ.I.e.e###Q#Q#Gbqbq#V.z#l#9.z.zaF.I#GaM#y.e#F.8.4aM#k#laMbg#l.5b##E.A.YbWaM.E.E", +"bz#a.YbWbz.S.S.AaJ#qaM#T#taqba.kbq.e#V#V.r.rbFbo.rboav.I.zbp.e#Q.X#4#l.3#kbL.z.n#g#Q#4#O.u#c.C#V#F#9bq#V#z#9.C.z#R#hb2#h#Y.z#G#Q#l.z#k#TbQ.PbQbQ.z.zbo#Qbo#k.P#kbQaM#9#9aF#bb2b2.T.O#9aQbn.xbq#z#V#Q#V#V.e.I.GaE#GaM#Gb1#G#Q#4aMaM.e.3#G#Q.I#Q#V#V.I#9bobo.4#g#9.z##.Q#F.e#Q#G#4bQ.P#l#qaM.5#4aV#abW.AbzbY.P", +"#7.H.pbva..Y.A#4##.4#j#j#H#ObXbX#jbG.4.4aFaF#Ja9bo#JbQ.z#4#4aM.IbobQbpbQ.nbQa1#e#4.e#9an#t.O#F.I.za9#JbMa9#zbnbF#tb2#hb2#b.4aMbg#l.hbQ.z####.z#l.z.z#kbQ#JbT#kbQ#l#V.rbM#oaq.Tb2.T.wbQbq.Cao#9#9bo.zan#Q#J#O.8#GaS.C.ebU.Q#p#V#G#Qb1#k#4.z#T#k#4#Vbo#Jbo#kbGaE#g#g#j.B#T.3##bX#j#R#t#X.h.5bAbLb#am#7aR.5bv.E", +".S#S.l#da.#qbgaX#4#Van#JbQ.O#b#b#H#R#oarbG.3an#9.z.h#gbX.8bp.zbQ.3an#JbQaRbTb##4#Q#9#Q#9.I.uboa9#9an.Iao.rav#JbG.waqaqaqahbQ#Q.A.z#o##.z#k#Jan##.zanbQbQbQ#kbQbQ#k.r#9#waFb5#Daqaqah.4an#wav#z#Vbob1#9an.U.4bU.K.C.CbhbhaQbf#laQbh.K.z#G#q###4boaM#9bobo.z.8#T.O#RbHb4#tb4a1#t#j.G#O.Gb4#k#a#7#E#qb#az.5#lbT", +"#q#q.Abvbg.A#lan#J.1#za9.u#b.G#O.w#R.u#R#o.8.4##.3.4.4bp.4##an#l.3an#G#l#Q#caMaM#G#9#G#9a9#9.I#9.I#9avbVaoaI#V#o#Haqb2a4bG#JaMaM#l.z#4bQ.z.z##.r#G#l#9.zbQ#kaF#k.zaM#z#V.r.4.9aLa4ahar#9aIbcbn#V#zavanana9.3bpbQ.z.zbQbQ.3#k#k.8.8.zbp##.3bL#kbA#k.4.8.4#k.Obp#ea1#OapapbH#O.Gb4#Xb4b4.Gap.n#ab#bLbL#8.Pbo.P", +".Pbz.P.5aR##a9.3an.1bQar#R.G#b#t.O.ubX.u.uaEbXbX.8.8.8.4bpanbp.8bQ##an#4#laR.zaXanbQana9a9av.r#9.I#VbZ.xaobq#VaFa4a4#D#Ba9#G.E#l#4bQ.zbQbQbQbQbQ.IboaM.z#J#kbQ#k#k.z#VbobUbMbFaea4.9#Baobm.1aI.xava9a9an.I#Jan#F#F#4bp.e#c.O#T#X.B#jaE.B.q.q#TbA#g.8.4.3bpaE#8.d#RbHb4#tbH#ObH#t#O#R#8bEapbE#8.naX##.5#o#obr", +"###kbT#k.h.3#TbXbXbGbXbX.4bXbXaEbaaE#T.U.8bXbX.BbX.UbX.BaE.BbXbXaE.U.n.B.z#c#g#X.B#Van#Janan.ra9boa9bZ.xavava9a9a6agaL#LbF#FaM.zbobTbT.h#kbQ.z#J.z#J#l.z#J#kaF.4bQ.z#l.z#p#Va6b.aeag.Da9.xaxbnbc.xavavbM#JbM#9.C.Qbq.Q#c#Q.fbA#8.n.B#Oa1.U.U.3.s.O.BaE#t.d.d.Oa1a1.daE.O#t.O.OaEaE.ZaEa1.na1aE.U#8bA##aR#kbT", +"###TbL#q.3.q.B.U.8.8.4.8an.BaEaE.BaE.4.U.BaEbXaE.U.c.3.B.BbG.U.Bbp.3aE##.faS#Q#9#V#F#F.1.rbMbQa9.I.raU#w.x.K#zavaUaf.Na6.1#p.r#JbT#J.8.u.4.4.4.z#J##bo.zbQaF#k#T.h#k.z#lbUbYaf#v#vafaf#9bmbnau.x.xbM.Da9an#J.3.1#F.e#Q#G.L#Q.L.3aEbp.UaEaE.ZaE.d.s.3.BaE.Ba1a1.d.UaE.waP#b.daE.B.U.Z.Z.s.ZaE.Bbp.s.A#a#ab#aR", +"#a.S.S.L.SbebDbD#Q###q#G#4.3.f.f.Lb1#9#Qan.Xb1b1.I#lbp.4aWanan.8.q.q####aM.Q#F#9bX.4.QbMan.I#9bo#9avau#waobc#9aoaN.N.N.D.Kbn.zbQ#H.G#Y.G#b#bbj#P#m#b#b#b#P#b#b#b#Y#RbGboaM.M#wa2.N#UaobZauaI.R.x.x.xavax#JaW.4aW.b.I.e#c.e#c#Qb1bpbp.U.s.BbpaE.U.B.q.UaEbA.U.U.q.q.B.B.XanaW.8.U.XaAaAam.SaO.L#c#0.pama.bWbz", +"bd.v.Y.p#nbeaCbe#qbOaR#Q.C#F.e.ebh#G#K#p#y.Qbhbh.e#p#Qb1bq.L#p.eaO.Q.Q.L#G#9bq#zbQ#9#V#9#9a9#9avaobc.xaUavavaoavbV.NalbV.MbqbQbG#X#Hbjbj#H#Y.w#Y#b#t#b#b#b#Y.G#Y#b#b.u#kbo.M.R#v.gaBbMavao.xaoauaI.1bZa9.D#JaW.8anbq#Q#F#c.I#9.f.ebh.e.L.L.b.L.f.q#QbDbJ##bDb1.L.q.Ubp.C#F#Gb1.fbD#0ambdam#naCbeb6#6.p.Y#2.p", +".v.va..paYbe#0#0bebJ#a#qbJaX.Qbsbsb1.l#ybD#ybs.e.bbg.L#G.B.q#Fb1bf.Q.C.I#J.I.r.I#9.1#V#9#V#V#9#V.x.xau#wbc.xbc.R#r.N#vbM.x#J.8.zaF.Ibnbn.8bG#obX#o#o#o#o#o#o.e.Cbn.4.zaF.hbcaN#rbb#vaN.xbcbmbnauaI.x.1aoavan#Janan.f.K#G#l#l#4.I.Lbs#K.Q.e.LbPbp.f.fbDbD.L#K#Q.fbp.U.3bs#F.C.b.LaV.Ha#.Hac#1.paCa0ak#2ak#2#2", +"#7#IbkaAb6b6.SaA.Lby.l.A#q#l.L#Qbs#QbLbg#K.e.e.bbA#Q#QaEbA.3.La1.L.e.C#9.r#J#J#J#l.I#9.f#V#Q.1#z#wauau.x.xau.x#w#v#vafafao#J.4anaFbobq#z.4#o#jar#obXar#jbX.8bq#F.x.4#J.P.4bcbVa2ad.NaNaubmau.RauaIaubcaoav#V.1.Ia9#J.Ibo#JbQbQan#Fbs.Q.b.1.L.X.saX.faX.l.L#q#4bJbp.B.BaQ#F#yb1amamam#6#6ak.H.Ha##x#6#2#2#2bK", +"bO.5#7#aaO.S#0.S#0#Cbe#Q#q#Qb1.L.Q.L.f.e#y.Q.e.e#Q.L##.saEbp.eaE.I#Q.Q.x.I.4bGbFbo#9#9#V#Q.x#Gau.xajauauan#w#w#r.Nb.#raTbZ#J#J#o#t.u#o#obj.w#b#b#P#b#b#b#b#b.u.4b5ahbG.r.zbcbV.o#v.NaBbMaUbV.xbmaIaIau.x.1av.x.I#9.I.zbQaF.h#J.z.Qbsbq.L#Qbq.X.B.ZbJ#qbJbJbJ.baXbJ#4.3#K#Q#V.qaX.Y.Ya##2#6#6aGa#b6aY.p.H#M#M", +"#T##aR.5#C.S#7bDbD.SaSby#c#4.fbP.Q.Q.e.L.b.b.X.f#QaOb1aE.BaE.faE.X.1.Q#9#B#JaF.4#l#9#Q.1#G.1.xbcaUajau.xbMbM#raT.N.gaTafaFaF#k#X.O#X#R.O#H#X.O#t.w#H#t#H#Hbj#X#j#ob5.ubT#J#GbI#ra2a2#vbV#UbIaU.Rajbm.xbn.xao.1.1a9ava9bQ.8.4bM.r.Q.C.f.I.f.e#QbAbEbLaXaAaX.L.l#cbJb1#QaQ.Lb1#TaVam#1ama#a##2a#a##iaAbW#1bWaH", +".z#4aRbL#Cbvbz#n.laJ.l#y.lb1.I.I.Q.Q#V.e#yb1bJ.e.L.L#4.saP.d.f.B.q.X#F.1an#z#JanaM#V#Q#V.1#z#w#w#U.RaubVbM#Bb.b..gaB#vag#B#o#X#8#Rbj#Y#Y#t#t#Y#Y#Y#b#P#b#b#b#b#Y#b#tbjbjbjarbFa2a2a2ata2a2aB#raN.ibmaUaNau.x.1#9.1#V.Iav.3#JbQbo.Q.C.fb1bqaO.LbpbE#7#0aV#Q.A.qbD#y.5bP#KbPb1.U.s.n#I.Y#1a#.va##6.0#6.YbWa8a8", +".z#4aRbW.l.l#n.Sbz.l.WaS#QaManb1.e#FaM#Q.LaM.eaX#T#q.La1.daPaX.Z.q.X.1.8anbq#9#l#9#V#V.1#z#w#w#w#Uaj.Ra6aW#LaLaLat#vaB#wbn#F#..C.C.C.C.C.K#p.K#p.K.CaI.K#pbU#paI.C.C.KbU.KbnbmaUaBad.Na2bbbb#r#r.iajaUaN.1.x.1#z.1#9.I.1.I#F#G#G#F.Q.fb1.e#Q.LaXaVaAb7a3aV.LbL#8.L.A.f#KbP.faE.n.naV#Eamac#1bk#6b6bka8bkbkbk", +"#abLaH#I#dbx#C#I#CbDbg#q#kbQ#Vb1bq#F.3#g#Q.e##a1bAbpbJ.f.saPaXaV.qaW.bb1.C.xan.I#9#Q#V#V#w.xaUbV#r.a.aalbFba#Latada2alaN.Kbhbf..bfbfbh.MaQaQbh.MaQ.Mbh.MbSbUbS#pbfbf..aQbh.CaIaUaBa2adadadbbbbaBaj.RbI#waN.xaoav.1#V#9ana9.1.Q#F.b.Q.f.f.b.f#QbJaX#7b7.ZbdaX.LbL#abJaO#KbPbP.UbA#g.5b#b7am#1a##6b6#6#6#s#2.p", +"#7bWbW.t#i.0a.aJbDbJ#laXbQ#F#Qanbq.e.B###GbJ.X##b7aV#7.s.f.Z.X.U.qaW.b.ebqaW.r#9#9#9#9#9.x#w#U#r#r#r#rb.a6baa4aLa2.oaTaIbh...MbfbfbS#p#.#p.K#p.K#p.K#.#paIbgaI#z.2.Mbf.Mbfbf.MaNbVbbadadadbbbbaBbR.abI#UbIaua6.w#D.w.w.w#t#ta9.e.Q#K.I.f.Q#Q.faAb7#0b7#M#1#0.q#QbJbL.f#KbPbP.L#k.n.5bObAb7aV.v.0.0.Y.v#I#I.p", +"b7#CbtaJa0#i#C.lbJ#l###4#c#G.fan#Q.e.b#Q.LaM#7b7#Mb7.YbE.s.X.L.X.q.q.bbq.I#9#9.1ao#V.I.1.xbI#U.o#U#U#vaTafa6aLata2aB#waQbfbhaQbf.M.M#p#p.C#p#p.KaS#..K#..K.K#.#pbS.Mbh.C..bfbfaIbV.oadadada2.oa2#UbIbR.obIaN.x.waq.waqaqb2aq.wbq.Q.bbP.L.Q.Lb1aVb7.pbdac#1#7b7#7#QbJ.Q.Q.f.X###q#7#a#j#g#E#EaV#S#S#1#7#a.p.p", +"#aaJ.S#d#S.0.l#l#4#4#l#G#G#G#Q.X.L.b.Q#Q#cbJ#7.Z.Vbd#s.V.d.U.fbPbpaW.bbq.I.1#9ao#9ao#9.1aNbI#U.o#U#Ual#va6b.aL.Na2aB#w.CbfbhaQbhbhaQ#p.C.C#p.C#p#F.K#p.K.C.K.KaQ.MbhbfaQbf.Mbf.CaUbIadbb.o.o#UaB#rbRbR.o#UaNaua6a4a4#D.w.w.waqb..Q.QbP.f.bbJaX#kb7a.bdaKaH#EbE.s.X#Q.Q.Q.f.fb1bL#4.A#g#g#gb7aHaAaY.vaR#a#a.Y" +}; +#endif diff --git a/rce/rcecalib/server/bootloader.cc b/rce/rcecalib/server/bootloader.cc new file mode 100644 index 00000000..b26b471d --- /dev/null +++ b/rce/rcecalib/server/bootloader.cc @@ -0,0 +1,201 @@ +/// @file core.cc +/// @brief As the last part of the initialization of the system after +/// a reboot, load from flash, relocate and run the application module +/// selected by the RCE front panel. + + +#include "rce/debug/Debug.hh" +#include "rce/debug/Print.hh" +#include "rce/shell/ShellCommon.hh" +#include "rce/gdbstub/rtems-gdb-stub.h" + + +#include "rce/service/Thread.hh" +#include "rceusr/init/NetworkConfig.hh" +#include "rceusr/tool/DebugHandler.hh" +#include "rcecalib/server/EthPrimitive.hh" +#include "rcecalib/server/CmdDecoder.hh" +#include "rce/dynalink/Linker.hh" + +#include "rce/pgp/DriverList.hh" + +#include "rcecalib/server/BootLoaderPort.hh" + +extern "C"{ + #include <librtemsNfs.h> + #include <rtems/malloc.h> +} + +//#include <omnithread.h> +#include <pthread.h> + +#include <exception> +#include <stdio.h> +#include <string> + +#include <iostream> + + +// We need to include <iostream> so that symbolic references to +// std::cout et al. are made. The weak definitions will therefore be +// picked up from libstdc++. Modules are not linked against libstdc++ +// so they rely on the definitions in the core. +#include <iostream> + +/* +// for speed test +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <netdb.h> +*/ + +using std::exception; +using std::string; + +using RCE::Shell::startShell; + +using RceDebug::printv; + +using RceInit::configure_network_from_dhcp; + +using RceSvc::Exception; + +using RCE::Dynalink::Linker; +using RCE::Dynalink::LinkingError; + +// use global IP address of bootp server in RTEMS +extern struct in_addr rtems_bsdnet_bootp_server_address; + + +namespace { + int majorVersion=1; + int minorVersion=4; + string branch("devel"); +} +extern "C" { + + // This symbol is set by the static linker (ld) to the start if the + // "dynamic section" which the linker uses to find the system symbol + // table. + extern const char _DYNAMIC; + + void *posix_init( void *argument ); +#if RCE_INTERFACE == 1 +#warning RCE_INTERFACE=1 +#elif RCE_INTERFACE == 0 +#warning RCE_INTERFACE=0 +#else +#error invalid RCE_INTERFACE +#endif + + + unsigned interface = RCE_INTERFACE; + void init_executive() + { + try { + RceInit::configure_network_from_dhcp(interface); + RcePgp::init_pgp(); + + (void)Linker::instance(&_DYNAMIC, majorVersion, minorVersion, branch); + + printf("starting shell\n"); + startShell(); + // Start a debugger daemon + // First arg = 0 --> use socket IO over TCP. + // Second arg = 0 --> Priority is chosen by the debugger daemon + rtems_gdb_start(0, 0); + //rpcUdpInit(); + // nfsInit( 0, 0 ); + // printf("BOOTP server is %s. Use as NFS server.\n",inet_ntoa( rtems_bsdnet_bootp_server_address)); + // nfsMount(inet_ntoa( rtems_bsdnet_bootp_server_address), NFSDIR ,"/nfs"); //NFSDIR comes from constituents.mk + pthread_t mthread; + pthread_attr_t attr; + int stacksize; + int ret; + // setting a new size + stacksize = (PTHREAD_STACK_MIN + 0x20000); + // void* stackbase = (void *) malloc(size); + ret = pthread_attr_init(&attr); + ret = pthread_attr_setstacksize(&attr, stacksize); + struct sched_param sparam; + sparam.sched_priority = 5; + pthread_attr_setschedparam(&attr, &sparam); + pthread_create( &mthread, &attr , posix_init, NULL); + rtems_malloc_statistics_t stats; + malloc_get_statistics(&stats); + printf("*** malloc statistics\n"); + printf("space available: %uk\n",(unsigned int)stats.space_available/1024); + printf("space allocated: %uk\n",(unsigned int)(stats.lifetime_allocated-stats.lifetime_freed)/1024); + + } catch (Exception& e) { + printv("*** RCE exception %s", e.what()); + } catch (exception& e) { + printv("*** C++ exception %s", e.what()); + } + printf("Done with init_executive"); + } +void *posix_init( void *argument ){ + std::cout<<"ATLAS Pixel RCE boot loader (built on " << BUILDDATE << " by " << BUILDUSER <<")" << std::endl; + // std::cout<<"ATLAS Pixel RCE boot loader." << std::endl; + EthPrimitive eth(BootloaderPort); + CmdDecoder cd(ð); + cd.run(); + + //this is for speed testing + /* + EthPrimitive eth(3434); + int length=1000000; + char *buffer=new char[1000000]; + eth.receiveCommand(); + sleep(7); + std::cout<<"Start"<<std::endl; + eth.reply(buffer, 270256); + std::cout<<"Stop"<<std::endl; + */ + +// more speed testing +/* + int sockfd, portno, n; + struct sockaddr_in serv_addr; + struct hostent *server; + + char *buffer=new char[251000]; + portno = 3434; + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) + printf("ERROR opening socket\n"); + server = gethostbyname("172.21.6.45"); + if (server == NULL) { + fprintf(stderr,"ERROR, no such host\n"); + exit(0); + } + bzero((char *) &serv_addr, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + bcopy((char *)server->h_addr, + (char *)&serv_addr.sin_addr.s_addr, + server->h_length); + serv_addr.sin_port = htons(portno); + if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) + printf("ERROR connecting\n"); + int flag = 1; + + int ret = setsockopt( sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag) ); + for(int i=0;i<100;i++)n = write(sockfd,buffer,100); + usleep(50000); + n = write(sockfd,buffer,212); + n = write(sockfd,buffer,10000); + + if (n < 0) + printf("Scheisse\n"); + close(sockfd); +*/ + return 0; +} + +} diff --git a/rce/rcecalib/server/bootloader_2.2.cc b/rce/rcecalib/server/bootloader_2.2.cc new file mode 100644 index 00000000..3c826cc3 --- /dev/null +++ b/rce/rcecalib/server/bootloader_2.2.cc @@ -0,0 +1,130 @@ +// -*-Mode: C++;-*- +/*! +* +* @brief Functions for bootstrapping the RCE system +* +* @author R. Claus -- REG/DRD - (claus@slac.stanford.edu) +* +* @date March 17, 2012 -- Created +* +* $Revision: 966 $ +* +* @verbatim +* Copyright 2012 +* by +* The Board of Trustees of the +* Leland Stanford Junior University. +* All rights reserved. +* @endverbatim +*/ + +#include <cstring> +#include <pthread.h> +#include <iostream> +#include <memory> +#include "rcecalib/server/EthPrimitive.hh" +#include "rcecalib/server/CmdDecoder.hh" +#include "rcecalib/server/BootLoaderPort.hh" +using std::auto_ptr; + +#include "datCode.hh" +//#include DAT_PUBLIC( configuration, rtems, prod.hh) +#include DAT_PRIVATE(platform, startup, Init.hh) +#include DAT_PRIVATE(platform, startup, TaskThread.hh) + +#if !tgt_board_rce440 +#include DAT_PUBLIC( service, shell, ShellCommon.hh) +#include DAT_PUBLIC( service, dynalink, Linker.hh) +#include DAT_PUBLIC( oldPpi, pgp, DriverList.hh) +using service::dynalink::Linker; + +#include DAT_PUBLIC( service, fci, Task.hh) +using service::fci::Task; + +// The address of the dynamic section created by ld. +extern "C" char _DYNAMIC[0]; +#endif +extern "C"{ + #include <rtems/malloc.h> +} + +void *posix_init( void *argument ); + +// GDB stub is compiled with C bindings +extern "C" int rtems_gdb_start(int pri, char *ttyName); + + +namespace platform { + + namespace startup { + + void initialize() + { + // Output some identification information + splash("prod"); + +#if !tgt_board_rce440 + // Add our custom commands first + service::shell::addCommands(); +#endif + + // Do the board-common initialization of the core + brdInitialize(); + // Initialize PGP + oldPpi::pgp::init_pgp(); +#if !tgt_board_rce440 + // Allow users to log in via telnet and execute interactive commands. + service::shell::initialize(); + + // Start a debugger daemon + // First arg = 0 --> Use socket IO over TCP. + // Second arg = 0 --> Priority is chosen by the debugger daemon + rtems_gdb_start(0, 0); + + // Establish the system image version for use by following code. + const uint majorVersion(rtems_majorv_macro); + const uint minorVersion(rtems_minorv_macro); + + // We must use the 4-argument form of Linker::instance() to + // create the linker instance that will be fetched by the + // no-argument form. + Linker::instance(_DYNAMIC, majorVersion, minorVersion, "prod"); + + pthread_t mthread; + pthread_attr_t attr; + int stacksize; + int ret; + // setting a new size + stacksize = (PTHREAD_STACK_MIN + 0x20000); + // void* stackbase = (void *) malloc(size); + ret = pthread_attr_init(&attr); + ret = pthread_attr_setstacksize(&attr, stacksize); + struct sched_param sparam; + sparam.sched_priority = 5; + pthread_attr_setschedparam(&attr, &sparam); + pthread_create( &mthread, &attr , posix_init, NULL); + rtems_malloc_statistics_t stats; + malloc_get_statistics(&stats); + printf("*** malloc statistics\n"); + printf("space available: %uk\n",(unsigned int)stats.space_available/1024); + printf("space allocated: %uk\n",(unsigned int)(stats.lifetime_allocated-stats.lifetime_freed)/1024); + + printf("Done with initialize\n"); + + +#endif + } + + } // startup + +} // platform + +void *posix_init( void *argument ){ + std::cout<<"ATLAS Pixel RCE boot loader (built on " << BUILDDATE << " by " << BUILDUSER <<")" << std::endl; + // std::cout<<"ATLAS Pixel RCE boot loader." << std::endl; + EthPrimitive eth(BootloaderPort); + CmdDecoder cd(ð); + cd.run(); + return 0; +} + diff --git a/rce/rcecalib/server/calibGui_Linkdef.hh b/rce/rcecalib/server/calibGui_Linkdef.hh new file mode 100644 index 00000000..68ff853b --- /dev/null +++ b/rce/rcecalib/server/calibGui_Linkdef.hh @@ -0,0 +1,5 @@ +#pragma link C++ class CalibGui; +#pragma link C++ class ScanGui; +#pragma link C++ class PrimListGui; +#pragma link C++ class ConfigGui; +#pragma link C++ class GlobalConfigGui; diff --git a/rce/rcecalib/server/calibclient.cc b/rce/rcecalib/server/calibclient.cc new file mode 100644 index 00000000..cea069ce --- /dev/null +++ b/rce/rcecalib/server/calibclient.cc @@ -0,0 +1,321 @@ +#include <stdio.h> + +#include <ers/ers.h> + +#include <ipc/partition.h> +#include <ipc/server.h> +#include <ipc/object.h> +#include <ipc/alarm.h> +#include <ipc/core.h> + +#include <owl/timer.h> +#include <cmdl/cmdargs.h> +#include <unistd.h> + +#include "rcecalib/server/TurboDaqFile.hh" +#include "rcecalib/server/IPCController.hh" +#include "rcecalib/server/IPCHistoController.hh" +#include "rcecalib/server/PixScan.hh" + +#include "IPCScanAdapter.hh" +#include "IPCConfigIFAdapter.hh" +#include "IPCFEI3Adapter.hh" +#include "ScanOptions.hh" +#include "PixelModuleConfig.hh" + +#include <TApplication.h> +#include <TROOT.h> +#include <TStyle.h> +#include <TCanvas.h> +#include <TH2F.h> + +using namespace RCE; + +void create_1d_hist(TH2F *h,const char *title) +{ + int max_val=(int) h->GetBinContent(h->GetMaximumBin())+1; + std::cout << "max " << max_val; + TH1F *h1d=new TH1F(title,title,max_val,0,max_val); + TCanvas *c=new TCanvas(title,title,600,600); + int nx=h->GetNbinsX(); + int ny=h->GetNbinsY(); + for(int x=0;x<nx;x++) { + for(int y=0;y<ny;y++) { + h1d->Fill(h->GetBinContent(x+1,y+1)); + } + } + c->Draw(); + h1d->Draw(); +} + + +int main( int argc, char ** argv ) +{ + + TApplication *tapp; + CmdArgStr partition_name ('p', "partition", "partition-name", "partition to work in."); + CmdArgInt channel ('c', "channel", "channel-number", "channel modules is connected too."); + CmdArgStr config_name ('m', "configuration", "module-configuration", "module configuation file."); + +// +// Initialize command line parameters with default values +// + try { + IPCCore::init( argc, argv ); + } + catch( daq::ipc::Exception & ex ) { + ers::fatal( ex ); + return 1; + } + +// +// Declare command object and its argument-iterator +// + CmdLine cmd(*argv, &partition_name,&channel,&config_name, NULL); + CmdArgvIter arg_iter(--argc, ++argv); + +// +// Parse arguments +// + cmd.parse(arg_iter); + + IPCPartition p( (const char*)partition_name ); + IPCController controller(p); + IPCHistoController hcontroller(p); + std::cout << "Partition : " <<(const char*)partition_name <<std::endl; + std::cout << "Channel : " <<channel <<std::endl; + std::cout << "Configuration: " <<(const char*)config_name <<std::endl; + tapp=new TApplication("bla", &argc, argv); + gROOT->SetStyle("Plain"); + gStyle->SetOptStat(0); + gStyle->SetPalette(1); + TH2F* occ=new TH2F("occ","occ", 8*18,0,8*18,2*160,0,2*160); + occ->SetMinimum(0); + TCanvas *c1=new TCanvas("occupancy","occupancy",600,600); + c1->Draw(); + occ->Draw("colz"); + + TH2F* mean=new TH2F("threshold mean","threshold mean", 8*18,0,8*18,2*160,0,2*160); + mean->SetMinimum(0); + TCanvas *c2=new TCanvas("threshold mean","threshold mean",600,600); + c2->Draw(); + mean->Draw("colz"); + + TH2F* sigma=new TH2F("threshold sigma","threshold sigma", 8*18,0,8*18,2*160,0,2*160); + sigma->SetMinimum(0); + TCanvas *c3=new TCanvas("threshold sigma","threshold sigma",600,600); + c3->Draw(); + sigma->Draw("colz"); + + TH2F* chi2=new TH2F("threshold chi2","threshold chi2", 8*18,0,8*18,2*160,0,2*160); + chi2->SetMinimum(0); + TCanvas *c4=new TCanvas("threshold chi2","threshold chi2",600,600); + c4->Draw(); + chi2->Draw("colz"); + + + TH2F* iter=new TH2F("threshold iter","thrshold iter", 8*18,0,8*18,2*160,0,2*160); + iter->SetMinimum(0); + TCanvas *c5=new TCanvas("threshold iter","threshold iter",600,600); + c5->Draw(); + iter->Draw("colz"); + + TH2F* totmean=new TH2F("tot mean","tot mean", 8*18,0,8*18,2*160,0,2*160); + totmean->SetMinimum(0); + TCanvas *c6=new TCanvas("tot mean","tot mean",600,600); + c6->Draw(); + totmean->Draw("colz"); + + TH2F* totsigma=new TH2F("tot sigma","tot sigma", 8*18,0,8*18,2*160,0,2*160); + totsigma->SetMinimum(0); + TCanvas *c7=new TCanvas("tot sigma","tot sigma",600,600); + c7->Draw(); + totsigma->Draw("colz"); + + TH2F* bcidmean=new TH2F("bcid mean","bcid mean", 8*18,0,8*18,2*160,0,2*160); + bcidmean->SetMinimum(0); + TCanvas *c8=new TCanvas("bcid mean","bcid mean",600,600); + c8->Draw(); + bcidmean->Draw("colz"); + + TH2F* bcidsigma=new TH2F("bcid sigma","bcid sigma", 8*18,0,8*18,2*160,0,2*160); + bcidsigma->SetMinimum(0); + TCanvas *c9=new TCanvas("bcid sigma","bcid sigma",600,600); + c9->Draw(); + bcidsigma->Draw("colz"); + + + ipc::PixelModuleConfig cfg; + TurboDaqFile turbo; + turbo.readModuleConfig(&cfg,(const char*)config_name); + // turbo.dump(cfg); + + controller.removeAllRces(); + controller.addRce(0); + controller.removeAllModules(); + controller.addModule("module 0","FEI3",0,channel, channel, 0, "JJ"); + controller.setupTrigger(); + controller.downloadModuleConfig(0, 0, cfg); + + PixScan* scn = new PixScan(PixScan::THRESHOLD_SCAN,PixLib::EnumFEflavour::PM_FE_I2 ); + + scn->resetScan(); + scn->setLoopVarValues(0, 0, 200, 101); + scn->setRepetitions(50); + scn-> setHistogramFilled(PixScan::TOT_MEAN,true); + scn-> setHistogramFilled(PixScan::TOT_SIGMA,true); + scn-> setHistogramFilled(PixScan::BCID_MEAN,true); + scn-> setHistogramFilled(PixScan::BCID_SIGMA,true); + + ipc::ScanOptions options; + scn->convertScanConfig(options); + //scn->dump(options); + + controller.downloadScanConfig(options); + + controller.runScan(ipc::LOW); + + //std::vector<TH1*> his=controller.getHistosByName("Mod_0_Occupancy_Point_075"); + std::vector<TH1*> his=hcontroller.getHistosFromIS("Mod_0_Occupancy_Point_075"); + assert(his.size()==1); + TH1* histo=his[0]; + for(int i=0;i<histo->GetNbinsX();i++){ + for(int j=0;j<histo->GetNbinsY();j++){ + int chip=i/18; + int col=i%18; + int row=j; + occ->Fill((chip%8)*18+col,chip/8*160+row,histo->GetBinContent(i+1,j+1)); + } + } + delete histo; + std::cout<<"Updated Mod_0_Occupancy_Point_075"<<std::endl; + //his=controller.getHistosByName("Mod_0_ToTmean_Point_075"); + his=hcontroller.getHistosFromIS("Mod_0_ToTmean_Point_075"); + assert(his.size()==1); + histo=his[0]; + for(int i=0;i<histo->GetNbinsX();i++){ + for(int j=0;j<histo->GetNbinsY();j++){ + int chip=i/18; + int col=i%18; + int row=j; + totmean->Fill((chip%8)*18+col,chip/8*160+row,histo->GetBinContent(i+1,j+1)/128); + } + } + delete histo; + std::cout<<"Updated Mod_0_ToTmean_Point_075" <<std::endl; + his=hcontroller.getHistosFromIS("Mod_0_ToTsigma_Point_075"); + //his=controller.getHistosByName("Mod_0_ToTsigma_Point_075"); + assert(his.size()==1); + histo=his[0]; + for(int i=0;i<histo->GetNbinsX();i++){ + for(int j=0;j<histo->GetNbinsY();j++){ + int chip=i/18; + int col=i%18; + int row=j; + totsigma->Fill((chip%8)*18+col,chip/8*160+row,histo->GetBinContent(i+1,j+1)/128); + } + } + delete histo; + std::cout<<"Updated Mod_0_ToTsigma_Point_075" <<std::endl; + + his=hcontroller.getHistosFromIS("Mod_0_BCIDmean_Point_075"); + assert(his.size()==1); + histo=his[0]; + for(int i=0;i<histo->GetNbinsX();i++){ + for(int j=0;j<histo->GetNbinsY();j++){ + int chip=i/18; + int col=i%18; + int row=j; + bcidmean->Fill((chip%8)*18+col,chip/8*160+row,histo->GetBinContent(i+1,j+1)/128); + } + } + delete histo; + std::cout<<"Updated Mod_0_BCIDmean_Point_075" <<std::endl; + + his=hcontroller.getHistosFromIS("Mod_0_BCIDsigma_Point_075"); + //his=controller.getHistosByName("Mod_0_BCIDsigma_Point_075"); + assert(his.size()==1); + histo=his[0]; + for(int i=0;i<histo->GetNbinsX();i++){ + for(int j=0;j<histo->GetNbinsY();j++){ + int chip=i/18; + int col=i%18; + int row=j; + bcidsigma->Fill((chip%8)*18+col,chip/8*160+row,histo->GetBinContent(i+1,j+1)/128); + } + } + + delete histo; + std::cout<<"Updated Mod_0_BCIDsigma_Point_075" <<std::endl; + + his=hcontroller.getHistosFromIS("Mod_0_Mean"); + //his=controller.getHistosByName("Mod_0_Mean"); + assert(his.size()==1); + histo=his[0]; + for(int i=0;i<histo->GetNbinsX();i++){ + for(int j=0;j<histo->GetNbinsY();j++){ + int chip=i/18; + int col=i%18; + int row=j; + mean->Fill((chip%8)*18+col,chip/8*160+row,histo->GetBinContent(i+1,j+1)); + } + } + delete histo; + + std::cout<<"Updated Mod_0_Mean"<<std::endl; + his=hcontroller.getHistosFromIS("Mod_0_Sigma"); + //his=controller.getHistosByName("Mod_0_Sigma"); + assert(his.size()==1); + histo=his[0]; + for(int i=0;i<histo->GetNbinsX();i++){ + for(int j=0;j<histo->GetNbinsY();j++){ + int chip=i/18; + int col=i%18; + int row=j; + sigma->Fill((chip%8)*18+col,chip/8*160+row,histo->GetBinContent(i+1,j+1)); + } + } + delete histo; + std::cout<<"Updated Mod_0_Sigma"<<std::endl; + his=hcontroller.getHistosFromIS("Mod_0_ChiSquare"); + //his=controller.getHistosByName("Mod_0_ChiSquare"); + assert(his.size()==1); + histo=his[0]; + for(int i=0;i<histo->GetNbinsX();i++){ + for(int j=0;j<histo->GetNbinsY();j++){ + int chip=i/18; + int col=i%18; + int row=j; + chi2->Fill((chip%8)*18+col,chip/8*160+row,histo->GetBinContent(i+1,j+1)); + } + } + delete histo; + std::cout<<"Updated Mod_0_ChiSquare"<<std::endl; + his=hcontroller.getHistosFromIS("Mod_0_Iter"); + //his=controller.getHistosByName("Mod_0_Iter"); + assert(his.size()==1); + histo=his[0]; + for(int i=0;i<histo->GetNbinsX();i++){ + for(int j=0;j<histo->GetNbinsY();j++){ + int chip=i/18; + int col=i%18; + int row=j; + iter->Fill((chip%8)*18+col,chip/8*160+row,histo->GetBinContent(i+1,j+1)); + } + } + delete histo; + std::cout<<"Updated Mod_0_Iter"<<std::endl; + + + create_1d_hist(mean,"threshold mean 1d"); + create_1d_hist(sigma,"threshold sigma 1d"); + create_1d_hist(chi2,"thresshold chi2 1d"); + create_1d_hist(iter,"threshold iter 1d"); + create_1d_hist(totsigma,"tot sigma 1d"); + create_1d_hist(totmean,"tot mean 1d"); + create_1d_hist(bcidsigma,"bcid sigma 1d"); + create_1d_hist(bcidmean,"bcid mean 1d"); + + controller.resetFE(); + tapp->Run(); +} diff --git a/rce/rcecalib/server/calibserver.cc b/rce/rcecalib/server/calibserver.cc new file mode 100644 index 00000000..3a7f191a --- /dev/null +++ b/rce/rcecalib/server/calibserver.cc @@ -0,0 +1,146 @@ +#include <stdio.h> +#include <unistd.h> + +#include <ers/ers.h> + +#include <ipc/object.h> +#include <ipc/alarm.h> +#include <ipc/core.h> +#include <ipc/server.h> + +#include <owl/timer.h> +#include <owl/semaphore.h> + +#include <boost/regex.hpp> +#include <fstream> + +#include "rcecalib/scanctrl/IPCScan.cc" +#include "rcecalib/scanctrl/IPCScanRoot.cc" +#include "rcecalib/config/IPCConfigIF.cc" +#include "rcecalib/HW/SerialHexdump.hh" +#include "rcecalib/HW/SerialPgp.hh" +#include "rcecalib/HW/SerialPgpBw.hh" +#include "rcecalib/HW/SerialPgpFei4.hh" +#include "rcecalib/config/IPCModuleFactory.hh" +#include "rcecalib/util/RceName.hh" + +#include "rcecalib/server/calibserver.hh" + +#include "rcecalib/profiler/Profiler.hh" + +#include <is/infoT.h> +#include <is/infodictionary.h> +#include <ipc/core.h> +#include <signal.h> + +static IPCServer ipcServer; + + + + +////////////////////////////////////////// +// +// Main function +// +////////////////////////////////////////// + + +void calibserver::run(bool ismodule, char* partition){ + +const char *cc_argv[] = +{ + "calibserver", /* always the name of the program */ + "-p", + "rcetest", + //"-ORBtraceLevel", /* trace level */ + //"25", + //"-ORBtraceInvocations", + //"1", + //"-ORBtraceTime", + //"1", + //"-ORBtraceThreadId", + //"1", + "-ORBgiopMaxMsgSize", + "33554422", /* max message size 32 MB */ + "-ORBmaxServerThreadPerConnection", "1" + // "-ORBendPoint", + //" giop:tcp:192.168.1.35:" +}; + + + if(partition)cc_argv[2]=partition; +int cc_argc = sizeof( cc_argv ) / sizeof( cc_argv[ 0 ] ); +// PROFILE_THREAD_SCOPED(); + + + try { + IPCCore::init( cc_argc, (char**)cc_argv ); + } + catch( daq::ipc::Exception & ex ) { + ers::fatal( ex ); + return; + } + + // Declare command object and its argument-iterator + IPCPartition p((const char*)cc_argv[2]); + printf("Partition is %s\n",cc_argv[2]); + char name[128]; + sprintf(name, "configIF_RCE%d", RceName::getRceNumber()); + p.isObjectValid<ipc::IPCConfigIFAdapter>(name); + + //Serial IF + new SerialPgpFei4; + + // set big endianness for pgp 2 + unsigned value; + asm volatile("mfdcr %0, %1" : "=r"(value) : "i"(0x2e0)); + value|=1<<13; + asm volatile("mtdcr %0, %1" : : "i"(0x2e0), "r"(value)); + + + + + //Module Factory + + ModuleFactory *moduleFactory=new IPCModuleFactory(p); + + // Config IF + + IPCConfigIF<ipc::single_thread> *cif; + IPCScan<ipc::multi_thread> *scan; + IPCScanRoot<ipc::single_thread> * scanroot; + + try{ + cif=new IPCConfigIF<ipc::single_thread>(p, name, moduleFactory); + sprintf(name, "scanCtrl_RCE%d", RceName::getRceNumber()); + scan = new IPCScan<ipc::multi_thread>( p, name); + sprintf(name, "scanRoot_RCE%d", RceName::getRceNumber()); + scanroot = new IPCScanRoot<ipc::single_thread>( p, name, (ConfigIF*)cif, (Scan*)scan); + }catch(...){ + std::cout<<"Could not add IPC objects (ipc_server not running? Several servers in the same partition?)."<<std::endl; + assert(0); + } + IPCHistoManager *hm; + try{ + sprintf(name, "RCE%d",RceName::getRceNumber()); + hm=new IPCHistoManager(p,"RceIsServer", name); + }catch(...){ + std::cout<<"Could not start histogram manager (is_server not running? Another server running on the same partition?)."<<std::endl; + assert(0); + } + printf("ipc_test_server has been started.\n"); + + if(ismodule==true){ + kill(getpid(),SIGUSR1); + pause(); + }else{ + ipcServer.run(); + } + scan->_destroy(); + scanroot->_destroy(); + cif->_destroy(); + IPCCore::shutdown(); + delete hm; + + std::cout << "Test successfully completed." << std::endl; +} diff --git a/rce/rcecalib/server/calibserver.hh b/rce/rcecalib/server/calibserver.hh new file mode 100644 index 00000000..e650b9ca --- /dev/null +++ b/rce/rcecalib/server/calibserver.hh @@ -0,0 +1,12 @@ +#ifndef CALIBSERVER_HH +#define CALIBSERVER_HH + + +class calibserver { + public: + calibserver(){}; + static void run(bool ismodule, char* partition=0); + +}; + +#endif diff --git a/rce/rcecalib/server/constituents.mk b/rce/rcecalib/server/constituents.mk new file mode 100644 index 00000000..060a3e88 --- /dev/null +++ b/rce/rcecalib/server/constituents.mk @@ -0,0 +1,820 @@ +build_date:=$(shell date +%Y/%m/%d-%H:%M:%S) +#ugly hack to link ers streams +ifeq ($(TDAQ_VERSION),4) +ifneq ($(findstring ppc-rtems-rce,$(tgt_arch)),) +extract_archive:=$(shell cd $(RELEASE)/build/rcecalib/obj/$(tgt_arch)/server; $(AR) x $(TDAQC_INST_PATH)/$(tgt_arch)/lib/libErsBaseStreams.a) +endif +endif +CPPFLAGS+=-DBUILDDATE=\"$(build_date)\" -DBUILDUSER=\"$(USER)\" + +ifeq ($(RCE_CORE_VERSION),2.2) +bootloader_cc:=bootloader_2.2.cc +rtems_config_cc:=rtems_config_2.2.cc +rce_service:=tool/exception +rce_net:= oldPpi/ethernet oldPpi/bsdNet oldPpi/net +else +bootloader_cc:=bootloader.cc +rtems_config_cc:=rtems_config.cc +rce_service:=rce/rceservice +rce_net:=rce/rcenet +endif +CPPFLAGS+=-I$(RELEASE_DIR)/rcecalib + +ifdef RCE_INTERFACE +CPPFLAGS+= '-DRCE_INTERFACE=$(RCE_INTERFACE)' +else +CPPFLAGS+= '-DRCE_INTERFACE=0' +endif +ifdef ELOG +CPPFLAGS+= '-DELOG' +endif +ifdef SQLDB +CPPFLAGS+= '-DSQLDB' +endif +ifdef SQLDBDBG +CPPFLAGS+= '-DSQLDBDBG' +endif +ifeq ($(profiler),y) +CPPFLAGS+='-D__PROFILER_ENABLED__' +profiler_lib=rcecalib/profiler +endif + +ifneq ($(findstring linux,$(tgt_os)),) +libnames := ipcclient ipcrootclient rcecontrol +endif +libsrcs_ipcclient:= IPCController.cc \ + TurboDaqFile.cc \ + FEI4AConfigFile.cc \ + FEI4BConfigFile.cc \ + HitbusConfigFile.cc \ + AFPHPTDCConfigFile.cc \ + PixScan.cc \ + PrimList.cc \ + IPCRegularCallback.cc + +libincs_ipcclient := \ + rcecalib + + +libsrcs_rcecontrol := RceControl.cc +libincs_rcecontrol : = rcecalib +tgtslibs_rcecontrol: = $(rce_service) $(rce_net) + +libsrcs_ipcrootclient:= IPCHistoController.cc +libincs_ipcrootclient := \ + rcecalib + +ifneq ($(findstring ppc-rtems-rce,$(tgt_arch)),) + + +tgtnames := bootloader #calibserver eudaqserver + +# need to fix this +ifneq ($(RCE_CORE_VERSION),2.2) +tgtnames += calibserver +endif + +CPPFLAGS += -DNFSDIR=\"/nfsexport/home/$(USER)\" +ifeq ($(TDAQ_VERSION),4) +LXFLAGS += $(RELEASE_DIR)/build/rcecalib/obj/$(tgt_arch)/server/ThrottleStream.o $(RELEASE_DIR)/build/rcecalib/obj/$(tgt_arch)/server/StandardStream.o +endif +LXFLAGS+=-L$(RELEASE_DIR)/build/rcecalib/modlib/$(tgt_arch) +ifeq ($(RCE_CORE_VERSION),2.2) +LXFLAGS += -u _ZTIN7service3fci9ExceptionE -u pthread_attr_destroy -u sem_trywait -u _ZTIi -u sem_getvalue -u pthread_getspecific -u __ltsf2 -u pthread_mutex_trylock -u clearerr -u _ZTIt -u pipe -u __mulsf3 -u toupper -u pthread_cond_wait -u __floatsisf -u _ZN5boost6thread4joinEv -u __floatundisf -u _ZN3ers11LocalStream5fatalERKNS_5IssueE -u pthread_cond_destroy -u tolower -u pthread_getschedparam -u _ZTIN5boost6detail16thread_data_baseE -u _ZN5boost11this_thread5sleepERKNS_10posix_time5ptimeE -u _ZN5boost6thread12start_threadEv -u sem_init -u isalnum -u pthread_cond_signal -u feof -u pthread_setspecific -u _ZTVN5boost6detail16thread_data_baseE -u sem_post -u sem_wait -u _ZN3ers11LocalStream7warningERKNS_5IssueE -u pthread_cond_broadcast -u _ZN5boost6thread9interruptEv -u _ZTIj -u ferror -u _ZN5boost6threadD1Ev -u sched_yield -u __gtsf2 -u sched_get_priority_min -u freeifaddrs -u _ZN3ers11LocalStream8instanceEv -u pthread_detach -u pthread_setschedparam -u sem_destroy -u _ZN5boost6detail16thread_data_baseD2Ev -u _ZN3ers11LocalStream5errorERKNS_5IssueE -u pthread_cond_init -u getifaddrs -u isspace -u pthread_attr_getstacksize -u pthread_cond_timedwait -u pthread_key_create -u pthread_mutexattr_init -u pthread_join -u sched_get_priority_max -u _ZNK5boost9gregorian10greg_month15as_short_stringEv +else +LXFLAGS += -u pthread_attr_destroy -u _ZN3ers13Configuration15verbosity_levelEi -u _ZN3ers5IssueD2Ev -u sem_trywait -u _ZTIi -u _ZN3ers5Issue15prepend_messageERKSs -u sem_getvalue -u pthread_getspecific -u sem_post -u sem_wait -u __lesf2 -u _ZN3ers11LocalStream7warningERKNS_5IssueE -u pthread_mutex_trylock -u clearerr -u pthread_cond_broadcast -u _ZN3ers13StreamManager3logERKNS_5IssueE -u _ZTIj -u ferror -u __eqsf2 -u _ZN3ers13StreamManager8instanceEv -u sched_yield -u pthread_mutex_destroy -u pthread_mutex_init -u _ZN3ers13Configuration8instanceEv -u sched_get_priority_min -u _ZTIt -u freeifaddrs -u pipe -u __mulsf3 -u _ZN3ers5IssueC2ERKNS_7ContextERKSs -u pthread_mutex_lock -u _ZN3ers11LocalStream8instanceEv -u _ZTIm -u pthread_detach -u _ZN3ers13StreamManager12report_issueENS_8severityERKNS_5IssueE -u _ZTIl -u _ZN3ers12IssueFactory14register_issueERKSsPFPNS_5IssueERKNS_7ContextEE -u _ZN3ers12LocalContext9c_processE -u sem_destroy -u pthread_setschedparam -u pthread_cond_wait -u __floatsisf -u pthread_mutex_unlock -u strtoll -u _ZN3ers11LocalStream5errorERKNS_5IssueE -u pthread_cond_init -u getifaddrs -u __floatundisf -u _ZN3ers11LocalStream5fatalERKNS_5IssueE -u isspace -u pthread_cond_destroy -u __moddi3 -u pthread_attr_getstacksize -u tolower -u pthread_getschedparam -u _ZN3ers12IssueFactory8instanceEv -u __divdi3 -u _ZN3erslsERSoRKNS_5IssueE -u pthread_cond_timedwait -u _ZN3ers5IssueC2ERKNS_7ContextERKSt9exception -u _ZTIh -u _ZN3ers5IssueC2ERKS0_ -u select -u _ZN3ers13StreamManager5debugERKNS_5IssueEi -u _ZTIN3ers5IssueE -u pthread_key_create -u sem_init -u _ZN3ers12LocalContextC1EPKcS2_iS2_ -u pthread_mutexattr_init -u isalnum -u pthread_join -u pthread_cond_signal -u feof -u sched_get_priority_max -u pthread_setspecific -u malloc_report_statistics -L$(RELEASE_DIR)/build/rcecalib/modlib/$(tgt_arch) +endif + + + +tgtsrcs_bootloader := $(bootloader_cc) $(rtems_config_cc) EthPrimitive.cc CmdDecoder.cc + +tgtincs_bootloader := +ifeq ($(RCE_CORE_VERSION),2.2) +tgtlibs_bootloader := \ + oldPpi/bsdNet \ + oldPpi/net \ + service/fci \ + service/shell \ + service/dynalink \ + service/debug \ + service/logger \ + tool/concurrency \ + tool/exception \ + tool/io \ + tool/string \ + tool/time \ + oldPpi/ethernet \ + oldPpi/init \ + oldPpi/pic \ + oldPpi/pgp +else +tgtlibs_bootloader := rce/rceshell \ + $(rce_service) \ + $(rce_net) \ + rce/rcefci \ + rce/rcedebug \ + rce/rcepic \ + rce/rcepgp \ + rce/rceethernet \ + rce/rcebsdnet \ + rce/rceinit \ + rce/dynalink \ + rce/gdbstub \ + rceusr/rceusrinit \ + rceusr/rcezcpnet +endif +ifeq ($(RCE_CORE_VERSION),2.2) +tgtslib_bootloader:= $(boost_thread_lib) \ + $(boost_date_time_lib) \ + $(ers_lib) \ + $(RTEMS_DIR)/nfs \ + $(RTEMS_DIR)/rtemscpu \ + $(RTEMS_DIR)/telnetd \ + $(RTEMS_DIR)/rtemsbsp \ + $(RTEMS_DIR)/rtems-gdb-stub +else +tgtslib_bootloader:= $(boost_thread_lib) \ + $(boost_date_time_lib) \ + $(ers_lib) \ + $(RTEMS_DIR)/nfs \ + $(RTEMS_DIR)/rtemscpu \ + $(RTEMS_DIR)/telnetd +endif +managrs_bootloader := io event msg sem ext region +#=================================================================== + +tgtsrcs_calibserver := runserver.cc $(rtems_config_cc) calibserver.cc +tgtincs_calibserver := \ + rcecalib + +tgtlibs_calibserver := rce/rceshell \ + $(rce_service) \ + $(rce_net) \ + rce/rcefci \ + rce/rcedebug \ + rce/rcepic \ + rce/rcepgp \ + rce/rceethernet \ + rce/rcebsdnet \ + rce/rceinit \ + rce/dynalink \ + rce/gdbstub \ + rceusr/rceusrinit \ + rceusr/rcezcpnet + +tgtslib_calibserver += \ + $(RTEMS_DIR)/nfs \ + $(RTEMS_DIR)/rtemscpu \ + $(RTEMS_DIR)/telnetd \ + $(z_lib) \ + $(boost_thread_lib) \ + $(boost_date_time_lib) \ + $(ipc_lib) \ + $(owl_lib) \ + $(ers_lib) \ + $(ipc_lib) \ + $(rdb_lib) \ + $(is_lib) \ + $(oh_lib) \ + $(omniorb_lib) \ + $(omnithread_lib) \ + $(boost_regex_lib) \ + rcecalib/eudaq \ + rcecalib/util \ + rcecalib/HW \ + rcecalib/dataproc \ + rcecalib/scanctrl \ + rcecalib/idl \ + rcecalib/rceconfig \ + $(profiler_lib) + + + +managrs_calibserver := io event msg sem ext region + +MLXFLAGS += -mlongcall +LXFLAGS += -mlongcall + +modnames := calibservermod # eudaqservermod +#========================================================================================= +ifeq ($(RCE_CORE_VERSION),2.2) +majorv_calibservermod := 2 +minorv_calibservermod := 2 +else +majorv_calibservermod := 1 +minorv_calibservermod := 0 +endif +branch_calibservermod := prod +modsrcs_calibservermod := runservermod.cc calibserver.cc +modincs_calibservermod := \ + rcecalib + +modlibs_calibservermod := \ + $(profiler_lib) \ + rcecalib/util \ + rcecalib/HW \ + rcecalib/dataproc \ + rcecalib/scanctrl \ + rcecalib/idl \ + rcecalib/rceconfig \ + rcecalib/eudaq + +TDAQ_DIR=$(RELEASE_DIR)/build/tdaq/lib/$(tgt_arch) +modslib_calibservermod := \ + $(z_lib) \ + $(omnithread_lib) \ + $(ipc_lib) \ + $(rdb_lib) \ + $(is_lib) \ + $(rdb_lib) \ + $(boost_regex_lib)\ + $(omniorb_lib) \ + $(z_lib) \ + $(oh_lib) \ + $(owl_lib) + + +#========================================================================================= +MLXFLAGS += -mlongcall +majorv_eudaqservermod := 1 +minorv_eudaqservermod := 0 +branch_eudaqservermod := prod +modsrcs_eudaqservermod := runeudaqservermod.cc eudaqserver.cc RceProducer.cc +modincs_eudaqservermod := \ + rcecalib + +modlibs_eudaqservermod := \ + $(profiler_lib) \ + rcecalib/util \ + rcecalib/HW \ + rcecalib/dataproc \ + rcecalib/scanctrl \ + rcecalib/idl \ + rcecalib/rceconfig \ + rcecalib/ipcclient \ + rcecalib/eudaq + +TDAQ_DIR=$(RELEASE_DIR)/build/tdaq/lib/$(tgt_arch) +modslib_eudaqservermod := \ + $(z_lib) \ + $(omnithread_lib) \ + $(ipc_lib) \ + $(rdb_lib) \ + $(is_lib) \ + $(rdb_lib) \ + $(boost_regex_lib)\ + $(omniorb_lib) \ + $(z_lib) \ + $(oh_lib) \ + $(owl_lib) + + + + + + +#-------------------------------------------- +tgtsrcs_eudaqserver := runeudaqserver.cc $(rtems_config_cc) eudaqserver.cc RceProducer.cc +tgtincs_eudaqserver := \ + rcecalib + +tgtlibs_eudaqserver := rce/rceshell \ + $(rce_service) \ + $(rce_net) \ + rce/rcefci \ + rce/rcedebug \ + rce/rcepic \ + rce/rcepgp \ + rce/rceethernet \ + rce/rcebsdnet \ + rce/rceinit \ + rce/dynalink \ + rce/gdbstub \ + rceusr/rceusrinit \ + rceusr/rcezcpnet \ + rcecalib/util \ + rcecalib/HW \ + rcecalib/dataproc \ + rcecalib/scanctrl \ + rcecalib/idl \ + rcecalib/rceconfig \ + rcecalib/eudaq \ + rcecalib/ipcclient \ + $(omniorb_lib) + +tgtslib_eudaqserver := \ + $(RTEMS_DIR)/nfs \ + $(RTEMS_DIR)/rtemscpu \ + $(RTEMS_DIR)/z \ + $(RTEMS_DIR)/telnetd \ + $(z_lib) \ + $(profiler_lib) \ + $(boost_thread_lib) \ + $(boost_date_time_lib) \ + $(omnithread_lib) \ + $(boost_regex_lib) \ + $(owl_lib) \ + $(ers_lib) \ + $(ipc_lib) \ + $(is_lib) \ + $(rdb_lib) \ + $(oh_lib) +managrs_eudaqserver := io event msg sem ext region + +endif + + +ifneq ($(findstring linux,$(tgt_os)),) + +LXFLAGS +=-pthread -lm -ldl -rdynamic +rootlibs:= \ + $(RELEASE_DIR)/build/root/lib/Gui \ + $(RELEASE_DIR)/build/root/lib/Thread \ + $(RELEASE_DIR)/build/root/lib/MathCore \ + $(RELEASE_DIR)/build/root/lib/Physics \ + $(RELEASE_DIR)/build/root/lib/Matrix \ + $(RELEASE_DIR)/build/root/lib/Postscript \ + $(RELEASE_DIR)/build/root/lib/Rint \ + $(RELEASE_DIR)/build/root/lib/Tree \ + $(RELEASE_DIR)/build/root/lib/Gpad \ + $(RELEASE_DIR)/build/root/lib/Graf3d \ + $(RELEASE_DIR)/build/root/lib/Graf \ + $(RELEASE_DIR)/build/root/lib/Hist \ + $(RELEASE_DIR)/build/root/lib/Net \ + $(RELEASE_DIR)/build/root/lib/RIO \ + $(RELEASE_DIR)/build/root/lib/Cint \ + $(RELEASE_DIR)/build/root/lib/Core + +tgtnames := host_bootloader \ + calibGui \ + cosmicGui \ + rebootHSIO \ + cosmicMonitoringGui \ + test_sctrl_server \ + rceOfflineProducer \ + sendBitStream \ + sendRandomPattern \ + calibclient \ + tdccalib \ + delaycalib \ + dumpRceMod dumpRceScan + +tgtsrcs_calibclient := calibclient.cc + +tgtincs_calibclient := \ + rcecalib + +tgtlibs_calibclient := \ + rcecalib/idl \ + rcecalib/ipcclient \ + rcecalib/ipcrootclient \ + + +tgtslib_calibclient := \ + dl \ + $(z_lib) \ + $(rootlibs) \ + $(boost_thread_lib) \ + $(boost_date_time_lib) \ + $(omniorb_lib) \ + $(omnithread_lib) \ + $(owl_lib) \ + $(ers_lib) \ + $(ipc_lib) \ + $(rdb_lib) \ + $(is_lib) \ + $(oh_lib) \ + $(tdaq_cmdline_lib) \ + $(boost_regex_lib) \ + $(oh_root_lib) + +#-------------------------------------------- + +tgtsrcs_tdccalib := tdccalib.cc + +tgtincs_tdccalib := \ + rcecalib + +tgtlibs_tdccalib := \ + rcecalib/idl \ + rcecalib/ipcclient + +tgtslib_tdccalib := \ + dl \ + $(rootlibs) \ + $(boost_thread_lib) \ + $(boost_date_time_lib) \ + $(omniorb_lib) \ + $(omnithread_lib) \ + $(owl_lib) \ + $(ers_lib) \ + rcecalib/idl \ + $(ipc_lib) \ + $(is_lib) \ + $(rdb_lib) \ + $(oh_lib) \ + $(oh_root_lib) \ + $(tdaq_cmdline_lib) \ + $(boost_regex_lib) +#-------------------------------------------- +tgtsrcs_delaycalib := delaycalib.cc + +tgtincs_delaycalib := \ + rcecalib + +tgtlibs_delaycalib := \ + rcecalib/idl \ + rcecalib/ipcclient \ + rcecalib/ipcrootclient + +tgtslib_delaycalib := \ + dl \ + $(rootlibs) \ + $(boost_thread_lib) \ + $(boost_date_time_lib) \ + $(omniorb_lib) \ + $(omnithread_lib) \ + $(owl_lib) \ + $(ers_lib) \ + $(ipc_lib) \ + $(is_lib) \ + $(rdb_lib) \ + $(oh_lib) \ + $(oh_root_lib) \ + $(tdaq_cmdline_lib) \ + $(boost_regex_lib) +#-------------------------------------------- + +GUIHEADERSDEP = CosmicGui.hh ConfigGui.hh CalibGui.hh ScanGui.hh PrimListGui.hh CosmicMonitoringGui.hh \ + CosmicDataReceiver.hh CosmicMonitoringGuiEmbedded.hh GlobalConfigGui.hh + +tgtsrcs_cosmicGui := CosmicGui.cc \ + ConfigGui.cc \ + GlobalConfigGui.cc \ + ScanLog.cc \ + cosmicGui_rootDict.cc \ + CosmicDataReceiver.cc \ + CosmicOfflineDataProc.cc \ + CosmicMonitoringGuiEmbedded.cc + +guiheaders_cosmicGui := CosmicGui.hh ConfigGui.hh CosmicMonitoringGuiEmbedded.hh GlobalConfigGui.hh + + + +tgtincs_cosmicGui := \ + rcecalib \ + rcecalib/server + +tgtlibs_cosmicGui := \ + rcecalib/idl \ + rcecalib/eudaq \ + rcecalib/rceconfig \ + rcecalib/dataproc \ + rcecalib/HW \ + rcecalib/util \ + rcecalib/ipcclient + +tgtslib_cosmicGui := \ + dl\ + $(z_lib) \ + $(rootlibs) \ + $(boost_thread_lib) \ + $(boost_date_time_lib) \ + $(omniorb_lib)\ + $(omnithread_lib) \ + $(owl_lib) \ + $(ers_lib) \ + $(ipc_lib) \ + $(is_lib) \ + $(rdb_lib) \ + $(oh_lib) \ + $(oh_root_lib) \ + $(tdaq_cmdline_lib) \ + $(boost_regex_lib) + +ifdef SQLDB + tgtslib_cosmicGui +=$(mysql_lib) +endif +#-------------------------------------------- + +tgtsrcs_dumpRceMod := dumpRceMod.cc +tgtslib_dumpRceMod := dl\ + $(z_lib) \ + $(rootlibs) \ + $(boost_thread_lib) \ + $(boost_date_time_lib) \ + $(omniorb_lib) \ + $(omnithread_lib) \ + $(owl_lib) \ + $(ers_lib) \ + $(ipc_lib) \ + $(is_lib) \ + $(rdb_lib) \ + $(oh_lib) \ + $(oh_root_lib) \ + $(tdaq_cmdline_lib) \ + $(boost_regex_lib) +tgtincs_dumpRceMod := \ + rcecalib \ + rcecalib/server +tgtlibs_dumpRceMod := \ + rcecalib/idl \ + rcecalib/ipcclient + +tgtsrcs_dumpRceScan := dumpRceScan.cc +tgtslib_dumpRceScan := dl\ + $(z_lib) \ + $(rootlibs) \ + $(boost_thread_lib) \ + $(boost_date_time_lib) \ + $(omniorb_lib) \ + $(omnithread_lib) \ + $(owl_lib) \ + $(ers_lib) \ + $(ipc_lib) \ + $(is_lib) \ + $(rdb_lib) \ + $(oh_lib) \ + $(oh_root_lib) \ + $(tdaq_cmdline_lib) \ + $(boost_regex_lib) +tgtincs_dumpRceScan := \ + rcecalib \ + rcecalib/server +tgtlibs_dumpRceScan := \ + rcecalib/idl \ + rcecalib/ipcclient + +tgtsrcs_calibGui := CalibGui.cc \ + ConfigGui.cc \ + GlobalConfigGui.cc \ + ScanGui.cc \ + PrimListGui.cc \ + DataExporter.cc \ + ScanLog.cc \ + IPCGuiCallback.cc \ + CallbackInfo.cc \ + calibGui_rootDict.cc + +guiheaders_calibGui := CalibGui.hh ScanGui.hh PrimListGui.hh ConfigGui.hh GlobalConfigGui.hh + + + +tgtincs_calibGui := \ + rcecalib \ + rcecalib/server + +tgtlibs_calibGui := \ + rcecalib/idl \ + rcecalib/analysis \ + rcecalib/ipcrootclient \ + rcecalib/ipcclient + +tgtslib_calibGui := \ + dl\ + $(z_lib) \ + $(rootlibs) \ + $(boost_thread_lib) \ + $(boost_date_time_lib) \ + $(omniorb_lib) \ + $(omnithread_lib) \ + $(owl_lib) \ + $(ers_lib) \ + $(ipc_lib) \ + $(is_lib) \ + $(rdb_lib) \ + $(oh_lib) \ + $(oh_root_lib) \ + $(tdaq_cmdline_lib) \ + $(boost_regex_lib) + +ifdef SQLDB + tgtslib_calibGui +=$(mysql_lib) +endif +#-------------------------------------------- +tgtsrcs_cosmicMonitoringGui := CosmicMonitoringGui.cc cosmicMonitoringGui_rootDict.cc CosmicMonitoringGuiEmbedded.cc ConfigGui.cc + +guiheaders_cosmicMonitoringGui := CosmicMonitoringGui.hh CosmicMonitoringGuiEmbedded.hh ConfigGui.hh + + +tgtincs_cosmicMonitoringGui := \ + rcecalib \ + rcecalib/server + + + +tgtlibs_cosmicMonitoringGui := \ + rcecalib/idl \ + rcecalib/eudaq \ + rcecalib/rceconfig \ + rcecalib/dataproc \ + rcecalib/HW \ + rcecalib/util \ + rcecalib/ipcclient + + + +tgtslib_cosmicMonitoringGui := \ + dl\ + $(z_lib) \ + $(rootlibs) \ + $(boost_thread_lib) \ + $(boost_date_time_lib) \ + $(omniorb_lib)\ + $(omnithread_lib) \ + $(owl_lib) \ + $(ers_lib) \ + $(ipc_lib) \ + $(is_lib) \ + $(rdb_lib) \ + $(oh_lib) \ + $(oh_root_lib) \ + $(tdaq_cmdline_lib) \ + $(boost_regex_lib) + +#-------------------------------------------- + +tgtsrcs_test_sctrl_server := test_server.cc +tgtincs_test_sctrl_server := \ + rcecalib + +tgtlibs_test_sctrl_server := \ + rcecalib/eudaq \ + $(rce_service) \ + $(rce_net) \ + rcecalib/util \ + rcecalib/HW \ + rcecalib/dataproc \ + rcecalib/scanctrl \ + rcecalib/idl \ + rcecalib/rceconfig + + +tgtslib_test_sctrl_server := \ + dl \ + $(z_lib) \ + $(boost_thread_lib) \ + $(boost_date_time_lib) \ + $(owl_lib) \ + $(ers_lib) \ + $(ipc_lib) \ + $(is_lib) \ + $(rdb_lib) \ + $(oh_lib) \ + $(tdaq_cmdline_lib) \ + $(omniorb_lib) \ + $(omnithread_lib) \ + $(boost_regex_lib) +#-------------------------------------------- + +tgtsrcs_rceOfflineProducer := RceOfflineProducer.cc \ + CosmicDataReceiver.cc \ + rceOfflineProducer_rootDict.cc \ + CosmicMonitoringGuiEmbedded.cc \ + ConfigGui.cc \ + CosmicOfflineDataProc.cc + +guiheaders_rceOfflineProducer := ConfigGui.hh CosmicMonitoringGuiEmbedded.hh + +tgtincs_rceOfflineProducer := \ + rcecalib \ + rcecalib/server + +tgtlibs_rceOfflineProducer := \ + rcecalib/eudaq \ + rcecalib/ipcclient \ + $(rce_service) \ + $(rce_net) \ + rcecalib/util \ + rcecalib/HW \ + rcecalib/dataproc \ + rcecalib/scanctrl \ + rcecalib/idl \ + rcecalib/rceconfig + + +tgtslib_rceOfflineProducer := \ + dl \ + $(z_lib) \ + $(boost_thread_lib) \ + $(boost_date_time_lib) \ + $(rootlibs) \ + $(owl_lib) \ + $(ers_lib) \ + $(ipc_lib) \ + $(is_lib) \ + $(rdb_lib) \ + $(oh_lib) \ + $(tdaq_cmdline_lib) \ + $(omniorb_lib) \ + $(omnithread_lib) \ + $(boost_regex_lib) +#-------------------------------------------- + +tgtsrcs_sendBitStream := sendBitStream.cc +tgtincs_sendBitStream := \ + rcecalib + +tgtlibs_sendBitStream := \ + $(rce_service) \ + $(rce_net) \ + rcecalib/idl \ + rcecalib/util \ + rcecalib/rceconfig \ + rcecalib/HW \ + rcecalib/dataproc \ + rcecalib/eudaq \ + rcecalib/ipcclient + + +tgtslib_sendBitStream := \ + dl \ + $(zlib) \ + $(boost_thread_lib) \ + $(boost_date_time_lib) \ + $(ers_lib) \ + $(owl_lib) \ + $(ipc_lib) \ + $(is_lib) \ + $(rdb_lib) \ + $(oh_lib) \ + $(omniorb_lib) \ + $(omnithread_lib) \ + $(tdaq_cmdline_lib) \ + $(boost_regex_lib) +#-------------------------------------------- + +tgtsrcs_sendRandomPattern := sendRandomPattern.cc +tgtincs_sendRandomPattern := \ + rcecalib + +tgtlibs_sendRandomPattern := \ + $(rce_service) \ + $(rce_net) \ + rcecalib/idl \ + rcecalib/util \ + rcecalib/rceconfig \ + rcecalib/HW \ + rcecalib/dataproc \ + rcecalib/eudaq \ + rcecalib/ipcclient + + +tgtslib_sendRandomPattern := \ + dl \ + $(zlib) \ + $(boost_thread_lib) \ + $(boost_date_time_lib) \ + $(ers_lib) \ + $(owl_lib) \ + $(ipc_lib) \ + $(is_lib) \ + $(rdb_lib) \ + $(oh_lib) \ + $(omniorb_lib) \ + $(omnithread_lib) \ + $(tdaq_cmdline_lib) \ + $(boost_regex_lib) + +#-------------------------------------------- +tgtsrcs_rebootHSIO := rebootHSIO.cc +tgtincs_rebootHSIO := \ + rcecalib + +tgtlibs_rebootHSIO := \ + rcecalib/idl \ + rcecalib/ipcclient + + +tgtslib_rebootHSIO := \ + dl \ + $(z_lib) \ + $(boost_thread_lib) \ + $(boost_date_time_lib) \ + $(owl_lib) \ + $(ers_lib) \ + $(ipc_lib) \ + $(is_lib) \ + $(rdb_lib) \ + $(oh_lib) \ + $(tdaq_cmdline_lib) \ + $(omniorb_lib) \ + $(omnithread_lib) \ + $(boost_regex_lib) + +#========================================================= +tgtsrcs_host_bootloader := host_bootloader.cc +tgtincs_host_bootloader := boost +tgtlibs_host_bootloader := $(rce_service) $(rce_net) rcecalib/rcecontrol +tgtslib_host_bootloader := /usr/lib/rt + +#========================================================= +tgtsrcs_testspeed := testspeed.cc EthPrimitive.cc +tgtincs_testspeed := boost +tgtlibs_testspeed := $(rce_service) $(rce_net) +tgtslib_testspeed := /usr/lib/rt + + +endif + diff --git a/rce/rcecalib/server/cosmicGui_Linkdef.hh b/rce/rcecalib/server/cosmicGui_Linkdef.hh new file mode 100644 index 00000000..b7c0ee9b --- /dev/null +++ b/rce/rcecalib/server/cosmicGui_Linkdef.hh @@ -0,0 +1,4 @@ +#pragma link C++ class CosmicGui; +#pragma link C++ class ConfigGui; +#pragma link C++ class GlobalConfigGui; +#pragma link C++ class CosmicMonitoringGuiEmbedded; diff --git a/rce/rcecalib/server/cosmicMonitoringGui_Linkdef.hh b/rce/rcecalib/server/cosmicMonitoringGui_Linkdef.hh new file mode 100644 index 00000000..a05abc78 --- /dev/null +++ b/rce/rcecalib/server/cosmicMonitoringGui_Linkdef.hh @@ -0,0 +1,4 @@ +#pragma link C++ class CosmicMonitoringGui; +#pragma link C++ class CosmicMonitoringGuiEmbedded; +#pragma link C++ class ConfigGui; + diff --git a/rce/rcecalib/server/delaycalib.cc b/rce/rcecalib/server/delaycalib.cc new file mode 100644 index 00000000..3978e6cd --- /dev/null +++ b/rce/rcecalib/server/delaycalib.cc @@ -0,0 +1,132 @@ +#include <stdio.h> + +#include <ers/ers.h> + +#include <ipc/partition.h> +#include <ipc/server.h> +#include <ipc/object.h> +#include <ipc/alarm.h> +#include <ipc/core.h> + +#include <owl/timer.h> +#include <cmdl/cmdargs.h> +#include <unistd.h> + +#include "rcecalib/server/TurboDaqFile.hh" +#include "rcecalib/server/IPCController.hh" +#include "rcecalib/server/IPCHistoController.hh" +#include "rcecalib/server/PixScan.hh" + +#include "IPCScanAdapter.hh" +#include "IPCConfigIFAdapter.hh" +#include "IPCFEI3Adapter.hh" +#include "ScanOptions.hh" +#include "PixelModuleConfig.hh" + +#include <TApplication.h> +#include <TROOT.h> +#include <TStyle.h> +#include <TCanvas.h> +#include <TH2F.h> +#include <TF1.h> +#include <TFile.h> +#include "rcecalib/server/Mean.hh" + +int acquireDataPoint(IPCController& controller); + +using namespace RCE; + +int main( int argc, char ** argv ) +{ + + TApplication *tapp; + CmdArgStr partition_name ('p', "partition", "partition-name", "partition to work in."); + +// +// Initialize command line parameters with default values +// + try { + IPCCore::init( argc, argv ); + } + catch( daq::ipc::Exception & ex ) { + ers::fatal( ex ); + return 1; + } + +// +// Declare command object and its argument-iterator +// + CmdLine cmd(*argv, &partition_name, NULL); + CmdArgvIter arg_iter(--argc, ++argv); + +// +// Parse arguments +// + cmd.parse(arg_iter); + + IPCPartition p( (const char*)partition_name ); + IPCController controller(p); + IPCHistoController hcontroller(p); + unsigned serstat; + int rce=0; + serstat=controller.writeHWregister(rce, 7,0); + assert(serstat==0); + //for(int i=0;i<60;i++)controller.writeHWregister(6,0); + //for (int i=0;i<60;i++)controller.writeHWregister(6,0); + tapp=new TApplication("bla", &argc, argv); + + gROOT->SetStyle("Plain"); + gStyle->SetOptStat(0); + gStyle->SetPalette(1); + gStyle->SetOptFit(111); + gStyle->SetErrorX(0); + gStyle->SetMarkerStyle(20); + + TH1F* del1=new TH1F("delay1","Delay Disc 1 wrt Disc 0",13,-65.,65 ); + del1->GetXaxis()->SetTitle("Delay (IDELAY counts)"); + TCanvas *c1=new TCanvas("c1","Canvas",600,600); + del1->SetMinimum(0); + c1->Draw(); + del1->Draw("ep"); + sleep(1); + + PixScan* scn = new PixScan(PixScan::SCINTDELAY_SCAN, PixLib::EnumFEflavour::PM_FE_I2); + //scn->resetScan(); + //scn->setLoopVarValues(0, 0, 200, 101); + //scn->setRepetitions(50); + ipc::ScanOptions options; + scn->convertScanConfig(options); + controller.setupTrigger(); + controller.downloadScanConfig(options); + serstat=controller.writeHWregister(rce,8,2); + assert(serstat==0); + controller.startScan(); + int status=-1; + do{ + sleep(5); + status = controller.getScanStatus(); + std::vector<TH1*> his=hcontroller.getHistosFromIS("delhisto"); + TH1* histo=his[0]; + for(int i=0;i<histo->GetNbinsX();i++){ + del1->SetBinContent(i+1,histo->GetBinContent(i+1)); + del1->SetBinError(i+1,sqrt((float)histo->GetBinContent(i+1))); + } + del1->Draw("ep"); + c1->Update(); + delete histo; + }while (status !=0); + std::cout<<"Loop done"<<std::endl; + if(del1->GetEntries()>10){ + del1->Fit("gaus"); + float fitpar=del1->GetFunction("gaus")->GetParameter(1); + std::cout<<"Fit result: "<<fitpar<<"IDELAY counts delay."<<std::endl; + } + std::cout<<"Fit done"<<std::endl; + serstat=controller.writeHWregister(rce, 3,0); //Return to normal mode + assert(serstat==0); + TFile *file=new TFile("histos.root","recreate"); + del1->Write(); + file->Close(); + + tapp->Run(); +} diff --git a/rce/rcecalib/server/dumpRceMod.cc b/rce/rcecalib/server/dumpRceMod.cc new file mode 100644 index 00000000..5881ecb9 --- /dev/null +++ b/rce/rcecalib/server/dumpRceMod.cc @@ -0,0 +1,46 @@ + +#include "rcecalib/server/GlobalConfigGui.hh" +#include "rcecalib/server/FEI4AConfigFile.hh" +#include "rcecalib/server/FEI4BConfigFile.hh" +#include "rcecalib/server/TurboDaqFile.hh" +#include "PixelFEI4AConfig.hh" +#include "PixelFEI4BConfig.hh" +#include "PixelModuleConfig.hh" +#include "rcecalib/server/CalibGui.hh" +#include <iostream> +#include <boost/regex.hpp> +#include <sys/stat.h> +#include <string> + +int main(int argc,char *argv[]) +{ + + +ipc::PixelFEI4AConfig confa; +ipc::PixelFEI4BConfig confb; + +FEI4AConfigFile fei4afile; +FEI4BConfigFile fei4bfile; + int flavour=-1; + std::string filename(argv[1]); + try { + fei4afile.readModuleConfig(&confa,filename); + flavour=0; + } catch (...) { flavour=-1;} + if(flavour==-1) { + try { + fei4bfile.readModuleConfig(&confb,filename); + flavour=1; + } catch(...) {flavour=-1;} + + } + if(flavour==0) fei4afile.dump(confa); + if(flavour==1) fei4bfile.dump(confb); + + + + + return 0; + + +} diff --git a/rce/rcecalib/server/dumpRceScan.cc b/rce/rcecalib/server/dumpRceScan.cc new file mode 100644 index 00000000..6732e758 --- /dev/null +++ b/rce/rcecalib/server/dumpRceScan.cc @@ -0,0 +1,53 @@ +#include <iostream> +#include <boost/regex.hpp> +#include <sys/stat.h> +#include <string> +#include "rcecalib/server/PixScan.hh" +#include "ScanOptions.hh" +#include <cmdl/cmdargs.h> +#include "PixScanBase.h" +#include "PixEnumBase.h" +int main(int argc,char *argv[]) +{ + + + CmdArgBool list ('l', "list", "list all scans"); + CmdArgStr flavor ('f',"flavor", "module-flavor","specify module flavor"); + CmdArgStr name("[name]","name of scan"); + CmdLine cmd(*argv, &list,&flavor,&name, NULL); + + + CmdArgvIter arg_iter(--argc, ++argv); + int scanindex=-1; + cmd.parse(arg_iter); + PixLib::EnumFEflavour::FEflavour f; + f = PixLib::EnumFEflavour::PM_FE_I4A; + if(!list) { + if(!strcmp(flavor,"PM_FE_I4A")) f = PixLib::EnumFEflavour::PM_FE_I4A; + else if(!strcmp(flavor,"PM_FE_I4B")) f = PixLib::EnumFEflavour::PM_FE_I4B ; + else if(!strcmp(flavor,"PM_FE_I2")) f = PixLib::EnumFEflavour::PM_FE_I2 ; + else if(!list) {std::cout << "unkown flavor " << flavor << std::endl;return 1;} + } + PixLib::EnumScanType scantype; + std::map<std::string, int> scannames=scantype.EnumScanTypeMap(); + for (std::map <std::string, int>::const_iterator it = scannames.begin(); it != scannames.end(); ++it){ + std::string scanname=it->first; + scanindex=it->second; + if(!name.isNULL()) if(std::string((const char*)name)==scanname) break; + if(list) std::cout << scanname << std::endl; + } + if(list) return 0; + std::cout <<"Flavor: " <<flavor << std::endl; + std::cout <<"ScanName: " <<name << std::endl; + std::cout <<"ScanIndex: "<< scanindex<< std::endl; + ipc::ScanOptions scanopts; + RCE::PixScan scan((RCE::PixScan::ScanType) scanindex, f); + if(scan.presetRCE((RCE::PixScan::ScanType) scanindex, f)==true) { + + scan.convertScanConfig(scanopts); + scan.dump(std::cout,scanopts); + } + return 0; + + +} diff --git a/rce/rcecalib/server/ettcp.c b/rce/rcecalib/server/ettcp.c new file mode 100644 index 00000000..b0401f1e --- /dev/null +++ b/rce/rcecalib/server/ettcp.c @@ -0,0 +1,922 @@ +/* + * N T T C P . C + * + * Test TCP connection. Makes a connection on port 5001 + * and transfers fabricated buffers or data copied from stdin. + * + * Usable on 4.2, 4.3, and 4.1a systems by defining one of + * BSD42 BSD43 (BSD41a) + * Machines using System V with BSD sockets should define SYSV. + * + * Modified for operation under 4.2BSD, 18 Dec 84 + * T.C. Slattery, USNA + * Minor improvements, Mike Muuss and Terry Slattery, 16-Oct-85. + * Modified in 1989 at Silicon Graphics, Inc. + * catch SIGPIPE to be able to print stats when receiver has died + * for tcp, don't look for sentinel during reads to allow small transfers + * increased default buffer size to 8K, nbuf to 2K to transfer 16MB + * moved default port to 5001, beyond IPPORT_USERRESERVED + * make sinkmode default because it is more popular, + * -s now means don't sink/source + * count number of read/write system calls to see effects of + * blocking from full socket buffers + * for tcp, -D option turns off buffered writes (sets TCP_NODELAY sockopt) + * buffer alignment options, -A and -O + * print stats in a format that's a bit easier to use with grep & awk + * for SYSV, mimic BSD routines to use most of the existing timing code + * Modified by Steve Miller of the University of Maryland, College Park + * -b sets the socket buffer size (SO_SNDBUF/SO_RCVBUF) + * Modified Sept. 1989 at Silicon Graphics, Inc. + * restored -s sense at request of tcs@brl + * Modified Oct. 1991 at Silicon Graphics, Inc. + * use getopt(3) for option processing, add -f and -T options. + * SGI IRIX 3.3 and 4.0 releases don't need #define SYSV. + * + * Modified by David Boreham <david@bozemanpass.com> + * to support call back mode + * + * Distribution Status - + * Public Domain. Distribution Unlimited. + */ +#ifndef lint +static char RCSid[] = "ttcp.c $Revision: 1.12 $"; +#endif + +#define BSD43 +/* #define BSD42 */ +/* #define BSD41a */ +/* #define SYSV */ /* required on SGI IRIX releases before 3.3 */ + +#include <stdio.h> +#include <signal.h> +#include <ctype.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <sys/time.h> /* struct timeval */ + +#if defined(SYSV) || defined(__rtems__) +#include <sys/times.h> +#include <sys/param.h> +struct rusage { + struct timeval ru_utime, ru_stime; +}; +#define RUSAGE_SELF 0 +#else +#include <sys/resource.h> +#endif + +#define SA( p ) ( (struct sockaddr *) (p) ) + +struct sockaddr_in sinme; +struct sockaddr_in sinhim; +struct sockaddr_in frominet; + +int domain, fromlen; +int fd; /* fd of network socket */ + +int buflen = 8 * 1024; /* length of buffer */ +char *buf; /* ptr to dynamic buffer */ +int nbuf = 2 * 1024; /* number of buffers to send in sinkmode */ + +int bufoffset = 0; /* align buffer to this */ +int bufalign = 16*1024; /* modulo this */ + +int udp = 0; /* 0 = tcp, !0 = udp */ +int options = 0; /* socket options */ +int one = 1; /* for 4.3 BSD style setsockopt() */ +short port = 5001; /* TCP port number */ +char *host; /* ptr to name of host */ +int trans; /* 0=receive, !0=transmit mode */ +int sinkmode = 0; /* 0=normal I/O, !0=sink/source mode */ +int verbose = 0; /* 0=print basic info, 1=print cpu rate, proc + * resource usage. */ +int nodelay = 0; /* set TCP_NODELAY socket option */ +int b_flag = 0; /* use mread() */ +int sockbufsize = 0; /* socket buffer size to use */ +char fmt = 'K'; /* output format: k = kilobits, K = kilobytes, + * m = megabits, M = megabytes, + * g = gigabits, G = gigabytes */ +int touchdata = 0; /* access data after reading */ +int c_flag = 0; /* collect call mode */ +int q_flag = 0; /* keep quiet */ +int interval = 0; /* time interval to test over */ + +struct hostent *addr; +extern int errno; +extern int optind; +extern char *optarg; + +char Usage[] = "\ +Usage: nttcp -t [-options] host [ < in ]\n\ + nttcp -r [-options > out]\n\ +Common options:\n\ + -l ## length of bufs read from or written to network (default 8192)\n\ + -u use UDP instead of TCP\n\ + -p ## port number to send to or listen at (default 5001)\n\ + -s -t: source a pattern to network\n\ + -r: sink (discard) all data from network\n\ + -i ## \"interval\": number of seconds to run the test, rather than number of buffers\n\ + -A align the start of buffers to this modulus (default 16384)\n\ + -O start buffers at this offset from the modulus (default 0)\n\ + -v verbose: print more statistics\n\ + -d set SO_DEBUG socket option\n\ + -b ## set socket buffer size (if supported)\n\ + -f X format for rate: b,B = {bit,byte}; k,K = kilo{bit,byte}; m,M = mega; g,G = giga; r,R = raw {bit,byte}\n\ +Options specific to -t:\n\ + -n## number of source bufs written to network (default 2048)\n\ + -D don't buffer TCP writes (sets TCP_NODELAY socket option)\n\ +Options specific to -r:\n\ + -B for -s, only output full blocks as specified by -l (for TAR)\n\ + -T \"touch\": access each byte as it's read\n\ + -c \"collect call\": initiate the TCP connection but then expect data sent from the other end\n\ + -q \"quiet\": only print the measured throughput, emit no other chatty output.\n\ +"; + +char stats[128]; +double nbytes; /* bytes on net */ +unsigned long numCalls; /* # of I/O system calls */ +double cput, realt; /* user, real time (seconds) */ + +int err(); +void mes(); +int pattern(); +void prep_timer(); +double read_timer(); +double elapsed_time(); +int Nread(); +int Nwrite(); +void delay(); +int mread(); +char *outfmt(); + +void +sigpipe() +{ +} + +#ifdef __rtems__ +int ttcp_main(int argc,char *argv[]) +#else +int main(int argc,char **argv) +#endif +{ + unsigned long addr_tmp; + int c; + printf("in main\n"); + + if (argc < 2) goto usage; + printf("in main\n"); + while ((c = getopt(argc, argv, "cdrstuvBDTqb:f:l:n:p:A:O:i:")) != -1) { + switch (c) { + + case 'B': + b_flag = 1; + break; + case 't': + trans = 1; + break; + case 'r': + trans = 0; + break; + case 'd': + options |= SO_DEBUG; + break; + case 'D': +#ifdef TCP_NODELAY + nodelay = 1; +#else + fprintf(stderr, + "ttcp: -D option ignored: TCP_NODELAY socket option not supported\n"); +#endif + break; + case 'n': + nbuf = atoi(optarg); + break; + case 'l': + buflen = atoi(optarg); + break; + case 's': + sinkmode = !sinkmode; + break; + case 'p': + port = atoi(optarg); + break; + case 'u': + udp = 1; + break; + case 'v': + verbose = 1; + break; + case 'A': + bufalign = atoi(optarg); + break; + case 'O': + bufoffset = atoi(optarg); + break; + case 'b': +#if defined(SO_SNDBUF) || defined(SO_RCVBUF) + sockbufsize = atoi(optarg); +#else + fprintf(stderr, +"ttcp: -b option ignored: SO_SNDBUF/SO_RCVBUF socket options not supported\n"); +#endif + break; + case 'f': + fmt = *optarg; + break; + case 'T': + touchdata = 1; + break; + case 'c': + c_flag = 1; + break; + case 'q': + q_flag = 1; + break; + case 'i': + interval = atoi(optarg); + break; + + default: + goto usage; + } + } + if(trans || c_flag) { + /* xmitr */ + if (optind == argc) + goto usage; + bzero((char *)&sinhim, sizeof(sinhim)); + host = argv[optind]; + if (atoi(host) > 0 ) { + /* Numeric */ + sinhim.sin_family = AF_INET; +#if defined(cray) + addr_tmp = inet_addr(host); + sinhim.sin_addr = addr_tmp; +#else + sinhim.sin_addr.s_addr = inet_addr(host); +#endif + } else { + if ((addr=gethostbyname(host)) == NULL) + err("bad hostname"); + sinhim.sin_family = addr->h_addrtype; + bcopy(addr->h_addr,(char*)&addr_tmp, addr->h_length); +#if defined(cray) + sinhim.sin_addr = addr_tmp; +#else + sinhim.sin_addr.s_addr = addr_tmp; +#endif /* cray */ + } + sinhim.sin_port = htons(port); + sinme.sin_port = 0; /* free choice */ + } else { + /* rcvr */ + sinme.sin_port = htons(port); + } + + + if (udp && buflen < 5) { + buflen = 5; /* send more than the sentinel size */ + } + + if ( (buf = (char *)malloc(buflen+bufalign)) == (char *)NULL) + err("malloc"); + if (bufalign != 0) + buf +=(bufalign - ((int)buf % bufalign) + bufoffset) % bufalign; + + if (!q_flag) { + if (trans) { + fprintf(stdout, + "ttcp-t: buflen=%d, nbuf=%d, align=%d/%d, port=%d", + buflen, nbuf, bufalign, bufoffset, port); + if (sockbufsize) + fprintf(stdout, ", sockbufsize=%d", sockbufsize); + fprintf(stdout, " %s -> %s\n", udp?"udp":"tcp", host); + } else { + fprintf(stdout, + "ttcp-r: buflen=%d, nbuf=%d, align=%d/%d, port=%d", + buflen, nbuf, bufalign, bufoffset, port); + if (sockbufsize) + fprintf(stdout, ", sockbufsize=%d", sockbufsize); + fprintf(stdout, " %s\n", udp?"udp":"tcp"); + } + } /* !q_flag */ + + if ((fd = socket(AF_INET, udp?SOCK_DGRAM:SOCK_STREAM, 0)) < 0) + err("socket"); + if (!q_flag) mes("socket"); + + if (bind(fd, SA(&sinme), sizeof(sinme)) < 0) + err("bind"); + +#if defined(SO_SNDBUF) || defined(SO_RCVBUF) + if (sockbufsize) { + if (trans) { + if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sockbufsize, + sizeof sockbufsize) < 0) + err("setsockopt: sndbuf"); + mes("sndbuf"); + } else { + if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &sockbufsize, + sizeof sockbufsize) < 0) + err("setsockopt: rcvbuf"); + mes("rcvbuf"); + } + } +#endif + + if (!udp) { + signal(SIGPIPE, sigpipe); + if (trans || c_flag) { + /* We are the client if transmitting */ + if (options) { +#if defined(BSD42) + if( setsockopt(fd, SOL_SOCKET, options, 0, 0) < 0) +#else /* BSD43 */ + if( setsockopt(fd, SOL_SOCKET, options, &one, sizeof(one)) < 0) +#endif + err("setsockopt"); + } +#ifdef TCP_NODELAY + if (nodelay) { + struct protoent *p; + p = getprotobyname("tcp"); + if( p && setsockopt(fd, p->p_proto, TCP_NODELAY, + &one, sizeof(one)) < 0) + err("setsockopt: nodelay"); + mes("nodelay"); + } +#endif + if(connect(fd, SA(&sinhim), sizeof(sinhim) ) < 0) + err("connect"); + if (!q_flag) mes("connect"); + } else { + /* otherwise, we are the server and + * should listen for the connections + */ +#if defined(ultrix) || defined(sgi) + listen(fd,1); /* workaround for alleged u4.2 bug */ +#else + listen(fd,0); /* allow a queue of 0 */ +#endif + if(options) { +#if defined(BSD42) + if( setsockopt(fd, SOL_SOCKET, options, 0, 0) < 0) +#else /* BSD43 */ + if( setsockopt(fd, SOL_SOCKET, options, &one, sizeof(one)) < 0) +#endif + err("setsockopt"); + } + fromlen = sizeof(frominet); + domain = AF_INET; + if((fd=accept(fd, SA(&frominet), &fromlen) ) < 0) + err("accept"); + { struct sockaddr_in peer; + int peerlen = sizeof(peer); + if (getpeername(fd, SA(&peer), + &peerlen) < 0) { + err("getpeername"); + } + if (!q_flag) fprintf(stderr,"ttcp-r: accept from %s\n", + inet_ntoa(peer.sin_addr)); + } + } + } + prep_timer(); + errno = 0; + if (sinkmode) { + register int cnt; + if (trans) { + pattern( buf, buflen ); + if(udp) (void)Nwrite( fd, buf, 4 ); /* rcvr start */ + if (0 == interval) { + while (nbuf-- && Nwrite(fd,buf,buflen) == buflen) + nbytes += buflen; + } else { + while (Nwrite(fd,buf,buflen) == buflen) { + nbytes += buflen; + if (elapsed_time() > interval) { + break; + } + } + } + if(udp) (void)Nwrite( fd, buf, 4 ); /* rcvr end */ + } else { + if (udp) { + while ((cnt=Nread(fd,buf,buflen)) > 0) { + static int going = 0; + if( cnt <= 4 ) { + if( going ) + break; /* "EOF" */ + going = 1; + prep_timer(); + } else { + nbytes += cnt; + } + } + } else { + int total_bytes = nbuf * buflen; + while ((cnt=Nread(fd,buf,buflen)) > 0) { + nbytes += cnt; + if (c_flag && (0 == interval) ) { + total_bytes -= cnt; + if (total_bytes <= 0) { + break; + } + } + if (0 != interval) { + if (elapsed_time() > interval) { + break; + } + } + } + } + } + } else { + register int cnt; + if (trans) { + while((cnt=read(0,buf,buflen)) > 0 && + Nwrite(fd,buf,cnt) == cnt) + nbytes += cnt; + } else { + while((cnt=Nread(fd,buf,buflen)) > 0 && + write(1,buf,cnt) == cnt) + nbytes += cnt; + } + } + if(errno) err("IO"); + (void)read_timer(stats,sizeof(stats)); + if(udp&&trans) { + (void)Nwrite( fd, buf, 4 ); /* rcvr end */ + (void)Nwrite( fd, buf, 4 ); /* rcvr end */ + (void)Nwrite( fd, buf, 4 ); /* rcvr end */ + (void)Nwrite( fd, buf, 4 ); /* rcvr end */ + } + if( cput <= 0.0 ) cput = 0.001; + if( realt <= 0.0 ) realt = 0.001; + if (q_flag) { + fprintf(stdout, + "%s\n", + outfmt(nbytes/realt)); + } else + { + fprintf(stdout, + "nttcp%s: %.0f bytes in %.2f real seconds = %s/sec +++\n", + trans?"-t":"-r", + nbytes, realt, outfmt(nbytes/realt)); + if (verbose) { + fprintf(stdout, + "nttcp%s: %.0f bytes in %.2f CPU seconds = %s/cpu sec\n", + trans?"-t":"-r", + nbytes, cput, outfmt(nbytes/cput)); + } + fprintf(stdout, + "nttcp%s: %d I/O calls, msec/call = %.2f, calls/sec = %.2f\n", + trans?"-t":"-r", + numCalls, + 1024.0 * realt/((double)numCalls), + ((double)numCalls)/realt); + fprintf(stdout,"nttcp%s: %s\n", trans?"-t":"-r", stats); + if (verbose) { + fprintf(stdout, + "nttcp%s: buffer address %#x\n", + trans?"-t":"-r", + buf); + } + } /* !q_flag */ + return(0); + +usage: + fprintf(stderr,Usage); + return(1); +} + +int +err(s) +char *s; +{ + fprintf(stderr,"nttcp%s: ", trans?"-t":"-r"); + perror(s); + fprintf(stderr,"errno=%d\n",errno); + return(1); +} + +void +mes(s) +char *s; +{ + fprintf(stderr,"nttcp%s: %s\n", trans?"-t":"-r", s); +} + +pattern( cp, cnt ) +register char *cp; +register int cnt; +{ + register char c; + c = 0; + while( cnt-- > 0 ) { + while( !isprint((c&0x7F)) ) c++; + *cp++ = (c++&0x7F); + } +} + +char * +outfmt(b) +double b; +{ + static char obuf[50]; + switch (fmt) { + case 'G': + sprintf(obuf, "%.2f GB", b / 1024.0 / 1024.0 / 1024.0); + break; + default: + case 'K': + sprintf(obuf, "%.2f KB", b / 1024.0); + break; + case 'M': + sprintf(obuf, "%.2f MB", b / 1024.0 / 1024.0); + break; + case 'B': + sprintf(obuf, "%.2f B", b ); + break; + case 'R': + sprintf(obuf, "%.2f", b ); + break; + case 'g': + sprintf(obuf, "%.2f Gbit", b * 8.0 / 1024.0 / 1024.0 / 1024.0); + break; + case 'k': + sprintf(obuf, "%.2f Kbit", b * 8.0 / 1024.0); + break; + case 'm': + sprintf(obuf, "%.2f Mbit", b * 8.0 / 1024.0 / 1024.0); + break; + case 'b': + sprintf(obuf, "%.2f bit", b * 8.0 ); + break; + case 'r': + sprintf(obuf, "%.2f", b * 8); + break; + } + return obuf; +} + +static struct timeval time0; /* Time at which timing started */ +static struct rusage ru0; /* Resource utilization at the start */ + +static void prusage(); +static void tvadd(); +static void tvsub(); +static void psecs(); + +#if defined(SYSV) || defined(__rtems__) +/*ARGSUSED*/ +static +getrusage(ignored, ru) + int ignored; + register struct rusage *ru; +{ + struct tms buf; + + times(&buf); + + /* Assumption: HZ <= 2147 (LONG_MAX/1000000) */ + ru->ru_stime.tv_sec = buf.tms_stime / HZ; + ru->ru_stime.tv_usec = ((buf.tms_stime % HZ) * 1000000) / HZ; + ru->ru_utime.tv_sec = buf.tms_utime / HZ; + ru->ru_utime.tv_usec = ((buf.tms_utime % HZ) * 1000000) / HZ; +} +#endif +#if defined(SYSV) && ! defined(__rtems__) +/*ARGSUSED*/ +static +gettimeofday(tp, zp) + struct timeval *tp; + struct timezone *zp; +{ + tp->tv_sec = time(0); + tp->tv_usec = 0; +} +#endif /* SYSV */ + +/* + * P R E P _ T I M E R + */ +void +prep_timer() +{ + gettimeofday(&time0, (struct timezone *)0); + getrusage(RUSAGE_SELF, &ru0); +} + +/* + * R E A D _ T I M E R + * + */ +double +read_timer(str,len) +char *str; +{ + struct timeval timedol; + struct rusage ru1; + struct timeval td; + struct timeval tend, tstart; + char line[132]; + + getrusage(RUSAGE_SELF, &ru1); + gettimeofday(&timedol, (struct timezone *)0); + prusage(&ru0, &ru1, &timedol, &time0, line); + (void)strncpy( str, line, len ); + + /* Get real time */ + tvsub( &td, &timedol, &time0 ); + realt = td.tv_sec + ((double)td.tv_usec) / 1000000; + + /* Get CPU time (user+sys) */ + tvadd( &tend, &ru1.ru_utime, &ru1.ru_stime ); + tvadd( &tstart, &ru0.ru_utime, &ru0.ru_stime ); + tvsub( &td, &tend, &tstart ); + cput = td.tv_sec + ((double)td.tv_usec) / 1000000; + if( cput < 0.00001 ) cput = 0.00001; + return( cput ); +} + +double +elapsed_time() +{ + struct timeval timedol; + struct timeval td; + double et = 0.0; + + gettimeofday(&timedol, (struct timezone *)0); + tvsub( &td, &timedol, &time0 ); + et = td.tv_sec + ((double)td.tv_usec) / 1000000; + + return( et ); +} + +static void +prusage(r0, r1, e, b, outp) + register struct rusage *r0, *r1; + struct timeval *e, *b; + char *outp; +{ + struct timeval tdiff; + register time_t t; + register char *cp; + register int i; + int ms; + + t = (r1->ru_utime.tv_sec-r0->ru_utime.tv_sec)*100+ + (r1->ru_utime.tv_usec-r0->ru_utime.tv_usec)/10000+ + (r1->ru_stime.tv_sec-r0->ru_stime.tv_sec)*100+ + (r1->ru_stime.tv_usec-r0->ru_stime.tv_usec)/10000; + ms = (e->tv_sec-b->tv_sec)*100 + (e->tv_usec-b->tv_usec)/10000; + +#define END(x) {while(*x) x++;} +#if defined(SYSV) + cp = "%Uuser %Ssys %Ereal %P"; +#else +#if defined(sgi) /* IRIX 3.3 will show 0 for %M,%F,%R,%C */ + cp = "%Uuser %Ssys %Ereal %P %Mmaxrss %F+%Rpf %Ccsw"; +#else + cp = "%Uuser %Ssys %Ereal %P %Xi+%Dd %Mmaxrss %F+%Rpf %Ccsw"; +#endif +#endif + for (; *cp; cp++) { + if (*cp != '%') + *outp++ = *cp; + else if (cp[1]) switch(*++cp) { + + case 'U': + tvsub(&tdiff, &r1->ru_utime, &r0->ru_utime); + sprintf(outp,"%d.%01d", tdiff.tv_sec, tdiff.tv_usec/100000); + END(outp); + break; + + case 'S': + tvsub(&tdiff, &r1->ru_stime, &r0->ru_stime); + sprintf(outp,"%d.%01d", tdiff.tv_sec, tdiff.tv_usec/100000); + END(outp); + break; + + case 'E': + psecs(ms / 100, outp); + END(outp); + break; + + case 'P': + sprintf(outp,"%d%%", (int) (t*100 / ((ms ? ms : 1)))); + END(outp); + break; + +#if !defined(SYSV) && !defined(__rtems__) + case 'W': + i = r1->ru_nswap - r0->ru_nswap; + sprintf(outp,"%d", i); + END(outp); + break; + + case 'X': + sprintf(outp,"%d", t == 0 ? 0 : (r1->ru_ixrss-r0->ru_ixrss)/t); + END(outp); + break; + + case 'D': + sprintf(outp,"%d", t == 0 ? 0 : + (r1->ru_idrss+r1->ru_isrss-(r0->ru_idrss+r0->ru_isrss))/t); + END(outp); + break; + + case 'K': + sprintf(outp,"%d", t == 0 ? 0 : + ((r1->ru_ixrss+r1->ru_isrss+r1->ru_idrss) - + (r0->ru_ixrss+r0->ru_idrss+r0->ru_isrss))/t); + END(outp); + break; + + case 'M': + sprintf(outp,"%d", r1->ru_maxrss/2); + END(outp); + break; + + case 'F': + sprintf(outp,"%d", r1->ru_majflt-r0->ru_majflt); + END(outp); + break; + + case 'R': + sprintf(outp,"%d", r1->ru_minflt-r0->ru_minflt); + END(outp); + break; + + case 'I': + sprintf(outp,"%d", r1->ru_inblock-r0->ru_inblock); + END(outp); + break; + + case 'O': + sprintf(outp,"%d", r1->ru_oublock-r0->ru_oublock); + END(outp); + break; + case 'C': + sprintf(outp,"%d+%d", r1->ru_nvcsw-r0->ru_nvcsw, + r1->ru_nivcsw-r0->ru_nivcsw ); + END(outp); + break; +#endif /* !SYSV */ + } + } + *outp = '\0'; +} + +static void +tvadd(tsum, t0, t1) + struct timeval *tsum, *t0, *t1; +{ + + tsum->tv_sec = t0->tv_sec + t1->tv_sec; + tsum->tv_usec = t0->tv_usec + t1->tv_usec; + if (tsum->tv_usec > 1000000) + tsum->tv_sec++, tsum->tv_usec -= 1000000; +} + +static void +tvsub(tdiff, t1, t0) + struct timeval *tdiff, *t1, *t0; +{ + + tdiff->tv_sec = t1->tv_sec - t0->tv_sec; + tdiff->tv_usec = t1->tv_usec - t0->tv_usec; + if (tdiff->tv_usec < 0) + tdiff->tv_sec--, tdiff->tv_usec += 1000000; +} + +static void +psecs(l,cp) +long l; +register char *cp; +{ + register int i; + + i = l / 3600; + if (i) { + sprintf(cp,"%d:", i); + END(cp); + i = l % 3600; + sprintf(cp,"%d%d", (i/60) / 10, (i/60) % 10); + END(cp); + } else { + i = l; + sprintf(cp,"%d", i / 60); + END(cp); + } + i %= 60; + *cp++ = ':'; + sprintf(cp,"%d%d", i / 10, i % 10); +} + +/* + * N R E A D + */ +Nread( fd, buf, count ) +int fd; +void *buf; +int count; +{ + struct sockaddr_in from; + int len = sizeof(from); + register int cnt; + if( udp ) { + cnt = recvfrom( fd, buf, count, 0, SA(&from), &len ); + numCalls++; + } else { + if( b_flag ) + cnt = mread( fd, buf, count ); /* fill buf */ + else { + cnt = read( fd, buf, count ); + numCalls++; + } + if (touchdata && cnt > 0) { + register int c = cnt, sum; + register char *b = buf; + while (c--) + sum += *b++; + } + } + return(cnt); +} + +/* + * N W R I T E + */ +Nwrite( fd, buf, count ) +int fd; +void *buf; +int count; +{ + register int cnt; + if( udp ) { +again: + cnt = sendto( fd, buf, count, 0, SA(&sinhim), sizeof(sinhim) ); + numCalls++; + if( cnt<0 && errno == ENOBUFS ) { + delay(18000); + errno = 0; + goto again; + } + } else { + cnt = write( fd, buf, count ); + numCalls++; + } + return(cnt); +} + +void +delay(us) +{ + struct timeval tv; + + tv.tv_sec = 0; + tv.tv_usec = us; + (void)select( 1, (fd_set*)0, (fd_set *)0, (fd_set *)0, &tv ); +} + +/* + * M R E A D + * + * This function performs the function of a read(II) but will + * call read(II) multiple times in order to get the requested + * number of characters. This can be necessary because + * network connections don't deliver data with the same + * grouping as it is written with. Written by Robert S. Miles, BRL. + */ +int +mread(fd, bufp, n) +int fd; +register char *bufp; +unsigned n; +{ + register unsigned count = 0; + register int nread; + + do { + nread = read(fd, bufp, n-count); + numCalls++; + if(nread < 0) { + perror("ttcp_mread"); + return(-1); + } + if(nread == 0) + return((int)count); + count += (unsigned)nread; + bufp += nread; + } while(count < n); + + return((int)count); +} diff --git a/rce/rcecalib/server/eudaqserver.cc b/rce/rcecalib/server/eudaqserver.cc new file mode 100644 index 00000000..013f8884 --- /dev/null +++ b/rce/rcecalib/server/eudaqserver.cc @@ -0,0 +1,124 @@ +#include <stdio.h> +#include <unistd.h> + +#include <ers/ers.h> + +#include <ipc/object.h> +#include <ipc/alarm.h> +#include <ipc/core.h> +#include <ipc/server.h> + +#include <owl/timer.h> +#include <owl/semaphore.h> + +#include <boost/regex.hpp> + +#include "rcecalib/scanctrl/IPCScan.cc" +#include "rcecalib/scanctrl/IPCScanRoot.cc" +#include "rcecalib/config/IPCConfigIF.cc" +#include "rcecalib/HW/SerialHexdump.hh" +#include "rcecalib/HW/SerialPgp.hh" +#include "rcecalib/HW/SerialPgpFei4.hh" +#include "rcecalib/config/IPCModuleFactory.hh" +#include "rcecalib/util/RceName.hh" + +#include "rcecalib/server/eudaqserver.hh" +#include "rcecalib/server/RceProducer.hh" + +#include <is/infoT.h> +#include <is/infodictionary.h> +#include <ipc/core.h> + +static IPCServer ipcServer; + +////////////////////////////////////////// +// +// Main function +// +////////////////////////////////////////// + + +void eudaqserver::run(bool ismodule, char* partition){ + +const char *cc_argv[] = +{ + "eudaqserver", /* always the name of the program */ + "-p", + "rcetest", + // "-ORBtraceLevel", /* trace level */ + //"1", + "-ORBgiopMaxMsgSize", + "33554422", /* max message size 32 MB */ + "-ORBmaxServerThreadPerConnection", "1" +// "-ORBendPoint", +// " giop:tcp:192.168.1.35:" + //"-ORBtraceInvocations", + //"1" +}; + if(partition)cc_argv[2]=partition; +int cc_argc = sizeof( cc_argv ) / sizeof( cc_argv[ 0 ] ); + try { + IPCCore::init( cc_argc, (char**)cc_argv ); + } + catch( daq::ipc::Exception & ex ) { + ers::fatal( ex ); + return; + } + + // Declare command object and its argument-iterator + + IPCPartition p((const char*)cc_argv[2]); + printf("Partition is %s\n",cc_argv[2]); + char name[128]; + sprintf(name, "configIF_RCE%d", RceName::getRceNumber()); + p.isObjectValid<ipc::IPCConfigIFAdapter>(name); + + //Serial IF + new SerialPgpFei4; + + //Module Factory + + ModuleFactory *moduleFactory=new IPCModuleFactory(p); + + // Config IF + + IPCConfigIF<ipc::single_thread> *cif; + IPCScan<ipc::multi_thread> *scan; + IPCScanRoot<ipc::single_thread> * scanroot; + + try{ + cif=new IPCConfigIF<ipc::single_thread>(p, name, moduleFactory); + sprintf(name, "scanCtrl_RCE%d", RceName::getRceNumber()); + scan = new IPCScan<ipc::multi_thread>( p, name); + sprintf(name, "scanRoot_RCE%d", RceName::getRceNumber()); + scanroot = new IPCScanRoot<ipc::single_thread>( p, name, (ConfigIF*)cif, (Scan*)scan); + }catch(...){ + std::cout<<"Could not add IPC objects (ipc_server not running? Several servers in the same partition?)."<<std::endl; + assert(0); + } + + IPCHistoManager *hm; + try{ + sprintf(name, "RCE%d",RceName::getRceNumber()); + hm=new IPCHistoManager(p,"RceIsServer", name); + }catch(...){ + std::cout<<"Could not start histogram manager (is_server not running? Another server running on the same partition?)."<<std::endl; + assert(0); + } + printf("ipc_test_server has been started.\n"); + + + RceProducer producer("RceProducer", "tcp://172.21.7.146:44000", p); + //RceProducer producer("RceProducer", "tcp://rdcds105:44000", p); + if(ismodule==true){ + kill(getpid(),SIGUSR1); + pause(); + }else{ + ipcServer.run(); + } + + scan->_destroy(); + scanroot->_destroy(); + + std::cout << "Test successfully completed." << std::endl; +} diff --git a/rce/rcecalib/server/eudaqserver.hh b/rce/rcecalib/server/eudaqserver.hh new file mode 100644 index 00000000..416633f4 --- /dev/null +++ b/rce/rcecalib/server/eudaqserver.hh @@ -0,0 +1,11 @@ +#ifndef EUDAQSERVER_HH +#define EUDAQSERVER_HH + +class eudaqserver { + public: + eudaqserver(){}; + static void run(bool ismodule, char* partition); + +}; + +#endif diff --git a/rce/rcecalib/server/host_bootloader.cc b/rce/rcecalib/server/host_bootloader.cc new file mode 100644 index 00000000..87a5b21c --- /dev/null +++ b/rce/rcecalib/server/host_bootloader.cc @@ -0,0 +1,81 @@ +#include <stdio.h> +#include <iostream> +#include <fstream> +#include <string.h> +#include "rcecalib/server/BootLoaderPort.hh" +#include <boost/algorithm/string.hpp> +#include "RceControl.hh" +#include <termios.h> + +#include <arpa/inet.h> // for htonl + + +int main(int argc, char** argv) +{ + extern char* optarg; + int c; + const char* scriptname=0; + const char* filename=0; + + const char* rce=0; + const char *iorfile=0; + while ( (c=getopt( argc, argv, "r:s:l:i:")) != EOF ) { + switch(c) { + case 'r': + rce=optarg; + break; + case 's': + scriptname = optarg; + break; + case 'l': + filename = optarg; + break; + case 'i': + iorfile = optarg; + break; + } + } + RCE::RceControl rcecontrol; + try { + rcecontrol =RCE::RceControl(rce); + } catch(...) { + std::cout<<"Usage: host_bootloader -r IP_address [-s config_file] [-l sharedlib.so] [-i ior_file]"<<std::endl; + return 0; + } + std::string inpline; + std::istream *inp; + if(scriptname){ + std::ifstream* inpf= new std::ifstream (scriptname); + if (!inpf->is_open()){ + std::cout<<"File "<<scriptname<<" not found. Exiting."<<std::endl; + exit(1); + } + inp=(std::istream*)inpf; + }else{ + inp = &std::cin; + struct termios tios; + // Make sure backspace works in the terminal window. + tcgetattr(STDIN_FILENO, &tios); + if(tios.c_cc[VERASE]!=0x7f){ + tios.c_cc[VERASE]=0x7f; // set backspace as erase + tcsetattr(STDIN_FILENO,TCSANOW, &tios); + } + } + while (true){ //main loop + getline (*inp,inpline); + if(inp->eof())break; + boost::trim(inpline); + if(inpline.size()!=0 && inpline[0]!='#'){ + rcecontrol.sendCommand(inpline); + } + } + // option -i: read iorfile and set TDAQ_IPC_INIT_REF + rcecontrol.setIorFromFile(iorfile); + + + //option -l: download shared library. + if(filename){ + if(rcecontrol.loadModule(filename)) exit(-1); + } +} + diff --git a/rce/rcecalib/server/rceOfflineProducer_Linkdef.hh b/rce/rcecalib/server/rceOfflineProducer_Linkdef.hh new file mode 100644 index 00000000..fe7635f7 --- /dev/null +++ b/rce/rcecalib/server/rceOfflineProducer_Linkdef.hh @@ -0,0 +1,2 @@ +#pragma link C++ class ConfigGui; +#pragma link C++ class CosmicMonitoringGuiEmbedded; diff --git a/rce/rcecalib/server/rebootHSIO.cc b/rce/rcecalib/server/rebootHSIO.cc new file mode 100644 index 00000000..fd015e03 --- /dev/null +++ b/rce/rcecalib/server/rebootHSIO.cc @@ -0,0 +1,82 @@ + +#include <ipc/partition.h> +#include <ipc/core.h> +//#include <ipc/server.h> +#include <ipc/object.h> +#include <boost/regex.hpp> +#include "rcecalib/server/IPCController.hh" +#include "IPCConfigIFAdapter.hh" + +#include <cmdl/cmdargs.h> +#include <iostream> +#include <stdlib.h> + +int main( int argc, char ** argv ){ + CmdArgStr partition_name ('p', "partition", "partition-name", "partition to work in."); + //CmdArgInt rce ('r', "rce","rce-number", "number of the RCE that has the HSIO attached"); + +// +// Initialize command line parameters with default values +// + try { + IPCCore::init( argc, argv ); + } + catch( daq::ipc::Exception & ex ) { + ers::fatal( ex ); + return 1; + } + + //CmdLine cmd(*argv, &partition_name, &rce, NULL); + CmdLine cmd(*argv, &partition_name, NULL); + CmdArgvIter arg_iter(--argc, ++argv); + +// +// Parse arguments +// + cmd.parse(arg_iter); + //std::cout << partition_name.isNULL() << std::endl; + + const char *p_name=getenv("TDAQ_PARTITION"); + if(p_name==NULL) p_name="rcetest"; + if(! partition_name.isNULL()) p_name= (const char*)partition_name; + IPCPartition p(p_name ); + IPCController controller(p); + // How many RCEs are in the partition? + std::map< std::string, ipc::IPCConfigIFAdapter_var > objects; + std::vector<int> rces; + p.getObjects<ipc::IPCConfigIFAdapter>( objects ); + std::map< std::string, ipc::IPCConfigIFAdapter_var >::iterator it; + for ( it = objects.begin(); it != objects.end(); it++ ){ + boost::regex re("configIF_RCE(\\d+)"); + boost::cmatch matches; + if(boost::regex_search(it->first.c_str(), matches, re)){ + assert(matches.size()>1); + std::string match(matches[1].first, matches[1].second); + rces.push_back(strtol(match.c_str(),0,10)); + } + } + if(rces.size()==0){ + std::cout<<"No RCE in your partition. Exiting."<<std::endl; + exit(0); + } + int rce=rces[0]; + if(rces.size()>1){ + std::cout<<"There are multiple RCEs in your partition:"<<std::endl; + while(1){ + for(size_t i=0;i<rces.size();i++)std::cout<<rces[i]<<std::endl; + std::cout<<"Which one has the HSIO attached that you would like to reboot (99 = all)?"<<std::endl; + std::cin>>rce; + bool valid=false; + for(size_t i=0;i<rces.size();i++)if(rce==99 || rce==rces[i])valid=true; + if(valid)break; + std::cout<<"This RCE is not on the list. Try again."<<std::endl; + } + } + for(size_t i=0;i<rces.size();i++){ + if(rce==99||rce==rces[i]){ + controller.addRce(rces[i]); + std::cout<<"Rebooting HSIO on RCE "<<rces[i]<<std::endl; + controller.sendHWcommand(rces[i],8); //reboot + } + } +} diff --git a/rce/rcecalib/server/rtems_config.cc b/rce/rcecalib/server/rtems_config.cc new file mode 100644 index 00000000..d72b02f0 --- /dev/null +++ b/rce/rcecalib/server/rtems_config.cc @@ -0,0 +1,68 @@ +//#define CONFIGURE_STACK_CHECKER_ENABLED +//#define STACK_CHECKER_ON +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_TIMER_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_NULL_DRIVER + +#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 20 +#define CONFIGURE_MAXIMUM_TASKS 20 +#define CONFIGURE_MAXIMUM_SEMAPHORES 100 +#define CONFIGURE_MAXIMUM_PARTITIONS 10 +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1 +#define CONFIGURE_MAXIMUM_DRIVERS 10 + + +#define CONFIGURE_MICROSECONDS_PER_TICK 10000 + +#define CONFIGURE_EXECUTIVE_RAM_SIZE (4096*1024) +//#define CONFIGURE_EXTRA_TASK_STACKS (256*1024) +// for telnetd and shell and IMFS +#define RTEMS_NETWORKING +#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 50 +#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK +#define CONFIGURE_MAXIMUM_PTYS 4 + +#define CONFIGURE_SHELL_COMMANDS_INIT +#define CONFIGURE_SHELL_COMMANDS_ALL +#define CONFIGURE_SHELL_MOUNT_TFTP +#define CONFIGURE_SHELL_MOUNT_FTP +#define CONFIGURE_SHELL_MOUNT_NFS + +#include <rtems/shellconfig.h> + +#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM +#define CONFIGURE_IMFS_MEMFILE_BYTES_PER_BLOCK 256 + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE +#define CONFIGURE_INIT + +/* POSIX API resources */ +#define CONFIGURE_MAXIMUM_POSIX_THREADS 100 +#define CONFIGURE_MAXIMUM_POSIX_MUTEXES 100 +#define CONFIGURE_MAXIMUM_POSIX_CONDITION_VARIABLES 100 +#define CONFIGURE_MAXIMUM_POSIX_KEYS 1024 +#define CONFIGURE_MAXIMUM_POSIX_TIMERS 100 +#define CONFIGURE_MAXIMUM_POSIX_QUEUED_SIGNALS 100 +#define CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES 100 +#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES 100 +#define CONFIGURE_MINIMUM_TASK_STACK_SIZE 16384 + + +//extern "C" void *POSIX_Init( void *argument ); +//#define CONFIGURE_INIT_TASK_STACK_SIZE (64*1024) + +//#define CONFIGURE_POSIX_INIT_THREAD_TABLE + + + +// to enable malloc statistics +#define CONFIGURE_MALLOC_STATISTICS + + +#include <rtems.h> + +extern "C" rtems_task Init(rtems_task_argument); + +#include <rtems/confdefs.h> +#define CONFIGURE_POSIX_INIT_THREAD_STACK_SIZE (256*1024) diff --git a/rce/rcecalib/server/rtems_config_2.2.cc b/rce/rcecalib/server/rtems_config_2.2.cc new file mode 100644 index 00000000..93090554 --- /dev/null +++ b/rce/rcecalib/server/rtems_config_2.2.cc @@ -0,0 +1,127 @@ +#ifndef CONFIGURATION_RTEMS_RCE_DEVEL_HH +#define CONFIGURATION_RTEMS_RCE_DEVEL_HH + +// See the RTEMS C USer's Guide Chanper 23, "Configuring a System" +// Modified for RTEMS 4.10.0. + +// The file configure_template.cc lists all the available options and +// gives a brief explanation of each. + +#include <rtems.h> + +#define CONFIGURE_INIT + +///////////////////////////// +// 23.2.1: Library support // +///////////////////////////// +//combine RTEMS workspace and C heap +#define CONFIGURE_UNIFIED_WORK_AREAS + +#define CONFIGURE_MALLOC_STATISTICS +#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS (20) +#define CONFIGURE_MAXIMUM_PTYS (4) +#define CONFIGURE_STACK_CHECKER_ENABLED +#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK +#define CONFIGURE_IMFS_MEMFILE_BYTES_PER_BLOCK (256) +#define CONFIGURE_FILESYSTEM_FTPFS +#define CONFIGURE_FILESYSTEM_IMFS +#define CONFIGURE_FILESYSTEM_NFS + +////////////////////////////////////// +// 23.2.2: Basic system information // +////////////////////////////////////// + +// These RCE-specific definitions will be used both here and in the +// section setting limits on the numbers of classic RTEMS objects. We +// expect that most applications will use the queue types defined in +// the RCE core so our limits here are rather small. +namespace { + enum {RCE_MAX_RTEMS_MSG_QUEUES = 10, + RCE_MAX_BYTES_PER_MSG = 8, // Enough for a regular pointer or a std::tr1::smart_ptr. + RCE_MAX_MSGS_PER_QUEUE = 100 + }; +} + +#define CONFIGURE_MESSAGE_BUFFER_MEMORY \ + (RCE_MAX_RTEMS_MSG_QUEUES * \ + CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE(RCE_MAX_MSGS_PER_QUEUE,RCE_MAX_BYTES_PER_MSG)\ + ) + +// Some applications are known to require extra stack space, e.g., +// Martin Kocian's PGP test. +#define CONFIGURE_MICROSECONDS_PER_TICK 10000 +//#define CONFIGURE_EXECUTIVE_RAM_SIZE (4096*1024) +#define CONFIGURE_EXTRA_TASK_STACKS (4096*1024*2) + +///////////////////////////////// +// 23.2.4: Device driver table // +///////////////////////////////// +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_TIMER_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_NULL_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_STUB_DRIVER +#define CONFIGURE_MAXIMUM_DRIVERS (11) + +///////////////////////// +// 23.2.6: Classic API // +///////////////////////// +#define CONFIGURE_MAXIMUM_TASKS (50) +#define CONFIGURE_MAXIMUM_TIMERS (20) +#define CONFIGURE_MAXIMUM_SEMAPHORES (100) +#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES (RCE_MAX_RTEMS_MSG_QUEUES) +#define CONFIGURE_MAXIMUM_PARTITIONS (10) +#define CONFIGURE_MAXIMUM_REGIONS (10) +#define CONFIGURE_MAXIMUM_PORTS (10) +#define CONFIGURE_MAXIMUM_PERIODS (10) +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS (5) +// One of the user extensions is defined by the BSP to delete tasks +// that exit from their main functions (entry points). Normally RTEMS +// treats that as an error. + +////////////////////////////////////////// +// 23.2.7: Classic API Init-tasks table // +////////////////////////////////////////// +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +//#define CONFIGURE_POSIX_INIT_THREAD_STACK_SIZE (128*1024) +//#define CONFIGURE_POSIX_INIT_THREAD_TABLE +//extern "C" void *POSIX_Init( void *argument ); +////////////////////////////// +// 23.3 Configuration table // +////////////////////////////// +#define CONFIGURE_CONFDEFS_DEBUG + +///////////////////////////////////////////////////////////// +// Enable to print information about the work area and heap// +///////////////////////////////////////////////////////////// +//#define BSP_GET_WORK_AREA_DEBUG + +/* POSIX API resources */ +#define CONFIGURE_MAXIMUM_POSIX_THREADS 100 +#define CONFIGURE_MAXIMUM_POSIX_MUTEXES 100 +#define CONFIGURE_MAXIMUM_POSIX_CONDITION_VARIABLES 100 +#define CONFIGURE_MAXIMUM_POSIX_KEYS 1024 +#define CONFIGURE_MAXIMUM_POSIX_TIMERS 100 +#define CONFIGURE_MAXIMUM_POSIX_QUEUED_SIGNALS 100 +#define CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES 100 +#define CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUE_DESCRIPTORS 100 +#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES 100 +#define CONFIGURE_MAXIMUM_POSIX_BARRIERS 100 +#define CONFIGURE_MAXIMUM_POSIX_SPINLOCKS 100 +#define CONFIGURE_MAXIMUM_POSIX_RWLOCKS 100 +#define CONFIGURE_MINIMUM_TASK_STACK_SIZE 16384 +#define CONFIGURE_POSIX_INIT_THREAD_STACK_SIZE (256*1024) +#include <rtems/confdefs.h> + +///////////////// +// RTEMS shell // +///////////////// +#define CONFIGURE_SHELL_COMMANDS_INIT +#define CONFIGURE_SHELL_COMMANDS_ALL +#define CONFIGURE_SHELL_COMMANDS_ALL_NETWORKING +#define CONFIGURE_SHELL_MOUNT_NFS + +#include <rtems/shellconfig.h> + +#endif diff --git a/rce/rcecalib/server/runeudaqserver.cc b/rce/rcecalib/server/runeudaqserver.cc new file mode 100644 index 00000000..a1fd37bc --- /dev/null +++ b/rce/rcecalib/server/runeudaqserver.cc @@ -0,0 +1,125 @@ +/// @file core.cc +/// @brief As the last part of the initialization of the system after +/// a reboot, load from flash, relocate and run the application module +/// selected by the RCE front panel. + + +#include "rce/debug/Debug.hh" +#include "rce/debug/Print.hh" +#include "rce/shell/ShellCommon.hh" +#include "rce/gdbstub/rtems-gdb-stub.h" + + +#include "rce/service/Thread.hh" +#include "rceusr/init/NetworkConfig.hh" +#include "rceusr/tool/DebugHandler.hh" + +#include "rce/pgp/DriverList.hh" + +extern "C"{ + #include <librtemsNfs.h> +} + +#include <omnithread.h> +#include <pthread.h> +#include "eudaqserver.hh" + +#include <exception> +#include <stdio.h> +#include <string> + +#include <iostream> + +// We need to include <iostream> so that symbolic references to +// std::cout et al. are made. The weak definitions will therefore be +// picked up from libstdc++. Modules are not linked against libstdc++ +// so they rely on the definitions in the core. +#include <iostream> + +using std::exception; +using std::string; + +using RCE::Shell::startShell; + +using RceDebug::printv; + +using RceInit::configure_network_from_dhcp; + +using RceSvc::Exception; + +// use global IP address of bootp server in RTEMS +extern struct in_addr rtems_bsdnet_bootp_server_address; + +extern "C" { + + // This symbol is set by the static linker (ld) to the start if the + // "dynamic section" which the linker uses to find the system symbol + // table. + extern const char _DYNAMIC; + + void *posix_init( void *argument ); +#if RCE_INTERFACE == 1 +#warning RCE_INTERFACE=1 +#elif RCE_INTERFACE == 0 +#warning RCE_INTERFACE=0 +#else +#error invalid RCE_INTERFACE +#endif + + + unsigned interface = RCE_INTERFACE; + void init_executive() + { + try { + RceInit::configure_network_from_dhcp(interface); + RcePgp::init_pgp(); + printf("starting shell\n"); + startShell(); + // Start a debugger daemon + // First arg = 0 --> use socket IO over TCP. + // Second arg = 0 --> Priority is chosen by the debugger daemon + rtems_gdb_start(0, 0); + + rpcUdpInit(); + nfsInit( 0, 0 ); + printf("BOOTP server is %s. Use as NFS server.\n",inet_ntoa( rtems_bsdnet_bootp_server_address)); + nfsMount(inet_ntoa( rtems_bsdnet_bootp_server_address), (char*)NFSDIR ,(char*)"/nfs"); //NFSDIR comes from constituents.mk + pthread_t mthread; + pthread_attr_t attr; + int stacksize; + int ret; + // setting a new size + stacksize = (PTHREAD_STACK_MIN + 0x20000); + // void* stackbase = (void *) malloc(size); + ret = pthread_attr_init(&attr); + ret = pthread_attr_setstacksize(&attr, stacksize); + struct sched_param sparam; + sparam.sched_priority = 5; + pthread_attr_setschedparam(&attr, &sparam); + pthread_create( &mthread, &attr , posix_init, NULL); + + + } catch (Exception& e) { + printv("*** RCE exception %s", e.what()); + } catch (exception& e) { + printv("*** C++ exception %s", e.what()); + } + printf("Done with init_executive"); + } +void *posix_init( void *argument ){ + printf("posixinit\n"); + std::cout<<"Init Exec called"<<std::endl; + omni_thread::init_t omni_thread_init; + pthread_attr_t attr; + size_t st = 0; + pthread_attr_init(&attr); + pthread_attr_getstacksize( &attr, &st ); + st = _Thread_Executing->Start.Initial_stack.size; + printf( "Init Task Stack Size is: %d\n", st ); + + // char* bla=new char[10000000]; + eudaqserver::run(); + printf("posixinit done\n"); + return 0; +} +} diff --git a/rce/rcecalib/server/runeudaqservermod.cc b/rce/rcecalib/server/runeudaqservermod.cc new file mode 100644 index 00000000..9379f3fd --- /dev/null +++ b/rce/rcecalib/server/runeudaqservermod.cc @@ -0,0 +1,106 @@ +/// @file core.cc +/// @brief As the last part of the initialization of the system after +/// a reboot, load from flash, relocate and run the application module +/// selected by the RCE front panel. + + +#include "rce/debug/Debug.hh" +#include "rce/debug/Print.hh" +//#include "rce/shell/ShellCommon.hh" + + +#include "rce/service/Thread.hh" +#include "rce/service/Exception.hh" +//#include "rceusr/init/NetworkConfig.hh" +//#include "rceusr/tool/DebugHandler.hh" + +#include "rce/pgp/DriverList.hh" + +//extern "C"{ +// #include <librtemsNfs.h> +//} + +#include <omnithread.h> +#include "eudaqserver.hh" + +#include <exception> +#include <stdio.h> +#include <stdlib.h> +#include <string> + +#include <iostream> + +// We need to include <iostream> so that symbolic references to +// std::cout et al. are made. The weak definitions will therefore be +// picked up from libstdc++. Modules are not linked against libstdc++ +// so they rely on the definitions in the core. +#include <iostream> + +using std::exception; +using std::string; + +//using RCE::Shell::startShell; + +using RceDebug::printv; + +//using RceInit::configure_network_from_dhcp; + +using RceSvc::Exception; + +// use global IP address of bootp server in RTEMS +extern struct in_addr rtems_bsdnet_bootp_server_address; +//extern char **environ; + + +extern "C" { + + // This symbol is set by the static linker (ld) to the start if the + // "dynamic section" which the linker uses to find the system symbol + // table. + extern const char _DYNAMIC; + + void *posix_init( void *argument ); + + + rtems_task rce_appmain(rtems_task_argument arg) + { + try { + printf("rce_appmain\n"); + pthread_t mthread; + pthread_attr_t attr; + int stacksize; + int ret; + // setting a new size + stacksize = (PTHREAD_STACK_MIN + 0x20000); + // void* stackbase = (void *) malloc(size); + ret = pthread_attr_init(&attr); + ret = pthread_attr_setstacksize(&attr, stacksize); + struct sched_param sparam; + sparam.sched_priority = 5; + pthread_attr_setschedparam(&attr, &sparam); + pthread_create( &mthread, &attr , posix_init, NULL); + + + } catch (Exception& e) { + printv("*** RCE exception %s", e.what()); + } catch (exception& e) { + printv("*** C++ exception %s", e.what()); + } + printf("Done with init_executive"); + } +void *posix_init( void *argument ){ + printf("posixinit\n"); + std::cout<<"Init Exec called"<<std::endl; + omni_thread::init_t omni_thread_init; + pthread_attr_t attr; + size_t st = 0; + pthread_attr_init(&attr); + pthread_attr_getstacksize( &attr, &st ); + st = _Thread_Executing->Start.Initial_stack.size; + printf( "Init Task Stack Size is: %d\n", st ); + char* partition=getenv("TDAQ_PARTITION"); + eudaqserver::run(true, partition); // if 0 then the default partition will be rcetest + printf("posixinit done\n"); + return 0; +} +} diff --git a/rce/rcecalib/server/runserver.cc b/rce/rcecalib/server/runserver.cc new file mode 100644 index 00000000..5dd3f996 --- /dev/null +++ b/rce/rcecalib/server/runserver.cc @@ -0,0 +1,127 @@ +/// @file core.cc +/// @brief As the last part of the initialization of the system after +/// a reboot, load from flash, relocate and run the application module +/// selected by the RCE front panel. + +#ifdef RCE_V2 +#include "datCode.hh" +#include DAT_PUBLIC( service, fci, Exception.hh) +#else +#include "rce/debug/Debug.hh" +#include "rce/debug/Print.hh" +#include "rce/shell/ShellCommon.hh" +#include "rce/gdbstub/rtems-gdb-stub.h" + + +#include "rce/service/Thread.hh" +#include "rceusr/init/NetworkConfig.hh" +#include "rceusr/tool/DebugHandler.hh" + +#include "rce/pgp/DriverList.hh" + +extern "C"{ + #include <librtemsNfs.h> +} +#endif + +#include <omnithread.h> +#include <pthread.h> +#include "calibserver.hh" + +#include <exception> +#include <stdio.h> +#include <string> + +#include <iostream> + +// We need to include <iostream> so that symbolic references to +// std::cout et al. are made. The weak definitions will therefore be +// picked up from libstdc++. Modules are not linked against libstdc++ +// so they rely on the definitions in the core. +#include <iostream> + +using std::exception; +using std::string; + +using RCE::Shell::startShell; + +using RceDebug::printv; + +using RceInit::configure_network_from_dhcp; + +using RceSvc::Exception; + +// use global IP address of bootp server in RTEMS +extern struct in_addr rtems_bsdnet_bootp_server_address; + +extern "C" { + + // This symbol is set by the static linker (ld) to the start if the + // "dynamic section" which the linker uses to find the system symbol + // table. + extern const char _DYNAMIC; + + void *posix_init( void *argument ); +#if RCE_INTERFACE == 1 +#warning RCE_INTERFACE=1 +#elif RCE_INTERFACE == 0 +#warning RCE_INTERFACE=0 +#else +#error invalid RCE_INTERFACE +#endif + + + unsigned interface = RCE_INTERFACE; + void init_executive() + { + try { + RceInit::configure_network_from_dhcp(interface); + RcePgp::init_pgp(); + printf("starting shell\n"); + startShell(); + // Start a debugger daemon + // First arg = 0 --> use socket IO over TCP. + // Second arg = 0 --> Priority is chosen by the debugger daemon + rtems_gdb_start(0, 0); + + rpcUdpInit(); + nfsInit( 0, 0 ); + printf("BOOTP server is %s. Use as NFS server.\n",inet_ntoa( rtems_bsdnet_bootp_server_address)); + nfsMount(inet_ntoa( rtems_bsdnet_bootp_server_address),(char*) NFSDIR ,(char*)"/nfs"); //NFSDIR comes from constituents.mk + pthread_t mthread; + pthread_attr_t attr; + int stacksize; + int ret; + // setting a new size + stacksize = (PTHREAD_STACK_MIN + 0x20000); + // void* stackbase = (void *) malloc(size); + ret = pthread_attr_init(&attr); + ret = pthread_attr_setstacksize(&attr, stacksize); + struct sched_param sparam; + sparam.sched_priority = 5; + pthread_attr_setschedparam(&attr, &sparam); + pthread_create( &mthread, &attr , posix_init, NULL); + + + } catch (Exception& e) { + printv("*** RCE exception %s", e.what()); + } catch (exception& e) { + printv("*** C++ exception %s", e.what()); + } + printf("Done with init_executive"); + } +void *posix_init( void *argument ){ + printf("posixinit\n"); + std::cout<<"Init Exec called"<<std::endl; + omni_thread::init_t omni_thread_init; + pthread_attr_t attr; + size_t st = 0; + pthread_attr_init(&attr); + pthread_attr_getstacksize( &attr, &st ); + st = _Thread_Executing->Start.Initial_stack.size; + printf( "Init Task Stack Size is: %d\n", st ); + calibserver::run(false); + printf("posixinit done\n"); + return 0; +} +} diff --git a/rce/rcecalib/server/runservermod.cc b/rce/rcecalib/server/runservermod.cc new file mode 100644 index 00000000..3187c18c --- /dev/null +++ b/rce/rcecalib/server/runservermod.cc @@ -0,0 +1,117 @@ +/// @file core.cc +/// @brief As the last part of the initialization of the system after +/// a reboot, load from flash, relocate and run the application module +/// selected by the RCE front panel. + +#ifdef RCE_V2 +#include "datCode.hh" +#include DAT_PUBLIC( service, fci, Exception.hh) +#include DAT_PUBLIC( service, debug, Print.hh) +#else +#include "rce/debug/Debug.hh" +#include "rce/debug/Print.hh" +//#include "rce/shell/ShellCommon.hh" +#include "rce/service/Thread.hh" +#include "rce/service/Exception.hh" +//#include "rceusr/init/NetworkConfig.hh" +//#include "rceusr/tool/DebugHandler.hh" + +#include "rce/pgp/DriverList.hh" +//extern "C"{ +// #include <librtemsNfs.h> +//} + +#endif +#include "namespace_aliases.hh" +#include <omnithread.h> +#include "calibserver.hh" +#include <limits.h> +#include <exception> +#include <stdio.h> +#include <stdlib.h> +#include <string> + +#include <iostream> + +// We need to include <iostream> so that symbolic references to +// std::cout et al. are made. The weak definitions will therefore be +// picked up from libstdc++. Modules are not linked against libstdc++ +// so they rely on the definitions in the core. +#include <iostream> + +using std::exception; +using std::string; + +//using RCE::Shell::startShell; + +using RceDebug::printv; + +//using RceInit::configure_network_from_dhcp; + +using RceSvc::Exception; + +// use global IP address of bootp server in RTEMS +extern struct in_addr rtems_bsdnet_bootp_server_address; +//extern char **environ; + + +extern "C" { + + // This symbol is set by the static linker (ld) to the start if the + // "dynamic section" which the linker uses to find the system symbol + // table. + extern const char _DYNAMIC; + + void *posix_init( void *argument ); + + +#ifdef RCE_V2 + void rce_appmain(void* arg) +#else + rtems_task rce_appmain(rtems_task_argument arg) +#endif + { + try { + printf("rce_appmain\n"); + pthread_t mthread; + pthread_attr_t attr; + int stacksize; + int ret; + // setting a new size + stacksize = (PTHREAD_STACK_MIN + 0x20000); + // void* stackbase = (void *) malloc(size); + ret = pthread_attr_init(&attr); + ret = pthread_attr_setstacksize(&attr, stacksize); + struct sched_param sparam; + sparam.sched_priority = 5; + pthread_attr_setschedparam(&attr, &sparam); + pthread_create( &mthread, &attr , posix_init, NULL); + + + } catch (Exception& e) { + printv("*** RCE exception %s", e.what()); + } catch (exception& e) { + printv("*** C++ exception %s", e.what()); + } + printf("Done with init_executive"); + } +void *posix_init( void *argument ){ + printf("posixinit\n"); + std::cout<<"Init Exec called"<<std::endl; + omni_thread::init_t omni_thread_init; + pthread_attr_t attr; + size_t st = 0; + pthread_attr_init(&attr); + pthread_attr_getstacksize( &attr, &st ); +#ifdef RCE_V2 + //st = _Per_CPU_Information_Executing->Start.Initial_stack.size; +#else + st = _Thread_Executing->Start.Initial_stack.size; +#endif + printf( "Init Task Stack Size is: %d\n", st ); + char* partition=getenv("TDAQ_PARTITION"); + calibserver::run(true, partition); // if 0 then the default partition will be rcetest + printf("posixinit done\n"); + return 0; +} +} diff --git a/rce/rcecalib/server/sendBitStream.cc b/rce/rcecalib/server/sendBitStream.cc new file mode 100644 index 00000000..23a45625 --- /dev/null +++ b/rce/rcecalib/server/sendBitStream.cc @@ -0,0 +1,604 @@ + +#include <ipc/partition.h> +#include <ipc/core.h> +#include <ipc/server.h> +#include <ipc/object.h> + +#include "rcecalib/server/IPCController.hh" +#include "rcecalib/server/PixScan.hh" +#include "ScanOptions.hh" +#include "rcecalib/config/FEI4/FECommands.hh" +#include "rcecalib/config/FEI4/FEI4ARecord.hh" +#include "rcecalib/config/FEI4/FEI4AFormatter.hh" +#include "rcecalib/config/FormattedRecord.hh" +#include "rcecalib/server/FEI4AConfigFile.hh" + +#include <cmdl/cmdargs.h> +#include <iostream> +#include <stdio.h> + +typedef struct { + uint16_t DB0; // (bitmask, one bit set) + uint16_t DB1; // (bitmask, one bit set) + uint16_t DB2; // (bitmask, one bit set) + uint16_t DB3; // (bitmask, one bit set) + uint16_t DB4; // (bitmask, one bit set) + uint16_t DB5; // (bitmask, one bit set) + uint16_t DB6; // (bitmask, one bit set) + uint16_t DB7; // (bitmask, one bit set) + uint16_t RS; // (bitmask, one bit set) + uint16_t RW; // (bitmask, one bit set) + uint16_t EN; // (bitmask, one bit set) + IPCController* controller; + int rce; +} HD44780_t; +static HD44780_t lcd = { 1 << 8, + 1 << 9, + 1 << 10, + 1 << 11, + 1 << 12, + 1 << 13, + 1 << 14, + 1 << 15, + 1 << 0, + 1 << 1, + 1 << 2, + 0, + 0}; + +HD44780_t* lcdp = &lcd; + +#define PCA9535_REG_INPUT_0 0 +#define PCA9535_REG_INPUT_1 1 +#define PCA9535_REG_OUTPUT_0 2 +#define PCA9535_REG_OUTPUT_1 3 +#define PCA9535_REG_POLINV_0 4 +#define PCA9535_REG_POLINV_1 5 +#define PCA9535_REG_CFG_0 6 +#define PCA9535_REG_CFG_1 7 + +#define HD44780_COMMAND 0 +#define HD44780_DATA 1 + +#define HD44780_MINDELAY 43 // minimum delay between commands +#define HD44780_EN_UP 1 //Time for EN bit to be up (us) + //Spec has either 480 or 460 ns + +#define DEL_INIT_POWERON 40000 // Max poweron delay from [2] and [3] +#define DEL_INIT_1 5000 // From [2] -- larger than [3] +#define DEL_INIT_2 100 // from [2] +#define INIT_8_BIT 0x30 +#define INIT_4_BIT 0x20 + +// Specific LCD commands, their arguments and their required delays (in us) +#define CMD_CLEARDISPLAY (1 << 0) //0b00000001 +#define DEL_CLEARDISPLAY 1520 // 1.52ms + +#define CMD_RETURNHOME (1 << 1) //0b00000010 +#define DEL_RETURNHOME 1520 // 1.52ms +#define NWR_RETURNHOME HD44780_MINWRITE + +#define CMD_ENTRYMODESET (1 << 2) //0b00000100 +#define DEL_ENTRYMODESET HD44780_MINDELAY +#define EMS_INCREMENT (1 << 1) //0b00000010 +#define EMS_DECREMENT 0 +#define EMS_DISPLAYSHIFTON (1 << 0) //0b00000001 +#define EMS_DISPLAYSHIFTOFF 0 + + +#define CMD_DISPLAYCONTROL (1 << 3) //0b00001000 +#define DEL_DISPLAYCONTROL HD44780_MINDELAY +#define DSC_DISPLAYON (1 << 2) //0b00000100 +#define DSC_DISPLAYOFF 0 +#define DSC_CURSORON (1 << 1) //0b00000010 +#define DSC_CURSOROFF 0 +#define DSC_BLINKON (1 << 0) //0b00000001 +#define DSC_BLINKOFF 0 + +#define CMD_CURSORDISPSHIFT (1 << 4) //0b00010000 +#define DEL_CURSORDISPSHIFT HD44780_MINDELAY +#define CDS_DISPLAYSHIFT (1 << 3) //0b00001000 +#define CDS_CURSORMOVE 0 +#define CDS_SHIFTRIGHT (1 << 2) //0b00000100 +#define CDS_SHIFTLEFT 0 + +#define CMD_FUNCTIONSET (1 << 5) //0b00100000 +#define DEL_FUNCTIONSET HD44780_MINDELAY +#define FNS_DATAWIDTH8 (1 << 4) //0b00010000 +#define FNS_DATAWIDTH4 0 +#define FNS_DISPLAYLINES2 (1 << 3) //0b00001000 +#define FNS_DISPLAYLINES1 0 +#define FNS_FONT5X10 (1 << 2) //0b00000100 +#define FNS_FONT5X7 0 + +#define CMD_SETCGRAMADDR (1 << 6) //0b01000000 +#define DEL_SETCGRAMADDR HD44780_MINDELAY +#define CGR_ADDRESSMASK 0x3F + +#define CMD_SETDDRAMADDR (1 << 7) //0b10000000 +#define DEL_SETDDRAMADDR HD44780_MINDELAY +#define DDR_ADDRESSMASK 0x7F + +#define DEL_ROTATEDISPLAY HD44780_MINDELAY // rotation rate controlled externally + +#define GPIO_ALL_LINES_OUTPUT 0x0000 +#define GPIO_ALL_LINES_INPUT 0xFFFF + +//Display +void HD44780_init(const HD44780_t *device, uint8_t lines); +void HD44780_reset(const HD44780_t *device); +int HD44780_WriteDelay(const HD44780_t* device, const uint16_t data, const uint32_t delayAfter); +int HD44780_WriteSync(const HD44780_t* device, const uint16_t data, const uint32_t delayAfter); +void HD44780_Command(const HD44780_t*, const uint8_t command, const uint32_t delayafter); +void HD44780_Data(const HD44780_t*, const uint8_t); +void HD44780_WriteByteDDRAM(const HD44780_t*, const uint8_t, const uint8_t); +void HD44780_WriteByte(const HD44780_t*, const uint8_t reg, const uint8_t data, const uint32_t delayafter); +void HD44780_GpioWrite(const HD44780_t* device, const uint16_t data); +int i2c_write_reg(const HD44780_t* device, uint8_t reg, uint8_t data); +void HD44780_clear(const HD44780_t* device); +void HD44780_home(const HD44780_t* device); +void HD44780_putChar(const HD44780_t* device, const uint8_t data); +void HD44780_putCharAt(const HD44780_t* device, const uint8_t data, const uint8_t address); +void HD44780_putStr(const HD44780_t* device, const char* str); +void HD44780_putStrN(const HD44780_t* device, const char* str, const uint8_t strlen); +void HD44780_rotate(const HD44780_t* device, const uint8_t direction); + +void encode8b10b(unsigned *patbuffer, int patlen, unsigned *encbuffer, int &enclen); +void addBits(unsigned *buffer, unsigned word, unsigned numbits, unsigned bitpos); +unsigned decode(std::vector<unsigned char> inpvec); + +int main( int argc, char ** argv ){ + + CmdArgStr partition_name ('p', "partition", "partition-name", "partition to work in."); + +// +// Initialize command line parameters with default values +// + try { + IPCCore::init( argc, argv ); + } + catch( daq::ipc::Exception & ex ) { + ers::fatal( ex ); + return 1; + } + + CmdLine cmd(*argv, &partition_name, NULL); + CmdArgvIter arg_iter(--argc, ++argv); + +// +// Parse arguments +// + cmd.parse(arg_iter); + + IPCPartition p( (const char*)partition_name ); + IPCController controller(p); + lcd.controller=&controller; + int rce=0; + std::cout<<"RCE number?"<<std::endl; + std::cin>>rce; + lcd.rce=rce; + unsigned serstat, val; + controller.removeAllRces(); + controller.addRce(rce); + //assert(controller.writeHWregister(3,0)==0); //emulator or loopback + //assert(controller.writeHWregister(rce, 16,1)==0); //channel mode, 1=framed + //assert(controller.writeHWregister(rce, 0,1)==0); //channel mask + //assert(controller.writeHWregister(rce, 13,1)==0); //channel out mask + //assert(controller.readHWregister(rce, 14,val)==0); //channel mask + std::cout<<"In Mask: "<<std::hex<<val<<std::dec<<std::endl; + //assert(controller.readHWregister(rce, 15,val)==0); //channel mask + //assert(controller.writeHWregister(10,2)==0); //clock + std::cout<<"Out Mask: "<<std::hex<<val<<std::dec<<std::endl; + //controller.removeAllModules(); + //controller.addModule("module", "FEI4A",0,0,0,rce, ""); + + //setup chip + //serstat=controller.writeHWglobalRegister("module", 16, 0x10); + //serstat=controller.writeHWregister(rce, 15,0x180); //setup mux + ////serstat=controller.writeHWglobalRegister("module", 4, 0xffff); + ////serstat=controller.writeHWglobalRegister("module", 14, 0x4b00); + //serstat=controller.writeHWglobalRegister("module", 15, 0xf3c); + //serstat=controller.writeHWglobalRegister("module", 27, 0x8000); + //serstat=controller.writeHWglobalRegister("module", 28, 0x8206); + ////serstat=controller.writeHWglobalRegister("module", 28, 0x8206); + //serstat=controller.writeHWglobalRegister("module", 29, 0x2007); + /* Raw bitstream test with printout + PixScan scn(PixScan::COSMIC_DATA); + ipc::ScanOptions options; + scn.setName("TCP_0000"); // send data over the network rather than to file + scn.convertScanConfig(options); + controller.downloadScanConfig("CosmicData", options); + unsigned encbuffer[1024]; + while(1){ + std::cout<<"Phase: "; + int phase; + std::cin >>phase; + controller.writeHWregister(10,phase); + for (int i=0;i<1024;i++)encbuffer[i]=0; + std::vector<unsigned> bitstream; + std::string inp; + bool eof=true; + do{ + std::cin>>inp; + if(inp=="s")break; + if(inp=="q")exit(0); + if(inp=="eof" || inp=="EOF"){ + bitstream.push_back(0x1bc); + eof=true; + } else if(inp=="sof" || inp=="SOF"){ + bitstream.push_back(0x1fc); + eof=false; + } else if(inp=="idle" || inp=="IDLE")bitstream.push_back(0x13c); + else bitstream.push_back(strtoul(inp.c_str(),0,16)); + }while (1); + if(eof==false){ + std::cout<<"SOF not followed by EOF. Send anyway?"<<std::endl; + std::cin>>inp; + if(inp!="y" && inp!="Y")continue; + } + int enclen; + encode8b10b(&bitstream[0],bitstream.size(),encbuffer,enclen); + std::vector<unsigned> bs8b10b; + for (int i=0;i<enclen;i++){ + std::cout<<std::hex<<encbuffer[i]<<std::endl; + bs8b10b.push_back(encbuffer[i]); + } + //serstat=controller.writeHWblockData(bs8b10b); + serstat=controller.writeHWblockData(bitstream); + assert(serstat==0); + } + */ + // Test of trigger command + int command; + unsigned short inp; + unsigned nbt; + int reg; + BitStream *bs; + std::vector<unsigned char> rep; + new IPCHistoManager(p,"RceIsServer", "dummy"); + FEI4AFormatter fmt(0); + FEI4::FECommands commands; + std::vector<unsigned> dcoldata; + std::vector<unsigned> retv; + unsigned dcol, bit, xval; + FEI4AConfigFile fei4file; + ipc::PixelFEI4AConfig* cfgfei4a; + bool good; + commands.setAddr(0); + bs=new BitStream; + commands.switchMode(bs, FEI4::FECommands::RUN); + bs->push_back(0); + for(size_t i=0;i<bs->size();i++)std::cout<<std::hex<<(*bs)[i]<<std::endl; + + while(true){ + std::cout<<"Choose a command"<<std::endl; + std::cout<<"================"<<std::endl; + std::cout<<" 1) Send command"<<std::endl; + std::cout<<" 2) Write register"<<std::endl; + std::cout<<" 3) Read register"<<std::endl; + std::cout<<" 4) Write block data"<<std::endl; + std::cout<<" 5) Initialize display"<<std::endl; + std::cout<<" 6) Write string to display"<<std::endl; + //std::cout<<" 5) Write block data with handshake"<<std::endl; + std::cin>>std::dec>>command; + switch (command){ + case 1: + std::cout<<"Opcode?"<<std::endl; + unsigned opcode; + std::cin>>opcode; + assert(controller.sendHWcommand(rce, opcode)==0); + break; + case 2: + unsigned address, data; + std::cout<<"Address?"<<std::endl; + std::cin>>std::hex>>address; + std::cout<<"Data?"<<std::endl; + std::cin>>std::hex>>data>>std::dec; + std::cout<<controller.writeHWregister(rce,address, data)<<std::endl;; + break; + case 3: + unsigned addressr, datar; + std::cout<<"Address?"<<std::endl; + std::cin>>addressr; + std::cout<<controller.readHWregister(rce,addressr, datar)<<std::endl; + std::cout<<"Data "<<std::hex<<datar<<std::dec<<std::endl; + break; + case 4: + bs=new BitStream; + commands.L1A(bs); + serstat=controller.writeHWblockData(rce, *bs); + if(serstat!=0)std::cout<<"Send Error "<<serstat<<std::endl; + delete bs; + break; + case 5: + HD44780_reset(lcdp); + break; + case 6: + char bla[128]; + std::cout<<"Enter string to display."<<std::endl; + std::cin>>bla; + HD44780_putStr(lcdp, bla); + break; + case 7: + unsigned short st; + std::cout<<"Enter Value."<<std::endl; + std::cin>>std::hex>>st; + std::cout<<std::hex<<st<<std::dec<<std::endl; + controller.writeHWregister(rce, 31, st); + break; + } + } +} + +void encode8b10b(unsigned *patbuffer, int patlen, unsigned *encbuffer, int &enclen){ + unsigned enc5b6b[2][32]={{39,29,45,49,53,41,25,56,57,37,21,52,13,44,28,23,27,35,19,50,11,42,26,58,51,38,22,54,14,46,30,43}, + {24,34,18,49,10,41,25,7,6,37,21,52,13,44,28,40,36,35,19,50,11,42,26,5,12,38,22,9,14,17,33,20}}; + unsigned disp5b6b[32]={1,1,1,0,1,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,1,0,1,1,1}; + unsigned enc3b4b[2][8]={{11,9,5,12,13,10,6,14},{4,9,5,3,2,10,6,1}}; + unsigned disp3b4b[8]={1,0,0,0,1,0,0,1}; + enclen=patlen*10/8/4; + if((patlen*10)%32!=0){ + enclen++; + std::cout<<"WARNING: last word not fully utilized... contains zeroes"<<std::endl; + } + unsigned char *sbuffer; + sbuffer=(unsigned char*)patbuffer; + unsigned bitpos=0; + int disparity=0; //1 is 1, 0 is -1 + for (int i=0;i<patlen;i++){ + unsigned char word=(unsigned char)patbuffer[i]&0xff; + std::cout<<"Word "<<(unsigned)word<<std::endl; + if(patbuffer[i]&0x100){ //K symbol + unsigned kword=0; + if(word==252){ + if(disparity==0){ + kword=0xf8; + disparity=1; + } else { + kword=0x307; + disparity=0; + } + }else if(word==188){ + if(disparity==0){ + kword=0xfa; + disparity=1; + } else { + kword=0x305; + disparity=0; + } + }else if(word==60){ + if(disparity==0){ + kword=0xf9; + disparity=1; + } else { + kword=0x306; + disparity=0; + } + } + addBits(encbuffer,kword,10,bitpos); + bitpos+=10; + }else{ + unsigned word5b=word&0x1f; + unsigned encword5b=enc5b6b[disparity][word5b]; + addBits(encbuffer,encword5b,6,bitpos); + bitpos+=6; + disparity=disparity ^ disp5b6b[word5b]; + unsigned word3b=word>>5; + unsigned encword3b=enc3b4b[disparity][word3b]; + addBits(encbuffer,encword3b,4,bitpos); + bitpos+=4; + disparity=disparity ^ disp3b4b[word3b]; + } + } +} + + void addBits(unsigned *buffer, unsigned word, unsigned numbits, unsigned bitpos){ + unsigned current = bitpos/32; + unsigned bits=bitpos%32; + if (numbits>32-bits){ // Split over 2 words + int bitsleft=32-bits; + buffer[current]|=word>>(numbits-bitsleft); + buffer[current+1]|=word<<(32-(numbits-bitsleft)); + }else{ // bits fit into same word; + buffer[current]|=word<<(32-bits-numbits); + } +} + +unsigned decode(std::vector<unsigned char> inpvec){ + if(inpvec.size()==0)return FEI4::FEI4ARecord::Empty; + unsigned char* bytepointer=&inpvec[0]; + size_t size=inpvec.size(); + unsigned char* last=bytepointer+size-3; + FEI4::FEI4ARecord rec; + bool header=false; + while(bytepointer<=last){ + rec.setRecord(bytepointer); + // std::cout<<"Record "<<std::hex<<rec.getUnsigned()<<" "<<rec.getHeader()<<std::endl; + if(rec.isAddressRecord()){ // address record + std::cout<<"Address record for "; + if(rec.isGlobal())std::cout<<" global register "; + else std::cout<<" shift register "; + std::cout<<rec.getAddress()<<std::endl; + header=false; + }else if(rec.isValueRecord()){ //val rec without addr rec + printf("Value record: %04x\n",rec.getValue()); + header=false; + }else if(rec.isServiceRecord()){ + printf("Service record. Error code: %d. Count: %d \n",rec.getErrorCode(), rec.getErrorCount()); + header=false; + }else if(rec.isEmptyRecord()){ + // do nothing + std::cout<<"Empty record"<<std::endl; + header=false; + }else if(rec.isDataHeader()){ + std::cout<<"Data Header Lv1ID = "<<std::dec<<rec.getL1id()<<" BXID = "<<rec.getBxid()<<std::endl; + header=true; + }else if(rec.isData()){ + // std::cout<<std::hex<<rec.getHeader()<<std::endl; + std::cout<<"Data = "<<std::hex<<rec.getUnsigned()<<std::dec<<"Data Col = "<<std::dec<<rec.getColumn()<<" Row = "<<rec.getRow()<<" TotTop = "<<rec.getTotTop()<<" TotBottom = "<<rec.getTotBottom()<<std::endl; + }else{ + std::cout<<"Unexpected record type: "<<std::hex<<rec.getUnsigned()<<std::dec<<std::endl; + } + bytepointer+=3; + } + return FEI4::FEI4ARecord::OK; + } + +void HD44780_reset(const HD44780_t *device){ + i2c_write_reg(device, PCA9535_REG_CFG_0, 0); + usleep(1000); + i2c_write_reg(device, PCA9535_REG_CFG_1, 0); + usleep(1000); + + i2c_write_reg(device, PCA9535_REG_OUTPUT_0, 0xff); + usleep(1000); + i2c_write_reg(device, PCA9535_REG_OUTPUT_1, 0xff); + usleep(1000); + + i2c_write_reg(device, PCA9535_REG_POLINV_0, 0); + usleep(1000); + i2c_write_reg(device, PCA9535_REG_POLINV_1, 0); + usleep(1000); + + HD44780_WriteByte(device, HD44780_COMMAND, INIT_8_BIT, DEL_INIT_1); + usleep(1000); + HD44780_WriteByte(device, HD44780_COMMAND, INIT_8_BIT, DEL_INIT_2); + usleep(1000); + HD44780_WriteByte(device, HD44780_COMMAND, INIT_8_BIT, DEL_FUNCTIONSET); + HD44780_init(device, 2); +} +void +HD44780_WriteByte(const HD44780_t* device, const uint8_t reg, const uint8_t data, const uint32_t delayafter) +{ + // Don't assume that the pins are in any order + uint16_t toWrite = (( (data & (1<<0)) ? device->DB0 : 0 ) | + ( (data & (1<<1)) ? device->DB1 : 0 ) | + ( (data & (1<<2)) ? device->DB2 : 0 ) | + ( (data & (1<<3)) ? device->DB3 : 0 ) | + ( (data & (1<<4)) ? device->DB4 : 0 ) | + ( (data & (1<<5)) ? device->DB5 : 0 ) | + ( (data & (1<<6)) ? device->DB6 : 0 ) | + ( (data & (1<<7)) ? device->DB7 : 0 )); + if (reg == HD44780_DATA) toWrite |= device->RS; + HD44780_WriteDelay(device, toWrite, delayafter); +} +void HD44780_Command(const HD44780_t* device, const uint8_t command, const uint32_t delayafter) +{ + HD44780_WriteByte(device, HD44780_COMMAND, command, delayafter); +} +void +HD44780_Data(const HD44780_t* device, const uint8_t data) +{ + HD44780_WriteByte(device, HD44780_DATA, data, HD44780_MINDELAY); +} +void +HD44780_WriteByteDDRAM(const HD44780_t* device, const uint8_t data, const uint8_t address) +{ + // Write a byte at a specific DDRAM address + HD44780_Command(device, CMD_SETDDRAMADDR | (address & DDR_ADDRESSMASK), + DEL_SETDDRAMADDR); + HD44780_Data(device, data); +} +int HD44780_WriteDelay(const HD44780_t* device, const uint16_t data, const uint32_t delayAfter) +{ + int usec = HD44780_WriteSync(device, data, delayAfter); + usleep(usec); + return usec; +} +int +HD44780_WriteSync(const HD44780_t* device, const uint16_t data, const uint32_t delayAfter) +{ + uint16_t ldata = data; + HD44780_GpioWrite(device, ldata); + usleep(1000); + ldata |= device->EN; + std::cout<<"Towrite "<<std::hex<<ldata<<std::dec<<std::endl; + HD44780_GpioWrite(device, ldata); + // one microsecond synchronous delay simply to allow risetime + usleep(HD44780_EN_UP); + usleep(1000); + ldata &= ~(device->EN); + HD44780_GpioWrite(device, ldata); + usleep(1000); + return delayAfter > HD44780_MINDELAY ? delayAfter : HD44780_MINDELAY; +} + +void HD44780_GpioWrite(const HD44780_t* device, const uint16_t data) +{ + uint8_t tmp0 = data & 0xFF; + uint8_t tmp1 = (data >> 8) & 0xFF; + i2c_write_reg(device, PCA9535_REG_OUTPUT_0, tmp0); + i2c_write_reg(device, PCA9535_REG_OUTPUT_1, tmp1); +} + +int i2c_write_reg(const HD44780_t* device, uint8_t reg, uint8_t data){ + device->controller->writeHWregister(device->rce, 31, (reg<<8)|data); + return 0; +} + +void +HD44780_clear(const HD44780_t *device) +{ + HD44780_Command(device, CMD_CLEARDISPLAY, DEL_CLEARDISPLAY); +} + +void +HD44780_home(const HD44780_t *device) +{ + HD44780_Command(device, CMD_RETURNHOME, DEL_RETURNHOME); +} + +void +HD44780_putChar(const HD44780_t *device, const uint8_t data) +{ + HD44780_Data(device, data); +} + +void +HD44780_putCharAt(const HD44780_t *device, const uint8_t data, const uint8_t address) +{ + HD44780_WriteByteDDRAM(device, data, address); +} + +void +HD44780_putStr(const HD44780_t *device, const char* str) +{ + while (*str) HD44780_putChar(device, *str++); +} + +void +HD44780_putStrN(const HD44780_t *device, const char* str, const uint8_t length) +{ + uint8_t toWrite = length; + while (toWrite--) HD44780_putChar(device, *str++); +} + +void +HD44780_rotate(const HD44780_t* device, const uint8_t direction) +{ + HD44780_Command(device, CMD_CURSORDISPSHIFT | CDS_DISPLAYSHIFT | + ((direction) ? CDS_SHIFTLEFT : CDS_SHIFTRIGHT), + DEL_ROTATEDISPLAY); +} +// Public interface +void +HD44780_init(const HD44780_t *device, const uint8_t lines) +{ + HD44780_Command(device, (CMD_FUNCTIONSET | + FNS_DATAWIDTH8 + | FNS_FONT5X7 | + (lines == 0 ? FNS_DISPLAYLINES1 : FNS_DISPLAYLINES2)), + DEL_FUNCTIONSET); + // Turn the display off + HD44780_Command(device, CMD_DISPLAYCONTROL | DSC_DISPLAYOFF | DSC_CURSOROFF | DSC_BLINKOFF, + DEL_FUNCTIONSET); + // Set the entry mode to increment, noshift + HD44780_Command(device, CMD_ENTRYMODESET | EMS_INCREMENT | EMS_DISPLAYSHIFTOFF, + DEL_ENTRYMODESET); + // Turn on display, turn on cursor and turn off blinking cursor + HD44780_Command(device, CMD_DISPLAYCONTROL | DSC_DISPLAYON | DSC_CURSORON | DSC_BLINKOFF, + DEL_DISPLAYCONTROL); + HD44780_clear(device); +} + + diff --git a/rce/rcecalib/server/sendRandomPattern.cc b/rce/rcecalib/server/sendRandomPattern.cc new file mode 100644 index 00000000..6d1f0bc4 --- /dev/null +++ b/rce/rcecalib/server/sendRandomPattern.cc @@ -0,0 +1,60 @@ +#include <ipc/partition.h> +#include <ipc/core.h> +#include <ipc/server.h> +#include <ipc/object.h> + +#include "rcecalib/server/IPCController.hh" +#include "rcecalib/server/PixScan.hh" +#include "ScanOptions.hh" +#include "rcecalib/config/FEI4/FECommands.hh" +#include "rcecalib/config/FEI4/FEI4ARecord.hh" +#include "rcecalib/config/FEI4/FEI4AFormatter.hh" +#include "rcecalib/config/FormattedRecord.hh" +#include "rcecalib/server/FEI4AConfigFile.hh" + +#include <cmdl/cmdargs.h> +#include <iostream> +#include <stdio.h> +#include <stdlib.h> + + +int main( int argc, char ** argv ){ + + CmdArgStr partition_name ('p', "partition", "partition-name", "partition to work in."); + CmdArgInt rce_name ('r', "rce", "rce-name", "rce to talk to."); + +// +// Initialize command line parameters with default values +// + try { + IPCCore::init( argc, argv ); + } + catch( daq::ipc::Exception & ex ) { + ers::fatal( ex ); + return 1; + } + + CmdLine cmd(*argv, &partition_name, &rce_name, NULL); + CmdArgvIter arg_iter(--argc, ++argv); + +// +// Parse arguments +// + cmd.parse(arg_iter); + + IPCPartition p( (const char*)partition_name ); + IPCController controller(p); + int rce=(int)rce_name; + controller.removeAllRces(); + controller.addRce(rce); + assert(controller.writeHWregister(rce, 0,0xff)==0); //channel mask + std::vector<unsigned int> rep; + srand(0); + std::string a; + while(1){ + for(int i=0;i<2048;i++)rep.push_back((unsigned int)rand()); + controller.writeHWblockData(rce, rep); + rep.clear(); + //std::cin>>a; + } +} diff --git a/rce/rcecalib/server/tdccalib.cc b/rce/rcecalib/server/tdccalib.cc new file mode 100644 index 00000000..b7ae1ef8 --- /dev/null +++ b/rce/rcecalib/server/tdccalib.cc @@ -0,0 +1,209 @@ +#include <stdio.h> + +#include <ers/ers.h> + +#include <ipc/partition.h> +#include <ipc/server.h> +#include <ipc/object.h> +#include <ipc/alarm.h> +#include <ipc/core.h> + +#include <owl/timer.h> +#include <cmdl/cmdargs.h> +#include <unistd.h> + +#include "rcecalib/server/TurboDaqFile.hh" +#include "rcecalib/server/IPCController.hh" +#include "rcecalib/server/PixScan.hh" + +#include "IPCScanAdapter.hh" +#include "IPCConfigIFAdapter.hh" +#include "IPCFEI3Adapter.hh" +#include "ScanOptions.hh" +#include "PixelModuleConfig.hh" + +#include <TApplication.h> +#include <TROOT.h> +#include <TStyle.h> +#include <TCanvas.h> +#include <TH2F.h> +#include <TF1.h> +#include <TFile.h> +#include "rcecalib/server/Mean.hh" + +int acquireDataPoint(IPCController& controller, int rce); + +int main( int argc, char ** argv ) +{ + + TApplication *tapp; + CmdArgStr partition_name ('p', "partition", "partition-name", "partition to work in."); + +// +// Initialize command line parameters with default values +// + try { + IPCCore::init( argc, argv ); + } + catch( daq::ipc::Exception & ex ) { + ers::fatal( ex ); + return 1; + } + +// +// Declare command object and its argument-iterator +// + CmdLine cmd(*argv, &partition_name, NULL); + CmdArgvIter arg_iter(--argc, ++argv); + +// +// Parse arguments +// + cmd.parse(arg_iter); + + IPCPartition p( (const char*)partition_name ); + IPCController controller(p); + + tapp=new TApplication("bla", &argc, argv); + + gROOT->SetStyle("Plain"); + gStyle->SetOptStat(0); + gStyle->SetPalette(1); + gStyle->SetOptFit(111); + gStyle->SetErrorX(0); + + TH2F* occ2=new TH2F("tdc2","TDC Linearity",64,-.5,63.5,251,-.05,25.05); + //TCanvas *c2=new TCanvas("c2","Canvas",600,600); + //c2->Draw(); + //occ2->Draw(); + + unsigned serstat; + int rce=0; + serstat=controller.writeHWregister(rce, 3,1); //TDC calibration mode + assert(serstat==0); + std::cout<<"Part 1: Measurement of tap unit"<<std::endl; + Mean p2; + // Set Clock to 90 deg phase + serstat=controller.writeHWregister(rce, 2,1); + assert(serstat==0); + serstat=controller.writeHWregister(rce, 0x180,0); + assert(serstat==0); + serstat=controller.writeHWregister(rce, 0x190,0); + assert(serstat==0); + for (int i=0;i<100;i++){ + int bitpos=acquireDataPoint(controller, rce); + if(bitpos>-1)p2.accumulate((float)bitpos); + } + assert(p2.nEntries()>0); + std::cout<<"TDC at 90 deg is "<<p2.mean()<<" +- "<<p2.sigma()/(float)p2.nEntries()<<std::endl; + + Mean p0; + serstat=controller.writeHWregister(rce, 2,0); //0 deg + assert(serstat==0); + int index=0; + for (int i=500;i<800;i+=10){ + p0.clear(); + std::cout<<"Data point "<<i<<std::endl; + controller.writeHWregister(rce, 0x180,i); //set phase in DCM + controller.writeHWregister(rce, 0x190,0); // move DCM to new phase + for (int j=0;j<100;j++){ + int bitpos=acquireDataPoint(controller, rce); + if(bitpos>-1)p0.accumulate((float)bitpos); + } + if(p0.mean()>p2.mean()){ + index=i; + break; + } + } + assert(index>0); + int index2=index; + for (int i=index-9;i<index;i++){ + p0.clear(); + std::cout<<"Data point "<<i<<std::endl; + serstat=controller.writeHWregister(rce, 0x180,i); //set phase in DCM + assert(serstat==0); + serstat=controller.writeHWregister(rce, 0x190,0); // move DCM to new phase + assert(serstat==0); + for (int j=0;j<100;j++){ + int bitpos=acquireDataPoint(controller, rce); + if(bitpos>-1)p0.accumulate((float)bitpos); + } + if(p0.mean()>p2.mean()){ + index2=i-1; + break; + } + } + std::cout<<"Overlap at setting "<<index2<<std::endl; + float tunit=6400./(float)index2; + std::cout<<"1 tap delay is "<<tunit<<" ps."<<std::endl; + + int npoints=(int)(25000./tunit/10); + TH1F* occ=new TH1F("tdc","TDC Linearity",npoints+1,-5e-3*tunit,25.+5e-3*tunit ); + occ->GetXaxis()->SetTitle("Delay (ns)"); + occ->GetYaxis()->SetTitle("TDC value"); + occ->SetMaximum(70); + occ->SetMarkerStyle(20); + occ->SetMarkerSize(.5); + TCanvas *c1=new TCanvas("c1","Canvas",600,600); + c1->Draw(); + occ->Draw(); + + for (int k=0;k<npoints*10;k+=10){ + if(k%500==0)std::cout<<"Data point "<<k<<std::endl; + unsigned int phase=k/index2; // 6.4 ns clock divided by 9.8 ps tap delay + unsigned int setting=k%index2; + controller.writeHWregister(rce, 2,phase); + controller.writeHWregister(rce, 0x180,setting); //set phase in DCM + controller.writeHWregister(rce, 0x190,0); // move DCM to new phase + int nloops=100; + Mean mn; + for (int i=0;i<nloops;i++){ + int bitpos=acquireDataPoint(controller, rce); + if(bitpos>-1){ + mn.accumulate((float)bitpos); + occ2->Fill(bitpos,(float)tunit/1000.*k); + } + } + float mean=mn.mean(); + float sig=mn.sigma(); + occ->SetBinContent(k/10+1,mean); + if(sig<10)occ->SetBinError(k/10+1,sig); + occ->Draw("ep"); + c1->Update(); + //occ2->Draw(); + //c2->Update(); + usleep(100000); + } + occ->Fit("pol1"); + float fitpar=occ->GetFunction("pol1")->GetParameter(1); + // float fitparerr=occ->GetFunction("pol1")->GetParError(1); + float fact=1./fitpar; + std::cout<<"Fit result: "<<fact<<" nanoseconds per TDC count"<<std::endl; + serstat=controller.writeHWregister(rce, 3,0); //Return to normal mode + assert(serstat==0); + TFile *file=new TFile("histos.root","recreate"); + occ->Write(); + occ2->Write(); + file->Close(); + + tapp->Run(); + +} + +int acquireDataPoint(IPCController& controller, int rce){ + controller.writeHWregister(rce, 1,0); //start TDC measurement + unsigned counter1; + controller.readHWregister(rce, 0, counter1); + unsigned counter2; + controller.readHWregister(rce, 1, counter2); + unsigned long long counter=counter2; + counter=(counter<<32) | counter1; + int bitpos=-1; + for (int j=0;j<64;j++){ + if(((counter>>j)&1)==0){ + bitpos=j; + break; + } + } + return bitpos; +} diff --git a/rce/rcecalib/server/test_client.cc b/rce/rcecalib/server/test_client.cc new file mode 100644 index 00000000..4765c14b --- /dev/null +++ b/rce/rcecalib/server/test_client.cc @@ -0,0 +1,756 @@ +// +// test-client.cc +// +// test application for IPC library +// +// Sergei Kolos January 2000 +// +// description: +// Shows how to access remote objects and call their methods +// Performs timing for the lookup and remote methods invocations +///////////////////////////////////////////////////////////////////////////////// +#include <stdio.h> + +#include <ers/ers.h> + +#include <ipc/partition.h> +#include <ipc/server.h> +#include <ipc/object.h> +#include <ipc/alarm.h> +#include <ipc/core.h> + +#include <owl/timer.h> +#include <cmdl/cmdargs.h> +#include <unistd.h> + + +#include "IPCScanAdapter.hh" +#include "IPCConfigIFAdapter.hh" +#include "IPCFEI3Adapter.hh" +#include "ScanOptions.hh" + +using namespace std; + +static bool echo = true; +static int iter=1; +static int delay=0; +static int asynch=1; +static int synch=0; +static const char *object_name="scanCtrl"; + +static int s_error_num; +static int a_error_num; + +static void s_error(CORBA::Exception & ex) +{ + s_error_num++; + std::cerr << "ERROR [synch_ping] exception " << ex._name() << std::endl; +} + +static void a_error(CORBA::Exception & ex) +{ + a_error_num++; + std::cerr << "ERROR [asynch_ping] exception " << ex._name() << std::endl; +} + + +static void +TestIterators( IPCPartition p ) +{ + std::map< std::string, ipc::IPCScanAdapter_var > scanobjects; + std::map< std::string, ipc::IPCConfigIFAdapter_var > confobjects; + std::map< std::string, ipc::IPCFEI3Adapter_var > modobjects; + + + OWLTimer time; + + time.start(); + try { + p.getObjects<ipc::IPCScanAdapter>( scanobjects ); + p.getObjects<ipc::IPCConfigIFAdapter>( confobjects ); + p.getObjects<ipc::IPCFEI3Adapter>( modobjects ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + time.stop(); + + if ( echo ) + { + std::cout << "There are " << confobjects.size() << " objects of type \"ipc::IPCConfigIFAdapter\" registered with the \"" + << p.name() << "\" partition" << std::endl; + std::cout << "There are " << scanobjects.size() << " objects of type \"ipc::IPCScanAdapter\" registered with the \"" + << p.name() << "\" partition" << std::endl; + std::cout << "There are " << modobjects.size() << " objects of type \"ipc::IPCFEI3Adapter\" registered with the \"" + << p.name() << "\" partition" << std::endl; + std::cout << "getObjects operation took (in seconds): " << std::endl + << "\t" << time.userTime() << "(user time)" << std::endl + << "\t" << time.systemTime() << "(system time)" << std::endl + << "\t" << time.totalTime() << "(total time)" << std::endl; + } + + std::map< std::string, ipc::IPCScanAdapter_var >::iterator scanit; + std::map< std::string, ipc::IPCConfigIFAdapter_var >::iterator confit; + std::map< std::string, ipc::IPCFEI3Adapter_var >::iterator modit; + + if ( echo ) + std::cout << "Objects are:" << std::endl; + for ( scanit = scanobjects.begin(); scanit != scanobjects.end(); scanit++ ) + { + if ( echo ) + std::cout << "\"" << (*scanit).first << "\"" << std::endl; + } + for ( confit = confobjects.begin(); confit != confobjects.end(); confit++ ) + { + if ( echo ) + std::cout << "\"" << (*confit).first << "\"" << std::endl; + } + for ( modit = modobjects.begin(); modit != modobjects.end(); modit++ ) + { + if ( echo ) + std::cout << "\"" << (*modit).first << "\"" << std::endl; + } +} + + +static void TestLookupMethod( IPCPartition p ) +{ + char oname[32]; + int i; + OWLTimer time; + + time.start(); + for ( i = 0; i < 1 ; i++ ) + { + sprintf( oname, "scanCtrl", i ); + try { + ipc::IPCScanAdapter_var handle = p.lookup<ipc::IPCScanAdapter>( oname ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + } + time.stop(); + if ( echo ) + { + std::cout << "object resolution (first time) takes (in seconds): " << std::endl + << "\t" << time.userTime() << "(user time)" << std::endl + << "\t" << time.systemTime() << "(system time)" << std::endl + << "\t" << time.totalTime() << "(total time)" << std::endl; + } + + time.reset(); + time.start(); + for ( i = 0; i < 1 ; i++ ) + { + sprintf( oname, "scanCtrl", i ); + try { + ipc::IPCScanAdapter_var handle = p.lookup<ipc::IPCScanAdapter>( oname ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + } + time.stop(); + if ( echo ) + { + std::cout << "object resolution (second time) takes (in seconds): " << std::endl + << "\t" << time.userTime() << "(user time)" << std::endl + << "\t" << time.systemTime() << "(system time)" << std::endl + << "\t" << time.totalTime() << "(total time)" << std::endl; + } +} + +static void TestResolve( IPCPartition p ) +{ + char oname[32] = "scanCtrl"; + int i; + OWLTimer time; + + time.start(); + for ( i = 0; i < iter; i++ ) + { + try { + ipc::IPCScanAdapter_var handle = p.lookup<ipc::IPCScanAdapter,ipc::no_cache,ipc::narrow>( oname ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + } + time.stop(); + if ( echo ) + { + std::cout << "object resolution takes (in seconds): " << std::endl + << "\t" << time.userTime()/iter << "(user time)" << std::endl + << "\t" << time.systemTime()/iter << "(system time)" << std::endl + << "\t" << time.totalTime()/iter << "(total time)" << std::endl; + } +} + +static void TestIsObjectValid( IPCPartition p ) +{ + char oname[32]; + int i; + + for ( i = 0; i < iter ; i++ ) + { + if ( echo ) + std::cout << " p.isValid( ) = " << p.isValid( ) << std::endl; + } + + sprintf( oname, "scanCtrl" ); + for ( i = 0; i < iter ; i++ ) + { + try { + bool v = p.isObjectValid<ipc::IPCScanAdapter>( oname ); + if ( echo ) + std::cout << " p.isObjectValid( ) = " << v << std::endl; + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + } + + for ( i = 0; i < 1 ; i++ ) + { + sprintf( oname, "scanCtrl", i ); + try { + bool v = p.isObjectValid<ipc::IPCScanAdapter>( oname ); + if ( echo ) + std::cout << " p.isObjectValid( ) = " << v << std::endl; + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + } + +} + +static void TestRemoteInvocation( IPCPartition p ) +{ + char line[2]; + int i; + + memset( line, 55, 1 ); + line[1] = 0; + + OWLTimer time; + + ipc::ScanOptions options; + char* pointer=(char*)&options; + for (int i=0;i<sizeof(ipc::ScanOptions);i++){ + *pointer++=0; + } + options.nMaskStages=5; + if ( !synch ) + { + if ( echo ) + { + std::cout << "Asynchronous method test ..." << std::endl; + } + + time.start(); + + for ( i = 0; i < 1; i++ ) + { + sleep( delay ); + ipc::IPCScanAdapter_var handle; + try { + // std::clog << "calling lookup ... {" << std::endl; + handle = p.lookup<ipc::IPCScanAdapter>( (const char*)object_name ); + //std::clog << "} done" << std::endl; + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + continue; + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + continue; + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + continue; + } + + try + { + //std::clog << "calling ping_a function ... {" << std::endl; + handle -> IPCabort( ); + //handle -> IPCconfigureScan( "Regular", options ); + handle -> IPCpause( ); + //std::clog << "} done" << std::endl; + + } + catch(CORBA::Exception & ex) + { + a_error( ex ); + } + } + time.stop(); + + if ( echo ) + { + std::cout << "passing 1024 bytes (asynchronously) takes (in seconds): " << std::endl + << "\t" << time.userTime()/iter << "(user time)" << std::endl + << "\t" << time.systemTime()/iter << "(system time)" << std::endl + << "\t" << time.totalTime()/iter << "(total time)" << std::endl; + } + } + + if ( !asynch ) + { + if ( echo ) + { + std::cout << "Synchronous method test ..." << std::endl; + } + + time.reset(); + time.start(); // Record starting time + + for ( i = 0; i < iter; i++ ) + { + sleep( delay ); + ipc::IPCScanAdapter_var handle; + try { + std::clog << "calling lookup ... {" << std::endl; + handle = p.lookup<ipc::IPCScanAdapter>( (const char*)object_name ); + std::clog << "} done" << std::endl; + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + continue; + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + continue; + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + continue; + } + + try + { + std::clog << "calling ping_s function ... {" << std::endl; + handle -> IPCresume( ); + std::clog << "} done" << std::endl; + } + catch(CORBA::Exception & ex) + { + s_error( ex ); + } + } + time.stop(); + if ( echo ) + { + std::cout << "passing 1024 bytes (synchronously) takes (in seconds): " << std::endl + << "\t" << time.userTime()/iter << "(user time)" << std::endl + << "\t" << time.systemTime()/iter << "(system time)" << std::endl + << "\t" << time.totalTime()/iter << "(total time)" << std::endl; + } + } +} + +static void TestExceptions( IPCPartition p ) +{ + char line[1025]; + int i; + + memset( line, 55, 1024 ); + line[1024] = 0; + + for ( i = 0; i < iter; i++ ) + { + ipc::IPCScanAdapter_var handle; + try { + handle = p.lookup<ipc::IPCScanAdapter>( (const char*)object_name ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + break; + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + break; + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + break; + } + + try + { + handle -> IPCabort( ); + } + catch(CORBA::SystemException & ex) + { + std::cerr << std::endl << "ERROR [ipc_IPCScanAdapter_client::TestExceptions] system exception " << ex._name() << std::endl; + } + } +} +/* +class IPCCallback : public IPCServer, + public IPCObject<POA_ipc::callback> +{ + public: + void notify( const char * name ) + { + std::cout << "Callback from employee \"" << name << "\" received" << std::endl; + } + + ~IPCCallback() + { + std::cout << "IPCCallback destructor is called" << std::endl; + } +}; + + +bool stop_test( void * param ) +{ + IPCCallback * cb = static_cast<IPCCallback*>( param ); + cb->stop(); + return false; +} + +void TestCallbacks( IPCPartition p ) +{ + IPCCallback * cb = new IPCCallback; + + std::map< std::string, ipc::person_var > persons; + try { + p.getObjects<ipc::person>( persons ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + + std::map< std::string, ipc::person_var >::iterator pit; + + std::cout << "Persons are:" << std::endl; + + for ( pit = persons.begin(); pit != persons.end(); pit++ ) + { + std::cout << "\"" << (*pit).first << "\"" << std::endl; + } + + std::map< std::string, ipc::employee_var > employees; + try { + p.getObjects<ipc::employee>( employees ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + + std::map< std::string, ipc::employee_var >::iterator eit; + + std::cout << "Employees are:" << std::endl; + + for ( eit = employees.begin(); eit != employees.end(); eit++ ) + { + std::cout << "\"" << (*eit).first << "\"" << std::endl; + (*eit).second->subscribe( cb->_this(), 1 ); + } + + IPCAlarm * alarm = new IPCAlarm( 10, 0, stop_test, cb ); + + cb->run(); + + delete alarm; + cb->_destroy(); + std::cout << "Callbacks test completed." << std::endl; +} +*/ +static void TestCache( IPCPartition p ) +{ + char line[2]; + int i; + + memset( line, 55, 1 ); + line[2] = 0; + + if ( echo ) + { + std::cout << "Cache test ..." << std::endl; + } + + ipc::IPCScanAdapter_var handle1; + ipc::IPCScanAdapter_var handle2; + try { + std::clog << "calling lookup for handle 1 ... {" << std::endl; + handle1 = p.lookup<ipc::IPCScanAdapter>( (const char*)object_name ); + std::clog << "} done" << std::endl; + + std::clog << "calling lookup for handle 2 ... {" << std::endl; + handle2 = p.lookup<ipc::IPCScanAdapter>( (const char*)object_name ); + std::clog << "} done" << std::endl; + } + catch( daq::ipc::Exception & ex ) { + ers::error( ex ); + return; + } + + for ( i = 0; i < iter; i++ ) + { + try + { + sleep( delay ); + std::clog << "calling ping_s function using handle 1 ... {" << std::endl; + handle1 -> IPCpause( ); + std::clog << "} done" << std::endl; + + sleep( delay ); + std::clog << "calling ping_s function using handle 2 ... {" << std::endl; + handle2 -> IPCresume( ); + std::clog << "} done" << std::endl; + } + catch(CORBA::Exception & ex) + { + s_error( ex ); + } + + try + { + sleep( delay ); + std::clog << "calling lookup for local handle ... {" << std::endl; + ipc::IPCScanAdapter_var handle = p.lookup<ipc::IPCScanAdapter>( (const char*)object_name ); + std::clog << "} done" << std::endl; + + sleep( delay ); + std::clog << "calling ping_s function using local handle ... {" << std::endl; + handle -> IPCpause( ); + std::clog << "} done" << std::endl; + } + catch(CORBA::Exception & ex) + { + s_error( ex ); + } + catch( daq::ipc::Exception & ex ) { + ers::error( ex ); + return; + } + } + + std::cout << "Cache test completed." << std::endl; +} + +static void TestPerformance( IPCPartition p, size_t size ) +{ + char * line = new char[size]; + + memset( line, 55, size ); + line[size-1] = 0; + + double total_time = 0; + double user_time = 0; + double system_time = 0; + if ( !synch ) + { + if ( echo ) + { + std::cout << "Asynchronous method test ..." << std::endl; + } + + for ( int i = 0; i < iter; i++ ) + { + if ( delay) usleep( delay ); + ipc::IPCScanAdapter_var handle; + try { + handle = p.lookup<ipc::IPCScanAdapter>( (const char*)object_name ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + continue; + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + continue; + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + continue; + } + + try + { + OWLTimer one_time; + one_time.start(); + handle -> IPCpause( ); + one_time.stop(); + std::cout << one_time.totalTime()*1000 << std::endl; + total_time += one_time.totalTime(); + user_time += one_time.userTime(); + system_time += one_time.systemTime(); + } + catch(CORBA::Exception & ex) + { + a_error( ex ); + } + } + + if ( echo ) + { + std::cout << "passing " << size << " bytes (asynchronously) takes (in milliseconds): " << std::endl + << "\t" << user_time/iter*1000 << "(user time)" << std::endl + << "\t" << system_time/iter*1000 << "(system time)" << std::endl + << "\t" << total_time/iter*1000 << "(total time)" << std::endl; + } + } + + total_time = 0; + user_time = 0; + system_time = 0; + if ( !asynch ) + { + if ( echo ) + { + std::cout << "Synchronous method test ..." << std::endl; + } + + for ( int i = 0; i < iter; i++ ) + { + if ( delay) usleep( delay ); + ipc::IPCScanAdapter_var handle; + try { + handle = p.lookup<ipc::IPCScanAdapter>( (const char*)object_name ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + continue; + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + continue; + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + continue; + } + + try + { + OWLTimer one_time; + one_time.start(); + handle -> IPCpause( ); + one_time.stop(); + std::cout << one_time.totalTime()*1000 << std::endl; + total_time += one_time.totalTime(); + user_time += one_time.userTime(); + system_time += one_time.systemTime(); + } + catch(CORBA::Exception & ex) + { + s_error( ex ); + } + } + + if ( echo ) + { + std::cout << "passing " << size << " bytes (asynchronously) takes (in milliseconds): " << std::endl + << "\t" << user_time/iter*1000 << "(user time)" << std::endl + << "\t" << system_time/iter*1000 << "(system time)" << std::endl + << "\t" << total_time/iter*1000 << "(total time)" << std::endl; + } + } + + delete line; +} + +int main( int argc, char ** argv ) +{ + + CmdArgStr partition_name ('p', "partition", "partition-name", "partition to work in."); + CmdArgInt length ('l', "length", "data-length", "size of data for timing test (1024 by default)."); + +// +// Initialize command line parameters with default values +// + + try { + IPCCore::init( argc, argv ); + } + catch( daq::ipc::Exception & ex ) { + ers::fatal( ex ); + return 1; + } + +// +// Declare command object and its argument-iterator +// + CmdLine cmd(*argv, &partition_name, NULL); + CmdArgvIter arg_iter(--argc, ++argv); + +// +// Parse arguments +// + cmd.parse(arg_iter); + + IPCPartition p( (const char*)partition_name ); + + std::cout<<"***********TestIterators"<<std::endl; + TestIterators(p); + std::cout<<"***********TestLookupMethod"<<std::endl; + TestLookupMethod(p); + std::cout<<"***********TestIsObjectValid"<<std::endl; + TestIsObjectValid(p); + std::cout<<"***********TestRemoteInvocation"<<std::endl; + TestRemoteInvocation(p); + //TestExceptions(p); + // TestCallbacks(p); + // TestCache(p); + //TestPerformance( p, length ); + //TestResolve(p); + + return 0; + + std::cout << "# of failed methods invocations: " << std::endl + << "\tasynchronous - " << a_error_num << std::endl + << "\tsynchronous - " << s_error_num << std::endl; + + ipc::IPCScanAdapter_var handle; + try { + handle = p.lookup<ipc::IPCScanAdapter>( (const char*)object_name ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + return 1; + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + return 1; + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + return 1; + } + + try + { + handle -> shutdown( ); + } + catch(CORBA::SystemException & ex) + { + std::cerr << "ERROR [ipc_test_client::main] Call to method shutdown failed " << ex._name() << std::endl; + return 1; + } + + return 0; +} diff --git a/rce/rcecalib/server/test_scan_client.cc b/rce/rcecalib/server/test_scan_client.cc new file mode 100644 index 00000000..e477dadf --- /dev/null +++ b/rce/rcecalib/server/test_scan_client.cc @@ -0,0 +1,244 @@ +// +// test-client.cc +// +// test application for IPC library +// +// Sergei Kolos January 2000 +// +// description: +// Shows how to access remote objects and call their methods +// Performs timing for the lookup and remote methods invocations +///////////////////////////////////////////////////////////////////////////////// +#include <stdio.h> + +#include <ers/ers.h> + +#include <ipc/partition.h> +#include <ipc/server.h> +#include <ipc/object.h> +#include <ipc/alarm.h> +#include <ipc/core.h> + +#include <owl/timer.h> +#include <cmdl/cmdargs.h> +#include <unistd.h> + + +#include "IPCScanAdapter.hh" +#include "IPCConfigIFAdapter.hh" +#include "IPCFEI3Adapter.hh" +#include "ScanOptions.hh" +#include "IPCScanAdapter.hh" +#include "IPCScanRootAdapter.hh" + +using namespace std; + + + +int main( int argc, char ** argv ) +{ + + CmdArgStr partition_name ('p', "partition", "partition-name", "partition to work in."); + + +// +// Initialize command line parameters with default values +// + + try { + IPCCore::init( argc, argv ); + } + catch( daq::ipc::Exception & ex ) { + ers::fatal( ex ); + return 1; + } + +// +// Declare command object and its argument-iterator +// + CmdLine cmd(*argv, &partition_name, NULL); + CmdArgvIter arg_iter(--argc, ++argv); + +// +// Parse arguments +// + cmd.parse(arg_iter); + + IPCPartition m_partition( (const char*)partition_name ); + + // write scan config + + ipc::ScanOptions m_scanPar; + ipc::PixelModuleConfig cfg; + char* pointer=(char*)&m_scanPar; + for (int i=0;i<sizeof(ipc::ScanOptions);i++){ + *pointer++=0; + } + pointer=(char *)&cfg; + for (int i=0;i<sizeof(ipc::PixelModuleConfig);i++){ + *pointer++=0; + } + // send minimal module configuration + + // some random vcal gradients for one FEC + cfg.FEConfig[0].FECalib.cinjLo=8.; + cfg.FEConfig[0].FECalib.cinjHi=40; + cfg.FEConfig[0].FECalib.vcalCoeff[0]=0.; + cfg.FEConfig[0].FECalib.vcalCoeff[1]=0.003; + cfg.FEConfig[0].FECalib.vcalCoeff[2]=0.000006; + cfg.FEConfig[0].FECalib.vcalCoeff[3]=0.000000043; + + // integer scaled version for FE calib + cfg.FEConfig[0].FECalibInt.cinjLo=8; + cfg.FEConfig[0].FECalibInt.cinjHi=40; + cfg.FEConfig[0].FECalibInt.vcalCoeff[0]=3; + cfg.FEConfig[0].FECalibInt.vcalCoeff[1]=5; + cfg.FEConfig[0].FECalibInt.vcalCoeff[2]=6; + cfg.FEConfig[0].FECalibInt.vcalCoeff[3]=43; + + ipc::IPCConfigIFAdapter_var moduleHandle; + try { + moduleHandle = m_partition.lookup<ipc::IPCConfigIFAdapter>( "configIF" ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + ipc::ModSetup s; + s.id=42; + s.link=0; + + moduleHandle->IPCdeleteModules(); + std::cout<<"before setupmodules"<<std::endl; + int ret=moduleHandle -> IPCsetupModule( "module","IPC_FEI3_multiThread",s ); + + /* set up trigger method */ + std::cout<<"before createtrg"<<std::endl; + ret=moduleHandle->IPCsetupTriggerIF("EventFromDsp"); + if(ret)std::cout<<"***ERROR*** IPCsetupTrigger failed"<<std::endl; + std::cout<<"after createtrg"<<std::endl; + + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + ipc::IPCFEI3Adapter_var modhandle; + try { + bool v=m_partition.isObjectValid<ipc::IPCFEI3Adapter>("module"); + //if(v)std::cout<<"Valid"<<std::endl; + if(!v) std::cout<<"Not valid"<<std::endl; + modhandle = m_partition.lookup<ipc::IPCFEI3Adapter>( "module" ); + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + + try { + modhandle -> IPCdownloadConfig( cfg ); + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + + // zero everything - very important to avoid MARSHALL exception + pointer=(char*)&m_scanPar; + for (int i=0;i<sizeof(ipc::ScanOptions);i++){ + *pointer++=0; + } + // Simple receiver + m_scanPar.receiver=CORBA::string_dup("Simple"); + m_scanPar.parser=CORBA::string_dup("Simple"); + /* define data processor */ + + m_scanPar.histOpt[ipc::IPC_SCAN_OCCUPANCY].optionMask = 1; + m_scanPar.nLoops++; + m_scanPar.scanLoop[0].endofLoopAction.Action = ipc::IPC_SCAN_FIT; + m_scanPar.scanLoop[0].endofLoopAction.fitFunction =ipc::IPC_SCAN_SCURVE; + /* needs to be defined for Parser Object */ + m_scanPar.trigOpt.nL1AperEvent=16; + + /* ScanLoop needs at least these defined */ + m_scanPar.scanLoop[0].nPoints = 101; + m_scanPar.trigOpt.nEvents=100; + m_scanPar.nMaskStages=3; + m_scanPar.scanLoop[0].dataPoints.length(m_scanPar.scanLoop[0].nPoints); + m_scanPar.scanLoop[0].scanParameter=ipc::IPC_SCAN_VCAL; + // m_scanPar.triggerMode=ipc::IPC_SCAN_USE_CLOW; + + for(unsigned int k=0;k<m_scanPar.scanLoop[0].nPoints;k++) + m_scanPar.scanLoop[0].dataPoints[k]=k*2; // default Vcal scaling of 2 + + ipc::IPCScanRootAdapter_var scanRootHandle; + try { + std::cerr << "calling lookup ... {" << std::endl; + scanRootHandle = m_partition.lookup<ipc::IPCScanRootAdapter>( "scanRoot" ); + std::cerr << "} done" << std::endl; + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + + + + try { + std::clog << "Calling configure scan function ... {" << std::endl; + scanRootHandle -> IPCconfigureScan("Regular", m_scanPar ); + //handle->shutdown(); + std::clog << "} done" << std::endl; + + } + + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name() <<std::endl; + } + + // finally start the scan + + ipc::IPCScanAdapter_var handleScanAdapter; + try { + std::cerr << "calling lookup ... {" << std::endl; + handleScanAdapter = m_partition.lookup<ipc::IPCScanAdapter>( "scanCtrl" ); + std::cerr << "} done" << std::endl; + } + catch( daq::ipc::InvalidPartition & ex ) { + ers::error( ex ); + } + catch( daq::ipc::ObjectNotFound & ex ) { + ers::error( ex ); + } + catch( daq::ipc::InvalidObjectName & ex ) { + ers::error( ex ); + } + try { + std::clog << "calling startScan function ... {" << std::endl; + handleScanAdapter -> IPCstartScan( ); + std::clog << "} done" << std::endl; + } + catch(CORBA::Exception & ex) { + std::cerr<<"Corba exception "<<ex._name()<<std::endl; + } + + + + + return 0; + +} diff --git a/rce/rcecalib/server/test_server.cc b/rce/rcecalib/server/test_server.cc new file mode 100644 index 00000000..4b5dec6c --- /dev/null +++ b/rce/rcecalib/server/test_server.cc @@ -0,0 +1,113 @@ +// +// test-server.cc +// +// test application for IPC library +// +// Sergei Kolos January 2000 +// +// description: +// Implements test.accessible interface +// Creates several implementation objects +// Performs timing for the publish and withdraw operations +///////////////////////////////////////////////////////////////////////////////// +#include <stdio.h> +#include <signal.h> +#include <unistd.h> + +#include <ers/ers.h> + +#include <ipc/object.h> +#include <ipc/alarm.h> +#include <ipc/core.h> + +#include <owl/timer.h> +#include <owl/semaphore.h> +#include <cmdl/cmdargs.h> + +#include "rcecalib/scanctrl/IPCScan.cc" +#include "rcecalib/scanctrl/IPCScanRoot.cc" +#include "rcecalib/config/IPCConfigIF.cc" +#include "rcecalib/HW/SerialHexdump.hh" +#include "rcecalib/config/IPCModuleFactory.hh" +#include "rcecalib/util/RceName.hh" +#include "rcecalib/scanctrl/Scan.hh" +OWLSemaphore semaphore; + +CmdArgBool echo ('e', "echo", "output results to stdout."); + +void sig_handler( int sig ) +{ + std::cout << " :: [IPCServer::sigint_handler] the signal " << sig << " received - exiting ... "<<std::endl; + semaphore.post(); +} + + +////////////////////////////////////////// +// +// Main function +// +////////////////////////////////////////// + + +int main ( int argc, char ** argv ) +{ + CmdArgStr partition_name ('p', "partition", "partition-name", "partition to work."); + + try { + IPCCore::init( argc, argv ); + } + catch( daq::ipc::Exception & ex ) { + ers::fatal( ex ); + return 1; + } + + // Declare command object and its argument-iterator + CmdLine cmd(*argv, &partition_name, &echo, NULL); + CmdArgvIter arg_iter(--argc, ++argv); + + // Parse arguments + + cmd.parse(arg_iter); + + signal( SIGINT , sig_handler ); + signal( SIGTERM, sig_handler ); + + + IPCPartition p((const char*)partition_name); + + //Serial IF + new SerialHexdump; + + //Module Factory + + ModuleFactory *moduleFactory=new IPCModuleFactory(p); + + char name[128]; + sprintf(name, "configIF_RCE%d", RceName::getRceNumber()); + // Config IF + IPCConfigIF<ipc::single_thread> *cif=new IPCConfigIF<ipc::single_thread>(p, name, moduleFactory); + + sprintf(name, "scanCtrl_RCE%d", RceName::getRceNumber()); + IPCScan<ipc::multi_thread> *scan = new IPCScan<ipc::multi_thread>( p, name); + sprintf(name, "scanRoot_RCE%d", RceName::getRceNumber()); + IPCScanRoot<ipc::single_thread> * scanroot = new IPCScanRoot<ipc::single_thread>( p, name, (ConfigIF*)cif, (Scan*)scan); + + sprintf(name, "RCE%d", RceName::getRceNumber()); + new IPCHistoManager(p,"RceIsServer", name); + // + std::cout << "ipc_test_server has been started." << std::endl; + + semaphore.wait(); + std::cout << "Shutdown." << std::endl; + + cif->_destroy(); + scanroot->_destroy(); + scan->_destroy(); + + if ( echo ) + { + std::cout << "Test successfully completed." << std::endl; + } + + return 0; +} diff --git a/rce/rcecalib/util/AbsRceHisto.cc b/rce/rcecalib/util/AbsRceHisto.cc new file mode 100644 index 00000000..9d91c09d --- /dev/null +++ b/rce/rcecalib/util/AbsRceHisto.cc @@ -0,0 +1,24 @@ +#include "rcecalib/util/AbsRceHisto.hh" +#include "rcecalib/util/IPCHistoManager.hh" +#include "oh/OHRawProvider.h" + +AbsRceHisto::AbsRceHisto(const char* name, const char* title, int ndim):m_ndim(ndim), m_name(name), m_title(title){ + IPCHistoManager* mgr=IPCHistoManager::instance(); + assert(mgr!=0); + mgr->addToInventory(this); +} +AbsRceHisto::~AbsRceHisto(){ + IPCHistoManager* mgr=IPCHistoManager::instance(); + assert(mgr!=0); + mgr->removeFromInventory(this); +} + +void AbsRceHisto::setAxisTitle(int axis, const char* title){ + if(axis>1)return; + m_axisTitle[axis]=title; +} +const char* AbsRceHisto::axisTitle(int axis){ + if(axis>1)return 0; + return m_axisTitle[axis].c_str(); +} + diff --git a/rce/rcecalib/util/AbsRceHisto.hh b/rce/rcecalib/util/AbsRceHisto.hh new file mode 100644 index 00000000..d9ab9b3c --- /dev/null +++ b/rce/rcecalib/util/AbsRceHisto.hh @@ -0,0 +1,31 @@ +#ifndef ABS_RCE_HISTO_HH +#define ABS_RCE_HISTO_HH +#include "oh/OHRawProvider.h" + + +class AbsRceHisto{ +public: + AbsRceHisto(const char* name, const char* title, int ndim); + virtual ~AbsRceHisto(); + std::string name() const {return m_name;} + std::string title() const { return m_title; }; + int nDim() const { return m_ndim; }; + virtual int nBin(int d) const { if (d >=0 && d <= 1) return m_dim[d]; else return 0; }; + float min(int d) const { if (d >=0 && d <= 1) return m_lim[d][0]; else return 0; }; + float max(int d) const { if (d >=0 && d <= 1) return m_lim[d][1]; else return 0; }; + void setAxisTitle(int axis, const char* title); + const char* axisTitle(int axis); + //retrieve histograms + virtual void publish(OHRawProvider<>*)=0; +protected: + int m_ndim; //! Number of dimensions (1 or 2) + std::string m_name; //! Histogram name + std::string m_title; //! Histogram title + std::string m_axisTitle[2]; //! Axis titles + unsigned int m_dim[2]; //! Dimensions + float m_lim[2][2]; //! Limits + float m_quot[2]; + float m_const[2]; +}; + +#endif diff --git a/rce/rcecalib/util/DataCond.hh b/rce/rcecalib/util/DataCond.hh new file mode 100644 index 00000000..c6d92387 --- /dev/null +++ b/rce/rcecalib/util/DataCond.hh @@ -0,0 +1,14 @@ +#ifndef DATACOND_HH +#define DATACOND_HH + +#include <omnithread.h> + +class DataCond{ +public: + DataCond(): cond(&mutex), waitingForData(false){} + omni_mutex mutex ; + omni_condition cond ; + bool waitingForData; +}; + +#endif diff --git a/rce/rcecalib/util/IPCHistoManager.cc b/rce/rcecalib/util/IPCHistoManager.cc new file mode 100644 index 00000000..5459f3f2 --- /dev/null +++ b/rce/rcecalib/util/IPCHistoManager.cc @@ -0,0 +1,70 @@ + +#include "rcecalib/util/IPCHistoManager.hh" +#include "ipc/partition.h" +#include "rcecalib/util/AbsRceHisto.hh" +#include "IPCScanRootAdapter.hh" +#include "oh/OHRawProvider.h" + + +#include <boost/regex.hpp> + +IPCHistoManager* IPCHistoManager::m_manager=0; + +IPCHistoManager::IPCHistoManager(IPCPartition& p, const char* servername, const char* providername){ + m_provider=new OHRawProvider<>(p, servername, providername, 0); + m_manager=this; +} +IPCHistoManager::~IPCHistoManager(){ + delete m_provider; + m_manager=0; +} +void IPCHistoManager::addToInventory(AbsRceHisto* histo){ + std::string name=histo->name(); + if(m_inventory.find(name)!=m_inventory.end()){ + std::cout<<"Histogram with name "<<name<<" exists already. Replacing..."<<std::endl; + } + m_inventory[name]=histo; +} +void IPCHistoManager::removeFromInventory(AbsRceHisto* histo){ + std::map<std::string, AbsRceHisto*>::iterator it; + it=m_inventory.find(histo->name()); + if(it==m_inventory.end()){ + std::cout<<"Histogram with name "<<histo->name()<<" was not in repository."<<std::endl; + }else{ + m_inventory.erase(it); + } + std::map<std::string, AbsRceHisto*>::iterator it2=m_published.find(histo->name()); + if(it2!=m_published.end()){ + m_published.erase(it2); + } +} + +void IPCHistoManager::publish(const char* rege){ + boost::regex re(rege); + std::map<std::string,AbsRceHisto*>::iterator it; + for(it=m_inventory.begin();it!=m_inventory.end();it++){ + if(boost::regex_match((*it).first,re)){ + (*it).second->publish(m_provider); + m_published[(*it).first]=(*it).second; + } + } +} +std::vector<std::string> IPCHistoManager::getHistoNames(const char *rege){ + std::vector<std::string> retvec; + boost::regex re(rege); + std::map<std::string,AbsRceHisto*>::iterator it; + for(it=m_inventory.begin();it!=m_inventory.end();it++){ + if(boost::regex_match((*it).first,re)){ + retvec.push_back((*it).first); + } + } + return retvec; +} +std::vector<std::string> IPCHistoManager::getPublishedHistoNames(){ + std::vector<std::string> retvec; + std::map<std::string,AbsRceHisto*>::iterator it; + for(it=m_published.begin();it!=m_published.end();it++){ + retvec.push_back((*it).first); + } + return retvec; +} diff --git a/rce/rcecalib/util/IPCHistoManager.hh b/rce/rcecalib/util/IPCHistoManager.hh new file mode 100644 index 00000000..c2c31fe8 --- /dev/null +++ b/rce/rcecalib/util/IPCHistoManager.hh @@ -0,0 +1,35 @@ +#ifndef IPC_HISTO_MANAGER_HH +#define IPC_HISTO_MANAGER_HH + +#include <vector> +#include <string> +#include <map> + + +class IPCPartition; + +class AbsRceHisto; +class OHBins; +template<class T> class OHRawProvider; +#include <iostream> + +class IPCHistoManager{ +public: + IPCHistoManager(IPCPartition& p, const char* servername, const char* providername); + ~IPCHistoManager(); + static IPCHistoManager* instance(){ + return m_manager; + } + void addToInventory(AbsRceHisto*); + void removeFromInventory(AbsRceHisto*); + void publish(const char* reg); + std::vector<std::string> getHistoNames(const char* reg); + std::vector<std::string> getPublishedHistoNames(); +private: + std::map<std::string,AbsRceHisto*> m_inventory; + std::map<std::string,AbsRceHisto*> m_published; + OHRawProvider<OHBins>* m_provider; + static IPCHistoManager* m_manager; +}; + +#endif diff --git a/rce/rcecalib/util/Makefile b/rce/rcecalib/util/Makefile new file mode 100644 index 00000000..c73fd5ec --- /dev/null +++ b/rce/rcecalib/util/Makefile @@ -0,0 +1,20 @@ +# Package level makefile +# ---------------------- +%.mk:; + +# Checks +# ------ +# Check release location variables +ifeq ($(RELEASE_DIR),) +export RELEASE_DIR := $(PWD)/../.. +endif + +include $(RELEASE_DIR)/make/share/setup.mk +include ../flags.mk + +ifndef PREMAKE_DONE +include $(RELEASE_DIR)/make/share/premake.mk +else +include constituents.mk +include $(RELEASE_DIR)/make/sw/package.mk +endif diff --git a/rce/rcecalib/util/RceHisto1d.cc b/rce/rcecalib/util/RceHisto1d.cc new file mode 100644 index 00000000..858729f0 --- /dev/null +++ b/rce/rcecalib/util/RceHisto1d.cc @@ -0,0 +1,181 @@ +#ifndef RCEHISTO1D_CC +#define RCEHISTO1D_CC + +#include "rcecalib/util/RceHisto1d.hh" +#include "rcecalib/util/IPCHistoManager.hh" +#include <string> + +template<typename T, typename TE> +RceHisto1d<T, TE>::RceHisto1d(std::string name, std::string title, unsigned int nbin, float xmin, float xmax, bool hasErrors) + :AbsRceHisto(name.c_str(),title.c_str(),1), m_hasErrors(hasErrors){ + m_dim[0] = nbin; + m_dim[1] = 1; + m_lim[0][0] = xmin; + m_lim[0][1] = xmax; + m_lim[1][0] = 0; + m_lim[1][1] = 0; +// if(xmax-xmin!=0)m_quot[0]=float(nbin)/(xmax-xmin); +// else m_quot[0]=0; +// m_const[0]=xmin*m_quot[0]; + m_data=new T[nbin]; + if(m_hasErrors)m_err=new TE[nbin]; + else m_err=0; + for (unsigned int i=0; i<m_dim[0]; i++){ + m_data[i]=0; + if(m_hasErrors)m_err[i]=0; + } +} + +template<typename T, typename TE> +RceHisto1d<T, TE>::RceHisto1d(const RceHisto1d<T, TE> &h):AbsRceHisto(std::string(h.name()+"_copy").c_str(),h.title().c_str(),1){ + m_dim[0] = h.m_dim[0]; + m_dim[1] = h.m_dim[1]; + m_lim[0][0] = h.m_lim[0][0]; + m_lim[0][1] = h.m_lim[0][1]; + m_lim[1][0] = h.m_lim[1][0]; + m_lim[1][1] = h.m_lim[1][1]; + m_hasErrors = h.m_hasErrors; + m_quot[0]=h.m_quot[0]; + m_const[0]=h.m_const[0]; + m_data=new T[m_dim[0]]; + if(m_hasErrors)m_err=new TE[m_dim[0]]; + else m_err=0; + for (int i=0;i<m_dim[0];i++){ + m_data[i]=h(i); + if(m_hasErrors)m_err[i]=h.getBinError(i); + } +} + + +template<typename T, typename TE> +RceHisto1d<T, TE>::~RceHisto1d(){ + delete [] m_data; + if(m_hasErrors)delete [] m_err; +} + +template<typename T, typename TE> +RceHisto1d<T, TE>& RceHisto1d<T, TE>::operator=(const RceHisto1d<T, TE>&h){ + if (&h == this) { + return *this; + } else { + IPCHistoManager* mgr=IPCHistoManager::instance(); + assert(mgr!=0); + mgr->removeFromInventory(this); + delete [] m_data; + if(m_hasErrors)delete [] m_err; + m_ndim = h.m_ndim; + m_name = h.m_name+"_copy"; + m_title = h.m_title; + m_dim[0] = h.m_dim[0]; + m_dim[1] = h.m_dim[1]; + m_lim[0][0] = h.m_lim[0][0]; + m_lim[0][1] = h.m_lim[0][1]; + m_lim[1][0] = h.m_lim[1][0]; + m_lim[1][1] = h.m_lim[1][1]; + m_hasErrors = h.m_hasErrors; + m_quot[0]=h.m_quot[0]; + m_const[0]=h.m_const[0]; + m_data = new T[m_ndim]; + if(m_hasErrors)m_err = new TE[m_ndim]; + for (int i=0;i<m_dim[0];i++){ + m_data[i]=h(i); + if(m_hasErrors)m_err[i]=h.getBinError(i); + } + mgr->addToInventory(this); + } +} + + +template<typename T, typename TE> +T RceHisto1d<T, TE>::operator()(unsigned int i) const{ + return m_data[i]; + } +template<typename T, typename TE> +TE RceHisto1d<T,TE>::getBinError(unsigned i) const{ + if(!m_hasErrors)return 0; + return m_err[i]; +} +template<typename T, typename TE> +void RceHisto1d<T, TE>::set(unsigned int i, T val) { + if(i<m_dim[0])m_data[i]=val; + } +template<typename T, typename TE> +void RceHisto1d<T, TE>::setFast(unsigned int i, T val) { + m_data[i]=val; + } +template<typename T, typename TE> +void RceHisto1d<T, TE>::setBinError(unsigned int i, TE val) { + if(!m_hasErrors)return; + if(i<m_dim[0])m_err[i]=val; + } +template<typename T, typename TE> +void RceHisto1d<T, TE>::setBinErrorFast(unsigned int i, TE val) { + if(!m_hasErrors)return; + m_err[i]=val; + } + +template<typename T, typename TE> +void RceHisto1d<T, TE>::fill(unsigned int i, T val) { + if(i<m_dim[0])m_data[i]+=val; + } +template<typename T, typename TE> +void RceHisto1d<T, TE>::fillFast(unsigned int i, T val) { + m_data[i]+=val; + } +//template<typename T, typename TE> +//void RceHisto1d<T, TE>::fillByValue(float x, T val) { +// if(x>=m_lim[0][0]&&x<m_lim[0][1]){ +// unsigned bin=int (m_quot[0]*x-m_const[0] ); +// m_data[bin]+=val; +// } +//} + +template<typename T, typename TE> +void RceHisto1d<T, TE>::increment(unsigned int i) { + if(i<m_dim[0])m_data[i]++; +} +template<typename T, typename TE> +void RceHisto1d<T, TE>::incrementFast(unsigned int i) { + m_data[i]++; +} + +template<typename T, typename TE> +void RceHisto1d<T, TE>::clear() { + for (unsigned int i=0;i<m_dim[0];i++){ + m_data[i]=0; + if(m_hasErrors)m_err[i]=0; + } +} + + +template<typename T, typename TE> +void RceHisto1d<T, TE>::publish(OHRawProvider<>* p){ + double width=1; + if(nBin(0)>0)width=(max(0)-min(0))/nBin(0); + /* fix for TDAQ 4 relase */ +#ifndef TDAQ_RELEASE_4 + OHAxis<double> xaxis(m_axisTitle[0].c_str(), m_dim[0], min(0), width ); +#else + OHAxis xaxis=OHMakeAxis<double>(m_axisTitle[0].c_str(), m_dim[0], min(0), width ); +#endif + // Create Annotations + std::vector<std::pair<std::string,std::string> > annotations; + annotations.push_back( std::make_pair("RceHisto1d", "RawProvider publish") ); + + // Publish in OH + try { + p->publish(m_name, m_title, xaxis, m_data, m_err, false, -1, annotations); + } catch (daq::oh::RepositoryNotFound) { + std::string mess = "The repository is not found "; + std::cout<<mess<<std::endl; + } catch (daq::oh::ObjectTypeMismatch) { + std::string mess = "Arguments invalid "; + std::cout<<mess<<std::endl; + } catch (...) { + std::string mess = "Unknown exception thrown "; + std::cout<<mess<<std::endl; + } +} + + +#endif diff --git a/rce/rcecalib/util/RceHisto1d.hh b/rce/rcecalib/util/RceHisto1d.hh new file mode 100644 index 00000000..55b3a7df --- /dev/null +++ b/rce/rcecalib/util/RceHisto1d.hh @@ -0,0 +1,35 @@ +#ifndef RCE_HISTO1D_HH +#define RCE_HISTO1D_HH + +#include "rcecalib/util/AbsRceHisto.hh" + +#include "oh/OHRawProvider.h" + + +template<typename T, typename TE> class RceHisto1d: public AbsRceHisto{ +public: + RceHisto1d(std::string name, std::string title, unsigned int nbin, float xmin, float xmax, bool hasErrors=false); //! Constructor 1D + RceHisto1d(const RceHisto1d<T, TE> &h); //! Copy contructor + virtual ~RceHisto1d(); + RceHisto1d &operator=(const RceHisto1d<T, TE>&h); + T operator()(unsigned i) const; + TE getBinError(unsigned i) const; + inline void setBinError(unsigned int i, TE val); + inline void setBinErrorFast(unsigned int i, TE val); + inline void set(unsigned int i, T val); //! Bin write access 1d + inline void setFast(unsigned int i, T val); //! Bin write access 1d + inline void fill(unsigned int i, T val); + inline void fillFast(unsigned int i, T val); +// inline void fillByValue(float x, T val); + inline void increment(unsigned int i); + inline void incrementFast(unsigned int i); + void clear(); + void publish(OHRawProvider<>* p); +private: + T *m_data; + TE *m_err; + bool m_hasErrors; +}; + + +#endif diff --git a/rce/rcecalib/util/RceHisto2d.cc b/rce/rcecalib/util/RceHisto2d.cc new file mode 100644 index 00000000..327239f3 --- /dev/null +++ b/rce/rcecalib/util/RceHisto2d.cc @@ -0,0 +1,223 @@ +#ifndef RCEHISTO2D_CC +#define RCEHISTO2D_CC + +#include "rcecalib/util/RceHisto2d.hh" +#include "rcecalib/util/IPCHistoManager.hh" +#include <iostream> + +template<typename T, typename TE> +RceHisto2d<T, TE>::RceHisto2d(std::string name, std::string title, unsigned int nbin, float xmin, float xmax, + unsigned int nbin2, float ymin, float ymax, bool isreversed, bool hasErrors) + :AbsRceHisto(name.c_str(),title.c_str(),2), m_hasErrors(hasErrors), m_reverse(isreversed){ + m_dim[0] = nbin; + m_dim[1] = nbin2; + m_lim[0][0] = xmin; + m_lim[0][1] = xmax; + m_lim[1][0] = ymin; + m_lim[1][1] = ymax; + +// if(xmax-xmin!=0)m_quot[0]=float(nbin)/(xmax-xmin); +// else m_quot[0]=0; +// m_const[0]=xmin*m_quot[0]; +// if(ymax-ymin!=0)m_quot[1]=float(nbin2)/(ymax-ymin); +// else m_quot[1]=0; +// m_const[1]=ymin*m_quot[1]; + + m_data = new T[m_dim[0]*m_dim[1]]; + if(m_hasErrors) m_err = new TE[m_dim[0]*m_dim[1]]; + else m_err=0; + for (unsigned int i=0; i<m_dim[0]*m_dim[1]; i++) { + m_data[i] = 0; + if(m_hasErrors)m_err[i]=0; + } +} +template<typename T, typename TE> +RceHisto2d<T, TE>::RceHisto2d(const RceHisto2d<T, TE> &h):AbsRceHisto(std::string(h.name()+"_copy").c_str(),h.title().c_str(),2){ + m_dim[0] = h.m_dim[0]; + m_dim[1] = h.m_dim[1]; + m_lim[0][0] = h.m_lim[0][0]; + m_lim[0][1] = h.m_lim[0][1]; + m_lim[1][0] = h.m_lim[1][0]; + m_lim[1][1] = h.m_lim[1][1]; + m_hasErrors = h.m_hasErrors; + m_reverse = h.m_reverse; + m_quot[0]=h.m_quot[0]; + m_const[0]=h.m_const[0]; + m_quot[1]=h.m_quot[1]; + m_const[1]=h.m_const[1]; + m_data = new T[m_dim[0]*m_dim[1]]; + if(m_hasErrors) m_err = new TE[m_dim[0]*m_dim[1]]; + else m_err=0; + for (unsigned int i=0; i<m_dim[0]*m_dim[1]; i++) { + m_data[i] = 0; + if(m_hasErrors)m_err[i]=0; + } +} + + +template<typename T, typename TE> +RceHisto2d<T, TE>::~RceHisto2d(){ + delete [] m_data; + if(m_hasErrors)delete [] m_err; +} + +template<typename T, typename TE> +RceHisto2d<T, TE>& RceHisto2d<T, TE>::operator=(const RceHisto2d<T, TE>&h){ + if (&h == this) { + return *this; + } else { + IPCHistoManager* mgr=IPCHistoManager::instance(); + assert(mgr!=0); + mgr->removeFromInventory(this); + delete [] m_data; + if(m_hasErrors)delete [] m_err; + m_ndim = h.m_ndim; + m_name = h.m_name+"_copy"; + m_title = h.m_title; + m_dim[0] = h.m_dim[0]; + m_dim[1] = h.m_dim[1]; + m_lim[0][0] = h.m_lim[0][0]; + m_lim[0][1] = h.m_lim[0][1]; + m_lim[1][0] = h.m_lim[1][0]; + m_lim[1][1] = h.m_lim[1][1]; + m_hasErrors = h.m_hasErrors; + m_reverse = h.m_reverse; + m_quot[0]=h.m_quot[0]; + m_const[0]=h.m_const[0]; + m_quot[1]=h.m_quot[1]; + m_const[1]=h.m_const[1]; + m_data = new T[m_dim[0]*m_dim[1]]; + if(m_hasErrors) m_err = new TE[m_dim[0]*m_dim[1]]; + else m_err=0; + for (unsigned int i=0; i<m_dim[0]*m_dim[1]; i++) { + m_data[i] = h.m_data[i]; + if(m_hasErrors)m_err[i]=h.m_err[i]; + } + mgr->addToInventory(this); + } +} + + +template<typename T, typename TE> +inline T RceHisto2d<T, TE>::operator()(unsigned int i, unsigned int j) { + return m_data[index(i,j)]; + } + +template<typename T, typename TE> +inline TE RceHisto2d<T, TE>::getBinError(unsigned int i, unsigned int j) { + if(!m_hasErrors)return 0; + return m_err[index(i,j)]; + } + +template<typename T, typename TE> +inline void RceHisto2d<T, TE>::set(unsigned int i, unsigned j, T val) { + if(i<m_dim[0]&&j<m_dim[1])m_data[index(i,j)]=val; + } +template<typename T, typename TE> +inline void RceHisto2d<T, TE>::setFast(unsigned int i, unsigned j, T val) { + m_data[index(i,j)]=val; + } + +template<typename T, typename TE> +inline void RceHisto2d<T, TE>::setBinError(unsigned int i, unsigned j, TE val) { + if(!m_hasErrors)return; + if(i<m_dim[0]&&j<m_dim[1])m_err[index(i,j)]=val; + } +template<typename T, typename TE> +inline void RceHisto2d<T, TE>::setBinErrorFast(unsigned int i, unsigned j, TE val) { + if(!m_hasErrors)return; + m_err[index(i,j)]=val; + } + +template<typename T, typename TE> +inline void RceHisto2d<T, TE>::fill(unsigned int i, unsigned j, T val) { + if(i<m_dim[0]&&j<m_dim[1])m_data[index(i,j)]+=val; + } +template<typename T, typename TE> +inline void RceHisto2d<T, TE>::fillFast(unsigned int i, unsigned j, T val) { + m_data[index(i,j)]+=val; + } +//template<typename T, typename TE> +//inline void RceHisto2d<T, TE>::fillByValue(float x, float y, T val) { +// if(x>=m_lim[0][0]&&x<m_lim[0][1] && y>=m_lim[1][0]&&y<m_lim[1][1]){ +// unsigned binx=int (m_quot[0]*x-m_const[0] ); +// unsigned biny=int (m_quot[1]*y-m_const[1] ); +// m_data[index(binx,biny)]+=val; +// } +//} +template<typename T, typename TE> +inline void RceHisto2d<T, TE>::increment(unsigned int i, unsigned j) { + if(i<m_dim[0]&&j<m_dim[1])m_data[index(i,j)]++; +} +template<typename T, typename TE> +inline void RceHisto2d<T, TE>::incrementFast(unsigned int i, unsigned j) { + m_data[index(i,j)]++; +} + + + +template<typename T, typename TE> +void RceHisto2d<T, TE>::clear() { + for (unsigned int i=0;i<m_dim[0]*m_dim[1];i++){ + m_data[i]=0; + if(m_hasErrors)m_err[i]=0; + } +} + + +template<typename T, typename TE> +void RceHisto2d<T, TE>::publish(OHRawProvider<>* p){ + double widthx=1; + if(nBin(0)>0)widthx=(max(0)-min(0))/nBin(0); + double widthy=1; + if(nBin(1)>0)widthy=(max(1)-min(1))/nBin(1); + /* fix for TDAQ 4 release */ +#ifndef TDAQ_RELEASE_4 + OHAxis<double> xaxis(m_axisTitle[0].c_str(), m_dim[0], min(0), widthx); + OHAxis<double> yaxis(m_axisTitle[1].c_str(),m_dim[1], min(1), widthy); +#else + OHAxis xaxis=OHMakeAxis<double>(m_axisTitle[0].c_str(), m_dim[0], min(0), widthx); + OHAxis yaxis=OHMakeAxis<double>(m_axisTitle[1].c_str(),m_dim[1], min(1), widthy); +#endif + // Create Annotations + std::vector<std::pair<std::string,std::string> > annotations; + annotations.push_back( std::make_pair("RceHisto2d", "RawProvider publish") ); + + T* sdata=0; + TE* serr=0; + // if x and y were swapped for performance reasons swap them back before shipping + if(m_reverse){ + sdata=new T[m_dim[0]*m_dim[1]]; + if(m_err)serr=new TE[m_dim[0]*m_dim[1]]; + for (unsigned i=0;i<m_dim[0]*m_dim[1];i++){ + sdata[i]=m_data[(i%m_dim[1])*m_dim[0]+(i/m_dim[1])]; + if(m_err)serr[i]=m_err[(i%m_dim[1])*m_dim[0]+(i/m_dim[1])]; + } + } + + // Publish in OH + try { + if(m_reverse) p->publish(m_name, m_title, yaxis, xaxis, sdata, serr, false, -1, annotations); + else p->publish(m_name, m_title, xaxis, yaxis, m_data, m_err, false, -1, annotations); + } catch (daq::oh::RepositoryNotFound) { + std::string mess = "The repository is not found "; + std::cout<<mess<<std::endl; + } catch (daq::oh::ObjectTypeMismatch) { + std::string mess = "Arguments invalid "; + std::cout<<mess<<std::endl; + } catch (...) { + std::string mess = "Unknown exception thrown "; + std::cout<<mess<<std::endl; + } + if(m_reverse){ + delete [] sdata; + if(m_hasErrors)delete [] serr; + } +} + +template<typename T, typename TE> +inline int RceHisto2d<T, TE>::index(int x, int y){ + return x+y*m_dim[0]; +} + +#endif diff --git a/rce/rcecalib/util/RceHisto2d.hh b/rce/rcecalib/util/RceHisto2d.hh new file mode 100644 index 00000000..2a53bfc6 --- /dev/null +++ b/rce/rcecalib/util/RceHisto2d.hh @@ -0,0 +1,38 @@ +#ifndef RCE_HISTO2D_HH +#define RCE_HISTO2D_HH + +#include "rcecalib/util/AbsRceHisto.hh" + +#include "oh/OHRawProvider.h" + + +template<typename T, typename TE> class RceHisto2d: public AbsRceHisto{ +public: + RceHisto2d(std::string name, std::string title, unsigned int nbin, float xmin, float xmax, //! Constructor 2D + unsigned int nbin2, float xmin2, float xmax2, bool isreversed=false, bool hasErrors=false); + RceHisto2d(const RceHisto2d<T, TE> &h); //! Copy contructor + virtual ~RceHisto2d(); + RceHisto2d &operator=(const RceHisto2d<T, TE>&h); + T operator()(unsigned i, unsigned j); + TE getBinError(unsigned i, unsigned j); + void setBinError(unsigned int i, unsigned j, TE val); + void setBinErrorFast(unsigned int i, unsigned j, TE val); + void set(unsigned int i, unsigned j, T val); //! Bin write access 2d + void setFast(unsigned int i, unsigned j, T val); //! Bin write access 2d + void fill(unsigned int i, unsigned j, T val); + void fillFast(unsigned int i, unsigned j, T val); +// void fillByValue(float x, float y, T val); + void increment(unsigned int i, unsigned j); + void incrementFast(unsigned int i, unsigned j); + void clear(); + void publish(OHRawProvider<>* p); +private: + int index(int x, int y); + T *m_data; + TE *m_err; + bool m_hasErrors; + bool m_reverse; +}; + + +#endif diff --git a/rce/rcecalib/util/RceMath.cc b/rce/rcecalib/util/RceMath.cc new file mode 100644 index 00000000..2738d177 --- /dev/null +++ b/rce/rcecalib/util/RceMath.cc @@ -0,0 +1,41 @@ +#include "rcecalib/util/RceMath.hh" + +namespace RceMath { +// Calculates SQRT fast, but not very precise +// Dirty playing with bits can give us the sqrt of a float +// Depends on the 32bit architecture +// See: http://bits.stephan-brumme.com/squareRoot.html +float fastCoarseSqrt(float x) { + // Get around dirty casting + union { + float x; + unsigned int i; + } u; + u.x = x; + // adjust bias + u.i += 127 << 23; + // approximation of square root + u.i >>= 1; + //printf("sqrt(%f)=%f\n",x, u.x); + return u.x; +} + +// Calcutes SQRT fast and kinda precise, but no as fast as fastCoarseSqrt() +// Uses basically the same method, but adds a newton approximation step +// to increase precision +// Taken from Quake3 engine +// See: http://www.lomont.org/Math/Papers/2003/InvSqrt.pdf +float fastQuakeSqrt(const float x) { + const float xhalf = 0.5f*x; + union { // get bits for floating value + float x; + int i; + } u; + u.x = x; + u.i = 0x5f3759df - (u.i >> 1); // gives initial guess y0 + float result = x*u.x*(1.5f - xhalf*u.x*u.x);// Newton step, repeating increases accuracy + //printf("sqrt(%f)=%f\n",x, result); + return result; +} + +} diff --git a/rce/rcecalib/util/RceMath.hh b/rce/rcecalib/util/RceMath.hh new file mode 100644 index 00000000..32a0d91e --- /dev/null +++ b/rce/rcecalib/util/RceMath.hh @@ -0,0 +1,13 @@ +// Mathmatical helper functions + +#ifndef RCEMATH_HH +#define RCEMATH_HH + +#include <stdio.h> + +namespace RceMath { + float fastCoarseSqrt(float x); + float fastQuakeSqrt(float x); +} + +#endif diff --git a/rce/rcecalib/util/RceName.cc b/rce/rcecalib/util/RceName.cc new file mode 100644 index 00000000..278830c9 --- /dev/null +++ b/rce/rcecalib/util/RceName.cc @@ -0,0 +1,20 @@ +#include "rcecalib/util/RceName.hh" +#include <stdlib.h> +#include <assert.h> + +int RceName::m_number=0; +bool RceName::m_initialized=false; + +int RceName::getRceNumber(){ + if(m_initialized==false){ + char* name=getenv("RCE_NAME"); + char* endptr; + if(name){ + m_number=(int)strtol(name, &endptr, 0); + assert(*endptr=='\0'); + } + else m_number=0; + m_initialized=true; + } + return m_number; +} diff --git a/rce/rcecalib/util/RceName.hh b/rce/rcecalib/util/RceName.hh new file mode 100644 index 00000000..899d8c30 --- /dev/null +++ b/rce/rcecalib/util/RceName.hh @@ -0,0 +1,14 @@ +#ifndef RCENAME_HH +#define RCENAME_HH + +#include <string> + +class RceName{ +public: + static int getRceNumber(); +private: + static int m_number; + static bool m_initialized; +}; + +#endif diff --git a/rce/rcecalib/util/VerifyErrors.hh b/rce/rcecalib/util/VerifyErrors.hh new file mode 100644 index 00000000..9569b7be --- /dev/null +++ b/rce/rcecalib/util/VerifyErrors.hh @@ -0,0 +1,11 @@ +#ifndef VERIFY_ERRORS_HH +#define VERIFY_ERRORS_HH + +namespace ModuleVerify{ + + enum verify_errors{OK=0, GLOBAL_READBACK_FAILED=0x1, GLOBAL_READBACK_DIFFERENT=0x2, PIXEL_WRONG_N_WORDS=0x4, + PIXEL_READBACK_DIFFERENT=0x8, NO_FORMATTER=0x100, NO_MODULE=0x200}; + +}; + +#endif diff --git a/rce/rcecalib/util/constituents.mk b/rce/rcecalib/util/constituents.mk new file mode 100644 index 00000000..29c85cf9 --- /dev/null +++ b/rce/rcecalib/util/constituents.mk @@ -0,0 +1,28 @@ + +ifdef SWAP_DATA +CPPFLAGS += '-DSWAP_DATA' +endif + +ifneq ($(findstring ppc-rtems-rce,$(tgt_arch)),) +modlibnames := util +endif +ifneq ($(findstring linux,$(tgt_os)),) +libnames := util +endif + +libsrcs_util := IPCHistoManager.cc \ + RceName.cc \ + AbsRceHisto.cc \ + RceMath.cc + + +libincs_util := rcecalib \ + $(ers_include_path) \ + $(owl_include_path) \ + $(ipc_include_path) \ + $(is_include_path) \ + $(oh_include_path) \ + $(boost_include_path) \ + $(omniorb_include_path) + + diff --git a/rce/rcecalib/util/exceptions.hh b/rce/rcecalib/util/exceptions.hh new file mode 100644 index 00000000..1a54acda --- /dev/null +++ b/rce/rcecalib/util/exceptions.hh @@ -0,0 +1,33 @@ +#ifndef SCANCTRLEXCEPTIONS_HH +#define SCANCTRLEXCEPTIONS_HH + +#include "ers/ers.h" + +ERS_DECLARE_ISSUE( rcecalib, // namespace name + Bad_ptree_param, // issue name + "Bad scan parameter: " << reason, // message + ((const char *)reason ) // first attribute + ) + +ERS_DECLARE_ISSUE( rcecalib, // namespace name + Param_exists, // issue name + "Parameter " << reason <<" was previously defined", // message + ((const char *)reason ) // first attribute + ) +ERS_DECLARE_ISSUE( rcecalib, // namespace name + Unknown_Module_Type, // issue name + "No such module type: " << reason, // message + ((const char *)reason ) // first attribute + ) +ERS_DECLARE_ISSUE( rcecalib, // namespace name + Unknown_Scan_Type, // issue name + "No such scan type: " << reason, // message + ((const char *)reason ) // first attribute + ) +ERS_DECLARE_ISSUE( rcecalib, // namespace name + Config_File_Error, // issue name + "Error in config file " , // message + ) + + +#endif diff --git a/rce/rcecalib/xmd.ini b/rce/rcecalib/xmd.ini new file mode 100755 index 00000000..ddd58a05 --- /dev/null +++ b/rce/rcecalib/xmd.ini @@ -0,0 +1 @@ +connect ppc hw -cable type xilinx_platformusb frequency 12000000 -debugdevice isocmstartadr 0xFFFFF000 isocmsize 4096 isocmdcrstartadr 0x0000000 icachestartadr 0x10000000 itagstartadr 0x20000000 dcachestartadr 0x30000000 dtagstartadr 0x40000000 dcrstartadr 0x50000000 diff --git a/rce/scripts/cmake_script b/rce/scripts/cmake_script new file mode 100755 index 00000000..9a5d499c --- /dev/null +++ b/rce/scripts/cmake_script @@ -0,0 +1,3 @@ +#!/bin/bash +unset LD_LIBRARY_PATH +echo `/usr/bin/cmake $*` diff --git a/rce/scripts/dumpscans b/rce/scripts/dumpscans new file mode 100755 index 00000000..0f799517 --- /dev/null +++ b/rce/scripts/dumpscans @@ -0,0 +1,22 @@ +#!/bin/csh -f + +rm -f ./scan_fei3 ./scan_fei4a ./scan_fei4b + +touch ./scan_fei3 +touch ./scan_fei4a +touch ./scan_fei4b + +foreach i (`dumpRceScan -l `) +set i=`echo $i | tr -d '\n'` +echo $i >> ./scan_fei3 +dumpRceScan -f PM_FE_I2 $i >> scan_fei3 + +echo $i >> ./scan_fei4b +dumpRceScan -f PM_FE_I4B $i >> scan_fei4b + +echo $i >> ./scan_fei4a +dumpRceScan -f PM_FE_I4A $i >> scan_fei4a + + +end + diff --git a/rce/scripts/findUndefSymbols.pl b/rce/scripts/findUndefSymbols.pl new file mode 100755 index 00000000..bded55b2 --- /dev/null +++ b/rce/scripts/findUndefSymbols.pl @@ -0,0 +1,38 @@ +#!/usr/bin/perl -w + +$core=$ARGV[0]; +$mod=$ARGV[1]; + +@nmm=`nm $mod`; +foreach (@nmm) { + $_ =~ s/^[0-9a-f]* //; + chomp; + @tbm=split; + #print "x$tbm[0]x\n"; + if($tbm[0] eq "U"){ + #print $tbm[1]."\n"; + $usym{$tbm[1]}=0; + } +} +#print %usym; + +@nmc=`nm $core`; +foreach (@nmc) { + $_ =~ s/^[0-9a-f]* //; + chomp; + @tbc=split; + if($tbc[0] ne "U"){ + #print $tbm[1]."\n"; + $usym{$tbc[1]}=1; + } + #print $tbc[0]."\n"; +} +#print $usym{"sleep"}."\n" ; +print "LXFLAGS +="; +for $key ( keys %usym ){ + if ($usym{$key}==0){ + print " -u $key"; + } +} +print "\n"; + diff --git a/rce/scripts/patch.links b/rce/scripts/patch.links new file mode 100755 index 00000000..13ebd4ea --- /dev/null +++ b/rce/scripts/patch.links @@ -0,0 +1,7 @@ +#!/bin/tcsh +ln -sf /daq/slc5/tdaq-common/tdaq-common-01-18-04/installed/i686-slc5-gcc43-opt /daq/slc5/tdaq-common/tdaq-common-01-18-04/installed/i686-slc5-gcc43-dbg +ln -sf /daq/slc5/sw/lcg/external/Boost/1.44.0_python2.6/i686-slc5-gcc43-opt /daq/slc5/sw/lcg/external/Boost/1.44.0_python2.6/i686-slc5-gcc43-dbg +ln -sf /daq/slc5/tdaq/tdaq-04-00-01/installed/i686-slc5-gcc43-opt /daq/slc5/tdaq/tdaq-04-00-01/installed/i686-slc5-gcc43-dbg +ln -sf /daq/slc5/tdaq/tdaq-04-00-01/external/i686-slc5-gcc43-opt /daq/slc5/tdaq/tdaq-04-00-01/external/i686-slc5-gcc43-dbg +ln -sf /daq/slc5/opt/rcecore/1.4/build/rce/lib/i686-slc5-gcc43-opt /daq/slc5/opt/rcecore/1.4/build/rce/lib/i686-slc5-gcc43-dbg + diff --git a/rce/scripts/rce_dow b/rce/scripts/rce_dow new file mode 100755 index 00000000..9b5ca15c --- /dev/null +++ b/rce/scripts/rce_dow @@ -0,0 +1,8 @@ +#!/bin/tcsh + +setenv TCL_LIBRARY /usr/share/tcl8.4 + +cd $RCE_BIN + +ln -sf $XMD_INI . +expect -f $HOME/rce/rcecalib/scripts/rce_dow.ex diff --git a/rce/scripts/rce_dow.ex b/rce/scripts/rce_dow.ex new file mode 100644 index 00000000..38961170 --- /dev/null +++ b/rce/scripts/rce_dow.ex @@ -0,0 +1,18 @@ +set timeout 120 +spawn xmd +expect "Starting GDB" +expect "XMD%" +send "stop\r" +expect "XMD%" +send "rst -processor\r" +expect "Target reset" +expect "XMD%" +send "dow calibserver\r" +expect "Setting PC" +expect "XMD%" +send "con\r" +expect "Info:Processor started" +expect "RUNNING> XMD%" +send "\r" +expect "XMD%" +send "exit\r" diff --git a/rce/scripts/setup-gen3.sh b/rce/scripts/setup-gen3.sh index ac775f11..21a35bdc 100644 --- a/rce/scripts/setup-gen3.sh +++ b/rce/scripts/setup-gen3.sh @@ -3,9 +3,8 @@ export TDAQ_VERSION=6 export LCG_INST_PATH=/sw/atlas export SDK_ROOT=/opt/AtlasRceSdk/V0.11.1 -_topdir=$(dirname ${BASH_SOURCE})/.. -_topdir=$(cd ${_topdir}/> /dev/null 2>&1 && pwd) -echo ${_topdir} + + source $LCG_INST_PATH/sw/lcg/contrib/gcc/4.9.3/x86_64-slc6/setup.sh source $SDK_ROOT/setup.sh @@ -34,26 +33,26 @@ fi export ROOTSYS=$LCG_INST_PATH/sw/lcg/LCG_81b/ROOT/6.04.12/x86_64-slc6-gcc49-opt export TDAQ_INST_PATH=/sw/atlas/tdaq/tdaq-06-01-00/installed set -- -if [ -d ${_topdir}/scripts ]; then - if [ ! -d ${_topdir}/$arm ]; then - echo Creating ${_topdir}/rce/$arm - mkdir ${_topdir}/$arm +if [ -d ~/daq/rce/scripts ]; then + if [ ! -d ~/daq/rce/$arm ]; then + echo Creating ~/daq/rce/$arm + mkdir ~/daq/rce/$arm fi - if [ ! -d ${_topdir}/$slc ]; then - echo Creating ${_topdir}/$slc - mkdir ${_topdir}/$slc + if [ ! -d ~/daq/rce/$slc ]; then + echo Creating ~/daq/rce/$slc + mkdir ~/daq/rce/$slc fi # source /sw/atlas/setup.sh export MAKEFLAGS="-j12 QUICK=1" - echo cd ${_topdir}/$arm - cd ${_topdir}/$arm - cmake -DCMAKE_BUILD_TYPE="$debug" -DCMAKE_TOOLCHAIN_FILE=${_topdir}/pixelrce/toolchain/arm-archlinux ${_topdir}/pixelrce $rcf - echo cd ${_topdir}/$slc - cd ${_topdir}/$slc - cmake -DCMAKE_BUILD_TYPE="$debug" -DCMAKE_TOOLCHAIN_FILE=${_topdir}/pixelrce/toolchain/tdaq-linux ${_topdir}/pixelrce $rcf + echo cd ~/daq/rce/$arm + cd ~/daq/rce/$arm + cmake -DCMAKE_BUILD_TYPE="$debug" -DCMAKE_TOOLCHAIN_FILE=~/daq/rce/pixelrce/toolchain/arm-archlinux ~/daq/rce/pixelrce $rcf + echo cd ~/daq/rce/$slc + cd ~/daq/rce/$slc + cmake -DCMAKE_BUILD_TYPE="$debug" -DCMAKE_TOOLCHAIN_FILE=~/daq/rce/pixelrce/toolchain/tdaq-linux ~/daq/rce/pixelrce $rcf -export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${_topdir}/${slc}/lib -export PATH=${PATH}:${_topdir}/${slc}/bin +export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:~/daq/rce/${slc}/lib +export PATH=${PATH}:~/daq/rce/${slc}/bin export TDAQ_PARTITION=rce_$USER export TDAQ_IPC_INIT_REF=file:~/daq/ipc_root.ref export ORBHOST=192.168.1.1 @@ -65,7 +64,6 @@ alias rce_ipc_ls='ipc_ls ; ipc_ls -p $TDAQ_PARTITION' alias rce_killall='pkill -u $USER ipc_server; pkill -u $USER is_server;' else - echo "${_topdir}/scripts does not exist" + echo "~/daq/rce/scripts does not exist" fi popd -unset _topdir diff --git a/rce/scripts/setup_rce-04-00-00.csh b/rce/scripts/setup_rce-04-00-00.csh new file mode 100644 index 00000000..cfe7b5f6 --- /dev/null +++ b/rce/scripts/setup_rce-04-00-00.csh @@ -0,0 +1,148 @@ +#--> These aliases are used to manipulate environmental variables used to hold +#--> directory paths, e.g. PATH, MANPATH. They allow one to append, prepend +#--> or remove specific directories from such variables. +alias addpath_clean 'delpath \!:*; setenv \!:1 ${\!:1}\:\!:2' +alias addpath2_clean 'delpath \!:*; setenv \!:1 \!:2\:${\!:1}' +# add to end of path +alias addpath 'if ( $\!:1 != \!:2 && $\!:1 !~ \!:2\:* && $\!:1 !~ *\:\!:2\:* && $\!:1 !~ *\:\!:2 ) setenv \!:1 ${\!:1}\:\!:2' +# add to front of path +alias addpath2 'if ( $\!:1 != \!:2 && $\!:1 !~ \!:2\:* && $\!:1 !~ *\:\!:2\:* && $\!:1 !~ *\:\!:2 ) setenv \!:1 \!:2\:${\!:1}; if ( $\!:1 != \!:2 && $\!:1 !~ \!:2\:* ) setenv \!:1 \!:2\:`echo ${\!:1} | sed -e s%^\!:2\:%% -e s%:\!:2\:%:%g -e s%:\!:2\$%%`' +alias delpath 'setenv \!:1 `echo ${\!:1} | sed -e s%^\!:2\$%% -e s%^\!:2\:%% -e s%:\!:2\:%:%g -e s%:\!:2\$%%`' +alias modpath 'setenv \!:1 `echo ${\!:1} | sed -e s%^\!:2\$%\!:3% -e s%^\!:2\:%\!:3\:% -e s%:\!:2\:\%:\!:3\:\%g -e s%:\!:2\$%\:\!:3\%`' + +if ( ! -d /home/$USER ) then +exit 0 +endif + +if ( ! $?LD_LIBRARY_PATH ) then +setenv LD_LIBRARY_PATH +endif + +setenv TDAQ_VERSION 4 + +setenv ORBHOST '' +setenv ORBHOST `/sbin/ifconfig | grep "inet addr:1[79]2" | head -1 | gawk -F: '{print $2}' | awk '{print $1}'` +if ( $ORBHOST != '' ) then +setenv ORBendPoint giop:tcp:${ORBHOST}:0 +else +unsetenv ORBHOST +endif + +setenv TDAQ_IPC_INIT_REF file:${HOME}/ipc_root.ref +if ( `uname -m` == 'x86_64' ) then +setenv HOST_ARCH x86_64-slc5-gcc43-opt +setenv TDAQ_HOST_ARCH x86_64-slc5-gcc43-opt +endif +if (`uname -m` == 'i386' ) then +setenv HOST_ARCH i686-slc5-gcc43-opt +setenv TDAQ_HOST_ARCH i686-slc5-gcc43-opt +endif + +#override for now - x86_64 build is broken +setenv HOST_ARCH i686-slc5-gcc43-opt +setenv TDAQ_HOST_ARCH i686-slc5-gcc43-opt + +setenv RCE_ARCH ppc-rtems-rce405-opt +setenv RCE ${HOME}/rce + +#ambush setup +if ( -e /reg/g/atlas/ambush ) then +setenv AMBUSH /reg/g/atlas/ambush +addpath2 LD_LIBRARY_PATH ${AMBUSH}/lib +addpath2 PATH ${AMBUSH}/bin +endif + +#setup python +if ( -e /daq/slc5/sw/lcg/external/Python/2.6.5/i686-slc5-gcc43-opt ) then +addpath2 LD_LIBRARY_PATH /daq/slc5/sw/lcg/external/Python/2.6.5/i686-slc5-gcc43-opt/lib +addpath2 PATH /daq/slc5/sw/lcg/external/Python/2.6.5/i686-slc5-gcc43-opt/bin +else + echo Error: Python is not installed + exit 1 +endif + +if ( -e /daq/slc5/opt/rtems-4.9.2 ) then + setenv RTEMS /daq/slc5/opt/rtems-4.9.2 +else + echo Error: RTEMS is not installed +endif + +#setup rtems cross compilers +set RTEMS_GCC='' + +if ( -e /daq/slc5/opt/powerpc-rtems49-gcc432 ) then + set RTEMS_GCC=/daq/slc5/opt/powerpc-rtems49-gcc432 +else + echo "rtems gcc not found" + exit 1 +endif + +if ( $RTEMS_GCC != '' ) then +addpath2 LD_LIBRARY_PATH $RTEMS_GCC/lib +addpath2 PATH $RTEMS_GCC/bin +endif + +#setup ROOT +setenv ROOTSYS '' +if ( -e /daq/slc5/sw/lcg/app/releases/ROOT/5.30.02/$TDAQ_HOST_ARCH ) then + setenv ROOTSYS /daq/slc5/sw/lcg/app/releases/ROOT/5.30.02/$TDAQ_HOST_ARCH/root +# this needs the TDAQ gcc + if ( `uname -m` == 'x86_64') then + source /daq/slc5/sw/lcg/contrib/gcc/4.3.5/x86_64-slc5-gcc43-opt/setup.csh + addpath2 LD_LIBRARY_PATH /daq/slc5/sw/lcg/contrib/gcc/4.3/x86_64-slc5-gcc43-opt/lib + else + source /daq/slc5/sw/lcg/contrib/gcc/4.3/slc4_ia32_gcc34/setup.csh + addpath2 LD_LIBRARY_PATH /daq/slc5/sw/lcg/contrib/gcc/4.3/slc4_ia32_gcc34-opt/lib + endif +else + echo "TDAQ gcc not installed" + exit 1 +endif +if ( $ROOTSYS != '' ) then +addpath2 PATH $ROOTSYS/bin +addpath2 LD_LIBRARY_PATH $ROOTSYS/lib +endif + +#setup RCE client software +addpath2 PATH ${RCE}/build/rceis/bin/${HOST_ARCH}:${RCE}/build/rceipc/bin/${HOST_ARCH}:${RCE}/build/rcecalib/bin/${HOST_ARCH}:${RCE}/rcecalib/scripts +addpath2 LD_LIBRARY_PATH ${RCE}/build/rcecalib/lib/${HOST_ARCH}:${RCE}/build/rceers/lib/${HOST_ARCH}:${RCE}/build/rceowl/lib/${HOST_ARCH}:${RCE}/build/rceipc/lib/${HOST_ARCH}:${RCE}/build/rceowl/lib/${HOST_ARCH}:${RCE}/build/rceoh/lib/${HOST_ARCH}:${RCE}/build/rceis/lib/${HOST_ARCH} + +setenv RELEASE ${RCE} +setenv RCE_BIN ${RCE}/build/rcecalib/bin/${RCE_ARCH} +setenv RCE_MOD ${RCE}/build/rcecalib/mod/${RCE_ARCH} + +setenv XMD_INI ${RCE}/rcecalib/xmd.ini +setenv TDAQ_IPC_INIT_REF file:/${HOME}/ipc_root.ref +setenv SVNROOT svn+ssh://svn.cern.ch/reps/RceCimDev +setenv TDAQ_PARTITION rcetest_${USER} + +alias rce_ipc_server 'ipc_server -p $TDAQ_PARTITION' +alias rce_is_server 'is_server -p $TDAQ_PARTITION -n RceIsServer' +alias rce_ipc_ls 'ipc_ls ; ipc_ls -p $TDAQ_PARTITION' +alias rce_load 'echo "reboot\nsetenv TDAQ_PARTITION $TDAQ_PARTITION\nsetenv TDAQ_IS_COMPRESSION_THRESHOLD 100000000\n" | host_bootloader -r \!:1 -l $RCE_MOD/calibservermod.1.0.prod.so' +alias rce_killall 'pkill -u $USER ipc_server; pkill -u $USER is_server;' + +if ( ! -d ~/calibData ) then +mkdir ~/calibData +endif + +#tdaq setup +setenv TDAQ_INST_PATH /daq/slc5/tdaq/tdaq-04-00-00/installed +setenv TDAQC_INST_PATH /daq/slc5/tdaq-common/tdaq-common-01-18-03/installed +setenv TDAQC_EXT_PATH /daq/slc5/tdaq-common/tdaq-common-01-18-03/external +setenv TDAQ_BOOST /daq/slc5/sw/lcg/external/Boost/1.44.0_python2.6 +addpath2 PATH $TDAQ_INST_PATH/$HOST_ARCH/bin +addpath2 LD_LIBRARY_PATH $TDAQ_INST_PATH/$HOST_ARCH/lib +addpath2 PATH $TDAQC_INST_PATH/$HOST_ARCH/bin +addpath2 LD_LIBRARY_PATH $TDAQC_INST_PATH/$HOST_ARCH/lib +addpath2 PATH $TDAQC_EXT_PATH/$HOST_ARCH/bin +addpath2 LD_LIBRARY_PATH $TDAQC_EXT_PATH/$HOST_ARCH/lib +addpath2 PATH $TDAQ_INST_PATH/share/bin +addpath2 LD_LIBRARY_PATH $TDAQ_INST_PATH/share/lib +setenv PYTHONPATH $TDAQ_INST_PATH/$HOST_ARCH/lib + +rehash + + + + diff --git a/rce/scripts/setup_rce-04-00-01.csh b/rce/scripts/setup_rce-04-00-01.csh new file mode 100644 index 00000000..b6f49102 --- /dev/null +++ b/rce/scripts/setup_rce-04-00-01.csh @@ -0,0 +1,126 @@ +#!/bin/csh +setenv LD_LIBRARY_PATH +setenv PATH /usr/lib/qt-3.3/bin:/bin:/sbin:/usr/sbin/:/usr/local/bin:/usr/bin:/usr/bin/X11:/usr/sue/bin:/usr/X11R6/bin +setenv LINUXVERS SLC`cat /etc/redhat-release | sed -e 's#[0-9])##g' -e 's#[^\.0-9]##g' -e 's#\.[0-9]##'` +setenv TDAQ_VERSION 4 + +setenv ORBHOST '' +setenv ORBHOST `/sbin/ifconfig | grep "inet addr:1[79]2" | head -1 | gawk -F: '{print $2}' | awk '{print $1}'` +#setenv ORBHOST `/sbin/ifconfig | grep "inet addr:192.168.1" | head -1 | gawk -F: '{print $2}' | awk '{print $1}'` +if ( $ORBHOST != '' ) then +setenv ORBendPoint giop:tcp:${ORBHOST}:0 +else +unsetenv ORBHOST +endif + + + +#override for now - x86_64 build is broken +set DBG_FLAG=opt +if ( "$1" == "debug" ) then +set DBG_FLAG=dbg +endif + +setenv HOST_ARCH i686-slc5-gcc43-${DBG_FLAG} +setenv TDAQ_HOST_ARCH i686-slc5-gcc43-${DBG_FLAG} + +setenv RCE_ARCH ppc-rtems-rce405-opt +setenv RCE ${HOME}/daq/rce + + +#setup python +if ( -e /daq/slc5/sw/lcg/external/Python/2.6.5/i686-slc5-gcc43-opt ) then +setenv LD_LIBRARY_PATH /daq/slc5/sw/lcg/external/Python/2.6.5/i686-slc5-gcc43-opt/lib:${LD_LIBRARY_PATH} +setenv PATH /daq/slc5/sw/lcg/external/Python/2.6.5/i686-slc5-gcc43-opt/bin:${PATH} +else + echo Error: Python is not installed +endif + +if ( -e /daq/slc5/opt/rtems-4.9.2 ) then + setenv RTEMS /daq/slc5/opt/rtems-4.9.2 +else + echo Error: RTEMS is not installed +endif + +#setup rtems cross compilers +set RTEMS_GCC='' + +if ( -e /daq/slc5/opt/powerpc-rtems49-gcc432 ) then + set RTEMS_GCC=/daq/slc5/opt/powerpc-rtems49-gcc432 +else + echo "rtems gcc not found" +endif + +if ( $RTEMS_GCC != '' ) then +setenv LD_LIBRARY_PATH $RTEMS_GCC/lib:${LD_LIBRARY_PATH} +setenv PATH $RTEMS_GCC/bin:${PATH} +endif + +#setup ROOT +setenv ROOTSYS '' +if ( -e /daq/slc5/sw/lcg/app/releases/ROOT/5.30.05/i686-slc5-gcc43-opt ) then + setenv ROOTSYS /daq/slc5/sw/lcg/app/releases/ROOT/5.30.05/i686-slc5-gcc43-opt/root +# this needs the TDAQ gcc + if ( `uname -m` == 'x86_64') then + source /daq/slc5/sw/lcg/contrib/gcc/4.3.5/x86_64-slc5-gcc43-opt/setup.csh + setenv LD_LIBRARY_PATH /daq/slc5/sw/lcg/contrib/gcc/4.3/x86_64-slc5-gcc43-opt/lib:${LD_LIBRARY_PATH} + else + source /daq/slc5/sw/lcg/contrib/gcc/4.3/slc4_ia32_gcc34/setup.csh + setenv LD_LIBRARY_PATH /daq/slc5/sw/lcg/contrib/gcc/4.3/slc4_ia32_gcc34-opt/lib:${LD_LIBRARY_PATH} + endif +else + echo "TDAQ gcc not installed" +endif +if ( $ROOTSYS != '' ) then +setenv PATH $ROOTSYS/bin:${PATH} +setenv LD_LIBRARY_PATH $ROOTSYS/lib:${LD_LIBRARY_PATH} +endif + +#setup RCE client software +setenv PATH ${RCE}/build/rceis/bin/${HOST_ARCH}:${RCE}/build/rceipc/bin/${HOST_ARCH}:${RCE}/build/rcecalib/bin/${HOST_ARCH}:${RCE}/rcecalib/scripts:${PATH} +setenv LD_LIBRARY_PATH ${RCE}/build/rcecalib/lib/${HOST_ARCH}:${RCE}/build/rceers/lib/${HOST_ARCH}:${RCE}/build/rceowl/lib/${HOST_ARCH}:${RCE}/build/rceipc/lib/${HOST_ARCH}:${RCE}/build/rceowl/lib/${HOST_ARCH}:${RCE}/build/rceoh/lib/${HOST_ARCH}:${RCE}/build/rceis/lib/${HOST_ARCH}:${LD_LIBRARY_PATH} + +setenv RELEASE ${RCE} +setenv RCE_BIN ${RCE}/build/rcecalib/bin/${RCE_ARCH} +setenv RCE_MOD ${RCE}/build/rcecalib/mod/${RCE_ARCH} + +setenv XMD_INI ${RCE}/rcecalib/xmd.ini +setenv TDAQ_IPC_INIT_REF file:/${HOME}/ipc_root.ref +setenv SVNROOT svn+ssh://svn.cern.ch/reps/RceCimDev +setenv TDAQ_PARTITION rcetest_${USER} + +alias rce_ipc_server 'ipc_server -p $TDAQ_PARTITION' +alias rce_is_server 'is_server -p $TDAQ_PARTITION -n RceIsServer' +alias rce_ipc_ls 'ipc_ls ; ipc_ls -p $TDAQ_PARTITION' +alias rce_load 'echo "reboot\nsetenv TDAQ_PARTITION $TDAQ_PARTITION\nsetenv TDAQ_IS_COMPRESSION_THRESHOLD 100000000\n" | host_bootloader -r \!:1 -l $RCE_MOD/calibservermod.1.0.prod.so' +alias rce_killall 'pkill -u $USER ipc_server; pkill -u $USER is_server;' + +if ( ! -d ~/calibData ) then +mkdir ~/calibData +endif + +#tdaq setup +setenv TDAQ_INST_PATH /daq/slc5/tdaq/tdaq-04-00-01/installed +setenv TDAQC_INST_PATH /daq/slc5/tdaq-common/tdaq-common-01-18-04/installed +setenv TDAQC_EXT_PATH /daq/slc5/tdaq-common/tdaq-common-01-18-04/external +setenv TDAQ_BOOST /daq/slc5/sw/lcg/external/Boost/1.44.0_python2.6 +setenv TDAQ_MYSQL /daq/slc5/sw/lcg/external/mysql/5.5.14 +setenv PATH $TDAQ_INST_PATH/$HOST_ARCH/bin:${PATH} +setenv LD_LIBRARY_PATH $TDAQ_INST_PATH/$HOST_ARCH/lib:${LD_LIBRARY_PATH} +setenv LD_LIBRARY_PATH $TDAQ_BOOST/$HOST_ARCH/lib:${LD_LIBRARY_PATH} +setenv PATH $TDAQC_INST_PATH/$HOST_ARCH/bin:${PATH} +setenv LD_LIBRARY_PATH $TDAQC_INST_PATH/$HOST_ARCH/lib:${LD_LIBRARY_PATH} +setenv PATH $TDAQC_EXT_PATH/$HOST_ARCH/bin:${PATH} +setenv LD_LIBRARY_PATH $TDAQC_EXT_PATH/$HOST_ARCH/lib:${LD_LIBRARY_PATH} +setenv PATH $TDAQ_INST_PATH/share/bin:${PATH} +setenv LD_LIBRARY_PATH $TDAQ_INST_PATH/share/lib:${LD_LIBRARY_PATH} +setenv PYTHONPATH $TDAQ_INST_PATH/$HOST_ARCH/lib:${PATH} +setenv ARCH $HOST_ARCH +rehash +setenv PIXLIBINTERFACE $RCE/../PixLibInterface +setenv USE_RCE yes +setenv RCE_CORE_VERSION 1.4 + + + + diff --git a/rce/scripts/setup_rce-04-00-01.sh b/rce/scripts/setup_rce-04-00-01.sh new file mode 100644 index 00000000..75fa5e0f --- /dev/null +++ b/rce/scripts/setup_rce-04-00-01.sh @@ -0,0 +1,114 @@ +#!/bin/bash +export LD_LIBRARY='' +export PATH=/usr/lib/qt-3.3/bin:/bin:/sbin:/usr/sbin/:/usr/local/bin:/usr/bin:/usr/bin/X11:/usr/sue/bin:/usr/X11R6/bin +export LINUXVERS=SLC`cat /etc/redhat-release | sed -e 's#[0-9])##g' -e 's#[^\.0-9]##g' -e 's#\.[0-9]##'` +if [ -n $LD_LIBRARY_PATH ] ; then + export LD_LIBRARY_PATH='' +fi + +export ORBHOST='' +export ORBHOST=`/sbin/ifconfig | grep "inet addr:1[79]2" | head -1 | gawk -F: '{print $2}' | awk '{print $1}'` +if [ -n $ORBHOST ] ; then + export ORBendPoint="giop:tcp:${ORBHOST}:0" +else + unset ORBHOST +fi + +export TDAQ_IPC_INIT_REF="file:${HOME}/ipc_root.ref" +export HOST_ARCH=i686-slc5-gcc43-opt +export TDAQ_HOST_ARCH=i686-slc5-gcc43-opt + +export RCE_ARCH=ppc-rtems-rce405-opt +export RCE=${HOME}/daq/rce +export ARCH=$HOST_ARCH + +#setup python +if [ -e /daq/slc5/sw/lcg/external/Python/2.6.5/i686-slc5-gcc43-opt ]; then +export LD_LIBRARY_PATH=/daq/slc5/sw/lcg/external/Python/2.6.5/i686-slc5-gcc43-opt/lib:${LD_LIBRARY_PATH} +export PATH=/daq/slc5/sw/lcg/external/Python/2.6.5/i686-slc5-gcc43-opt/bin:${PATH} +else + echo Error: Python is not installed +fi + +if [ -e /daq/slc5/opt/rtems-4.9.2 ]; then + export RTEMS=/daq/slc5/opt/rtems-4.9.2 +else + echo Error: RTEMS is not installed +fi + +#setup rtems cross compilers +RTEMS_GCC='' +if [ -e /daq/slc5/opt/powerpc-rtems49-gcc432 ] ; then + RTEMS_GCC=/daq/slc5/opt/powerpc-rtems49-gcc432 +else + echo "rtems gcc not found"รง +fi +if [ -n $RTEMS_GCC ] ; then +export LD_LIBRARY_PATH=$RTEMS_GCC/lib:${LD_LIBRARY_PATH} +export PATH=$RTEMS_GCC/bin:${PATH} +fi + +#setup ROOT +export ROOTSYS="" +if [ -e /daq/slc5/sw/lcg/app/releases/ROOT/5.30.05/${TDAQ_HOST_ARCH} ]; then + export ROOTSYS=/daq/slc5/sw/lcg/app/releases/ROOT/5.30.05/${TDAQ_HOST_ARCH}/root + # this needs the TDAQ gcc + if [ `uname -m` = 'x86_64' ] ; then + . /daq/slc5/sw/lcg/contrib/gcc/4.3.5/x86_64-slc5-gcc43-opt/setup.sh + export LD_LIBRARY_PATH=/daq/slc5/sw/lcg/contrib/gcc/4.3/x86_64-slc5-gcc43-opt/lib:${LD_LIBRARY_PATH} + else + . /daq/slc5/sw/lcg/contrib/gcc/4.3/slc4_ia32_gcc34/setup.sh + export LD_LIBRARY_PATH=/daq/slc5/sw/lcg/contrib/gcc/4.3/slc4_ia32_gcc43-opt/lib:${LD_LIBRARY_PATH} + fi +else + echo "TDAQ gcc not installed" +fi +if [ -n $ROOTSYS ] ; then + export PATH=$ROOTSYS/bin:${PATH} + export LD_LIBRARY_PATH=$ROOTSYS/lib:${LD_LIBRARY_PATH} +fi + +#setup RCE client software +export PATH=${RCE}/build/rceis/bin/${HOST_ARCH}:${RCE}/build/rceipc/bin/${HOST_ARCH}:${RCE}/build/rcecalib/bin/${HOST_ARCH}:${RCE}/rcecalib/scripts:${PATH} +export LD_LIBRARY_PATH=${RCE}/build/rcecalib/lib/${HOST_ARCH}:${RCE}/build/rceers/lib/${HOST_ARCH}:${RCE}/build/rceowl/lib/${HOST_ARCH}:${RCE}/build/rceipc/lib/${HOST_ARCH}:${RCE}/build/rceowl/lib/${HOST_ARCH}:${RCE}/build/rceoh/lib/${HOST_ARCH}:${RCE}/build/rceis/lib/${HOST_ARCH}:${LD_LIBRARY_PATH} + +export RELEASE=${RCE} +export RCE_BIN=${RCE}/build/rcecalib/bin/${RCE_ARCH} +export RCE_MOD=${RCE}/build/rcecalib/mod/${RCE_ARCH} + +export XMD_INI=${RCE}/rcecalib/xmd.ini +export TDAQ_IPC_INIT_REF=file:/${HOME}/ipc_root.ref +export SVNROOT=svn+ssh://svn.cern.ch/reps/RceCimDev +export TDAQ_PARTITION=rcetest_${USER} + +alias rce_ipc_server='ipc_server -p $TDAQ_PARTITION' +alias rce_is_server='is_server -p $TDAQ_PARTITION -n RceIsServer' +alias rce_ipc_ls='ipc_ls ; ipc_ls -p $TDAQ_PARTITION' +function rce_load () { echo -e "reboot\nsetenv TDAQ_PARTITION $TDAQ_PARTITION\nsetenv TDAQ_IS_COMPRESSION_THRESHOLD 100000000\n" | host_bootloader -r $1 -l $RCE_MOD/calibservermod.1.0.prod.so ; } +alias rce_killall='pkill -u $USER ipc_server; pkill -u $USER is_server;' +#fix HOSTTYPE on bash +export HOSTTYPE=`uname -m`-linux + + +if [ ! -d ~/calibData ] ; then +mkdir ~/calibData +fi +#tdaq setup +export TDAQ_INST_PATH=/daq/slc5/tdaq/tdaq-04-00-01/installed +export TDAQC_INST_PATH=/daq/slc5/tdaq-common/tdaq-common-01-18-04/installed +export TDAQC_EXT_PATH=/daq/slc5/tdaq-common/tdaq-common-01-18-04/external +export TDAQ_BOOST=/daq/slc5/sw/lcg/external/Boost/1.44.0_python2.6 +export TDAQ_MYSQL=/daq/slc5/sw/lcg/external/mysql/5.5.14/ +export PATH=$TDAQ_INST_PATH/$HOST_ARCH/bin:${PATH} +export LD_LIBRARY_PATH=$TDAQ_INST_PATH/$HOST_ARCH/lib:${LD_LIBRARY_PATH} +export PATH=$TDAQC_INST_PATH/$HOST_ARCH/bin:${PATH} +export LD_LIBRARY_PATH=$TDAQC_INST_PATH/$HOST_ARCH/lib:${LD_LIBRARY_PATH} +export PATH=$TDAQC_EXT_PATH/$HOST_ARCH/bin:${PATH} +export LD_LIBRARY_PATH=$TDAQC_EXT_PATH/$HOST_ARCH/lib:${LD_LIBRARY_PATH} +export PATH=$TDAQ_INST_PATH/share/bin:${PATH} +export LD_LIBRARY_PATH=$TDAQ_INST_PATH/share/lib:${LD_LIBRARY_PATH} +export PYTHONPATH=$TDAQ_INST_PATH/$HOST_ARCH/lib +export PIXLIBINTERFACE=${RCE}/../PixLibInterface +export USE_RCE=yes +export TDAQ_VERSION=4 +export RCE_CORE_VERSION=1.4 diff --git a/rce/scripts/setup_rce-04-00-01_rceG1.csh b/rce/scripts/setup_rce-04-00-01_rceG1.csh new file mode 100644 index 00000000..81ca19f3 --- /dev/null +++ b/rce/scripts/setup_rce-04-00-01_rceG1.csh @@ -0,0 +1,131 @@ +setenv RCE ${HOME}/daq/rce +setenv RCE_ARCH ppc-rtems-rceG1-opt +# clear path +setenv PATH /usr/lib/qt-3.3/bin:/bin:/sbin:/usr/sbin/:/usr/local/bin:/usr/bin:/usr/bin/X11:/usr/X11R6/bin +setenv LINUXVERS SLC`cat /etc/redhat-release | sed -e 's#[0-9])##g' -e 's#[^\.0-9]##g' -e 's#\.[0-9]##'` +setenv LD_LIBRARY_PATH + +setenv TDAQ_VERSION 4 + +setenv ORBHOST '' +setenv ORBHOST `/sbin/ifconfig | grep "inet addr:1[79]2" | head -1 | gawk -F: '{print $2}' | awk '{print $1}'` +if ( $ORBHOST != '' ) then +setenv ORBendPoint giop:tcp:${ORBHOST}:0 +else +unsetenv ORBHOST +endif + +setenv TDAQ_IPC_INIT_REF file:${HOME}/ipc_root.ref +if ( `uname -m` == 'x86_64' ) then +setenv HOST_ARCH x86_64-slc5-gcc43-opt +setenv TDAQ_HOST_ARCH x86_64-slc5-gcc43-opt +endif +if (`uname -m` == 'i386' ) then +setenv HOST_ARCH i686-slc5-gcc43-opt +setenv TDAQ_HOST_ARCH i686-slc5-gcc43-opt +endif + +#override for now - x86_64 build is broken +setenv HOST_ARCH i686-slc5-gcc43-opt +setenv TDAQ_HOST_ARCH i686-slc5-gcc43-opt + + +#setup python +if ( -e /daq/slc5/sw/lcg/external/Python/2.6.5/i686-slc5-gcc43-opt ) then +setenv LD_LIBRARY_PATH /daq/slc5/sw/lcg/external/Python/2.6.5/i686-slc5-gcc43-opt/lib: ${LD_LIBRARY_PATH} +setenv PATH /daq/slc5/sw/lcg/external/Python/2.6.5/i686-slc5-gcc43-opt/bin:${PATH} +else + echo Error: Python is not installed + exit 1 +endif + +if ( -e /daq/slc5/opt/rtems-4.10.2 ) then + setenv RTEMS /daq/slc5/opt/rtems/4.10.2 + setenv RTEMS_ROOT ${RTEMS} +else + echo Error: RTEMS is not installed +endif + +#setup rtems cross compilers +set RTEMS_GCC='' + +if ( -e /daq/slc5/opt/powerpc-rtems410-gcc445 ) then + set RTEMS_GCC=/daq/slc5/opt/powerpc-rtems410-gcc445 +else + echo "rtems gcc not found" + exit 1 +endif + +if ( $RTEMS_GCC != '' ) then +setenv PATH $RTEMS_GCC/bin:${PATH} +endif + +#setup ROOT +setenv ROOTSYS '' +if ( -e /daq/slc5/sw/lcg/app/releases/ROOT/5.30.05/$TDAQ_HOST_ARCH ) then + setenv ROOTSYS /daq/slc5/sw/lcg/app/releases/ROOT/5.30.05/$TDAQ_HOST_ARCH/root +# this needs the TDAQ gcc + if ( `uname -m` == 'x86_64') then + source /daq/slc5/sw/lcg/contrib/gcc/4.3.5/x86_64-slc5-gcc43-opt/setup.csh + setenv LD_LIBRARY_PATH /daq/slc5/sw/lcg/contrib/gcc/4.3/x86_64-slc5-gcc43-opt/lib:${LD_LIBRARY_PATH} + else + source /daq/slc5/sw/lcg/contrib/gcc/4.3/slc4_ia32_gcc34/setup.csh + setenv LD_LIBRARY_PATH /daq/slc5/sw/lcg/contrib/gcc/4.3/slc4_ia32_gcc34-opt/lib:${LD_LIBRARY_PATH} + endif +else + echo "TDAQ gcc not installed" + exit 1 +endif +if ( $ROOTSYS != '' ) then +setenv PATH $ROOTSYS/bin:${PATH} +setenv LD_LIBRARY_PATH $ROOTSYS/lib:${LD_LIBRARY_PATH} +endif + +#setup RCE client software +setenv PATH ${RCE}/build/rceis/bin/${HOST_ARCH}:${RCE}/build/rceipc/bin/${HOST_ARCH}:${RCE}/build/rcecalib/bin/${HOST_ARCH}:${RCE}/rcecalib/scripts:${PATH} +setenv LD_LIBRARY_PATH ${RCE}/build/rcecalib/lib/${HOST_ARCH}:${RCE}/build/rceers/lib/${HOST_ARCH}:${RCE}/build/rceowl/lib/${HOST_ARCH}:${RCE}/build/rceipc/lib/${HOST_ARCH}:${RCE}/build/rceowl/lib/${HOST_ARCH}:${RCE}/build/rceoh/lib/${HOST_ARCH}:${RCE}/build/rceis/lib/${HOST_ARCH}:${LD_LIBRARY_PATH} + +setenv RELEASE ${RCE} +setenv RCE_BIN ${RCE}/build/rcecalib/bin/${RCE_ARCH} +setenv RCE_MOD ${RCE}/build/rcecalib/mod/${RCE_ARCH} + +setenv XMD_INI ${RCE}/rcecalib/xmd.ini +setenv TDAQ_IPC_INIT_REF file:/${HOME}/ipc_root.ref +setenv SVNROOT svn+ssh://svn.cern.ch/reps/RceCimDev +setenv TDAQ_PARTITION rcetest_${USER} + +alias rce_ipc_server 'ipc_server -p $TDAQ_PARTITION' +alias rce_is_server 'is_server -p $TDAQ_PARTITION -n RceIsServer' +alias rce_ipc_ls 'ipc_ls ; ipc_ls -p $TDAQ_PARTITION' +alias rce_load 'echo "reboot\nsetenv TDAQ_PARTITION $TDAQ_PARTITION\nsetenv TDAQ_IS_COMPRESSION_THRESHOLD 100000000\n" | host_bootloader -r \!:1 -l $RCE_MOD/calibservermod.2.2.prod.so' +alias rce_killall 'pkill -u $USER ipc_server; pkill -u $USER is_server;' + +if ( ! -d ~/calibData ) then +mkdir ~/calibData +endif + +#tdaq setup +setenv TDAQ_INST_PATH /daq/slc5/tdaq/tdaq-04-00-01/installed +setenv TDAQC_INST_PATH /daq/slc5/tdaq-common/tdaq-common-01-18-04/installed +setenv TDAQC_EXT_PATH /daq/slc5/tdaq-common/tdaq-common-01-18-04/external +setenv TDAQ_BOOST /daq/slc5/sw/lcg/external/Boost/1.44.0_python2.6 +setenv TDAQ_MYSQL /daq/slc5/sw/lcg/external/mysql/5.5.14 +setenv PATH $TDAQ_INST_PATH/$HOST_ARCH/bin:${PATH} +setenv LD_LIBRARY_PATH $TDAQ_INST_PATH/$HOST_ARCH/lib:${LD_LIBRARY_PATH} +setenv LD_LIBRARY_PATH $TDAQ_BOOST/$HOST_ARCH/lib:${LD_LIBRARY_PATH} +setenv PATH $TDAQC_INST_PATH/$HOST_ARCH/bin:${PATH} +setenv LD_LIBRARY_PATH $TDAQC_INST_PATH/$HOST_ARCH/lib:${LD_LIBRARY_PATH} +setenv PATH $TDAQC_EXT_PATH/$HOST_ARCH/bin:${PATH} +setenv LD_LIBRARY_PATH $TDAQC_EXT_PATH/$HOST_ARCH/lib:${LD_LIBRARY_PATH} +setenv PATH $TDAQ_INST_PATH/share/bin:${PATH} +setenv LD_LIBRARY_PATH $TDAQ_INST_PATH/share/lib:${LD_LIBRARY_PATH} +setenv PYTHONPATH $TDAQ_INST_PATH/$HOST_ARCH/lib:${PATH} +setenv ARCH $HOST_ARCH +rehash +setenv PIXLIBINTERFACE $RCE/../PixLibInterface +setenv USE_RCE yes +setenv RCE_CORE_VERSION 2.2 + + + + diff --git a/rce/scripts/setup_rce.csh b/rce/scripts/setup_rce.csh new file mode 100644 index 00000000..a705439a --- /dev/null +++ b/rce/scripts/setup_rce.csh @@ -0,0 +1,147 @@ +#--> These aliases are used to manipulate environmental variables used to hold +#--> directory paths, e.g. PATH, MANPATH. They allow one to append, prepend +#--> or remove specific directories from such variables. +alias addpath_clean 'delpath \!:*; setenv \!:1 ${\!:1}\:\!:2' +alias addpath2_clean 'delpath \!:*; setenv \!:1 \!:2\:${\!:1}' +# add to end of path +alias addpath 'if ( $\!:1 != \!:2 && $\!:1 !~ \!:2\:* && $\!:1 !~ *\:\!:2\:* && $\!:1 !~ *\:\!:2 ) setenv \!:1 ${\!:1}\:\!:2' +# add to front of path +alias addpath2 'if ( $\!:1 != \!:2 && $\!:1 !~ \!:2\:* && $\!:1 !~ *\:\!:2\:* && $\!:1 !~ *\:\!:2 ) setenv \!:1 \!:2\:${\!:1}; if ( $\!:1 != \!:2 && $\!:1 !~ \!:2\:* ) setenv \!:1 \!:2\:`echo ${\!:1} | sed -e s%^\!:2\:%% -e s%:\!:2\:%:%g -e s%:\!:2\$%%`' +alias delpath 'setenv \!:1 `echo ${\!:1} | sed -e s%^\!:2\$%% -e s%^\!:2\:%% -e s%:\!:2\:%:%g -e s%:\!:2\$%%`' +alias modpath 'setenv \!:1 `echo ${\!:1} | sed -e s%^\!:2\$%\!:3% -e s%^\!:2\:%\!:3\:% -e s%:\!:2\:\%:\!:3\:\%g -e s%:\!:2\$%\:\!:3\%`' + +if ( ! -d /home/$USER ) then +exit 0 +endif +setenv PATH /usr/lib/qt-3.3/bin:/bin:/sbin:/usr/sbin/:/usr/local/bin:/usr/bin:/usr/bin/X11:/usr/sue/bin:/usr/X11R6/bin + +setenv LD_LIBRARY_PATH +setenv TDAQ_VERSION 3 + +setenv ORBHOST '' +setenv ORBHOST `/sbin/ifconfig | grep "inet addr:1[79]2" | head -1 | gawk -F: '{print $2}' | awk '{print $1}'` +if ( $ORBHOST != '' ) then +setenv ORBendPoint giop:tcp:${ORBHOST}:0 +else +unsetenv ORBHOST +endif + +setenv TDAQ_IPC_INIT_REF file:${HOME}/ipc_root.ref +if ( `uname -m` == 'x86_64' ) then +setenv HOST_ARCH x86_64-slc5-gcc43-opt +setenv TDAQ_HOST_ARCH x86_64-slc5-gcc43-opt +endif +if (`uname -m` == 'i386' ) then +setenv HOST_ARCH i686-slc5-gcc43-opt +setenv TDAQ_HOST_ARCH i686-slc5-gcc43-opt +endif + +#override for now - x86_64 build is broken +setenv HOST_ARCH i686-slc5-gcc43-opt +setenv TDAQ_HOST_ARCH i686-slc5-gcc43-opt + +setenv RCE_ARCH ppc-rtems-rce405-opt +setenv RCE ${HOME}/daq/rce + +#ambush setup +if ( -e /reg/g/atlas/ambush ) then +setenv AMBUSH /reg/g/atlas/ambush +addpath2 LD_LIBRARY_PATH ${AMBUSH}/lib +addpath2 PATH ${AMBUSH}/bin +endif + +#setup python +if ( -e /daq/slc5/sw/lcg/external/Python/2.6.5/i686-slc5-gcc43-opt ) then +addpath2 LD_LIBRARY_PATH /daq/slc5/sw/lcg/external/Python/2.6.5/i686-slc5-gcc43-opt/lib +addpath2 PATH /daq/slc5/sw/lcg/external/Python/2.6.5/i686-slc5-gcc43-opt/bin +else + echo Error: Python is not installed + exit 1 +endif + +if ( -e /daq/slc5/opt/rtems-4.9.2 ) then + setenv RTEMS /daq/slc5/opt/rtems-4.9.2 +else + echo Error: RTEMS is not installed +endif + +#setup rtems cross compilers +set RTEMS_GCC='' + +if ( -e /daq/slc5/opt/powerpc-rtems49-gcc432 ) then + set RTEMS_GCC=/daq/slc5/opt/powerpc-rtems49-gcc432 +else + echo "rtems gcc not found" + exit 1 +endif + +if ( $RTEMS_GCC != '' ) then +addpath2 LD_LIBRARY_PATH $RTEMS_GCC/lib +addpath2 PATH $RTEMS_GCC/bin +endif + +#setup ROOT +setenv ROOTSYS '' +if ( -e /daq/slc5/sw/lcg/app/releases/ROOT/5.26.00d_python2.6/$TDAQ_HOST_ARCH ) then + setenv ROOTSYS /daq/slc5/sw/lcg/app/releases/ROOT/5.26.00d_python2.6/$TDAQ_HOST_ARCH/root +# this needs the TDAQ gcc + if ( `uname -m` == 'x86_64') then + source /daq/slc5/sw/lcg/contrib/gcc/4.3/x86_64-slc5-gcc34-opt/setup.csh + addpath2 LD_LIBRARY_PATH /daq/slc5/sw/lcg/contrib/gcc/4.3/x86_64-slc5-gcc34-opt/lib + else + source /daq/slc5/sw/lcg/contrib/gcc/4.3/slc4_ia32_gcc34/setup.csh + addpath2 LD_LIBRARY_PATH /daq/slc5/sw/lcg/contrib/gcc/4.3/slc4_ia32_gcc34-opt/lib + endif +else + echo "TDAQ gcc not installed" + exit 1 +endif +if ( $ROOTSYS != '' ) then +addpath2 PATH $ROOTSYS/bin +addpath2 LD_LIBRARY_PATH $ROOTSYS/lib +endif + +#setup RCE client software +addpath2 PATH ${RCE}/build/rceis/bin/${HOST_ARCH}:${RCE}/build/rceipc/bin/${HOST_ARCH}:${RCE}/build/rcecalib/bin/${HOST_ARCH}:${RCE}/rcecalib/scripts +addpath2 LD_LIBRARY_PATH ${RCE}/build/rcecalib/lib/${HOST_ARCH}:${RCE}/build/rceers/lib/${HOST_ARCH}:${RCE}/build/rceowl/lib/${HOST_ARCH}:${RCE}/build/rceipc/lib/${HOST_ARCH}:${RCE}/build/rceowl/lib/${HOST_ARCH}:${RCE}/build/rceoh/lib/${HOST_ARCH}:${RCE}/build/rceis/lib/${HOST_ARCH} + +setenv RELEASE ${RCE} +setenv RCE_BIN ${RCE}/build/rcecalib/bin/${RCE_ARCH} +setenv RCE_MOD ${RCE}/build/rcecalib/mod/${RCE_ARCH} + +setenv XMD_INI ${RCE}/rcecalib/xmd.ini +setenv TDAQ_IPC_INIT_REF file:/${HOME}/ipc_root.ref +setenv SVNROOT svn+ssh://svn.cern.ch/reps/RceCimDev +setenv TDAQ_PARTITION rcetest_${USER} + +alias rce_ipc_server 'ipc_server -p $TDAQ_PARTITION' +alias rce_is_server 'is_server -p $TDAQ_PARTITION -n RceIsServer' +alias rce_ipc_ls 'ipc_ls ; ipc_ls -p $TDAQ_PARTITION' +alias rce_load 'echo "reboot\nsetenv TDAQ_PARTITION $TDAQ_PARTITION\nsetenv TDAQ_IS_COMPRESSION_THRESHOLD 100000000\n" | host_bootloader -r \!:1 -l $RCE_MOD/calibservermod.1.0.prod.so' +alias rce_killall 'pkill -u $USER ipc_server; pkill -u $USER is_server;' + +if ( ! -d ~/calibData ) then +mkdir ~/calibData +endif + +#tdaq setup +setenv TDAQ_INST_PATH /daq/slc5/tdaq/tdaq-03-00-01/installed +setenv TDAQC_INST_PATH /daq/slc5/tdaq-common/tdaq-common-01-16-02/installed +setenv TDAQC_EXT_PATH /daq/slc5/tdaq-common/tdaq-common-01-16-02/external +setenv TDAQ_BOOST /daq/slc5/sw/lcg/external/Boost/1.42.0_python2.6 +addpath2 PATH $TDAQ_INST_PATH/$HOST_ARCH/bin +addpath2 LD_LIBRARY_PATH $TDAQ_INST_PATH/$HOST_ARCH/lib +addpath2 PATH $TDAQC_INST_PATH/$HOST_ARCH/bin +addpath2 LD_LIBRARY_PATH $TDAQC_INST_PATH/$HOST_ARCH/lib +addpath2 PATH $TDAQC_EXT_PATH/$HOST_ARCH/bin +addpath2 LD_LIBRARY_PATH $TDAQC_EXT_PATH/$HOST_ARCH/lib +addpath2 PATH $TDAQ_INST_PATH/share/bin +addpath2 LD_LIBRARY_PATH $TDAQ_INST_PATH/share/lib +setenv PYTHONPATH $TDAQ_INST_PATH/$HOST_ARCH/lib +setenv ARCH $HOST_ARCH +setenv PIXLIBINTERFACE $RCE/../PixLibInterface +rehash + + + + diff --git a/rce/scripts/setup_rce.sh b/rce/scripts/setup_rce.sh new file mode 100644 index 00000000..f25d9ef3 --- /dev/null +++ b/rce/scripts/setup_rce.sh @@ -0,0 +1,183 @@ +#!/bin/bash -xv + +#--> These aliases are used to manipulate environmental variables used to hold +#--> directory paths, e.g. PATH, MANPATH. They allow one to append, prepend +#--> or remove specific directories from such variables. + +if [ -n "${BASH_VERSION:-""}" ]; then + + addpath_clean() + { + delpath $* + eval "$1=\$$1:$2" + } + + addpath2_clean() + { + delpath $* + eval "$1=$2:\$$1" + } + + # add to end of path + addpath() + { + if eval test -z \${$1}; then + eval "$1=$2" + elif ! eval test -z \"\${$1##$2}\" -o -z \"\${$1##*:$2:*}\" -o -z \"\${$1%%*:$2}\" -o -z \"\${$1##$2:*}\" ; then + eval "$1=\$$1:$2" + fi + } + + # add to front of path + addpath2() + { + if eval test -z \${$1}; then + eval "$1=$2" + elif ! eval test -z \"\${$1##$2}\" -o -z \"\${$1##*:$2:*}\" -o -z \"\${$1%%*:$2}\" -o -z \"\${$1##$2:*}\" ; then + eval "$1=$2:\$$1" + fi + } + + # delete from path + delpath() + { + eval "$1=\$(echo \$$1 | sed -e s%^$2\$%% -e s%^$2\:%% -e s%:$2\:%:%g -e s%:$2\\\$%%)" + } + + modpath() + { + eval "$1=\$(echo \$$1 | sed -e s%^$2\$%$3% -e s%^$2\:%$3\:% -e s%:$2\:%:$3\:%g -e s%:$2\\\$%:$3%)" + } +fi + +if [ ! -d /home/$USER ] ; then + exit 0 +fi + + + +if [ -n $LD_LIBRARY_PATH ] ; then + export LD_LIBRARY_PATH='' +fi + +export ORBHOST='' +export ORBHOST=`/sbin/ifconfig | grep "inet addr:1[79]2" | head -1 | gawk -F: '{print $2}' | awk '{print $1}'` +if [ -n $ORBHOST ] ; then + export ORBendPoint="giop:tcp:${ORBHOST}:0" +else + unset ORBHOST +fi + +export TDAQ_IPC_INIT_REF="file:${HOME}/ipc_root.ref" +if [ `uname -m` = 'x86_64' ] ; then + export HOST_ARCH=x86_64-slc5-gcc43-opt + export TDAQ_HOST_ARCH=x86_64-slc5-gcc43-opt +fi +if [ `uname -m` = 'i386' ] ; then + export HOST_ARCH=i386-linux + export TDAQ_HOST_ARCH=i686-slc5-gcc43-opt +fi + +#override for now - x86_64 build is broken +export HOST_ARCH=i686-slc5-gcc43-opt +export TDAQ_HOST_ARCH=i686-slc5-gcc43-opt + +export RCE_ARCH=ppc-rtems-rce405-opt +export RCE=${HOME}/rce + +#ambush setup +if [ -e /reg/g/atlas/ambush ] ; then + export AMBUSH=/reg/g/atlas/ambush + addpath2 LD_LIBRARY_PATH ${AMBUSH}/lib + addpath2 PATH ${AMBUSH}/bin +fi + +#setup python +if [ -e /daq/slc5/sw/lcg/external/Python/2.6.5/i686-slc5-gcc43-opt ]; then +addpath2 LD_LIBRARY_PATH /daq/slc5/sw/lcg/external/Python/2.6.5/i686-slc5-gcc43-opt/lib +addpath2 PATH /daq/slc5/sw/lcg/external/Python/2.6.5/i686-slc5-gcc43-opt/bin +else + echo Error: Python is not installed + exit 1 +fi + +if [ -e /daq/slc5/opt/rtems-4.9.2 ]; then + export RTEMS=/daq/slc5/opt/rtems-4.9.2 +else + echo Error: RTEMS is not installed +fi + +#setup rtems cross compilers +RTEMS_GCC='' +if [ -e /daq/slc5/opt/powerpc-rtems49-gcc432 ] ; then + RTEMS_GCC=/daq/slc5/opt/powerpc-rtems49-gcc432 +else + echo "rtems gcc not found" + exit 1 +fi +if [ -n $RTEMS_GCC ] ; then +addpath2 LD_LIBRARY_PATH $RTEMS_GCC/lib +addpath2 PATH $RTEMS_GCC/bin +fi + +#setup ROOT +export ROOTSYS="" +if [ -e /daq/slc5/sw/lcg/app/releases/ROOT/5.26.00d_python2.6/${TDAQ_HOST_ARCH} ]; then + export ROOTSYS=/daq/slc5/sw/lcg/app/releases/ROOT/5.26.00d_python2.6/${TDAQ_HOST_ARCH}/root + # this needs the TDAQ gcc + if [ `uname -m` = 'x86_64' ] ; then + . /daq/slc5/sw/lcg/contrib/gcc/4.3/x86_64-slc5-gcc34-opt/setup.sh + addpath2 LD_LIBRARY_PATH /daq/slc5/sw/lcg/contrib/gcc/4.3/x86_64-slc5-gcc34-opt/lib + else + . /daq/slc5/sw/lcg/contrib/gcc/4.3/slc4_ia32_gcc34/setup.sh + addpath2 LD_LIBRARY_PATH /daq/slc5/sw/lcg/contrib/gcc/4.3/slc4_ia32_gcc34-opt/lib + fi +else + echo "TDAQ gcc not installed" + exit 1 +fi +if [ -n $ROOTSYS ] ; then + addpath2 PATH $ROOTSYS/bin + addpath2 LD_LIBRARY_PATH $ROOTSYS/lib +fi + +#setup RCE client software +addpath2 PATH ${RCE}/build/rceis/bin/${HOST_ARCH}:${RCE}/build/rceipc/bin/${HOST_ARCH}:${RCE}/build/rcecalib/bin/${HOST_ARCH}:${RCE}/rcecalib/scripts +addpath2 LD_LIBRARY_PATH ${RCE}/build/rcecalib/lib/${HOST_ARCH}:${RCE}/build/rceers/lib/${HOST_ARCH}:${RCE}/build/rceowl/lib/${HOST_ARCH}:${RCE}/build/rceipc/lib/${HOST_ARCH}:${RCE}/build/rceowl/lib/${HOST_ARCH}:${RCE}/build/rceoh/lib/${HOST_ARCH}:${RCE}/build/rceis/lib/${HOST_ARCH} + +export RELEASE=${RCE} +export RCE_BIN=${RCE}/build/rcecalib/bin/${RCE_ARCH} +export RCE_MOD=${RCE}/build/rcecalib/mod/${RCE_ARCH} + +export XMD_INI=${RCE}/rcecalib/xmd.ini +export TDAQ_IPC_INIT_REF=file:/${HOME}/ipc_root.ref +export SVNROOT=svn+ssh://svn.cern.ch/reps/RceCimDev +export TDAQ_PARTITION=rcetest_${USER} + +alias rce_ipc_server='ipc_server -p $TDAQ_PARTITION' +alias rce_is_server='is_server -p $TDAQ_PARTITION -n RceIsServer' +alias rce_ipc_ls='ipc_ls ; ipc_ls -p $TDAQ_PARTITION' +function rce_load () { echo -e "reboot\nsetenv TDAQ_PARTITION $TDAQ_PARTITION\nsetenv TDAQ_IS_COMPRESSION_THRESHOLD 100000000\n" | host_bootloader -r $1 -l $RCE_MOD/calibservermod.1.0.prod.so ; } +alias rce_killall='pkill -u $USER ipc_server; pkill -u $USER is_server;' +#fix HOSTTYPE on bash +export HOSTTYPE=`uname -m`-linux + + +if [ ! -d ~/calibData ] ; then +mkdir ~/calibData +fi +#tdaq setup +export TDAQ_INST_PATH=/daq/slc5/tdaq/tdaq-03-00-01/installed +export TDAQC_INST_PATH=/daq/slc5/tdaq-common/tdaq-common-01-16-02/installed +export TDAQC_EXT_PATH=/daq/slc5/tdaq-common/tdaq-common-01-16-02/external +export TDAQ_BOOST=/daq/slc5/sw/lcg/external/Boost/1.42.0_python2.6 +addpath2 PATH $TDAQ_INST_PATH/$HOST_ARCH/bin +addpath2 LD_LIBRARY_PATH $TDAQ_INST_PATH/$HOST_ARCH/lib +addpath2 PATH $TDAQC_INST_PATH/$HOST_ARCH/bin +addpath2 LD_LIBRARY_PATH $TDAQC_INST_PATH/$HOST_ARCH/lib +addpath2 PATH $TDAQC_EXT_PATH/$HOST_ARCH/bin +addpath2 LD_LIBRARY_PATH $TDAQC_EXT_PATH/$HOST_ARCH/lib +addpath2 PATH $TDAQ_INST_PATH/share/bin +addpath2 LD_LIBRARY_PATH $TDAQ_INST_PATH/share/lib +export PYTHONPATH=$TDAQ_INST_PATH/$HOST_ARCH/lib + -- GitLab